summaryrefslogtreecommitdiffstats
path: root/security/nss/cmd
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /security/nss/cmd
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/nss/cmd')
-rw-r--r--security/nss/cmd/Makefile48
-rw-r--r--security/nss/cmd/addbuiltin/Makefile48
-rw-r--r--security/nss/cmd/addbuiltin/addbuiltin.c610
-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.c188
-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.c4314
-rw-r--r--security/nss/cmd/bltest/bltest.gyp35
-rw-r--r--security/nss/cmd/bltest/manifest.mn20
-rw-r--r--security/nss/cmd/bltest/pkcs1_vectors.h804
-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/README5
-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/ciphertext111
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext121
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext131
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext143
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext153
-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/ciphertext81
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/ciphertext91
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key03
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key11
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key103
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key113
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key123
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key133
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key145
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key154
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key164
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key174
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key184
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key194
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key21
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key204
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key31
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key41
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key51
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key61
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key73
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key83
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/key93
-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/plaintext152
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext162
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext172
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext182
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext192
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext21
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/plaintext202
-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/plaintext82
-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/sigseed152
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed162
-rw-r--r--security/nss/cmd/bltest/tests/ecdsa/sigseed172
-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/README1
-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/ciphertext181
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext191
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext23
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext201
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/ciphertext211
-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/hash181
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash191
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash201
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/hash211
-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/key181
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key191
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key201
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/key211
-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/maskhash181
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash191
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash201
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/maskhash211
-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/plaintext181
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext191
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext201
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/plaintext211
-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/seed181
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed191
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed21
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed201
-rw-r--r--security/nss/cmd/bltest/tests/rsa_pss/seed211
-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/sha3_224/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/sha3_224/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/sha3_224/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/sha3_224/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha3_224/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/sha3_256/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/sha3_256/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/sha3_256/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/sha3_256/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha3_256/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/sha3_384/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/sha3_384/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/sha3_384/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/sha3_384/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha3_384/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/sha3_512/ciphertext02
-rw-r--r--security/nss/cmd/bltest/tests/sha3_512/ciphertext12
-rw-r--r--security/nss/cmd/bltest/tests/sha3_512/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/sha3_512/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha3_512/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.c218
-rw-r--r--security/nss/cmd/btoa/btoa.gyp30
-rw-r--r--security/nss/cmd/btoa/manifest.mn21
-rw-r--r--security/nss/cmd/certutil/Makefile48
-rw-r--r--security/nss/cmd/certutil/certext.c2266
-rw-r--r--security/nss/cmd/certutil/certutil.c4038
-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.c595
-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.mn21
-rw-r--r--security/nss/cmd/crlutil/Makefile53
-rw-r--r--security/nss/cmd/crlutil/crlgen.c1541
-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.c1144
-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/crmfcgi.c1090
-rw-r--r--security/nss/cmd/crmf-cgi/crmfcgi.html136
-rw-r--r--security/nss/cmd/crmf-cgi/manifest.mn29
-rw-r--r--security/nss/cmd/crmftest/Makefile61
-rw-r--r--security/nss/cmd/crmftest/crmftest.gyp25
-rw-r--r--security/nss/cmd/crmftest/manifest.mn21
-rw-r--r--security/nss/cmd/crmftest/testcrmf.c1655
-rw-r--r--security/nss/cmd/dbck/Makefile47
-rw-r--r--security/nss/cmd/dbck/dbck.c1348
-rw-r--r--security/nss/cmd/dbck/dbrecover.c669
-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.c243
-rw-r--r--security/nss/cmd/dbtest/dbtest.gyp25
-rw-r--r--security/nss/cmd/dbtest/manifest.mn22
-rw-r--r--security/nss/cmd/dbtool/Makefile50
-rw-r--r--security/nss/cmd/dbtool/dbtool.c830
-rw-r--r--security/nss/cmd/dbtool/dbtool.gyp36
-rw-r--r--security/nss/cmd/dbtool/manifest.mn21
-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.c204
-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.c637
-rw-r--r--security/nss/cmd/ecperf/ecperf.gyp35
-rw-r--r--security/nss/cmd/ecperf/manifest.mn18
-rw-r--r--security/nss/cmd/fbectest/Makefile46
-rw-r--r--security/nss/cmd/fbectest/fbectest.c275
-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
-rw-r--r--security/nss/cmd/fipstest/Makefile49
-rw-r--r--security/nss/cmd/fipstest/README1
-rw-r--r--security/nss/cmd/fipstest/fipstest.c8923
-rw-r--r--security/nss/cmd/fipstest/fipstest.gyp31
-rw-r--r--security/nss/cmd/fipstest/manifest.mn17
-rw-r--r--security/nss/cmd/httpserv/Makefile46
-rw-r--r--security/nss/cmd/httpserv/httpserv.c1447
-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/Makefile48
-rw-r--r--security/nss/cmd/lib/basicutil.c868
-rw-r--r--security/nss/cmd/lib/basicutil.h139
-rw-r--r--security/nss/cmd/lib/berparse.c388
-rw-r--r--security/nss/cmd/lib/derprint.c596
-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.gyp37
-rw-r--r--security/nss/cmd/lib/manifest.mn42
-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.c163
-rw-r--r--security/nss/cmd/lib/secutil.c4740
-rw-r--r--security/nss/cmd/lib/secutil.h450
-rw-r--r--security/nss/cmd/libpkix/Makefile46
-rw-r--r--security/nss/cmd/libpkix/manifest.mn11
-rw-r--r--security/nss/cmd/libpkix/perf/Makefile44
-rw-r--r--security/nss/cmd/libpkix/perf/libpkix_buildthreads.c337
-rw-r--r--security/nss/cmd/libpkix/perf/manifest.mn22
-rw-r--r--security/nss/cmd/libpkix/perf/nss_threads.c158
-rw-r--r--security/nss/cmd/libpkix/pkix/Makefile46
-rw-r--r--security/nss/cmd/libpkix/pkix/certsel/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/certsel/manifest.mn22
-rw-r--r--security/nss/cmd/libpkix/pkix/certsel/test_certselector.c1677
-rw-r--r--security/nss/cmd/libpkix/pkix/certsel/test_comcertselparams.c800
-rw-r--r--security/nss/cmd/libpkix/pkix/checker/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/checker/manifest.mn20
-rw-r--r--security/nss/cmd/libpkix/pkix/checker/test_certchainchecker.c185
-rw-r--r--security/nss/cmd/libpkix/pkix/crlsel/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/crlsel/manifest.mn22
-rw-r--r--security/nss/cmd/libpkix/pkix/crlsel/test_comcrlselparams.c406
-rw-r--r--security/nss/cmd/libpkix/pkix/crlsel/test_crlselector.c168
-rw-r--r--security/nss/cmd/libpkix/pkix/manifest.mn11
-rw-r--r--security/nss/cmd/libpkix/pkix/params/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/params/manifest.mn24
-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
-rw-r--r--security/nss/cmd/libpkix/pkix/results/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/results/manifest.mn24
-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
-rw-r--r--security/nss/cmd/libpkix/pkix/store/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/store/manifest.mn20
-rw-r--r--security/nss/cmd/libpkix/pkix/store/test_store.c194
-rw-r--r--security/nss/cmd/libpkix/pkix/top/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/top/manifest.mn34
-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
-rw-r--r--security/nss/cmd/libpkix/pkix/util/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/util/manifest.mn24
-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.c118
-rw-r--r--security/nss/cmd/libpkix/pkix/util/test_logger.c314
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/Makefile46
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/manifest.mn11
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/manifest.mn25
-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
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/manifest.mn29
-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
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/Makefile45
-rw-r--r--security/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.c189
-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
-rw-r--r--security/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
-rw-r--r--security/nss/cmd/libpkix/sample_apps/manifest.mn23
-rw-r--r--security/nss/cmd/libpkix/sample_apps/validate_chain.c220
-rw-r--r--security/nss/cmd/libpkix/testutil/Makefile50
-rw-r--r--security/nss/cmd/libpkix/testutil/config.mk8
-rw-r--r--security/nss/cmd/libpkix/testutil/manifest.mn27
-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.c108
-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/Makefile57
-rw-r--r--security/nss/cmd/lowhashtest/lowhashtest.c501
-rw-r--r--security/nss/cmd/lowhashtest/lowhashtest.gyp32
-rw-r--r--security/nss/cmd/lowhashtest/manifest.mn18
-rw-r--r--security/nss/cmd/makepqg/Makefile49
-rw-r--r--security/nss/cmd/makepqg/makepqg.c353
-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.mn113
-rw-r--r--security/nss/cmd/modutil/Makefile54
-rw-r--r--security/nss/cmd/modutil/README7
-rw-r--r--security/nss/cmd/modutil/error.h142
-rw-r--r--security/nss/cmd/modutil/install-ds.c1522
-rw-r--r--security/nss/cmd/modutil/install-ds.h260
-rw-r--r--security/nss/cmd/modutil/install.c941
-rw-r--r--security/nss/cmd/modutil/install.h100
-rw-r--r--security/nss/cmd/modutil/installparse.c479
-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.c1600
-rw-r--r--security/nss/cmd/modutil/manifest.mn32
-rw-r--r--security/nss/cmd/modutil/modutil.c996
-rw-r--r--security/nss/cmd/modutil/modutil.gyp44
-rw-r--r--security/nss/cmd/modutil/modutil.h42
-rw-r--r--security/nss/cmd/modutil/pk11.c1050
-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.c2146
-rw-r--r--security/nss/cmd/mpitests/mpitests.gyp54
-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.c878
-rw-r--r--security/nss/cmd/multinit/multinit.gyp24
-rw-r--r--security/nss/cmd/nss-policy-check/Makefile47
-rw-r--r--security/nss/cmd/nss-policy-check/manifest.mn15
-rw-r--r--security/nss/cmd/nss-policy-check/nss-policy-check.c305
-rw-r--r--security/nss/cmd/nss-policy-check/nss-policy-check.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.c1248
-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.c336
-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.c264
-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.c260
-rw-r--r--security/nss/cmd/pk11ectest/pk11ectest.gyp31
-rw-r--r--security/nss/cmd/pk11gcmtest/Makefile47
-rw-r--r--security/nss/cmd/pk11gcmtest/manifest.mn14
-rw-r--r--security/nss/cmd/pk11gcmtest/pk11gcmtest.c465
-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
-rw-r--r--security/nss/cmd/pk11importtest/Makefile43
-rw-r--r--security/nss/cmd/pk11importtest/manifest.mn15
-rw-r--r--security/nss/cmd/pk11importtest/pk11importtest.c407
-rw-r--r--security/nss/cmd/pk11importtest/pk11importtest.gyp25
-rw-r--r--security/nss/cmd/pk11mode/Makefile65
-rw-r--r--security/nss/cmd/pk11mode/manifest.mn14
-rw-r--r--security/nss/cmd/pk11mode/pk11mode.c5370
-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.c1223
-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.c317
-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.c34
-rw-r--r--security/nss/cmd/pkix-errcodes/pkix-errcodes.gyp24
-rw-r--r--security/nss/cmd/platlibs.gypi62
-rw-r--r--security/nss/cmd/platlibs.mk260
-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.c200
-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.c695
-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.mn16
-rw-r--r--security/nss/cmd/rsapoptst/rsapoptst.c639
-rw-r--r--security/nss/cmd/rsapoptst/rsapoptst.gyp25
-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/sdbthreadtst/Makefile48
-rw-r--r--security/nss/cmd/sdbthreadtst/manifest.mn22
-rw-r--r--security/nss/cmd/sdbthreadtst/sdbthreadtst.c217
-rw-r--r--security/nss/cmd/sdbthreadtst/sdbthreadtst.gyp29
-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.c3149
-rw-r--r--security/nss/cmd/selfserv/selfserv.gyp30
-rw-r--r--security/nss/cmd/shlibsign/Makefile101
-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.c1643
-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.c206
-rw-r--r--security/nss/cmd/signtool/manifest.mn27
-rw-r--r--security/nss/cmd/signtool/sign.c872
-rw-r--r--security/nss/cmd/signtool/signtool.c1066
-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.c1046
-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.c907
-rw-r--r--security/nss/cmd/signver/signver.c313
-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.c1625
-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.mn21
-rw-r--r--security/nss/cmd/ssltap/ssltap-manual.html170
-rw-r--r--security/nss/cmd/ssltap/ssltap.c2584
-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.c1611
-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.c1105
-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.c88
-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.c2438
-rw-r--r--security/nss/cmd/tstclnt/tstclnt.gyp31
-rw-r--r--security/nss/cmd/validation/Makefile48
-rw-r--r--security/nss/cmd/validation/manifest.mn23
-rw-r--r--security/nss/cmd/validation/validation.c250
-rw-r--r--security/nss/cmd/validation/validation.gyp30
-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.c821
-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.c575
-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
1369 files changed, 142506 insertions, 0 deletions
diff --git a/security/nss/cmd/Makefile b/security/nss/cmd/Makefile
new file mode 100644
index 0000000000..d1f3891eec
--- /dev/null
+++ b/security/nss/cmd/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/.
+
+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 =
+DBTOOL_SRCDIR =
+ECPERF_SRCDIR =
+FREEBL_ECTEST_SRCDIR =
+FIPSTEST_SRCDIR =
+SHLIBSIGN_SRCDIR =
+else
+BLTEST_SRCDIR = bltest
+DBTOOL_SRCDIR = dbtool
+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)
+
+$(SOFTOKEN_SRCDIRS) $(NSS_SRCDIRS): $(LIB_SRCDIRS)
+
+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 0000000000..74ae200208
--- /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 0000000000..da2533144e
--- /dev/null
+++ b/security/nss/cmd/addbuiltin/addbuiltin.c
@@ -0,0 +1,610 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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");
+}
+
+int
+hasPositiveTrust(unsigned int trust)
+{
+ if (trust & CERTDB_TRUSTED) {
+ if (trust & CERTDB_TRUSTED_CA) {
+ return PR_TRUE;
+ } else {
+ return PR_FALSE;
+ }
+ } else {
+ if (trust & CERTDB_TRUSTED_CA) {
+ return PR_TRUE;
+ } else if (trust & CERTDB_VALID_CA) {
+ return PR_TRUE;
+ } else if (trust & CERTDB_TERMINAL_RECORD) {
+ return PR_FALSE;
+ } else {
+ return PR_FALSE;
+ }
+ }
+ return PR_FALSE;
+}
+
+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";
+ }
+ }
+}
+
+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 (hasPositiveTrust(trust->sslFlags) ||
+ hasPositiveTrust(trust->emailFlags) ||
+ hasPositiveTrust(trust->objectSigningFlags)) {
+ printf("CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE\n");
+ }
+ printf("CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE\n");
+ printf("CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE\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"
+ "# CKA_NSS_SERVER_DISTRUST_AFTER DER+base64 (varies)\n"
+ "# CKA_NSS_EMAIL_DISTRUST_AFTER DER+base64 (varies)\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", "");
+ fprintf(stderr, "%-15s convert a timestamp to DER, and output.\n", "-d timestamp");
+ fprintf(stderr, "%-15s useful to fill server and email distrust fields\n", "");
+ fprintf(stderr, "%-15s Example: %s -d 1561939200\n", "", progName);
+ fprintf(stderr, "%-15s NOTE: The informed timestamp are interpreted as seconds\n", "");
+ fprintf(stderr, "%-15s since unix epoch.\n", "");
+ fprintf(stderr, "%-15s TIP: date -d \"2019-07-01 00:00:00 UTC\" +%%s\n", "");
+ exit(-1);
+}
+
+enum {
+ opt_Input = 0,
+ opt_Nickname,
+ opt_Trust,
+ opt_Distrust,
+ opt_ExcludeCert,
+ opt_ExcludeHash,
+ opt_DistrustCRL,
+ opt_CRLEntry,
+ opt_ConvertDate
+};
+
+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_CRLEntry */ 'e', PR_TRUE, 0, PR_FALSE },
+ { /* opt_ConvertDate */ 'd', 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_ConvertDate].activated) {
+ char *endPtr;
+ PRTime distrustTimestamp = strtol(addbuiltin.options[opt_ConvertDate].arg, &endPtr, 0) * PR_USEC_PER_SEC;
+ if (*endPtr != '\0' && distrustTimestamp > 0) {
+ Usage(progName);
+ exit(1);
+ }
+ SECItem encTime;
+ DER_EncodeTimeChoice(NULL, &encTime, distrustTimestamp);
+ SECU_PrintTimeChoice(stdout, &encTime, "The timestamp represents this date", 0);
+ printf("Locate the entry of the desired certificate in certdata.txt\n"
+ "Erase the CKA_NSS_[SERVER|EMAIL]_DISTRUST_AFTER CK_BBOOL CK_FALSE\n"
+ "And override with the following respective entry:\n\n");
+ SECU_PrintTimeChoice(stdout, &encTime, "# For Server Distrust After", 0);
+ printf("CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL\n");
+ dumpbytes(encTime.data, encTime.len);
+ printf("END\n");
+ SECU_PrintTimeChoice(stdout, &encTime, "# For Email Distrust After", 0);
+ printf("CKA_NSS_EMAIL_DISTRUST_AFTER MULTILINE_OCTAL\n");
+ dumpbytes(encTime.data, encTime.len);
+ printf("END\n");
+ exit(0);
+ }
+
+ 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_CRLEntry].activated) {
+ fprintf(stderr, "%s: you must specify the CRL entry number.\n",
+ progName);
+ Usage(progName);
+ } else {
+ crlentry = atoi(addbuiltin.options[opt_CRLEntry].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);
+
+ if (NSS_NoDB_Init(NULL) != SECSuccess) {
+ exit(1);
+ }
+
+ 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 0000000000..a8d1382e39
--- /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 0000000000..9c44c089ad
--- /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 0000000000..2aaef8fe5b
--- /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 0000000000..3e15ceadb0
--- /dev/null
+++ b/security/nss/cmd/atob/atob.c
@@ -0,0 +1,188 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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");
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ SECStatus rv;
+ FILE *inFile = NULL, *outFile = NULL;
+ PRBool closeIn = PR_TRUE, closeOut = PR_TRUE;
+ PLOptState *optstate = NULL;
+ PLOptStatus status;
+ int exitCode = -1;
+
+ 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);
+ goto loser;
+ break;
+
+ case 'i':
+ inFile = fopen(optstate->value, "r");
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ goto loser;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "wb");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ goto loser;
+ }
+ break;
+ }
+ }
+ if (!inFile) {
+ inFile = stdin;
+ closeIn = PR_FALSE;
+ }
+ 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);
+ goto loser;
+ }
+#endif
+ outFile = stdout;
+ closeOut = PR_FALSE;
+ }
+ rv = decode_file(outFile, inFile);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
+ progName, PORT_GetError(), errno);
+ goto loser;
+ }
+ exitCode = 0;
+loser:
+ if (optstate) {
+ PL_DestroyOptState(optstate);
+ }
+ if (inFile && closeIn) {
+ fclose(inFile);
+ }
+ if (outFile && closeOut) {
+ fclose(outFile);
+ }
+ return exitCode;
+}
diff --git a/security/nss/cmd/atob/atob.gyp b/security/nss/cmd/atob/atob.gyp
new file mode 100644
index 0000000000..af972c2e9f
--- /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 0000000000..5d822b96ec
--- /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 0000000000..a5e83efdfa
--- /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 0000000000..78a831a023
--- /dev/null
+++ b/security/nss/cmd/bltest/blapitest.c
@@ -0,0 +1,4314 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 "ecl-curve.h"
+#include "chacha20poly1305.h"
+
+#include "pkcs1_vectors.h"
+
+SECStatus EC_DecodeParams(const SECItem *encodedParams,
+ ECParams **ecparams);
+SECStatus EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
+ const ECParams *srcParams);
+
+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]");
+ PRINTUSAGE("", "", "[-n curvename]");
+ 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");
+ PRINTUSAGE("", "-n", "name of curve for EC key generation; one of:");
+ PRINTUSAGE("", "", " nistp256, nistp384, nistp521");
+ 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;
+}
+
+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;
+}
+
+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);
+}
+
+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);
+}
+
+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, /* . */
+#ifndef NSS_DISABLE_DEPRECATED_RC2
+ bltestRC2_ECB, /* . */
+ bltestRC2_CBC, /* . */
+#endif
+ 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, /* . */
+#ifndef NSS_DISABLE_DEPRECATED_SEED
+ bltestSEED_ECB, /* SEED algorithm */
+ bltestSEED_CBC, /* SEED algorithm */
+#endif
+ bltestCHACHA20_CTR, /* ChaCha20 block cipher */
+ bltestCHACHA20, /* ChaCha20 + Poly1305 */
+ bltestRSA, /* Public Key Ciphers */
+ bltestRSA_OAEP, /* . (Public Key Enc.) */
+ bltestRSA_PSS, /* . (Public Key Sig.) */
+ bltestECDSA, /* . (Public Key Sig.) */
+ bltestDSA, /* . (Public Key Sig.) */
+ bltestMD2, /* Hash algorithms */
+ bltestMD5, /* . */
+ bltestSHA1, /* . */
+ bltestSHA224, /* . */
+ bltestSHA256, /* . */
+ bltestSHA384, /* . */
+ bltestSHA512, /* . */
+ bltestSHA3_224, /* . */
+ bltestSHA3_256, /* . */
+ bltestSHA3_384, /* . */
+ bltestSHA3_512, /* . */
+ NUMMODES
+} bltestCipherMode;
+
+static char *mode_strings[] = {
+ "des_ecb",
+ "des_cbc",
+ "des3_ecb",
+ "des3_cbc",
+#ifndef NSS_DISABLE_DEPRECATED_RC2
+ "rc2_ecb",
+ "rc2_cbc",
+#endif
+ "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",
+#ifndef NSS_DISABLE_DEPRECATED_SEED
+ "seed_ecb",
+ "seed_cbc",
+#endif
+ "chacha20_ctr",
+ "chacha20_poly1305",
+ "rsa",
+ "rsa_oaep",
+ "rsa_pss",
+ "ecdsa",
+ /*"pqg",*/
+ "dsa",
+ "md2",
+ "md5",
+ "sha1",
+ "sha224",
+ "sha256",
+ "sha384",
+ "sha512",
+ "sha3_224",
+ "sha3_256",
+ "sha3_384",
+ "sha3_512",
+};
+
+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;
+
+typedef struct
+{
+ char *curveName;
+ bltestIO sigseed;
+} bltestECDSAParams;
+
+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;
+ bltestECDSAParams ecdsa;
+ } 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 <= bltestCHACHA20_CTR)
+ 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_CTR:
+ 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 <= bltestSHA3_512)
+ 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:
+#ifndef NSS_DISABLE_DEPRECATED_RC2
+ case bltestRC2_CBC:
+#endif
+#ifdef NSS_SOFTOKEN_DOES_RC5
+ case bltestRC5_CBC:
+#endif
+ case bltestAES_CBC:
+ case bltestAES_CTS:
+ case bltestAES_CTR:
+ case bltestAES_GCM:
+ case bltestCAMELLIA_CBC:
+#ifndef NSS_DISABLE_DEPRECATED_SEED
+ case bltestSEED_CBC:
+#endif
+ case bltestCHACHA20_CTR:
+ 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;
+ PRBool needToFreeFile = PR_FALSE;
+
+ if (file && (numBytes == 0 || file == PR_STDIN)) {
+ /* grabbing data from a file */
+ rv = SECU_FileToItem(&fileData, file);
+ if (rv != SECSuccess)
+ return SECFailure;
+ in = &fileData;
+ needToFreeFile = PR_TRUE;
+ } 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;
+ rv = SECITEM_CopyItem(arena, &input->buf, in);
+ 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 (needToFreeFile)
+ 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);
+}
+
+#ifndef NSS_DISABLE_DEPRECATED_RC2
+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);
+}
+#endif /* NSS_DISABLE_DEPRECATED_RC2 */
+
+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_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ if (maxOutputLen < inputLen) {
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ return SECFailure;
+ }
+ ChaCha20Context *ctx = cx;
+ *outputLen = inputLen;
+ return ChaCha20_Xor(output, input, inputLen, ctx->key, ctx->nonce,
+ ctx->counter);
+}
+
+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);
+}
+
+#ifndef NSS_DISABLE_DEPRECATED_SEED
+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);
+}
+#endif /* NSS_DISABLE_DEPRECATED_SEED */
+
+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);
+}
+
+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);
+}
+
+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;
+}
+
+#ifndef NSS_DISABLE_DEPRECATED_RC2
+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;
+}
+#endif /* NSS_DISABLE_DEPRECATED_RC2 */
+
+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_NSS_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;
+}
+
+#ifndef NSS_DISABLE_DEPRECATED_SEED
+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;
+}
+#endif /* NSS_DISABLE_DEPRECATED_SEED */
+
+SECStatus
+bltest_chacha20_ctr_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ const PRUint32 counter = 1;
+ bltestSymmKeyParams *sk = &cipherInfo->params.sk;
+ cipherInfo->cx = ChaCha20_CreateContext(sk->key.buf.data, sk->key.buf.len,
+ sk->iv.buf.data, sk->iv.buf.len,
+ counter);
+
+ if (cipherInfo->cx == NULL) {
+ PR_fprintf(PR_STDERR, "ChaCha20_CreateContext() returned NULL\n"
+ "key must be 32 bytes, iv must be 12 bytes\n");
+ return SECFailure;
+ }
+ cipherInfo->cipher.symmkeyCipher = chacha20_Encrypt;
+ 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;
+}
+
+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;
+}
+
+/* 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,
+ int keysize, int exponent, char *curveName)
+{
+ int i;
+ SECStatus rv = SECSuccess;
+ bltestAsymKeyParams *asymk = &cipherInfo->params.asymk;
+ bltestRSAParams *rsap;
+ RSAPrivateKey **rsaKey = NULL;
+ bltestDSAParams *dsap;
+ DSAPrivateKey **dsaKey = NULL;
+ SECItem *tmpECParamsDER;
+ ECParams *tmpECParams = NULL;
+ SECItem ecSerialize[3];
+ ECPrivateKey **ecKey = NULL;
+ 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;
+ 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;
+ 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;
+#ifndef NSS_DISABLE_DEPRECATED_RC2
+ case bltestRC2_ECB:
+ case bltestRC2_CBC:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+ return bltest_rc2_init(cipherInfo, encrypt);
+ break;
+#endif /* NSS_DISABLE_DEPRECATED_RC2 */
+ 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);
+ return bltest_rc5_init(cipherInfo, encrypt);
+ break;
+#endif
+ 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;
+#ifndef NSS_DISABLE_DEPRECATED_SEED
+ case bltestSEED_ECB:
+ case bltestSEED_CBC:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+ return bltest_seed_init(cipherInfo, encrypt);
+ break;
+#endif /* NSS_DISABLE_DEPRECATED_SEED */
+ case bltestCHACHA20_CTR:
+ outlen = cipherInfo->input.pBuf.len;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, outlen);
+ return bltest_chacha20_ctr_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;
+ case bltestECDSA:
+ if (encrypt) {
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ 2 * MAX_ECKEY_LEN);
+ }
+ return bltest_ecdsa_init(cipherInfo, encrypt);
+ break;
+ 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;
+ case bltestSHA3_224:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ SHA3_224_LENGTH);
+ cipherInfo->cipher.hashCipher = SHA3_224_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestSHA3_256:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ SHA3_256_LENGTH);
+ cipherInfo->cipher.hashCipher = SHA3_256_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestSHA3_384:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ SHA3_384_LENGTH);
+ cipherInfo->cipher.hashCipher = SHA3_384_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestSHA3_512:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ SHA3_512_LENGTH);
+ cipherInfo->cipher.hashCipher = SHA3_512_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;
+#ifndef NSS_DISABLE_DEPRECATED_SEED
+ case bltestSEED_ECB:
+ case bltestSEED_CBC:
+ SEED_DestroyContext((SEEDContext *)cipherInfo->cx, PR_TRUE);
+ break;
+#endif /* NSS_DISABLE_DEPRECATED_SEED */
+ case bltestCHACHA20_CTR:
+ ChaCha20_DestroyContext((ChaCha20Context *)cipherInfo->cx, PR_TRUE);
+ break;
+ case bltestCHACHA20:
+ ChaCha20Poly1305_DestroyContext((ChaCha20Poly1305Context *)
+ cipherInfo->cx,
+ PR_TRUE);
+ break;
+#ifndef NSS_DISABLE_DEPRECATED_RC2
+ case bltestRC2_ECB:
+ case bltestRC2_CBC:
+ RC2_DestroyContext((RC2Context *)cipherInfo->cx, PR_TRUE);
+ break;
+#endif /* NSS_DISABLE_DEPRECATED_RC2 */
+ 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:
+ case bltestECDSA:
+ case bltestMD2: /* hash contexts are ephemeral */
+ case bltestMD5:
+ case bltestSHA1:
+ case bltestSHA224:
+ case bltestSHA256:
+ case bltestSHA384:
+ case bltestSHA512:
+ case bltestSHA3_224:
+ case bltestSHA3_256:
+ case bltestSHA3_384:
+ case bltestSHA3_512:
+ 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;
+ }
+ }
+
+ if (i == 0)
+ return PR_smprintf("%d%s", spl[i], marks[i]);
+ else
+ return PR_smprintf("%d%s %d%s", spl[i], marks[i], spl[i - 1], marks[i - 1]);
+}
+
+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:
+#ifndef NSS_DISABLE_DEPRECATED_SEED
+ case bltestSEED_ECB:
+ case bltestSEED_CBC:
+#endif
+#ifndef NSS_DISABLE_DEPRECATED_RC2
+ case bltestRC2_ECB:
+ case bltestRC2_CBC:
+#endif
+ 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;
+ 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;
+ 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:
+ snprintf(filename, sizeof(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:
+#ifndef NSS_DISABLE_DEPRECATED_RC2
+ case bltestRC2_CBC:
+#endif
+ case bltestAES_CBC:
+ case bltestAES_CTS:
+ case bltestAES_CTR:
+ case bltestCAMELLIA_CBC:
+#ifndef NSS_DISABLE_DEPRECATED_SEED
+ case bltestSEED_CBC:
+#endif
+ snprintf(filename, sizeof(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:
+#ifndef NSS_DISABLE_DEPRECATED_RC2
+ case bltestRC2_ECB:
+#endif
+ case bltestRC4:
+ case bltestAES_ECB:
+ case bltestCAMELLIA_ECB:
+#ifndef NSS_DISABLE_DEPRECATED_SEED
+ case bltestSEED_ECB:
+#endif
+ snprintf(filename, sizeof(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:
+ snprintf(filename, sizeof(filename), "%s/tests/%s/%s%d", testdir, modestr, "iv", j);
+ load_file_data(arena, &params->sk.iv, filename, bltestBinary);
+ snprintf(filename, sizeof(filename), "%s/tests/%s/%s%d", testdir, modestr, "key", j);
+ load_file_data(arena, &params->sk.key, filename, bltestBinary);
+ snprintf(filename, sizeof(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:
+ snprintf(filename, sizeof(filename), "%s/tests/%s/%s%d", testdir, modestr, "ciphertext", j);
+ load_file_data(arena, &params->asymk.sig, filename, bltestBase64Encoded);
+ /* fall through */
+ case bltestRSA_OAEP:
+ snprintf(filename, sizeof(filename), "%s/tests/%s/%s%d", testdir, modestr, "seed", j);
+ load_file_data(arena, &params->asymk.cipherParams.rsa.seed,
+ filename, bltestBase64Encoded);
+
+ snprintf(filename, sizeof(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);
+
+ snprintf(filename, sizeof(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:
+ snprintf(filename, sizeof(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:
+ snprintf(filename, sizeof(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);
+ snprintf(filename, sizeof(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);
+ snprintf(filename, sizeof(filename), "%s/tests/%s/%s%d", testdir, modestr, "keyseed", j);
+ load_file_data(arena, &params->asymk.cipherParams.dsa.keyseed, filename,
+ bltestBase64Encoded);
+ snprintf(filename, sizeof(filename), "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j);
+ load_file_data(arena, &params->asymk.cipherParams.dsa.sigseed, filename,
+ bltestBase64Encoded);
+ snprintf(filename, sizeof(filename), "%s/tests/%s/%s%d", testdir, modestr, "ciphertext", j);
+ load_file_data(arena, &params->asymk.sig, filename, bltestBase64Encoded);
+ break;
+ case bltestECDSA:
+ snprintf(filename, sizeof(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);
+ snprintf(filename, sizeof(filename), "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j);
+ load_file_data(arena, &params->asymk.cipherParams.ecdsa.sigseed,
+ filename, bltestBase64Encoded);
+ snprintf(filename, sizeof(filename), "%s/tests/%s/%s%d", testdir, modestr, "ciphertext", j);
+ load_file_data(arena, &params->asymk.sig, filename, bltestBase64Encoded);
+ break;
+ 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 */
+ snprintf(filename, sizeof(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++) {
+ snprintf(filename, sizeof(filename), "%s/tests/%s/%s%d", testdir, modestr,
+ "plaintext", j);
+ load_file_data(arena, &pt, filename,
+ is_sigCipher(mode) ? bltestBase64Encoded
+ : bltestBinary);
+ snprintf(filename, sizeof(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);
+ } else if (mode == bltestECDSA) {
+ ECPrivateKey *key;
+ load_file_data(arena, &keydata, filename, bltestBase64Encoded);
+ key = eckey_from_filedata(arena, &keydata.buf);
+ dump_eckey(key);
+ }
+ 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,
+ opt_CurveName,
+ 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 },
+ { /* opt_CurveName */ 'n', PR_TRUE, 0, PR_FALSE },
+ { /* 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;
+ char *curveName = NULL;
+ 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 keyExponent = 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) {
+ keyExponent = 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, keyExponent);
+ 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) {
+ PORT_Free(cipherInfo);
+#ifdef NSS_FIPS_DISABLED
+ fprintf(stdout, "FIPS self-test failed with: NSS_FIPS_DISABLED\n");
+ return SECFailure;
+#else
+ CK_RV ckrv = sftk_FIPSEntryOK(PR_FALSE);
+ if (ckrv == CKR_OK) {
+ fprintf(stdout, "FIPS self-test was successful.\n");
+ return SECSuccess;
+ }
+ fprintf(stdout, "FIPS self-test failed with the CK_RV: %ld.\n", ckrv);
+ return SECFailure;
+#endif
+ }
+
+ /*
+ * 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;
+
+ if (bltest.options[opt_CurveName].activated)
+ curveName = PORT_Strdup(bltest.options[opt_CurveName].arg);
+ else
+ curveName = NULL;
+
+ 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;
+ pubkeyInitKey(cipherInfo, file, keysize, exponent, curveName);
+ 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 0000000000..7139c3181d
--- /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 0000000000..8b05116e5c
--- /dev/null
+++ b/security/nss/cmd/bltest/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
+
+REQUIRES = seccmd dbm softoken
+
+INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
+
+PROGRAM = bltest
+
+USE_STATIC_LIBS = 1
+
+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 0000000000..15812bee0b
--- /dev/null
+++ b/security/nss/cmd/bltest/pkcs1_vectors.h
@@ -0,0 +1,804 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 0000000000..6d1302b468
--- /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 0000000000..4da9e529b7
--- /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 0000000000..1126bbf384
--- /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 0000000000..c3d443ffef
--- /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 0000000000..ae00d8b01b
--- /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 0000000000..605a1bab01
--- /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 0000000000..2abf3695cb
--- /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 0000000000..f16428a985
--- /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 0000000000..ed1cecd99f
--- /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 0000000000..8fa895224d
--- /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 0000000000..8ca864c9e6
--- /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 0000000000..9b42740914
--- /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 0000000000..39bf9377ec
--- /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 0000000000..ec069abd47
--- /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 0000000000..d74f0e041c
--- /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 0000000000..9f3b9ead75
--- /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 0000000000..b9b5b5ce3c
--- /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 0000000000..e7710c1f0f
--- /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 0000000000..d5234aa646
--- /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 0000000000..82c4cd2028
--- /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 0000000000..81714bd4dd
--- /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 0000000000..ce9672a51a
--- /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 0000000000..fc53a4f55c
--- /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 0000000000..1d6d84bb0b
--- /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 0000000000..7191a647aa
--- /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 0000000000..232a691140
--- /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 0000000000..4e65bc0347
--- /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 0000000000..01d633b27e
--- /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 0000000000..58d7a2da90
--- /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 0000000000..6847886b91
--- /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 0000000000..15040cd21c
--- /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 0000000000..1bef08adf9
--- /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 0000000000..099828fdf5
--- /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 0000000000..d7a44d9d6f
--- /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 0000000000..678bb8d679
--- /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 0000000000..7ff21ab69d
--- /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 0000000000..244b5022eb
--- /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 0000000000..919e165742
--- /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 0000000000..01d633b27e
--- /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 0000000000..c49bf8f700
--- /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 0000000000..6452e3d63a
--- /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 0000000000..42b7bd3afc
--- /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 0000000000..99b22495cc
--- /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 0000000000..0104daff21
--- /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 0000000000..01d633b27e
--- /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 0000000000..01d633b27e
--- /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 0000000000..01d633b27e
--- /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 0000000000..01d633b27e
--- /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 0000000000..524d1b984a
--- /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 0000000000..f58e954f93
--- /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 0000000000..d6c4782673
--- /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 0000000000..13911cc29a
--- /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 0000000000..01d633b27e
--- /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 0000000000..3cdff7a852
--- /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 0000000000..4a1304010a
--- /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 0000000000..0a0103deb5
--- /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 0000000000..87ae208d68
--- /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 0000000000..de4da4d4e0
--- /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 0000000000..b13351f01a
--- /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 0000000000..71afcb384f
--- /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 0000000000..291b89b1b2
--- /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 0000000000..9c28957d77
--- /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 0000000000..f0ca408202
--- /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 0000000000..01d633b27e
--- /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 0000000000..ce28587640
--- /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 0000000000..1b1a9bc440
--- /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 0000000000..4b23daa1bf
--- /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 0000000000..cc1b48fe4a
--- /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 0000000000..cf579fcfe2
--- /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 0000000000..4ac5fc6cf8
--- /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 0000000000..4ac5fc6cf8
--- /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 0000000000..4e4e493570
--- /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 0000000000..4e4e493570
--- /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 0000000000..c1e46cee5e
--- /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 0000000000..804b8d421e
--- /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 0000000000..193a2a14d4
--- /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 0000000000..443167efb7
--- /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 0000000000..7273c0fa8c
--- /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 0000000000..cc67189450
--- /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 0000000000..8bac1b7568
--- /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 0000000000..779400be5e
--- /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 0000000000..c226c29df2
--- /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 0000000000..357fd2ccd2
--- /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 0000000000..88c5250f63
--- /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 0000000000..c42aec2ae4
--- /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 0000000000..12662556e7
--- /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 0000000000..6348620c84
--- /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 0000000000..6343a1aacc
--- /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 0000000000..4858130f66
--- /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 0000000000..0d6ad5e8c8
--- /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 0000000000..b2153e2ad1
--- /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 0000000000..6873047fc2
--- /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 0000000000..22bfbac6eb
--- /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 0000000000..a36a7f9da0
--- /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 0000000000..5201604a5f
--- /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 0000000000..42c59ead88
--- /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 0000000000..b565f3abc5
--- /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 0000000000..9ef1cbb5fc
--- /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 0000000000..767e9f4302
--- /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 0000000000..e8537b6e68
--- /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 0000000000..b3b728441d
--- /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 0000000000..32b0833208
--- /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 0000000000..ba4b4551f0
--- /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 0000000000..1d46380233
--- /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 0000000000..e220c9016a
--- /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 0000000000..4eb4383bcf
--- /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 0000000000..1b2c7aab5a
--- /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 0000000000..344157f6c7
--- /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 0000000000..c548ceba40
--- /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 0000000000..71e0f1c0a3
--- /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 0000000000..60e6e583d9
--- /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 0000000000..262b055c9c
--- /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 0000000000..50a2966a23
--- /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 0000000000..a38ed0104b
--- /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 0000000000..d9b681bb81
--- /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 0000000000..a0586e1e8b
--- /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 0000000000..06abcde6c5
--- /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 0000000000..991068f55c
--- /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 0000000000..aa6b7d0cf0
--- /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 0000000000..231fcd17b7
--- /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 0000000000..bdbc91b1e4
--- /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 0000000000..764b0953f1
--- /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 0000000000..8a58240f1d
--- /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 0000000000..aa9748941e
--- /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 0000000000..734c8c2c99
--- /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 0000000000..ed628c9a59
--- /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 0000000000..16bc6d6b6a
--- /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 0000000000..1e2a367d46
--- /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 0000000000..d42fc1955c
--- /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 0000000000..7db8009099
--- /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 0000000000..bef853b6ed
--- /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 0000000000..a3a4ab21d3
--- /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 0000000000..60ed7007a1
--- /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 0000000000..4c6462f6f1
--- /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 0000000000..10ae5e187e
--- /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 0000000000..10ae5e187e
--- /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 0000000000..10ae5e187e
--- /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 0000000000..efb781943e
--- /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 0000000000..06b40e45dc
--- /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 0000000000..cf22d1a2d3
--- /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 0000000000..b6f2f6f3d0
--- /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 0000000000..00750edc07
--- /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 0000000000..8ad770497e
--- /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 0000000000..8ad770497e
--- /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 0000000000..8ad770497e
--- /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 0000000000..b107586769
--- /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 0000000000..fa28439b31
--- /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 0000000000..dae97358a7
--- /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 0000000000..df892892e2
--- /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 0000000000..11e68e0c88
--- /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 0000000000..b5dc5ae3fd
--- /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 0000000000..db837f9272
--- /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 0000000000..bcfdc10da6
--- /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 0000000000..66560807c9
--- /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 0000000000..336d705c97
--- /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 0000000000..7c53d4002a
--- /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 0000000000..ef31331c85
--- /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 0000000000..0ead143371
--- /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 0000000000..4bdfab8333
--- /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 0000000000..3e8c8e9e6b
--- /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 0000000000..b4bbc2e76f
--- /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 0000000000..c065e8362d
--- /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 0000000000..ba11a0ec02
--- /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 0000000000..213a4bd3c7
--- /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 0000000000..8ec57e84c4
--- /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 0000000000..8ec57e84c4
--- /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 0000000000..8ec57e84c4
--- /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 0000000000..8ec57e84c4
--- /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 0000000000..8ec57e84c4
--- /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 0000000000..8ec57e84c4
--- /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 0000000000..58b628d8dd
--- /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 0000000000..1e8b314962
--- /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 0000000000..3f35c974a1
--- /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 0000000000..3975448711
--- /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 0000000000..d0664ea0db
--- /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 0000000000..563970bfa5
--- /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 0000000000..b908471e32
--- /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 0000000000..5e4c069476
--- /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 0000000000..d6818c1d0b
--- /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 0000000000..1126bbf384
--- /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 0000000000..ec069abd47
--- /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 0000000000..82c4cd2028
--- /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 0000000000..81714bd4dd
--- /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 0000000000..ce9672a51a
--- /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 0000000000..fc53a4f55c
--- /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 0000000000..13911cc29a
--- /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 0000000000..01d633b27e
--- /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 0000000000..01d633b27e
--- /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 0000000000..4ac5fc6cf8
--- /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 0000000000..4ac5fc6cf8
--- /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 0000000000..4e4e493570
--- /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 0000000000..4e4e493570
--- /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 0000000000..6d46509f0b
--- /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 0000000000..7f8f011eb7
--- /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 0000000000..8d6a8d555b
--- /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 0000000000..8bac1b7568
--- /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 0000000000..b2153e2ad1
--- /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 0000000000..b565f3abc5
--- /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 0000000000..9ef1cbb5fc
--- /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 0000000000..767e9f4302
--- /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 0000000000..e8537b6e68
--- /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 0000000000..96a2adb9ca
--- /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 0000000000..a01daaef3c
--- /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 0000000000..803c23c814
--- /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 0000000000..e567fab647
--- /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 0000000000..c96940e2c2
--- /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 0000000000..d8d00582a9
--- /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 0000000000..e69de29bb2
--- /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 0000000000..e69de29bb2
--- /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 0000000000..87b29d32cc
--- /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 0000000000..87b29d32cc
--- /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 0000000000..e69de29bb2
--- /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 0000000000..e69de29bb2
--- /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 0000000000..e69de29bb2
--- /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 0000000000..87b29d32cc
--- /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 0000000000..87b29d32cc
--- /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 0000000000..87b29d32cc
--- /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 0000000000..e69de29bb2
--- /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 0000000000..87b29d32cc
--- /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 0000000000..87b29d32cc
--- /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 0000000000..87b29d32cc
--- /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 0000000000..e69de29bb2
--- /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 0000000000..e69de29bb2
--- /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 0000000000..e69de29bb2
--- /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 0000000000..87b29d32cc
--- /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 0000000000..3b352147b4
--- /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 0000000000..9913ff1fa8
--- /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 0000000000..70cb471007
--- /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 0000000000..b9c42364ea
--- /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 0000000000..b756f5c56b
--- /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 0000000000..15bc5e17f6
--- /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 0000000000..a982ef2fe0
--- /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 0000000000..5f5b95261e
--- /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 0000000000..86d9096bdb
--- /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 0000000000..6be2346bff
--- /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 0000000000..f5efb3d522
--- /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 0000000000..80fe95e851
--- /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 0000000000..cbc0194aad
--- /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 0000000000..77127ff0e3
--- /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 0000000000..dc07bfd3f5
--- /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 0000000000..d405c82fe8
--- /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 0000000000..53738bbef2
--- /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 0000000000..bde2785bc1
--- /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 0000000000..cdf583da2f
--- /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 0000000000..ce58bc9f84
--- /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 0000000000..ce58bc9f84
--- /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 0000000000..bad60b08b7
--- /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 0000000000..f446641db1
--- /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 0000000000..ce58bc9f84
--- /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 0000000000..ce58bc9f84
--- /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 0000000000..e3728f7261
--- /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 0000000000..e3728f7261
--- /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 0000000000..bad60b08b7
--- /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 0000000000..f446641db1
--- /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 0000000000..e3728f7261
--- /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 0000000000..e3728f7261
--- /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 0000000000..bad60b08b7
--- /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 0000000000..f446641db1
--- /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 0000000000..ce58bc9f84
--- /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 0000000000..ce58bc9f84
--- /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 0000000000..e3728f7261
--- /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 0000000000..e3728f7261
--- /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 0000000000..01d633b27e
--- /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 0000000000..01d633b27e
--- /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 0000000000..222b4b5a24
--- /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 0000000000..222b4b5a24
--- /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 0000000000..4e4e493570
--- /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 0000000000..4e4e493570
--- /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 0000000000..2163baf5a3
--- /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 0000000000..2163baf5a3
--- /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 0000000000..2163baf5a3
--- /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 0000000000..2163baf5a3
--- /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 0000000000..767ebdace0
--- /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 0000000000..767ebdace0
--- /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 0000000000..767ebdace0
--- /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 0000000000..767ebdace0
--- /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 0000000000..4ac5fc6cf8
--- /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 0000000000..4ac5fc6cf8
--- /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 0000000000..222b4b5a24
--- /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 0000000000..222b4b5a24
--- /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 0000000000..a990f519c6
--- /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 0000000000..3c032078a4
--- /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 0000000000..e69de29bb2
--- /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 0000000000..01d633b27e
--- /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 0000000000..00505877ab
--- /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 0000000000..00505877ab
--- /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 0000000000..e69de29bb2
--- /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 0000000000..01d633b27e
--- /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 0000000000..664f6c9de7
--- /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 0000000000..00505877ab
--- /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 0000000000..00505877ab
--- /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 0000000000..00505877ab
--- /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 0000000000..664f6c9de7
--- /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 0000000000..00505877ab
--- /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 0000000000..00505877ab
--- /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 0000000000..00505877ab
--- /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 0000000000..e69de29bb2
--- /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 0000000000..01d633b27e
--- /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 0000000000..664f6c9de7
--- /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 0000000000..00505877ab
--- /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 0000000000..a8bd4e15fa
--- /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 0000000000..7bb83ce8be
--- /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 0000000000..2a4a5a99ed
--- /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 0000000000..d46e6f91f8
--- /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 0000000000..b9ccfa86ad
--- /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 0000000000..b589ba4138
--- /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 0000000000..f650ea7c64
--- /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 0000000000..f1a49e3fe2
--- /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 0000000000..6918aca776
--- /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 0000000000..a5c538ea66
--- /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 0000000000..8e69bf6784
--- /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 0000000000..4083eac7a7
--- /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 0000000000..ec62258d03
--- /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 0000000000..709251b456
--- /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 0000000000..b738e1f054
--- /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 0000000000..68bc521389
--- /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 0000000000..544324035f
--- /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 0000000000..bcd5939291
--- /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 0000000000..61c78fcc5f
--- /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 0000000000..e7895954ab
--- /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 0000000000..7dbd9b036e
--- /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 0000000000..007a2b0faf
--- /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 0000000000..4e65bc0347
--- /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 0000000000..13911cc29a
--- /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 0000000000..a9cb2f12f8
--- /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 0000000000..ab55fe2ee5
--- /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 0000000000..00750edc07
--- /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 0000000000..8d6a8d555b
--- /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 0000000000..084ba780ee
--- /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 0000000000..dbd6e5f420
--- /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 0000000000..0b278ce2a6
--- /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 0000000000..13911cc29a
--- /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 0000000000..a9cb2f12f8
--- /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 0000000000..ab55fe2ee5
--- /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 0000000000..00750edc07
--- /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 0000000000..8d6a8d555b
--- /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 0000000000..a420ef1842
--- /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 0000000000..91287a1a2e
--- /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 0000000000..a06f68b5f0
--- /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 0000000000..e7f0d01007
--- /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 0000000000..7e8a175046
--- /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 0000000000..7c8b98f50d
--- /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 0000000000..503ecb84e0
--- /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 0000000000..002bf1b455
--- /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 0000000000..0cfbf08886
--- /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 0000000000..74c2229083
--- /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 0000000000..029317d8ec
--- /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 0000000000..61dae3192e
--- /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 0000000000..97b5955f78
--- /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 0000000000..588efd1118
--- /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 0000000000..d00491fd7e
--- /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 0000000000..5513e438c0
--- /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 0000000000..76dc820d3b
--- /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 0000000000..588efd1118
--- /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 0000000000..d00491fd7e
--- /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 0000000000..5513e438c0
--- /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 0000000000..67d2ad1aac
--- /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 0000000000..97b5955f78
--- /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 0000000000..65513c116c
--- /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 0000000000..d00491fd7e
--- /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 0000000000..5513e438c0
--- /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 0000000000..8be22fa5c6
--- /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 0000000000..65513c116c
--- /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 0000000000..d00491fd7e
--- /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 0000000000..5513e438c0
--- /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 0000000000..8e7150562e
--- /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 0000000000..4420dc71b4
--- /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 0000000000..55e975aa82
--- /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 0000000000..62388f1465
--- /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 0000000000..5a933e6c85
--- /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 0000000000..4a21643e58
--- /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 0000000000..ca7896ff3c
--- /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 0000000000..65e68f99dd
--- /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 0000000000..e72ae9e72c
--- /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 0000000000..83417303a9
--- /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 0000000000..56e3ad3751
--- /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 0000000000..16d0828bf1
--- /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 0000000000..e2442d9f79
--- /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 0000000000..ead0ebbeef
--- /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 0000000000..072c996ef3
--- /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 0000000000..4a5ebfa0a6
--- /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 0000000000..707fd56d06
--- /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 0000000000..1bba78703c
--- /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 0000000000..d1a66d3366
--- /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 0000000000..87fa10cf5b
--- /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 0000000000..dad2c50af8
--- /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 0000000000..e657c083ed
--- /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 0000000000..e582eeb044
--- /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 0000000000..8ba3118ddf
--- /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 0000000000..166f9bd03f
--- /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 0000000000..086f493759
--- /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 0000000000..bb2cba1cfe
--- /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 0000000000..b3e25c7ccd
--- /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 0000000000..759c602be8
--- /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 0000000000..dee9a8a756
--- /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 0000000000..704d76cb49
--- /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 0000000000..d5b0144963
--- /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 0000000000..fe841bb262
--- /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 0000000000..5f769bec2f
--- /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 0000000000..7df1a90316
--- /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 0000000000..5a5dbfdb17
--- /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 0000000000..50c0a9b31e
--- /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 0000000000..657abc8c49
--- /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 0000000000..8d94d7fa77
--- /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 0000000000..3408d5cc90
--- /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 0000000000..e7830fb08c
--- /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 0000000000..e7e72bd30e
--- /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 0000000000..1ab8a0c90a
--- /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 0000000000..6eea359dbd
--- /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 0000000000..6eea359dbd
--- /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 0000000000..054c192d98
--- /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 0000000000..cde1798da8
--- /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 0000000000..cde1798da8
--- /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 0000000000..cde1798da8
--- /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 0000000000..cde1798da8
--- /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 0000000000..cde1798da8
--- /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 0000000000..cde1798da8
--- /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 0000000000..cde1798da8
--- /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 0000000000..cde1798da8
--- /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 0000000000..cde1798da8
--- /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 0000000000..6eea359dbd
--- /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 0000000000..cde1798da8
--- /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 0000000000..6eea359dbd
--- /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 0000000000..6eea359dbd
--- /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 0000000000..6eea359dbd
--- /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 0000000000..054c192d98
--- /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 0000000000..054c192d98
--- /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 0000000000..054c192d98
--- /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 0000000000..054c192d98
--- /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 0000000000..aabe6ec390
--- /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 0000000000..48fbdb6fde
--- /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 0000000000..f7b1badf6e
--- /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 0000000000..08d653e66c
--- /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 0000000000..05f0054e57
--- /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 0000000000..639a7cce7b
--- /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 0000000000..924d0edc29
--- /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 0000000000..967d952be9
--- /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 0000000000..a702f7ed22
--- /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 0000000000..dfa0cdaa5d
--- /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 0000000000..ec01a51bda
--- /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 0000000000..84a9856298
--- /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 0000000000..aa054c5cee
--- /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 0000000000..bf54afc074
--- /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 0000000000..20c8ee2c35
--- /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 0000000000..a8ec5df961
--- /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 0000000000..46644c0d56
--- /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 0000000000..631d1eb9e5
--- /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 0000000000..f62997be73
--- /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 0000000000..c0f0aa06a6
--- /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 0000000000..9c053cbf87
--- /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 0000000000..c0378ae026
--- /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 0000000000..f16326cccb
--- /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 0000000000..0c09290dcc
--- /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 0000000000..6654a09f37
--- /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 0000000000..a0a47d4539
--- /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 0000000000..b62db4b953
--- /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 0000000000..3f01b91a74
--- /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 0000000000..5b04b1e93f
--- /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 0000000000..ecc45f342c
--- /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 0000000000..e298647ebb
--- /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 0000000000..fa1b638bce
--- /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 0000000000..cd7ed66ab7
--- /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 0000000000..cacd4e4aad
--- /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 0000000000..4bde8eca64
--- /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 0000000000..f78284051f
--- /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 0000000000..1f9216111e
--- /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 0000000000..0446942f22
--- /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 0000000000..6a091c5357
--- /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 0000000000..e1220d7afc
--- /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 0000000000..f65cc5c3f4
--- /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 0000000000..93b5700501
--- /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 0000000000..8cec6fa331
--- /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 0000000000..05d7fd2d65
--- /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 0000000000..83a7ecfa3a
--- /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 0000000000..7ddd4ea0db
--- /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 0000000000..a12adcbfc1
--- /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 0000000000..d51eaf3887
--- /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 0000000000..77c773ac7d
--- /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 0000000000..8178d4b665
--- /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 0000000000..8bfb678098
--- /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 0000000000..06c4c1bdbd
--- /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 0000000000..43148bff9e
--- /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 0000000000..370f857d60
--- /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 0000000000..edb0bf8a52
--- /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 0000000000..814709f1bf
--- /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 0000000000..de625fdd23
--- /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 0000000000..d2c7339408
--- /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 0000000000..036d29a8ff
--- /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 0000000000..7d80d66772
--- /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 0000000000..2f8d8df4e4
--- /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 0000000000..eda93236db
--- /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 0000000000..03997e0107
--- /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 0000000000..0ce4ead348
--- /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 0000000000..e562a38a8d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/README
@@ -0,0 +1,5 @@
+The files in this directory contain test-vectors for ECDSA using NIST P-256 Curve (the test-vectors from 0 to 6 included), using NIST P-384 Curve (the test-vectors from 7 to 13 included) and using NIST P-521 Curve (the test-vectors from 14 to 20 included).
+
+The key files used for the signature contain a curve, a private key and a public key. Each key is represented as follows: Base64(len (curveID), curveID, len(privateKey), privateKey, len(publicKey), publicKey). The length is 4 bytes long. The curveID is a DER encoded OID (as stated in http://www.secg.org/sec2-v2.pdf). A public key (a point) is encoded as 0x4 || x coordinate || y coordinate, where (x, y) computed using the base point. The private key is generated randomly. To generate the test-vectors we were using Sage Math system.
+
+The random nonces (sigseed) and the plaintexts (already as hashes) are generated randomly and encoded using Base64 encoding. The resulted ciphertexts are presented in the ciphertext files and encoded using Base64 encoding. \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext0 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext0
new file mode 100644
index 0000000000..30b6d6ff23
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext0
@@ -0,0 +1 @@
+g0O4OK4uKlJAlR1MDRLTBjyfxFI3PLKLYk+pJyu7gDJTgMptbhg+vZS0lgEBR7jHFDG89TymXn2bZ+NWDE6h5Q== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext1 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext1
new file mode 100644
index 0000000000..4941703a81
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext1
@@ -0,0 +1 @@
+yaMRWtXb5AUhgva2zYOq3aczhYOP5pEldcaXtbnIbARVv3o2RjdhnVl2Nq6BaL36nPdO6KZrjHm0oQoUvD2bTA== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext10 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext10
new file mode 100644
index 0000000000..e6f98da8ac
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext10
@@ -0,0 +1,2 @@
+AIlc19+p3H+s2rJ98KkTaA351Vz2pAVuMCFB1jRshJVrw4QbHS+UQ9VuSGjZLe6dTf5vBAjlfeYQ
+NGnU7yhOxU2nl3tI+9qe/MrAL76d3e0+G/jBHk8hp006TbdiBrNK \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext11 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext11
new file mode 100644
index 0000000000..4bdf36dd58
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext11
@@ -0,0 +1 @@
+L8GGYb8eZCyjr/YAgmB7jWonjqXZ773+Iizm80wRe9PQzQKjaP3c9PiBjAJ5W8VBH8X0twayfznc/v4jozzE2PC3adIkOiIhn4TGWd0zcD/TpxeVreCEOLtCnO7ZTwGh \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext12 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext12
new file mode 100644
index 0000000000..9914f4d47a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext12
@@ -0,0 +1 @@
+lbxmnrmyoI+SotJ0F3cTBm+XigEB12hCBhXWdLotb1juvr80ksg2komHRqzKuuyrgQbmQwTnpQfmn/Y2iNx3CsL4++UWRH77/MaleccxGjHTJ0fNoQsBTT3Pa7s+1FDg \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext13 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext13
new file mode 100644
index 0000000000..01fe1f9057
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext13
@@ -0,0 +1 @@
+wRJKnt6DnqSYtMHr0HX/4v3qT2FTdLA/aY40y0Grz8Jc5aPD062+mUSSI3d43BKy3aGvJBJPXo5FfBAGZrrcPTZ4hb783D8MnRRzGnYqlP18d+HxGbhI/X3FgQvDpvoA \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext14 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext14
new file mode 100644
index 0000000000..7f3d91f8f9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext14
@@ -0,0 +1,3 @@
+AcKWiddIfeC5MGnUw8HxiW6h55HY+QgSgE2aPGdgv06hz3fF7+ibSHHWOOOKDAb+DOkDS/06fUSj
+Bz4JPrI+1S7GAfsjSDNA7FCdMMDlz6SzJ/AXtDqEnqPvuKjxkZTIWFoGcl3ckEqaXuHZQY6/ZUEC
+tU6BBedWeaZcj0VDiFDhT7VM \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext15 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext15
new file mode 100644
index 0000000000..d00accee00
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext15
@@ -0,0 +1,3 @@
+ALrhfS4bAPvF9GooBRAmS5BPItf9JJxuB9kXAnqFyoTfeo9Qj2X1BsZ1lRQ9/tNm791Pg434w6XT
+jVifx3sWdo79AZ/sgRq97VGVjVLvSNPkEuDWUP0UcjHQP7sOPZS3i04pactfM2D/xI9KKTH7nF0/
+oNQGqp3kSV5pdo9tBD5kNLxP \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext16 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext16
new file mode 100644
index 0000000000..329ca475d6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext16
@@ -0,0 +1,3 @@
+AUpC4BhuE7JTjlHZVrtjHZgzyudEOC5/I73cN3IJREJoUi4GaD34Lbc2Uaj2I40J/imqTukMAF92
+AIhzAoPKbY7LATmfsfCzC9QJJ110ch19FxipEUEmgYi2khejzsDgSjhDP9DjUHyvnX5GCC/jGzbZ
++38Vef+1pH73V1Dk7VGPfly/ \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext17 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext17
new file mode 100644
index 0000000000..35bff63b1b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext17
@@ -0,0 +1,3 @@
+AVu1YHSDn9uZIQcRKy79vaUtrfJb6dG6gX001BmwMnInkt3QpylrzyPScpWlMHHeNG7WhSJudTp+
+9EbcmQOvG6eUAb1cnamAm0q3oX4PlJMM50lUsX1bjSG7CEYwb0x1H9xr9fN+TgFMUgvZZXC7pY5r
+bhHlEUYQcMmRKG9ZHFc6LbEj \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext18 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext18
new file mode 100644
index 0000000000..4cb3b8eb44
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext18
@@ -0,0 +1,3 @@
+AHC8RciYJUDbd9w/47KfKD/9pKS98cXqep7XnKi9NDRuKi1wzgnVDMiUACkRA4IRy2I1/9cNKA8o
+j17hRNbWAEO9AF2fg5BhJSNLiOAkhBCt2GvLOsBRvPX58xn4u6gWyY8oV5bFBrMQvHS2avNujgHs
+MI+/lDXXb7w6GOFiScWeX6NC \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext19 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext19
new file mode 100644
index 0000000000..0d87e32c0c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext19
@@ -0,0 +1,3 @@
+AXNA1v4coiWNri0FEpHBpyDBt3IWjsaSa222ySUgcf6bz1SUIfB0DBGPZI7CZpRHl+B8oRHaD6gB
++IN6+4UI+nf+ACSsoM4ivi6HO3OcwG1uK1I93qhujMOkHSWZ27njMq6K20VbAW1WIAOwIwhEyqUc
+br/V+GZCCQgoKdmRh4Q2daOi \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext2 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext2
new file mode 100644
index 0000000000..1b6a3aade6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext2
@@ -0,0 +1 @@
+tnDjU02HxiZc64bV5bXn0SY9qRc302CSEXbSojvsVWL9MDLf7n+HYoCL3KzDzc9c3Am23YkNe+UmGmyiQ2cDsQ== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext20 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext20
new file mode 100644
index 0000000000..b7b204a8f9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext20
@@ -0,0 +1,3 @@
+APkk3zqRJEzbXeIJ1d7RgzkRJzgTUZwwpTDSVvSGgkMLs/vKSBnWHQk4sVGbU5lTNbgltF6sBC+1
+J2XgsiQ/xqLbAG/Bu4mbGTmWs1kaNDiDFg/BUr+au2QQSx8HbBTHZcXLmsLxNzItCS8oAlRA2Rjv
+Nq9oZNaz3rebPdt9xHXFh6bw \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext3 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext3
new file mode 100644
index 0000000000..67bf5604d8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext3
@@ -0,0 +1 @@
+4KKGd2/fEIClyuhRwrehW6BKH0/+OQgsirRfzIcrOZvFzAfKi5khbVYxHK37tL9P5PomDbXN4Dp0AeruvBLAiA== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext4 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext4
new file mode 100644
index 0000000000..9c5aa11d60
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext4
@@ -0,0 +1 @@
+pnjNl+SQmTBayW5VQ+CkmKP0xnB7UTBY4RsZtkSbCeTHWSbv3i6bZPR105a0uMLG5nS/gQjyl4eH/zE+MgETpA== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext5 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext5
new file mode 100644
index 0000000000..68e026b6a5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext5
@@ -0,0 +1 @@
+U9uDPGgYelgtc3AfIMnUtUUbAy0r+Gfu4Ig2RnrtlEZyEBE4VFKqwT55ScQqD5FUwjCqhjtnrKohq+FbrRejjA== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext6 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext6
new file mode 100644
index 0000000000..809f1c326c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext6
@@ -0,0 +1 @@
+7ED/IZr06H2cFwgTZ3iOtg59SCsSIa4+t1DW9cwd2u1oMgkkFvPHMgQboH8aULC6lRE8aGMJZTZ6WnTYJR3hBw== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext7 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext7
new file mode 100644
index 0000000000..5dd55e5d46
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext7
@@ -0,0 +1 @@
+b37O7Ui12JgVhBxhPsr6SVBu9WAfYgNj0VE5j8sIq7S2KH2UkLMsV87cAn0LAj58clN0lmBJXJViLyU9zptz5A/IodDm/mAY92yVr2V/SdOGdrubjqQ74giLceDaWK5G \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext8 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext8
new file mode 100644
index 0000000000..ab3a66dfec
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext8
@@ -0,0 +1 @@
+5wrpYRET0Om1gAeZOQrqeDkWLC11pKLF2ECxWwaUD4lqDbJYKF6mfYPXz8hrrbFvfq1TQywm+Wvb9fkAofHg99tdlv5HOE0vrhIdZHyXACtJ9hAjlYYZhmp0wSjP02ZH \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext9 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext9
new file mode 100644
index 0000000000..6f7f767520
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext9
@@ -0,0 +1 @@
+Ehmee5KL3MVy+ulw/4sw22HbIqY2pPp3V29Q7MTTSmA9xxhyLe4tuzWvio3rRFFaSiTDJUs9FJ/qN5uRrU59VtyU27jv+jXmRZGF14eW/+bI7pJ46u2I4oC/PKWrJUlg \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key0 b/security/nss/cmd/bltest/tests/ecdsa/key0
new file mode 100644
index 0000000000..491fdba1b8
--- /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 0000000000..f64e2de0d4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key1
@@ -0,0 +1 @@
+AAAACgYIKoZIzj0DAQcAAABBBP8XY2jN9iSwGmgjiKiEJ13traQZAfQjp9gm/s1ued3vKcAUoCya7wVzoOtE+1e318eseAmUCFTmSue3oRQ4iNAAAAAgUoPXpYUpyVq3AM/eQ8krtoa+IvndvJSu2d0Wfmw4G3k= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key10 b/security/nss/cmd/bltest/tests/ecdsa/key10
new file mode 100644
index 0000000000..d37d95ce7b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key10
@@ -0,0 +1,3 @@
+AAAABwYFK4EEACIAAABhBGNmUY5lDAhCxgugJReD7Q9NWibKxv4mPCeXk90hyZKquY0U1Z6WUOEY
+PbpMei6MDGdjOUnMAfTLKa10WajMqIFgR7rInBQqZqOtpKqtFUb3ilJbiOZUnUpn4zuWoDUCFQAA
+ADD/dS8s2Bui8eTEmURjxj0bzlPVfhbPErX/BETy11xb63U48OK2obH+N5b1mJlck3w= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key11 b/security/nss/cmd/bltest/tests/ecdsa/key11
new file mode 100644
index 0000000000..af2013affe
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key11
@@ -0,0 +1,3 @@
+AAAABwYFK4EEACIAAABhBI+fZwvjDD9sX9mh9nLTOiy6npcJ2nzGGeDLkcSlFhsnwigQLvyMNBvP
+d7afj9P09hHRozYAf2Z0UWhCHAiFccw9GChq2eTgCvTl6jxNKsdPIHqa1+eoukMB2mLchEKk8gAA
+ADAVhVW7PB4G4UBgfYgSDrbKZ4MJaED8XCvlKjjvPHaiYlr7+le4A54annNInynW3DY=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key12 b/security/nss/cmd/bltest/tests/ecdsa/key12
new file mode 100644
index 0000000000..32cede8d28
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key12
@@ -0,0 +1,3 @@
+AAAABwYFK4EEACIAAABhBPF9n9O34oRxht9krXuHEQFusdW2Q7XrgWTMX4w4YXasi3OXSzOHywxa
+JQ8jIXu7AcUVQTLfhSwQvswwvzvJUD1vPiJH/AZFPhQOrg8fYzsuSVs0NLQ/PW0nDqdcz9BVxAAA
+ADBfPgxyWf18Zn/ftiQfrpU/+Td0WD3QhAVYbNmRGGzP73YSLgmD8rafs1fW6NjZEOg=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key13 b/security/nss/cmd/bltest/tests/ecdsa/key13
new file mode 100644
index 0000000000..3743f1c41c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key13
@@ -0,0 +1,3 @@
+AAAABwYFK4EEACIAAABhBN9riLgrpq184TDaWpgqnU4pYyqyTXreZQ69O2sU4GENCGN9tmsgyGi3
+lt0r4wRwchlU4cxJeO5f6XrX0dqF46s57Pw6+tFf2OCU1X0jCPn7NrYz8X9Gjw9ZrKnqESLNyQAA
+ADBIzoBK0nAaFkL9z0H/6dmakHfrRZtrZE556sN0bHbN6uo+YGv8JK4xYJ+okqorCV4=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key14 b/security/nss/cmd/bltest/tests/ecdsa/key14
new file mode 100644
index 0000000000..2740bbb8fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key14
@@ -0,0 +1,5 @@
+AAAABwYFK4EEACMAAACFBAHLMSpMFVyG6mXE7SZ5O5Bwv4d8/QiAB3BzpXkyrU1W
+jJ9O9uOYTXM+cFtF5v56+LsI4yGkaAl9+RF6lFPjrhpIswCmBmEqMBgZpjoz38my
+nLHBI9MaFF8AHkRQwD3LJLo4eSZHOVkdIvDYLwicdlgr0zD3Nf76/HB1+0DkBGqE
+MyG22gAAAEIAFah7z179UbqqdH68pzdZsP1ChXjtYZ11rBM0+HP7yLirxH3ahKTt
+DjsY19GEjz4gKsaLfLiQ1/Dp+VKVLcBKpk0= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key15 b/security/nss/cmd/bltest/tests/ecdsa/key15
new file mode 100644
index 0000000000..c0e241b259
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key15
@@ -0,0 +1,4 @@
+AAAABwYFK4EEACMAAACFBAHNraBOZWsOfiIfcjggO2UgdVT/hWKgnuPNxeiBUN0y7hhWdeJDJEQw
+h8CKaKe34NwLHkI9v3srwrjjgrZhSE1C0wEqnTHutNYvzgdim0/1ez1AltxjpE2EELzUqnsrXl+V
+IbvO/SMGiUb4SPz3ddc3BDQ6uCCWkawr6CryY6fbQHSZgQAAAEIBVb3HzBg8uneljgGlyFD+6hQs
+nyNyOwYeMZTgd7pPCY43K4TGDGFtKzpDWPWjf5/TvLgxFhvzwPGLPMK5TLPtTPs= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key16 b/security/nss/cmd/bltest/tests/ecdsa/key16
new file mode 100644
index 0000000000..93858e7d99
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key16
@@ -0,0 +1,4 @@
+AAAABwYFK4EEACMAAACFBAELM1S0u6wWCy7/Alg1B/a3VSSnO42mKq/7Eydq+ae+nqhLUa7tX7Vv
+e6N1uWdJOX4t1ZwdHKyQUrrcR2ZhXCymmABTwSVTmcqRRIALlehX+Z24mE1hMyxJwlJAGOmDNpXg
+aWhBXQXu10vqQVfWqOER5OdvZlSMDlsHVmldgTxFi/tw8wAAAEIBc6g47xXFFvgOcqgikHnuMm+4
+F4YmKLbIXuCAlVqeMtlGG4utC4jeX2BKgsVoifsL1amJM4NNP9PJmeXHjtJKpRo= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key17 b/security/nss/cmd/bltest/tests/ecdsa/key17
new file mode 100644
index 0000000000..b7be949397
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key17
@@ -0,0 +1,4 @@
+AAAABwYFK4EEACMAAACFBADPXFUBwFhZPy1f6FaZu6IWEDpPRh0UmxGsbBYyXGXme/zgR9masrLY
+Q9SmgR9I+qfl2tpBjmwB8ltoNjcxyJGg+QFAdH/rM+0TRJo6qDm7uJNzY5mloOsKVgefekfMEPdX
+A2Sn2FVafJLZW7A6R6GvxRX5btTgjM6/XfnJaHr47DFBMwAAAEIAwzmBaAc3LPeoyPzcX70vAo6T
+jfI7tvA+N3DXvynLTcKWYZjIilMIqsNn7u+eMQ0xDM45im6j3yPcATmgGzUDam4=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key18 b/security/nss/cmd/bltest/tests/ecdsa/key18
new file mode 100644
index 0000000000..f58b965ade
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key18
@@ -0,0 +1,4 @@
+AAAABwYFK4EEACMAAACFBAFieatjCQKes5RNySyOxoR3TvNJ9tDAHwsR9RZJM4S3At6tU3fe8Pql
+yPt1eibbLvh7wgELngpPmoIRVWGG4LbCiQGHsWFJtpZQ2bs7BHGHT7L/t+vGqOUtvubTLq+xfTgW
+pUj0epQp+M8ZD0Fd622S4hODtlmPae695+yzNfUub4AjrAAAAEIBDMKWdudLb+7AriZjMEir6Qr+
+JUw6SG5KjiAi3nYymFRqr7tRGwUTkvX1Q64lMV7BgJ1Ch9qW6J11g4H6vtbGxLc=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key19 b/security/nss/cmd/bltest/tests/ecdsa/key19
new file mode 100644
index 0000000000..866ac08967
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key19
@@ -0,0 +1,4 @@
+AAAABwYFK4EEACMAAACFBAFRn1tqa8+H8gsEY6SDyUIg7L0ssJAePQcx1ADEbqorSXraND7BecWW
+fdzB/l3KbHXcFWAySIEhHJsxiaZEkoiOlQHKvTgw4WVzThQ09xcPBxP01R2Z29jRvoR6dh0vwCt6
+/Yw8Bt5DkafIV3fhrGSQcAPHNomub9yKoSrntNzgPBPZKQAAAEIBBeO8oosJMamU5b7R5LVAkl+J
+WEpiwFKGyK9svHBF5xbBy5HSFxt0tKXCzkhaJhu/tXGyeSedFATSTznrUR71tYU=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key2 b/security/nss/cmd/bltest/tests/ecdsa/key2
new file mode 100644
index 0000000000..f364b2377b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key2
@@ -0,0 +1 @@
+AAAACgYIKoZIzj0DAQcAAABBBGVG3cGzcX5hDchx/w8PZLuMMc2P6qlhzbfzWvtxVTkEd7MQ9deN7hIlyVUYk198Q2PQIRTiWtRVYA7bRwIlRCIAAAAggL+HbIocY2czS/UJE8y5lYKptWxLz7l2nkDCicqb3BM= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key20 b/security/nss/cmd/bltest/tests/ecdsa/key20
new file mode 100644
index 0000000000..db094b89b2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key20
@@ -0,0 +1,4 @@
+AAAABwYFK4EEACMAAACFBAAO18BJbSwNGxuZotCaEE2ZRutYNruikxsjqbXE5WtbyED65bllWUzD
+iCi9kn+r7avAL/ld+qDoTme1Pmzt+BSreQBBird/RGH5XIDuge8UQjnNMUPu6Iu4/j4DcoDuewtG
+O2y44isoGdRvOc3Iw9jQULJ5VtJtuCMmsIleglJ9gjAO9QAAAEIBPQClifuzZvzcrw4Hahu1UH3o
+A1m6xnJUK9JL8B/tZmUCdUwBevXHQ1xIajGxVka1DnYC7KzfgoqTJQhZnmejCOY=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key3 b/security/nss/cmd/bltest/tests/ecdsa/key3
new file mode 100644
index 0000000000..2d0e5de338
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key3
@@ -0,0 +1 @@
+AAAACgYIKoZIzj0DAQcAAABBBNgKE5o33CAcWXYgyE967xgyVCx/Ny3T+46oDsNoGguKssq2oVqlhpDwJeuwcSWjFUADuZKdpfGsfsCZwoG2oTsAAAAgc1T8iAilEQPJwL3QLVoSYH+gj9WyaMIzlEXb/BdDXHA= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key4 b/security/nss/cmd/bltest/tests/ecdsa/key4
new file mode 100644
index 0000000000..0b566446c9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key4
@@ -0,0 +1 @@
+AAAACgYIKoZIzj0DAQcAAABBBF5bq/2D0xa1ImD8HKoGiWLNU2p7HOegQcYVROWRQQyzFl3UOtrjQVHsef4oKfo8G3eHWAJRVc+iuLyvGOPQXl8AAAAgjzwuwj9STrQmn1vaUjll1jDQe6K/cH0F2IbIuFImXgQ= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key5 b/security/nss/cmd/bltest/tests/ecdsa/key5
new file mode 100644
index 0000000000..9102602941
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key5
@@ -0,0 +1 @@
+AAAACgYIKoZIzj0DAQcAAABBBFB50pPWkcrENLddIYxsb/1DyEEFqk+k3NODT7NfrgDPmP+rgdYQS8dpSTDMLio+lS9BWAHEXPLJpY9RuSkjlD8AAAAgP9tI3QDXD5JFPCNfxYRSiQCsvwH+rKefnaKPUOBqIcM= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key6 b/security/nss/cmd/bltest/tests/ecdsa/key6
new file mode 100644
index 0000000000..17b151edcf
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key6
@@ -0,0 +1 @@
+AAAACgYIKoZIzj0DAQcAAABBBMaKRuPseagu0jdyGJMGK/v/R3hGN2Jgsx0nLOKxDQTjD96BClG7fFOf4KlWY5+SVvIa+ySmH95oOEvlvFw/O7QAAAAg9pRcgToGhu2rwCf97g7rWxMv8ZM+nn7KhN1ChI25xuU= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key7 b/security/nss/cmd/bltest/tests/ecdsa/key7
new file mode 100644
index 0000000000..58ad8e0873
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key7
@@ -0,0 +1,3 @@
+AAAABwYFK4EEACIAAABhBLWMJG3t4khPYcsl3H492rAqukJ1RqJm27pqpN54rFGGr2VDwOfqb9tM
+ninq8IyOh42eaaVOEPXXu4Q/ATWBEfrbTRBjTpzAE2SSPuQma0lMq0RSVECCgdBOKIhB0H6VxAAA
+ADA3WPjUaMWCS9E5KbVDrEcf5CV5tCNNWJQkwjsAyALMCiXJqRVXwbq42WMuaELMW+g= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key8 b/security/nss/cmd/bltest/tests/ecdsa/key8
new file mode 100644
index 0000000000..5a8eec2df0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key8
@@ -0,0 +1,3 @@
+AAAABwYFK4EEACIAAABhBFAOD4kkHmLG2ASSN8n3K/R/ZNOKl8egsJUv+l2KNicOjOJqwTnhi1gN
+0gFX6tV0ZN9IEzj48bvMG3T9goEptgk5GWVMZv4tbsctnWzO6xEOD3szB0rWc+0Gdc9ZNxVuWQAA
+ADBMZ8FYtBjL0iyvCuK3sv7SKqjPBlRap0IhzlhGq8yROlBNj9O9T+SbVPqSGg4dca0=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/key9 b/security/nss/cmd/bltest/tests/ecdsa/key9
new file mode 100644
index 0000000000..c794c44c80
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/key9
@@ -0,0 +1,3 @@
+AAAABwYFK4EEACIAAABhBHwN4O5s8oMHEZRW9Cw25pBY1wN3aEA1FhY+YB6pGuRWW2gyR8gER0LJ
+iaL678GU9dRO6M3vqtxUXtmS/f3RkvsV/kcQa5tod5G7EPGzcnnhxB4jQ7s+eVtDEE3LQRm54AAA
+ADA4ahA2Ems2zcznoW2Ogdv9XOTfuVU5cx7RvcygOqljsXs7kMIiK0g7ChP9AgRcmmM=
diff --git a/security/nss/cmd/bltest/tests/ecdsa/numtests b/security/nss/cmd/bltest/tests/ecdsa/numtests
new file mode 100644
index 0000000000..aabe6ec390
--- /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 0000000000..48fbdb6fde
--- /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 0000000000..f393cca4ad
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext1
@@ -0,0 +1 @@
+70+lqMS2yiBPPask+j3Iru0I+CBps0dkxKYv9wkKN/0= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext10 b/security/nss/cmd/bltest/tests/ecdsa/plaintext10
new file mode 100644
index 0000000000..2c85a2b929
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext10
@@ -0,0 +1 @@
+O7xOr9dtXLrVOUwnoZuOamJoksOCu/AJQl7vnM5nKBrG+MiyB6tT0QinvJf/V/Dg
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext11 b/security/nss/cmd/bltest/tests/ecdsa/plaintext11
new file mode 100644
index 0000000000..bfcb0c7199
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext11
@@ -0,0 +1 @@
+2Ea3W3p+4T9F8jQ3u1sB08h45Icn0g0XZdAkqkZAl8C+bNRt7HFD2yelVjO1n2++
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext12 b/security/nss/cmd/bltest/tests/ecdsa/plaintext12
new file mode 100644
index 0000000000..a088eefc86
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext12
@@ -0,0 +1 @@
+7tI6LK4h3omU9JIsy3YQ5D35Q6bvA7SSHC5dfr7HRHVBO0aHG8LvB/MmUeSKC1Lx
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext13 b/security/nss/cmd/bltest/tests/ecdsa/plaintext13
new file mode 100644
index 0000000000..b25b1b58f8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext13
@@ -0,0 +1 @@
+V3J3ZsDxwglKTddpj0cZb+iDqOyJ6GeQqJAkPW9bFwAmsD2UVBntvKR4kQsk7CQR
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext14 b/security/nss/cmd/bltest/tests/ecdsa/plaintext14
new file mode 100644
index 0000000000..48fbdb6fde
--- /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 0000000000..12108ddcc4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext15
@@ -0,0 +1,2 @@
+ASGhzaNwWzEVNsr0G7vLgzHLmwanZp/58qj/yrcC711bn6cAzVnm0yD7klFyypW55PmE07T0b45D
+0hMzO3URX8kY \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext16 b/security/nss/cmd/bltest/tests/ecdsa/plaintext16
new file mode 100644
index 0000000000..66e3b7b275
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext16
@@ -0,0 +1,2 @@
+ACU0to4fsw+gcz5fwzPuRGxbnh1wk0kNPbk09Bg7zarJb/0SnZf0RL/JciIZXS0mfZwBprfYcLss
+g5E09EiLyYPE
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext17 b/security/nss/cmd/bltest/tests/ecdsa/plaintext17
new file mode 100644
index 0000000000..f5df9aeb6d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext17
@@ -0,0 +1,2 @@
+AHFZ+2hr7LE73SrITnxBdRIAQuIhe9sJv2IjH6mZ63hz7B0lUZBRq1L1UZYCMiJcySQE72fm58qD
+HBTp4TZFT4i6 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext18 b/security/nss/cmd/bltest/tests/ecdsa/plaintext18
new file mode 100644
index 0000000000..f1c641f08d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext18
@@ -0,0 +1,2 @@
+ASwIYky567pL6O3quwElPDfKVZO/7mDgYfyTfDXPdgzshZy5m0m9QeBHyt+nR0tHHEQGGm+fyhD2
+j3ymdPPQ7vhO \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext19 b/security/nss/cmd/bltest/tests/ecdsa/plaintext19
new file mode 100644
index 0000000000..a7586d77c1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext19
@@ -0,0 +1,2 @@
+AeL/vCfQJqo6G0cKf4JP85zORGd2wDp47NI8jilqs3hPzN0DRV322Kgwpn1Wm819FP6zOiMgtw+p
+lKiA2AoX9vA1 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext2 b/security/nss/cmd/bltest/tests/ecdsa/plaintext2
new file mode 100644
index 0000000000..65a772dd0f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext2
@@ -0,0 +1 @@
+SfpXl5Llf4iquhkXy4lshoIqoSbnaBB+PxGW17x99sU= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext20 b/security/nss/cmd/bltest/tests/ecdsa/plaintext20
new file mode 100644
index 0000000000..c41bffa25c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext20
@@ -0,0 +1,2 @@
+ANDejmBr18vwOj5bRuaVvsbCJsJUnsY0h7meGKBmehWiaSzEy+Uk3frUxD+jFwB3QJ+y00mfjJHk
+gcQTb1dNKtk7 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext3 b/security/nss/cmd/bltest/tests/ecdsa/plaintext3
new file mode 100644
index 0000000000..aff2e23609
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext3
@@ -0,0 +1 @@
+5zRhgEl3WocyPf53pVA08iC9rhwsXNu6esNgfNOd09A= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext4 b/security/nss/cmd/bltest/tests/ecdsa/plaintext4
new file mode 100644
index 0000000000..ac7fcfec9d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext4
@@ -0,0 +1 @@
+CbvtewBEVhbGdugFywOCh7YyM/99PoGsqgmM100hFok= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext5 b/security/nss/cmd/bltest/tests/ecdsa/plaintext5
new file mode 100644
index 0000000000..ecba6e38bd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext5
@@ -0,0 +1 @@
+cROiGlKZaGbm1nfrM2L8YXXX9l+h4IkQtI5ovo66Vm0= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext6 b/security/nss/cmd/bltest/tests/ecdsa/plaintext6
new file mode 100644
index 0000000000..c834e9c34d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext6
@@ -0,0 +1 @@
+nBtD5rFYJ+4NmPw6qfeAxfcjl+UtcHJ6AtXgnC04Kck= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext7 b/security/nss/cmd/bltest/tests/ecdsa/plaintext7
new file mode 100644
index 0000000000..48fbdb6fde
--- /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 0000000000..064bd690cb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext8
@@ -0,0 +1,2 @@
+Mxl2AoAoODkjI3BRRJhERyaYl3mGdClyckJTOYg3ApBlAXdQY2mQJmOXQDiUiXhyGEIyEWWRcJJI
+GQ== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext9 b/security/nss/cmd/bltest/tests/ecdsa/plaintext9
new file mode 100644
index 0000000000..53199176dd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext9
@@ -0,0 +1 @@
+cxSK1gNt4qh6Q/YMYTPGb06yvMmOA8CdF2Fe+TA3KWu9Sma4Uw60bsNiUXVfGJaG
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed0 b/security/nss/cmd/bltest/tests/ecdsa/sigseed0
new file mode 100644
index 0000000000..05d7fd2d65
--- /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 0000000000..1a8f41a8bc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed1
@@ -0,0 +1 @@
++uIjgHPQK45HEoD6scaacINDhCSlavy/LOQstFOjA9I= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed10 b/security/nss/cmd/bltest/tests/ecdsa/sigseed10
new file mode 100644
index 0000000000..a2adf8a40f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed10
@@ -0,0 +1 @@
+Ee3Cm8MeIculRkFplZnPEv7gBCPRTq+C9g55xgfw6XlEDgwQ2O4sW0QBpSbV1bkE
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed11 b/security/nss/cmd/bltest/tests/ecdsa/sigseed11
new file mode 100644
index 0000000000..5dbd37dbb7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed11
@@ -0,0 +1 @@
+eacQrgxAKTRE67OWEAIn1PiBGMjr1MHrAvugBZGvWLWj0qpJK7ysGrP5AUU5knA6
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed12 b/security/nss/cmd/bltest/tests/ecdsa/sigseed12
new file mode 100644
index 0000000000..8d85f4c971
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed12
@@ -0,0 +1 @@
+OZyWwfeQNAwuldqcxrvG6D1U53pto7nNeBtFOxWApMAsfy8znVlNJ392yPOYFXR1
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed13 b/security/nss/cmd/bltest/tests/ecdsa/sigseed13
new file mode 100644
index 0000000000..05ad2f58d1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed13
@@ -0,0 +1 @@
+E5M7txkzv3/JJzgkWgYkjSb+auo3diREUK6QtEe5tUovRinB9D62rwsUnYO4Zh9h
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed14 b/security/nss/cmd/bltest/tests/ecdsa/sigseed14
new file mode 100644
index 0000000000..4ac0765848
--- /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 0000000000..647e49207e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed15
@@ -0,0 +1,2 @@
+AWTDEcA39i86TZu4RjBbkDE4Bo0PcPsy3Vs7uSpfEpzG1za21tk7778bg0zjh+Cn40uqfG0F47do
+hMKNtshEivBN \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed16 b/security/nss/cmd/bltest/tests/ecdsa/sigseed16
new file mode 100644
index 0000000000..603e1d8b28
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed16
@@ -0,0 +1,2 @@
+ASnw0hIQ2FzntL2vHcZrIFWeJHVhlPlIBQformN6nv8vzp7a9/hqIudPY/uHv001e9ryEuczmG36
+cgjmxOTEca2X \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed17 b/security/nss/cmd/bltest/tests/ecdsa/sigseed17
new file mode 100644
index 0000000000..34b0ad79c1
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed17
@@ -0,0 +1,2 @@
+AKdGyvpvfzX4pI3TBFsTbVyLLlOoVQXpvz8xYLGB6n/bMEe3pLpsb8lRCbVuS/9agXzY3XZN27PX
+tf3CclGx4rbW \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed18 b/security/nss/cmd/bltest/tests/ecdsa/sigseed18
new file mode 100644
index 0000000000..de76ac8a4d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed18
@@ -0,0 +1,2 @@
+AUr+RxF9oCVYkIwufo/WMRy6x4ftZlTojmEwUIQ3XS/tEtsqOJmvSKB304R1P6hpdghAYUVQ5Lf0
+P8BheUDuOLE5 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed19 b/security/nss/cmd/bltest/tests/ecdsa/sigseed19
new file mode 100644
index 0000000000..f5803e2eff
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed19
@@ -0,0 +1,2 @@
+AJWl5lI4w6SWNnOAIM5JG2/zJlLmG8KtuVy0LALG0geNHjNuh6WOjmBMOB0Ru14m/nvVp/AOXOaD
+NXbhZaCuuwoX \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed2 b/security/nss/cmd/bltest/tests/ecdsa/sigseed2
new file mode 100644
index 0000000000..cc79571786
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed2
@@ -0,0 +1 @@
+a5F2DtjzM797shbFrp7g4O/tBT9jdtljEWKhnldZOak= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed20 b/security/nss/cmd/bltest/tests/ecdsa/sigseed20
new file mode 100644
index 0000000000..aacfb9f5f4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed20
@@ -0,0 +1,2 @@
+ABJ+5ak5x4Npkzxcq1hRKJjhKjIy4jVkVDhgZ9+3p+1ItpbJxsWMlVD835yQyeW/lFOENrcLo2Qw
+RyNEPndnPG5D \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed3 b/security/nss/cmd/bltest/tests/ecdsa/sigseed3
new file mode 100644
index 0000000000..49473d7f8e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed3
@@ -0,0 +1 @@
+IV8M637yzsL+KYLyALkf92O+euGBw9PrMopiHcb/SJU= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed4 b/security/nss/cmd/bltest/tests/ecdsa/sigseed4
new file mode 100644
index 0000000000..254aa94a40
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed4
@@ -0,0 +1 @@
+ZxclhYSFGNGLM7tZ1Z5k39ZVXiWCnd/PnsVUza3O/WQ= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed5 b/security/nss/cmd/bltest/tests/ecdsa/sigseed5
new file mode 100644
index 0000000000..6ddd59d81a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed5
@@ -0,0 +1 @@
+gbPop+RXoXIuYeNAb+IGgLwdTE1AnhG7LsPkfETvayQ= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed6 b/security/nss/cmd/bltest/tests/ecdsa/sigseed6
new file mode 100644
index 0000000000..3f9c9808fb
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed6
@@ -0,0 +1 @@
+WAHT3XYcVbT0ZB5MxfUo9636BVA4JkEKcYBFhQvIWkQ= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed7 b/security/nss/cmd/bltest/tests/ecdsa/sigseed7
new file mode 100644
index 0000000000..a0687196c4
--- /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 0000000000..ad47b64b79
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed8
@@ -0,0 +1 @@
+LLGTvUo3kUNR3qdAVcvKCDEFPT/ialozxy0RY3aJJxkJJ3NpuXl3l7v6dUo51/qg
diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed9 b/security/nss/cmd/bltest/tests/ecdsa/sigseed9
new file mode 100644
index 0000000000..080fceb649
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed9
@@ -0,0 +1 @@
+3pch8aH8+9zNR8+8P8gS0ftX0dqTkzExF1x4TkKfnYUfttwtkU0D1ge62Hg0tiVr
diff --git a/security/nss/cmd/bltest/tests/md2/ciphertext0 b/security/nss/cmd/bltest/tests/md2/ciphertext0
new file mode 100644
index 0000000000..22e1fc496c
--- /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 0000000000..d00491fd7e
--- /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 0000000000..dce2994ba5
--- /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 0000000000..ea11ee523b
--- /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 0000000000..d00491fd7e
--- /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 0000000000..5ae3875e2a
--- /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 0000000000..d964ef8644
--- /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 0000000000..97b5955f78
--- /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 0000000000..65513c116c
--- /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 0000000000..d00491fd7e
--- /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 0000000000..5513e438c0
--- /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 0000000000..337d307655
--- /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 0000000000..65513c116c
--- /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 0000000000..d00491fd7e
--- /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 0000000000..5513e438c0
--- /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 0000000000..004f13472a
--- /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 0000000000..6050da4c68
--- /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 0000000000..65513c116c
--- /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 0000000000..65513c116c
--- /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 0000000000..0cfbf08886
--- /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 0000000000..5513e438c0
--- /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 0000000000..d41abc7b84
--- /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 0000000000..544713b339
--- /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 0000000000..97b5955f78
--- /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 0000000000..65513c116c
--- /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 0000000000..d00491fd7e
--- /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 0000000000..d68e0362d5
--- /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 0000000000..5513e438c0
--- /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 0000000000..133777dd08
--- /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 0000000000..65513c116c
--- /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 0000000000..d00491fd7e
--- /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 0000000000..d68e0362d5
--- /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 0000000000..5513e438c0
--- /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 0000000000..943ea599ae
--- /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 0000000000..1352fe9866
--- /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 0000000000..d00491fd7e
--- /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 0000000000..d915bc88c4
--- /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 0000000000..7037fa2e10
--- /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 0000000000..4cece4832f
--- /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 0000000000..6007b8d655
--- /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 0000000000..43b65a6706
--- /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 0000000000..9d0da8a074
--- /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 0000000000..3ecd857681
--- /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 0000000000..09d8a8582f
--- /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 0000000000..bae2acb56e
--- /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 0000000000..6226b0e7f6
--- /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 0000000000..9095393e01
--- /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 0000000000..8eb40cd8c0
--- /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 0000000000..1e86bb071b
--- /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 0000000000..3f87612fc8
--- /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 0000000000..64a5f4fe72
--- /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 0000000000..9af9805c60
--- /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 0000000000..4396ffbafd
--- /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 0000000000..5d53ef0b0c
--- /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 0000000000..6e865ff4bc
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..61684becc4
--- /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 0000000000..61684becc4
--- /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 0000000000..3c9f8742f1
--- /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 0000000000..3c9f8742f1
--- /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 0000000000..a2ad3ff8d5
--- /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 0000000000..a2ad3ff8d5
--- /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 0000000000..a2ad3ff8d5
--- /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 0000000000..a2ad3ff8d5
--- /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 0000000000..a2ad3ff8d5
--- /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 0000000000..a2ad3ff8d5
--- /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 0000000000..61684becc4
--- /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 0000000000..61684becc4
--- /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 0000000000..61684becc4
--- /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 0000000000..61684becc4
--- /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 0000000000..3c9f8742f1
--- /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 0000000000..3c9f8742f1
--- /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 0000000000..3c9f8742f1
--- /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 0000000000..3c9f8742f1
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..3c032078a4
--- /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 0000000000..5961feea3d
--- /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 0000000000..bd17cf9e93
--- /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 0000000000..d07c85b367
--- /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 0000000000..fcd6baa03d
--- /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 0000000000..a154e41321
--- /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 0000000000..8af8ac61d7
--- /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 0000000000..b302369ad6
--- /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 0000000000..36812091de
--- /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 0000000000..7449ac6779
--- /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 0000000000..f3945c85f8
--- /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 0000000000..6c08a2a23f
--- /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 0000000000..efd84ad707
--- /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 0000000000..17963365b6
--- /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 0000000000..38913e9c7e
--- /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 0000000000..5d4bf7cb23
--- /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 0000000000..d1bf800968
--- /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 0000000000..bb96c956f0
--- /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 0000000000..8a71ad8e7b
--- /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 0000000000..8b990a2f31
--- /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 0000000000..afb497d5b1
--- /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 0000000000..762ceaf5ad
--- /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 0000000000..5cfd292ad5
--- /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 0000000000..516e13d9a6
--- /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 0000000000..680ddbd4ae
--- /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 0000000000..f41e51c600
--- /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 0000000000..9a825c93cf
--- /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 0000000000..dcf464dc4b
--- /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 0000000000..90133c73e6
--- /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 0000000000..0c82aab49c
--- /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 0000000000..4cd022ec9f
--- /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 0000000000..275f908022
--- /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 0000000000..3406494e6c
--- /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 0000000000..c7316f9dfe
--- /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 0000000000..a4cbd16407
--- /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 0000000000..d4a76a0526
--- /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 0000000000..8cd39a9c68
--- /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/README b/security/nss/cmd/bltest/tests/rsa_pss/README
new file mode 100644
index 0000000000..6b2ebf0bda
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/README
@@ -0,0 +1 @@
+The test vectors in this folder are used to test the RSA-PSS code. The tests 0-17 use the SHA-1 hash function, the tests 18-19 use the SHA-256 hash function, the tests 20-21 use the SHA-384 hash function. \ No newline at end of file
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 0000000000..0ed7e8c103
--- /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 0000000000..01aa061c9c
--- /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 0000000000..f31ec8eef6
--- /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 0000000000..2e67c03762
--- /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 0000000000..7f3530c213
--- /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 0000000000..2d8791535e
--- /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 0000000000..eaa167e352
--- /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 0000000000..a7bff41b96
--- /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 0000000000..79e7afb613
--- /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 0000000000..86b2cfd3b4
--- /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/ciphertext18 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext18
new file mode 100644
index 0000000000..30ba6cb031
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext18
@@ -0,0 +1 @@
+lIqC19k21FCCvK9St7rh1YBrWugJI76xgKSh7XuuV0/AH6lIukcqCkODU5zIza9sRz6VluOKEvNOkscaqkCjbPVVQeNa/II0iwjcRG/XNgj1J9vNi9Lt+UiKRcO/YMoAz+UmqJTL9nbKVJEbAX3ckjDnMZZ/XzQJS87WyUFw7Ak= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext19 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext19
new file mode 100644
index 0000000000..50d693d35d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext19
@@ -0,0 +1 @@
+oNSdYElIrvVdpPuXWr+eDKcy2DaBoRPdCitzmoorhd2e3nc0V1VSjun5/x/UxUojVe11tcVzDhXXmZFDLT1DEF1ZIq4BUBg9Og0bHXsd93BAC8P1M15I3O1Tsw8fs711XfRy2ONarnyUF+yI2pMSvI95eKB/tPaOVyWVgkgwpm5LssAoRjxP0zE/OIVMH+jIvVeg+gf1uVh7QncCv7VuCgEOViH4mjd05Zydc6YMwbjeH5AZM778l38eZtz6Vg50x1yB/0r09KKDc9D7awIbPSU3GiDy2fbmfPIyBqwNvtZbVd1rEdCUEJiSvXOhW7Fle9FSYekTyH3Rfr/R0GKiTQ== \ No newline at end of file
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 0000000000..47f9922489
--- /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/ciphertext20 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext20
new file mode 100644
index 0000000000..2a16959ac8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext20
@@ -0,0 +1 @@
+L3Ad3lcyjzUFWRLBB6V8LvizEEbKA9+gBKarSAG8LViCtuoJJ5jrXTv8BMdV121JJIFNMF6YsHPa+o7n1tMwVasRCiLirvP9yORL/2THHhcNxX+AO1kpvz6IdgTueior3zRjutR3wzrwxYaJSo8WlCYSlSoDLJt4wt5aw1eOh1U= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/ciphertext21 b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext21
new file mode 100644
index 0000000000..97abe8fe57
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/ciphertext21
@@ -0,0 +1 @@
+l3HCE9I9e21NAXYVhsvJySQVu2+pfHP+0e82Vr7ke7htBg21AsG/jWd+JpEhpVwNyA2cqDBLDQZn4YigM6HX+AqhEXxcMeFccGleb3NF5qXwtmuaFQBJyuU9/gXFEip3mldECMuLdZono0zdDgiCpz/Ep3x43aD/RzVK/tLKSbSyUROw3bKifpaSIAMYPeJ1iA2AMv2c1ON1oaKjb0GUH5bv/ZHF0uCbuShoxJHu8aYrYkeL3y1b8RQRO/e/mjpGNNZTGZTCEa6UFv7GdBO5bYZBFsfgAMkCyut74aDSNTpyr68gfGY4XXglKwpXUFw6/pkOWOG6GB+m5g0ULSrBqg== \ No newline at end of file
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 0000000000..28306f23a1
--- /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 0000000000..a83e4f591d
--- /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 0000000000..b4a3e3c41d
--- /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 0000000000..92a284cac9
--- /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 0000000000..55bed19a46
--- /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 0000000000..b6a3018a33
--- /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 0000000000..0da2bcba07
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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/hash18 b/security/nss/cmd/bltest/tests/rsa_pss/hash18
new file mode 100644
index 0000000000..64262c2eac
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash18
@@ -0,0 +1 @@
+sha256
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash19 b/security/nss/cmd/bltest/tests/rsa_pss/hash19
new file mode 100644
index 0000000000..64262c2eac
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash19
@@ -0,0 +1 @@
+sha256
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 0000000000..fcdd09c7dd
--- /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/hash20 b/security/nss/cmd/bltest/tests/rsa_pss/hash20
new file mode 100644
index 0000000000..197e4aa310
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash20
@@ -0,0 +1 @@
+sha384
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/hash21 b/security/nss/cmd/bltest/tests/rsa_pss/hash21
new file mode 100644
index 0000000000..60f458cde7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/hash21
@@ -0,0 +1 @@
+sha384 \ No newline at end of file
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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..46154801ca
--- /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 0000000000..46154801ca
--- /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 0000000000..ef62249f14
--- /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 0000000000..ef62249f14
--- /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 0000000000..9f74b3113f
--- /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 0000000000..9f74b3113f
--- /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 0000000000..9f74b3113f
--- /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 0000000000..9f74b3113f
--- /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 0000000000..9f74b3113f
--- /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 0000000000..9f74b3113f
--- /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/key18 b/security/nss/cmd/bltest/tests/rsa_pss/key18
new file mode 100644
index 0000000000..46154801ca
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key18
@@ -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/key19 b/security/nss/cmd/bltest/tests/rsa_pss/key19
new file mode 100644
index 0000000000..9f74b3113f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key19
@@ -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 0000000000..46154801ca
--- /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/key20 b/security/nss/cmd/bltest/tests/rsa_pss/key20
new file mode 100644
index 0000000000..46154801ca
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key20
@@ -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/key21 b/security/nss/cmd/bltest/tests/rsa_pss/key21
new file mode 100644
index 0000000000..9f74b3113f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/key21
@@ -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/key3 b/security/nss/cmd/bltest/tests/rsa_pss/key3
new file mode 100644
index 0000000000..46154801ca
--- /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 0000000000..46154801ca
--- /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 0000000000..46154801ca
--- /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 0000000000..ef62249f14
--- /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 0000000000..ef62249f14
--- /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 0000000000..ef62249f14
--- /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 0000000000..ef62249f14
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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/maskhash18 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash18
new file mode 100644
index 0000000000..64262c2eac
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash18
@@ -0,0 +1 @@
+sha256
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash19 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash19
new file mode 100644
index 0000000000..64262c2eac
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash19
@@ -0,0 +1 @@
+sha256
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 0000000000..fcdd09c7dd
--- /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/maskhash20 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash20
new file mode 100644
index 0000000000..60f458cde7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash20
@@ -0,0 +1 @@
+sha384 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/maskhash21 b/security/nss/cmd/bltest/tests/rsa_pss/maskhash21
new file mode 100644
index 0000000000..197e4aa310
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/maskhash21
@@ -0,0 +1 @@
+sha384
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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..fcdd09c7dd
--- /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 0000000000..8fdd954df9
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/numtests
@@ -0,0 +1 @@
+22 \ No newline at end of file
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 0000000000..6218384634
--- /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 0000000000..e8ce055a64
--- /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 0000000000..e7c8e71c7e
--- /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 0000000000..6af26f1733
--- /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 0000000000..d94dd83f42
--- /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 0000000000..a7998a4d14
--- /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 0000000000..b18920b745
--- /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 0000000000..407ec5cc89
--- /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 0000000000..c10bd8dc8e
--- /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 0000000000..cf9856cb50
--- /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/plaintext18 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext18
new file mode 100644
index 0000000000..308d889751
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext18
@@ -0,0 +1 @@
+sHTPDreX8OBy2HI7TTylTgcp23MHZaDCzD2EvH2a2eU= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext19 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext19
new file mode 100644
index 0000000000..69042a098f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext19
@@ -0,0 +1 @@
++7ollkbnkxPBlmn44TwIqunTc/mhZKZBSEw+8sVi6Do= \ No newline at end of file
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 0000000000..3b390ec8f3
--- /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/plaintext20 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext20
new file mode 100644
index 0000000000..9423c5ca9b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext20
@@ -0,0 +1 @@
+X5EfOb/yrZEPkVDoFO8tcT+SoSb12FF81pFkh496bjQxOsTR+JB0117SKnMlETrs \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/plaintext21 b/security/nss/cmd/bltest/tests/rsa_pss/plaintext21
new file mode 100644
index 0000000000..5717923302
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/plaintext21
@@ -0,0 +1 @@
+9c/VD/5YZylCA6IiXXail2FiXvTM0eE0kDpqyGwqBaROdiYWxPXGIKjoueke7jpB \ No newline at end of file
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 0000000000..36da06a987
--- /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 0000000000..c8d7ff2ba9
--- /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 0000000000..fb0a775cf3
--- /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 0000000000..05de2c24b6
--- /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 0000000000..b0b066052c
--- /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 0000000000..dc97a9c554
--- /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 0000000000..cd9c0725a0
--- /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 0000000000..2e26315332
--- /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 0000000000..26e4788dad
--- /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 0000000000..8418bb7cc4
--- /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 0000000000..f582586461
--- /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 0000000000..59469f99fd
--- /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 0000000000..402552fe5e
--- /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 0000000000..d840fd556e
--- /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 0000000000..2edca8b903
--- /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 0000000000..80e23fbba2
--- /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 0000000000..2e7a00d429
--- /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/seed18 b/security/nss/cmd/bltest/tests/rsa_pss/seed18
new file mode 100644
index 0000000000..a5cd7b8cb6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed18
@@ -0,0 +1 @@
+GFt1LMXU6mtkIJwKMP+Nm3l2Z9CJ1KUVKpjF9WZ+5WY= \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed19 b/security/nss/cmd/bltest/tests/rsa_pss/seed19
new file mode 100644
index 0000000000..59c88aa698
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed19
@@ -0,0 +1 @@
+xa78saDnF7JsnT1IOUVcvZvd1wXaiWMZdQ80MB41H3s= \ No newline at end of file
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 0000000000..4df6784b4f
--- /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/seed20 b/security/nss/cmd/bltest/tests/rsa_pss/seed20
new file mode 100644
index 0000000000..da123f117f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed20
@@ -0,0 +1 @@
+taPFMNUYb279NTjWAWJUeFKsN3c4aRO0B2zcV4VfXlZenae7NRFD1GV+kivVIBk3 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/rsa_pss/seed21 b/security/nss/cmd/bltest/tests/rsa_pss/seed21
new file mode 100644
index 0000000000..6a392f4def
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa_pss/seed21
@@ -0,0 +1 @@
+kegGyCeVFDJ2DtrL/DKfeTFjodxhcehNAjtluf09+2WS0uD3Lce3V9Knl4I1VlBS \ No newline at end of file
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 0000000000..d58108df16
--- /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 0000000000..7d366c13eb
--- /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 0000000000..a2da928b0a
--- /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 0000000000..6dcd0e5098
--- /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 0000000000..0b6e3f37af
--- /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 0000000000..b1b34b4687
--- /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 0000000000..d18d81a02f
--- /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 0000000000..97e970e1ba
--- /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 0000000000..2b3b07661c
--- /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 0000000000..13911cc29a
--- /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 0000000000..d00491fd7e
--- /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 0000000000..8d6a8d555b
--- /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 0000000000..314ffbd8e6
--- /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 0000000000..2b3b07661c
--- /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 0000000000..13911cc29a
--- /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 0000000000..d00491fd7e
--- /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 0000000000..8d6a8d555b
--- /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 0000000000..1fe4bd2bd4
--- /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 0000000000..d00491fd7e
--- /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 0000000000..863e79c65b
--- /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 0000000000..dfc3d279c5
--- /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 0000000000..bef4714bbe
--- /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 0000000000..0cfbf08886
--- /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 0000000000..8baef1b4ab
--- /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 0000000000..afb5dce5d4
--- /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 0000000000..07e2ff14fa
--- /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 0000000000..2ab6e1da58
--- /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 0000000000..0cfbf08886
--- /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 0000000000..8baef1b4ab
--- /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 0000000000..afb5dce5d4
--- /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 0000000000..c94f91e22a
--- /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 0000000000..833f06d844
--- /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 0000000000..0cfbf08886
--- /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 0000000000..8baef1b4ab
--- /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 0000000000..94fcc2b297
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha384/plaintext1
@@ -0,0 +1 @@
+abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu
diff --git a/security/nss/cmd/bltest/tests/sha3_224/ciphertext0 b/security/nss/cmd/bltest/tests/sha3_224/ciphertext0
new file mode 100644
index 0000000000..c85d77885b
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_224/ciphertext0
@@ -0,0 +1 @@
+5kKCTD+M8krQkjTufTx2b8mjpRaNDJStc7Rv3w== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/sha3_224/ciphertext1 b/security/nss/cmd/bltest/tests/sha3_224/ciphertext1
new file mode 100644
index 0000000000..3862d7517a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_224/ciphertext1
@@ -0,0 +1 @@
+zETk/sw7yR9vyKyHeowvdE7qZDvXRqjFNAODyw== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/sha3_224/numtests b/security/nss/cmd/bltest/tests/sha3_224/numtests
new file mode 100644
index 0000000000..0cfbf08886
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_224/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/sha3_224/plaintext0 b/security/nss/cmd/bltest/tests/sha3_224/plaintext0
new file mode 100644
index 0000000000..8baef1b4ab
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_224/plaintext0
@@ -0,0 +1 @@
+abc
diff --git a/security/nss/cmd/bltest/tests/sha3_224/plaintext1 b/security/nss/cmd/bltest/tests/sha3_224/plaintext1
new file mode 100644
index 0000000000..3c8366ea1e
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_224/plaintext1
@@ -0,0 +1 @@
+122EK2FIG0MB5BSL1SC5JGBW9RX44WHS
diff --git a/security/nss/cmd/bltest/tests/sha3_256/ciphertext0 b/security/nss/cmd/bltest/tests/sha3_256/ciphertext0
new file mode 100644
index 0000000000..4b7a8be437
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_256/ciphertext0
@@ -0,0 +1 @@
+BBu9VoDtr36iEIcqkh5GSTVWgNbvfBKfXw7JQWMN1K4=
diff --git a/security/nss/cmd/bltest/tests/sha3_256/ciphertext1 b/security/nss/cmd/bltest/tests/sha3_256/ciphertext1
new file mode 100644
index 0000000000..3be5bf7e83
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_256/ciphertext1
@@ -0,0 +1 @@
+Wfasna8sxiTTAswiFp+hKz94w/IcrycenfQlx3tMcj0=
diff --git a/security/nss/cmd/bltest/tests/sha3_256/numtests b/security/nss/cmd/bltest/tests/sha3_256/numtests
new file mode 100644
index 0000000000..0cfbf08886
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_256/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/sha3_256/plaintext0 b/security/nss/cmd/bltest/tests/sha3_256/plaintext0
new file mode 100644
index 0000000000..143eeaad2c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_256/plaintext0
@@ -0,0 +1 @@
+XG8XAO4I3YZNVJJ5K40R12F3YIRA7WP8
diff --git a/security/nss/cmd/bltest/tests/sha3_256/plaintext1 b/security/nss/cmd/bltest/tests/sha3_256/plaintext1
new file mode 100644
index 0000000000..e1624c19d2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_256/plaintext1
@@ -0,0 +1 @@
+DKOG28OVG5JCS7922VF7G00QBZTOA2Q2
diff --git a/security/nss/cmd/bltest/tests/sha3_384/ciphertext0 b/security/nss/cmd/bltest/tests/sha3_384/ciphertext0
new file mode 100644
index 0000000000..a5150d6417
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_384/ciphertext0
@@ -0,0 +1 @@
+lEDUd0ZL5Q+Q8v3YMw/mhulZ4IKML9XDmjLsffyRup43WaYCSYVIcpS6n7rezVZy \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/sha3_384/ciphertext1 b/security/nss/cmd/bltest/tests/sha3_384/ciphertext1
new file mode 100644
index 0000000000..18b364b900
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_384/ciphertext1
@@ -0,0 +1 @@
+fzLOq3a6G7i5Yc/6KnDR/P8ZrnwHb+DlzhR+nIqCe6BhCGuyciUbetJ+C61Ygt74 \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/sha3_384/numtests b/security/nss/cmd/bltest/tests/sha3_384/numtests
new file mode 100644
index 0000000000..0cfbf08886
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_384/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/sha3_384/plaintext0 b/security/nss/cmd/bltest/tests/sha3_384/plaintext0
new file mode 100644
index 0000000000..050e980f86
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_384/plaintext0
@@ -0,0 +1 @@
+TQWW3E325C08FJ1B8T4P6Q7UPYZRBRKD \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/sha3_384/plaintext1 b/security/nss/cmd/bltest/tests/sha3_384/plaintext1
new file mode 100644
index 0000000000..a1533ca331
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_384/plaintext1
@@ -0,0 +1 @@
+Z13PMSNAM542GHFNBPV12TJHDNF63WY2
diff --git a/security/nss/cmd/bltest/tests/sha3_512/ciphertext0 b/security/nss/cmd/bltest/tests/sha3_512/ciphertext0
new file mode 100644
index 0000000000..0843b43b58
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_512/ciphertext0
@@ -0,0 +1,2 @@
+NWdFNsaq+p0m6999OGSEgOu7XxK6aAz8On5IhE4ebC07C0PAJTcZ/Y3AUt5bvQXCEw3vXsFGqaPn
+GvtAwbcvpg== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/sha3_512/ciphertext1 b/security/nss/cmd/bltest/tests/sha3_512/ciphertext1
new file mode 100644
index 0000000000..840f68cfc4
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_512/ciphertext1
@@ -0,0 +1,2 @@
+LO9UaCHnbFW7D1Lofc3MKDTzJMaiLPySWTgcOBohj16AP8V65V5DsRzUCQq7BvJ+2DtXbsX8wRMv
+sXDjNNyVJw== \ No newline at end of file
diff --git a/security/nss/cmd/bltest/tests/sha3_512/numtests b/security/nss/cmd/bltest/tests/sha3_512/numtests
new file mode 100644
index 0000000000..0cfbf08886
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_512/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/sha3_512/plaintext0 b/security/nss/cmd/bltest/tests/sha3_512/plaintext0
new file mode 100644
index 0000000000..85eca6ba56
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_512/plaintext0
@@ -0,0 +1 @@
+BU66CYFKPPT6LLPIYLJOCZ5QZP5IB2FM
diff --git a/security/nss/cmd/bltest/tests/sha3_512/plaintext1 b/security/nss/cmd/bltest/tests/sha3_512/plaintext1
new file mode 100644
index 0000000000..0f1bd22d86
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha3_512/plaintext1
@@ -0,0 +1 @@
+T18RE9CFOLCHXPYCZMKSCUIKX3MCT6FY
diff --git a/security/nss/cmd/bltest/tests/sha512/ciphertext0 b/security/nss/cmd/bltest/tests/sha512/ciphertext0
new file mode 100644
index 0000000000..8b626e2379
--- /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 0000000000..c02d1752d0
--- /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 0000000000..0cfbf08886
--- /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 0000000000..8baef1b4ab
--- /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 0000000000..94fcc2b297
--- /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 0000000000..f3b23fdcdc
--- /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 0000000000..f82341325b
--- /dev/null
+++ b/security/nss/cmd/btoa/btoa.c
@@ -0,0 +1,218 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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",
+ "");
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ SECStatus rv;
+ FILE *inFile = NULL, *outFile = NULL;
+ PRBool closeIn = PR_TRUE, closeOut = PR_TRUE;
+ PLOptState *optstate = NULL;
+ PLOptStatus status;
+ char *suffix = NULL;
+ int exitCode = -1;
+
+ 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:");
+ PORT_Assert(optstate);
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ default:
+ Usage(progName);
+ goto loser;
+ break;
+
+ case 'i':
+ inFile = fopen(optstate->value, "rb");
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ goto loser;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "wb");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ goto loser;
+ }
+ 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);
+ goto loser;
+ }
+#endif
+ inFile = stdin;
+ closeIn = PR_FALSE;
+ }
+ 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);
+ goto loser;
+ }
+#endif
+ outFile = stdout;
+ closeOut = PR_FALSE;
+ }
+ 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);
+ goto loser;
+ }
+ if (suffix) {
+ fprintf(outFile, "-----END %s-----\n", suffix);
+ }
+ exitCode = 0;
+loser:
+ PL_DestroyOptState(optstate);
+ if (inFile && closeIn) {
+ fclose(inFile);
+ }
+ if (outFile && closeOut) {
+ fclose(outFile);
+ }
+ if (suffix) {
+ PORT_Free(suffix);
+ }
+ return exitCode;
+}
diff --git a/security/nss/cmd/btoa/btoa.gyp b/security/nss/cmd/btoa/btoa.gyp
new file mode 100644
index 0000000000..295d5758ed
--- /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 0000000000..52508a59a6
--- /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/certutil/Makefile b/security/nss/cmd/certutil/Makefile
new file mode 100644
index 0000000000..74ae200208
--- /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 0000000000..501608c850
--- /dev/null
+++ b/security/nss/cmd/certutil/certext.c
@@ -0,0 +1,2266 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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",
+ "x509Any",
+ "ipsecIKE",
+ "ipsecIKEEnd",
+ "ipsecIKEIntermediate",
+ "ipsecEnd",
+ "ipsecTunnel",
+ "ipsecUser",
+ 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) {
+ /*
+ * none of the 'new' extended key usage options work with the prompted menu. This is so
+ * old scripts can continue to work.
+ */
+ 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;
+ /*
+ * These new usages can only be added explicitly by the userSuppliedValues. This allows old
+ * scripts which used '>7' as an exit value to continue to work.
+ */
+ case 8:
+ if (!userSuppliedValue)
+ goto endloop;
+ rv = AddOidToSequence(os, SEC_OID_X509_ANY_EXT_KEY_USAGE);
+ break;
+ case 9:
+ if (!userSuppliedValue)
+ goto endloop;
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_IPSEC_IKE);
+ break;
+ case 10:
+ if (!userSuppliedValue)
+ goto endloop;
+ rv = AddOidToSequence(os, SEC_OID_IPSEC_IKE_END);
+ break;
+ case 11:
+ if (!userSuppliedValue)
+ goto endloop;
+ rv = AddOidToSequence(os, SEC_OID_IPSEC_IKE_INTERMEDIATE);
+ break;
+ case 12:
+ if (!userSuppliedValue)
+ goto endloop;
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_IPSEC_END);
+ break;
+ case 13:
+ if (!userSuppliedValue)
+ goto endloop;
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_IPSEC_TUNNEL);
+ break;
+ case 14:
+ if (!userSuppliedValue)
+ goto endloop;
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_IPSEC_USER);
+ 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);
+ }
+
+ 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 0000000000..07b1ea51bd
--- /dev/null
+++ b/security/nss/cmd/certutil/certutil.c
@@ -0,0 +1,4038 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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"
+#include "basicutil.h"
+#include "ssl.h"
+
+#define MIN_KEY_BITS 512
+/* MAX_KEY_BITS should agree with RSA_MAX_MODULUS_BITS in freebl */
+#define MAX_KEY_BITS 8192
+#define DEFAULT_KEY_BITS 2048
+
+#define GEN_BREAK(e) \
+ rv = e; \
+ break;
+
+char *progName;
+
+static SECStatus
+ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert,
+ CERTCertTrust *trust, PK11SlotInfo *slot, void *pwdata)
+{
+ SECStatus rv;
+
+ 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 (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
+ PK11SlotInfo *internalslot;
+ internalslot = PK11_GetInternalKeySlot();
+ rv = PK11_Authenticate(internalslot, PR_TRUE, pwdata);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName,
+ "could not authenticate to token %s.",
+ PK11_GetTokenName(internalslot));
+ PK11_FreeSlot(internalslot);
+ return SECFailure;
+ }
+ PK11_FreeSlot(internalslot);
+ }
+ rv = CERT_ChangeCertTrust(handle, cert, trust);
+ }
+ }
+ return rv;
+}
+
+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 = ChangeCertTrust(handle, cert, trust, slot, pwdata);
+ 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 };
+ SECAlgorithmID signAlg;
+ SECItem *params = NULL;
+
+ 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) {
+ params = SEC_CreateSignatureAlgorithmParameters(arena,
+ NULL,
+ SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
+ hashAlgTag,
+ NULL,
+ privk);
+ if (!params) {
+ PORT_FreeArena(arena, PR_FALSE);
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ SECU_PrintError(progName, "unable to create RSA-PSS parameters");
+ return SECFailure;
+ }
+
+ spki->algorithm.parameters.data = NULL;
+ rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
+ SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
+ hashAlgTag == SEC_OID_UNKNOWN ? NULL : params);
+ if (rv != SECSuccess) {
+ PORT_FreeArena(arena, PR_FALSE);
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ 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;
+ }
+
+ PORT_Memset(&signAlg, 0, sizeof(signAlg));
+ if (pssCertificate) {
+ rv = SECOID_SetAlgorithmID(arena, &signAlg,
+ SEC_OID_PKCS1_RSA_PSS_SIGNATURE, params);
+ if (rv != SECSuccess) {
+ PORT_FreeArena(arena, PR_FALSE);
+ SECU_PrintError(progName, "unable to set algorithm ID");
+ return SECFailure;
+ }
+ } else {
+ 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 = SECOID_SetAlgorithmID(arena, &signAlg, signAlgTag, 0);
+ if (rv != SECSuccess) {
+ PORT_FreeArena(arena, PR_FALSE);
+ SECU_PrintError(progName, "unable to set algorithm ID");
+ return SECFailure;
+ }
+ }
+
+ /* Sign the request */
+ rv = SEC_DerSignDataWithAlgorithmID(arena, &signedReq,
+ encoding->data, encoding->len,
+ privk, &signAlg);
+ 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_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
+ 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 = ChangeCertTrust(handle, cert, trust, slot, pwdata);
+ 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,
+ PRBool simpleSelfSigned)
+{
+ 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;
+ }
+ if (simpleSelfSigned &&
+ SECEqual == SECITEM_CompareItem(&the_cert->derIssuer,
+ &the_cert->derSubject)) {
+ printf("\"%s\" [%s]\n\n", the_cert->nickname, the_cert->subjectName);
+ CERT_DestroyCertificate(the_cert);
+ return SECSuccess;
+ }
+
+ 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 (slot && PK11_NeedUserInit(slot)) {
+ printf("\nDatabase needs user init\n");
+ }
+
+ 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, void *pwdata)
+{
+ SECStatus rv;
+ CERTCertificate *cert;
+
+ cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
+ 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, void *pwdata)
+{
+ SECStatus rv;
+ CERTCertificate *cert;
+
+ cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
+ 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 'I':
+ usage = certificateUsageIPsec;
+ 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 *nick;
+ CERTVerifyLogNode *node;
+
+ node = log->head;
+ while (node) {
+ if (node->cert->nickname != NULL) {
+ nick = node->cert->nickname;
+ } else {
+ nick = node->cert->subjectName;
+ }
+ fprintf(stderr, "%s : %s\n", nick,
+ 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) {
+ snprintf(dst, 3, "%02x", *src++);
+ }
+ *dst = '\0';
+ }
+}
+
+static const char *const keyTypeName[] = {
+ "null", "rsa", "dsa", "fortezza", "dh", "kea", "ec", "rsaPss", "rsaOaep"
+};
+
+#define MAX_CKA_ID_BIN_LEN 20
+#define MAX_CKA_ID_STR_LEN 40
+
+/* output human readable key ID in buffer, which should have at least
+ * MAX_CKA_ID_STR_LEN + 3 octets (quotations and a null terminator) */
+static void
+formatPrivateKeyID(SECKEYPrivateKey *privkey, char *buffer)
+{
+ SECItem *ckaID;
+
+ ckaID = PK11_GetLowLevelKeyIDForPrivateKey(privkey);
+ if (!ckaID) {
+ strcpy(buffer, "(no CKA_ID)");
+ } else if (ItemIsPrintableASCII(ckaID)) {
+ int len = PR_MIN(MAX_CKA_ID_STR_LEN, ckaID->len);
+ buffer[0] = '"';
+ memcpy(buffer + 1, ckaID->data, len);
+ buffer[1 + len] = '"';
+ buffer[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, buffer);
+ }
+ SECITEM_ZfreeItem(ckaID, PR_TRUE);
+}
+
+/* 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)
+{
+ char ckaIDbuf[MAX_CKA_ID_STR_LEN + 4];
+ CERTCertificate *cert;
+ KeyType keyType;
+
+ formatPrivateKeyID(key, ckaIDbuf);
+ cert = PK11_GetCertFromPrivateKey(key);
+ if (cert) {
+ keyType = CERT_GetCertKeyType(&cert->subjectPublicKeyInfo);
+ CERT_DestroyCertificate(cert);
+ } else {
+ keyType = key->keyType;
+ }
+ PR_fprintf(out, "<%2d> %-8.8s %-42.42s %s\n", count,
+ keyTypeName[keyType], ckaIDbuf, nickName);
+
+ 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
+DeleteCertAndKey(char *nickname, secuPWData *pwdata)
+{
+ SECStatus rv;
+ CERTCertificate *cert;
+ PK11SlotInfo *slot;
+
+ slot = PK11_GetInternalKeySlot();
+ if (PK11_NeedLogin(slot)) {
+ 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;
+}
+
+static SECKEYPrivateKey *
+findPrivateKeyByID(PK11SlotInfo *slot, const char *ckaID, secuPWData *pwarg)
+{
+ PORTCheapArenaPool arena;
+ SECItem ckaIDItem = { 0 };
+ SECKEYPrivateKey *privkey = NULL;
+ SECStatus rv;
+
+ if (PK11_NeedLogin(slot)) {
+ rv = PK11_Authenticate(slot, PR_TRUE, pwarg);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "could not authenticate to token %s.",
+ PK11_GetTokenName(slot));
+ return NULL;
+ }
+ }
+
+ if (0 == PL_strncasecmp("0x", ckaID, 2)) {
+ ckaID += 2; /* skip leading "0x" */
+ }
+ PORT_InitCheapArena(&arena, DER_DEFAULT_CHUNKSIZE);
+ if (SECU_HexString2SECItem(&arena.arena, &ckaIDItem, ckaID)) {
+ privkey = PK11_FindKeyByKeyID(slot, &ckaIDItem, pwarg);
+ }
+ PORT_DestroyCheapArena(&arena);
+ return privkey;
+}
+
+static SECStatus
+DeleteKey(SECKEYPrivateKey *privkey, secuPWData *pwarg)
+{
+ SECStatus rv;
+ PK11SlotInfo *slot;
+
+ slot = PK11_GetSlotFromPrivateKey(privkey);
+ if (PK11_NeedLogin(slot)) {
+ rv = PK11_Authenticate(slot, PR_TRUE, pwarg);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "could not authenticate to token %s.",
+ PK11_GetTokenName(slot));
+ return SECFailure;
+ }
+ }
+
+ rv = PK11_DeleteTokenPrivateKey(privkey, PR_TRUE);
+ if (rv != SECSuccess) {
+ char ckaIDbuf[MAX_CKA_ID_STR_LEN + 4];
+ formatPrivateKeyID(privkey, ckaIDbuf);
+ SECU_PrintError("problem deleting private key \"%s\"\n", ckaIDbuf);
+ }
+
+ 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) {
+ char *token_uri = PK11_GetTokenURI(le->slot);
+ printf("\n");
+ printf(" slot: %s\n", PK11_GetSlotName(le->slot));
+ printf(" token: %s\n", PK11_GetTokenName(le->slot));
+ printf(" uri: %s\n", token_uri);
+ PORT_Free(token_uri);
+ }
+ PK11_FreeSlotList(list);
+
+ return SECSuccess;
+}
+
+static void
+PrintBuildFlags()
+{
+#ifdef NSS_FIPS_DISABLED
+ PR_fprintf(PR_STDOUT, "NSS_FIPS_DISABLED\n");
+#endif
+#ifdef NSS_NO_INIT_SUPPORT
+ PR_fprintf(PR_STDOUT, "NSS_NO_INIT_SUPPORT\n");
+#endif
+ exit(0);
+}
+
+static void
+PrintSyntax()
+{
+#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 cert-name [-d certdir] [-P dbprefix]\n",
+ progName);
+ FPS "\t%s -F -k key-id [-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);
+ 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);
+ 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 --build-flags\n", progName);
+ 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"
+ "\t\t [--simple-self-signed]\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 Sign the certificate with RSA-PSS (the issuer key must be rsa)\n",
+ " --pss-sign");
+ 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\", \"x509Any\",\n"
+ "%-20s \"ipsecIKE\", \"ipsecIKEEnd\", \"ipsecIKEIntermediate\",\n"
+ "%-20s \"ipsecEnd\", \"ipsecTunnel\", \"ipsecUser\",\n"
+ "%-20s \"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");
+ 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);
+ 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");
+ 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", "");
+ 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 and associated certificate 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 The key id of the key to delete, obtained using -K\n",
+ " -k key-id");
+ 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\","
+ " \"ec\","
+ " \"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 "%-20s don't search for a chain if issuer name equals subject name\n",
+ " --simple-self-signed");
+ 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");
+ FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
+ " -k key-type-or-id");
+ FPS "%-20s or nickname of the cert key to use, or key id obtained using -K\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 Create a certificate request restricted to RSA-PSS (rsa only)\n",
+ " --pss");
+ FPS "%-20s Name of file containing PQG parameters (dsa only)\n",
+ " -q pqgfile");
+ 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",
+ "");
+ 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 I \t IPsec\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");
+ FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
+ " -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 Create a certificate restricted to RSA-PSS (rsa only)\n",
+ " --pss");
+ FPS "%-20s Name of file containing PQG parameters (dsa only)\n",
+ " -q pqgfile");
+ 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",
+ "");
+ FPS "%-20s Self sign\n",
+ " -x");
+ FPS "%-20s Sign the certificate with RSA-PSS (the issuer key must be rsa)\n",
+ " --pss-sign");
+ 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
+luBuildFlags(enum usage_level ul, const char *command)
+{
+ int is_my_command = (command && 0 == strcmp(command, "build-flags"));
+ if (ul == usage_all || !command || is_my_command)
+ FPS "%-15s Print enabled build flags relevant for NSS test execution\n",
+ "--build-flags");
+ if (ul == usage_selected && !is_my_command)
+ return;
+ FPS "\n");
+}
+
+static void
+LongUsage(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);
+ luBuildFlags(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()
+{
+ 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(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
+SetSignatureAlgorithm(PLArenaPool *arena,
+ SECAlgorithmID *signAlg,
+ SECAlgorithmID *spkiAlg,
+ SECOidTag hashAlgTag,
+ SECKEYPrivateKey *privKey,
+ PRBool pssSign)
+{
+ SECStatus rv;
+
+ if (pssSign ||
+ SECOID_GetAlgorithmTag(spkiAlg) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
+ SECItem *srcParams;
+ SECItem *params;
+
+ if (SECOID_GetAlgorithmTag(spkiAlg) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
+ srcParams = &spkiAlg->parameters;
+ } else {
+ /* If the issuer's public key is RSA, the parameter field
+ * of the SPKI should be NULL, which can't be used as a
+ * basis of RSA-PSS parameters. */
+ srcParams = NULL;
+ }
+ params = SEC_CreateSignatureAlgorithmParameters(arena,
+ NULL,
+ SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
+ hashAlgTag,
+ srcParams,
+ privKey);
+ if (!params) {
+ SECU_PrintError(progName, "Could not create RSA-PSS parameters");
+ return SECFailure;
+ }
+ rv = SECOID_SetAlgorithmID(arena, signAlg,
+ SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
+ params);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Could not set signature algorithm id.");
+ return rv;
+ }
+ } else {
+ KeyType keyType = SECKEY_GetPrivateKeyType(privKey);
+ SECOidTag algID;
+
+ algID = SEC_GetSignatureAlgorithmOidTag(keyType, hashAlgTag);
+ if (algID == SEC_OID_UNKNOWN) {
+ SECU_PrintError(progName, "Unknown key or hash type for issuer.");
+ return SECFailure;
+ }
+ rv = SECOID_SetAlgorithmID(arena, signAlg, algID, 0);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Could not set signature algorithm id.");
+ return rv;
+ }
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+SignCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool selfsign,
+ SECOidTag hashAlgTag,
+ SECKEYPrivateKey *privKey, char *issuerNickName,
+ int certVersion, PRBool pssSign, void *pwarg)
+{
+ SECItem der;
+ SECKEYPrivateKey *caPrivateKey = NULL;
+ SECStatus rv;
+ PLArenaPool *arena;
+ CERTCertificate *issuer;
+ void *dummy;
+
+ arena = cert->arena;
+
+ if (selfsign) {
+ issuer = cert;
+ } else {
+ issuer = PK11_FindCertFromNickname(issuerNickName, pwarg);
+ if ((CERTCertificate *)NULL == issuer) {
+ SECU_PrintError(progName, "unable to find issuer with nickname %s",
+ issuerNickName);
+ rv = SECFailure;
+ goto done;
+ }
+ privKey = caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg);
+ if (caPrivateKey == NULL) {
+ SECU_PrintError(progName, "unable to retrieve key %s", issuerNickName);
+ rv = SECFailure;
+ CERT_DestroyCertificate(issuer);
+ goto done;
+ }
+ }
+
+ if (pssSign &&
+ (SECKEY_GetPrivateKeyType(privKey) != rsaKey &&
+ SECKEY_GetPrivateKeyType(privKey) != rsaPssKey)) {
+ SECU_PrintError(progName, "unable to create RSA-PSS signature with key %s",
+ issuerNickName);
+ rv = SECFailure;
+ if (!selfsign) {
+ CERT_DestroyCertificate(issuer);
+ }
+ goto done;
+ }
+
+ rv = SetSignatureAlgorithm(arena,
+ &cert->signature,
+ &issuer->subjectPublicKeyInfo.algorithm,
+ hashAlgTag,
+ privKey,
+ pssSign);
+ if (!selfsign) {
+ CERT_DestroyCertificate(issuer);
+ }
+ if (rv != SECSuccess) {
+ 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);
+ rv = SECFailure;
+ goto done;
+ }
+
+ 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_DerSignDataWithAlgorithmID(arena, &cert->derCert, der.data, der.len,
+ privKey, &cert->signature);
+ 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,
+ PRBool pssSign,
+ 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, pssSign, 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];
+ }
+ snprintf(buf, sizeof(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 = PR_ARRAY_SIZE(opFlagsArray);
+
+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 = PR_ARRAY_SIZE(attrFlagsArray);
+
+#define MAX_STRING 30
+CK_ULONG
+GetFlags(char *flagsString, flagArray *flags, 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, flags[i].name, flags[i].nameSize) ==
+ 0) {
+ flagsValue |= flags[i].value;
+ flagsString += flags[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,
+ cmd_BuildFlags,
+ 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_PssSign,
+ opt_SimpleSelfSigned,
+ 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" },
+ { /* cmd_BuildFlags */ 0, PR_FALSE, 0, PR_FALSE,
+ "build-flags" }
+};
+#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" },
+ { /* opt_PssSign */ 0, PR_FALSE, 0, PR_FALSE,
+ "pss-sign" },
+ { /* opt_SimpleSelfSigned */ 0, PR_FALSE, 0, PR_FALSE,
+ "simple-self-signed" },
+};
+#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();
+
+ if (certutil.commands[cmd_PrintSyntax].activated) {
+ PrintSyntax();
+ }
+
+ if (certutil.commands[cmd_PrintHelp].activated) {
+ 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((command ? usage_selected : usage_all), command);
+ exit(1);
+ }
+
+ if (certutil.commands[cmd_BuildFlags].activated) {
+ PrintBuildFlags();
+ }
+
+ 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;
+ }
+ if (keytype == ecKey) {
+ PR_fprintf(PR_STDERR, "%s -g: Not for ec keys.\n", progName);
+ return 255;
+ }
+ }
+
+ /* -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;
+ } else if (PL_strcmp(arg, "ec") == 0) {
+ keytype = ecKey;
+ } 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();
+ }
+ }
+
+ /* --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();
+ }
+ }
+
+ /* -q PQG file or curve name */
+ if (certutil.options[opt_PQGFile].activated) {
+ 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);
+ 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();
+ }
+
+ 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, -M, -S, -V, and all require -n */
+ if ((certutil.commands[cmd_AddCert].activated ||
+ certutil.commands[cmd_DeleteCert].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;
+ }
+
+ /* Delete needs a nickname or a key ID */
+ if (certutil.commands[cmd_DeleteKey].activated &&
+ !(certutil.options[opt_Nickname].activated || keysource)) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: specify a nickname (-n) or\n"
+ " a key ID (-k).\n",
+ progName, commandToRun);
+ 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();
+ /* Ensure the SSL error code table has been registered. Bug 1460284. */
+ SSL_OptionSetDefault(-1, 0);
+ }
+ 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))) {
+ rv = PK11_InitPin(slot, (char *)NULL, "");
+ } else {
+ rv = SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg,
+ certutil.options[opt_NewPasswordFile].arg);
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Could not set password for the slot");
+ goto shutdown;
+ }
+ }
+
+ /* if we are going to modify the cert database,
+ * make sure it's initialized */
+ if (certutil.commands[cmd_ModifyCertTrust].activated ||
+ certutil.commands[cmd_CreateAndAddCert].activated ||
+ certutil.commands[cmd_AddCert].activated ||
+ certutil.commands[cmd_AddEmailCert].activated) {
+ if (PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) {
+ char *password = NULL;
+ /* fetch the password from the command line or the file
+ * if no password is supplied, initialize the password to NULL */
+ if (pwdata.source == PW_FROMFILE) {
+ password = SECU_FilePasswd(slot, PR_FALSE, pwdata.data);
+ } else if (pwdata.source == PW_PLAINTEXT) {
+ password = PL_strdup(pwdata.data);
+ }
+ rv = PK11_InitPin(slot, (char *)NULL, password ? password : "");
+ if (password) {
+ PORT_Memset(password, 0, PL_strlen(password));
+ PORT_Free(password);
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Could not set password for the slot");
+ goto shutdown;
+ }
+ }
+ }
+
+ /* 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,
+ certutil.options[opt_SimpleSelfSigned].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, &pwdata);
+ goto shutdown;
+ }
+ /* Rename cert (--rename) */
+ if (certutil.commands[cmd_Rename].activated) {
+ rv = RenameCert(certHandle, name, newName, &pwdata);
+ goto shutdown;
+ }
+ /* Delete key (-F) */
+ if (certutil.commands[cmd_DeleteKey].activated) {
+ if (certutil.options[opt_Nickname].activated) {
+ rv = DeleteCertAndKey(name, &pwdata);
+ } else {
+ privkey = findPrivateKeyByID(slot, keysource, &pwdata);
+ if (!privkey) {
+ SECU_PrintError(progName, "%s is not a key-id", keysource);
+ rv = SECFailure;
+ } else {
+ rv = DeleteKey(privkey, &pwdata);
+ /* already destroyed by PK11_DeleteTokenPrivateKey */
+ privkey = NULL;
+ }
+ }
+ 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);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Could not set password for the slot");
+ 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) {
+ privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata);
+ } else {
+ /* Interpret keysource as CKA_ID */
+ privkey = findPrivateKeyByID(slot, keysource, &pwdata);
+ }
+
+ if (!privkey) {
+ SECU_PrintError(
+ progName,
+ "%s is neither a key-type nor a nickname nor a key-id", keysource);
+ return SECFailure;
+ }
+
+ pubkey = SECKEY_ConvertToPublicKey(privkey);
+ if (!pubkey) {
+ SECU_PrintError(progName,
+ "Could not get keys from cert %s", keysource);
+ if (keycert) {
+ CERT_DestroyCertificate(keycert);
+ }
+ rv = SECFailure;
+ 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) {
+ if (keycert) {
+ 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;
+ }
+ } else {
+ SECU_PrintError(progName, "Subject name not provided");
+ rv = SECFailure;
+ goto shutdown;
+ }
+ }
+ if (keycert) {
+ 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;
+ }
+ }
+
+ /* --pss-sign is to sign a certificate with RSA-PSS, even if the
+ * issuer's key is an RSA key. If the key is an RSA-PSS key, the
+ * generated signature is always RSA-PSS. */
+ if (certutil.options[opt_PssSign].activated) {
+ if (!certutil.commands[cmd_CreateNewCert].activated &&
+ !certutil.commands[cmd_CreateAndAddCert].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: --pss-sign only works with -C or -S.\n",
+ progName, commandToRun);
+ return 255;
+ }
+ if (keytype != rsaKey) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: --pss-sign only works with RSA keys.\n",
+ progName, commandToRun);
+ return 255;
+ }
+ }
+
+ if (certutil.options[opt_SimpleSelfSigned].activated &&
+ !certutil.commands[cmd_DumpChain].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: --simple-self-signed only works with -O.\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,
+ certutil.options[opt_PssSign].activated,
+ &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 0000000000..d8f1b5d4c9
--- /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 0000000000..565587264d
--- /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 0000000000..9b96bce911
--- /dev/null
+++ b/security/nss/cmd/certutil/keystuff.c
@@ -0,0 +1,595 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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
+
+#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];
+#ifdef XP_UNIX
+ int fd;
+#endif
+ int c;
+ int rv = 0;
+ size_t count;
+#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|");
+
+#if defined(XP_UNIX)
+ /* turn off echo on stdin & return on 1 char instead of NL */
+ fd = fileno(stdin);
+
+ 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;
+}
+
+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;
+}
+
+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;
+ case ecKey:
+ mechanism = CKM_EC_KEY_PAIR_GEN;
+ /* For EC keys, PQGFile determines EC parameters */
+ if ((params = (void *)getECParams(pqgFile)) == NULL)
+ return NULL;
+ break;
+ 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;
+ case ecKey:
+ SECITEM_FreeItem((SECItem *)params, PR_TRUE);
+ break;
+ 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 0000000000..c0bce4c7e6
--- /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 0000000000..3ffa387472
--- /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 0000000000..a33d184570
--- /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 0000000000..15abbcc938
--- /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 0000000000..e74e1d73d0
--- /dev/null
+++ b/security/nss/cmd/chktest/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 = nss
+
+#REQUIRES = seccmd dbm softoken
+REQUIRES = seccmd dbm
+
+#INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
+
+PROGRAM = chktest
+
+USE_STATIC_LIBS = 1
+
+CSRCS = \
+ chktest.c \
+ $(NULL)
+
diff --git a/security/nss/cmd/crlutil/Makefile b/security/nss/cmd/crlutil/Makefile
new file mode 100644
index 0000000000..a61ae1c4c3
--- /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 0000000000..fce5e2a601
--- /dev/null
+++ b/security/nss/cmd/crlutil/crlgen.c
@@ -0,0 +1,1541 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 0000000000..3ec792108b
--- /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 0000000000..d5950ff91f
--- /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 0000000000..603dd2d1be
--- /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 0000000000..a412e9892e
--- /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 0000000000..89ac46c737
--- /dev/null
+++ b/security/nss/cmd/crlutil/crlutil.c
@@ -0,0 +1,1144 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 {
+ SECStatus rv = SECITEM_CopyItem(NULL, &derName, &cert->derSubject);
+ CERT_DestroyCertificate(cert);
+ if (rv != SECSuccess) {
+ return ((CERTSignedCrl *)NULL);
+ }
+ }
+
+ 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;
+
+ 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;
+ }
+
+ crl = PK11_ImportCRL(slot, &crlDER, url, type,
+ NULL, importOptions, NULL, decodeOptions);
+
+ 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");
+ 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()
+{
+ 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();
+ 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();
+ if (importCRL && !inFile)
+ Usage();
+ if (showFileCRL && !inFile)
+ Usage();
+ if ((generateCRL && !nickName) ||
+ (modifyCRL && !inFile && !nickName))
+ Usage();
+ if (!(listCRL || deleteCRL || importCRL || showFileCRL || generateCRL ||
+ modifyCRL || test || erase))
+ Usage();
+
+ if (listCRL || showFileCRL) {
+ readonly = PR_TRUE;
+ }
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ if (showFileCRL) {
+ rv = NSS_NoDB_Init(NULL);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ } 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 0000000000..470449b0cb
--- /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 0000000000..cd0549c6d6
--- /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 0000000000..00a6b95dca
--- /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). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+EXTRA_LIBS += $(DIST)/lib/crmf.lib
+else
+EXTRA_LIBS += $(DIST)/lib/libcrmf.$(LIB_SUFFIX)
+endif
+
+#######################################################################
+# (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/crmfcgi.c b/security/nss/cmd/crmf-cgi/crmfcgi.c
new file mode 100644
index 0000000000..096a7fe9d5
--- /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 "keyhi.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;
+ }
+ snprintf(cgiChalVar, sizeof(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 0000000000..537b0f5a98
--- /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 0000000000..04d2d8d350
--- /dev/null
+++ b/security/nss/cmd/crmf-cgi/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 = sectools
+
+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 0000000000..715d0b7d18
--- /dev/null
+++ b/security/nss/cmd/crmftest/Makefile
@@ -0,0 +1,61 @@
+#! 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) #
+#######################################################################
+
+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)
+
+#######################################################################
+# (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). #
+#######################################################################
+
+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/crmftest.gyp b/security/nss/cmd/crmftest/crmftest.gyp
new file mode 100644
index 0000000000..c14bd195ab
--- /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 0000000000..4ac669a21b
--- /dev/null
+++ b/security/nss/cmd/crmftest/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 = ../..
+DEPTH = .
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+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 0000000000..1982b9d48a
--- /dev/null
+++ b/security/nss/cmd/crmftest/testcrmf.c
@@ -0,0 +1,1655 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 "keyhi.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 1024
+#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++) {
+ 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);
+ SECITEM_FreeItem(publicValue, PR_TRUE);
+ if (keyID == NULL) {
+ printf("Could not make the keyID from the public value\n");
+ return 909;
+ }
+ foundPrivKey = PK11_FindKeyByKeyID(privKey->pkcs11Slot, keyID, &pwdata);
+ SECITEM_FreeItem(keyID, PR_TRUE);
+ 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 0000000000..ea1d2f49ae
--- /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 0000000000..934bde0048
--- /dev/null
+++ b/security/nss/cmd/dbck/dbck.c
@@ -0,0 +1,1348 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 0000000000..318e4eb242
--- /dev/null
+++ b/security/nss/cmd/dbck/dbrecover.c
@@ -0,0 +1,669 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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) ||
+ (oldCert->keyUsage == certUsageIPsec));
+ 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 0000000000..ec8812edb0
--- /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 0000000000..a27a3ce97f
--- /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 0000000000..11713c23fb
--- /dev/null
+++ b/security/nss/cmd/dbtest/dbtest.c
@@ -0,0 +1,243 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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()
+{
+ 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();
+ 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();
+
+ 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();
+ 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 0000000000..fb58573282
--- /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 0000000000..8f9ec1f672
--- /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/dbtool/Makefile b/security/nss/cmd/dbtool/Makefile
new file mode 100644
index 0000000000..3a5b703130
--- /dev/null
+++ b/security/nss/cmd/dbtool/Makefile
@@ -0,0 +1,50 @@
+#! 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
+
+sdb.c: $(CORE_DEPTH)/lib/softoken/sdb.c
+ cp $< $@
+
+
diff --git a/security/nss/cmd/dbtool/dbtool.c b/security/nss/cmd/dbtool/dbtool.c
new file mode 100644
index 0000000000..7ae5c36516
--- /dev/null
+++ b/security/nss/cmd/dbtool/dbtool.c
@@ -0,0 +1,830 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+** dbtool.c
+**
+** tool to dump the underlying encoding of a database. This tool duplicates
+** some private functions in softoken. It uses libsec and libutil, but no
+** other portions of NSS. It currently only works on sqlite databases. For
+** an even more primitive dump, use sqlite3 on the individual files.
+**
+** TODO: dump the meta data for the databases.
+** optionally dump more PKCS5 information (KDF/salt/iterations)
+** take a password and decode encrypted attributes/verify signed
+** attributes.
+*/
+#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 "nss.h"
+#include "secasn1.h"
+#include "secder.h"
+#include "pk11table.h"
+#include "sftkdbt.h"
+#include "sdb.h"
+#include "secoid.h"
+
+#include "plgetopt.h"
+
+static char *progName;
+
+char *dbDir = NULL;
+
+static void
+Usage()
+{
+ printf("Usage: %s [-c certprefix] [-k keyprefix] "
+ "[-V certversion] [-v keyversion]\n"
+ " [-d dbdir]\n",
+ progName);
+ printf("%-20s Directory with cert database (default is .)\n",
+ "-d certdir");
+ printf("%-20s prefix for the cert database (default is \"\")\n",
+ "-c certprefix");
+ printf("%-20s prefix for the key database (default is \"\")\n",
+ "-k keyprefix");
+ printf("%-20s version of the cert database (default is 9)\n",
+ "-V certversion");
+ printf("%-20s version of the key database (default is 4)\n",
+ "-v keyversion");
+ exit(1);
+}
+#define SFTK_KEYDB_TYPE 0x40000000
+#define SFTK_TOKEN_TYPE 0x80000000
+
+/*
+ * known attributes
+ */
+static const CK_ATTRIBUTE_TYPE known_attributes[] = {
+ CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_APPLICATION,
+ CKA_VALUE, CKA_OBJECT_ID, CKA_CERTIFICATE_TYPE, CKA_ISSUER,
+ CKA_SERIAL_NUMBER, CKA_AC_ISSUER, CKA_OWNER, CKA_ATTR_TYPES, CKA_TRUSTED,
+ CKA_CERTIFICATE_CATEGORY, CKA_JAVA_MIDP_SECURITY_DOMAIN, CKA_URL,
+ CKA_HASH_OF_SUBJECT_PUBLIC_KEY, CKA_HASH_OF_ISSUER_PUBLIC_KEY,
+ CKA_CHECK_VALUE, CKA_KEY_TYPE, CKA_SUBJECT, CKA_ID, CKA_SENSITIVE,
+ CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, CKA_SIGN, CKA_SIGN_RECOVER,
+ CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_DERIVE, CKA_START_DATE, CKA_END_DATE,
+ CKA_MODULUS, CKA_MODULUS_BITS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT,
+ CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT,
+ CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_PRIME_BITS,
+ CKA_SUB_PRIME_BITS, CKA_VALUE_BITS, CKA_VALUE_LEN, CKA_EXTRACTABLE,
+ CKA_LOCAL, CKA_NEVER_EXTRACTABLE, CKA_ALWAYS_SENSITIVE,
+ CKA_KEY_GEN_MECHANISM, CKA_MODIFIABLE, CKA_EC_PARAMS,
+ CKA_EC_POINT, CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
+ CKA_ALWAYS_AUTHENTICATE, CKA_WRAP_WITH_TRUSTED, CKA_WRAP_TEMPLATE,
+ CKA_UNWRAP_TEMPLATE, CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT,
+ CKA_HAS_RESET, CKA_PIXEL_X, CKA_PIXEL_Y, CKA_RESOLUTION, CKA_CHAR_ROWS,
+ CKA_CHAR_COLUMNS, CKA_COLOR, CKA_BITS_PER_PIXEL, CKA_CHAR_SETS,
+ CKA_ENCODING_METHODS, CKA_MIME_TYPES, CKA_MECHANISM_TYPE,
+ CKA_REQUIRED_CMS_ATTRIBUTES, CKA_DEFAULT_CMS_ATTRIBUTES,
+ CKA_SUPPORTED_CMS_ATTRIBUTES, CKA_NSS_URL, CKA_NSS_EMAIL,
+ CKA_NSS_SMIME_INFO, CKA_NSS_SMIME_TIMESTAMP,
+ CKA_NSS_PKCS8_SALT, CKA_NSS_PASSWORD_CHECK, CKA_NSS_EXPIRES,
+ CKA_NSS_KRL, CKA_NSS_PQG_COUNTER, CKA_NSS_PQG_SEED,
+ CKA_NSS_PQG_H, CKA_NSS_PQG_SEED_BITS, CKA_NSS_MODULE_SPEC,
+ CKA_TRUST_DIGITAL_SIGNATURE, CKA_TRUST_NON_REPUDIATION,
+ CKA_TRUST_KEY_ENCIPHERMENT, CKA_TRUST_DATA_ENCIPHERMENT,
+ CKA_TRUST_KEY_AGREEMENT, CKA_TRUST_KEY_CERT_SIGN, CKA_TRUST_CRL_SIGN,
+ CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_CODE_SIGNING,
+ CKA_TRUST_EMAIL_PROTECTION, CKA_TRUST_IPSEC_END_SYSTEM,
+ CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, CKA_TRUST_TIME_STAMPING,
+ CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH,
+ CKA_NSS_DB, CKA_NSS_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS,
+ CKA_PUBLIC_KEY_INFO
+};
+
+static unsigned int known_attributes_size = sizeof(known_attributes) /
+ sizeof(known_attributes[0]);
+
+PRBool
+isULONGAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ switch (type) {
+ case CKA_CERTIFICATE_CATEGORY:
+ case CKA_CERTIFICATE_TYPE:
+ case CKA_CLASS:
+ case CKA_JAVA_MIDP_SECURITY_DOMAIN:
+ case CKA_KEY_GEN_MECHANISM:
+ case CKA_KEY_TYPE:
+ case CKA_MECHANISM_TYPE:
+ case CKA_MODULUS_BITS:
+ case CKA_PRIME_BITS:
+ case CKA_SUBPRIME_BITS:
+ case CKA_VALUE_BITS:
+ case CKA_VALUE_LEN:
+
+ case CKA_TRUST_DIGITAL_SIGNATURE:
+ case CKA_TRUST_NON_REPUDIATION:
+ case CKA_TRUST_KEY_ENCIPHERMENT:
+ case CKA_TRUST_DATA_ENCIPHERMENT:
+ case CKA_TRUST_KEY_AGREEMENT:
+ case CKA_TRUST_KEY_CERT_SIGN:
+ case CKA_TRUST_CRL_SIGN:
+
+ case CKA_TRUST_SERVER_AUTH:
+ case CKA_TRUST_CLIENT_AUTH:
+ case CKA_TRUST_CODE_SIGNING:
+ case CKA_TRUST_EMAIL_PROTECTION:
+ case CKA_TRUST_IPSEC_END_SYSTEM:
+ case CKA_TRUST_IPSEC_TUNNEL:
+ case CKA_TRUST_IPSEC_USER:
+ case CKA_TRUST_TIME_STAMPING:
+ case CKA_TRUST_STEP_UP_APPROVED:
+ return PR_TRUE;
+ default:
+ break;
+ }
+ return PR_FALSE;
+}
+
+/* are the attributes private? */
+static PRBool
+isPrivateAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ switch (type) {
+ case CKA_VALUE:
+ case CKA_PRIVATE_EXPONENT:
+ case CKA_PRIME_1:
+ case CKA_PRIME_2:
+ case CKA_EXPONENT_1:
+ case CKA_EXPONENT_2:
+ case CKA_COEFFICIENT:
+ return PR_TRUE;
+ default:
+ break;
+ }
+ return PR_FALSE;
+}
+
+/* These attributes must be authenticated with an hmac. */
+static PRBool
+isAuthenticatedAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ switch (type) {
+ case CKA_MODULUS:
+ case CKA_PUBLIC_EXPONENT:
+ case CKA_CERT_SHA1_HASH:
+ case CKA_CERT_MD5_HASH:
+ case CKA_TRUST_SERVER_AUTH:
+ case CKA_TRUST_CLIENT_AUTH:
+ case CKA_TRUST_EMAIL_PROTECTION:
+ case CKA_TRUST_CODE_SIGNING:
+ case CKA_TRUST_STEP_UP_APPROVED:
+ case CKA_NSS_OVERRIDE_EXTENSIONS:
+ return PR_TRUE;
+ default:
+ break;
+ }
+ return PR_FALSE;
+}
+
+/*
+ * convert a database ulong back to a native ULONG. (reverse of the above
+ * function.
+ */
+static CK_ULONG
+sdbULong2ULong(unsigned char *data)
+{
+ int i;
+ CK_ULONG value = 0;
+
+ for (i = 0; i < SDB_ULONG_SIZE; i++) {
+ value |= (((CK_ULONG)data[i]) << (SDB_ULONG_SIZE - 1 - i) * PR_BITS_PER_BYTE);
+ }
+ return value;
+}
+
+/* PBE defines and functions */
+SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
+
+typedef struct EncryptedDataInfoStr {
+ SECAlgorithmID algorithm;
+ SECItem encryptedData;
+} EncryptedDataInfo;
+
+static const SEC_ASN1Template encryptedDataInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(EncryptedDataInfo) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
+ offsetof(EncryptedDataInfo, algorithm),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(EncryptedDataInfo, encryptedData) },
+ { 0 }
+};
+
+typedef struct PBEParameterStr {
+ SECAlgorithmID prfAlg;
+ SECItem salt;
+ SECItem iteration;
+ SECItem keyLength;
+} PBEParameter;
+
+static const SEC_ASN1Template pkcs5V1PBEParameterTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(PBEParameter) },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(PBEParameter, salt) },
+ { SEC_ASN1_INTEGER,
+ offsetof(PBEParameter, iteration) },
+ { 0 }
+};
+
+static const SEC_ASN1Template pkcs12V2PBEParameterTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PBEParameter) },
+ { SEC_ASN1_OCTET_STRING, offsetof(PBEParameter, salt) },
+ { SEC_ASN1_INTEGER, offsetof(PBEParameter, iteration) },
+ { 0 }
+};
+
+static const SEC_ASN1Template pkcs5V2PBEParameterTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PBEParameter) },
+ /* this is really a choice, but since we don't understand any other
+ * choice, just inline it. */
+ { SEC_ASN1_OCTET_STRING, offsetof(PBEParameter, salt) },
+ { SEC_ASN1_INTEGER, offsetof(PBEParameter, iteration) },
+ { SEC_ASN1_INTEGER, offsetof(PBEParameter, keyLength) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
+ offsetof(PBEParameter, prfAlg),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { 0 }
+};
+
+typedef struct Pkcs5v2PBEParameterStr {
+ SECAlgorithmID keyParams; /* parameters of the key generation */
+ SECAlgorithmID algParams; /* parameters for the encryption or mac op */
+} Pkcs5v2PBEParameter;
+
+static const SEC_ASN1Template pkcs5v2PBES2ParameterTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(Pkcs5v2PBEParameter) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
+ offsetof(Pkcs5v2PBEParameter, keyParams),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
+ offsetof(Pkcs5v2PBEParameter, algParams),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { 0 }
+};
+
+static inline PRBool
+isPKCS12PBE(SECOidTag alg)
+{
+ switch (alg) {
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
+ return PR_TRUE;
+ default:
+ break;
+ }
+ return PR_FALSE;
+}
+
+/* helper functions */
+
+/* output an NSS specific attribute or name that wasn't found in our
+ * pkcs #11 table */
+const char *
+makeNSSVendorName(CK_ATTRIBUTE_TYPE attribute, const char *nameType)
+{
+ static char nss_name[256];
+ const char *name = NULL;
+ if ((attribute >= CKA_NSS) && (attribute < 0xffffffffUL)) {
+ sprintf(nss_name, "%s+%d", nameType, (int)(attribute - CKA_NSS));
+ name = nss_name;
+ }
+ return name;
+}
+
+/* turn and attribute into a name */
+const char *
+AttributeName(CK_ATTRIBUTE_TYPE attribute)
+{
+ const char *name = getNameFromAttribute(attribute);
+ if (!name) {
+ name = makeNSSVendorName(attribute, "CKA_NSS");
+ }
+
+ return name ? name : "UNKNOWN_ATTRIBUTE_TYPE";
+}
+
+/* turn and error code into a name */
+const char *
+ErrorName(CK_RV crv)
+{
+ const char *error = getName(crv, ConstResult);
+ if (!error) {
+ error = makeNSSVendorName(crv, "CKR_NSS");
+ }
+ return error ? error : "UNKNOWN_ERROR";
+}
+
+/* turn an oud tag into a string */
+const char *
+oid2string(SECOidTag alg)
+{
+ const char *oidstring = SECOID_FindOIDTagDescription(alg);
+ const char *def = "Invalid oid tag"; /* future build a dotted oid string value here */
+ return oidstring ? oidstring : def;
+}
+
+/* dump an arbitary data blob. Dump it has hex with ascii on the side */
+#define ASCCHAR(val) ((val) >= ' ' && (val) <= 0x7e ? (val) : '.')
+#define LINE_LENGTH 16
+void
+dumpValue(const unsigned char *v, int len)
+{
+ int i, next = 0;
+ char string[LINE_LENGTH + 1];
+ char space[LINE_LENGTH * 2 + 1];
+ char *nl = "";
+ char *sp = "";
+ PORT_Memset(string, 0, sizeof(string));
+
+ for (i = 0; i < len; i++) {
+ if ((i % LINE_LENGTH) == 0) {
+ printf("%s%s%s ", sp, string, nl);
+ PORT_Memset(string, 0, sizeof(string));
+ next = 0;
+ nl = "\n";
+ sp = " ";
+ }
+ printf("%02x", v[i]);
+ string[next++] = ASCCHAR(v[i]);
+ }
+ PORT_Memset(space, 0, sizeof(space));
+ i = LINE_LENGTH - (len % LINE_LENGTH);
+ if (i != LINE_LENGTH) {
+ int j;
+ for (j = 0; j < i; j++) {
+ space[j * 2] = ' ';
+ space[j * 2 + 1] = ' ';
+ }
+ }
+ printf("%s%s%s%s", space, sp, string, nl);
+}
+
+/* dump a PKCS5/12 PBE blob */
+void
+dumpPKCS(unsigned char *val, CK_ULONG len, PRBool *hasSig)
+{
+ EncryptedDataInfo edi;
+ SECStatus rv;
+ SECItem data;
+ PLArenaPool *arena;
+ SECOidTag alg, prfAlg;
+ PBEParameter pbeParam;
+ unsigned char zero = 0;
+ const SEC_ASN1Template *template = pkcs5V1PBEParameterTemplate;
+ int iter, keyLen, i;
+
+ if (hasSig) {
+ *hasSig = PR_FALSE;
+ }
+
+ data.data = val;
+ data.len = len;
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ printf("Couldn't allocate arena\n");
+ return;
+ }
+
+ /* initialize default values */
+ PORT_Memset(&pbeParam, 0, sizeof(pbeParam));
+ pbeParam.keyLength.data = &zero;
+ pbeParam.keyLength.len = sizeof(zero);
+ SECOID_SetAlgorithmID(arena, &pbeParam.prfAlg, SEC_OID_SHA1, NULL);
+
+ /* first crack the encrypted data from the PBE algorithm ID */
+ rv = SEC_QuickDERDecodeItem(arena, &edi, encryptedDataInfoTemplate, &data);
+ if (rv != SECSuccess) {
+ printf("Encrypted Data, failed to decode\n");
+ dumpValue(val, len);
+ PORT_FreeArena(arena, PR_FALSE);
+ return;
+ }
+ /* now use the pbe secalg to dump info on the pbe */
+ alg = SECOID_GetAlgorithmTag(&edi.algorithm);
+ if ((alg == SEC_OID_PKCS5_PBES2) || (alg == SEC_OID_PKCS5_PBMAC1)) {
+ Pkcs5v2PBEParameter param;
+ SECOidTag palg;
+ const char *typeName = (alg == SEC_OID_PKCS5_PBES2) ? "Encrypted Data PBES2" : "Mac Data PBMAC1";
+
+ rv = SEC_QuickDERDecodeItem(arena, &param,
+ pkcs5v2PBES2ParameterTemplate,
+ &edi.algorithm.parameters);
+ if (rv != SECSuccess) {
+ printf("%s, failed to decode\n", typeName);
+ dumpValue(val, len);
+ PORT_FreeArena(arena, PR_FALSE);
+ return;
+ }
+ palg = SECOID_GetAlgorithmTag(&param.algParams);
+ printf("%s alg=%s ", typeName, oid2string(palg));
+ if (hasSig && palg == SEC_OID_AES_256_CBC) {
+ *hasSig = PR_TRUE;
+ }
+ template = pkcs5V2PBEParameterTemplate;
+ edi.algorithm.parameters = param.keyParams.parameters;
+ } else {
+ printf("Encrypted Data alg=%s ", oid2string(alg));
+ if (alg == SEC_OID_PKCS5_PBKDF2) {
+ template = pkcs5V2PBEParameterTemplate;
+ } else if (isPKCS12PBE(alg)) {
+ template = pkcs12V2PBEParameterTemplate;
+ } else {
+ template = pkcs5V1PBEParameterTemplate;
+ }
+ }
+ rv = SEC_QuickDERDecodeItem(arena, &pbeParam,
+ template,
+ &edi.algorithm.parameters);
+ if (rv != SECSuccess) {
+ printf("( failed to decode params)\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ return;
+ }
+ /* dump the pbe parmeters */
+ iter = DER_GetInteger(&pbeParam.iteration);
+ keyLen = DER_GetInteger(&pbeParam.keyLength);
+ prfAlg = SECOID_GetAlgorithmTag(&pbeParam.prfAlg);
+ printf("(prf=%s iter=%d keyLen=%d salt=0x",
+ oid2string(prfAlg), iter, keyLen);
+ for (i = 0; i < pbeParam.salt.len; i++)
+ printf("%02x", pbeParam.salt.data[i]);
+ printf(")\n");
+ /* finally dump the raw encrypted data */
+ dumpValue(edi.encryptedData.data, edi.encryptedData.len);
+ PORT_FreeArena(arena, PR_FALSE);
+}
+
+/* dump a long attribute, convert to an unsigned long. PKCS #11 Longs are
+ * limited to 32 bits by the spec, even if the CK_ULONG is longer */
+void
+dumpLongAttribute(CK_ATTRIBUTE_TYPE type, CK_ULONG value)
+{
+ const char *nameType = "CK_NSS";
+ ConstType constType = ConstNone;
+ const char *valueName = NULL;
+
+ switch (type) {
+ case CKA_CLASS:
+ nameType = "CKO_NSS";
+ constType = ConstObject;
+ break;
+ case CKA_CERTIFICATE_TYPE:
+ nameType = "CKC_NSS";
+ constType = ConstCertType;
+ break;
+ case CKA_KEY_TYPE:
+ nameType = "CKK_NSS";
+ constType = ConstKeyType;
+ break;
+ case CKA_MECHANISM_TYPE:
+ nameType = "CKM_NSS";
+ constType = ConstMechanism;
+ break;
+ case CKA_TRUST_SERVER_AUTH:
+ case CKA_TRUST_CLIENT_AUTH:
+ case CKA_TRUST_CODE_SIGNING:
+ case CKA_TRUST_EMAIL_PROTECTION:
+ case CKA_TRUST_IPSEC_END_SYSTEM:
+ case CKA_TRUST_IPSEC_TUNNEL:
+ case CKA_TRUST_IPSEC_USER:
+ case CKA_TRUST_TIME_STAMPING:
+ nameType = "CKT_NSS";
+ constType = ConstTrust;
+ break;
+ default:
+ break;
+ }
+ /* if value has a symbolic name, use it */
+ if (constType != ConstNone) {
+ valueName = getName(value, constType);
+ }
+ if (!valueName) {
+ valueName = makeNSSVendorName(value, nameType);
+ }
+ if (!valueName) {
+ printf("%d (0x%08x)\n", (int)value, (int)value);
+ } else {
+ printf("%s (0x%08x)\n", valueName, (int)value);
+ }
+}
+
+/* dump a signature for an object */
+static const char META_SIG_TEMPLATE[] = "sig_%s_%08x_%08x";
+void
+dumpSignature(CK_ATTRIBUTE_TYPE attribute, SDB *keydb, PRBool isKey,
+ CK_OBJECT_HANDLE objectID, PRBool force)
+{
+ char id[30];
+ CK_RV crv;
+ SECItem signText;
+ unsigned char signData[SDB_MAX_META_DATA_LEN];
+
+ if (!force && !isAuthenticatedAttribute(attribute)) {
+ return;
+ }
+ sprintf(id, META_SIG_TEMPLATE,
+ isKey ? "key" : "cert",
+ (unsigned int)objectID, (unsigned int)attribute);
+ printf(" Signature %s:", id);
+ signText.data = signData;
+ signText.len = sizeof(signData);
+
+ crv = (*keydb->sdb_GetMetaData)(keydb, id, &signText, NULL);
+ if ((crv != CKR_OK) && isKey) {
+ sprintf(id, META_SIG_TEMPLATE,
+ isKey ? "key" : "cert", (unsigned int)(objectID | SFTK_KEYDB_TYPE | SFTK_TOKEN_TYPE),
+ (unsigned int)attribute);
+ crv = (*keydb->sdb_GetMetaData)(keydb, id, &signText, NULL);
+ }
+ if (crv != CKR_OK) {
+ printf(" FAILED %s with %s (0x%08x)\n", id, ErrorName(crv), (int)crv);
+ return;
+ }
+ dumpPKCS(signText.data, signText.len, NULL);
+ return;
+}
+
+/* dump an attribute. use the helper functions above */
+void
+dumpAttribute(CK_ATTRIBUTE *template, SDB *keydb, PRBool isKey,
+ CK_OBJECT_HANDLE id)
+{
+ CK_ATTRIBUTE_TYPE attribute = template->type;
+ printf(" %s(0x%08x): ", AttributeName(attribute), (int)attribute);
+ if (template->pValue == NULL) {
+ printf("NULL (%d)\n", (int)template->ulValueLen);
+ return;
+ }
+ if (template->ulValueLen == SDB_ULONG_SIZE && isULONGAttribute(attribute)) {
+ CK_ULONG value = sdbULong2ULong(template->pValue);
+ dumpLongAttribute(attribute, value);
+ return;
+ }
+ if (template->ulValueLen == 1) {
+ unsigned char val = *(unsigned char *)template->pValue;
+ switch (val) {
+ case 0:
+ printf("CK_FALSE\n");
+ break;
+ case 1:
+ printf("CK_TRUE\n");
+ break;
+ default:
+ printf("%d 0x%02x %c\n", val, val, ASCCHAR(val));
+ break;
+ }
+ return;
+ }
+ if (isKey && isPrivateAttribute(attribute)) {
+ PRBool hasSig = PR_FALSE;
+ dumpPKCS(template->pValue, template->ulValueLen, &hasSig);
+ if (hasSig) {
+ dumpSignature(attribute, keydb, isKey, id, PR_TRUE);
+ }
+ return;
+ }
+ if (template->ulValueLen == 0) {
+ printf("empty");
+ }
+ printf("\n");
+ dumpValue(template->pValue, template->ulValueLen);
+}
+
+/* dump all the attributes in an object */
+void
+dumpObject(CK_OBJECT_HANDLE id, SDB *db, SDB *keydb, PRBool isKey)
+{
+ CK_RV crv;
+ int i;
+ CK_ATTRIBUTE template;
+ char buffer[2048];
+ char *alloc = NULL;
+
+ printf(" Object 0x%08x:\n", (int)id);
+ for (i = 0; i < known_attributes_size; i++) {
+ CK_ATTRIBUTE_TYPE attribute = known_attributes[i];
+ template.type = attribute;
+ template.pValue = NULL;
+ template.ulValueLen = 0;
+ crv = (*db->sdb_GetAttributeValue)(db, id, &template, 1);
+
+ if (crv != CKR_OK) {
+ if (crv != CKR_ATTRIBUTE_TYPE_INVALID) {
+ PR_fprintf(PR_STDERR, " "
+ "Get Attribute %s (0x%08x):FAILED\"%s\"(0x%08x)\n",
+ AttributeName(attribute), (int)attribute,
+ ErrorName(crv), (int)crv);
+ }
+ continue;
+ }
+
+ if (template.ulValueLen < sizeof(buffer)) {
+ template.pValue = buffer;
+ } else {
+ alloc = PORT_Alloc(template.ulValueLen);
+ template.pValue = alloc;
+ }
+ if (template.pValue == NULL) {
+ PR_fprintf(PR_STDERR, " "
+ "Could allocate %d bytes for Attribute %s (0x%08x)\n",
+ (int)template.ulValueLen,
+ AttributeName(attribute), (int)attribute);
+ continue;
+ }
+ crv = (*db->sdb_GetAttributeValue)(db, id, &template, 1);
+
+ if (crv != CKR_OK) {
+ if (crv != CKR_ATTRIBUTE_TYPE_INVALID) {
+ PR_fprintf(PR_STDERR, " "
+ "Get Attribute %s (0x%08x):FAILED\"%s\"(0x%08x)\n",
+ AttributeName(attribute), (int)attribute,
+ ErrorName(crv), (int)crv);
+ }
+ if (alloc) {
+ PORT_Free(alloc);
+ alloc = NULL;
+ }
+ continue;
+ }
+
+ dumpAttribute(&template, keydb, isKey, id);
+ dumpSignature(template.type, keydb, isKey, id, PR_FALSE);
+ if (alloc) {
+ PORT_Free(alloc);
+ alloc = NULL;
+ }
+ }
+}
+
+/* dump all the objects in a database */
+void
+dumpDB(SDB *db, const char *name, SDB *keydb, PRBool isKey)
+{
+ SDBFind *findHandle = NULL;
+ CK_BBOOL isTrue = 1;
+ CK_ATTRIBUTE allObjectTemplate = { CKA_TOKEN, NULL, 1 };
+ CK_ULONG allObjectTemplateCount = 1;
+ PRBool recordFound = PR_FALSE;
+ CK_RV crv = CKR_OK;
+ CK_ULONG objectCount = 0;
+ printf("%s:\n", name);
+
+ allObjectTemplate.pValue = &isTrue;
+ crv = (*db->sdb_FindObjectsInit)(db, &allObjectTemplate,
+ allObjectTemplateCount, &findHandle);
+ do {
+ CK_OBJECT_HANDLE id;
+ recordFound = PR_FALSE;
+ crv = (*db->sdb_FindObjects)(db, findHandle, &id, 1, &objectCount);
+ if ((crv == CKR_OK) && (objectCount == 1)) {
+ recordFound = PR_TRUE;
+ dumpObject(id, db, keydb, isKey);
+ }
+ } while (recordFound);
+ if (crv != CKR_OK) {
+ PR_fprintf(PR_STDERR,
+ "Last record return PKCS #11 error = %s (0x%08x)\n",
+ ErrorName(crv), (int)crv);
+ }
+ (*db->sdb_FindObjectsFinal)(db, findHandle);
+}
+
+static 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;
+}
+
+int
+main(int argc, char **argv)
+{
+ PLOptState *optstate;
+ PLOptStatus optstatus;
+ char *certPrefix = "", *keyPrefix = "";
+ int cert_version = 9;
+ int key_version = 4;
+ SDB *certdb = NULL;
+ SDB *keydb = NULL;
+ PRBool isNew = PR_FALSE;
+
+ CK_RV crv;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName + 1 : argv[0];
+
+ optstate = PL_CreateOptState(argc, argv, "d:c:k:v:V:h");
+
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'h':
+ default:
+ Usage();
+ break;
+
+ case 'd':
+ dbDir = PORT_Strdup(optstate->value);
+ break;
+
+ case 'c':
+ certPrefix = PORT_Strdup(optstate->value);
+ break;
+
+ case 'k':
+ keyPrefix = PORT_Strdup(optstate->value);
+ break;
+
+ case 'v':
+ key_version = atoi(optstate->value);
+ break;
+
+ case 'V':
+ cert_version = atoi(optstate->value);
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+ if (optstatus == PL_OPT_BAD)
+ Usage();
+
+ if (dbDir) {
+ char *tmp = dbDir;
+ dbDir = secu_ConfigDirectory(tmp);
+ PORT_Free(tmp);
+ } else {
+ dbDir = secu_ConfigDirectory(NULL);
+ }
+ PR_fprintf(PR_STDERR, "dbdir selected is %s\n\n", dbDir);
+
+ if (dbDir[0] == '\0') {
+ PR_fprintf(PR_STDERR,
+ "ERROR: Directory \"%s\" does not exist.\n", dbDir);
+ return 1;
+ }
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ SECOID_Init();
+
+ crv = s_open(dbDir, certPrefix, keyPrefix, cert_version, key_version,
+ SDB_RDONLY, &certdb, &keydb, &isNew);
+ if (crv != CKR_OK) {
+ PR_fprintf(PR_STDERR,
+ "Couldn't open databased in %s, error=%s (0x%08x)\n",
+ dbDir, ErrorName(crv), (int)crv);
+ return 1;
+ }
+
+ /* now dump the objects in the cert database */
+ dumpDB(certdb, "CertDB", keydb, PR_FALSE);
+ dumpDB(keydb, "KeyDB", keydb, PR_TRUE);
+ return 0;
+}
diff --git a/security/nss/cmd/dbtool/dbtool.gyp b/security/nss/cmd/dbtool/dbtool.gyp
new file mode 100644
index 0000000000..4c1081f810
--- /dev/null
+++ b/security/nss/cmd/dbtool/dbtool.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': 'dbtool',
+ 'type': 'executable',
+ 'sources': [
+ 'dbtool.c',
+ '../../lib/softoken/sdb.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ],
+ 'conditions': [
+ [ 'use_system_sqlite==1', {
+ 'dependencies': [
+ '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3',
+ ],
+ }, {
+ 'dependencies': [
+ '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite',
+ ],
+ }],
+ ] }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/cmd/dbtool/manifest.mn b/security/nss/cmd/dbtool/manifest.mn
new file mode 100644
index 0000000000..fa93eaacb9
--- /dev/null
+++ b/security/nss/cmd/dbtool/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
+
+USE_STATIC_LIBS = 1
+
+# DIRS =
+
+CSRCS = dbtool.c sdb.c
+
+# sdb.c is copied for softoken, clean it up on make clean
+GARBAGE = sdb.c
+
+PROGRAM = dbtool
+
diff --git a/security/nss/cmd/derdump/Makefile b/security/nss/cmd/derdump/Makefile
new file mode 100644
index 0000000000..c2039d82b6
--- /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 0000000000..d687a8b7ad
--- /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 0000000000..5637685da9
--- /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 0000000000..0b550377c5
--- /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 0000000000..c2039d82b6
--- /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 0000000000..87e6dcb891
--- /dev/null
+++ b/security/nss/cmd/digest/digest.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/. */
+
+#include "secutil.h"
+#include "pk11func.h"
+#include "sechash.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 *
+HashNameToOID(const char *hashName)
+{
+ HASH_HashType htype;
+ SECOidData *hashOID;
+
+ for (htype = HASH_AlgNULL + 1; htype < HASH_AlgTOTAL; htype++) {
+ hashOID = SECOID_FindOIDByTag(HASH_GetHashOidTagByHashType(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++) {
+ fputs(SECOID_FindOIDByTag(HASH_GetHashOidTagByHashType(htype))->desc,
+ stderr);
+ 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[HASH_LENGTH_MAX];
+ 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, HASH_LENGTH_MAX);
+ 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);
+ free(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 0000000000..c2e00289f4
--- /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 0000000000..3e764063a7
--- /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 0000000000..7b74b369c7
--- /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 0000000000..a07004d8ec
--- /dev/null
+++ b/security/nss/cmd/ecperf/ecperf.c
@@ -0,0 +1,637 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 <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"
+
+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;
+
+typedef SECItem SECKEYECParams;
+
+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;
+ void *tmp = NULL;
+
+ 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);
+ tmp = threadData->p2;
+ threadData->p2 = (void *)&sig;
+ }
+
+ while (iters--) {
+ threadData->status = (*op)(session, threadData->p1,
+ threadData->p2, threadData->p3);
+ if (threadData->status != SECSuccess) {
+ break;
+ }
+ threadData->count++;
+ }
+
+ if (threadData->isSign) {
+ threadData->p2 = tmp;
+ }
+ return;
+}
+
+void
+genericThread(void *data)
+{
+ ThreadData *threadData = (ThreadData *)data;
+ int iters = threadData->iters;
+ unsigned char sigData[256];
+ SECItem sig;
+ void *tmp = NULL;
+
+ threadData->status = SECSuccess;
+ threadData->count = 0;
+
+ if (threadData->isSign) {
+ sig.data = sigData;
+ sig.len = sizeof(sigData);
+ tmp = threadData->p2;
+ threadData->p2 = (void *)&sig;
+ }
+
+ while (iters--) {
+ threadData->status = (*threadData->op)(threadData->p1,
+ threadData->p2, threadData->p3);
+ if (threadData->status != SECSuccess) {
+ break;
+ }
+ threadData->count++;
+ }
+
+ if (threadData->isSign) {
+ threadData->p2 = tmp;
+ }
+ 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;
+}
+
+/* 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 = SECU_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;
+ SECStatus rv = SECFailure;
+ PLArenaPool *arena;
+ SECItem ecEncodedParams = { siBuffer, NULL, 0 };
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ return SECFailure;
+ }
+
+ if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return SECFailure;
+ }
+
+ rv = SECU_ecName2params(curve, &ecEncodedParams);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ EC_FillParams(arena, &ecEncodedParams, &ecParams);
+
+ 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) {
+ goto cleanup;
+ }
+ 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:
+ SECITEM_FreeItem(&ecEncodedParams, PR_FALSE);
+ PORT_FreeArena(arena, PR_FALSE);
+ if (ecPriv) {
+ 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 0000000000..c6e99448dc
--- /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 100644
index 0000000000..96cdc5ac8c
--- /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 0000000000..d20daa4b78
--- /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 0000000000..1c8f4c0392
--- /dev/null
+++ b/security/nss/cmd/fbectest/fbectest.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/. */
+
+#include "blapi.h"
+#include "ec.h"
+#include "ecl-curve.h"
+#include "prprf.h"
+#include "basicutil.h"
+#include "secder.h"
+#include "secitem.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 };
+ SECItem ecEncodedParams = { siBuffer, NULL, 0 };
+ int i;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ return SECFailure;
+ }
+
+ rv = SECU_ecName2params(curve, &ecEncodedParams);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ EC_FillParams(arena, &ecEncodedParams, &ecParams);
+
+ 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:
+ SECITEM_FreeItem(&ecEncodedParams, PR_FALSE);
+ 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 0000000000..07357bc4fb
--- /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 0000000000..85d6aa5732
--- /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 0000000000..e66a2bfb82
--- /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 100644
index 0000000000..2cf5c0563f
--- /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/README b/security/nss/cmd/fipstest/README
new file mode 100644
index 0000000000..8f076587dc
--- /dev/null
+++ b/security/nss/cmd/fipstest/README
@@ -0,0 +1 @@
+The scripts have been moved to tests/fips/cavs_scripts
diff --git a/security/nss/cmd/fipstest/fipstest.c b/security/nss/cmd/fipstest/fipstest.c
new file mode 100644
index 0000000000..48ca78b54a
--- /dev/null
+++ b/security/nss/cmd/fipstest/fipstest.c
@@ -0,0 +1,8923 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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
+#define MATCH_OPENSSL 1
+/*#define MATCH_NIST 1 */
+#ifdef MATCH_NIST
+#define VERBOSE_REASON 1
+#endif
+
+extern SECStatus
+EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
+extern SECStatus
+EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
+ const ECParams *srcParams);
+
+#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 */
+ snprintf(buf, sizeof(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_NSS_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++) {
+ snprintf(buf, sizeof(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++) {
+ snprintf(buf, sizeof(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++) {
+ snprintf(buf, sizeof(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++) {
+ snprintf(buf, sizeof(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;
+}
+
+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;
+}
+
+HASH_HashType
+hash_string_to_hashType(const char *src)
+{
+ HASH_HashType shaAlg = HASH_AlgNULL;
+ 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 if (strncmp(src, "SHA1", 4) == 0) {
+ shaAlg = HASH_AlgSHA1;
+ } else if (strncmp(src, "SHA224", 6) == 0) {
+ shaAlg = HASH_AlgSHA224;
+ } else if (strncmp(src, "SHA256", 6) == 0) {
+ shaAlg = HASH_AlgSHA256;
+ } else if (strncmp(src, "SHA384", 6) == 0) {
+ shaAlg = HASH_AlgSHA384;
+ } else if (strncmp(src, "SHA512", 6) == 0) {
+ shaAlg = HASH_AlgSHA512;
+ }
+ return shaAlg;
+}
+
+/*
+ * 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 */
+ shaAlg = hash_string_to_hashType(src);
+ if (shaAlg == HASH_AlgNULL) {
+ 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 */
+ shaAlg = hash_string_to_hashType(src);
+ if (shaAlg == HASH_AlgNULL) {
+ 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);
+}
+
+/*
+ * Perform the ECDH Functional Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+#define MAX_ECC_PARAMS 256
+void
+ecdh_functional(char *reqfn, PRBool response)
+{
+ 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 *ecdhreq; /* input stream from the REQUEST file */
+ FILE *ecdhresp; /* output stream to the RESPONSE file */
+ char curve[16]; /* "nistxddd" */
+ unsigned char hashBuf[HASH_LENGTH_MAX];
+ ECParams *ecparams[MAX_ECC_PARAMS] = { NULL };
+ ECPrivateKey *ecpriv = NULL;
+ ECParams *current_ecparams = NULL;
+ SECItem pubkey;
+ SECItem ZZ;
+ unsigned int i;
+ unsigned int len = 0;
+ unsigned int uit_len = 0;
+ int current_curve = -1;
+ HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
+
+ ecdhreq = fopen(reqfn, "r");
+ ecdhresp = stdout;
+ strcpy(curve, "nist");
+ pubkey.data = NULL;
+ while (fgets(buf, sizeof buf, ecdhreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
+ fputs(buf, ecdhresp);
+ continue;
+ }
+ if (buf[0] == '[') {
+ /* [Ex] */
+ if (buf[1] == 'E' && buf[3] == ']') {
+ current_curve = buf[2] - 'A';
+ fputs(buf, ecdhresp);
+ continue;
+ }
+ /* [Curve selected: x-nnn */
+ if (strncmp(buf, "[Curve ", 7) == 0) {
+ const char *src;
+ char *dst;
+ SECItem *encodedparams;
+
+ if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) {
+ fprintf(stderr, "No curve type defined\n");
+ goto loser;
+ }
+
+ src = &buf[1];
+ /* skip passed the colon */
+ while (*src && *src != ':')
+ src++;
+ if (*src != ':') {
+ fprintf(stderr,
+ "No colon in curve selected statement\n%s", buf);
+ goto loser;
+ }
+ src++;
+ /* skip to the first non-space */
+ while (*src && *src == ' ')
+ src++;
+ dst = &curve[4];
+ *dst++ = tolower(*src);
+ src += 2; /* skip the hyphen */
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst = '\0';
+ if (ecparams[current_curve] != NULL) {
+ PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE);
+ ecparams[current_curve] = NULL;
+ }
+ encodedparams = getECParams(curve);
+ if (encodedparams == NULL) {
+ fprintf(stderr, "Unknown curve %s.", curve);
+ goto loser;
+ }
+ if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) != SECSuccess) {
+ fprintf(stderr, "Curve %s not supported.\n", curve);
+ goto loser;
+ }
+ SECITEM_FreeItem(encodedparams, PR_TRUE);
+ fputs(buf, ecdhresp);
+ continue;
+ }
+ /* [Ex - SHAxxx] */
+ if (buf[1] == 'E' && buf[3] == ' ') {
+ const char *src;
+ current_curve = buf[2] - 'A';
+ if ((current_curve < 0) || (current_curve > 256)) {
+ fprintf(stderr, "bad curve type defined (%c)\n", buf[2]);
+ goto loser;
+ }
+ current_ecparams = ecparams[current_curve];
+ if (current_ecparams == NULL) {
+ fprintf(stderr, "no curve defined for type %c defined\n",
+ buf[2]);
+ goto loser;
+ }
+ /* skip passed the colon */
+ src = &buf[1];
+ while (*src && *src != '-')
+ src++;
+ if (*src != '-') {
+ fprintf(stderr,
+ "No data in curve selected statement\n%s", buf);
+ goto loser;
+ }
+ src++;
+ /* skip to the first non-space */
+ while (*src && *src == ' ')
+ src++;
+ hash = hash_string_to_hashType(src);
+ if (hash == HASH_AlgNULL) {
+ fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type");
+ goto loser;
+ }
+ fputs(buf, ecdhresp);
+ continue;
+ }
+ fputs(buf, ecdhresp);
+ continue;
+ }
+ /* COUNT = ... */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ fputs(buf, ecdhresp);
+ if (current_ecparams == NULL) {
+ fprintf(stderr, "no curve defined for type %c defined\n",
+ buf[2]);
+ goto loser;
+ }
+ len = (current_ecparams->fieldID.size + 7) >> 3;
+ if (pubkey.data != NULL) {
+ PORT_Free(pubkey.data);
+ pubkey.data = NULL;
+ }
+ SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams));
+ if (pubkey.data == NULL) {
+ goto loser;
+ }
+ pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
+ continue;
+ }
+ /* QeCAVSx = ... */
+ if (strncmp(buf, "QeCAVSx", 7) == 0) {
+ fputs(buf, ecdhresp);
+ i = 7;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ from_hex_str(&pubkey.data[1], len, &buf[i]);
+ continue;
+ }
+ /* QeCAVSy = ... */
+ if (strncmp(buf, "QeCAVSy", 7) == 0) {
+ fputs(buf, ecdhresp);
+ i = 7;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
+ if (current_ecparams == NULL) {
+ fprintf(stderr, "no curve defined\n");
+ goto loser;
+ }
+ /* validate CAVS public key */
+ if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) {
+ fprintf(stderr, "BAD key detected\n");
+ goto loser;
+ }
+
+ /* generate ECC key pair */
+ if (EC_NewKey(current_ecparams, &ecpriv) != SECSuccess) {
+ fprintf(stderr, "Failed to generate new key\n");
+ goto loser;
+ }
+ /* validate UIT generated public key */
+ if (EC_ValidatePublicKey(current_ecparams, &ecpriv->publicValue) !=
+ SECSuccess) {
+ fprintf(stderr, "generate key did not validate\n");
+ goto loser;
+ }
+ /* output UIT public key */
+ uit_len = ecpriv->publicValue.len;
+ if (uit_len % 2 == 0) {
+ fprintf(stderr, "generate key had invalid public value len\n");
+ goto loser;
+ }
+ uit_len = (uit_len - 1) / 2;
+ if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
+ fprintf(stderr, "generate key was compressed\n");
+ goto loser;
+ }
+ fputs("deIUT = ", ecdhresp);
+ to_hex_str(buf, ecpriv->privateValue.data, ecpriv->privateValue.len);
+ fputs(buf, ecdhresp);
+ fputc('\n', ecdhresp);
+ fputs("QeIUTx = ", ecdhresp);
+ to_hex_str(buf, &ecpriv->publicValue.data[1], uit_len);
+ fputs(buf, ecdhresp);
+ fputc('\n', ecdhresp);
+ fputs("QeIUTy = ", ecdhresp);
+ to_hex_str(buf, &ecpriv->publicValue.data[1 + uit_len], uit_len);
+ fputs(buf, ecdhresp);
+ fputc('\n', ecdhresp);
+ /* ECDH */
+ if (ECDH_Derive(&pubkey, current_ecparams, &ecpriv->privateValue,
+ PR_FALSE, &ZZ) != SECSuccess) {
+ fprintf(stderr, "Derive failed\n");
+ goto loser;
+ }
+ /* output hash of ZZ */
+ if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
+ fprintf(stderr, "hash of derived key failed\n");
+ goto loser;
+ }
+ SECITEM_FreeItem(&ZZ, PR_FALSE);
+ fputs("HashZZ = ", ecdhresp);
+ to_hex_str(buf, hashBuf, fips_hashLen(hash));
+ fputs(buf, ecdhresp);
+ fputc('\n', ecdhresp);
+ fputc('\n', ecdhresp);
+ PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
+ ecpriv = NULL;
+ continue;
+ }
+ }
+loser:
+ if (ecpriv != NULL) {
+ PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
+ }
+ for (i = 0; i < MAX_ECC_PARAMS; i++) {
+ if (ecparams[i] != NULL) {
+ PORT_FreeArena(ecparams[i]->arena, PR_FALSE);
+ ecparams[i] = NULL;
+ }
+ }
+ if (pubkey.data != NULL) {
+ PORT_Free(pubkey.data);
+ }
+ fclose(ecdhreq);
+}
+
+/*
+ * Perform the ECDH Validity Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+ecdh_verify(char *reqfn, PRBool response)
+{
+ 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 *ecdhreq; /* input stream from the REQUEST file */
+ FILE *ecdhresp; /* output stream to the RESPONSE file */
+ char curve[16]; /* "nistxddd" */
+ unsigned char hashBuf[HASH_LENGTH_MAX];
+ unsigned char cavsHashBuf[HASH_LENGTH_MAX];
+ unsigned char private_data[MAX_ECKEY_LEN];
+ ECParams *ecparams[MAX_ECC_PARAMS] = { NULL };
+ ECParams *current_ecparams = NULL;
+ SECItem pubkey;
+ SECItem ZZ;
+ SECItem private_value;
+ unsigned int i;
+ unsigned int len = 0;
+ int current_curve = -1;
+ HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
+
+ ecdhreq = fopen(reqfn, "r");
+ ecdhresp = stdout;
+ strcpy(curve, "nist");
+ pubkey.data = NULL;
+ while (fgets(buf, sizeof buf, ecdhreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
+ fputs(buf, ecdhresp);
+ continue;
+ }
+ if (buf[0] == '[') {
+ /* [Ex] */
+ if (buf[1] == 'E' && buf[3] == ']') {
+ current_curve = buf[2] - 'A';
+ fputs(buf, ecdhresp);
+ continue;
+ }
+ /* [Curve selected: x-nnn */
+ if (strncmp(buf, "[Curve ", 7) == 0) {
+ const char *src;
+ char *dst;
+ SECItem *encodedparams;
+
+ if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) {
+ fprintf(stderr, "No curve type defined\n");
+ goto loser;
+ }
+
+ src = &buf[1];
+ /* skip passed the colon */
+ while (*src && *src != ':')
+ src++;
+ if (*src != ':') {
+ fprintf(stderr,
+ "No colon in curve selected statement\n%s", buf);
+ goto loser;
+ }
+ src++;
+ /* skip to the first non-space */
+ while (*src && *src == ' ')
+ src++;
+ dst = &curve[4];
+ *dst++ = tolower(*src);
+ src += 2; /* skip the hyphen */
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst = '\0';
+ if (ecparams[current_curve] != NULL) {
+ PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE);
+ ecparams[current_curve] = NULL;
+ }
+ encodedparams = getECParams(curve);
+ if (encodedparams == NULL) {
+ fprintf(stderr, "Unknown curve %s.\n", curve);
+ goto loser;
+ }
+ if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) != SECSuccess) {
+ fprintf(stderr, "Curve %s not supported.\n", curve);
+ goto loser;
+ }
+ SECITEM_FreeItem(encodedparams, PR_TRUE);
+ fputs(buf, ecdhresp);
+ continue;
+ }
+ /* [Ex - SHAxxx] */
+ if (buf[1] == 'E' && buf[3] == ' ') {
+ const char *src;
+ current_curve = buf[2] - 'A';
+ if ((current_curve < 0) || (current_curve > 256)) {
+ fprintf(stderr, "bad curve type defined (%c)\n", buf[2]);
+ goto loser;
+ }
+ current_ecparams = ecparams[current_curve];
+ if (current_ecparams == NULL) {
+ fprintf(stderr, "no curve defined for type %c defined\n",
+ buf[2]);
+ goto loser;
+ }
+ /* skip passed the colon */
+ src = &buf[1];
+ while (*src && *src != '-')
+ src++;
+ if (*src != '-') {
+ fprintf(stderr,
+ "No data in curve selected statement\n%s", buf);
+ goto loser;
+ }
+ src++;
+ /* skip to the first non-space */
+ while (*src && *src == ' ')
+ src++;
+ hash = hash_string_to_hashType(src);
+ if (hash == HASH_AlgNULL) {
+ fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type");
+ goto loser;
+ }
+ fputs(buf, ecdhresp);
+ continue;
+ }
+ fputs(buf, ecdhresp);
+ continue;
+ }
+ /* COUNT = ... */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ fputs(buf, ecdhresp);
+ if (current_ecparams == NULL) {
+ fprintf(stderr, "no curve defined for type %c defined\n",
+ buf[2]);
+ goto loser;
+ }
+ len = (current_ecparams->fieldID.size + 7) >> 3;
+ if (pubkey.data != NULL) {
+ PORT_Free(pubkey.data);
+ pubkey.data = NULL;
+ }
+ SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams));
+ if (pubkey.data == NULL) {
+ goto loser;
+ }
+ pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
+ continue;
+ }
+ /* QeCAVSx = ... */
+ if (strncmp(buf, "QeCAVSx", 7) == 0) {
+ fputs(buf, ecdhresp);
+ i = 7;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ from_hex_str(&pubkey.data[1], len, &buf[i]);
+ continue;
+ }
+ /* QeCAVSy = ... */
+ if (strncmp(buf, "QeCAVSy", 7) == 0) {
+ fputs(buf, ecdhresp);
+ i = 7;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ from_hex_str(&pubkey.data[1 + len], len, &buf[i]);
+ continue;
+ }
+ if (strncmp(buf, "deIUT", 5) == 0) {
+ fputs(buf, ecdhresp);
+ i = 5;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ from_hex_str(private_data, len, &buf[i]);
+ private_value.data = private_data;
+ private_value.len = len;
+ continue;
+ }
+ if (strncmp(buf, "QeIUTx", 6) == 0) {
+ fputs(buf, ecdhresp);
+ continue;
+ }
+ if (strncmp(buf, "QeIUTy", 6) == 0) {
+ fputs(buf, ecdhresp);
+ continue;
+ }
+ if ((strncmp(buf, "CAVSHashZZ", 10) == 0) ||
+ (strncmp(buf, "HashZZ", 6) == 0)) {
+ fputs(buf, ecdhresp);
+ i = (buf[0] == 'C') ? 10 : 6;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]);
+ if (current_ecparams == NULL) {
+ fprintf(stderr, "no curve defined for type defined\n");
+ goto loser;
+ }
+ /* validate CAVS public key */
+ if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) {
+#ifdef VERBOSE_REASON
+ fprintf(ecdhresp, "Result = F # key didn't validate\n");
+#else
+ fprintf(ecdhresp, "Result = F\n");
+#endif
+ continue;
+ }
+
+ /* ECDH */
+ if (ECDH_Derive(&pubkey, current_ecparams, &private_value,
+ PR_FALSE, &ZZ) != SECSuccess) {
+#ifdef VERBOSE_REASON
+ fprintf(ecdhresp, "Result = F # derive failure\n");
+#else
+ fprintf(ecdhresp, "Result = F\n");
+#endif
+ continue;
+ }
+/* output ZZ */
+#ifndef MATCH_OPENSSL
+ fputs("Z = ", ecdhresp);
+ to_hex_str(buf, ZZ.data, ZZ.len);
+ fputs(buf, ecdhresp);
+ fputc('\n', ecdhresp);
+#endif
+
+ if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
+ fprintf(stderr, "hash of derived key failed\n");
+ goto loser;
+ }
+ SECITEM_FreeItem(&ZZ, PR_FALSE);
+#ifndef MATCH_NIST
+ fputs("IUTHashZZ = ", ecdhresp);
+ to_hex_str(buf, hashBuf, fips_hashLen(hash));
+ fputs(buf, ecdhresp);
+ fputc('\n', ecdhresp);
+#endif
+ if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) {
+#ifdef VERBOSE_REASON
+ fprintf(ecdhresp, "Result = F # hash doesn't match\n");
+#else
+ fprintf(ecdhresp, "Result = F\n");
+#endif
+ } else {
+ fprintf(ecdhresp, "Result = P\n");
+ }
+#ifndef MATCH_OPENSSL
+ fputc('\n', ecdhresp);
+#endif
+ continue;
+ }
+ }
+loser:
+ for (i = 0; i < MAX_ECC_PARAMS; i++) {
+ if (ecparams[i] != NULL) {
+ PORT_FreeArena(ecparams[i]->arena, PR_FALSE);
+ ecparams[i] = NULL;
+ }
+ }
+ if (pubkey.data != NULL) {
+ PORT_Free(pubkey.data);
+ }
+ fclose(ecdhreq);
+}
+
+/*
+ * Perform the DH Functional Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+#define MAX_ECC_PARAMS 256
+void
+dh_functional(char *reqfn, PRBool response)
+{
+ char buf[1024]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "YephCAVS = <512 hex digits>\n".
+ */
+ FILE *dhreq; /* input stream from the REQUEST file */
+ FILE *dhresp; /* output stream to the RESPONSE file */
+ unsigned char hashBuf[HASH_LENGTH_MAX];
+ DSAPrivateKey *dsapriv = NULL;
+ PQGParams pqg = { 0 };
+ unsigned char pubkeydata[DSA_MAX_P_BITS / 8];
+ SECItem pubkey;
+ SECItem ZZ;
+ unsigned int i, j;
+ unsigned int pgySize;
+ HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
+
+ dhreq = fopen(reqfn, "r");
+ dhresp = stdout;
+ while (fgets(buf, sizeof buf, dhreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
+ fputs(buf, dhresp);
+ continue;
+ }
+ if (buf[0] == '[') {
+ /* [Fx - SHAxxx] */
+ if (buf[1] == 'F' && buf[3] == ' ') {
+ const char *src;
+ /* skip passed the colon */
+ src = &buf[1];
+ while (*src && *src != '-')
+ src++;
+ if (*src != '-') {
+ fprintf(stderr, "No hash specified\n%s", buf);
+ goto loser;
+ }
+ src++;
+ /* skip to the first non-space */
+ while (*src && *src == ' ')
+ src++;
+ hash = hash_string_to_hashType(src);
+ if (hash == HASH_AlgNULL) {
+ fprintf(dhresp, "ERROR: Unable to find SHAAlg type");
+ goto loser;
+ }
+ /* clear the PQG parameters */
+ 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);
+ }
+ pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */
+ SECITEM_AllocItem(NULL, &pqg.prime, pgySize);
+ SECITEM_AllocItem(NULL, &pqg.base, pgySize);
+ pqg.prime.len = pqg.base.len = pgySize;
+
+ /* set q to the max allows */
+ SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS / 8);
+ pqg.subPrime.len = DSA_MAX_Q_BITS / 8;
+ fputs(buf, dhresp);
+ continue;
+ }
+ fputs(buf, dhresp);
+ continue;
+ }
+ if (buf[0] == 'P') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < pqg.prime.len; i += 2, j++) {
+ if (!isxdigit(buf[i])) {
+ pqg.prime.len = j;
+ break;
+ }
+ hex_to_byteval(&buf[i], &pqg.prime.data[j]);
+ }
+
+ fputs(buf, dhresp);
+ 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++) {
+ if (!isxdigit(buf[i])) {
+ pqg.subPrime.len = j;
+ break;
+ }
+ hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
+ }
+
+ fputs(buf, dhresp);
+ continue;
+ }
+
+ /* G = ... */
+ if (buf[0] == 'G') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < pqg.base.len; i += 2, j++) {
+ if (!isxdigit(buf[i])) {
+ pqg.base.len = j;
+ break;
+ }
+ hex_to_byteval(&buf[i], &pqg.base.data[j]);
+ }
+
+ fputs(buf, dhresp);
+ continue;
+ }
+
+ /* COUNT = ... */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ fputs(buf, dhresp);
+ continue;
+ }
+
+ /* YephemCAVS = ... */
+ if (strncmp(buf, "YephemCAVS", 10) == 0) {
+ fputs(buf, dhresp);
+ i = 10;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ from_hex_str(pubkeydata, pqg.prime.len, &buf[i]);
+ pubkey.data = pubkeydata;
+ pubkey.len = pqg.prime.len;
+
+ /* generate FCC key pair, nist uses pqg rather then pg,
+ * so use DSA to generate the key */
+ if (DSA_NewKey(&pqg, &dsapriv) != SECSuccess) {
+ fprintf(stderr, "Failed to generate new key\n");
+ goto loser;
+ }
+ fputs("XephemIUT = ", dhresp);
+ to_hex_str(buf, dsapriv->privateValue.data, dsapriv->privateValue.len);
+ fputs(buf, dhresp);
+ fputc('\n', dhresp);
+ fputs("YephemIUT = ", dhresp);
+ to_hex_str(buf, dsapriv->publicValue.data, dsapriv->publicValue.len);
+ fputs(buf, dhresp);
+ fputc('\n', dhresp);
+ /* DH */
+ if (DH_Derive(&pubkey, &pqg.prime, &dsapriv->privateValue,
+ &ZZ, pqg.prime.len) != SECSuccess) {
+ fprintf(stderr, "Derive failed\n");
+ goto loser;
+ }
+ /* output hash of ZZ */
+ if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
+ fprintf(stderr, "hash of derived key failed\n");
+ goto loser;
+ }
+ SECITEM_FreeItem(&ZZ, PR_FALSE);
+ fputs("HashZZ = ", dhresp);
+ to_hex_str(buf, hashBuf, fips_hashLen(hash));
+ fputs(buf, dhresp);
+ fputc('\n', dhresp);
+ fputc('\n', dhresp);
+ PORT_FreeArena(dsapriv->params.arena, PR_TRUE);
+ dsapriv = NULL;
+ continue;
+ }
+ }
+loser:
+ if (dsapriv != NULL) {
+ PORT_FreeArena(dsapriv->params.arena, PR_TRUE);
+ }
+ fclose(dhreq);
+}
+
+/*
+ * Perform the DH Validity Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+dh_verify(char *reqfn, PRBool response)
+{
+ char buf[1024]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "YephCAVS = <512 hex digits>\n".
+ */
+ FILE *dhreq; /* input stream from the REQUEST file */
+ FILE *dhresp; /* output stream to the RESPONSE file */
+ unsigned char hashBuf[HASH_LENGTH_MAX];
+ unsigned char cavsHashBuf[HASH_LENGTH_MAX];
+ PQGParams pqg = { 0 };
+ unsigned char pubkeydata[DSA_MAX_P_BITS / 8];
+ unsigned char privkeydata[DSA_MAX_P_BITS / 8];
+ SECItem pubkey;
+ SECItem privkey;
+ SECItem ZZ;
+ unsigned int i, j;
+ unsigned int pgySize;
+ HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */
+
+ dhreq = fopen(reqfn, "r");
+ dhresp = stdout;
+ while (fgets(buf, sizeof buf, dhreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
+ fputs(buf, dhresp);
+ continue;
+ }
+ if (buf[0] == '[') {
+ /* [Fx - SHAxxx] */
+ if (buf[1] == 'F' && buf[3] == ' ') {
+ const char *src;
+ /* skip passed the colon */
+ src = &buf[1];
+ while (*src && *src != '-')
+ src++;
+ if (*src != '-') {
+ fprintf(stderr, "No hash specified\n%s", buf);
+ goto loser;
+ }
+ src++;
+ /* skip to the first non-space */
+ while (*src && *src == ' ')
+ src++;
+ hash = hash_string_to_hashType(src);
+ if (hash == HASH_AlgNULL) {
+ fprintf(dhresp, "ERROR: Unable to find SHAAlg type");
+ goto loser;
+ }
+ /* clear the PQG parameters */
+ 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);
+ }
+ pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */
+ SECITEM_AllocItem(NULL, &pqg.prime, pgySize);
+ SECITEM_AllocItem(NULL, &pqg.base, pgySize);
+ pqg.prime.len = pqg.base.len = pgySize;
+
+ /* set q to the max allows */
+ SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS / 8);
+ pqg.subPrime.len = DSA_MAX_Q_BITS / 8;
+ fputs(buf, dhresp);
+ continue;
+ }
+ fputs(buf, dhresp);
+ continue;
+ }
+ if (buf[0] == 'P') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < pqg.prime.len; i += 2, j++) {
+ if (!isxdigit(buf[i])) {
+ pqg.prime.len = j;
+ break;
+ }
+ hex_to_byteval(&buf[i], &pqg.prime.data[j]);
+ }
+
+ fputs(buf, dhresp);
+ 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++) {
+ if (!isxdigit(buf[i])) {
+ pqg.subPrime.len = j;
+ break;
+ }
+ hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
+ }
+
+ fputs(buf, dhresp);
+ continue;
+ }
+
+ /* G = ... */
+ if (buf[0] == 'G') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < pqg.base.len; i += 2, j++) {
+ if (!isxdigit(buf[i])) {
+ pqg.base.len = j;
+ break;
+ }
+ hex_to_byteval(&buf[i], &pqg.base.data[j]);
+ }
+
+ fputs(buf, dhresp);
+ continue;
+ }
+
+ /* COUNT = ... */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ fputs(buf, dhresp);
+ continue;
+ }
+
+ /* YephemCAVS = ... */
+ if (strncmp(buf, "YephemCAVS", 10) == 0) {
+ fputs(buf, dhresp);
+ i = 10;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ from_hex_str(pubkeydata, pqg.prime.len, &buf[i]);
+ pubkey.data = pubkeydata;
+ pubkey.len = pqg.prime.len;
+ continue;
+ }
+ /* XephemUIT = ... */
+ if (strncmp(buf, "XephemIUT", 9) == 0) {
+ fputs(buf, dhresp);
+ i = 9;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ from_hex_str(privkeydata, pqg.subPrime.len, &buf[i]);
+ privkey.data = privkeydata;
+ privkey.len = pqg.subPrime.len;
+ continue;
+ }
+ /* YephemUIT = ... */
+ if (strncmp(buf, "YephemIUT", 9) == 0) {
+ fputs(buf, dhresp);
+ continue;
+ }
+ /* CAVSHashZZ = ... */
+ if ((strncmp(buf, "CAVSHashZZ", 10) == 0) ||
+ (strncmp(buf, "HashZZ", 6) == 0)) {
+ fputs(buf, dhresp);
+ i = buf[0] == 'C' ? 10 : 6;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]);
+ /* do the DH operation*/
+ if (DH_Derive(&pubkey, &pqg.prime, &privkey,
+ &ZZ, pqg.prime.len) != SECSuccess) {
+ fprintf(stderr, "Derive failed\n");
+ goto loser;
+ }
+/* output ZZ */
+#ifndef MATCH_OPENSSL
+ fputs("Z = ", dhresp);
+ to_hex_str(buf, ZZ.data, ZZ.len);
+ fputs(buf, dhresp);
+ fputc('\n', dhresp);
+#endif
+ if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
+ fprintf(stderr, "hash of derived key failed\n");
+ goto loser;
+ }
+ SECITEM_FreeItem(&ZZ, PR_FALSE);
+#ifndef MATCH_NIST
+ fputs("IUTHashZZ = ", dhresp);
+ to_hex_str(buf, hashBuf, fips_hashLen(hash));
+ fputs(buf, dhresp);
+ fputc('\n', dhresp);
+#endif
+ if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) {
+ fprintf(dhresp, "Result = F\n");
+ } else {
+ fprintf(dhresp, "Result = P\n");
+ }
+#ifndef MATCH_OPENSSL
+ fputc('\n', dhresp);
+#endif
+ continue;
+ }
+ }
+loser:
+ fclose(dhreq);
+}
+
+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);
+
+ snprintf(buf, sizeof(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 */
+ shaAlg = hash_string_to_hashType(&buf[i]);
+ if (shaAlg == HASH_AlgNULL) {
+ 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 */
+ shaAlg = hash_string_to_hashType(&buf[i]);
+ if (shaAlg == HASH_AlgNULL) {
+ 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_TLS12_MASTER_KEY_DERIVE_PARAMS master_params;
+ CK_TLS12_KEY_MAT_PARAMS key_block_params;
+ CK_SSL3_KEY_MAT_OUT key_material;
+ CK_RV crv;
+
+ /* set up PKCS #11 parameters */
+ master_params.prfHashMechanism = CKM_SHA256;
+ 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.prfHashMechanism = CKM_SHA256;
+ 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') {
+ /* CK_SSL3_MASTER_KEY_DERIVE_PARAMS is a subset of
+ * CK_TLS12_MASTER_KEY_DERIVE_PARAMS and
+ * CK_SSL3_KEY_MAT_PARAMS is a subset of
+ * CK_TLS12_KEY_MAT_PARAMS. The latter params have
+ * an extra prfHashMechanism field at the end. */
+ master_mech.mechanism = CKM_TLS_MASTER_KEY_DERIVE;
+ key_block_mech.mechanism = CKM_TLS_KEY_AND_MAC_DERIVE;
+ master_mech.ulParameterLen = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
+ key_block_mech.ulParameterLen = sizeof(CK_SSL3_KEY_MAT_PARAMS);
+ } else if (buf[7] == '2') {
+ if (strncmp(&buf[10], "SHA-1", 5) == 0) {
+ master_params.prfHashMechanism = CKM_SHA_1;
+ key_block_params.prfHashMechanism = CKM_SHA_1;
+ } else if (strncmp(&buf[10], "SHA-224", 7) == 0) {
+ master_params.prfHashMechanism = CKM_SHA224;
+ key_block_params.prfHashMechanism = CKM_SHA224;
+ } else if (strncmp(&buf[10], "SHA-256", 7) == 0) {
+ master_params.prfHashMechanism = CKM_SHA256;
+ key_block_params.prfHashMechanism = CKM_SHA256;
+ } else if (strncmp(&buf[10], "SHA-384", 7) == 0) {
+ master_params.prfHashMechanism = CKM_SHA384;
+ key_block_params.prfHashMechanism = CKM_SHA384;
+ } else if (strncmp(&buf[10], "SHA-512", 7) == 0) {
+ master_params.prfHashMechanism = CKM_SHA512;
+ key_block_params.prfHashMechanism = CKM_SHA512;
+ } else {
+ fprintf(tlsresp, "ERROR: Unable to find prf Hash type");
+ goto loser;
+ }
+ master_mech.mechanism = CKM_TLS12_MASTER_KEY_DERIVE;
+ key_block_mech.mechanism = CKM_TLS12_KEY_AND_MAC_DERIVE;
+ master_mech.ulParameterLen = sizeof(master_params);
+ key_block_mech.ulParameterLen = sizeof(key_block_params);
+ } 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);
+}
+
+void
+ikev1(char *reqfn)
+{
+ char buf[4096]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "g^xy = <2048 hex digits>\n".
+ */
+ unsigned char *gxy = NULL;
+ int gxy_len;
+ unsigned char *Ni = NULL;
+ int Ni_len;
+ unsigned char *Nr = NULL;
+ int Nr_len;
+ unsigned char CKYi[8];
+ int CKYi_len;
+ unsigned char CKYr[8];
+ int CKYr_len;
+ unsigned int i, j;
+ FILE *ikereq = NULL; /* input stream from the REQUEST file */
+ FILE *ikeresp; /* output stream to the RESPONSE file */
+
+ 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 keyLen = 1;
+ CK_ATTRIBUTE gxy_template[] = {
+ { CKA_VALUE, NULL, 0 }, /* must be first */
+ { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
+ { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
+ { CKA_DERIVE, &ck_true, sizeof(ck_true) },
+ };
+ CK_ULONG gxy_template_count =
+ sizeof(gxy_template) / sizeof(gxy_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, &keyLen, sizeof(keyLen) }, /* must be last */
+ };
+ CK_ULONG derive_template_count =
+ sizeof(derive_template) / sizeof(derive_template[0]);
+ CK_ATTRIBUTE skeyid_template = { CKA_VALUE, NULL, 0 };
+ CK_ATTRIBUTE skeyid_d_template = { CKA_VALUE, NULL, 0 };
+ CK_ATTRIBUTE skeyid_a_template = { CKA_VALUE, NULL, 0 };
+ CK_ATTRIBUTE skeyid_e_template = { CKA_VALUE, NULL, 0 };
+ unsigned char skeyid_secret[HASH_LENGTH_MAX];
+ unsigned char skeyid_d_secret[HASH_LENGTH_MAX];
+ unsigned char skeyid_a_secret[HASH_LENGTH_MAX];
+ unsigned char skeyid_e_secret[HASH_LENGTH_MAX];
+
+ CK_MECHANISM ike_mech = { CKM_NSS_IKE_PRF_DERIVE, NULL, 0 };
+ CK_MECHANISM ike1_mech = { CKM_NSS_IKE1_PRF_DERIVE, NULL, 0 };
+ CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf;
+ CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf;
+ CK_RV crv;
+
+ /* set up PKCS #11 parameters */
+ ike_prf.bDataAsKey = PR_TRUE;
+ ike_prf.bRekey = PR_FALSE;
+ ike_prf.hNewKey = CK_INVALID_HANDLE;
+ CKYi_len = sizeof(CKYi);
+ CKYr_len = sizeof(CKYr);
+ ike1_prf.pCKYi = CKYi;
+ ike1_prf.ulCKYiLen = CKYi_len;
+ ike1_prf.pCKYr = CKYr;
+ ike1_prf.ulCKYrLen = CKYr_len;
+ ike_mech.pParameter = &ike_prf;
+ ike_mech.ulParameterLen = sizeof(ike_prf);
+ ike1_mech.pParameter = &ike1_prf;
+ ike1_mech.ulParameterLen = sizeof(ike1_prf);
+ skeyid_template.pValue = skeyid_secret;
+ skeyid_template.ulValueLen = HASH_LENGTH_MAX;
+ skeyid_d_template.pValue = skeyid_d_secret;
+ skeyid_d_template.ulValueLen = HASH_LENGTH_MAX;
+ skeyid_a_template.pValue = skeyid_a_secret;
+ skeyid_a_template.ulValueLen = HASH_LENGTH_MAX;
+ skeyid_e_template.pValue = skeyid_e_secret;
+ skeyid_e_template.ulValueLen = HASH_LENGTH_MAX;
+
+ 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];
+ ikereq = fopen(reqfn, "r");
+ ikeresp = stdout;
+ while (fgets(buf, sizeof buf, ikereq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* [.....] */
+ if (buf[0] == '[') {
+ if (strncmp(buf, "[SHA-1]", 7) == 0) {
+ ike_prf.prfMechanism = CKM_SHA_1_HMAC;
+ ike1_prf.prfMechanism = CKM_SHA_1_HMAC;
+ }
+ if (strncmp(buf, "[SHA-224]", 9) == 0) {
+ ike_prf.prfMechanism = CKM_SHA224_HMAC;
+ ike1_prf.prfMechanism = CKM_SHA224_HMAC;
+ }
+ if (strncmp(buf, "[SHA-256]", 9) == 0) {
+ ike_prf.prfMechanism = CKM_SHA256_HMAC;
+ ike1_prf.prfMechanism = CKM_SHA256_HMAC;
+ }
+ if (strncmp(buf, "[SHA-384]", 9) == 0) {
+ ike_prf.prfMechanism = CKM_SHA384_HMAC;
+ ike1_prf.prfMechanism = CKM_SHA384_HMAC;
+ }
+ if (strncmp(buf, "[SHA-512]", 9) == 0) {
+ ike_prf.prfMechanism = CKM_SHA512_HMAC;
+ ike1_prf.prfMechanism = CKM_SHA512_HMAC;
+ }
+ if (strncmp(buf, "[AES-XCBC", 9) == 0) {
+ ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
+ ike1_prf.prfMechanism = CKM_AES_XCBC_MAC;
+ }
+ if (strncmp(buf, "[g^xy", 5) == 0) {
+ if (sscanf(buf, "[g^xy length = %d]",
+ &gxy_len) != 1) {
+ goto loser;
+ }
+ gxy_len = gxy_len / 8;
+ if (gxy)
+ free(gxy);
+ gxy = malloc(gxy_len);
+ gxy_template[0].pValue = gxy;
+ gxy_template[0].ulValueLen = gxy_len;
+ }
+ if (strncmp(buf, "[Ni", 3) == 0) {
+ if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
+ goto loser;
+ }
+ Ni_len = Ni_len / 8;
+ if (Ni)
+ free(Ni);
+ Ni = malloc(Ni_len);
+ ike_prf.pNi = Ni;
+ ike_prf.ulNiLen = Ni_len;
+ }
+ if (strncmp(buf, "[Nr", 3) == 0) {
+ if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
+ goto loser;
+ }
+ Nr_len = Nr_len / 8;
+ if (Nr)
+ free(Nr);
+ Nr = malloc(Nr_len);
+ ike_prf.pNr = Nr;
+ ike_prf.ulNrLen = Nr_len;
+ }
+ fputs(buf, ikeresp);
+ 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(gxy, 0, gxy_len);
+ memset(Ni, 0, Ni_len);
+ memset(Nr, 0, Nr_len);
+ memset(CKYi, 0, CKYi_len);
+ memset(CKYr, 0, CKYr_len);
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* Ni = ... */
+ if (strncmp(buf, "Ni", 2) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < Ni_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &Ni[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* Nr = ... */
+ if (strncmp(buf, "Nr", 2) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < Nr_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &Nr[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* CKYi = ... */
+ if (strncmp(buf, "CKY_I", 5) == 0) {
+ i = 5;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < CKYi_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &CKYi[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* CKYr = ... */
+ if (strncmp(buf, "CKY_R", 5) == 0) {
+ i = 5;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < CKYr_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &CKYr[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* g^xy = ... */
+ if (strncmp(buf, "g^xy", 4) == 0) {
+ CK_SESSION_HANDLE session;
+ CK_OBJECT_HANDLE gxy_handle;
+ CK_OBJECT_HANDLE skeyid_handle;
+ CK_OBJECT_HANDLE skeyid_d_handle;
+ CK_OBJECT_HANDLE skeyid_a_handle;
+ CK_OBJECT_HANDLE skeyid_e_handle;
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < gxy_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &gxy[j]);
+ }
+ fputs(buf, ikeresp);
+ 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, gxy_template,
+ gxy_template_count, &gxy_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_CreateObject failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ /* get the skeyid key */
+ crv = NSC_DeriveKey(session, &ike_mech, gxy_handle,
+ derive_template, derive_template_count - 1,
+ &skeyid_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ skeyid_template.ulValueLen = HASH_LENGTH_MAX;
+ crv = NSC_GetAttributeValue(session, skeyid_handle,
+ &skeyid_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ /* use the length of the skeyid to set the target length of all the
+ * other keys */
+ keyLen = skeyid_template.ulValueLen;
+ ike1_prf.hKeygxy = gxy_handle;
+ ike1_prf.bHasPrevKey = PR_FALSE;
+ ike1_prf.keyNumber = 0;
+ crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
+ derive_template, derive_template_count,
+ &skeyid_d_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(skeyid_d) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+
+ ike1_prf.hKeygxy = gxy_handle;
+ ike1_prf.bHasPrevKey = CK_TRUE;
+ ike1_prf.hPrevKey = skeyid_d_handle;
+ ike1_prf.keyNumber = 1;
+ crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
+ derive_template, derive_template_count,
+ &skeyid_a_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(skeyid_a) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ ike1_prf.hKeygxy = gxy_handle;
+ ike1_prf.bHasPrevKey = CK_TRUE;
+ ike1_prf.hPrevKey = skeyid_a_handle;
+ ike1_prf.keyNumber = 2;
+ crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
+ derive_template, derive_template_count,
+ &skeyid_e_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(skeyid_e) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("SKEYID = ", ikeresp);
+ to_hex_str(buf, skeyid_secret, keyLen);
+ fputs(buf, ikeresp);
+ fputc('\n', ikeresp);
+
+ skeyid_d_template.ulValueLen = keyLen;
+ crv = NSC_GetAttributeValue(session, skeyid_d_handle,
+ &skeyid_d_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(skeyid_d) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("SKEYID_d = ", ikeresp);
+ to_hex_str(buf, skeyid_d_secret, skeyid_d_template.ulValueLen);
+ fputs(buf, ikeresp);
+ fputc('\n', ikeresp);
+
+ skeyid_a_template.ulValueLen = keyLen;
+ crv = NSC_GetAttributeValue(session, skeyid_a_handle,
+ &skeyid_a_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(skeyid_a) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("SKEYID_a = ", ikeresp);
+ to_hex_str(buf, skeyid_a_secret, skeyid_a_template.ulValueLen);
+ fputs(buf, ikeresp);
+ fputc('\n', ikeresp);
+
+ skeyid_e_template.ulValueLen = keyLen;
+ crv = NSC_GetAttributeValue(session, skeyid_e_handle,
+ &skeyid_e_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(skeyid_e) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("SKEYID_e = ", ikeresp);
+ to_hex_str(buf, skeyid_e_secret, skeyid_e_template.ulValueLen);
+ fputs(buf, ikeresp);
+ fputc('\n', ikeresp);
+
+ crv = NSC_CloseSession(session);
+ continue;
+ }
+ }
+loser:
+ NSC_Finalize(NULL);
+ if (gxy)
+ free(gxy);
+ if (Ni)
+ free(Ni);
+ if (Nr)
+ free(Nr);
+ if (ikereq)
+ fclose(ikereq);
+}
+
+void
+ikev1_psk(char *reqfn)
+{
+ char buf[4096]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "g^xy = <2048 hex digits>\n".
+ */
+ unsigned char *gxy = NULL;
+ int gxy_len;
+ unsigned char *Ni = NULL;
+ int Ni_len;
+ unsigned char *Nr = NULL;
+ int Nr_len;
+ unsigned char CKYi[8];
+ int CKYi_len;
+ unsigned char CKYr[8];
+ int CKYr_len;
+ unsigned char *psk = NULL;
+ int psk_len;
+ unsigned int i, j;
+ FILE *ikereq = NULL; /* input stream from the REQUEST file */
+ FILE *ikeresp; /* output stream to the RESPONSE file */
+
+ 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 keyLen = 1;
+ CK_ATTRIBUTE gxy_template[] = {
+ { CKA_VALUE, NULL, 0 }, /* must be first */
+ { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
+ { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
+ { CKA_DERIVE, &ck_true, sizeof(ck_true) },
+ };
+ CK_ULONG gxy_template_count =
+ sizeof(gxy_template) / sizeof(gxy_template[0]);
+ CK_ATTRIBUTE psk_template[] = {
+ { CKA_VALUE, NULL, 0 }, /* must be first */
+ { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
+ { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
+ { CKA_DERIVE, &ck_true, sizeof(ck_true) },
+ };
+ CK_ULONG psk_template_count =
+ sizeof(psk_template) / sizeof(psk_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, &keyLen, sizeof(keyLen) }, /* must be last */
+ };
+ CK_ULONG derive_template_count =
+ sizeof(derive_template) / sizeof(derive_template[0]);
+ CK_ATTRIBUTE skeyid_template = { CKA_VALUE, NULL, 0 };
+ CK_ATTRIBUTE skeyid_d_template = { CKA_VALUE, NULL, 0 };
+ CK_ATTRIBUTE skeyid_a_template = { CKA_VALUE, NULL, 0 };
+ CK_ATTRIBUTE skeyid_e_template = { CKA_VALUE, NULL, 0 };
+ unsigned char skeyid_secret[HASH_LENGTH_MAX];
+ unsigned char skeyid_d_secret[HASH_LENGTH_MAX];
+ unsigned char skeyid_a_secret[HASH_LENGTH_MAX];
+ unsigned char skeyid_e_secret[HASH_LENGTH_MAX];
+
+ CK_MECHANISM ike_mech = { CKM_NSS_IKE_PRF_DERIVE, NULL, 0 };
+ CK_MECHANISM ike1_mech = { CKM_NSS_IKE1_PRF_DERIVE, NULL, 0 };
+ CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf;
+ CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf;
+ CK_RV crv;
+
+ /* set up PKCS #11 parameters */
+ ike_prf.bDataAsKey = PR_FALSE;
+ ike_prf.bRekey = PR_FALSE;
+ ike_prf.hNewKey = CK_INVALID_HANDLE;
+ CKYi_len = 8;
+ CKYr_len = 8;
+ ike1_prf.pCKYi = CKYi;
+ ike1_prf.ulCKYiLen = CKYi_len;
+ ike1_prf.pCKYr = CKYr;
+ ike1_prf.ulCKYrLen = CKYr_len;
+ ike_mech.pParameter = &ike_prf;
+ ike_mech.ulParameterLen = sizeof(ike_prf);
+ ike1_mech.pParameter = &ike1_prf;
+ ike1_mech.ulParameterLen = sizeof(ike1_prf);
+ skeyid_template.pValue = skeyid_secret;
+ skeyid_template.ulValueLen = HASH_LENGTH_MAX;
+ skeyid_d_template.pValue = skeyid_d_secret;
+ skeyid_d_template.ulValueLen = HASH_LENGTH_MAX;
+ skeyid_a_template.pValue = skeyid_a_secret;
+ skeyid_a_template.ulValueLen = HASH_LENGTH_MAX;
+ skeyid_e_template.pValue = skeyid_e_secret;
+ skeyid_e_template.ulValueLen = HASH_LENGTH_MAX;
+
+ 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];
+ ikereq = fopen(reqfn, "r");
+ ikeresp = stdout;
+ while (fgets(buf, sizeof buf, ikereq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* [.....] */
+ if (buf[0] == '[') {
+ if (strncmp(buf, "[SHA-1]", 7) == 0) {
+ ike_prf.prfMechanism = CKM_SHA_1_HMAC;
+ ike1_prf.prfMechanism = CKM_SHA_1_HMAC;
+ }
+ if (strncmp(buf, "[SHA-224]", 9) == 0) {
+ ike_prf.prfMechanism = CKM_SHA224_HMAC;
+ ike1_prf.prfMechanism = CKM_SHA224_HMAC;
+ }
+ if (strncmp(buf, "[SHA-256]", 9) == 0) {
+ ike_prf.prfMechanism = CKM_SHA256_HMAC;
+ ike1_prf.prfMechanism = CKM_SHA256_HMAC;
+ }
+ if (strncmp(buf, "[SHA-384]", 9) == 0) {
+ ike_prf.prfMechanism = CKM_SHA384_HMAC;
+ ike1_prf.prfMechanism = CKM_SHA384_HMAC;
+ }
+ if (strncmp(buf, "[SHA-512]", 9) == 0) {
+ ike_prf.prfMechanism = CKM_SHA512_HMAC;
+ ike1_prf.prfMechanism = CKM_SHA512_HMAC;
+ }
+ if (strncmp(buf, "[AES-XCBC", 9) == 0) {
+ ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
+ ike1_prf.prfMechanism = CKM_AES_XCBC_MAC;
+ }
+ if (strncmp(buf, "[g^xy", 5) == 0) {
+ if (sscanf(buf, "[g^xy length = %d]",
+ &gxy_len) != 1) {
+ goto loser;
+ }
+ gxy_len = gxy_len / 8;
+ if (gxy)
+ free(gxy);
+ gxy = malloc(gxy_len);
+ gxy_template[0].pValue = gxy;
+ gxy_template[0].ulValueLen = gxy_len;
+ }
+ if (strncmp(buf, "[pre-shared-key", 15) == 0) {
+ if (sscanf(buf, "[pre-shared-key length = %d]",
+ &psk_len) != 1) {
+ goto loser;
+ }
+ psk_len = psk_len / 8;
+ if (psk)
+ free(psk);
+ psk = malloc(psk_len);
+ psk_template[0].pValue = psk;
+ psk_template[0].ulValueLen = psk_len;
+ }
+ if (strncmp(buf, "[Ni", 3) == 0) {
+ if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
+ goto loser;
+ }
+ Ni_len = Ni_len / 8;
+ if (Ni)
+ free(Ni);
+ Ni = malloc(Ni_len);
+ ike_prf.pNi = Ni;
+ ike_prf.ulNiLen = Ni_len;
+ }
+ if (strncmp(buf, "[Nr", 3) == 0) {
+ if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
+ goto loser;
+ }
+ Nr_len = Nr_len / 8;
+ if (Nr)
+ free(Nr);
+ Nr = malloc(Nr_len);
+ ike_prf.pNr = Nr;
+ ike_prf.ulNrLen = Nr_len;
+ }
+ fputs(buf, ikeresp);
+ 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(gxy, 0, gxy_len);
+ memset(Ni, 0, Ni_len);
+ memset(Nr, 0, Nr_len);
+ memset(CKYi, 0, CKYi_len);
+ memset(CKYr, 0, CKYr_len);
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* Ni = ... */
+ if (strncmp(buf, "Ni", 2) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < Ni_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &Ni[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* Nr = ... */
+ if (strncmp(buf, "Nr", 2) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < Nr_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &Nr[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* CKYi = ... */
+ if (strncmp(buf, "CKY_I", 5) == 0) {
+ i = 5;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < CKYi_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &CKYi[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* CKYr = ... */
+ if (strncmp(buf, "CKY_R", 5) == 0) {
+ i = 5;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < CKYr_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &CKYr[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* g^xy = ... */
+ if (strncmp(buf, "g^xy", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < gxy_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &gxy[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* pre-shared-key = ... */
+ if (strncmp(buf, "pre-shared-key", 14) == 0) {
+ CK_SESSION_HANDLE session;
+ CK_OBJECT_HANDLE gxy_handle;
+ CK_OBJECT_HANDLE psk_handle;
+ CK_OBJECT_HANDLE skeyid_handle;
+ CK_OBJECT_HANDLE skeyid_d_handle;
+ CK_OBJECT_HANDLE skeyid_a_handle;
+ CK_OBJECT_HANDLE skeyid_e_handle;
+ i = 14;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < psk_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &psk[j]);
+ }
+ fputs(buf, ikeresp);
+ 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, psk_template,
+ psk_template_count, &psk_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_CreateObject(psk) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ crv = NSC_CreateObject(session, gxy_template,
+ gxy_template_count, &gxy_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_CreateObject(gxy) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ /* get the skeyid key */
+ crv = NSC_DeriveKey(session, &ike_mech, psk_handle,
+ derive_template, derive_template_count - 1,
+ &skeyid_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ skeyid_template.ulValueLen = HASH_LENGTH_MAX;
+ crv = NSC_GetAttributeValue(session, skeyid_handle,
+ &skeyid_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ /* use the length of the skeyid to set the target length of all the
+ * other keys */
+ keyLen = skeyid_template.ulValueLen;
+ ike1_prf.hKeygxy = gxy_handle;
+ ike1_prf.bHasPrevKey = PR_FALSE;
+ ike1_prf.keyNumber = 0;
+ crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
+ derive_template, derive_template_count,
+ &skeyid_d_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(skeyid_d) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+
+ ike1_prf.hKeygxy = gxy_handle;
+ ike1_prf.bHasPrevKey = CK_TRUE;
+ ike1_prf.hPrevKey = skeyid_d_handle;
+ ike1_prf.keyNumber = 1;
+ crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
+ derive_template, derive_template_count,
+ &skeyid_a_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(skeyid_a) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ ike1_prf.hKeygxy = gxy_handle;
+ ike1_prf.bHasPrevKey = CK_TRUE;
+ ike1_prf.hPrevKey = skeyid_a_handle;
+ ike1_prf.keyNumber = 2;
+ crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
+ derive_template, derive_template_count,
+ &skeyid_e_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(skeyid_e) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("SKEYID = ", ikeresp);
+ to_hex_str(buf, skeyid_secret, keyLen);
+ fputs(buf, ikeresp);
+ fputc('\n', ikeresp);
+
+ skeyid_d_template.ulValueLen = keyLen;
+ crv = NSC_GetAttributeValue(session, skeyid_d_handle,
+ &skeyid_d_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(skeyid_d) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("SKEYID_d = ", ikeresp);
+ to_hex_str(buf, skeyid_d_secret, skeyid_d_template.ulValueLen);
+ fputs(buf, ikeresp);
+ fputc('\n', ikeresp);
+
+ skeyid_a_template.ulValueLen = keyLen;
+ crv = NSC_GetAttributeValue(session, skeyid_a_handle,
+ &skeyid_a_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(skeyid_a) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("SKEYID_a = ", ikeresp);
+ to_hex_str(buf, skeyid_a_secret, skeyid_a_template.ulValueLen);
+ fputs(buf, ikeresp);
+ fputc('\n', ikeresp);
+
+ skeyid_e_template.ulValueLen = keyLen;
+ crv = NSC_GetAttributeValue(session, skeyid_e_handle,
+ &skeyid_e_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(skeyid_e) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("SKEYID_e = ", ikeresp);
+ to_hex_str(buf, skeyid_e_secret, skeyid_e_template.ulValueLen);
+ fputs(buf, ikeresp);
+ fputc('\n', ikeresp);
+
+ crv = NSC_CloseSession(session);
+ continue;
+ }
+ }
+loser:
+ NSC_Finalize(NULL);
+ if (psk)
+ free(psk);
+ if (gxy)
+ free(gxy);
+ if (Ni)
+ free(Ni);
+ if (Nr)
+ free(Nr);
+ if (ikereq)
+ fclose(ikereq);
+}
+
+void
+ikev2(char *reqfn)
+{
+ char buf[4096]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "g^xy = <2048 hex digits>\n".
+ */
+ unsigned char *gir = NULL;
+ unsigned char *gir_new = NULL;
+ int gir_len;
+ unsigned char *Ni = NULL;
+ int Ni_len;
+ unsigned char *Nr = NULL;
+ int Nr_len;
+ unsigned char *SPIi = NULL;
+ int SPIi_len = 8;
+ unsigned char *SPIr = NULL;
+ int SPIr_len = 8;
+ unsigned char *DKM = NULL;
+ int DKM_len;
+ unsigned char *DKM_child = NULL;
+ int DKM_child_len;
+ unsigned char *seed_data = NULL;
+ int seed_data_len = 0;
+ unsigned int i, j;
+ FILE *ikereq = NULL; /* input stream from the REQUEST file */
+ FILE *ikeresp; /* output stream to the RESPONSE file */
+
+ 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 keyLen = 1;
+ CK_ATTRIBUTE gir_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 gir_template_count =
+ sizeof(gir_template) / sizeof(gir_template[0]);
+ CK_ATTRIBUTE gir_new_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 gir_new_template_count =
+ sizeof(gir_new_template) / sizeof(gir_new_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, &keyLen, sizeof(keyLen) },
+ };
+ CK_ULONG derive_template_count =
+ sizeof(derive_template) / sizeof(derive_template[0]);
+ CK_ATTRIBUTE skeyseed_template = { CKA_VALUE, NULL, 0 };
+ CK_ATTRIBUTE dkm_template = { CKA_VALUE, NULL, 0 };
+ CK_ATTRIBUTE dkm_child_template = { CKA_VALUE, NULL, 0 };
+ unsigned char skeyseed_secret[HASH_LENGTH_MAX];
+
+ CK_MECHANISM ike_mech = { CKM_NSS_IKE_PRF_DERIVE, NULL, 0 };
+ CK_MECHANISM ike2_mech = { CKM_NSS_IKE_PRF_PLUS_DERIVE, NULL, 0 };
+ CK_MECHANISM subset_mech = { CKM_EXTRACT_KEY_FROM_KEY, NULL, 0 };
+ CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf;
+ CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS ike2_prf;
+ CK_EXTRACT_PARAMS subset_params;
+ CK_RV crv;
+
+ /* set up PKCS #11 parameters */
+ ike_mech.pParameter = &ike_prf;
+ ike_mech.ulParameterLen = sizeof(ike_prf);
+ ike2_mech.pParameter = &ike2_prf;
+ ike2_mech.ulParameterLen = sizeof(ike2_prf);
+ subset_mech.pParameter = &subset_params;
+ subset_mech.ulParameterLen = sizeof(subset_params);
+ subset_params = 0;
+ skeyseed_template.pValue = skeyseed_secret;
+ skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
+
+ 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];
+ ikereq = fopen(reqfn, "r");
+ ikeresp = stdout;
+ while (fgets(buf, sizeof buf, ikereq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* [.....] */
+ if (buf[0] == '[') {
+ if (strncmp(buf, "[SHA-1]", 7) == 0) {
+ ike_prf.prfMechanism = CKM_SHA_1_HMAC;
+ ike2_prf.prfMechanism = CKM_SHA_1_HMAC;
+ }
+ if (strncmp(buf, "[SHA-224]", 9) == 0) {
+ ike_prf.prfMechanism = CKM_SHA224_HMAC;
+ ike2_prf.prfMechanism = CKM_SHA224_HMAC;
+ }
+ if (strncmp(buf, "[SHA-256]", 9) == 0) {
+ ike_prf.prfMechanism = CKM_SHA256_HMAC;
+ ike2_prf.prfMechanism = CKM_SHA256_HMAC;
+ }
+ if (strncmp(buf, "[SHA-384]", 9) == 0) {
+ ike_prf.prfMechanism = CKM_SHA384_HMAC;
+ ike2_prf.prfMechanism = CKM_SHA384_HMAC;
+ }
+ if (strncmp(buf, "[SHA-512]", 9) == 0) {
+ ike_prf.prfMechanism = CKM_SHA512_HMAC;
+ ike2_prf.prfMechanism = CKM_SHA512_HMAC;
+ }
+ if (strncmp(buf, "[AES-XCBC", 9) == 0) {
+ ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
+ ike2_prf.prfMechanism = CKM_AES_XCBC_MAC;
+ }
+ if (strncmp(buf, "[g^ir", 5) == 0) {
+ if (sscanf(buf, "[g^ir length = %d]",
+ &gir_len) != 1) {
+ goto loser;
+ }
+ gir_len = gir_len / 8;
+ if (gir)
+ free(gir);
+ if (gir_new)
+ free(gir_new);
+ gir = malloc(gir_len);
+ gir_new = malloc(gir_len);
+ gir_template[0].pValue = gir;
+ gir_template[0].ulValueLen = gir_len;
+ gir_new_template[0].pValue = gir_new;
+ gir_new_template[0].ulValueLen = gir_len;
+ }
+ if (strncmp(buf, "[Ni", 3) == 0) {
+ if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
+ goto loser;
+ }
+ Ni_len = Ni_len / 8;
+ }
+ if (strncmp(buf, "[Nr", 3) == 0) {
+ if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
+ goto loser;
+ }
+ Nr_len = Nr_len / 8;
+ }
+ if (strncmp(buf, "[DKM", 4) == 0) {
+ if (sscanf(buf, "[DKM length = %d]",
+ &DKM_len) != 1) {
+ goto loser;
+ }
+ DKM_len = DKM_len / 8;
+ if (DKM)
+ free(DKM);
+ DKM = malloc(DKM_len);
+ dkm_template.pValue = DKM;
+ dkm_template.ulValueLen = DKM_len;
+ }
+ if (strncmp(buf, "[Child SA DKM", 13) == 0) {
+ if (sscanf(buf, "[Child SA DKM length = %d]",
+ &DKM_child_len) != 1) {
+ goto loser;
+ }
+ DKM_child_len = DKM_child_len / 8;
+ if (DKM_child)
+ free(DKM_child);
+ DKM_child = malloc(DKM_child_len);
+ dkm_child_template.pValue = DKM_child;
+ dkm_child_template.ulValueLen = DKM_child_len;
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* "COUNT = x" begins a new data set */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ /* zeroize the variables for the test with this data set */
+ int new_seed_len = Ni_len + Nr_len + SPIi_len + SPIr_len;
+ if (seed_data_len != new_seed_len) {
+ if (seed_data)
+ free(seed_data);
+ seed_data_len = new_seed_len;
+ seed_data = malloc(seed_data_len);
+ Ni = seed_data;
+ Nr = &seed_data[Ni_len];
+ SPIi = &seed_data[Ni_len + Nr_len];
+ SPIr = &seed_data[new_seed_len - SPIr_len];
+ ike_prf.pNi = Ni;
+ ike_prf.ulNiLen = Ni_len;
+ ike_prf.pNr = Nr;
+ ike_prf.ulNrLen = Nr_len;
+ ike2_prf.pSeedData = seed_data;
+ }
+ memset(gir, 0, gir_len);
+ memset(gir_new, 0, gir_len);
+ memset(seed_data, 0, seed_data_len);
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* Ni = ... */
+ if (strncmp(buf, "Ni", 2) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < Ni_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &Ni[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* Nr = ... */
+ if (strncmp(buf, "Nr", 2) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < Nr_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &Nr[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* g^ir (new) = ... */
+ if (strncmp(buf, "g^ir (new)", 10) == 0) {
+ i = 10;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < gir_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &gir_new[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* g^ir = ... */
+ if (strncmp(buf, "g^ir", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < gir_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &gir[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* SPIi = ... */
+ if (strncmp(buf, "SPIi", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < SPIi_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &SPIi[j]);
+ }
+ fputs(buf, ikeresp);
+ continue;
+ }
+ /* SPIr = ... */
+ if (strncmp(buf, "SPIr", 4) == 0) {
+ CK_SESSION_HANDLE session;
+ CK_OBJECT_HANDLE gir_handle;
+ CK_OBJECT_HANDLE gir_new_handle;
+ CK_OBJECT_HANDLE skeyseed_handle;
+ CK_OBJECT_HANDLE sk_d_handle;
+ CK_OBJECT_HANDLE skeyseed_new_handle;
+ CK_OBJECT_HANDLE dkm_handle;
+ CK_OBJECT_HANDLE dkm_child_handle;
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j = 0; j < SPIr_len; i += 2, j++) {
+ hex_to_byteval(&buf[i], &SPIr[j]);
+ }
+ fputs(buf, ikeresp);
+ 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, gir_template,
+ gir_template_count, &gir_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_CreateObject (g^ir) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ crv = NSC_CreateObject(session, gir_new_template,
+ gir_new_template_count, &gir_new_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_CreateObject (g^ir new) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ /* get the SKEYSEED key */
+ ike_prf.bDataAsKey = CK_TRUE;
+ ike_prf.bRekey = CK_FALSE;
+ ike_prf.hNewKey = CK_INVALID_HANDLE;
+ crv = NSC_DeriveKey(session, &ike_mech, gir_handle,
+ derive_template, derive_template_count - 1,
+ &skeyseed_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
+ crv = NSC_GetAttributeValue(session, skeyseed_handle,
+ &skeyseed_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("SKEYSEED = ", ikeresp);
+ to_hex_str(buf, skeyseed_secret, skeyseed_template.ulValueLen);
+ fputs(buf, ikeresp);
+ fputc('\n', ikeresp);
+
+ /* get DKM */
+ keyLen = DKM_len;
+ ike2_prf.bHasSeedKey = CK_FALSE;
+ ike2_prf.hSeedKey = CK_INVALID_HANDLE;
+ ike2_prf.ulSeedDataLen = seed_data_len;
+ crv = NSC_DeriveKey(session, &ike2_mech, skeyseed_handle,
+ derive_template, derive_template_count,
+ &dkm_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(DKM) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ crv = NSC_GetAttributeValue(session, dkm_handle,
+ &dkm_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(DKM) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("DKM = ", ikeresp);
+ to_hex_str(buf, DKM, DKM_len);
+ fputs(buf, ikeresp);
+ fputc('\n', ikeresp);
+
+ /* get the sk_d from the DKM */
+ keyLen = skeyseed_template.ulValueLen;
+ crv = NSC_DeriveKey(session, &subset_mech, dkm_handle,
+ derive_template, derive_template_count,
+ &sk_d_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(sk_d) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+
+ /* get DKM child */
+ keyLen = DKM_child_len;
+ ike2_prf.bHasSeedKey = CK_FALSE;
+ ike2_prf.hSeedKey = CK_INVALID_HANDLE;
+ ike2_prf.ulSeedDataLen = Ni_len + Nr_len;
+ crv = NSC_DeriveKey(session, &ike2_mech, sk_d_handle,
+ derive_template, derive_template_count,
+ &dkm_child_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(DKM Child SA) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ crv = NSC_GetAttributeValue(session, dkm_child_handle,
+ &dkm_child_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(DKM Child SA) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("DKM(Child SA) = ", ikeresp);
+ to_hex_str(buf, DKM_child, DKM_child_len);
+ fputs(buf, ikeresp);
+ fputc('\n', ikeresp);
+
+ /* get DKM child D-H*/
+ keyLen = DKM_child_len;
+ ike2_prf.bHasSeedKey = CK_TRUE;
+ ike2_prf.hSeedKey = gir_new_handle;
+ ike2_prf.ulSeedDataLen = Ni_len + Nr_len;
+ crv = NSC_DeriveKey(session, &ike2_mech, sk_d_handle,
+ derive_template, derive_template_count,
+ &dkm_child_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(DKM Child SA D-H) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ crv = NSC_GetAttributeValue(session, dkm_child_handle,
+ &dkm_child_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(DKM Child SA D-H) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("DKM(Child SA D-H) = ", ikeresp);
+ to_hex_str(buf, DKM_child, DKM_child_len);
+ fputs(buf, ikeresp);
+ fputc('\n', ikeresp);
+
+ /* get SKEYSEED(rekey) */
+ ike_prf.bDataAsKey = CK_FALSE;
+ ike_prf.bRekey = CK_TRUE;
+ ike_prf.hNewKey = gir_new_handle;
+ crv = NSC_DeriveKey(session, &ike_mech, sk_d_handle,
+ derive_template, derive_template_count - 1,
+ &skeyseed_new_handle);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(skeyid rekey) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
+ crv = NSC_GetAttributeValue(session, skeyseed_new_handle,
+ &skeyseed_template, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
+ (unsigned int)crv);
+ goto loser;
+ }
+ fputs("SKEYSEED(rekey) = ", ikeresp);
+ to_hex_str(buf, skeyseed_secret, skeyseed_template.ulValueLen);
+ fputs(buf, ikeresp);
+ fputc('\n', ikeresp);
+
+ crv = NSC_CloseSession(session);
+ continue;
+ }
+ }
+loser:
+ NSC_Finalize(NULL);
+ if (gir)
+ free(gir);
+ if (gir_new)
+ free(gir_new);
+ if (seed_data)
+ free(seed_data);
+ if (DKM)
+ free(DKM);
+ if (DKM_child)
+ free(DKM_child);
+ if (ikereq)
+ fclose(ikereq);
+}
+
+void
+kbkdf(char *path)
+{
+ /* == Parser data == */
+ char buf[610]; /* holds one line from the input REQUEST file. Needs to
+ * be large enough to hold the longest line:
+ * "KO = <600 hex digits>\n". */
+ CK_ULONG L;
+ unsigned char KI[64];
+ unsigned int KI_len = 64;
+ unsigned char KO[300];
+ unsigned int KO_len = 300;
+ /* This is used only with feedback mode. */
+ unsigned char IV[64];
+ unsigned int IV_len = 64;
+ /* These are only used in counter mode with counter location as
+ * MIDDLE_FIXED. */
+ unsigned char BeforeFixedInputData[50];
+ unsigned int BeforeFixedInputData_len = 50;
+ unsigned char AfterFixedInputData[10];
+ unsigned int AfterFixedInputData_len = 10;
+ /* These are used with every KDF type. */
+ unsigned char FixedInputData[60];
+ unsigned int FixedInputData_len = 60;
+
+ /* Counter locations:
+ *
+ * 0: not used
+ * 1: beginning
+ * 2: middle
+ * 3: end */
+ int ctr_location = 0;
+ CK_ULONG counter_bitlen = 0;
+
+ size_t buf_offset;
+ size_t offset;
+
+ FILE *kbkdf_req = NULL;
+ FILE *kbkdf_resp = NULL;
+
+ /* == PKCS#11 data == */
+ CK_RV crv;
+
+ CK_SLOT_ID slotList[10];
+ CK_SLOT_ID slotID;
+ CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
+ CK_ULONG slotCount = 0;
+
+ CK_MECHANISM kdf = { 0 };
+
+ CK_MECHANISM_TYPE prf_mech = 0;
+ CK_BBOOL ck_true = CK_TRUE;
+
+ /* We never need more than 3 data parameters. */
+ CK_PRF_DATA_PARAM dataParams[3];
+ CK_ULONG dataParams_len = 3;
+
+ CK_SP800_108_COUNTER_FORMAT iterator = { CK_FALSE, 0 };
+
+ CK_SP800_108_KDF_PARAMS kdfParams = { 0 };
+ CK_SP800_108_FEEDBACK_KDF_PARAMS feedbackParams = { 0 };
+
+ CK_OBJECT_CLASS ck_secret_key = CKO_SECRET_KEY;
+ CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
+
+ CK_ATTRIBUTE prf_template[] = {
+ { CKA_VALUE, &KI, sizeof(KI) },
+ { CKA_CLASS, &ck_secret_key, sizeof(ck_secret_key) },
+ { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
+ { CKA_DERIVE, &ck_true, sizeof(ck_true) }
+ };
+ CK_ULONG prf_template_count = sizeof(prf_template) / sizeof(prf_template[0]);
+
+ CK_ATTRIBUTE derive_template[] = {
+ { CKA_CLASS, &ck_secret_key, sizeof(ck_secret_key) },
+ { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
+ { CKA_DERIVE, &ck_true, sizeof(ck_true) },
+ { CKA_VALUE_LEN, &L, sizeof(L) }
+ };
+ CK_ULONG derive_template_count = sizeof(derive_template) / sizeof(derive_template[0]);
+
+ CK_ATTRIBUTE output_key = { CKA_VALUE, KO, KO_len };
+
+ const CK_C_INITIALIZE_ARGS pk11args = {
+ NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
+ (void *)"flags=readOnly,noCertDB,noModDB", NULL
+ };
+
+ /* == Start up PKCS#11 == */
+ crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
+ goto done;
+ }
+
+ slotCount = slotListCount;
+ crv = NSC_GetSlotList(PR_TRUE, slotList, &slotCount);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
+ goto done;
+ }
+ if ((slotCount > slotListCount) || slotCount < 1) {
+ fprintf(stderr,
+ "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
+ (int)slotCount, (int)slotListCount);
+ goto done;
+ }
+ slotID = slotList[0];
+
+ /* == Start parsing the file == */
+ kbkdf_req = fopen(path, "r");
+ kbkdf_resp = stdout;
+
+ while (fgets(buf, sizeof buf, kbkdf_req) != NULL) {
+ /* If we have a comment, check if it tells us the type of KDF to use.
+ * This differs per-file, so we have to parse it. */
+ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') {
+ if (strncmp(buf, "# KDF Mode Supported: Counter Mode", 34) == 0) {
+ kdf.mechanism = CKM_SP800_108_COUNTER_KDF;
+ }
+ if (strncmp(buf, "# KDF Mode Supported: Feedback Mode", 35) == 0) {
+ kdf.mechanism = CKM_SP800_108_FEEDBACK_KDF;
+ }
+ if (strncmp(buf, "# KDF Mode Supported: DblPipeline Mode", 38) == 0) {
+ kdf.mechanism = CKM_SP800_108_DOUBLE_PIPELINE_KDF;
+ }
+
+ fputs(buf, kbkdf_resp);
+ continue;
+ }
+
+ /* [....] - context directive */
+ if (buf[0] == '[') {
+ /* PRF begins each new section. */
+ if (strncmp(buf, "[PRF=CMAC_AES128]", 17) == 0) {
+ prf_mech = CKM_AES_CMAC;
+ KI_len = 16;
+ } else if (strncmp(buf, "[PRF=CMAC_AES192]", 17) == 0) {
+ prf_mech = CKM_AES_CMAC;
+ KI_len = 24;
+ } else if (strncmp(buf, "[PRF=CMAC_AES256]", 17) == 0) {
+ prf_mech = CKM_AES_CMAC;
+ KI_len = 32;
+ } else if (strncmp(buf, "[PRF=HMAC_SHA1]", 15) == 0) {
+ prf_mech = CKM_SHA_1_HMAC;
+ KI_len = 20;
+ } else if (strncmp(buf, "[PRF=HMAC_SHA224]", 17) == 0) {
+ prf_mech = CKM_SHA224_HMAC;
+ KI_len = 28;
+ } else if (strncmp(buf, "[PRF=HMAC_SHA256]", 17) == 0) {
+ prf_mech = CKM_SHA256_HMAC;
+ KI_len = 32;
+ } else if (strncmp(buf, "[PRF=HMAC_SHA384]", 17) == 0) {
+ prf_mech = CKM_SHA384_HMAC;
+ KI_len = 48;
+ } else if (strncmp(buf, "[PRF=HMAC_SHA512]", 17) == 0) {
+ prf_mech = CKM_SHA512_HMAC;
+ KI_len = 64;
+ } else if (strncmp(buf, "[PRF=", 5) == 0) {
+ fprintf(stderr, "Invalid or unsupported PRF mechanism: %s\n", buf);
+ goto done;
+ }
+
+ /* Then comes counter, if present. */
+ if (strncmp(buf, "[CTRLOCATION=BEFORE_FIXED]", 26) == 0 ||
+ strncmp(buf, "[CTRLOCATION=BEFORE_ITER]", 24) == 0) {
+ ctr_location = 1;
+ }
+ if (strncmp(buf, "[CTRLOCATION=MIDDLE_FIXED]", 26) == 0 ||
+ strncmp(buf, "[CTRLOCATION=AFTER_ITER]", 24) == 0) {
+ ctr_location = 2;
+ }
+ if (strncmp(buf, "[CTRLOCATION=AFTER_FIXED]", 25) == 0) {
+ ctr_location = 3;
+ }
+
+ /* If counter is present, then we need to know its size. */
+ if (strncmp(buf, "[RLEN=", 6) == 0) {
+ if (sscanf(buf, "[RLEN=%lu_BITS]", &counter_bitlen) != 1) {
+ goto done;
+ }
+ }
+
+ fputs(buf, kbkdf_resp);
+ continue;
+ }
+
+ /* Each test contains a counter, an output length L, an input key KI,
+ * maybe an initialization vector IV, one of a couple of fixed data
+ * buffers, and finally the output key KO. */
+
+ /* First comes COUNT. */
+ if (strncmp(buf, "COUNT=", 6) == 0) {
+ /* Clear all out data fields on each test. */
+ memset(KI, 0, sizeof KI);
+ memset(KO, 0, sizeof KO);
+ memset(IV, 0, sizeof IV);
+ memset(BeforeFixedInputData, 0, sizeof BeforeFixedInputData);
+ memset(AfterFixedInputData, 0, sizeof AfterFixedInputData);
+ memset(FixedInputData, 0, sizeof FixedInputData);
+
+ /* Then reset lengths except KI: it was determined by PRF
+ * selection above. */
+ KO_len = 0;
+ IV_len = 0;
+ BeforeFixedInputData_len = 0;
+ AfterFixedInputData_len = 0;
+ FixedInputData_len = 0;
+
+ fputs(buf, kbkdf_resp);
+ continue;
+ }
+
+ /* Then comes L. */
+ if (strncmp(buf, "L = ", 4) == 0) {
+ if (sscanf(buf, "L = %lu", &L) != 1) {
+ goto done;
+ }
+
+ if ((L % 8) != 0) {
+ fprintf(stderr, "Assumption that L was length in bits incorrect: %lu - %s", L, buf);
+ fprintf(stderr, "Note that NSS only supports byte-aligned outputs and not bit-aligned outputs.\n");
+ goto done;
+ }
+
+ L = L / 8;
+
+ fputs(buf, kbkdf_resp);
+ continue;
+ }
+
+ /* Then comes KI. */
+ if (strncmp(buf, "KI = ", 5) == 0) {
+ buf_offset = 5;
+
+ for (offset = 0; offset < KI_len; offset++, buf_offset += 2) {
+ hex_to_byteval(buf + buf_offset, KI + offset);
+ }
+
+ fputs(buf, kbkdf_resp);
+ continue;
+ }
+
+ /* Then comes IVlen and IV, if present. */
+ if (strncmp(buf, "IVlen = ", 8) == 0) {
+ if (sscanf(buf, "IVlen = %u", &IV_len) != 1) {
+ goto done;
+ }
+
+ if ((IV_len % 8) != 0) {
+ fprintf(stderr, "Assumption that IV_len was length in bits incorrect: %u - %s. ", IV_len, buf);
+ fprintf(stderr, "Note that NSS only supports byte-aligned inputs and not bit-aligned inputs.\n");
+ goto done;
+ }
+
+ /* Need the IV length in bytes, not bits. */
+ IV_len = IV_len / 8;
+
+ fputs(buf, kbkdf_resp);
+ continue;
+ }
+ if (strncmp(buf, "IV = ", 5) == 0) {
+ buf_offset = 5;
+
+ for (offset = 0; offset < IV_len; offset++, buf_offset += 2) {
+ hex_to_byteval(buf + buf_offset, IV + offset);
+ }
+
+ fputs(buf, kbkdf_resp);
+ continue;
+ }
+
+ /* We might have DataBeforeCtr and DataAfterCtr if present. */
+ if (strncmp(buf, "DataBeforeCtrLen = ", 19) == 0) {
+ if (sscanf(buf, "DataBeforeCtrLen = %u", &BeforeFixedInputData_len) != 1) {
+ goto done;
+ }
+
+ fputs(buf, kbkdf_resp);
+ continue;
+ }
+ if (strncmp(buf, "DataBeforeCtrData = ", 20) == 0) {
+ buf_offset = 20;
+
+ for (offset = 0; offset < BeforeFixedInputData_len; offset++, buf_offset += 2) {
+ hex_to_byteval(buf + buf_offset, BeforeFixedInputData + offset);
+ }
+
+ fputs(buf, kbkdf_resp);
+ continue;
+ }
+ if (strncmp(buf, "DataAfterCtrLen = ", 18) == 0) {
+ if (sscanf(buf, "DataAfterCtrLen = %u", &AfterFixedInputData_len) != 1) {
+ goto done;
+ }
+
+ fputs(buf, kbkdf_resp);
+ continue;
+ }
+ if (strncmp(buf, "DataAfterCtrData = ", 19) == 0) {
+ buf_offset = 19;
+
+ for (offset = 0; offset < AfterFixedInputData_len; offset++, buf_offset += 2) {
+ hex_to_byteval(buf + buf_offset, AfterFixedInputData + offset);
+ }
+
+ fputs(buf, kbkdf_resp);
+ continue;
+ }
+
+ /* Otherwise, we might have FixedInputData, if present. */
+ if (strncmp(buf, "FixedInputDataByteLen = ", 24) == 0) {
+ if (sscanf(buf, "FixedInputDataByteLen = %u", &FixedInputData_len) != 1) {
+ goto done;
+ }
+
+ fputs(buf, kbkdf_resp);
+ continue;
+ }
+ if (strncmp(buf, "FixedInputData = ", 17) == 0) {
+ buf_offset = 17;
+
+ for (offset = 0; offset < FixedInputData_len; offset++, buf_offset += 2) {
+ hex_to_byteval(buf + buf_offset, FixedInputData + offset);
+ }
+
+ fputs(buf, kbkdf_resp);
+ continue;
+ }
+
+ /* Finally, run the KBKDF calculation when KO is passed. */
+ if (strncmp(buf, "KO = ", 5) == 0) {
+ CK_SESSION_HANDLE session;
+ CK_OBJECT_HANDLE prf_key;
+ CK_OBJECT_HANDLE derived_key;
+
+ /* Open the session. */
+ 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 done;
+ }
+
+ /* Create the PRF key object. */
+ prf_template[0].ulValueLen = KI_len;
+ crv = NSC_CreateObject(session, prf_template, prf_template_count, &prf_key);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_CreateObject (prf_key) failed crv=0x%x\n", (unsigned int)crv);
+ goto done;
+ }
+
+ /* Set up the KDF parameters. */
+ if (kdf.mechanism == CKM_SP800_108_COUNTER_KDF) {
+ /* Counter operates in one of three ways: counter before fixed
+ * input data, counter between fixed input data, and counter
+ * after fixed input data. In all cases, we have an iterator.
+ */
+ iterator.ulWidthInBits = counter_bitlen;
+
+ if (ctr_location == 0 || ctr_location > 3) {
+ fprintf(stderr, "Expected ctr_location != 0 for Counter Mode KDF but got 0.\n");
+ goto done;
+ } else if (ctr_location == 1) {
+ /* Counter before */
+ dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
+ dataParams[0].pValue = &iterator;
+ dataParams[0].ulValueLen = sizeof(iterator);
+
+ dataParams[1].type = CK_SP800_108_BYTE_ARRAY;
+ dataParams[1].pValue = FixedInputData;
+ dataParams[1].ulValueLen = FixedInputData_len;
+
+ dataParams_len = 2;
+ } else if (ctr_location == 2) {
+ /* Counter between */
+ dataParams[0].type = CK_SP800_108_BYTE_ARRAY;
+ dataParams[0].pValue = BeforeFixedInputData;
+ dataParams[0].ulValueLen = BeforeFixedInputData_len;
+
+ dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE;
+ dataParams[1].pValue = &iterator;
+ dataParams[1].ulValueLen = sizeof(iterator);
+
+ dataParams[2].type = CK_SP800_108_BYTE_ARRAY;
+ dataParams[2].pValue = AfterFixedInputData;
+ dataParams[2].ulValueLen = AfterFixedInputData_len;
+
+ dataParams_len = 3;
+ } else {
+ /* Counter after */
+ dataParams[0].type = CK_SP800_108_BYTE_ARRAY;
+ dataParams[0].pValue = FixedInputData;
+ dataParams[0].ulValueLen = FixedInputData_len;
+
+ dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE;
+ dataParams[1].pValue = &iterator;
+ dataParams[1].ulValueLen = sizeof(iterator);
+
+ dataParams_len = 2;
+ }
+ } else if (kdf.mechanism == CKM_SP800_108_FEEDBACK_KDF || kdf.mechanism == CKM_SP800_108_DOUBLE_PIPELINE_KDF) {
+ /* When counter_bitlen != 0, we have an optional counter. */
+ if (counter_bitlen != 0) {
+ iterator.ulWidthInBits = counter_bitlen;
+
+ if (ctr_location == 0 || ctr_location > 3) {
+ fprintf(stderr, "Expected ctr_location != 0 for Counter Mode KDF but got 0.\n");
+ goto done;
+ } else if (ctr_location == 1) {
+ /* Counter before */
+ dataParams[0].type = CK_SP800_108_OPTIONAL_COUNTER;
+ dataParams[0].pValue = &iterator;
+ dataParams[0].ulValueLen = sizeof(iterator);
+
+ dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE;
+ dataParams[1].pValue = NULL;
+ dataParams[1].ulValueLen = 0;
+
+ dataParams[2].type = CK_SP800_108_BYTE_ARRAY;
+ dataParams[2].pValue = FixedInputData;
+ dataParams[2].ulValueLen = FixedInputData_len;
+
+ dataParams_len = 3;
+ } else if (ctr_location == 2) {
+ /* Counter between */
+ dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
+ dataParams[0].pValue = NULL;
+ dataParams[0].ulValueLen = 0;
+
+ dataParams[1].type = CK_SP800_108_OPTIONAL_COUNTER;
+ dataParams[1].pValue = &iterator;
+ dataParams[1].ulValueLen = sizeof(iterator);
+
+ dataParams[2].type = CK_SP800_108_BYTE_ARRAY;
+ dataParams[2].pValue = FixedInputData;
+ dataParams[2].ulValueLen = FixedInputData_len;
+
+ dataParams_len = 3;
+ } else {
+ /* Counter after */
+ dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
+ dataParams[0].pValue = NULL;
+ dataParams[0].ulValueLen = 0;
+
+ dataParams[1].type = CK_SP800_108_BYTE_ARRAY;
+ dataParams[1].pValue = FixedInputData;
+ dataParams[1].ulValueLen = FixedInputData_len;
+
+ dataParams[2].type = CK_SP800_108_OPTIONAL_COUNTER;
+ dataParams[2].pValue = &iterator;
+ dataParams[2].ulValueLen = sizeof(iterator);
+
+ dataParams_len = 3;
+ }
+ } else {
+ dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE;
+ dataParams[0].pValue = NULL;
+ dataParams[0].ulValueLen = 0;
+
+ dataParams[1].type = CK_SP800_108_BYTE_ARRAY;
+ dataParams[1].pValue = FixedInputData;
+ dataParams[1].ulValueLen = FixedInputData_len;
+
+ dataParams_len = 2;
+ }
+ }
+
+ if (kdf.mechanism != CKM_SP800_108_FEEDBACK_KDF) {
+ kdfParams.prfType = prf_mech;
+ kdfParams.ulNumberOfDataParams = dataParams_len;
+ kdfParams.pDataParams = dataParams;
+
+ kdf.pParameter = &kdfParams;
+ kdf.ulParameterLen = sizeof(kdfParams);
+ } else {
+ feedbackParams.prfType = prf_mech;
+ feedbackParams.ulNumberOfDataParams = dataParams_len;
+ feedbackParams.pDataParams = dataParams;
+ feedbackParams.ulIVLen = IV_len;
+ if (IV_len == 0) {
+ feedbackParams.pIV = NULL;
+ } else {
+ feedbackParams.pIV = IV;
+ }
+
+ kdf.pParameter = &feedbackParams;
+ kdf.ulParameterLen = sizeof(feedbackParams);
+ }
+
+ crv = NSC_DeriveKey(session, &kdf, prf_key, derive_template, derive_template_count, &derived_key);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_DeriveKey(derived_key) failed crv=0x%x\n", (unsigned int)crv);
+ goto done;
+ }
+
+ crv = NSC_GetAttributeValue(session, derived_key, &output_key, 1);
+ if (crv != CKR_OK) {
+ fprintf(stderr, "NSC_GetAttribute(derived_value) failed crv=0x%x\n", (unsigned int)crv);
+ goto done;
+ }
+
+ fputs("KO = ", kbkdf_resp);
+ to_hex_str(buf, KO, output_key.ulValueLen);
+ fputs(buf, kbkdf_resp);
+ fputs("\r\n", kbkdf_resp);
+
+ continue;
+ }
+ }
+
+done:
+ if (kbkdf_req != NULL) {
+ fclose(kbkdf_req);
+ }
+ if (kbkdf_resp != stdout && kbkdf_resp != NULL) {
+ fclose(kbkdf_resp);
+ }
+
+ return;
+}
+
+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]);
+ }
+ /*************/
+ /* 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]);
+ }
+ /*************/
+ /* ECDH */
+ /*************/
+ } else if (strcmp(argv[1], "ecdh") == 0) {
+ /* argv[2]={init|resp}-{func|verify} argv[3]=<test name>.req */
+ if (strcmp(argv[2], "init-func") == 0) {
+ ecdh_functional(argv[3], 0);
+ } else if (strcmp(argv[2], "resp-func") == 0) {
+ ecdh_functional(argv[3], 1);
+ } else if (strcmp(argv[2], "init-verify") == 0) {
+ ecdh_verify(argv[3], 0);
+ } else if (strcmp(argv[2], "resp-verify") == 0) {
+ ecdh_verify(argv[3], 1);
+ }
+ /*************/
+ /* DH */
+ /*************/
+ } else if (strcmp(argv[1], "dh") == 0) {
+ /* argv[2]={init|resp}-{func|verify} argv[3]=<test name>.req */
+ if (strcmp(argv[2], "init-func") == 0) {
+ dh_functional(argv[3], 0);
+ } else if (strcmp(argv[2], "resp-func") == 0) {
+ dh_functional(argv[3], 1);
+ } else if (strcmp(argv[2], "init-verify") == 0) {
+ dh_verify(argv[3], 0);
+ } else if (strcmp(argv[2], "resp-verify") == 0) {
+ dh_verify(argv[3], 1);
+ }
+ /*************/
+ /* 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]);
+ } else if (strcmp(argv[1], "tls") == 0) {
+ tls(argv[2]);
+ } else if (strcmp(argv[1], "ikev1") == 0) {
+ ikev1(argv[2]);
+ } else if (strcmp(argv[1], "ikev1-psk") == 0) {
+ ikev1_psk(argv[2]);
+ } else if (strcmp(argv[1], "ikev2") == 0) {
+ ikev2(argv[2]);
+ } else if (strcmp(argv[1], "kbkdf") == 0) {
+ kbkdf(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 0000000000..41024ca7b8
--- /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/manifest.mn b/security/nss/cmd/fipstest/manifest.mn
new file mode 100644
index 0000000000..6e93f4ba48
--- /dev/null
+++ b/security/nss/cmd/fipstest/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
+
+PROGRAM = fipstest
+
+USE_STATIC_LIBS = 1
+
+CSRCS = \
+ fipstest.c \
+ $(NULL)
+
diff --git a/security/nss/cmd/httpserv/Makefile b/security/nss/cmd/httpserv/Makefile
new file mode 100644
index 0000000000..7b74b369c7
--- /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 0000000000..99e433cfb1
--- /dev/null
+++ b/security/nss/cmd/httpserv/httpserv.c
@@ -0,0 +1,1447 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_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 = PR_FALSE;
+
+ 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);
+ arena = NULL;
+ }
+ if (!request || !request->tbsRequest ||
+ !request->tbsRequest->requestList ||
+ !request->tbsRequest->requestList[0]) {
+ snprintf(msgBuf, sizeof(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();
+ CERTOCSPSingleResponse *sr;
+ CERTOCSPSingleResponse **singleResponses;
+ SECItem *ocspResponse;
+
+ PORT_Assert(!arena);
+ 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) {
+ snprintf(msgBuf, sizeof(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 */
+ snprintf(msgBuf, sizeof(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) {
+ snprintf(msgBuf, sizeof(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_htonl(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;
+ 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) {
+ caRevoIter = &caRevoInfos->link;
+ do {
+ 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 0000000000..0067066686
--- /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 0000000000..e969661103
--- /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 0000000000..b1f9d1a31e
--- /dev/null
+++ b/security/nss/cmd/lib/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). #
+#######################################################################
+
+
+
diff --git a/security/nss/cmd/lib/basicutil.c b/security/nss/cmd/lib/basicutil.c
new file mode 100644
index 0000000000..3ccacd7356
--- /dev/null
+++ b/security/nss/cmd/lib/basicutil.c
@@ -0,0 +1,868 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 <stddef.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+
+#include "secoid.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 errLenInt = PR_GetErrorTextLength();
+ size_t errLen = errLenInt < 0 ? 0 : (size_t)errLenInt;
+ 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) {
+ snprintf(dst, 3, "%02x", *src++);
+ }
+ }
+}
+
+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;
+}
+
+SECItem *
+SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
+{
+ int i = 0;
+ int byteval = 0;
+ int tmp = PORT_Strlen(str);
+
+ 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 {
+ if (!arena) {
+ SECITEM_FreeItem(item, PR_FALSE);
+ }
+ return NULL;
+ }
+
+ byteval = byteval * 16 + tmp;
+ if ((i % 2) != 0) {
+ item->data[i / 2] = byteval;
+ byteval = 0;
+ }
+ i++;
+ }
+
+ return item;
+}
+
+/* mapping between ECCurveName enum and SECOidTags */
+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 */
+};
+
+SECStatus
+SECU_ecName2params(ECCurveName curve, SECItem *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;
+ }
+
+ if (SECITEM_AllocItem(NULL, params, (2 + oidData->oid.len)) == NULL) {
+ return SECFailure;
+ }
+ /*
+ * 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;
+}
diff --git a/security/nss/cmd/lib/basicutil.h b/security/nss/cmd/lib/basicutil.h
new file mode 100644
index 0000000000..ba76b1798f
--- /dev/null
+++ b/security/nss/cmd/lib/basicutil.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 _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 "ecl-exp.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);
+
+/* Dump contents of private key */
+extern int SECU_PrintPrivateKey(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);
+
+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);
+
+/*
+** Read a hex string into a SecItem.
+*/
+extern SECItem *SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item,
+ const char *str);
+
+extern SECStatus SECU_ecName2params(ECCurveName curve, SECItem *params);
+
+/*
+ *
+ * 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);
+
+/*
+ *
+ * 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 0000000000..8cd1ebae08
--- /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/derprint.c b/security/nss/cmd/lib/derprint.c
new file mode 100644
index 0000000000..b86179e30a
--- /dev/null
+++ b/security/nss/cmd/lib/derprint.c
@@ -0,0 +1,596 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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"
+
+#include <stdint.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 > end || slen > (end - data)) {
+ 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 0000000000..f6b469397f
--- /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 0000000000..d1cbf67e28
--- /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 0000000000..c5835a8696
--- /dev/null
+++ b/security/nss/cmd/lib/lib.gyp
@@ -0,0 +1,37 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.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',
+ 'NSS_USE_STATIC_LIBS'
+ ]
+ },
+ '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 0000000000..86233e63d7
--- /dev/null
+++ b/security/nss/cmd/lib/manifest.mn
@@ -0,0 +1,42 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.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
+SHARED_LIBRARY = $(NULL)
+
+# 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
+
+USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/lib/moreoids.c b/security/nss/cmd/lib/moreoids.c
new file mode 100644
index 0000000000..ed5022cef2
--- /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 0000000000..06f7591394
--- /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_F_P, 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_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_NSS_DB, Attribute, None),
+ mkEntry2(CKA_NSS_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_AES_CMAC, Mechanism),
+ mkEntry(CKM_AES_CMAC_GENERAL, 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_NSS_PBE_SHA1_DES_CBC, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_40_BIT_RC4, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_128_BIT_RC4, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_HMAC_KEY_GEN, Mechanism),
+ mkEntry(CKM_NSS_PBE_MD5_HMAC_KEY_GEN, Mechanism),
+ mkEntry(CKM_NSS_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_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 0000000000..3dea8204d1
--- /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 0000000000..aaf45599d2
--- /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 0000000000..472bc2615b
--- /dev/null
+++ b/security/nss/cmd/lib/secpwd.c
@@ -0,0 +1,163 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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>
+#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
+
+#if !defined(_WINDOWS)
+static void
+echoOff(int fd)
+{
+ if (isatty(fd)) {
+ struct termios tio;
+ tcgetattr(fd, &tio);
+ tio.c_lflag &= ~ECHO;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+ }
+}
+
+static void
+echoOn(int fd)
+{
+ 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[500] = { '\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 0000000000..916dd8de79
--- /dev/null
+++ b/security/nss/cmd/lib/secutil.c
@@ -0,0 +1,4740 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 <stdio.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.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;
+
+/* The minimum password/pin length (in Unicode characters) in FIPS mode,
+ * defined in lib/softoken/pkcs11i.h. */
+#define FIPS_MIN_PIN 7
+
+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:
+ snprintf(prompt, sizeof(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:
+ snprintf(prompt, sizeof(prompt),
+ "Press Enter, then enter PIN for \"%s\" on external device.\n",
+ PK11_GetTokenName(slot));
+ char *pw = SECU_GetPasswordString(NULL, prompt);
+ PORT_Free(pw);
+ /* 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 */
+ if (PK11_IsFIPS()) {
+ PR_fprintf(PR_STDERR,
+ "Enter a password which will be used to encrypt your keys.\n"
+ "The password should be at least %d characters long,\n"
+ "and should consist of at least three character classes.\n"
+ "The available character classes are: digits (0-9), ASCII\n"
+ "lowercase letters, ASCII uppercase letters, ASCII\n"
+ "non-alphanumeric characters, and non-ASCII characters.\n\n"
+ "If an ASCII uppercase letter appears at the beginning of\n"
+ "the password, it is not counted toward its character class.\n"
+ "Similarly, if a digit appears at the end of the password,\n"
+ "it is not counted toward its character class.\n\n",
+ FIPS_MIN_PIN);
+ } else {
+ 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;
+ }
+ snprintf(sslDir, sizeof(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] == '/')
+ snprintf(path, sizeof(path), "%s%s", dir, filename);
+ else
+ snprintf(path, sizeof(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] == '/')
+ snprintf(buf, sizeof(buf), "%.900s%s", home, dir);
+ else
+ snprintf(buf, sizeof(buf), "%.900s/%s", home, dir);
+ } else {
+ snprintf(buf, sizeof(buf), "%.900s", base);
+ if (buf[strlen(buf) - 1] == '/')
+ buf[strlen(buf) - 1] = 0;
+ }
+
+ initted = PR_TRUE;
+ return buf;
+}
+
+SECStatus
+SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii,
+ PRBool warnOnPrivateKeyInAsciiFile)
+{
+ SECStatus rv;
+ if (ascii) {
+ /* First convert ascii to binary */
+ SECItem filedata;
+
+ /* Read in ascii data */
+ rv = SECU_FileToItem(&filedata, inFile);
+ if (rv != SECSuccess)
+ return rv;
+ if (!filedata.data) {
+ fprintf(stderr, "unable to read data from input file\n");
+ return SECFailure;
+ }
+ /* need one additional byte for zero terminator */
+ rv = SECITEM_ReallocItemV2(NULL, &filedata, filedata.len + 1);
+ if (rv != SECSuccess) {
+ PORT_Free(filedata.data);
+ return rv;
+ }
+ char *asc = (char *)filedata.data;
+ asc[filedata.len - 1] = '\0';
+
+ if (warnOnPrivateKeyInAsciiFile && strstr(asc, "PRIVATE KEY")) {
+ fprintf(stderr, "Warning: ignoring private key. Consider to use "
+ "pk12util.\n");
+ }
+
+ char *body;
+ /* 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 {
+ body = asc;
+ }
+
+ /* 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
+
+/*
+ * remove the tag and length and just leave the bare BER data
+ */
+SECStatus
+SECU_StripTagAndLength(SECItem *i)
+{
+ unsigned int start;
+ PRBool isIndefinite;
+
+ if (!i || !i->data || i->len < 2) { /* must be at least tag and length */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ isIndefinite = (i->data[1] == 0x80);
+ start = ((i->data[1] & 0x80) ? (i->data[1] & 0x7f) + 2 : 2);
+ if (i->len < start) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ i->data += start;
+ i->len -= start;
+ /* we are using indefinite encoding, drop the trailing zero */
+ if (isIndefinite) {
+ if (i->len <= 1) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ /* verify tags are zero */
+ if ((i->data[i->len - 1] != 0) || (i->data[i->len - 2] != 0)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ i->len -= 2;
+ }
+
+ return SECSuccess;
+}
+
+/*
+ * Create a new SECItem which points to the current BER tag and length with
+ * all it's data. For indefinite encoding, this will also include the trailing
+ * indefinite markers
+ * The 'in' item is advanced to point to the next BER tag.
+ * You don't want to use this in an actual BER/DER parser as NSS already
+ * has 3 to choose from)
+ */
+SECStatus
+SECU_ExtractBERAndStep(SECItem *in, SECItem *out)
+{
+ if (!in || !in->data || in->len < 2) { /* must be at least tag and length */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ *out = *in;
+
+ /* first handle indefinite encoding */
+ if (out->data[1] == 0x80) {
+ SECItem this = *out;
+ SECItem next;
+ this.data += 2;
+ this.len -= 2;
+ out->len = 2;
+ /* walk through all the entries until we find the '0' */
+ while ((this.len >= 2) && (this.data[0] != 0)) {
+ SECStatus rv = SECU_ExtractBERAndStep(&this, &next);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ out->len += next.len;
+ }
+ if ((this.len < 2) || ((this.data[0] != 0) && (this.data[1] != 0))) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ out->len += 2; /* include the trailing zeros */
+ in->data += out->len;
+ in->len -= out->len;
+ return SECSuccess;
+ }
+
+ /* now handle normal DER encoding */
+ if (out->data[1] & 0x80) {
+ unsigned int i;
+ unsigned int lenlen = out->data[1] & 0x7f;
+ unsigned int len = 0;
+ if (lenlen > sizeof out->len) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ for (i = 0; i < lenlen; i++) {
+ len = (len << 8) | out->data[2 + i];
+ }
+ out->len = len + lenlen + 2;
+ } else {
+ out->len = out->data[1] + 2;
+ }
+ if (out->len > in->len) {
+ /* we've ran into a truncated file */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ in->data += out->len;
+ in->len -= out->len;
+ 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;
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &tmp)) {
+ break;
+ }
+ 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 */
+SECOidTag
+SECU_PrintEncodedObjectID(FILE *out, const SECItem *i, const char *m, int level)
+{
+ SECItem my = *i;
+ SECOidTag tag = SEC_OID_UNKNOWN;
+ if (SECSuccess == SECU_StripTagAndLength(&my))
+ tag = SECU_PrintObjectID(out, &my, m, level);
+ return tag;
+}
+
+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 & 0xFF))
+ 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 (a->parameters.len == 0 ||
+ (a->parameters.len == 2 &&
+ PORT_Memcmp(a->parameters.data, "\005\000", 2) == 0)) {
+ /* No arguments or NULL argument */
+ } else if (algtag == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
+ secu_PrintRSAPSSParams(out, &a->parameters, "Parameters", level + 1);
+ } 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) {
+ snprintf(om, sizeof(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;
+ }
+ }
+ }
+ }
+}
+
+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;
+ curveOID.len = PR_MIN(curveOID.len, pk->u.ec.DEREncodedParams.len - 2);
+ SECU_PrintObjectID(out, &curveOID, "Curve", level + 1);
+ }
+}
+
+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;
+
+ case ecKey:
+ secu_PrintECPublicKey(out, pk, "EC Public Key", level + 1);
+ break;
+
+ 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 ch = *(chardata + i);
+
+ fprintf(out, "\\x%02x", ch);
+ }
+ 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;
+}
+
+/* sometimes a PRErrorCode, other times a SECStatus. Sigh. */
+int
+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;
+}
+
+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;
+}
+
+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 */
+typedef enum {
+ secuPKCS7Unknown = 0,
+ secuPKCS7PKCS12AuthSafe,
+ secuPKCS7PKCS12Safe
+} secuPKCS7State;
+
+static int
+secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, secuPKCS7State,
+ const char *, int);
+static int
+secu_PrintDERPKCS7ContentInfo(FILE *, SECItem *, secuPKCS7State,
+ const char *, int);
+
+/*
+** secu_PrintPKCS7EncContent
+** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
+*/
+static int
+secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
+ secuPKCS7State state, const 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);
+ return 0;
+}
+
+/*
+** secu_PrintRecipientInfo
+** Prints a PKCS7RecipientInfo type
+*/
+static void
+secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info,
+ const 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,
+ const 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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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,
+ secuPKCS7State state, 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) {
+ snprintf(om, sizeof(om), "Digest Algorithm (%x)", iv);
+ SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
+ }
+ }
+
+ /* Now for the content */
+ rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
+ state, "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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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 int
+secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
+ secuPKCS7State state, 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) {
+ snprintf(om, sizeof(om), "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ return secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
+ "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,
+ secuPKCS7State state, 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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(om), "Digest Algorithm (%x)", iv);
+ SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
+ }
+ }
+
+ rv = secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
+ "Encrypted Content Information", level + 1);
+ if (rv)
+ 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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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 int
+secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
+ secuPKCS7State state, const char *m, int level)
+{
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ return secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7Digested
+** Pretty print a PKCS7 digested data type (up to version 1).
+*/
+static int
+secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
+ secuPKCS7State state, 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, state,
+ "Content Information", level + 1);
+ SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
+ return 0;
+}
+
+static int
+secu_PrintPKCS12Attributes(FILE *out, SECItem *item, const char *m, int level)
+{
+ SECItem my = *item;
+ SECItem attribute;
+ SECItem attributeID;
+ SECItem attributeValues;
+
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SET)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ level++;
+
+ while (my.len) {
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &attribute)) {
+ return SECFailure;
+ }
+ if ((attribute.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&attribute)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ /* attribute ID */
+ if (SECSuccess != SECU_ExtractBERAndStep(&attribute, &attributeID)) {
+ return SECFailure;
+ }
+ if ((attributeID.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OBJECT_ID) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ SECU_PrintEncodedObjectID(out, &attributeID, "Attribute ID", level);
+
+ /* attribute values */
+ if (!attribute.len) { /* skip if there aren't any */
+ continue;
+ }
+ if (SECSuccess != SECU_ExtractBERAndStep(&attribute, &attributeValues)) {
+ return SECFailure;
+ }
+ if (SECSuccess != SECU_StripTagAndLength(&attributeValues)) {
+ return SECFailure;
+ }
+ while (attributeValues.len) {
+ SECItem tmp;
+ if (SECSuccess != SECU_ExtractBERAndStep(&attributeValues, &tmp)) {
+ return SECFailure;
+ }
+ SECU_PrintAny(out, &tmp, NULL, level + 1);
+ }
+ }
+ return SECSuccess;
+}
+
+static int
+secu_PrintPKCS12Bag(FILE *out, SECItem *item, const char *desc, int level)
+{
+ SECItem my = *item;
+ SECItem bagID;
+ SECItem bagValue;
+ SECItem bagAttributes;
+ SECOidTag bagTag;
+ SECStatus rv;
+ int i;
+ char *m;
+
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ /* bagId BAG-TYPE.&id ({PKCS12BagSet}) */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagID)) {
+ return SECFailure;
+ }
+ if ((bagID.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OBJECT_ID) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ m = PR_smprintf("%s ID", desc);
+ bagTag = SECU_PrintEncodedObjectID(out, &bagID, m ? m : "Bag ID", level);
+ if (m)
+ PR_smprintf_free(m);
+
+ /* bagValue [0] EXPLICIT BAG-TYPE.&type({PKCS12BagSet}{@bagID}) */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagValue)) {
+ return SECFailure;
+ }
+ if ((bagValue.data[0] & (SEC_ASN1_CLASS_MASK | SEC_ASN1_TAGNUM_MASK)) !=
+ (SEC_ASN1_CONTEXT_SPECIFIC | 0)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ if (SECSuccess != SECU_StripTagAndLength(&bagValue)) {
+ return SECFailure;
+ }
+
+ rv = SECSuccess;
+ switch (bagTag) {
+ case SEC_OID_PKCS12_V1_KEY_BAG_ID:
+ /* Future we need to print out raw private keys. Not a priority since
+ * p12util can't create files with unencrypted private keys, but
+ * some tools can and do */
+ SECU_PrintAny(out, &bagValue, "Private Key", level);
+ break;
+ case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
+ rv = SECU_PrintPrivateKey(out, &bagValue,
+ "Encrypted Private Key", level);
+ break;
+ case SEC_OID_PKCS12_V1_CERT_BAG_ID:
+ rv = secu_PrintPKCS12Bag(out, &bagValue, "Certificate Bag", level + 1);
+ break;
+ case SEC_OID_PKCS12_V1_CRL_BAG_ID:
+ rv = secu_PrintPKCS12Bag(out, &bagValue, "Crl Bag", level + 1);
+ break;
+ case SEC_OID_PKCS12_V1_SECRET_BAG_ID:
+ rv = secu_PrintPKCS12Bag(out, &bagValue, "Secret Bag", level + 1);
+ break;
+ /* from recursive call from CRL and certificate Bag */
+ case SEC_OID_PKCS9_X509_CRL:
+ case SEC_OID_PKCS9_X509_CERT:
+ case SEC_OID_PKCS9_SDSI_CERT:
+ /* unwrap the octect string */
+ rv = SECU_StripTagAndLength(&bagValue);
+ if (rv != SECSuccess) {
+ break;
+ }
+ /* fall through */
+ case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
+ case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
+ case SEC_OID_PKCS12_SDSI_CERT_BAG:
+ if (strcmp(desc, "Crl Bag") == 0) {
+ rv = SECU_PrintSignedData(out, &bagValue, NULL, level + 1,
+ (SECU_PPFunc)SECU_PrintCrl);
+ } else {
+ rv = SECU_PrintSignedData(out, &bagValue, NULL, level + 1,
+ (SECU_PPFunc)SECU_PrintCertificate);
+ }
+ break;
+ case SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID:
+ for (i = 1; my.len; i++) {
+ SECItem nextBag;
+ rv = SECU_ExtractBERAndStep(&bagValue, &nextBag);
+ if (rv != SECSuccess) {
+ break;
+ }
+ m = PR_smprintf("Nested Bag %d", i);
+ rv = secu_PrintPKCS12Bag(out, &nextBag,
+ m ? m : "Nested Bag", level + 1);
+ if (m)
+ PR_smprintf_free(m);
+ if (rv != SECSuccess) {
+ break;
+ }
+ }
+ break;
+ default:
+ m = PR_smprintf("%s Value", desc);
+ SECU_PrintAny(out, &bagValue, m ? m : "Bag Value", level);
+ if (m)
+ PR_smprintf_free(m);
+ }
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ /* bagAttributes SET OF PKCS12Attributes OPTIONAL */
+ if (my.len &&
+ (my.data[0] == (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SET))) {
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagAttributes)) {
+ return SECFailure;
+ }
+ m = PR_smprintf("%s Attributes", desc);
+ rv = secu_PrintPKCS12Attributes(out, &bagAttributes,
+ m ? m : "Bag Attributes", level);
+ if (m)
+ PR_smprintf_free(m);
+ }
+ return rv;
+}
+
+static int
+secu_PrintPKCS7Data(FILE *out, SECItem *item, secuPKCS7State state,
+ const char *desc, int level)
+{
+ SECItem my = *item;
+ SECItem nextbag;
+ int i;
+ SECStatus rv;
+
+ /* walk down each safe */
+ switch (state) {
+ case secuPKCS7PKCS12AuthSafe:
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ for (i = 1; my.len; i++) {
+ char *m;
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &nextbag)) {
+ return SECFailure;
+ }
+ m = PR_smprintf("Safe %d", i);
+ rv = secu_PrintDERPKCS7ContentInfo(out, &nextbag,
+ secuPKCS7PKCS12Safe,
+ m ? m : "Safe", level);
+ if (m)
+ PR_smprintf_free(m);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+ case secuPKCS7PKCS12Safe:
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ for (i = 1; my.len; i++) {
+ char *m;
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &nextbag)) {
+ return SECFailure;
+ }
+ m = PR_smprintf("Bag %d", i);
+ rv = secu_PrintPKCS12Bag(out, &nextbag,
+ m ? m : "Bag", level);
+ if (m)
+ PR_smprintf_free(m);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+ case secuPKCS7Unknown:
+ SECU_PrintAsHex(out, item, desc, level);
+ break;
+ }
+ return SECSuccess;
+}
+
+/*
+** secu_PrintPKCS7ContentInfo
+** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
+** appropriate function
+*/
+static int
+secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
+ secuPKCS7State state, const 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_UNKNOWN;
+ } 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,
+ state, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
+ rv = secu_PrintPKCS7Enveloped(out, src->content.envelopedData,
+ state, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
+ rv = secu_PrintPKCS7SignedAndEnveloped(out,
+ src->content.signedAndEnvelopedData,
+ state, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
+ rv = secu_PrintPKCS7Digested(out, src->content.digestedData,
+ state, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
+ rv = secu_PrintPKCS7Encrypted(out, src->content.encryptedData,
+ state, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_DATA:
+ rv = secu_PrintPKCS7Data(out, src->content.data, state, 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).
+*/
+static int
+secu_PrintDERPKCS7ContentInfo(FILE *out, SECItem *der, secuPKCS7State state,
+ const 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, state, m, level);
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ } else {
+ rv = -1;
+ }
+
+ return rv;
+}
+
+int
+SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
+{
+ return secu_PrintDERPKCS7ContentInfo(out, der, secuPKCS7Unknown, m, level);
+}
+
+/*
+** 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 signatureOption)
+{
+ 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 (signatureOption == 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;
+ PK11SlotList *slotList;
+ PRBool falseAttributeFound = PR_FALSE;
+ PRBool trueAttributeFound = PR_FALSE;
+ const char *moz_policy_ca_info = NULL;
+
+ 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);
+ }
+
+ slotList = PK11_GetAllSlotsForCert(cert, NULL);
+ if (slotList) {
+ PK11SlotListElement *se = PK11_GetFirstSafe(slotList);
+ for (; se; se = PK11_GetNextSafe(slotList, se, PR_FALSE)) {
+ CK_OBJECT_HANDLE handle = PK11_FindCertInSlot(se->slot, cert, NULL);
+ if (handle != CK_INVALID_HANDLE) {
+ PORT_SetError(0);
+ if (PK11_HasAttributeSet(se->slot, handle,
+ CKA_NSS_MOZILLA_CA_POLICY, PR_FALSE)) {
+ trueAttributeFound = PR_TRUE;
+ } else if (!PORT_GetError()) {
+ falseAttributeFound = PR_TRUE;
+ }
+ }
+ }
+ PK11_FreeSlotList(slotList);
+ }
+
+ if (trueAttributeFound) {
+ moz_policy_ca_info = "true (attribute present)";
+ } else if (falseAttributeFound) {
+ moz_policy_ca_info = "false (attribute present)";
+ } else {
+ moz_policy_ca_info = "false (attribute missing)";
+ }
+ SECU_Indent(stdout, 1);
+ printf("Mozilla-CA-Policy: %s\n", moz_policy_ca_info);
+
+ 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);
+ }
+
+ /* The distrust fields are hard-coded in nssckbi and read-only.
+ * If verifying some cert, with vfychain, for instance, the certificate may
+ * not have a defined slot if not imported. */
+ if (cert->slot != NULL && cert->distrust != NULL) {
+ const unsigned int kDistrustFieldSize = 13;
+ fprintf(stdout, "\n");
+ SECU_Indent(stdout, 1);
+ fprintf(stdout, "%s:\n", "Certificate Distrust Dates");
+ if (cert->distrust->serverDistrustAfter.len == kDistrustFieldSize) {
+ SECU_PrintTimeChoice(stdout,
+ &cert->distrust->serverDistrustAfter,
+ "Server Distrust After", 2);
+ }
+ if (cert->distrust->emailDistrustAfter.len == kDistrustFieldSize) {
+ SECU_PrintTimeChoice(stdout,
+ &cert->distrust->emailDistrustAfter,
+ "E-mail Distrust After", 2);
+ }
+ }
+
+ 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;
+}
+
+/*
+ * 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_FindCertByNicknameOrEmailAddrCX(handle, name, pwarg);
+ 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;
+}
+
+static 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;
+ }
+ }
+ if (PL_strlen(name) == 11) {
+ if (!strncmp(name, "xyber768d00", 11)) {
+ return ssl_grp_kem_xyber768d00;
+ }
+ }
+
+ return ssl_grp_none;
+}
+
+static SECStatus
+countItems(const char *arg, unsigned int *numItems)
+{
+ char *str = PORT_Strdup(arg);
+ if (!str) {
+ return SECFailure;
+ }
+ char *p = strtok(str, ",");
+ while (p) {
+ ++(*numItems);
+ p = strtok(NULL, ",");
+ }
+ PORT_Free(str);
+ str = NULL;
+ return SECSuccess;
+}
+
+SECStatus
+parseGroupList(const char *arg, SSLNamedGroup **enabledGroups,
+ unsigned int *enabledGroupsCount)
+{
+ SSLNamedGroup *groups;
+ char *str;
+ char *p;
+ unsigned int numValues = 0;
+ unsigned int count = 0;
+
+ if (countItems(arg, &numValues) != SECSuccess) {
+ return SECFailure;
+ }
+ groups = PORT_ZNewArray(SSLNamedGroup, numValues);
+ if (!groups) {
+ return SECFailure;
+ }
+
+ /* 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:
+ PORT_Free(str);
+ if (!count) {
+ PORT_Free(groups);
+ return SECFailure;
+ }
+
+ *enabledGroupsCount = count;
+ *enabledGroups = groups;
+ return SECSuccess;
+}
+
+SSLSignatureScheme
+schemeNameToScheme(const char *name)
+{
+#define compareScheme(x) \
+ do { \
+ if (!PORT_Strncmp(name, #x, PORT_Strlen(#x))) { \
+ return ssl_sig_##x; \
+ } \
+ } while (0)
+
+ compareScheme(rsa_pkcs1_sha1);
+ compareScheme(rsa_pkcs1_sha256);
+ compareScheme(rsa_pkcs1_sha384);
+ compareScheme(rsa_pkcs1_sha512);
+ compareScheme(ecdsa_sha1);
+ compareScheme(ecdsa_secp256r1_sha256);
+ compareScheme(ecdsa_secp384r1_sha384);
+ compareScheme(ecdsa_secp521r1_sha512);
+ compareScheme(rsa_pss_rsae_sha256);
+ compareScheme(rsa_pss_rsae_sha384);
+ compareScheme(rsa_pss_rsae_sha512);
+ compareScheme(ed25519);
+ compareScheme(ed448);
+ compareScheme(rsa_pss_pss_sha256);
+ compareScheme(rsa_pss_pss_sha384);
+ compareScheme(rsa_pss_pss_sha512);
+ compareScheme(dsa_sha1);
+ compareScheme(dsa_sha256);
+ compareScheme(dsa_sha384);
+ compareScheme(dsa_sha512);
+
+#undef compareScheme
+
+ return ssl_sig_none;
+}
+
+SECStatus
+parseSigSchemeList(const char *arg, const SSLSignatureScheme **enabledSigSchemes,
+ unsigned int *enabledSigSchemeCount)
+{
+ SSLSignatureScheme *schemes;
+ unsigned int numValues = 0;
+ unsigned int count = 0;
+
+ if (countItems(arg, &numValues) != SECSuccess) {
+ return SECFailure;
+ }
+ schemes = PORT_ZNewArray(SSLSignatureScheme, numValues);
+ if (!schemes) {
+ return SECFailure;
+ }
+
+ /* Get group names. */
+ char *str = PORT_Strdup(arg);
+ if (!str) {
+ goto done;
+ }
+ char *p = strtok(str, ",");
+ while (p) {
+ SSLSignatureScheme scheme = schemeNameToScheme(p);
+ if (scheme == ssl_sig_none) {
+ count = 0;
+ goto done;
+ }
+ schemes[count++] = scheme;
+ p = strtok(NULL, ",");
+ }
+
+done:
+ PORT_Free(str);
+ if (!count) {
+ PORT_Free(schemes);
+ return SECFailure;
+ }
+
+ *enabledSigSchemeCount = count;
+ *enabledSigSchemes = schemes;
+ return SECSuccess;
+}
+
+/* Parse the exporter spec in the form: LABEL[:OUTPUT-LENGTH[:CONTEXT]] */
+static SECStatus
+parseExporter(const char *arg,
+ secuExporter *exporter)
+{
+ SECStatus rv = SECSuccess;
+
+ char *str = PORT_Strdup(arg);
+ if (!str) {
+ rv = SECFailure;
+ goto done;
+ }
+
+ char *labelEnd = strchr(str, ':');
+ if (labelEnd) {
+ *labelEnd = '\0';
+ labelEnd++;
+
+ /* To extract CONTEXT, first skip OUTPUT-LENGTH */
+ char *outputEnd = strchr(labelEnd, ':');
+ if (outputEnd) {
+ *outputEnd = '\0';
+ outputEnd++;
+
+ exporter->hasContext = PR_TRUE;
+ exporter->context.data = (unsigned char *)PORT_Strdup(outputEnd);
+ exporter->context.len = strlen(outputEnd);
+ if (PORT_Strncasecmp((char *)exporter->context.data, "0x", 2) == 0) {
+ rv = SECU_SECItemHexStringToBinary(&exporter->context);
+ if (rv != SECSuccess) {
+ goto done;
+ }
+ }
+ }
+ }
+
+ if (labelEnd && *labelEnd != '\0') {
+ long int outputLength = strtol(labelEnd, NULL, 10);
+ if (!(outputLength > 0 && outputLength <= UINT_MAX)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+ goto done;
+ }
+ exporter->outputLength = outputLength;
+ } else {
+ exporter->outputLength = 20;
+ }
+
+ char *label = PORT_Strdup(str);
+ exporter->label.data = (unsigned char *)label;
+ exporter->label.len = strlen(label);
+ if (PORT_Strncasecmp((char *)exporter->label.data, "0x", 2) == 0) {
+ rv = SECU_SECItemHexStringToBinary(&exporter->label);
+ if (rv != SECSuccess) {
+ goto done;
+ }
+ }
+
+done:
+ PORT_Free(str);
+
+ return rv;
+}
+
+SECStatus
+parseExporters(const char *arg,
+ const secuExporter **enabledExporters,
+ unsigned int *enabledExporterCount)
+{
+ secuExporter *exporters;
+ unsigned int numValues = 0;
+ unsigned int count = 0;
+
+ if (countItems(arg, &numValues) != SECSuccess) {
+ return SECFailure;
+ }
+ exporters = PORT_ZNewArray(secuExporter, numValues);
+ if (!exporters) {
+ return SECFailure;
+ }
+
+ /* Get exporter definitions. */
+ char *str = PORT_Strdup(arg);
+ if (!str) {
+ goto done;
+ }
+ char *p = strtok(str, ",");
+ while (p) {
+ SECStatus rv = parseExporter(p, &exporters[count++]);
+ if (rv != SECSuccess) {
+ count = 0;
+ goto done;
+ }
+ p = strtok(NULL, ",");
+ }
+
+done:
+ PORT_Free(str);
+ if (!count) {
+ PORT_Free(exporters);
+ return SECFailure;
+ }
+
+ *enabledExporterCount = count;
+ *enabledExporters = exporters;
+ return SECSuccess;
+}
+
+static SECStatus
+exportKeyingMaterial(PRFileDesc *fd, const secuExporter *exporter)
+{
+ SECStatus rv = SECSuccess;
+ unsigned char *out = PORT_Alloc(exporter->outputLength);
+
+ if (!out) {
+ fprintf(stderr, "Unable to allocate buffer for keying material\n");
+ return SECFailure;
+ }
+ rv = SSL_ExportKeyingMaterial(fd,
+ (char *)exporter->label.data,
+ exporter->label.len,
+ exporter->hasContext,
+ exporter->context.data,
+ exporter->context.len,
+ out,
+ exporter->outputLength);
+ if (rv != SECSuccess) {
+ goto done;
+ }
+ fprintf(stdout, "Exported Keying Material:\n");
+ secu_PrintRawString(stdout, (SECItem *)&exporter->label, "Label", 1);
+ if (exporter->hasContext) {
+ SECU_PrintAsHex(stdout, &exporter->context, "Context", 1);
+ }
+ SECU_Indent(stdout, 1);
+ fprintf(stdout, "Length: %u\n", exporter->outputLength);
+ SECItem temp = { siBuffer, out, exporter->outputLength };
+ SECU_PrintAsHex(stdout, &temp, "Keying Material", 1);
+
+done:
+ PORT_Free(out);
+ return rv;
+}
+
+SECStatus
+exportKeyingMaterials(PRFileDesc *fd,
+ const secuExporter *exporters,
+ unsigned int exporterCount)
+{
+ unsigned int i;
+
+ for (i = 0; i < exporterCount; i++) {
+ SECStatus rv = exportKeyingMaterial(fd, &exporters[i]);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ }
+
+ return SECSuccess;
+}
+
+SECStatus
+readPSK(const char *arg, SECItem *psk, SECItem *label)
+{
+ SECStatus rv = SECFailure;
+ char *str = PORT_Strdup(arg);
+ if (!str) {
+ goto cleanup;
+ }
+
+ char *pskBytes = strtok(str, ":");
+ if (!pskBytes) {
+ goto cleanup;
+ }
+ if (PORT_Strncasecmp(pskBytes, "0x", 2) != 0) {
+ goto cleanup;
+ }
+
+ psk = SECU_HexString2SECItem(NULL, psk, &pskBytes[2]);
+ if (!psk || !psk->data || psk->len != strlen(&str[2]) / 2) {
+ goto cleanup;
+ }
+
+ SECItem labelItem = { siBuffer, NULL, 0 };
+ char *inLabel = strtok(NULL, ":");
+ if (inLabel) {
+ labelItem.data = (unsigned char *)PORT_Strdup(inLabel);
+ if (!labelItem.data) {
+ goto cleanup;
+ }
+ labelItem.len = strlen(inLabel);
+
+ if (PORT_Strncasecmp(inLabel, "0x", 2) == 0) {
+ rv = SECU_SECItemHexStringToBinary(&labelItem);
+ if (rv != SECSuccess) {
+ SECITEM_FreeItem(&labelItem, PR_FALSE);
+ goto cleanup;
+ }
+ }
+ rv = SECSuccess;
+ } else {
+ PRUint8 defaultLabel[] = { 'C', 'l', 'i', 'e', 'n', 't', '_',
+ 'i', 'd', 'e', 'n', 't', 'i', 't', 'y' };
+ SECItem src = { siBuffer, defaultLabel, sizeof(defaultLabel) };
+ rv = SECITEM_CopyItem(NULL, &labelItem, &src);
+ }
+ if (rv == SECSuccess) {
+ *label = labelItem;
+ }
+
+cleanup:
+ PORT_Free(str);
+ return rv;
+}
+
+static SECStatus
+secu_PrintPKCS12DigestInfo(FILE *out, const SECItem *t, char *m, int level)
+{
+ SECItem my = *t;
+ SECItem rawDigestAlgID;
+ SECItem digestData;
+ SECStatus rv;
+ PLArenaPool *arena;
+ SECAlgorithmID digestAlgID;
+ char *mAlgID = NULL;
+ char *mDigest = NULL;
+
+ /* strip the outer sequence */
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ /* get the algorithm ID */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &rawDigestAlgID)) {
+ return SECFailure;
+ }
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ return SECFailure;
+ }
+#define DIGEST_ALGID_STRING "Digest Algorithm ID"
+ if (m)
+ mAlgID = PR_smprintf("%s " DIGEST_ALGID_STRING, m);
+ rv = SEC_QuickDERDecodeItem(arena, &digestAlgID,
+ SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
+ &rawDigestAlgID);
+ if (rv == SECSuccess) {
+ SECU_PrintAlgorithmID(out, &digestAlgID,
+ mAlgID ? mAlgID : DIGEST_ALGID_STRING, level);
+ }
+ if (mAlgID)
+ PR_smprintf_free(mAlgID);
+ PORT_FreeArena(arena, PR_FALSE);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ /* get the mac data */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &digestData)) {
+ return SECFailure;
+ }
+ if ((digestData.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OCTET_STRING) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+#define DIGEST_STRING "Digest"
+ if (m)
+ mDigest = PR_smprintf("%s " DIGEST_STRING, m);
+ secu_PrintOctetString(out, &digestData,
+ mDigest ? mDigest : DIGEST_STRING, level);
+ if (mDigest)
+ PR_smprintf_free(mDigest);
+ return SECSuccess;
+}
+
+static SECStatus
+secu_PrintPKCS12MacData(FILE *out, const SECItem *t, char *m, int level)
+{
+ SECItem my = *t;
+ SECItem hash;
+ SECItem salt;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s: \n", m);
+ level++;
+ }
+
+ /* strip the outer sequence */
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &hash)) {
+ return SECFailure;
+ }
+ if (SECSuccess != secu_PrintPKCS12DigestInfo(out, &hash, "Mac", level)) {
+ return SECFailure;
+ }
+
+ /* handle the salt */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &salt)) {
+ return SECFailure;
+ ;
+ }
+ if ((salt.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OCTET_STRING) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ secu_PrintOctetString(out, &salt, "Mac Salt", level);
+
+ if (my.len &&
+ ((my.data[0] & SEC_ASN1_TAGNUM_MASK) == SEC_ASN1_INTEGER)) {
+ SECItem iterator;
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &iterator)) {
+ return SECFailure;
+ }
+ SECU_PrintEncodedInteger(out, &iterator, "Iterations", level);
+ }
+ return SECSuccess;
+}
+
+SECStatus
+SECU_PrintPKCS12(FILE *out, const SECItem *t, char *m, int level)
+{
+ SECItem my = *t;
+ SECItem authSafe;
+ SECItem macData;
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ level++;
+
+ /* strip the outer sequence */
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ /* print and remove the optional version number */
+ if (my.len && ((my.data[0] & SEC_ASN1_TAGNUM_MASK) == SEC_ASN1_INTEGER)) {
+ SECItem version;
+
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &version)) {
+ return SECFailure;
+ }
+ SECU_PrintEncodedInteger(out, &version, "Version", level);
+ }
+
+ /* print the authSafe */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &authSafe)) {
+ return SECFailure;
+ }
+ if (SECSuccess != secu_PrintDERPKCS7ContentInfo(out, &authSafe,
+ secuPKCS7PKCS12AuthSafe,
+ "AuthSafe", level)) {
+ return SECFailure;
+ }
+
+ /* print the mac data (optional) */
+ if (!my.len) {
+ return SECSuccess;
+ }
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &macData)) {
+ return SECFailure;
+ }
+ if (SECSuccess != secu_PrintPKCS12MacData(out, &macData,
+ "Mac Data", level)) {
+ return SECFailure;
+ }
+
+ if (my.len) {
+ fprintf(out, "Unknown extra data found \n");
+ }
+ return SECSuccess;
+}
diff --git a/security/nss/cmd/lib/secutil.h b/security/nss/cmd/lib/secutil.h
new file mode 100644
index 0000000000..b5f86ad061
--- /dev/null
+++ b/security/nss/cmd/lib/secutil.h
@@ -0,0 +1,450 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 "keyhi.h"
+#include "secpkcs7.h"
+#include "secasn1.h"
+#include "secder.h"
+#include <stdio.h>
+
+#include "basicutil.h"
+#include "sslerr.h"
+#include "sslt.h"
+#include "blapi.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_PKCS12 "pkcs12"
+#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);
+
+/* Dump contents of private key */
+extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level);
+
+/* 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);
+/* Pretty-print a pkcs12 file */
+extern SECStatus SECU_PrintPKCS12(FILE *out, const 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);
+
+SECStatus parseGroupList(const char *arg, SSLNamedGroup **enabledGroups,
+ unsigned int *enabledGroupsCount);
+SECStatus parseSigSchemeList(const char *arg,
+ const SSLSignatureScheme **enabledSigSchemes,
+ unsigned int *enabledSigSchemeCount);
+typedef struct {
+ SECItem label;
+ PRBool hasContext;
+ SECItem context;
+ unsigned int outputLength;
+} secuExporter;
+
+SECStatus parseExporters(const char *arg,
+ const secuExporter **enabledExporters,
+ unsigned int *enabledExporterCount);
+
+SECStatus exportKeyingMaterials(PRFileDesc *fd,
+ const secuExporter *exporters,
+ unsigned int exporterCount);
+
+SECStatus readPSK(const char *arg, SECItem *psk, SECItem *label);
+
+/*
+ *
+ * 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 100644
index 0000000000..1de5ef2694
--- /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/manifest.mn b/security/nss/cmd/libpkix/manifest.mn
new file mode 100644
index 0000000000..4f232a5100
--- /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 100644
index 0000000000..3181547e2c
--- /dev/null
+++ b/security/nss/cmd/libpkix/perf/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 $(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 0000000000..4b8d438112
--- /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 100644
index 0000000000..f70040234a
--- /dev/null
+++ b/security/nss/cmd/libpkix/perf/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+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 0000000000..202f128b61
--- /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 100644
index 0000000000..1de5ef2694
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/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/pkix/certsel/Makefile b/security/nss/cmd/libpkix/pkix/certsel/Makefile
new file mode 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/certsel/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 $(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 100644
index 0000000000..d9da6e1674
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/certsel/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+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 0000000000..1fde3739b8
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/certsel/test_certselector.c
@@ -0,0 +1,1677 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 0000000000..57f192a42f
--- /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 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/checker/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 $(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 100644
index 0000000000..54e1486e68
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/checker/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+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 0000000000..5fab3a6920
--- /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 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/crlsel/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 $(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 100644
index 0000000000..3b13298aa6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/crlsel/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+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 0000000000..fcc5ef5a33
--- /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 0000000000..f17406be5d
--- /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 100644
index 0000000000..895bf52b2b
--- /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 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/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 $(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 100644
index 0000000000..c7629a6207
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/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_procparams.c \
+ test_trustanchor.c \
+ test_valparams.c \
+ test_resourcelimits.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixtoolparams
+SHARED_LIBRARY = $(NULL)
+
+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 0000000000..419322a1e7
--- /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 0000000000..f52c3ef87f
--- /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 0000000000..4bd9d174ce
--- /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 0000000000..6419062c40
--- /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 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/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 $(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 100644
index 0000000000..7e4caeac60
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/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_buildresult.c \
+ test_policynode.c \
+ test_verifynode.c \
+ test_valresult.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixtoolresults
+SHARED_LIBRARY = $(NULL)
+
+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 0000000000..8b13e8eea6
--- /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 0000000000..38ac1d95e6
--- /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 0000000000..7760a431e3
--- /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 0000000000..21c61aa96c
--- /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 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/store/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 $(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 100644
index 0000000000..b939ffdcfd
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/store/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+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 0000000000..59606b8929
--- /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 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/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 $(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 100644
index 0000000000..8840204f7f
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+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 0000000000..e2743b343f
--- /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 0000000000..eba5153ac0
--- /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 0000000000..5c9ec5968b
--- /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 0000000000..4861a8e326
--- /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 0000000000..1b28435b01
--- /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 0000000000..43f06ec2ac
--- /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 0000000000..d2c667ae74
--- /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 0000000000..3ce4513177
--- /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 0000000000..e97e57096e
--- /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 0000000000..1318f13ba6
--- /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 0000000000..3f9711e691
--- /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 0000000000..98cb7b018c
--- /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 0000000000..ad73a5df76
--- /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 0000000000..480ec2643c
--- /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 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/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 $(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 100644
index 0000000000..c7790c401b
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/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_error.c \
+ test_list.c \
+ test_list2.c \
+ test_logger.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixtoolutil
+SHARED_LIBRARY = $(NULL)
+
+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 0000000000..9cddecc827
--- /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 0000000000..e5e6e507ba
--- /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 0000000000..b802ff0e66
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/test_list2.c
@@ -0,0 +1,118 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 0000000000..3b7e5160a3
--- /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 100644
index 0000000000..1de5ef2694
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/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/pkix_pl/manifest.mn b/security/nss/cmd/libpkix/pkix_pl/manifest.mn
new file mode 100644
index 0000000000..84997cbe6f
--- /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 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/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 $(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 100644
index 0000000000..50d20d0bb4
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+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 0000000000..37169d6ff7
--- /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 0000000000..ccd05a5bf8
--- /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 0000000000..62f86300ab
--- /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 0000000000..58fceb14f0
--- /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 0000000000..d43614a6b3
--- /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_htonl(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 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/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 $(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 100644
index 0000000000..15fae7bb5f
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+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 0000000000..156b440f9c
--- /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 0000000000..274f818ab3
--- /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 0000000000..6372c7a370
--- /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 0000000000..30a008b4cf
--- /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 0000000000..4fb3718c19
--- /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 0000000000..88181e3f20
--- /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 0000000000..636ba3ead3
--- /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 0000000000..8f2ff9ec7e
--- /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 0000000000..91ff63fd0a
--- /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 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/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 $(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 100644
index 0000000000..52bb34ece0
--- /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
+SHARED_LIBRARY = $(NULL)
+
+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 0000000000..839dc068d1
--- /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 0000000000..281e373790
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_bigint.c
@@ -0,0 +1,189 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 0000000000..402685b59d
--- /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 0000000000..663bfc9fac
--- /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 0000000000..3a4e5f7135
--- /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 0000000000..21974258f9
--- /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 0000000000..bb0e7a0246
--- /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 0000000000..197eba2b44
--- /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 0000000000..9f42f629b1
--- /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 0000000000..ebb691ba63
--- /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 0000000000..09cddaeea9
--- /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 0000000000..9c09d6479e
--- /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 0000000000..9b84f94d9c
--- /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 0000000000..c76d1e9ac8
--- /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 0000000000..2e1eb154f0
--- /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 0000000000..bbaf85c568
--- /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 0000000000..a2cfa73bd0
--- /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 0000000000..180e995aa1
--- /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 0000000000..158f458952
--- /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 100644
index 0000000000..daa8765778
--- /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 0000000000..38bf1d9f3a
--- /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 0000000000..6ff5f83779
--- /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 0000000000..642601409a
--- /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 100644
index 0000000000..32926cc1bb
--- /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 0000000000..1ccf364e0c
--- /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 100644
index 0000000000..cc9d235938
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/Makefile
@@ -0,0 +1,50 @@
+#! 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/testutil/config.mk b/security/nss/cmd/libpkix/testutil/config.mk
new file mode 100644
index 0000000000..f1f6674f90
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/config.mk
@@ -0,0 +1,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/.
+
+# don't build the static library
+LIBRARY =
+RES =
diff --git a/security/nss/cmd/libpkix/testutil/manifest.mn b/security/nss/cmd/libpkix/testutil/manifest.mn
new file mode 100644
index 0000000000..184085b1b1
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+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 0000000000..407d40a318
--- /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 0000000000..0f438ba430
--- /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 0000000000..9c594fa038
--- /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 0000000000..3417d0ab7c
--- /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 0000000000..e1f24af89d
--- /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 0000000000..6e1d4ecdfc
--- /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 0000000000..b49f2d8cf4
--- /dev/null
+++ b/security/nss/cmd/listsuites/listsuites.c
@@ -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/. */
+
+/* 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 "nss.h"
+#include "secport.h"
+#include "secutil.h"
+#include "ssl.h"
+
+int
+main(int argc, char **argv)
+{
+ const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
+ int i;
+ int errCount = 0;
+ SECStatus rv;
+ PRErrorCode err;
+ char *certDir = NULL;
+
+ /* load policy from $SSL_DIR/pkcs11.txt, for testing */
+ certDir = SECU_DefaultSSLDir();
+ if (certDir) {
+ rv = NSS_Init(certDir);
+ } else {
+ rv = NSS_NoDB_Init(NULL);
+ }
+ if (rv != SECSuccess) {
+ err = PR_GetError();
+ ++errCount;
+ fprintf(stderr, "NSS_Init failed: %s\n", PORT_ErrorToString(err));
+ goto out;
+ }
+
+ /* apply policy */
+ rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, 0);
+ if (rv != SECSuccess) {
+ err = PR_GetError();
+ ++errCount;
+ fprintf(stderr, "NSS_SetAlgorithmPolicy failed: %s\n",
+ PORT_ErrorToString(err));
+ goto out;
+ }
+
+ /* update the default cipher suites according to the policy */
+ rv = SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE);
+ if (rv != SECSuccess) {
+ err = PR_GetError();
+ ++errCount;
+ fprintf(stderr, "SSL_OptionSetDefault failed: %s\n",
+ PORT_ErrorToString(err));
+ goto out;
+ }
+
+ 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];
+ PRBool enabled;
+ 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" : "");
+ }
+
+out:
+ rv = NSS_Shutdown();
+ if (rv != SECSuccess) {
+ err = PR_GetError();
+ ++errCount;
+ fprintf(stderr, "NSS_Shutdown failed: %s\n", PORT_ErrorToString(err));
+ }
+
+ return errCount;
+}
diff --git a/security/nss/cmd/listsuites/listsuites.gyp b/security/nss/cmd/listsuites/listsuites.gyp
new file mode 100644
index 0000000000..51f8d8f6e9
--- /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 0000000000..3e78daceea
--- /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 0000000000..a9c64c1d53
--- /dev/null
+++ b/security/nss/cmd/lowhashtest/Makefile
@@ -0,0 +1,57 @@
+#! 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). #
+#######################################################################
+
+
+#######################################################################
+# (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) \
+ -lfreebl3 \
+ $(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 0000000000..6a980fbbf3
--- /dev/null
+++ b/security/nss/cmd/lowhashtest/lowhashtest.c
@@ -0,0 +1,501 @@
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+/* nss headers */
+#include "hasht.h"
+#include "nsslowhash.h"
+#include "secport.h"
+
+static char *progName = NULL;
+
+/* can't call NSPR or NSSUtil directly, so just include
+ * our own versions of SECU_ functions in basicutil.c.
+ * We need this test program to link without those functions
+ * so we can test that everyting works in a freebl only
+ * environment */
+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 */
+};
+
+static 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);
+ }
+}
+
+/* simple version o print error */
+static void
+SECU_PrintError(const char *prog, const char *string)
+{
+ fprintf(stderr, "%s: %s", prog, string);
+}
+
+/* simple version o print error */
+static void
+SECU_PrintError3(const char *prog, const char *string, const char *string2)
+{
+ fprintf(stderr, "%s: %s %s\n", prog, string, string2);
+}
+
+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)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);
+ assert(len == hashLen);
+ 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 };
+
+ 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 };
+
+ 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 };
+
+ 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 };
+
+ 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);
+ assert(len == hashLen);
+ 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()
+{
+ 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 < 2 || !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], "SHA256") == 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_PrintError3(progName, "Unsupported hash type", argv[0]);
+ Usage();
+ }
+
+ 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 0000000000..3b3e3c29cb
--- /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 0000000000..8f438704c1
--- /dev/null
+++ b/security/nss/cmd/lowhashtest/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/.
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+REQUIRES =
+
+INCLUDES += -I$(CORE_DEPTH)/nss/lib/freebl
+
+PROGRAM = lowhashtest
+
+CSRCS = \
+ lowhashtest.c \
+ $(NULL)
+
diff --git a/security/nss/cmd/makepqg/Makefile b/security/nss/cmd/makepqg/Makefile
new file mode 100644
index 0000000000..8b239d2f5e
--- /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 0000000000..edc023e483
--- /dev/null
+++ b/security/nss/cmd/makepqg/makepqg.c
@@ -0,0 +1,353 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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;
+ }
+
+ if (NSS_NoDB_Init(NULL) != SECSuccess) {
+ return 1;
+ }
+
+ 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);
+ if (NSS_Shutdown() != SECSuccess) {
+ return 1;
+ }
+ 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 0000000000..3ddc34afe4
--- /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 0000000000..f424410bfb
--- /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 0000000000..e2cdb028bd
--- /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 0000000000..06bb99f4f8
--- /dev/null
+++ b/security/nss/cmd/manifest.mn
@@ -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/.
+
+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) \
+ $(DBTOOL_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 \
+ certutil \
+ chktest \
+ crlutil \
+ crmftest \
+ dbtest \
+ derdump \
+ digest \
+ httpserv \
+ listsuites \
+ makepqg \
+ multinit \
+ nss-policy-check \
+ ocspclnt \
+ ocspresp \
+ oidcalc \
+ p7content \
+ p7env \
+ p7sign \
+ p7verify \
+ pk12util \
+ pk11importtest \
+ pk11ectest \
+ pk11gcmtest \
+ pk11mode \
+ pk1sign \
+ pp \
+ pwdecrypt \
+ rsaperf \
+ rsapoptst \
+ sdbthreadtst \
+ sdrtest \
+ selfserv \
+ signtool \
+ signver \
+ smimetools \
+ ssltap \
+ strsclnt \
+ symkeyutil \
+ tests \
+ tstclnt \
+ validation \
+ 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 0000000000..fc7b4b122b
--- /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 0000000000..12d192c9ff
--- /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 0000000000..33ed7bde7d
--- /dev/null
+++ b/security/nss/cmd/modutil/error.h
@@ -0,0 +1,142 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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,
+ INITPW_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",
+ "ERROR: Unable to set initial password on the database.\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,
+ P11_KIT_ENABLED_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 0000000000..d4ea73eda6
--- /dev/null
+++ b/security/nss/cmd/modutil/install-ds.c
@@ -0,0 +1,1522 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 pad_i; \
+ for (pad_i = 0; pad_i < (x); pad_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++) {
+ snprintf(buf, sizeof(buf), "%s.", _this->verString[i]);
+ strcat(tmp, buf);
+ }
+ if (i < _this->numDigits) {
+ snprintf(buf, sizeof(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);
+ 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 0000000000..70813f6030
--- /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 0000000000..91bcca928e
--- /dev/null
+++ b/security/nss/cmd/modutil/install.c
@@ -0,0 +1,941 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.
+ */
+
+#include <stdarg.h>
+
+static void
+error(PRErrorCode errcode, ...)
+{
+
+ va_list ap;
+ char *errstr;
+ Pk11Install_ErrorHandler handler;
+
+ if (!errorHandlerLock) {
+ errorHandlerLock = PR_NewLock();
+ }
+
+ PR_Lock(errorHandlerLock);
+
+ handler = errorHandler;
+
+ PR_Unlock(errorHandlerLock);
+
+ if (handler) {
+ va_start(ap, errcode);
+ errstr = PR_vsmprintf(errorString[errcode], ap);
+ 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) {
+ snprintf(filename, sizeof(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 0000000000..5d6d3eabaa
--- /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 0000000000..1d8e6cc473
--- /dev/null
+++ b/security/nss/cmd/modutil/installparse.c
@@ -0,0 +1,479 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 0000000000..2c02b57b65
--- /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 0000000000..71fb56101d
--- /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 0000000000..b6d701136a
--- /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 0000000000..95191e7292
--- /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 0000000000..7dcc1c295d
--- /dev/null
+++ b/security/nss/cmd/modutil/lex.Pk11Install_yy.c
@@ -0,0 +1,1600 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_VERSION__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC_VERSION__ */
+#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_VERSION__
+#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 0000000000..99b5f3f99c
--- /dev/null
+++ b/security/nss/cmd/modutil/manifest.mn
@@ -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/.
+
+CORE_DEPTH = ../..
+
+MODULE = sectools
+
+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 0000000000..f04ad3d925
--- /dev/null
+++ b/security/nss/cmd/modutil/modutil.c
@@ -0,0 +1,996 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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",
+ "\nWARNING: Manually adding a module while p11-kit is enabled could cause"
+ "\nduplicate module registration in your security database. It is suggested "
+ "\nto configure the module through p11-kit configuration file instead.\n"
+ "\nType 'q <enter>' to abort, or <enter> to continue: "
+};
+
+/* 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;
+ }
+
+ /* Warn if we are adding a module while p11-kit is enabled in the
+ * database. */
+ if ((command == ADD_COMMAND || command == RAW_ADD_COMMAND) &&
+ IsP11KitEnabled()) {
+ char* response;
+
+ PR_fprintf(PR_STDOUT, msgStrings[P11_KIT_ENABLED_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");
+ }
+
+ /* 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:
+ errcode = InitPW();
+ 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 0000000000..5d0f87a65c
--- /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 0000000000..1981fec7bc
--- /dev/null
+++ b/security/nss/cmd/modutil/modutil.h
@@ -0,0 +1,42 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 InitPW(void);
+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);
+PRBool IsP11KitEnabled(void);
+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 0000000000..6d17a33657
--- /dev/null
+++ b/security/nss/cmd/modutil/pk11.c
@@ -0,0 +1,1050 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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;
+}
+
+static PRBool
+IsP11KitProxyModule(SECMODModule *module)
+{
+ CK_INFO modinfo;
+ static const char p11KitManufacturerID[33] =
+ "PKCS#11 Kit ";
+ static const char p11KitLibraryDescription[33] =
+ "PKCS#11 Kit Proxy Module ";
+
+ if (PK11_GetModInfo(module, &modinfo) == SECSuccess &&
+ PORT_Memcmp(modinfo.manufacturerID,
+ p11KitManufacturerID,
+ sizeof(modinfo.manufacturerID)) == 0 &&
+ PORT_Memcmp(modinfo.libraryDescription,
+ p11KitLibraryDescription,
+ sizeof(modinfo.libraryDescription)) == 0) {
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+}
+
+PRBool
+IsP11KitEnabled(void)
+{
+ SECMODListLock *lock;
+ SECMODModuleList *mlp;
+ PRBool found = PR_FALSE;
+
+ lock = SECMOD_GetDefaultModuleListLock();
+ if (!lock) {
+ PR_fprintf(PR_STDERR, errStrings[NO_LIST_LOCK_ERR]);
+ return found;
+ }
+
+ SECMOD_GetReadLock(lock);
+
+ mlp = SECMOD_GetDefaultModuleList();
+ for (; mlp != NULL; mlp = mlp->next) {
+ if (IsP11KitProxyModule(mlp->module)) {
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ SECMOD_ReleaseReadLock(lock);
+ return found;
+}
+
+/**********************************************************************
+ *
+ * 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;
+ char *modUri;
+ 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);
+ }
+
+ modUri = PK11_GetModuleURI(module);
+ if (modUri) {
+ PR_fprintf(PR_STDOUT, "\t uri: %s\n", modUri);
+ PORT_Free(modUri);
+ }
+ 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];
+ char *tokenUri = PK11_GetTokenURI(slot);
+ 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));
+ PR_fprintf(PR_STDOUT, "\t uri: %s\n", tokenUri);
+ PORT_Free(tokenUri);
+ }
+ 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 size_t 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;
+ size_t reasonIdx;
+ 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)) {
+ reasonIdx = PK11_GetDisabledReason(slot);
+ if (reasonIdx < numDisableReasonStr) {
+ PR_fprintf(PR_STDOUT, PAD "Status: DISABLED (%s)\n",
+ disableReasonStr[reasonIdx]);
+ } 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;
+}
+
+/************************************************************************
+ *
+ * I n i t P W
+ */
+Error
+InitPW(void)
+{
+ PK11SlotInfo *slot;
+ Error ret = UNSPECIFIED_ERR;
+
+ slot = PK11_GetInternalKeySlot();
+ if (!slot) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_TOKEN_ERR], "internal");
+ return NO_SUCH_TOKEN_ERR;
+ }
+
+ /* Set the initial password to empty */
+ if (PK11_NeedUserInit(slot)) {
+ if (PK11_InitPin(slot, NULL, "") != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[INITPW_FAILED_ERR]);
+ ret = INITPW_FAILED_ERR;
+ goto loser;
+ }
+ }
+
+ ret = SUCCESS;
+
+loser:
+ PK11_FreeSlot(slot);
+
+ return ret;
+}
+
+/************************************************************************
+ *
+ * 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 if (PK11_NeedLogin(slot)) {
+ 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 0000000000..bb50b8f3e4
--- /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 0000000000..3ad6a97f1e
--- /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 0000000000..6477a37cef
--- /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 0000000000..af4633aa93
--- /dev/null
+++ b/security/nss/cmd/mpitests/mpi-test.c
@@ -0,0 +1,2146 @@
+/*
+ * 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 "blapi.h"
+#include "mpi.h"
+#include "secmpi.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? */
+
+#define IFOK(x) \
+ { \
+ int ifok_res = (x); \
+ if (MP_OKAY > ifok_res) { \
+ reason("test %s failed: error %d\n", #x, ifok_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;
+ }
+
+ snprintf(g_intbuf, sizeof(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;
+ }
+
+ snprintf(g_intbuf, sizeof(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));
+ snprintf(g_intbuf, sizeof(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;
+ mp_int b;
+ char *buf;
+
+ mp_init(&a);
+ mp_init(&b);
+ 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;
+ }
+
+ // read the binary output back and compare with the original number
+ memcpy(buf, b_mp4, sizeof(b_mp4));
+ mp_err read_err = mp_read_raw(&b, buf, sizeof(b_mp4));
+ if (read_err != MP_OKAY) {
+ reason("error: reading raw mp_int failed: %d\n", read_err);
+ out = 1;
+ }
+
+ if (mp_cmp(&a, &b) != 0) {
+ reason("error: test_raw: mp_int from read_raw does not match the original number\n");
+ out = 1;
+ }
+
+ free(buf);
+ mp_clear(&a);
+ mp_clear(&b);
+
+ return out;
+}
+
+/*------------------------------------------------------------------------*/
+
+int
+test_pprime(void)
+{
+ mp_int p;
+ int err = 0;
+ mp_err res;
+
+ RNG_RNGInit();
+ mp_init(&p);
+ mp_read_radix(&p, mp7, 16);
+
+ if (mpp_pprime_secure(&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_secure(&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_secure(9, 50) failed: error %d\n", res);
+ err = 1;
+ }
+
+ IFOK(mp_set_int(&p, 15));
+ res = mpp_pprime_secure(&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_secure(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 0000000000..cbeed68eae
--- /dev/null
+++ b/security/nss/cmd/mpitests/mpitests.gyp
@@ -0,0 +1,54 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.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',
+ ],
+ 'defines': [
+ 'NSS_USE_STATIC_LIBS'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports',
+ '<(DEPTH)/lib/util/util.gyp:nssutil3',
+ '<(DEPTH)/lib/nss/nss.gyp:nss_static',
+ '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
+ '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
+ '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
+ '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
+ '<(DEPTH)/lib/base/base.gyp:nssb',
+ '<(DEPTH)/lib/dev/dev.gyp:nssdev',
+ '<(DEPTH)/lib/pki/pki.gyp:nsspki',
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'include_dirs': [
+ '<(DEPTH)/lib/freebl/mpi',
+ '<(DEPTH)/lib/util',
+ ],
+ # This uses test builds and has to set defines for MPI.
+ 'conditions': [
+ [ 'target_arch=="ia32"', {
+ 'defines': [
+ 'MP_USE_UINT_DIGIT',
+ 'MP_ASSEMBLY_MULTIPLY',
+ 'MP_ASSEMBLY_SQUARE',
+ 'MP_ASSEMBLY_DIV_2DX1D',
+ ],
+ }],
+ ],
+ },
+ 'variables': {
+ 'module': 'nss',
+ 'use_static_libs': 1
+ }
+}
diff --git a/security/nss/cmd/mpitests/test-info.c b/security/nss/cmd/mpitests/test-info.c
new file mode 100644
index 0000000000..66386ff5d2
--- /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 0000000000..6e1d4ecdfc
--- /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 0000000000..a86adc8c8a
--- /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 0000000000..b0a49b92e8
--- /dev/null
+++ b/security/nss/cmd/multinit/multinit.c
@@ -0,0 +1,878 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 0000000000..b99c018433
--- /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/nss-policy-check/Makefile b/security/nss/cmd/nss-policy-check/Makefile
new file mode 100644
index 0000000000..6e1d4ecdfc
--- /dev/null
+++ b/security/nss/cmd/nss-policy-check/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/nss-policy-check/manifest.mn b/security/nss/cmd/nss-policy-check/manifest.mn
new file mode 100644
index 0000000000..8fb9abf000
--- /dev/null
+++ b/security/nss/cmd/nss-policy-check/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 = nss-policy-check.c
+
+REQUIRES = seccmd
+
+PROGRAM = nss-policy-check
+
diff --git a/security/nss/cmd/nss-policy-check/nss-policy-check.c b/security/nss/cmd/nss-policy-check/nss-policy-check.c
new file mode 100644
index 0000000000..b806dfba64
--- /dev/null
+++ b/security/nss/cmd/nss-policy-check/nss-policy-check.c
@@ -0,0 +1,305 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 can be used to check the validity of a NSS crypto policy
+ * configuration file, specified using a config= line.
+ *
+ * Exit codes:
+ * failure: 2
+ * warning: 1
+ * success: 0
+ */
+
+#include <limits.h>
+#include <errno.h>
+#include <stdio.h>
+#include "utilparst.h"
+#include "nss.h"
+#include "secport.h"
+#include "secutil.h"
+#include "secmod.h"
+#include "ssl.h"
+#include "prenv.h"
+#include "plgetopt.h"
+
+const char *sWarn = "WARN";
+const char *sInfo = "INFO";
+
+void
+get_tls_info(SSLProtocolVariant protocolVariant, const char *display)
+{
+ SSLVersionRange vrange_supported, vrange_enabled;
+ unsigned num_enabled = 0;
+ PRBool failed = PR_FALSE;
+
+ /* We assume SSL v2 is inactive, and therefore SSL_VersionRangeGetDefault
+ * gives complete information. */
+ if ((SSL_VersionRangeGetSupported(protocolVariant, &vrange_supported) != SECSuccess) ||
+ (SSL_VersionRangeGetDefault(protocolVariant, &vrange_enabled) != SECSuccess) ||
+ !vrange_enabled.min ||
+ !vrange_enabled.max ||
+ vrange_enabled.max < vrange_supported.min ||
+ vrange_enabled.min > vrange_supported.max) {
+ failed = PR_TRUE;
+ } else {
+ if (vrange_enabled.min < vrange_supported.min) {
+ vrange_enabled.min = vrange_supported.min;
+ }
+ if (vrange_enabled.max > vrange_supported.max) {
+ vrange_enabled.max = vrange_supported.max;
+ }
+ if (vrange_enabled.min > vrange_enabled.max) {
+ failed = PR_TRUE;
+ }
+ }
+ if (failed) {
+ num_enabled = 0;
+ } else {
+ num_enabled = vrange_enabled.max - vrange_enabled.min + 1;
+ }
+ fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-%s-VERSIONS: %u\n",
+ num_enabled ? sInfo : sWarn, display, num_enabled);
+ if (!num_enabled) {
+ PR_SetEnv("NSS_POLICY_WARN=1");
+ }
+}
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+/* private flags for policy check; should be in sync with pk11wrap/pk11pars.c */
+#define SECMOD_FLAG_POLICY_CHECK_IDENTIFIER 0x01
+#define SECMOD_FLAG_POLICY_CHECK_VALUE 0x02
+
+static void
+printUsage(const char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [options] <path-to-policy-file>\n"
+ "\tWhere options are:\n"
+ "\t-f flag\t Set policy check flag (can be specified multiple times)\n"
+ "\t \t Possible flags: \"identifier\" or \"value\"\n",
+ progName);
+}
+
+int
+main(int argc, char **argv)
+{
+ const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
+ int i;
+ SECStatus rv;
+ SECMODModule *module = NULL;
+ char path[PATH_MAX];
+ const char *filename;
+ char moduleSpec[1024 + PATH_MAX];
+ unsigned num_enabled = 0;
+ int result = 0;
+ char *flags = NULL;
+ PLOptState *optstate = NULL;
+ PLOptStatus status;
+ char *fullPath = NULL;
+ int fullPathLen;
+ char *progName = NULL;
+ PRUint32 policyCheckFlags = 0;
+
+ progName = PORT_Strdup(argv[0]);
+ if (!progName) {
+ result = 2;
+ goto loser_no_shutdown;
+ }
+
+ /* Use PL_CreateOptState as SECU_ParseCommandLine ignores
+ * positional parameters */
+ optstate = PL_CreateOptState(argc, argv, "f:");
+ if (!optstate) {
+ result = 2;
+ goto loser_no_shutdown;
+ }
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 0: /* positional parameter */
+ fullPath = PL_strdup(optstate->value);
+ if (!fullPath) {
+ result = 2;
+ goto loser_no_shutdown;
+ }
+ goto breakout;
+ case 'f':
+ if (!PORT_Strcmp(optstate->value, "identifier")) {
+ policyCheckFlags |= SECMOD_FLAG_POLICY_CHECK_IDENTIFIER;
+ } else if (!PORT_Strcmp(optstate->value, "value")) {
+ policyCheckFlags |= SECMOD_FLAG_POLICY_CHECK_VALUE;
+ } else {
+ fprintf(stderr, "not a valid flag: %s\n", optstate->value);
+ printUsage(progName);
+ result = 2;
+ goto loser_no_shutdown;
+ }
+ break;
+ default:
+ printUsage(progName);
+ result = 2;
+ goto loser_no_shutdown;
+ }
+ }
+breakout:
+ if (status != PL_OPT_OK || !fullPath) {
+ printUsage(progName);
+ result = 2;
+ goto loser_no_shutdown;
+ }
+
+ fullPathLen = strlen(fullPath);
+
+ if (!fullPathLen || PR_Access(fullPath, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ fprintf(stderr, "Error: cannot read file %s\n", fullPath);
+ result = 2;
+ goto loser_no_shutdown;
+ }
+
+ if (fullPathLen >= PATH_MAX) {
+ fprintf(stderr, "Error: filename parameter is too long\n");
+ result = 2;
+ goto loser_no_shutdown;
+ }
+
+ path[0] = 0;
+ filename = fullPath + fullPathLen - 1;
+ while ((filename > fullPath) && (*filename != NSSUTIL_PATH_SEPARATOR[0])) {
+ filename--;
+ }
+
+ if (filename == fullPath) {
+ PORT_Strcpy(path, ".");
+ } else {
+ filename++; /* Go past the path separator. */
+ PORT_Strncat(path, fullPath, (filename - fullPath));
+ }
+
+ PR_SetEnv("NSS_IGNORE_SYSTEM_POLICY=1");
+ rv = NSS_NoDB_Init(NULL);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "NSS_Init failed: %s\n", PORT_ErrorToString(PR_GetError()));
+ result = 2;
+ goto loser_no_shutdown;
+ }
+
+ PR_SetEnv("NSS_POLICY_LOADED=0");
+ PR_SetEnv("NSS_POLICY_FAIL=0");
+ PR_SetEnv("NSS_POLICY_WARN=0");
+
+ flags = PORT_Strdup("internal,moduleDB,skipFirst,moduleDBOnly,critical,printPolicyFeedback");
+ if (!flags) {
+ result = 2;
+ goto loser_no_shutdown;
+ }
+
+ if (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_IDENTIFIER) {
+ char *newflags;
+
+ newflags = PORT_Realloc(flags, strlen(flags) + strlen(",policyCheckIdentifier") + 1);
+ if (!newflags) {
+ result = 2;
+ goto loser_no_shutdown;
+ }
+ flags = newflags;
+ PORT_Strcat(flags, ",policyCheckIdentifier");
+ }
+
+ if (policyCheckFlags & SECMOD_FLAG_POLICY_CHECK_VALUE) {
+ char *newflags;
+
+ newflags = PORT_Realloc(flags, strlen(flags) + strlen(",policyCheckValue") + 1);
+ if (!newflags) {
+ result = 2;
+ goto loser_no_shutdown;
+ }
+ flags = newflags;
+ PORT_Strcat(flags, ",policyCheckValue");
+ }
+
+ snprintf(moduleSpec, sizeof(moduleSpec),
+ "name=\"Policy File\" "
+ "parameters=\"configdir='sql:%s' "
+ "secmod='%s' "
+ "flags=readOnly,noCertDB,forceSecmodChoice,forceOpen\" "
+ "NSS=\"flags=%s\"",
+ path, filename, flags);
+
+ module = SECMOD_LoadModule(moduleSpec, NULL, PR_TRUE);
+ if (!module || !module->loaded || atoi(PR_GetEnvSecure("NSS_POLICY_LOADED")) != 1) {
+ fprintf(stderr, "Error: failed to load policy file\n");
+ result = 2;
+ goto loser;
+ }
+
+ rv = SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "enable SSL_SECURITY failed: %s\n", PORT_ErrorToString(PR_GetError()));
+ result = 2;
+ goto loser;
+ }
+
+ for (i = 0; i < SSL_NumImplementedCiphers; i++) {
+ PRUint16 suite = cipherSuites[i];
+ PRBool enabled;
+ SSLCipherSuiteInfo info;
+
+ rv = SSL_CipherPrefGetDefault(suite, &enabled);
+ if (rv != SECSuccess) {
+ fprintf(stderr,
+ "SSL_CipherPrefGetDefault didn't like value 0x%04x (i = %d): %s\n",
+ suite, i, PORT_ErrorToString(PR_GetError()));
+ continue;
+ }
+ rv = SSL_GetCipherSuiteInfo(suite, &info, (int)(sizeof info));
+ if (rv != SECSuccess) {
+ fprintf(stderr,
+ "SSL_GetCipherSuiteInfo didn't like value 0x%04x (i = %d): %s\n",
+ suite, i, PORT_ErrorToString(PR_GetError()));
+ continue;
+ }
+ if (enabled) {
+ ++num_enabled;
+ fprintf(stderr, "NSS-POLICY-INFO: ciphersuite %s is enabled\n", info.cipherSuiteName);
+ }
+ }
+ fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-CIPHERSUITES: %u\n", num_enabled ? sInfo : sWarn, num_enabled);
+ if (!num_enabled) {
+ PR_SetEnv("NSS_POLICY_WARN=1");
+ }
+
+ get_tls_info(ssl_variant_stream, "TLS");
+ get_tls_info(ssl_variant_datagram, "DTLS");
+
+ if (atoi(PR_GetEnvSecure("NSS_POLICY_FAIL")) != 0) {
+ result = 2;
+ } else if (atoi(PR_GetEnvSecure("NSS_POLICY_WARN")) != 0) {
+ result = 1;
+ }
+
+loser:
+ if (module) {
+ SECMOD_DestroyModule(module);
+ }
+ rv = NSS_Shutdown();
+ if (rv != SECSuccess) {
+ fprintf(stderr, "NSS_Shutdown failed: %s\n", PORT_ErrorToString(PR_GetError()));
+ result = 2;
+ }
+loser_no_shutdown:
+ if (optstate) {
+ PL_DestroyOptState(optstate);
+ }
+ PORT_Free(flags);
+ PORT_Free(progName);
+ PORT_Free(fullPath);
+ if (result == 2) {
+ fprintf(stderr, "NSS-POLICY-FAIL\n");
+ } else if (result == 1) {
+ fprintf(stderr, "NSS-POLICY-WARN\n");
+ }
+ return result;
+}
diff --git a/security/nss/cmd/nss-policy-check/nss-policy-check.gyp b/security/nss/cmd/nss-policy-check/nss-policy-check.gyp
new file mode 100644
index 0000000000..877a5bc06e
--- /dev/null
+++ b/security/nss/cmd/nss-policy-check/nss-policy-check.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': 'nss-policy-check',
+ 'type': 'executable',
+ 'sources': [
+ 'nss-policy-check.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 0000000000..265ea56015
--- /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 0000000000..a2794a3831
--- /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 0000000000..69d48b4987
--- /dev/null
+++ b/security/nss/cmd/ocspclnt/ocspclnt.c
@@ -0,0 +1,1248 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 *progname)
+{
+ PRFileDesc *pr_stderr;
+
+ pr_stderr = PR_STDERR;
+ PR_fprintf(pr_stderr, "Usage:");
+ PR_fprintf(pr_stderr,
+ "\t%s -p [-d <dir>]\n",
+ progname);
+ PR_fprintf(pr_stderr,
+ "\t%s -P [-d <dir>]\n",
+ progname);
+ PR_fprintf(pr_stderr,
+ "\t%s -r <name> [-a] [-L] [-s <name>] [-d <dir>]\n",
+ progname);
+ PR_fprintf(pr_stderr,
+ "\t%s -R <name> [-a] [-l <location>] [-s <name>] [-d <dir>]\n",
+ progname);
+ PR_fprintf(pr_stderr,
+ "\t%s -S <name> [-a] [-l <location> -t <name>]\n",
+ progname);
+ 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",
+ progname);
+ PR_fprintf(pr_stderr,
+ "\t\t [-s <name>] [-w <time>] [-d <dir>]\n");
+}
+
+static void
+short_usage(char *progname)
+{
+ PR_fprintf(PR_STDERR,
+ "Type %s -H for more detailed descriptions\n",
+ progname);
+ synopsis(progname);
+}
+
+static void
+long_usage(char *progname)
+{
+ PRFileDesc *pr_stderr;
+
+ pr_stderr = PR_STDERR;
+ synopsis(progname);
+ 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 I IPsec\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) {
+ snprintf(cert_label, sizeof(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 'I':
+ *cert_usage = certUsageIPsec;
+ 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 0000000000..4ab7c5e363
--- /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 0000000000..6e1d4ecdfc
--- /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 0000000000..3608623b8a
--- /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 0000000000..d18d32e18e
--- /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
+ {
+ 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
+ {
+ 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 0000000000..81f02dfe88
--- /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 0000000000..d7c879aec2
--- /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 0000000000..e7976c6616
--- /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 0000000000..46ef56c411
--- /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 0000000000..b02ab87216
--- /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 0000000000..6e1d4ecdfc
--- /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 0000000000..6fa632f551
--- /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 0000000000..d8c4d6524a
--- /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 0000000000..7380dfae1c
--- /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 0000000000..6e1d4ecdfc
--- /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 0000000000..db385b2082
--- /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 0000000000..453cbee194
--- /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 = SECFailure;
+
+ 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 = SECFailure;
+
+ 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 0000000000..e84eaabee6
--- /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 0000000000..6e1d4ecdfc
--- /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 0000000000..1f32e3954b
--- /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 0000000000..334c80a2e1
--- /dev/null
+++ b/security/nss/cmd/p7sign/p7sign.c
@@ -0,0 +1,336 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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)
+{
+ HASH_HashType hashAlg;
+
+ fprintf(stderr,
+ "Usage: %s -k keyname [-d keydir] [-i input] [-o output] [-e]\n",
+ progName);
+ fprintf(stderr,
+ " %*s [-p password|-f password file] [-a hash] [-u certusage]\n",
+ (int)strlen(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 password");
+ fprintf(stderr, "%-20s File to read password from\n", "-f password file");
+ fprintf(stderr, "%-20s Use case-insensitive hash algorithm (default: SHA-1)\n",
+ "-a hash");
+ fprintf(stderr, "%-25s ", "");
+ for (hashAlg = HASH_AlgNULL + 1; hashAlg != HASH_AlgTOTAL; ++hashAlg)
+ fprintf(stderr, "%s%s", hashAlg == HASH_AlgNULL + 1 ? "" : ", ",
+ SECOID_FindOIDByTag(HASH_GetHashOidTagByHashType(hashAlg))->desc);
+ fputc('\n', stderr);
+ fprintf(stderr, "%-20s Sign for usage (default: 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", "");
+ fprintf(stderr, "%-25s 12 - certUsageIPsec\n", "");
+ 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, HASH_HashType hashAlg)
+{
+ const SECHashObject *hashObj;
+ void *hashcx;
+
+ hashObj = HASH_GetHashObject(hashAlg);
+
+ 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, HASH_HashType hashAlg, SECOidTag hashAlgOid,
+ SECCertUsage usage)
+{
+ char digestdata[HASH_LENGTH_MAX];
+ 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,
+ sizeof(digestdata), hashAlg) < 0) {
+ SECITEM_FreeItem(&data2sign, PR_FALSE);
+ return -1;
+ }
+ digest.data = (unsigned char *)digestdata;
+ digest.len = len;
+ }
+
+ cinfo = SEC_PKCS7CreateSignedData(cert, usage, NULL,
+ hashAlgOid,
+ encapsulated ? NULL : &digest,
+ NULL, NULL);
+ if (cinfo == NULL) {
+ SECITEM_FreeItem(&data2sign, PR_FALSE);
+ return -1;
+ }
+
+ if (encapsulated) {
+ SEC_PKCS7SetContent(cinfo, (char *)data2sign.data, data2sign.len);
+ }
+
+ rv = SEC_PKCS7IncludeCertChain(cinfo, NULL);
+ if (rv != SECSuccess) {
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ SECITEM_FreeItem(&data2sign, PR_FALSE);
+ 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;
+ HASH_HashType hashAlg = HASH_AlgSHA1;
+ SECOidTag hashAlgOid = SEC_OID_SHA1;
+ SECCertUsage usage = certUsageEmailSigner;
+ 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:a:u:");
+ 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;
+
+ case 'a':
+ for (hashAlg = HASH_AlgNULL + 1; hashAlg != HASH_AlgTOTAL;
+ ++hashAlg) {
+ hashAlgOid = HASH_GetHashOidTagByHashType(hashAlg);
+ if (!PORT_Strcasecmp(optstate->value,
+ SECOID_FindOIDByTag(hashAlgOid)->desc))
+ break;
+ }
+ if (hashAlg == HASH_AlgTOTAL)
+ Usage(progName);
+ break;
+
+ case 'u':
+ usage = atoi(optstate->value);
+ if (usage < certUsageSSLClient || usage > certUsageIPsec)
+ Usage(progName);
+ 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 = SECU_FindCertByNicknameOrFilename(certHandle, keyName, PR_FALSE, NULL);
+ 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,
+ hashAlg, hashAlgOid, usage)) {
+ 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 0000000000..c2c672d7e7
--- /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 0000000000..6e1d4ecdfc
--- /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 0000000000..565c74bc29
--- /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 0000000000..ba324a45b9
--- /dev/null
+++ b/security/nss/cmd/p7verify/p7verify.c
@@ -0,0 +1,264 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 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", " ");
+ fprintf(stderr, "%-25s 12 - certUsageIPsec\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 = HASH_GetHashTypeByOidTag(
+ SECOID_GetAlgorithmTag(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(optstate->value);
+ if (usageType < certUsageSSLClient || usageType > certUsageIPsec)
+ 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 0000000000..220a72a428
--- /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 0000000000..d20daa4b78
--- /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 0000000000..af814b5810
--- /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 0000000000..0a3a1cf018
--- /dev/null
+++ b/security/nss/cmd/pk11ectest/pk11ectest.c
@@ -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/. */
+
+#include "blapi.h"
+#include "nss.h"
+#include "secutil.h"
+#include "secitem.h"
+#include "nspr.h"
+#include "pk11pub.h"
+#include <stdio.h>
+
+typedef struct KeyLengthEntryStr {
+ SECOidTag tag;
+ unsigned int len;
+ PRBool encoded;
+} KeyLengthEntry;
+
+const KeyLengthEntry keyLengthTable[] = {
+ { SEC_OID_SECG_EC_SECP256R1, 65, PR_TRUE },
+ { SEC_OID_SECG_EC_SECP384R1, 97, PR_TRUE },
+ { SEC_OID_SECG_EC_SECP521R1, 133, PR_TRUE },
+ { SEC_OID_CURVE25519, 32, PR_FALSE }
+};
+
+const KeyLengthEntry *
+getKeyLengthEntry(SECOidTag tag)
+{
+ int i;
+
+ for (i = 0; i < PR_ARRAY_SIZE(keyLengthTable); i++) {
+ if (keyLengthTable[i].tag == tag) {
+ return &keyLengthTable[i];
+ }
+ }
+ return NULL;
+}
+
+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;
+ const KeyLengthEntry *keyLengthEntry;
+ SECItem point = { siBuffer, NULL, 0 };
+ SECItem value = { siBuffer, NULL, 0 };
+ PLArenaPool *arena = NULL;
+
+ 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);
+
+ keyLengthEntry = getKeyLengthEntry(oid);
+ /* this shouldn't happen unless new curves are added without adding them
+ * to the keyLengthTable */
+ PR_ASSERT(keyLengthEntry);
+
+ /* make sure we are returning CKA_EC_POINT according to the PKCS #11 standard.
+ * NSS itself can tolerate non-standard CKA_EC_POINT, so this is the only place
+ * our test will detect incorrect behavior */
+ rv = PK11_ReadRawAttribute(PK11_TypePubKey, pubKey, CKA_EC_POINT, &point);
+ if (rv == SECFailure) {
+ printf(" >>> Couldn't get CKA_EC_POINT from the ec pubKey.\n");
+ goto cleanup;
+ }
+ rv = SECFailure;
+ if (keyLengthEntry->encoded) {
+ if (point.len == keyLengthEntry->len) {
+ printf(" >>> Expected encoded CKA_EC_POINT and got a decoded value.\n");
+ printBuf(&point);
+ goto cleanup;
+ }
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ printf(" >>> arena alloc failed.\n");
+ goto cleanup;
+ }
+
+ rv = SEC_QuickDERDecodeItem(arena, &value, SEC_ASN1_GET(SEC_OctetStringTemplate),
+ &point);
+ if (rv != SECSuccess) {
+ printf(" >>> invalid endoded CKA_EC_POINT.\n");
+ printBuf(&point);
+ goto cleanup;
+ }
+ rv = SECFailure;
+ if (value.len != keyLengthEntry->len) {
+ printf(" >>> invalid decoded CKA_EC_POINT len (%d) expected %d.\n",
+ value.len, keyLengthEntry->len);
+ printBuf(&value);
+ goto cleanup;
+ }
+ if (value.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
+ printf(" >>> invalid CKA_EC_POINT format (%02x) expected %02x.\n",
+ value.data[0], EC_POINT_FORM_UNCOMPRESSED);
+ printBuf(&value);
+ goto cleanup;
+ }
+ } else {
+ if (point.len != keyLengthEntry->len) {
+ printf(" >>> invalid CKA_EC_POINT len (%d) expected %d.\n",
+ point.len, keyLengthEntry->len);
+ printBuf(&point);
+ goto cleanup;
+ }
+ }
+
+ rv = SECSuccess;
+cleanup:
+ if (privKey) {
+ SECKEY_DestroyPrivateKey(privKey);
+ }
+ if (pubKey) {
+ SECKEY_DestroyPublicKey(pubKey);
+ }
+ if (symKey) {
+ PK11_FreeSymKey(symKey);
+ }
+ if (arena) {
+ PORT_FreeArena(arena, PR_TRUE);
+ }
+ SECITEM_FreeItem(&pk_11_ecParams, PR_FALSE);
+ SECITEM_FreeItem(&point, 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 0000000000..584bc07414
--- /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 100644
index 0000000000..3ffa387472
--- /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 0000000000..0f7354800f
--- /dev/null
+++ b/security/nss/cmd/pk11gcmtest/manifest.mn
@@ -0,0 +1,14 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.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
+
+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 0000000000..fc64db86f0
--- /dev/null
+++ b/security/nss/cmd/pk11gcmtest/pk11gcmtest.c
@@ -0,0 +1,465 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_NSS_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_NSS_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) {
+ return 1;
+ }
+
+ if (NSS_NoDB_Init(NULL) != SECSuccess) {
+ return 1;
+ }
+
+ /*************/
+ /* 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]);
+ }
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/security/nss/cmd/pk11gcmtest/pk11gcmtest.gyp b/security/nss/cmd/pk11gcmtest/pk11gcmtest.gyp
new file mode 100644
index 0000000000..fff80f8e8b
--- /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 0000000000..9131b52314
--- /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 0000000000..49f264fd5d
--- /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 0000000000..860167036a
--- /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 0000000000..7406a3556d
--- /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 0000000000..e5ccc3eebb
--- /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 0000000000..cda212f68e
--- /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 0000000000..1b10fa8868
--- /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/pk11importtest/Makefile b/security/nss/cmd/pk11importtest/Makefile
new file mode 100644
index 0000000000..fc8358d5ad
--- /dev/null
+++ b/security/nss/cmd/pk11importtest/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/pk11importtest/manifest.mn b/security/nss/cmd/pk11importtest/manifest.mn
new file mode 100644
index 0000000000..5c40a8108a
--- /dev/null
+++ b/security/nss/cmd/pk11importtest/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 = pk11importtest.c \
+ $(NULL)
+
+REQUIRES = seccmd
+
+PROGRAM = pk11importtest
+
diff --git a/security/nss/cmd/pk11importtest/pk11importtest.c b/security/nss/cmd/pk11importtest/pk11importtest.c
new file mode 100644
index 0000000000..817a0f12fc
--- /dev/null
+++ b/security/nss/cmd/pk11importtest/pk11importtest.c
@@ -0,0 +1,407 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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"
+#include "pk11pub.h"
+#include "pk11pqg.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"
+
+SECOidData *
+getCurveFromString(char *curve_name)
+{
+ SECOidTag tag = SEC_OID_SECG_EC_SECP256R1;
+
+ if (PORT_Strcasecmp(curve_name, "NISTP256") == 0) {
+ } else if (PORT_Strcasecmp(curve_name, "NISTP384") == 0) {
+ tag = SEC_OID_SECG_EC_SECP384R1;
+ } else if (PORT_Strcasecmp(curve_name, "NISTP521") == 0) {
+ tag = SEC_OID_SECG_EC_SECP521R1;
+ } else if (PORT_Strcasecmp(curve_name, "Curve25519") == 0) {
+ tag = SEC_OID_CURVE25519;
+ }
+ return SECOID_FindOIDByTag(tag);
+}
+
+void
+dumpItem(const char *label, const SECItem *item)
+{
+ int i;
+ printf("%s = [%d bytes] {", label, item->len);
+ for (i = 0; i < item->len; i++) {
+ if ((i & 0xf) == 0)
+ printf("\n ");
+ else
+ printf(", ");
+ printf("%02x", item->data[i]);
+ }
+ printf("};\n");
+}
+
+SECStatus
+handleEncryptedPrivateImportTest(char *progName, PK11SlotInfo *slot,
+ char *testname, CK_MECHANISM_TYPE genMech, void *params, void *pwArgs)
+{
+ SECStatus rv = SECSuccess;
+ SECItem privID = { 0 };
+ SECItem pubID = { 0 };
+ SECItem pubValue = { 0 };
+ SECItem pbePwItem = { 0 };
+ SECItem nickname = { 0 };
+ SECItem token = { 0 };
+ SECKEYPublicKey *pubKey = NULL;
+ SECKEYPrivateKey *privKey = NULL;
+ PK11GenericObject *objs = NULL;
+ PK11GenericObject *obj = NULL;
+ SECKEYEncryptedPrivateKeyInfo *epki = NULL;
+ PRBool keyFound = 0;
+ KeyType keyType;
+
+ fprintf(stderr, "Testing %s PrivateKeyImport ***********************\n",
+ testname);
+
+ /* generate a temp key */
+ privKey = PK11_GenerateKeyPair(slot, genMech, params, &pubKey,
+ PR_FALSE, PR_TRUE, pwArgs);
+ if (privKey == NULL) {
+ SECU_PrintError(progName, "PK11_GenerateKeyPair Failed");
+ goto cleanup;
+ }
+
+ /* wrap the temp key */
+ pbePwItem.data = (unsigned char *)"pw";
+ pbePwItem.len = 2;
+ epki = PK11_ExportEncryptedPrivKeyInfo(slot, SEC_OID_AES_256_CBC,
+ &pbePwItem, privKey, 1, NULL);
+ if (epki == NULL) {
+ SECU_PrintError(progName, "PK11_ExportEncryptedPrivKeyInfo Failed");
+ goto cleanup;
+ }
+
+ /* Save the public value, which we will need on import */
+ keyType = pubKey->keyType;
+ switch (keyType) {
+ case rsaKey:
+ SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.rsa.modulus);
+ break;
+ case dhKey:
+ SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.dh.publicValue);
+ break;
+ case dsaKey:
+ SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.dsa.publicValue);
+ break;
+ case ecKey:
+ SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.ec.publicValue);
+ break;
+ default:
+ fprintf(stderr, "Unknown keytype = %d\n", keyType);
+ goto cleanup;
+ }
+ if (pubValue.data == NULL) {
+ SECU_PrintError(progName, "Unable to allocate memory");
+ goto cleanup;
+ }
+ dumpItem("pubValue", &pubValue);
+
+ /* when Asymetric keys represent session keys, those session keys are
+ * destroyed when we destroy the Asymetric key representations */
+ SECKEY_DestroyPublicKey(pubKey);
+ pubKey = NULL;
+ SECKEY_DestroyPrivateKey(privKey);
+ privKey = NULL;
+
+ /* unwrap the temp key as a perm */
+ nickname.data = (unsigned char *)"testKey";
+ nickname.len = sizeof("testKey");
+ rv = PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(
+ slot, epki, &pbePwItem, &nickname, &pubValue,
+ PR_TRUE, PR_TRUE, keyType, 0, &privKey, NULL);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "PK11_ImportEncryptedPrivateKeyInfo Failed");
+ goto cleanup;
+ }
+
+ /* verify the public key exists */
+ rv = PK11_ReadRawAttribute(PK11_TypePrivKey, privKey, CKA_ID, &privID);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName,
+ "Couldn't read CKA_ID from pub key, checking next key");
+ goto cleanup;
+ }
+ dumpItem("privKey CKA_ID", &privID);
+ objs = PK11_FindGenericObjects(slot, CKO_PUBLIC_KEY);
+ for (obj = objs; obj; obj = PK11_GetNextGenericObject(obj)) {
+ rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_ID, &pubID);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName,
+ "Couldn't read CKA_ID from object, checking next key");
+ continue;
+ }
+ dumpItem("pubKey CKA_ID", &pubID);
+ if (!SECITEM_ItemsAreEqual(&privID, &pubID)) {
+ fprintf(stderr,
+ "CKA_ID does not match priv key, checking next key\n");
+ SECITEM_FreeItem(&pubID, PR_FALSE);
+ continue;
+ }
+ SECITEM_FreeItem(&pubID, PR_FALSE);
+ rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_TOKEN, &token);
+ if (rv == SECSuccess) {
+ if (token.len == 1) {
+ keyFound = token.data[0];
+ }
+ SECITEM_FreeItem(&token, PR_FALSE);
+ }
+ if (keyFound) {
+ printf("matching public key found\n");
+ break;
+ }
+ printf("Matching key was not a token key, checking next key\n");
+ }
+
+cleanup:
+ if (objs) {
+ PK11_DestroyGenericObjects(objs);
+ }
+ SECITEM_FreeItem(&pubValue, PR_FALSE);
+ SECITEM_FreeItem(&privID, PR_FALSE);
+ if (epki && epki->arena) {
+ PORT_FreeArena(epki->arena, PR_TRUE);
+ }
+ SECKEY_DestroyPublicKey(pubKey);
+ SECKEY_DestroyPrivateKey(privKey);
+ fprintf(stderr, "%s PrivateKeyImport %s ***********************\n",
+ testname, keyFound ? "PASSED" : "FAILED");
+ return keyFound ? SECSuccess : SECFailure;
+}
+
+static const char *const usageInfo[] = {
+ "pk11import - test PK11_PrivateKeyImport()",
+ "Options:",
+ " -d certdir directory containing cert database",
+ " -k keysize size of the rsa, dh, and dsa key to test (default 1024)",
+ " -C ecc_curve ecc curve (default )",
+ " -f pwFile file to fetch the password from",
+ " -p pwString password",
+ " -r skip rsa test",
+ " -D skip dsa test",
+ " -h skip dh test",
+ " -e skip ec test",
+};
+static int nUsageInfo = sizeof(usageInfo) / sizeof(char *);
+
+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);
+}
+
+enum {
+ opt_CertDir,
+ opt_KeySize,
+ opt_ECCurve,
+ opt_PWFile,
+ opt_PWString,
+ opt_NoRSA,
+ opt_NoDSA,
+ opt_NoEC,
+ opt_NoDH
+};
+
+static secuCommandFlag options[] = {
+ { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeySize */ 'k', PR_TRUE, 0, PR_FALSE },
+ { /* opt_ECCurve */ 'C', PR_TRUE, 0, PR_FALSE },
+ { /* opt_PWFile */ 'f', PR_TRUE, 0, PR_FALSE },
+ { /* opt_PWString */ 'p', PR_TRUE, 0, PR_FALSE },
+ { /* opt_NORSA */ 'r', PR_TRUE, 0, PR_FALSE },
+ { /* opt_NoDSA */ 'D', PR_TRUE, 0, PR_FALSE },
+ { /* opt_NoDH */ 'h', PR_TRUE, 0, PR_FALSE },
+ { /* opt_NoEC */ 'e', PR_TRUE, 0, PR_FALSE },
+};
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ SECStatus rv;
+ secuCommand args;
+ PK11SlotInfo *slot = NULL;
+ PRBool failed = PR_FALSE;
+ secuPWData pwArgs = { PW_NONE, 0 };
+ PRBool doRSA = PR_TRUE;
+ PRBool doDSA = PR_TRUE;
+ PRBool doDH = PR_FALSE; /* NSS currently can't export wrapped DH keys */
+ PRBool doEC = PR_TRUE;
+ PQGParams *pqgParams = NULL;
+ int keySize;
+
+ args.numCommands = 0;
+ args.numOptions = sizeof(options) / sizeof(secuCommandFlag);
+ args.commands = NULL;
+ args.options = 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, &args);
+ if (SECSuccess != rv) {
+ Usage(progName, stderr);
+ }
+
+ /* Set the certdb directory (default is ~/.netscape) */
+ rv = NSS_InitReadWrite(SECU_ConfigDirectory(args.options[opt_CertDir].arg));
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return 255;
+ }
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ /* below here, goto cleanup */
+ SECU_RegisterDynamicOids();
+
+ /* handle the arguments */
+ if (args.options[opt_PWFile].arg) {
+ pwArgs.source = PW_FROMFILE;
+ pwArgs.data = args.options[opt_PWFile].arg;
+ }
+ if (args.options[opt_PWString].arg) {
+ pwArgs.source = PW_PLAINTEXT;
+ pwArgs.data = args.options[opt_PWString].arg;
+ }
+ if (args.options[opt_NoRSA].activated) {
+ doRSA = PR_FALSE;
+ }
+ if (args.options[opt_NoDSA].activated) {
+ doDSA = PR_FALSE;
+ }
+ if (args.options[opt_NoDH].activated) {
+ doDH = PR_FALSE;
+ }
+ if (args.options[opt_NoEC].activated) {
+ doEC = PR_FALSE;
+ }
+
+ slot = PK11_GetInternalKeySlot();
+ if (slot == NULL) {
+ SECU_PrintError(progName, "Couldn't find the internal key slot\n");
+ return 255;
+ }
+ rv = PK11_Authenticate(slot, PR_TRUE, &pwArgs);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Failed to log into slot");
+ PK11_FreeSlot(slot);
+ return 255;
+ }
+
+ keySize = 1024;
+ if (args.options[opt_KeySize].activated &&
+ args.options[opt_KeySize].arg) {
+ keySize = atoi(args.options[opt_KeySize].arg);
+ }
+
+ if (doDSA || doDH) {
+ PQGVerify *pqgVfy;
+ rv = PK11_PQG_ParamGenV2(keySize, 0, keySize / 16, &pqgParams, &pqgVfy);
+ if (rv == SECSuccess) {
+ PK11_PQG_DestroyVerify(pqgVfy);
+ } else {
+ SECU_PrintError(progName,
+ "PK11_PQG_ParamGenV2 failed, can't test DH or DSA");
+ doDSA = doDH = PR_FALSE;
+ failed = PR_TRUE;
+ }
+ }
+
+ if (doRSA) {
+ PK11RSAGenParams rsaParams;
+ rsaParams.keySizeInBits = keySize;
+ rsaParams.pe = 0x010001;
+ rv = handleEncryptedPrivateImportTest(progName, slot, "RSA",
+ CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams, &pwArgs);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "RSA Import Failed!\n");
+ failed = PR_TRUE;
+ }
+ }
+ if (doDSA) {
+ rv = handleEncryptedPrivateImportTest(progName, slot, "DSA",
+ CKM_DSA_KEY_PAIR_GEN, pqgParams, &pwArgs);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "DSA Import Failed!\n");
+ failed = PR_TRUE;
+ }
+ }
+ if (doDH) {
+ SECKEYDHParams dhParams;
+ dhParams.prime = pqgParams->prime;
+ dhParams.base = pqgParams->base;
+ rv = handleEncryptedPrivateImportTest(progName, slot, "DH",
+ CKM_DH_PKCS_KEY_PAIR_GEN, &dhParams, &pwArgs);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "DH Import Failed!\n");
+ failed = PR_TRUE;
+ }
+ }
+ if (doEC) {
+ SECKEYECParams ecParams;
+ SECOidData *curve = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
+ if (args.options[opt_ECCurve].activated &&
+ args.options[opt_ECCurve].arg) {
+ curve = getCurveFromString(args.options[opt_ECCurve].arg);
+ }
+ ecParams.data = PORT_Alloc(curve->oid.len + 2);
+ if (ecParams.data == NULL) {
+ rv = SECFailure;
+ goto ec_failed;
+ }
+ ecParams.data[0] = SEC_ASN1_OBJECT_ID;
+ ecParams.data[1] = (unsigned char)curve->oid.len;
+ PORT_Memcpy(&ecParams.data[2], curve->oid.data, curve->oid.len);
+ ecParams.len = curve->oid.len + 2;
+ rv = handleEncryptedPrivateImportTest(progName, slot, "ECC",
+ CKM_EC_KEY_PAIR_GEN, &ecParams, &pwArgs);
+ PORT_Free(ecParams.data);
+ ec_failed:
+ if (rv != SECSuccess) {
+ fprintf(stderr, "ECC Import Failed!\n");
+ failed = PR_TRUE;
+ }
+ }
+
+ if (pqgParams) {
+ PK11_PQG_DestroyParams(pqgParams);
+ }
+
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+
+ rv = NSS_Shutdown();
+ if (rv != SECSuccess) {
+ fprintf(stderr, "Shutdown failed\n");
+ SECU_PrintPRandOSError(progName);
+ return 255;
+ }
+
+ return failed ? 1 : 0;
+}
diff --git a/security/nss/cmd/pk11importtest/pk11importtest.gyp b/security/nss/cmd/pk11importtest/pk11importtest.gyp
new file mode 100644
index 0000000000..4fce059621
--- /dev/null
+++ b/security/nss/cmd/pk11importtest/pk11importtest.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': 'pk11importtest',
+ 'type': 'executable',
+ 'sources': [
+ 'pk11importtest.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/cmd/pk11mode/Makefile b/security/nss/cmd/pk11mode/Makefile
new file mode 100644
index 0000000000..e9cbcac409
--- /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 0000000000..964fad3053
--- /dev/null
+++ b/security/nss/cmd/pk11mode/manifest.mn
@@ -0,0 +1,14 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.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 = 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 0000000000..caf1f90a87
--- /dev/null
+++ b/security/nss/cmd/pk11mode/pk11mode.c
@@ -0,0 +1,5370 @@
+/*
+ * 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(DO_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_C_INITIALIZE_ARGS_NSS initArgsRerun; /* rerun selftests */
+ 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 *moduleSpecRerun = 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);
+ moduleSpecRerun = PR_smprintf("configdir='%s' certPrefix='%s' "
+ "keyPrefix='%s' secmod='secmod.db' flags=forcePOST ",
+ configDir, dbPrefix, dbPrefix);
+ initArgs.LibraryParameters = (CK_CHAR_PTR *)moduleSpec;
+ initArgs.pReserved = NULL;
+ initArgsRerun = initArgs;
+ initArgsRerun.LibraryParameters = (CK_CHAR_PTR *)moduleSpecRerun;
+
+ /*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(&initArgsRerun);
+ 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);
+ }
+ if (moduleSpecRerun) {
+ PR_smprintf_free(moduleSpecRerun);
+ }
+
+#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[500];
+ 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 0000000000..ed042c1834
--- /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 0000000000..74ae200208
--- /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 0000000000..ca818aad4b
--- /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 0000000000..bd1ea2bcda
--- /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 0000000000..33e761f0b6
--- /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 0000000000..9bcf365cc4
--- /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 0000000000..0f249c3b5e
--- /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 0000000000..d103a9c4ff
--- /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 0000000000..0be909bb4e
--- /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 0000000000..82e860258e
--- /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 0000000000..c322a8bfe6
--- /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 0000000000..74ae200208
--- /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 0000000000..5f7e0ab49f
--- /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 0000000000..9b88cf0da9
--- /dev/null
+++ b/security/nss/cmd/pk12util/pk12util.c
@@ -0,0 +1,1223 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 "sechash.h"
+#include "certdb.h"
+
+#define PKCS12_IN_BUFFER_SIZE 200
+
+static char *progName;
+PRBool pk12_debugging = PR_FALSE;
+PRBool dumpRawFile;
+static PRBool pk12uForceUnicode;
+
+PRIntn pk12uErrno = 0;
+
+static void
+Usage()
+{
+#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] [-M mac_alg]\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 forceUnicode = pk12uForceUnicode;
+ 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 if (forceUnicode == pk12uForceUnicode) {
+ /* try again with a different password encoding */
+ forceUnicode = !pk12uForceUnicode;
+ rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE,
+ forceUnicode);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "PKCS12 decoding failed to set option");
+ pk12uErrno = PK12UERR_DECODEVERIFY;
+ break;
+ }
+ SEC_PKCS12DecoderFinish(p12dcx);
+ trypw = PR_TRUE;
+ } else {
+ SECU_PrintError(progName, "PKCS12 decode not verified");
+ pk12uErrno = PK12UERR_DECODEVERIFY;
+ break;
+ }
+ }
+ } while (trypw == PR_TRUE);
+
+ /* revert the option setting */
+ if (forceUnicode != pk12uForceUnicode) {
+ rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE, pk12uForceUnicode);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "PKCS12 decoding failed to set option");
+ pk12uErrno = PK12UERR_DECODEVERIFY;
+ }
+ }
+ /* 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 };
+ PRBool forceUnicode = pk12uForceUnicode;
+ PRBool trypw;
+ 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;
+ }
+
+ do {
+ trypw = PR_FALSE; /* normally we do this once */
+ 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 */
+ if (forceUnicode != pk12uForceUnicode) {
+ rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE,
+ forceUnicode);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "PKCS12 decode set option failed");
+ pk12uErrno = PK12UERR_DECODEIMPTBAGS;
+ goto loser;
+ }
+ }
+ rv = SEC_PKCS12DecoderImportBags(p12dcx);
+ if (rv != SECSuccess) {
+ if (PR_GetError() == SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY &&
+ forceUnicode == pk12uForceUnicode) {
+ /* try again with a different password encoding */
+ forceUnicode = !pk12uForceUnicode;
+ SEC_PKCS12DecoderFinish(p12dcx);
+ SECITEM_ZfreeItem(&uniPwitem, PR_FALSE);
+ trypw = PR_TRUE;
+ } else {
+ SECU_PrintError(progName, "PKCS12 decode import bags failed");
+ pk12uErrno = PK12UERR_DECODEIMPTBAGS;
+ goto loser;
+ }
+ }
+ } while (trypw);
+
+ /* revert the option setting */
+ if (forceUnicode != pk12uForceUnicode) {
+ rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE, pk12uForceUnicode);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "PKCS12 decode set option 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, SECOidTag hash,
+ 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) {
+ PORT_SetError(SEC_ERROR_UNKNOWN_CERT);
+ 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;
+ }
+
+ /* we are passing UTF8, drop the NULL in the normal password value.
+ * UCS2 conversion will add it back if necessary. This only affects
+ * password > Blocksize of the Hash function and pkcs5v2 pbe (if password
+ * <=Blocksize then the password is zero padded anyway, so an extra NULL
+ * at the end has not effect). This is allows us to work with openssl and
+ * gnutls. Older versions of NSS already fail to decrypt long passwords
+ * in this case, so we aren't breaking anyone with this code */
+ if ((pwitem->len > 0) && (!pwitem->data[pwitem->len - 1])) {
+ pwitem->len--;
+ }
+
+ 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 = CERT_LIST_HEAD(certlist)->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, hash) !=
+ 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];
+ snprintf(fileName, sizeof(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;
+}
+
+SECOidTag
+PKCS12U_FindTagFromString(char *cipherString)
+{
+ SECOidTag tag;
+ SECOidData *oid;
+
+ /* future enhancement: accept dotted oid spec? */
+
+ 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;
+ }
+ return tag;
+ }
+ return SEC_OID_UNKNOWN;
+}
+
+/*
+ * use the oid table description to map a user input string to a particular
+ * oid.
+ */
+SECOidTag
+PKCS12U_MapCipherFromString(char *cipherString, int keyLen)
+{
+ SECOidTag tag;
+ SECOidTag cipher;
+
+ /* future enhancement: provide 'friendlier' typed in names for
+ * pbe mechanisms.
+ */
+
+ /* look for the oid tag by Description */
+ tag = PKCS12U_FindTagFromString(cipherString);
+ if (tag == SEC_OID_UNKNOWN) {
+ return tag;
+ }
+
+ cipher = SEC_OID_UNKNOWN;
+ /* 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;
+ }
+ return cipher;
+}
+
+SECOidTag
+PKCS12U_MapHashFromString(char *hashString)
+{
+ SECOidTag hashAlg;
+
+ /* look for the oid tag by Description */
+ hashAlg = PKCS12U_FindTagFromString(hashString);
+ if (hashAlg == SEC_OID_UNKNOWN) {
+ return hashAlg;
+ }
+ /* make sure it's a hashing oid */
+ if (HASH_GetHashTypeByOidTag(hashAlg) == HASH_AlgNULL) {
+ return SEC_OID_UNKNOWN;
+ }
+ return hashAlg;
+}
+
+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_PKCS12EnableCipher(PKCS12_AES_CBC_128, 1);
+ SEC_PKCS12EnableCipher(PKCS12_AES_CBC_192, 1);
+ SEC_PKCS12EnableCipher(PKCS12_AES_CBC_256, 1);
+ SEC_PKCS12SetPreferredCipher(PKCS12_AES_CBC_256, 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,
+ opt_Mac
+};
+
+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" },
+ { /* opt_Mac */ 'M', PR_TRUE, 0, PR_FALSE, PR_FALSE }
+};
+
+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_AES_256_CBC;
+ SECOidTag hash = SEC_OID_SHA256;
+ SECOidTag certCipher = SEC_OID_AES_128_CBC;
+ int keyLen = 0;
+ int certKeyLen = 0;
+ secuCommand pk12util;
+ PRInt32 forceUnicode;
+
+#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();
+
+ 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();
+ }
+
+ if (pk12util.options[opt_Export].activated &&
+ !pk12util.options[opt_Nickname].activated) {
+ Usage();
+ }
+
+ rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE, &forceUnicode);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName,
+ "Failed to get NSS_PKCS12_DECODE_FORCE_UNICODE option");
+ Usage();
+ }
+ pk12uForceUnicode = forceUnicode;
+
+ 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;
+ }
+ }
+
+ 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 (certCipher == SEC_OID_UNKNOWN) {
+ PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+ SECU_PrintError(progName, "Algorithm: \"%s\"", cipherString);
+ pk12uErrno = PK12UERR_INVALIDALGORITHM;
+ goto done;
+ }
+ }
+ }
+ if (pk12util.options[opt_Mac].activated) {
+ char *hashString = pk12util.options[opt_Mac].arg;
+
+ hash = PKCS12U_MapHashFromString(hashString);
+ /* We don't support creating Mac-less pkcs 12 files */
+ if (hash == SEC_OID_UNKNOWN) {
+ PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+ SECU_PrintError(progName, "Algorithm: \"%s\"", hashString);
+ 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,
+ hash, &slotPw, &p12FilePw);
+
+ } else if (pk12util.options[opt_List].activated) {
+ P12U_ListPKCS12File(import_file, slot, &slotPw, &p12FilePw);
+
+ } else {
+ Usage();
+ 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 0000000000..5eb59e04b0
--- /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 0000000000..d1588814ef
--- /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 0000000000..6e1d4ecdfc
--- /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 0000000000..0094611668
--- /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 0000000000..a4482bde61
--- /dev/null
+++ b/security/nss/cmd/pk1sign/pk1sign.c
@@ -0,0 +1,317 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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) {
+ PR_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 0000000000..ff77c55755
--- /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 0000000000..6e1d4ecdfc
--- /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 0000000000..bef0636921
--- /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 0000000000..51608e49e8
--- /dev/null
+++ b/security/nss/cmd/pkix-errcodes/pkix-errcodes.c
@@ -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/. */
+/*
+ * 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 0000000000..e305c07f81
--- /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 0000000000..9963bdd336
--- /dev/null
+++ b/security/nss/cmd/platlibs.gypi
@@ -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/.
+{
+ '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/sqlite/sqlite.gyp:sqlite3',
+ '<(DEPTH)/lib/libpkix/libpkix.gyp:libpkix',
+ ],
+ 'conditions': [
+ [ 'disable_dbm==0', {
+ 'dependencies': [
+ '<(DEPTH)/lib/dbm/src/src.gyp:dbm',
+ '<(DEPTH)/lib/softoken/legacydb/legacydb.gyp:nssdbm',
+ ],
+ }],
+ ]},{ # !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 0000000000..6401778826
--- /dev/null
+++ b/security/nss/cmd/platlibs.mk
@@ -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/.
+
+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
+
+ifeq ($(NSS_BUILD_UTIL_ONLY),1)
+SECTOOL_LIB = $(NULL)
+else
+SECTOOL_LIB = $(DIST)/lib/$(LIB_PREFIX)sectool.$(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=
+NSS_LIBS_2=
+NSS_LIBS_3=
+NSS_LIBS_4=
+
+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)
+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 += \
+ $(SECTOOL_LIB) \
+ $(NSS_LIBS_1) \
+ $(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 += \
+ $(SECTOOL_LIB) \
+ $(NSS_LIBS_1) \
+ $(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 += \
+ $(SECTOOL_LIB) \
+ $(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 += \
+ $(SECTOOL_LIB) \
+ $(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 \
+ -L$(NSSUTIL_LIB_DIR) \
+ -lnssutil3 \
+ -L$(NSPR_LIB_DIR) \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+ifndef NSS_BUILD_UTIL_ONLY
+ifndef NSS_BUILD_SOFTOKEN_ONLY
+EXTRA_SHARED_LIBS += \
+ -lssl3 \
+ -lsmime3 \
+ -lnss3
+endif
+endif
+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 0000000000..54586bfd86
--- /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 0000000000..6e1d4ecdfc
--- /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 0000000000..de6126ae4a
--- /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 0000000000..b89b9ad0d9
--- /dev/null
+++ b/security/nss/cmd/pp/pp.c
@@ -0,0 +1,200 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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");
+ fprintf(stderr, " %s (sk),", SEC_CT_PRIVATE_KEY);
+ 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 (p12), %s or %s (n).\n", "",
+ SEC_CT_CERTIFICATE_ID, SEC_CT_PKCS7, SEC_CT_PKCS12,
+ 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);
+ PORT_Free(typeTag);
+ PL_DestroyOptState(optstate);
+ 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);
+ PORT_Free(typeTag);
+ PL_DestroyOptState(optstate);
+ 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);
+ } else if (PORT_Strcmp(typeTag, SEC_CT_PRIVATE_KEY) == 0 ||
+ PORT_Strcmp(typeTag, "sk") == 0) {
+ rv = SECU_PrintPrivateKey(outFile, &data, "Private Key", 0);
+ } 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 if (PORT_Strcmp(typeTag, SEC_CT_PKCS12) == 0 ||
+ PORT_Strcmp(typeTag, "p12") == 0) {
+ rv = SECU_PrintPKCS12(outFile, &data, "PKCS #12 File", 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 0000000000..c0fef6ac95
--- /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 0000000000..2aaef8fe5b
--- /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 0000000000..142a773caa
--- /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 0000000000..be12e9354a
--- /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 0000000000..265ea56015
--- /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 0000000000..51cb8c8f3c
--- /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 0000000000..486486770f
--- /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 0000000000..c3ae8eeb99
--- /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 0000000000..7b74b369c7
--- /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 0000000000..3ca366fa77
--- /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 0000000000..14fce7271b
--- /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 0000000000..292b40b0f1
--- /dev/null
+++ b/security/nss/cmd/rsaperf/rsaperf.c
@@ -0,0 +1,695 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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(int);
+extern NSSLOWKEYPublicKey *getDefaultRSAPublicKey(int);
+
+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 *rsaKeyPtr = 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;
+ rsaKeyPtr = (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;
+ rsaKeyPtr = (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;
+ rsaKeyPtr = (void *)pubHighKey;
+ } else {
+ /* do private key operations */
+ fn = (RSAOp)PK11_PrivateKeyOp;
+ keys.privKey = privHighKey;
+ keys.pubKey = pubHighKey;
+ rsaKeyPtr = (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;
+
+ rsaKeyPtr = 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(keybits);
+ } else {
+ privKey = getDefaultRSAPrivateKey(keybits);
+ }
+ }
+
+ if (doPub) {
+ /* do public key operations */
+ fn = (RSAOp)RSA_PublicKeyOp;
+ if (rsaKeyPtr) {
+ /* convert the RSAPrivateKey to RSAPublicKey */
+ pubKeyStr.arena = NULL;
+ pubKeyStr.modulus = ((RSAPrivateKey *)rsaKeyPtr)->modulus;
+ pubKeyStr.publicExponent =
+ ((RSAPrivateKey *)rsaKeyPtr)->publicExponent;
+ rsaKeyPtr = &pubKeyStr;
+ } else {
+ /* convert NSSLOWKeyPublicKey to RSAPublicKey */
+ rsaKeyPtr = (void *)(&pubKey->u.rsa);
+ }
+ PORT_Assert(rsaKeyPtr);
+ } else {
+ /* do private key operations */
+ fn = (RSAOp)RSA_PrivateKeyOp;
+ if (privKey) {
+ /* convert NSSLOWKeyPrivateKey to RSAPrivateKey */
+ rsaKeyPtr = (void *)(&privKey->u.rsa);
+ }
+ PORT_Assert(rsaKeyPtr);
+ }
+ }
+
+ memset(buf, 1, sizeof buf);
+ rv = fn(rsaKeyPtr, 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 = rsaKeyPtr;
+ 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 0000000000..8ca4b4c500
--- /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 0000000000..a5e83efdfa
--- /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 0000000000..ddf561e575
--- /dev/null
+++ b/security/nss/cmd/rsapoptst/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
+
+REQUIRES = seccmd dbm softoken
+
+PROGRAM = rsapoptst
+
+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 0000000000..4b9618e3b0
--- /dev/null
+++ b/security/nss/cmd/rsapoptst/rsapoptst.c
@@ -0,0 +1,639 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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, modulus" }
+};
+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_ID, 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)
+
+static void
+dumphex(FILE *file, const unsigned char *cpval, int start, int end)
+{
+ int i;
+ for (i = start; i < end; i++) {
+ if ((i % 16) == 0)
+ fprintf(file, "\n ");
+ fprintf(file, " %02x", cpval[i]);
+ }
+ return;
+}
+
+void
+dumpTemplate(FILE *file, const CK_ATTRIBUTE *template, int start, int end)
+{
+ int i;
+ for (i = start; i < end; i++) {
+ unsigned char cval;
+ CK_ULONG ulval;
+ const unsigned char *cpval;
+
+ fprintf(file, "%s:", ATTR_STRING(template[i].type));
+ switch (template[i].ulValueLen) {
+ case 1:
+ cval = *(unsigned char *)template[i].pValue;
+ switch (cval) {
+ case 0:
+ fprintf(file, " false");
+ break;
+ case 1:
+ fprintf(file, " true");
+ break;
+ default:
+ fprintf(file, " %d (=0x%02x,'%c')", cval, cval, cval);
+ break;
+ }
+ break;
+ case sizeof(CK_ULONG):
+ ulval = *(CK_ULONG *)template[i].pValue;
+ fprintf(file, " %ld (=0x%04lx)", ulval, ulval);
+ break;
+ default:
+ cpval = (const unsigned char *)template[i].pValue;
+ dumphex(file, cpval, 0, template[i].ulValueLen);
+ break;
+ }
+ fprintf(file, "\n");
+ }
+}
+
+void
+dumpItem(FILE *file, const SECItem *item)
+{
+ const unsigned char *cpval;
+
+ if (item == NULL) {
+ fprintf(file, " pNULL ");
+ return;
+ }
+ if (item->data == NULL) {
+ fprintf(file, " NULL ");
+ return;
+ }
+ if (item->len == 0) {
+ fprintf(file, " Empty ");
+ return;
+ }
+ cpval = item->data;
+ dumphex(file, cpval, 0, item->len);
+ fprintf(file, " ");
+ return;
+}
+
+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;
+ }
+ rv = 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].type == CKA_ID) {
+ continue; /* we purposefully make the CKA_ID different */
+ }
+ 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(stderr, srcTemplate, 0, RSA_ATTRIBUTES);
+ fprintf(stderr, "created key:\n");
+ dumpTemplate(stderr, destTemplate, 0, RSA_ATTRIBUTES);
+ }
+ resetTemplate(srcTemplate, 0, RSA_ATTRIBUTES);
+ resetTemplate(destTemplate, 0, RSA_ATTRIBUTES);
+ return areEqual;
+}
+
+static int exp_exp_prime_fail_count = 0;
+
+#define LEAK_ID 0xf
+
+static int
+doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
+ int mask, int round, 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;
+ CK_BYTE cka_id[2] = { 0, 0 };
+ int failed = 0;
+ int leak_found; /* did we find the expected leak */
+ int expect_leak = 0; /* are we expecting a leak? */
+
+ 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);
+ tstTemplate[5].pValue = &cka_id[0];
+ tstTemplate[5].ulValueLen = sizeof(cka_id);
+ tstHeaderCount = 6;
+ cka_id[0] = round;
+
+ if (mask & 1) {
+ printf("%s\n", test_array[1].description);
+ resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
+ cka_id[1] = 0;
+ 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_CreateManagedGenericObject(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);
+ cka_id[1] = 1;
+ 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_CreateManagedGenericObject(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);
+ cka_id[1] = 2;
+
+ 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_CreateManagedGenericObject(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);
+ cka_id[1] = 3;
+ 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_CreateManagedGenericObject(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 & 0x10) {
+ printf("%s\n", test_array[5].description);
+ /* test the advanced case2, public exponent, private exponent, modulus
+ */
+ resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
+ cka_id[1] = LEAK_ID;
+
+ 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);
+
+ /* purposefully use the old version. This will create a leak */
+ 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;
+ }
+ expect_leak = 1;
+ if (tstPrivKey)
+ PK11_DestroyGenericObject(tstPrivKey);
+ }
+ resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
+ SECKEY_DestroyPrivateKey(rsaPrivKey);
+ SECKEY_DestroyPublicKey(rsaPubKey);
+
+ /* make sure we didn't leak */
+ leak_found = 0;
+ tstPrivKey = PK11_FindGenericObjects(slot, CKO_PRIVATE_KEY);
+ if (tstPrivKey) {
+ SECStatus rv;
+ PK11GenericObject *thisKey;
+ int i;
+
+ fprintf(stderr, "Leaking keys...\n");
+ for (i = 0, thisKey = tstPrivKey; thisKey; i++,
+ thisKey = PK11_GetNextGenericObject(thisKey)) {
+ SECItem id = { 0, NULL, 0 };
+
+ rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisKey,
+ CKA_ID, &id);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "Key %d: couldn't read CKA_ID: %s\n",
+ i, PORT_ErrorToString(PORT_GetError()));
+ continue;
+ }
+ fprintf(stderr, "id = { ");
+ dumpItem(stderr, &id);
+ fprintf(stderr, "};");
+ if (id.data[1] == LEAK_ID) {
+ fprintf(stderr, " ---> leak expected\n");
+ if (id.data[0] == round)
+ leak_found = 1;
+ } else {
+ if (id.len != sizeof(cka_id)) {
+ fprintf(stderr,
+ " ---> ERROR unexpected leak in generated key\n");
+ } else {
+ fprintf(stderr,
+ " ---> ERROR unexpected leak in constructed key\n");
+ }
+ failed = 1;
+ }
+ SECITEM_FreeItem(&id, PR_FALSE);
+ }
+ PK11_DestroyGenericObjects(tstPrivKey);
+ }
+ if (expect_leak && !leak_found) {
+ fprintf(stderr, "ERROR expected leak not found\n");
+ failed = 1;
+ }
+
+ 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, i, 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);
+ }
+ if (NSS_Shutdown() != SECSuccess) {
+ fprintf(stderr, "Shutdown failed\n");
+ ret = -1;
+ }
+ return ret;
+}
diff --git a/security/nss/cmd/rsapoptst/rsapoptst.gyp b/security/nss/cmd/rsapoptst/rsapoptst.gyp
new file mode 100644
index 0000000000..325a109095
--- /dev/null
+++ b/security/nss/cmd/rsapoptst/rsapoptst.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': 'rsapoptst',
+ 'type': 'executable',
+ 'sources': [
+ 'rsapoptst.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports',
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss',
+ }
+}
diff --git a/security/nss/cmd/samples/cert b/security/nss/cmd/samples/cert
new file mode 100644
index 0000000000..3f8ec48df2
--- /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 0000000000..05cdc8553e
--- /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 0000000000..38a7d299a6
--- /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 0000000000..147c3eb9ee
--- /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 0000000000..6e3814c37f
--- /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 0000000000..0ee6cfc133
--- /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 0000000000..df2bb2dd18
--- /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 0000000000..c46a1786d7
--- /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 0000000000..1ada57c567
--- /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 0000000000..dde307697f
--- /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/sdbthreadtst/Makefile b/security/nss/cmd/sdbthreadtst/Makefile
new file mode 100644
index 0000000000..d7c879aec2
--- /dev/null
+++ b/security/nss/cmd/sdbthreadtst/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/sdbthreadtst/manifest.mn b/security/nss/cmd/sdbthreadtst/manifest.mn
new file mode 100644
index 0000000000..cf97660031
--- /dev/null
+++ b/security/nss/cmd/sdbthreadtst/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 = \
+ sdbthreadtst.c \
+ $(NULL)
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+
+PROGRAM = sdbthreadtst
+
+# USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/sdbthreadtst/sdbthreadtst.c b/security/nss/cmd/sdbthreadtst/sdbthreadtst.c
new file mode 100644
index 0000000000..6ea429a9ef
--- /dev/null
+++ b/security/nss/cmd/sdbthreadtst/sdbthreadtst.c
@@ -0,0 +1,217 @@
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <nss.h>
+#include <prtypes.h>
+#include <prerr.h>
+#include <prerror.h>
+#include <prthread.h>
+#include <pk11pub.h>
+#include <keyhi.h>
+
+#define MAX_THREAD_COUNT 100
+
+/* globals */
+int THREAD_COUNT = 30;
+int FAILED = 0;
+int ERROR = 0;
+int LOOP_COUNT = 100;
+int KEY_SIZE = 3072;
+int STACK_SIZE = 0;
+int VERBOSE = 0;
+char *NSSDIR = ".";
+PRBool ISTOKEN = PR_TRUE;
+CK_MECHANISM_TYPE MECHANISM = CKM_RSA_PKCS_KEY_PAIR_GEN;
+
+void
+usage(char *prog, char *error)
+{
+ if (error) {
+ fprintf(stderr, "Bad Arguments: %s", error);
+ }
+ fprintf(stderr, "usage: %s [-l loop_count] [-t thread_count] "
+ "[-k key_size] [-s stack_size] [-d nss_dir] [-e] [-v] [-h]\n",
+ prog);
+ fprintf(stderr, " loop_count -- "
+ "number of keys to generate on each thread (default=%d)\n",
+ LOOP_COUNT);
+ fprintf(stderr, " thread_count -- "
+ "number of of concurrent threads to run (def=%d,max=%d)\n",
+ THREAD_COUNT, MAX_THREAD_COUNT);
+ fprintf(stderr, " key_size -- "
+ "rsa key size in bits (default=%d)\n",
+ KEY_SIZE);
+ fprintf(stderr, " stack_size -- "
+ "thread stack size in bytes, 0=optimal (default=%d)\n",
+ STACK_SIZE);
+ fprintf(stderr, " nss_dir -- "
+ "location of the nss directory (default=%s)\n",
+ NSSDIR);
+ fprintf(stderr, " -e use session keys rather than token keys\n");
+ fprintf(stderr, " -v verbose, print progress indicators\n");
+ fprintf(stderr, " -h print this message\n");
+ exit(2);
+}
+
+void
+create_key_loop(void *arg)
+{
+ int i;
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot();
+ PK11RSAGenParams param;
+ int threadnumber = *(int *)arg;
+ int failures = 0;
+ int progress = 5;
+ PRIntervalTime epoch = PR_IntervalNow();
+ param.keySizeInBits = KEY_SIZE;
+ param.pe = 0x10001L;
+ printf(" - thread %d starting\n", threadnumber);
+ progress = 30 / THREAD_COUNT;
+ if (progress < 2)
+ progress = 2;
+ for (i = 0; i < LOOP_COUNT; i++) {
+ SECKEYPrivateKey *privKey;
+ SECKEYPublicKey *pubKey;
+ privKey = PK11_GenerateKeyPair(slot, MECHANISM, &param, &pubKey,
+ ISTOKEN, PR_TRUE, NULL);
+ if (privKey == NULL) {
+ fprintf(stderr,
+ "keypair gen in thread %d failed %s\n", threadnumber,
+ PORT_ErrorToString(PORT_GetError()));
+ FAILED++;
+ failures++;
+ }
+ if (VERBOSE && (i % progress) == 0) {
+ PRIntervalTime current = PR_IntervalNow();
+ PRIntervalTime interval = current - epoch;
+ int seconds = (interval / PR_TicksPerSecond());
+ int mseconds = ((interval * 1000) / PR_TicksPerSecond()) - (seconds * 1000);
+ epoch = current;
+ printf(" - thread %d @ %d iterations %d.%03d sec\n", threadnumber,
+ i, seconds, mseconds);
+ }
+ if (ISTOKEN && privKey) {
+ SECKEY_DestroyPublicKey(pubKey);
+ SECKEY_DestroyPrivateKey(privKey);
+ }
+ }
+ PK11_FreeSlot(slot);
+ printf(" * thread %d ending with %d failures\n", threadnumber, failures);
+ return;
+}
+
+int
+main(int argc, char **argv)
+{
+ PRThread *thread[MAX_THREAD_COUNT];
+ int threadnumber[MAX_THREAD_COUNT];
+ int i;
+ PRStatus status;
+ SECStatus rv;
+ char *prog = *argv++;
+ char buf[2048];
+ char *arg;
+
+ while ((arg = *argv++) != NULL) {
+ if (*arg == '-') {
+ switch (arg[1]) {
+ case 'l':
+ if (*argv == NULL)
+ usage(prog, "missing loop count");
+ LOOP_COUNT = atoi(*argv++);
+ break;
+ case 'k':
+ if (*argv == NULL)
+ usage(prog, "missing key size");
+ KEY_SIZE = atoi(*argv++);
+ break;
+ case 's':
+ if (*argv == NULL)
+ usage(prog, "missing stack size");
+ STACK_SIZE = atoi(*argv++);
+ break;
+ case 't':
+ if (*argv == NULL)
+ usage(prog, "missing thread count");
+ THREAD_COUNT = atoi(*argv++);
+ if (THREAD_COUNT > MAX_THREAD_COUNT) {
+ usage(prog, "max thread count exceeded");
+ }
+ break;
+ case 'v':
+ VERBOSE = 1;
+ break;
+ case 'd':
+ if (*argv == NULL)
+ usage(prog, "missing directory");
+ NSSDIR = *argv++;
+ break;
+ case 'e':
+ ISTOKEN = PR_FALSE;
+ break;
+ case 'h':
+ usage(prog, NULL);
+ break;
+ default:
+ snprintf(buf, sizeof(buf), "unknown option %c", arg[1]);
+ usage(prog, buf);
+ }
+ } else {
+ snprintf(buf, sizeof(buf), "unknown argument %s", arg);
+ usage(prog, buf);
+ }
+ }
+ /* initialize NSS */
+ rv = NSS_InitReadWrite(NSSDIR);
+ if (rv != SECSuccess) {
+ fprintf(stderr,
+ "NSS_InitReadWrite(%s) failed(%s)\n", NSSDIR,
+ PORT_ErrorToString(PORT_GetError()));
+ exit(2);
+ }
+
+ /* need to initialize the database here if it's not already */
+
+ printf("creating %d threads\n", THREAD_COUNT);
+ for (i = 0; i < THREAD_COUNT; i++) {
+ threadnumber[i] = i;
+ thread[i] = PR_CreateThread(PR_USER_THREAD, create_key_loop,
+ &threadnumber[i], PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD, STACK_SIZE);
+ if (thread[i] == NULL) {
+ ERROR++;
+ fprintf(stderr,
+ "PR_CreateThread failed iteration %d, %s\n", i,
+ PORT_ErrorToString(PORT_GetError()));
+ }
+ }
+ printf("waiting on %d threads\n", THREAD_COUNT);
+ for (i = 0; i < THREAD_COUNT; i++) {
+ if (thread[i] == NULL) {
+ continue;
+ }
+ status = PR_JoinThread(thread[i]);
+ if (status != PR_SUCCESS) {
+ ERROR++;
+ fprintf(stderr,
+ "PR_CreateThread filed iteration %d, %s\n", i,
+ PORT_ErrorToString(PORT_GetError()));
+ }
+ }
+ if (NSS_Shutdown() != SECSuccess) {
+ ERROR++;
+ fprintf(stderr, "NSS_Shutdown failed: %s\n",
+ PORT_ErrorToString(PORT_GetError()));
+ }
+ printf("%d failures and %d errors found\n", FAILED, ERROR);
+ /* clean up */
+ if (FAILED) {
+ exit(1);
+ }
+ if (ERROR) {
+ exit(2);
+ }
+ exit(0);
+}
diff --git a/security/nss/cmd/sdbthreadtst/sdbthreadtst.gyp b/security/nss/cmd/sdbthreadtst/sdbthreadtst.gyp
new file mode 100644
index 0000000000..e801b16ac1
--- /dev/null
+++ b/security/nss/cmd/sdbthreadtst/sdbthreadtst.gyp
@@ -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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'sdbthreadtst',
+ 'type': 'executable',
+ 'sources': [
+ 'sdbthreadtst.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/cmd/sdrtest/Makefile b/security/nss/cmd/sdrtest/Makefile
new file mode 100644
index 0000000000..265ea56015
--- /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 0000000000..d0c67450f8
--- /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 0000000000..651c63b24e
--- /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 0000000000..c544e17d89
--- /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 0000000000..7b74b369c7
--- /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 0000000000..a170169c8b
--- /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 0000000000..77e1dcbf47
--- /dev/null
+++ b/security/nss/cmd/selfserv/selfserv.c
@@ -0,0 +1,3149 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 "sslexp.h"
+#include "cert.h"
+#include "certt.h"
+#include "ocsp.h"
+#include "nssb64.h"
+
+#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 *);
+
+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*/
+SECItem psk = { siBuffer, NULL, 0 };
+SECItem pskLabel = { siBuffer, NULL, 0 };
+char *echParamsStr = NULL;
+
+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 [-BDENRZbjlmrsuvx] [-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]\n"
+ " [-I groups] [-J signatureschemes] [-e ec_nickname]\n"
+ " -U [0|1] -H [0|1|2] -W [0|1] [-z externalPsk]\n"
+ "\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 tls1.3\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"
+ "-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 [RFC7919]\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"
+ " xyber768d00\n"
+ "-J comma separated list of enabled signature schemes in preference order.\n"
+ " The following values are valid:\n"
+ " rsa_pkcs1_sha1, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512,\n"
+ " ecdsa_sha1, ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384,\n"
+ " ecdsa_secp521r1_sha512,\n"
+ " rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512,\n"
+ " rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512,\n"
+ "-Z enable 0-RTT (for TLS 1.3; also use -u)\n"
+ "-E enable post-handshake authentication\n"
+ " (for TLS 1.3; only has an effect with 3 or more -r options)\n"
+ "-x Export and print keying material after successful handshake\n"
+ " The argument is a comma separated list of exporters in the form:\n"
+ " LABEL[:OUTPUT-LENGTH[:CONTEXT]]\n"
+ " where LABEL and CONTEXT can be either a free-form string or\n"
+ " a hex string if it is preceded by \"0x\"; OUTPUT-LENGTH\n"
+ " is a decimal integer.\n"
+ "-z Configure a TLS 1.3 External PSK with the given hex string for a key.\n"
+ " To specify a label, use ':' as a delimiter. For example:\n"
+ " 0xAAAABBBBCCCCDDDD:mylabel. Otherwise, the default label of\n"
+ " 'Client_identity' will be used.\n"
+ "-X Configure the server for ECH via the given <ECHParams>. ECHParams\n"
+ " are expected in one of two formats:\n"
+ " 1. A string containing the ECH public name prefixed by the substring\n"
+ " \"publicname:\". For example, \"publicname:example.com\". In this mode,\n"
+ " an ephemeral ECH keypair is generated and ECHConfigs are printed to stdout.\n"
+ " 2. As a Base64 tuple of <ECHRawPrivateKey> || <ECHConfigs>. In this mode, the\n"
+ " raw private key is used to bootstrap the HPKE context.\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%s\n",
+ channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
+ suite.effectiveKeyBits, suite.symCipherName,
+ suite.macBits, suite.macAlgorithmName,
+ channel.isFIPS ? " FIPS" : "");
+ 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;
+} 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);
+
+typedef enum { rs_idle = 0,
+ rs_running = 1,
+ rs_zombie = 2 } runState;
+
+typedef struct perThreadStr {
+ PRFileDesc *a;
+ PRFileDesc *b;
+ 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);
+
+ /* 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)
+{
+ 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);
+ 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,
+ 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->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 failedToNegotiateName = PR_FALSE;
+PRBool enableExtendedMasterSecret = PR_FALSE;
+PRBool zeroRTT = PR_FALSE;
+SSLAntiReplayContext *antiReplay = NULL;
+PRBool enableALPN = PR_FALSE;
+PRBool enablePostHandshakeAuth = PR_FALSE;
+SSLNamedGroup *enabledGroups = NULL;
+unsigned int enabledGroupsCount = 0;
+const SSLSignatureScheme *enabledSigSchemes = NULL;
+unsigned int enabledSigSchemeCount = 0;
+const secuExporter *enabledExporters = NULL;
+unsigned int enabledExporterCount = 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 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)
+{
+ 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);
+
+ 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,
+ 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 (ocspStaplingMode) {
+ 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,
+ (ocspStaplingMode == 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,
+ 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, 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)
+{
+ 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) {
+ 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;
+ }
+ if (enablePostHandshakeAuth) {
+ rv = SSL_SendCertificateRequest(ssl_sock);
+ if (rv != SECSuccess) {
+ errWarn("SSL_SendCertificateRequest");
+ break;
+ }
+ rv = SSL_ForceHandshake(ssl_sock);
+ if (rv != SECSuccess) {
+ errWarn("SSL_ForceHandshake");
+ break;
+ }
+ } else {
+ 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 */
+ snprintf(msgBuf, sizeof(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) {
+ snprintf(msgBuf, sizeof(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)
+{
+ 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;
+ }
+
+ 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 = NULL;
+ int listenQueueDepth = 5 + (2 * maxThreads);
+ PRStatus prStatus;
+ PRNetAddr addr;
+ PRSocketOptionData opt;
+
+ // We want to listen on the IP family that tstclnt will use.
+ // tstclnt uses PR_GetPrefLoopbackAddrInfo to decide, if it's
+ // asked to connect to localhost.
+
+ prStatus = PR_GetPrefLoopbackAddrInfo(&addr, port);
+ if (prStatus == PR_FAILURE) {
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_htonl(PR_INADDR_ANY);
+ addr.inet.port = PR_htons(port);
+ }
+
+ if (addr.inet.family == PR_AF_INET6) {
+ listen_sock = PR_OpenTCPSocket(PR_AF_INET6);
+ } else if (addr.inet.family == PR_AF_INET) {
+ listen_sock = PR_NewTCPSocket();
+ }
+ if (listen_sock == NULL) {
+ errExit("Couldn't create socket");
+ }
+
+ 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);
+ }
+ }
+ if (enabledExporters) {
+ SECStatus rv = exportKeyingMaterials(fd, enabledExporters, enabledExporterCount);
+ if (rv != SECSuccess) {
+ PRErrorCode err = PR_GetError();
+ fprintf(stderr,
+ "couldn't export keying material: %s\n",
+ SECU_Strerror(err));
+ }
+ }
+}
+
+static SECStatus
+importPsk(PRFileDesc *model_sock)
+{
+ SECU_PrintAsHex(stdout, &psk, "Using External PSK", 0);
+ PK11SlotInfo *slot = NULL;
+ PK11SymKey *symKey = NULL;
+ slot = PK11_GetInternalSlot();
+ if (!slot) {
+ errWarn("PK11_GetInternalSlot failed");
+ return SECFailure;
+ }
+ symKey = PK11_ImportSymKey(slot, CKM_HKDF_KEY_GEN, PK11_OriginUnwrap,
+ CKA_DERIVE, &psk, NULL);
+ PK11_FreeSlot(slot);
+ if (!symKey) {
+ errWarn("PK11_ImportSymKey failed\n");
+ return SECFailure;
+ }
+
+ SECStatus rv = SSL_AddExternalPsk(model_sock, symKey,
+ (const PRUint8 *)pskLabel.data,
+ pskLabel.len, ssl_hash_sha256);
+ PK11_FreeSymKey(symKey);
+ return rv;
+}
+
+static SECStatus
+configureEchWithPublicName(PRFileDesc *model_sock, const char *public_name)
+{
+ SECStatus rv;
+
+#define OID_LEN 65
+ unsigned char paramBuf[OID_LEN];
+ SECItem ecParams = { siBuffer, paramBuf, sizeof(paramBuf) };
+ SECKEYPublicKey *pubKey = NULL;
+ SECKEYPrivateKey *privKey = NULL;
+ SECOidData *oidData;
+ char *echConfigBase64 = NULL;
+ PRUint8 configId = 0;
+ PRUint8 configBuf[1000];
+ unsigned int len = 0;
+ HpkeSymmetricSuite echCipherSuite = { HpkeKdfHkdfSha256,
+ HpkeAeadChaCha20Poly1305 };
+
+ PK11SlotInfo *slot = PK11_GetInternalKeySlot();
+ if (!slot) {
+ errWarn("PK11_GetInternalKeySlot failed");
+ return SECFailure;
+ }
+
+ if (PK11_GenerateRandom(&configId, sizeof(configId)) != SECSuccess) {
+ errWarn("Failed to generate random configId");
+ goto loser;
+ }
+
+ oidData = SECOID_FindOIDByTag(SEC_OID_CURVE25519);
+ if (oidData && (2 + oidData->oid.len) < sizeof(paramBuf)) {
+ ecParams.data[0] = SEC_ASN1_OBJECT_ID;
+ ecParams.data[1] = oidData->oid.len;
+ memcpy(ecParams.data + 2, oidData->oid.data, oidData->oid.len);
+ ecParams.len = oidData->oid.len + 2;
+ } else {
+ errWarn("SECOID_FindOIDByTag failed");
+ goto loser;
+ }
+ privKey = PK11_GenerateKeyPair(slot, CKM_EC_KEY_PAIR_GEN, &ecParams,
+ &pubKey, PR_FALSE, PR_FALSE, NULL);
+ if (!privKey || !pubKey) {
+ errWarn("Failed to generate ECH keypair");
+ goto loser;
+ }
+
+ rv = SSL_EncodeEchConfigId(configId, public_name, 100,
+ HpkeDhKemX25519Sha256, pubKey,
+ &echCipherSuite, 1,
+ configBuf, &len, sizeof(configBuf));
+ if (rv != SECSuccess) {
+ errWarn("SSL_EncodeEchConfigId failed");
+ goto loser;
+ }
+
+ rv = SSL_SetServerEchConfigs(model_sock, pubKey, privKey, configBuf, len);
+ if (rv != SECSuccess) {
+ errWarn("SSL_SetServerEchConfigs failed");
+ goto loser;
+ }
+
+ SECItem echConfigItem = { siBuffer, configBuf, len };
+ echConfigBase64 = NSSBase64_EncodeItem(NULL, NULL, 0, &echConfigItem);
+ if (!echConfigBase64) {
+ errWarn("NSSBase64_EncodeItem failed");
+ goto loser;
+ }
+
+ // Remove the newline characters that NSSBase64_EncodeItem unhelpfully inserts.
+ char *newline = strstr(echConfigBase64, "\r\n");
+ if (newline) {
+ memmove(newline, newline + 2, strlen(newline + 2) + 1);
+ }
+
+ printf("%s\n", echConfigBase64);
+ PORT_Free(echConfigBase64);
+ SECKEY_DestroyPrivateKey(privKey);
+ SECKEY_DestroyPublicKey(pubKey);
+ PK11_FreeSlot(slot);
+ return SECSuccess;
+
+loser:
+ PORT_Free(echConfigBase64);
+ SECKEY_DestroyPrivateKey(privKey);
+ SECKEY_DestroyPublicKey(pubKey);
+ PK11_FreeSlot(slot);
+ return SECFailure;
+}
+
+static SECStatus
+configureEchWithData(PRFileDesc *model_sock)
+{
+ /* The input should be a Base64-encoded ECHKey struct:
+ * struct {
+ * opaque pkcs8_ech_keypair<0..2^16-1>;
+ * ECHConfigs configs<0..2^16>; // draft-ietf-tls-esni-09
+ * } ECHKey;
+ *
+ * This is not a standardized format, rather it's designed for
+ * interoperability with https://github.com/xvzcf/tls-interop-runner.
+ * It is the user's responsibility to ensure that the PKCS8 keypair
+ * corresponds to the public key embedded in the ECHConfigs.
+ */
+
+#define REMAINING_BYTES(rdr, buf) \
+ buf->len - (rdr - buf->data)
+
+ SECStatus rv;
+ size_t len;
+ unsigned char *reader;
+ PK11SlotInfo *slot = NULL;
+ SECItem *decoded = NULL;
+ SECKEYPublicKey *pk = NULL;
+ SECKEYPrivateKey *sk = NULL;
+ SECItem pkcs8Key = { siBuffer, NULL, 0 };
+
+ decoded = NSSBase64_DecodeBuffer(NULL, NULL, echParamsStr, PORT_Strlen(echParamsStr));
+ if (!decoded || decoded->len < 2) {
+ errWarn("Couldn't decode ECHParams");
+ goto loser;
+ };
+ reader = decoded->data;
+
+ len = (*(reader++) << 8);
+ len |= *(reader++);
+ if (len > (REMAINING_BYTES(reader, decoded) - 2)) {
+ errWarn("Bad ECHParams encoding");
+ goto loser;
+ }
+ pkcs8Key.data = reader;
+ pkcs8Key.len = len;
+ reader += len;
+
+ /* Convert the key bytes to key handles */
+ slot = PK11_GetInternalKeySlot();
+ rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
+ slot, &pkcs8Key, NULL, NULL, PR_FALSE, PR_FALSE, KU_ALL, &sk, NULL);
+ if (rv != SECSuccess || !sk) {
+ errWarn("ECH key import failed");
+ goto loser;
+ }
+ pk = SECKEY_ConvertToPublicKey(sk);
+ if (!pk) {
+ errWarn("ECH key conversion failed");
+ goto loser;
+ }
+
+ /* Remainder is the ECHConfigs. */
+ rv = SSL_SetServerEchConfigs(model_sock, pk, sk, reader,
+ REMAINING_BYTES(reader, decoded));
+ if (rv != SECSuccess) {
+ errWarn("SSL_SetServerEchConfigs failed");
+ goto loser;
+ }
+
+ PK11_FreeSlot(slot);
+ SECKEY_DestroyPrivateKey(sk);
+ SECKEY_DestroyPublicKey(pk);
+ SECITEM_FreeItem(decoded, PR_TRUE);
+ return SECSuccess;
+loser:
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ SECKEY_DestroyPrivateKey(sk);
+ SECKEY_DestroyPublicKey(pk);
+ SECITEM_FreeItem(decoded, PR_TRUE);
+ return SECFailure;
+}
+
+static SECStatus
+configureEch(PRFileDesc *model_sock)
+{
+ if (!PORT_Strncmp(echParamsStr, "publicname:", PORT_Strlen("publicname:"))) {
+ return configureEchWithPublicName(model_sock,
+ &echParamsStr[PORT_Strlen("publicname:")]);
+ }
+ return configureEchWithData(model_sock);
+}
+
+void
+server_main(
+ PRFileDesc *listen_sock,
+ 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 (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, NULL, 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_SetAntiReplayContext(model_sock, antiReplay);
+ if (rv != SECSuccess) {
+ errExit("error configuring anti-replay ");
+ }
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_0RTT_DATA, PR_TRUE);
+ if (rv != SECSuccess) {
+ errExit("error enabling 0RTT ");
+ }
+ }
+
+ if (enablePostHandshakeAuth) {
+ if (enabledVersions.max < SSL_LIBRARY_VERSION_TLS_1_3) {
+ errExit("You tried enabling post-handshake auth without enabling TLS 1.3!");
+ }
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE);
+ if (rv != SECSuccess) {
+ errExit("error enabling post-handshake auth");
+ }
+ }
+
+ 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");
+ }
+ }
+
+ if (enabledSigSchemes) {
+ rv = SSL_SignatureSchemePrefSet(model_sock, enabledSigSchemes, enabledSigSchemeCount);
+ if (rv < 0) {
+ errExit("SSL_SignatureSchemePrefSet 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 || enabledExporters) {
+ 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 (psk.data) {
+ rv = importPsk(model_sock);
+ if (rv != SECSuccess) {
+ errExit("importPsk failed");
+ }
+ }
+
+ if (echParamsStr) {
+ rv = configureEch(model_sock);
+ if (rv != SECSuccess) {
+ errExit("configureEch failed");
+ }
+ }
+
+ 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);
+
+ 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;
+}
+
+#ifdef XP_UNIX
+void
+sigusr1_parent_handler(int sig)
+{
+ PRProcess *process;
+ int i;
+ fprintf(stderr, "SIG_USER: Parent got sig_user, killing children (%d).\n", numChildren);
+ for (i = 0; i < numChildren; i++) {
+ process = child[i];
+ PR_KillProcess(process); /* it would be nice to kill with a sigusr signal */
+ }
+}
+#endif
+
+void
+beAGoodParent(int argc, char **argv, int maxProcs, PRFileDesc *listen_sock)
+{
+ PRProcess *newProcess;
+ PRProcessAttr *attr;
+ int i;
+ PRInt32 exitCode;
+ PRStatus rv;
+
+#ifdef XP_UNIX
+ struct sigaction act;
+
+ /* set up the signal handler */
+ act.sa_handler = sigusr1_parent_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ if (sigaction(SIGUSR1, &act, NULL)) {
+ fprintf(stderr, "Error installing signal handler.\n");
+ exit(1);
+ }
+#endif
+
+ 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', and 'q' 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:DEGH:I:J:L:M:NP:QRS:T:U:V:W:X:YZa:bc:d:e:f:g:hi:jk:lmn:op:rst:uvw:x: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 'E':
+ enablePostHandshakeAuth = 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) {
+ fprintf(stderr, "Bad version specified.\n");
+ Usage(progName);
+ exit(1);
+ }
+ 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;
+
+ case 'e':
+ if (certNicknameIndex >= MAX_CERT_NICKNAME_ARRAY_INDEX) {
+ Usage(progName);
+ break;
+ }
+ certNicknameArray[certNicknameIndex++] = PORT_Strdup(optstate->value);
+ break;
+
+ 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':
+ zeroRTT = PR_TRUE;
+ break;
+
+ case 'z':
+ rv = readPSK(optstate->value, &psk, &pskLabel);
+ if (rv != SECSuccess) {
+ PL_DestroyOptState(optstate);
+ fprintf(stderr, "Bad PSK specified.\n");
+ Usage(progName);
+ exit(1);
+ }
+ 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;
+
+ case 'J':
+ rv = parseSigSchemeList(optstate->value, &enabledSigSchemes, &enabledSigSchemeCount);
+ if (rv != SECSuccess) {
+ PL_DestroyOptState(optstate);
+ fprintf(stderr, "Bad signature scheme specified.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(5);
+ }
+ break;
+
+ case 'x':
+ rv = parseExporters(optstate->value,
+ &enabledExporters, &enabledExporterCount);
+ if (rv != SECSuccess) {
+ PL_DestroyOptState(optstate);
+ fprintf(stderr, "Bad exporter specified.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(5);
+ }
+ break;
+
+ case 'X':
+ echParamsStr = PORT_Strdup(optstate->value);
+ if (echParamsStr == NULL) {
+ PL_DestroyOptState(optstate);
+ fprintf(stderr, "echParamsStr copy failed.\n");
+ exit(5);
+ }
+ break;
+ default:
+ case '?':
+ fprintf(stderr, "Unrecognized or bad option specified: %c\n", optstate->option);
+ 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);
+ }
+
+ envString = PR_GetEnvSecure(envVarName);
+ if (!envString && 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;
+ /* 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);
+ }
+ } 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 {
+ /* 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);
+ }
+ /* 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);
+
+ /* 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) {
+ rv = SSL_CipherPrefSetDefault(cipher, SSL_ALLOWED);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "SSL_CipherPrefSetDefault()");
+ exit(9);
+ }
+ } 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);
+ }
+ if (privKey[i]->keyType != ecKey)
+ setupCertStatus(certStatusArena, 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");
+ }
+ if (zeroRTT) {
+ rv = SSL_CreateAntiReplayContext(PR_Now(), 10L * PR_USEC_PER_SEC, 7, 14, &antiReplay);
+ if (rv != SECSuccess) {
+ errExit("Unable to create anti-replay context for 0-RTT.");
+ }
+ }
+
+ /* allocate the array of thread slots, and launch the worker threads. */
+ rv = launch_threads(&jobLoop, 0, 0, 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, 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);
+ }
+
+ {
+ 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 (antiReplay) {
+ SSL_ReleaseAntiReplayContext(antiReplay);
+ }
+ SECITEM_ZfreeItem(&psk, PR_FALSE);
+ SECITEM_ZfreeItem(&pskLabel, PR_FALSE);
+ PORT_Free(echParamsStr);
+ 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 0000000000..783be845ef
--- /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 0000000000..a1192055c1
--- /dev/null
+++ b/security/nss/cmd/shlibsign/Makefile
@@ -0,0 +1,101 @@
+#! 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
+ifdef CHECKLOC
+ $(MAKE) $(CHECKLOC)
+endif
diff --git a/security/nss/cmd/shlibsign/mangle/Makefile b/security/nss/cmd/shlibsign/mangle/Makefile
new file mode 100644
index 0000000000..b52243e01c
--- /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 0000000000..e58bbee410
--- /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 0000000000..1dd5c10d7c
--- /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 0000000000..40b4841cb1
--- /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 0000000000..95f8765b36
--- /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 0000000000..5745426ba4
--- /dev/null
+++ b/security/nss/cmd/shlibsign/shlibsign.c
@@ -0,0 +1,1643 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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
+
+#define COMPAT_MAJOR 0x01
+#define COMPAT_MINOR 0x02
+
+#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"
+
+/* nss headers for definition of HASH_HashType */
+#include "hasht.h"
+
+CK_BBOOL cktrue = CK_TRUE;
+CK_BBOOL ckfalse = CK_FALSE;
+static PRBool verbose = PR_FALSE;
+static PRBool verify = PR_FALSE;
+static PRBool compat = PR_FALSE;
+
+typedef struct HashTableStruct {
+ char *name;
+ CK_MECHANISM_TYPE hash;
+ CK_MECHANISM_TYPE hmac;
+ CK_KEY_TYPE keyType;
+ HASH_HashType hashType;
+ CK_ULONG hashLength;
+} HashTable;
+
+#define CKR_INTERNAL_OUT_FAILURE 0x80111111
+#define CKR_INTERNAL_IN_FAILURE 0x80222222
+#define CKM_SHA1 CKM_SHA_1
+#define CKM_SHA1_HMAC CKM_SHA_1_HMAC
+#define CKK_SHA1_HMAC CKK_SHA_1_HMAC
+#define MKHASH(name, mech) \
+ { \
+ name, CKM_##mech, CKM_##mech##_HMAC, \
+ CKK_##mech##_HMAC, HASH_Alg##mech, mech##_LENGTH \
+ }
+static HashTable hashTable[] = {
+ MKHASH("sha-1", SHA1), MKHASH("sha1", SHA1), MKHASH("sha224", SHA224),
+ MKHASH("sha256", SHA256), MKHASH("sha384", SHA384),
+ MKHASH("sha512", SHA512)
+};
+static size_t hashTableSize = PR_ARRAY_SIZE(hashTable);
+
+const HashTable *
+findHash(const char *hashName)
+{
+ int i;
+
+ for (i = 0; i < hashTableSize; i++) {
+ if (PL_strcasecmp(hashTable[i].name, hashName) == 0) {
+ return &hashTable[i];
+ }
+ }
+ return NULL;
+}
+
+static void
+usage(const char *program_name)
+{
+ int i;
+ const char *comma = "";
+ 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 ] [-t hash]"
+ " [-D] [-k keysize] [-c]"
+ "-i shared_library_name\n",
+ program_name);
+ PR_fprintf(debug_out, "Valid Hashes: ");
+ for (i = 0; i < hashTableSize; i++) {
+ PR_fprintf(debug_out, "%s%s", comma, hashTable[i].name);
+ comma = ", ";
+ }
+ PR_fprintf(debug_out, "\n");
+ exit(1);
+}
+
+static void
+long_usage(const char *program_name)
+{
+ PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
+ int i;
+ const char *comma = "";
+ 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-t <hash> Hash for HMAC/or DSA\n");
+ PR_fprintf(debug_out, "\t-D Sign with DSA rather than HMAC\n");
+ PR_fprintf(debug_out, "\t-k <keysize> size of the DSA key\n");
+ PR_fprintf(debug_out, "\t-c Use compatible versions for old NSS\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");
+ PR_fprintf(debug_out, "Valid Hashes: ");
+ for (i = 0; i < hashTableSize; i++) {
+ PR_fprintf(debug_out, "%s%s", comma, hashTable[i].name);
+ comma = ", ";
+ }
+ PR_fprintf(debug_out, "\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)
+{
+ 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) {
+ return PR_FAILURE;
+ }
+ bytesWritten = PR_Write(fd, pValue, ulValueLen);
+ if (bytesWritten < 0 || (CK_ULONG)bytesWritten != ulValueLen) {
+ 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_NSS_CERTDB_FAILED " },
+ { 0xCE534352, "CKR_NSS_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[500];
+ 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;
+}
+
+CK_RV
+shlibSignDSA(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID slot,
+ CK_SESSION_HANDLE hRwSession, int keySize, PRFileDesc *ifd,
+ PRFileDesc *ofd, const HashTable *hash)
+{
+ CK_MECHANISM digestmech;
+ CK_ULONG digestLen = 0;
+ CK_BYTE digest[HASH_LENGTH_MAX];
+ CK_BYTE sign[64]; /* DSA2 SIGNATURE LENGTH */
+ CK_ULONG signLen = 0;
+ CK_ULONG expectedSigLen = sizeof(sign);
+ CK_MECHANISM signMech = {
+ CKM_DSA, NULL, 0
+ };
+ int bytesRead;
+ int bytesWritten;
+ unsigned char file_buf[512];
+ NSSSignChkHeader header;
+ int count = 0;
+ CK_RV crv = CKR_GENERAL_ERROR;
+ PRStatus rv = PR_SUCCESS;
+ const char *hashName = "sha256"; /* default hash value */
+ int i;
+
+ /*** 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;
+
+ if ((keySize == 0) || (keySize > 1024)) {
+ CK_MECHANISM_INFO mechInfo;
+ crv = pFunctionList->C_GetMechanismInfo(slot,
+ CKM_DSA, &mechInfo);
+ if (crv != CKR_OK) {
+ pk11error("Couldn't get mechanism info for DSA", crv);
+ return crv;
+ }
+
+ if (keySize && (mechInfo.ulMaxKeySize < keySize)) {
+ PR_fprintf(PR_STDERR,
+ "token doesn't support DSA2 (Max key size=%d)\n",
+ mechInfo.ulMaxKeySize);
+ return crv;
+ }
+
+ 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);
+ hashName = "sha-1"; /* use sha-1 for old dsa keys */
+ expectedSigLen = 32;
+ } 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 = hash ? hash->hash : CKM_SHA256;
+ digestmech.pParameter = NULL;
+ digestmech.ulParameterLen = 0;
+ } else {
+ PR_fprintf(PR_STDERR, "Only keysizes 1024 and 2048 are supported");
+ return CKR_GENERAL_ERROR;
+ }
+ if (hash == NULL) {
+ hash = findHash(hashName);
+ }
+ if (hash == NULL) {
+ PR_fprintf(PR_STDERR,
+ "Internal error, couldn't find hash '%s' in table.\n",
+ hashName);
+ return CKR_GENERAL_ERROR;
+ }
+ digestmech.mechanism = hash->hash;
+ digestmech.pParameter = NULL;
+ digestmech.ulParameterLen = 0;
+ dsaPubKeyTemplate[3].type = CKA_TOKEN;
+ dsaPubKeyTemplate[3].pValue = &ckfalse; /* session object */
+ dsaPubKeyTemplate[3].ulValueLen = sizeof(ckfalse);
+ dsaPubKeyTemplate[4].type = CKA_VERIFY;
+ dsaPubKeyTemplate[4].pValue = &cktrue;
+ dsaPubKeyTemplate[4].ulValueLen = sizeof(cktrue);
+ dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN;
+ dsaKeyPairGenMech.pParameter = NULL;
+ dsaKeyPairGenMech.ulParameterLen = 0;
+ dsaPrivKeyTemplate[0].type = CKA_TOKEN;
+ dsaPrivKeyTemplate[0].pValue = &ckfalse; /* session object */
+ dsaPrivKeyTemplate[0].ulValueLen = sizeof(ckfalse);
+ dsaPrivKeyTemplate[1].type = CKA_PRIVATE;
+ dsaPrivKeyTemplate[1].pValue = &cktrue;
+ dsaPrivKeyTemplate[1].ulValueLen = sizeof(cktrue);
+ dsaPrivKeyTemplate[2].type = CKA_SENSITIVE;
+ dsaPrivKeyTemplate[2].pValue = &cktrue;
+ dsaPrivKeyTemplate[2].ulValueLen = sizeof(cktrue);
+ dsaPrivKeyTemplate[3].type = CKA_SIGN,
+ dsaPrivKeyTemplate[3].pValue = &cktrue;
+ dsaPrivKeyTemplate[3].ulValueLen = sizeof(cktrue);
+ dsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE;
+ dsaPrivKeyTemplate[4].pValue = &ckfalse;
+ dsaPrivKeyTemplate[4].ulValueLen = sizeof(ckfalse);
+
+ /* Generate a DSA key pair */
+ logIt("Generate a DSA key pair ... \n");
+ crv = pFunctionList->C_GenerateKeyPair(hRwSession, &dsaKeyPairGenMech,
+ dsaPubKeyTemplate,
+ PR_ARRAY_SIZE(dsaPubKeyTemplate),
+ dsaPrivKeyTemplate,
+ PR_ARRAY_SIZE(dsaPrivKeyTemplate),
+ &hDSApubKey, &hDSAprivKey);
+ if (crv != CKR_OK) {
+ pk11error("DSA key pair generation failed", crv);
+ return crv;
+ }
+
+ /* compute the digest */
+ memset(digest, 0, sizeof(digest));
+ crv = pFunctionList->C_DigestInit(hRwSession, &digestmech);
+ if (crv != CKR_OK) {
+ pk11error("C_DigestInit failed", crv);
+ return crv;
+ }
+
+ /* Digest the file */
+ while ((bytesRead = PR_Read(ifd, 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);
+ return crv;
+ }
+ count += bytesRead;
+ }
+
+ if (bytesRead < 0) {
+ lperror("0 bytes read from input file");
+ return CKR_INTERNAL_IN_FAILURE;
+ }
+
+ digestLen = sizeof(digest);
+ crv = pFunctionList->C_DigestFinal(hRwSession, (CK_BYTE_PTR)digest,
+ &digestLen);
+ if (crv != CKR_OK) {
+ pk11error("C_DigestFinal failed", crv);
+ return crv;
+ }
+
+ if (digestLen != hash->hashLength) {
+ PR_fprintf(PR_STDERR, "digestLen has incorrect length %lu "
+ "it should be %lu \n",
+ digestLen, sizeof(digest));
+ return crv;
+ }
+
+ /* 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);
+ return crv;
+ }
+
+ signLen = sizeof(sign);
+ crv = pFunctionList->C_Sign(hRwSession, (CK_BYTE *)digest, digestLen,
+ sign, &signLen);
+ if (crv != CKR_OK) {
+ pk11error("C_Sign failed", crv);
+ return crv;
+ }
+
+ if (signLen != expectedSigLen) {
+ PR_fprintf(PR_STDERR, "signLen has incorrect length %lu "
+ "it should be %lu \n",
+ signLen, expectedSigLen);
+ return crv;
+ }
+
+ if (verify) {
+ crv = pFunctionList->C_VerifyInit(hRwSession, &signMech, hDSApubKey);
+ if (crv != CKR_OK) {
+ pk11error("C_VerifyInit failed", crv);
+ return crv;
+ }
+ crv = pFunctionList->C_Verify(hRwSession, digest, digestLen,
+ sign, signLen);
+ if (crv != CKR_OK) {
+ pk11error("C_Verify failed", crv);
+ return crv;
+ }
+ }
+
+ if (verbose) {
+ int j;
+ PR_fprintf(PR_STDERR, "Library File Size: %d bytes\n", count);
+ 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");
+ }
+ }
+
+ /*
+ * 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.
+ */
+
+ header.magic1 = NSS_SIGN_CHK_MAGIC1;
+ header.magic2 = NSS_SIGN_CHK_MAGIC2;
+ header.majorVersion = compat ? COMPAT_MAJOR : NSS_SIGN_CHK_MAJOR_VERSION;
+ header.minorVersion = compat ? COMPAT_MINOR : NSS_SIGN_CHK_MINOR_VERSION;
+ encodeInt(header.offset, sizeof(header)); /* offset to data start */
+ encodeInt(header.type, CKK_DSA);
+ bytesWritten = PR_Write(ofd, &header, sizeof(header));
+ if (bytesWritten != sizeof(header)) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+
+ /* 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);
+ return crv;
+ }
+
+ /* CKA_PRIME */
+ rv = writeItem(ofd, dsaPubKeyTemplate[0].pValue,
+ dsaPubKeyTemplate[0].ulValueLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+ /* CKA_SUBPRIME */
+ rv = writeItem(ofd, dsaPubKeyTemplate[1].pValue,
+ dsaPubKeyTemplate[1].ulValueLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+ /* CKA_BASE */
+ rv = writeItem(ofd, dsaPubKeyTemplate[2].pValue,
+ dsaPubKeyTemplate[2].ulValueLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+ /* DSA Public Key value */
+ rv = writeItem(ofd, dsaPubKeyValue.pValue,
+ dsaPubKeyValue.ulValueLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+ /* DSA SIGNATURE */
+ rv = writeItem(ofd, &sign, signLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+
+ return CKR_OK;
+}
+
+CK_RV
+shlibSignHMAC(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID slot,
+ CK_SESSION_HANDLE hRwSession, int keySize, PRFileDesc *ifd,
+ PRFileDesc *ofd, const HashTable *hash)
+{
+ CK_MECHANISM hmacMech = { 0, NULL, 0 };
+ CK_MECHANISM hmacKeyGenMech = { 0, NULL, 0 };
+ CK_BYTE keyBuf[HASH_LENGTH_MAX];
+ CK_ULONG keyLen = 0;
+ CK_BYTE sign[HASH_LENGTH_MAX];
+ CK_ULONG signLen = 0;
+ int bytesRead;
+ int bytesWritten;
+ unsigned char file_buf[512];
+ NSSSignChkHeader header;
+ int count = 0;
+ CK_RV crv = CKR_GENERAL_ERROR;
+ PRStatus rv = PR_SUCCESS;
+ int i;
+
+ /*** HMAC Key ***/
+ CK_ATTRIBUTE hmacKeyTemplate[7];
+ CK_ATTRIBUTE hmacKeyValue;
+ CK_OBJECT_HANDLE hHMACKey = CK_INVALID_HANDLE;
+
+ if (hash == NULL) {
+ hash = findHash("sha256");
+ }
+ if (hash == NULL) {
+ PR_fprintf(PR_STDERR,
+ "Internal error:Could find sha256 entry in table.\n");
+ }
+
+ hmacKeyTemplate[0].type = CKA_TOKEN;
+ hmacKeyTemplate[0].pValue = &ckfalse; /* session object */
+ hmacKeyTemplate[0].ulValueLen = sizeof(ckfalse);
+ hmacKeyTemplate[1].type = CKA_PRIVATE;
+ hmacKeyTemplate[1].pValue = &cktrue;
+ hmacKeyTemplate[1].ulValueLen = sizeof(cktrue);
+ hmacKeyTemplate[2].type = CKA_SENSITIVE;
+ hmacKeyTemplate[2].pValue = &ckfalse;
+ hmacKeyTemplate[2].ulValueLen = sizeof(cktrue);
+ hmacKeyTemplate[3].type = CKA_SIGN;
+ hmacKeyTemplate[3].pValue = &cktrue;
+ hmacKeyTemplate[3].ulValueLen = sizeof(cktrue);
+ hmacKeyTemplate[4].type = CKA_EXTRACTABLE;
+ hmacKeyTemplate[4].pValue = &ckfalse;
+ hmacKeyTemplate[4].ulValueLen = sizeof(ckfalse);
+ hmacKeyTemplate[5].type = CKA_VALUE_LEN;
+ hmacKeyTemplate[5].pValue = (void *)&hash->hashLength;
+ hmacKeyTemplate[5].ulValueLen = sizeof(hash->hashLength);
+ hmacKeyTemplate[6].type = CKA_KEY_TYPE;
+ hmacKeyTemplate[6].pValue = (void *)&hash->keyType;
+ hmacKeyTemplate[6].ulValueLen = sizeof(hash->keyType);
+ hmacKeyGenMech.mechanism = CKM_GENERIC_SECRET_KEY_GEN;
+ hmacMech.mechanism = hash->hmac;
+
+ /* Generate a DSA key pair */
+ logIt("Generate an HMAC key ... \n");
+ crv = pFunctionList->C_GenerateKey(hRwSession, &hmacKeyGenMech,
+ hmacKeyTemplate,
+ PR_ARRAY_SIZE(hmacKeyTemplate),
+ &hHMACKey);
+ if (crv != CKR_OK) {
+ pk11error("HMAC key generation failed", crv);
+ return crv;
+ }
+
+ /* compute the digest */
+ memset(sign, 0, sizeof(sign));
+ crv = pFunctionList->C_SignInit(hRwSession, &hmacMech, hHMACKey);
+ if (crv != CKR_OK) {
+ pk11error("C_SignInit failed", crv);
+ return crv;
+ }
+
+ /* Digest the file */
+ while ((bytesRead = PR_Read(ifd, file_buf, sizeof(file_buf))) > 0) {
+ crv = pFunctionList->C_SignUpdate(hRwSession, (CK_BYTE_PTR)file_buf,
+ bytesRead);
+ if (crv != CKR_OK) {
+ pk11error("C_SignUpdate failed", crv);
+ return crv;
+ }
+ count += bytesRead;
+ }
+
+ if (bytesRead < 0) {
+ lperror("0 bytes read from input file");
+ return CKR_INTERNAL_IN_FAILURE;
+ }
+
+ signLen = sizeof(sign);
+ crv = pFunctionList->C_SignFinal(hRwSession, (CK_BYTE_PTR)sign,
+ &signLen);
+ if (crv != CKR_OK) {
+ pk11error("C_SignFinal failed", crv);
+ return crv;
+ }
+
+ if (signLen != hash->hashLength) {
+ PR_fprintf(PR_STDERR, "digestLen has incorrect length %lu "
+ "it should be %lu \n",
+ signLen, hash->hashLength);
+ return crv;
+ }
+ /* get HMAC KeyValue */
+ memset(keyBuf, 0, sizeof(keyBuf));
+ hmacKeyValue.type = CKA_VALUE;
+ hmacKeyValue.pValue = (CK_VOID_PTR)&keyBuf;
+ hmacKeyValue.ulValueLen = sizeof(keyBuf);
+
+ crv = pFunctionList->C_GetAttributeValue(hRwSession, hHMACKey,
+ &hmacKeyValue, 1);
+ if (crv != CKR_OK && crv != CKR_ATTRIBUTE_TYPE_INVALID) {
+ pk11error("C_GetAttributeValue failed", crv);
+ return crv;
+ }
+ keyLen = hmacKeyValue.ulValueLen;
+
+ if (verbose) {
+ int j;
+ PR_fprintf(PR_STDERR, "Library File Size: %d bytes\n", count);
+ PR_fprintf(PR_STDERR, " key: %lu bytes\n", keyLen);
+#define STEP 10
+ for (i = 0; i < (int)keyLen; i += STEP) {
+ PR_fprintf(PR_STDERR, " ");
+ for (j = 0; j < STEP && (i + j) < (int)keyLen; j++) {
+ PR_fprintf(PR_STDERR, " %02x", keyBuf[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");
+ }
+ }
+
+ /*
+ * 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.
+ */
+
+ header.magic1 = NSS_SIGN_CHK_MAGIC1;
+ header.magic2 = NSS_SIGN_CHK_MAGIC2;
+ header.majorVersion = NSS_SIGN_CHK_MAJOR_VERSION;
+ header.minorVersion = NSS_SIGN_CHK_MINOR_VERSION;
+ encodeInt(header.offset, sizeof(header)); /* offset to data start */
+ encodeInt(header.type, NSS_SIGN_CHK_FLAG_HMAC | hash->hashType);
+ bytesWritten = PR_Write(ofd, &header, sizeof(header));
+ if (bytesWritten != sizeof(header)) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+
+ /* HMACKey */
+ rv = writeItem(ofd, keyBuf, keyLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+ /* HMAC SIGNATURE */
+ rv = writeItem(ofd, &sign, signLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+
+ return CKR_OK;
+}
+
+int
+main(int argc, char **argv)
+{
+ PLOptState *optstate;
+ char *program_name;
+ char *libname = NULL;
+ PRLibrary *lib = NULL;
+ PRFileDesc *ifd = NULL;
+ PRFileDesc *ofd = NULL;
+ const char *input_file = NULL; /* read/create encrypted data from here */
+ char *output_file = NULL; /* write new encrypted data here */
+ unsigned int keySize = 0;
+ static PRBool FIPSMODE = PR_FALSE;
+ static PRBool useDSA = PR_FALSE;
+ PRBool successful = PR_FALSE;
+ const HashTable *hash = NULL;
+
+#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;
+
+ 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:t:Dc");
+ 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 'D':
+ useDSA = PR_TRUE;
+ break;
+
+ case 'c':
+ compat = PR_TRUE;
+ 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 't':
+ if (!optstate->value) {
+ PL_DestroyOptState(optstate);
+ usage(program_name);
+ }
+ hash = findHash(optstate->value);
+ if (hash == NULL) {
+ PR_fprintf(PR_STDERR, "Invalid hash '%s'\n",
+ optstate->value);
+ usage(program_name);
+ }
+ 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;
+ }
+
+ 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");
+ }
+
+ /* open the shared library */
+ ifd = PR_OpenFile(input_file, PR_RDONLY, 0);
+ if (ifd == 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);
+ }
+
+ if (verbose) {
+ PR_fprintf(PR_STDERR, "Library File: %s\n", input_file);
+ 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
+ }
+
+ /* open the target signature file */
+ ofd = PR_Open(output_file, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0666);
+ if (ofd == NULL) {
+ lperror(output_file);
+ goto cleanup;
+ }
+
+ if (useDSA) {
+ crv = shlibSignDSA(pFunctionList, pSlotList[slotIndex], hRwSession,
+ keySize, ifd, ofd, hash);
+ } else {
+ crv = shlibSignHMAC(pFunctionList, pSlotList[slotIndex], hRwSession,
+ keySize, ifd, ofd, hash);
+ }
+ if (crv == CKR_INTERNAL_OUT_FAILURE) {
+ lperror(output_file);
+ }
+ if (crv == CKR_INTERNAL_IN_FAILURE) {
+ lperror(input_file);
+ }
+
+ PR_Close(ofd);
+ ofd = NULL;
+ /* close the input_File */
+ PR_Close(ifd);
+ ifd = NULL;
+
+#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
+ if (ifd) {
+ PR_Close(ifd);
+ }
+ if (ofd) {
+ PR_Close(ofd);
+ }
+
+ 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 0000000000..75612c07a2
--- /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 0000000000..db37411af4
--- /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 0000000000..d8bd837d64
--- /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 0000000000..408ee6da4d
--- /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 0000000000..100fb27785
--- /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 0000000000..a2d03f7c39
--- /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') {
+ snprintf(common_name_buf, sizeof(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();
+ }
+ snprintf(common_name, strlen(cp) + 6, "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();
+ }
+ snprintf(org, strlen(cp) + 5, "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();
+ }
+ snprintf(orgunit, strlen(cp) + 6, "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();
+ }
+ snprintf(state, strlen(cp) + 6, "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();
+ }
+ snprintf(country, strlen(cp) + 5, "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();
+ }
+ snprintf(uid, strlen(cp) + 7, "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();
+ }
+ snprintf(email, strlen(cp) + 5, "E=%s,", cp);
+ subjectlen += strlen(email);
+ }
+
+ subjectlen++;
+
+ subject = PORT_ZAlloc(subjectlen);
+ if (!subject) {
+ out_of_memory();
+ }
+
+ snprintf(subject, subjectlen, "%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();
+
+ snprintf(filename, strlen(DEFAULT_X509_BASENAME) + 8, "%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 */
+
+ snprintf(filename, strlen(DEFAULT_X509_BASENAME) + 8, "%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 0000000000..f843e4f38c
--- /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;
+
+ snprintf(fullname, sizeof(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) {
+ 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")) {
+ char *newArchiveDir = NULL;
+ PR_fprintf(errorFD,
+ "warning: ARCHIVE attribute should end in \".jar\" in tag"
+ " starting on %s:%d.\n",
+ filename, curitem->startLine);
+ warningCount++;
+ newArchiveDir = PR_smprintf("%s.arc", archiveDir);
+ PR_Free(archiveDir);
+ archiveDir = newArchiveDir;
+ } 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 (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 *basepath, char *path)
+{
+ char fn[FNSIZE];
+ PRDir *dir;
+ int c = snprintf(fn, sizeof(fn), "%s/%s", basepath, path);
+ if (c >= sizeof(fn)) {
+ return PR_FAILURE;
+ }
+
+ /*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 0000000000..dd42d81258
--- /dev/null
+++ b/security/nss/cmd/signtool/list.c
@@ -0,0 +1,206 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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;
+ 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;
+
+ 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 0000000000..c8d3fd39ce
--- /dev/null
+++ b/security/nss/cmd/signtool/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
+
+ifdef ZLIB_INCLUDE_DIR
+INCLUDES += -I$(ZLIB_INCLUDE_DIR)
+endif
+
+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 0000000000..168bb1b9ec
--- /dev/null
+++ b/security/nss/cmd/signtool/sign.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/. */
+
+#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;
+ int count;
+
+ 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 */
+ count = snprintf(tempfn, sizeof(tempfn), "META-INF/%s.%s", base, (keyType == dsaKey ? "dsa" : "rsa"));
+ if (count >= sizeof(tempfn)) {
+ PR_fprintf(errorFD, "unable to write key metadata\n");
+ errorCount++;
+ exit(ERRX);
+ }
+ count = snprintf(fullfn, sizeof(fullfn), "%s/%s", tree, tempfn);
+ if (count >= sizeof(fullfn)) {
+ PR_fprintf(errorFD, "unable to write key metadata\n");
+ errorCount++;
+ exit(ERRX);
+ }
+ 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");
+ count = snprintf(fullfn, sizeof(fullfn), "%s/%s", tree, tempfn);
+ if (count >= sizeof(fullfn)) {
+ PR_fprintf(errorFD, "unable to write manifest\n");
+ errorCount++;
+ exit(ERRX);
+ }
+ JzipAdd(fullfn, tempfn, zipfile, compression_level);
+
+ /* sf to zip */
+ count = snprintf(tempfn, sizeof(tempfn), "META-INF/%s.sf", base);
+ if (count >= sizeof(tempfn)) {
+ PR_fprintf(errorFD, "unable to write sf metadata\n");
+ errorCount++;
+ exit(ERRX);
+ }
+ count = snprintf(fullfn, sizeof(fullfn), "%s/%s", tree, tempfn);
+ if (count >= sizeof(fullfn)) {
+ PR_fprintf(errorFD, "unable to write sf metadata\n");
+ errorCount++;
+ exit(ERRX);
+ }
+ JzipAdd(fullfn, tempfn, zipfile, compression_level);
+
+ /* Add the rsa/dsa file to the zip archive normally */
+ if (!xpi_arc) {
+ /* rsa/dsa to zip */
+ count = snprintf(tempfn, sizeof(tempfn), "META-INF/%s.%s", base, (keyType == dsaKey ? "dsa" : "rsa"));
+ if (count >= sizeof(tempfn)) {
+ PR_fprintf(errorFD, "unable to write key metadata\n");
+ errorCount++;
+ exit(ERRX);
+ }
+ count = snprintf(fullfn, sizeof(fullfn), "%s/%s", tree, tempfn);
+ if (count >= sizeof(fullfn)) {
+ PR_fprintf(errorFD, "unable to write key metadata\n");
+ errorCount++;
+ exit(ERRX);
+ }
+ 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 *metafilename,
+ char *install_script, int optimize_level, PRBool recurse)
+{
+ SignArcInfo info;
+
+ info.keyName = keyName;
+ info.javascript = javascript;
+ info.metafile = metafilename;
+ info.install_script = install_script;
+ info.optimize = optimize_level;
+
+ 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 *zipfilename = 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);
+
+ zipfilename = PL_strdup(archive);
+ arc = PORT_Strrchr(zipfilename, '.');
+
+ 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", zipfilename);
+ }
+ retval = SignArchive(archive, infop->keyName, zipfilename,
+ infop->javascript, infop->metafile, infop->install_script,
+ infop->optimize, PR_TRUE /* recurse */);
+ }
+finish:
+ if (archive)
+ PR_Free(archive);
+ if (zipfilename)
+ PR_Free(zipfilename);
+
+ 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";
+
+ snprintf(sf_file, sizeof(sf_file), "%s/META-INF/%s.sf", dir, base);
+ snprintf(pk7_file, sizeof(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);
+ }
+
+ snprintf(metadir, sizeof(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];
+ int count;
+
+ 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;
+ }
+ count = snprintf(fullname, sizeof(fullname), "%s/%s", basedir, relpath);
+ if (count >= sizeof(fullname)) {
+ return 1;
+ }
+ 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;
+ }
+
+ snprintf(fullname, sizeof(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 *sfFile;
+ FILE *mfFile;
+ long r1, r2, r3;
+ char whofile[FNSIZE];
+ char *buf, *name = NULL;
+ char *md5, *sha1;
+ JAR_Digest dig;
+ int line = 0;
+
+ strcpy(whofile, who);
+
+ if ((mfFile = fopen(manifile, "rb")) == NULL) {
+ perror(manifile);
+ exit(ERRX);
+ }
+
+ if ((sfFile = 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(sfFile, "Signature-Version: 1.0\n");
+ fprintf(sfFile, "Created-By: %s\n", CREATOR);
+ fprintf(sfFile, "Comments: %s\n", BREAKAGE);
+
+ if (fgets(buf, BUFSIZ, mfFile) == 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(mfFile, 0L, SEEK_SET);
+
+ /* Process blocks of headers, and calculate their hashen */
+
+ while (1) {
+ /* Beginning range */
+ r1 = ftell(mfFile);
+
+ if (fgets(name, BUFSIZ, mfFile) == 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, mfFile)) {
+ if (*buf == 0 || *buf == '\n' || *buf == '\r')
+ break;
+
+ line++;
+
+ /* Ending range for hashing */
+ r2 = ftell(mfFile);
+ }
+
+ r3 = ftell(mfFile);
+
+ if (r1) {
+ fprintf(sfFile, "\n");
+ fprintf(sfFile, "%s", name);
+ }
+
+ calculate_MD5_range(mfFile, r1, r2, &dig);
+
+ if (optimize == 0) {
+ fprintf(sfFile, "Digest-Algorithms: MD5 SHA1\n");
+
+ md5 = BTOA_DataToAscii(dig.md5, MD5_LENGTH);
+ fprintf(sfFile, "MD5-Digest: %s\n", md5);
+ PORT_Free(md5);
+ }
+
+ sha1 = BTOA_DataToAscii(dig.sha1, SHA1_LENGTH);
+ fprintf(sfFile, "SHA1-Digest: %s\n", sha1);
+ PORT_Free(sha1);
+
+ /* restore normalcy after changing offset position */
+ fseek(mfFile, r3, SEEK_SET);
+ }
+
+ PORT_Free(buf);
+ PORT_Free(name);
+
+ fclose(sfFile);
+ fclose(mfFile);
+
+ 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 0000000000..915a00fbc1
--- /dev/null
+++ b/security/nss/cmd/signtool/signtool.c
@@ -0,0 +1,1066 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 0000000000..53465ac63a
--- /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 0000000000..bdb3b597cb
--- /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 0000000000..54de0f2ddc
--- /dev/null
+++ b/security/nss/cmd/signtool/util.c
@@ -0,0 +1,1046 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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) {
+ snprintf(filename, sizeof(filename), "%s/%s", path, entry->name);
+ if (rm_dash_r(filename)) {
+ PR_CloseDir(dir);
+ 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)
+{
+ /* this function is truly evil. Tools and applications should not have
+ * any knowledge of actual cert databases! */
+ return;
+}
+
+/*
+ * 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:
+ snprintf(errstring, sizeof(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) {
+ snprintf(db, sizeof(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) {
+ snprintf(db, sizeof(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";
+
+ snprintf(db, sizeof(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 = ".";
+
+ snprintf(db, sizeof(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 0000000000..41656a10f6
--- /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 0000000000..aeb5d6c541
--- /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 lvl)
+{
+ 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, lvl, 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 0000000000..1c00762239
--- /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 0000000000..fc8358d5ad
--- /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 0000000000..f2cfddc691
--- /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 0000000000..ac48e3f1e6
--- /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 0000000000..1a126d2ff9
--- /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 0000000000..847814c90a
--- /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 0000000000..7a1de149f9
--- /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 0000000000..d8dbe09a7b
--- /dev/null
+++ b/security/nss/cmd/signver/pk7print.c
@@ -0,0 +1,907 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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) {
+ snprintf(om, sizeof(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) {
+ snprintf(mm, sizeof(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) {
+ snprintf(mm, sizeof(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=");
+}
+
+void
+sv_PrintECDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m)
+{
+ SECItem curve = { siBuffer, NULL, 0 };
+ if ((pk->u.ec.DEREncodedParams.len > 2) &&
+ (pk->u.ec.DEREncodedParams.data[0] == 0x06)) {
+ /* strip to just the oid for the curve */
+ curve.len = pk->u.ec.DEREncodedParams.data[1];
+ curve.data = pk->u.ec.DEREncodedParams.data + 2;
+ /* don't overflow the buffer */
+ curve.len = PR_MIN(curve.len, pk->u.ec.DEREncodedParams.len - 2);
+ fprintf(out, "%s", m);
+ sv_PrintObjectID(out, &curve, "curve=");
+ }
+ fprintf(out, "%s", m);
+ sv_PrintInteger(out, &pk->u.ec.publicValue, "publicValue=");
+}
+
+int
+sv_PrintSubjectPublicKeyInfo(FILE *out, PLArenaPool *arena,
+ CERTSubjectPublicKeyInfo *i, char *msg)
+{
+ SECKEYPublicKey pk;
+ int rv;
+ char mm[200];
+
+ snprintf(mm, sizeof(mm), "%s.publicKeyAlgorithm=", msg);
+ sv_PrintAlgorithmID(out, &i->algorithm, mm);
+
+ DER_ConvertBitString(&i->subjectPublicKey);
+ switch (SECOID_FindOIDTag(&i->algorithm.algorithm)) {
+ case SEC_OID_PKCS1_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
+ rv = SEC_ASN1DecodeItem(arena, &pk,
+ SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate),
+ &i->subjectPublicKey);
+ if (rv)
+ return rv;
+ snprintf(mm, sizeof(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;
+#ifdef notdef
+ /* SECKEY_PQGParamsTemplate is not yet exported form NSS */
+ rv = SEC_ASN1DecodeItem(arena, &pk.u.dsa.params,
+ SEC_ASN1_GET(SECKEY_PQGParamsTemplate),
+ &i->algorithm.parameters);
+ if (rv)
+ return rv;
+#endif
+ snprintf(mm, sizeof(mm), "%s.dsaPublicKey.", msg);
+ sv_PrintDSAPublicKey(out, &pk, mm);
+ break;
+ case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
+ rv = SECITEM_CopyItem(arena, &pk.u.ec.DEREncodedParams,
+ &i->algorithm.parameters);
+ if (rv)
+ return rv;
+ rv = SECITEM_CopyItem(arena, &pk.u.ec.publicValue,
+ &i->subjectPublicKey);
+ if (rv)
+ return rv;
+ snprintf(mm, sizeof(mm), "%s.ecdsaPublicKey.", msg);
+ sv_PrintECDSAPublicKey(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=");
+ snprintf(om, sizeof(om), "%sentry[%d].signedCRLEntriesExtensions.", m, iv++);
+ sv_PrintExtensions(out, entry->extensions, om);
+ }
+ }
+ snprintf(om, sizeof(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);
+ snprintf(mm, sizeof(mm), "%sserialNumber=", m);
+ sv_PrintInteger(out, &c->serialNumber, mm);
+ snprintf(mm, sizeof(mm), "%ssignatureAlgorithm=", m);
+ sv_PrintAlgorithmID(out, &c->signature, mm);
+ snprintf(mm, sizeof(mm), "%sissuerName=", m);
+ sv_PrintName(out, &c->issuer, mm);
+ snprintf(mm, sizeof(mm), "%svalidity.", m);
+ sv_PrintValidity(out, &c->validity, mm);
+ snprintf(mm, sizeof(mm), "%ssubject=", m);
+ sv_PrintName(out, &c->subject, mm);
+ snprintf(mm, sizeof(mm), "%ssubjectPublicKeyInfo", m);
+ rv = sv_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo, mm);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+ }
+ snprintf(mm, sizeof(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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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=");
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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 0000000000..8b122bde05
--- /dev/null
+++ b/security/nss/cmd/signver/signver.c
@@ -0,0 +1,313 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 0000000000..9aeb504591
--- /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 0000000000..74139629f3
--- /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 0000000000..4343695ede
--- /dev/null
+++ b/security/nss/cmd/smimetools/cmsutil.c
@@ -0,0 +1,1625 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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(void)
+{
+ 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:SHA256)\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", " ");
+ fprintf(stderr, "%-25s 12 - certUsageIPsec\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 = NULL;
+ 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.
+ */
+ 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_SHA256;
+ 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();
+ 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();
+ 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();
+ 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();
+ 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();
+ 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();
+ 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();
+ exit(1);
+ }
+ batch = PR_TRUE;
+ break;
+
+ case 'c':
+ if (mode != DECODE) {
+ fprintf(stderr,
+ "%s: option -c only supported with option -D.\n",
+ progName);
+ Usage();
+ 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();
+ 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();
+ 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();
+ 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();
+ 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();
+ 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();
+ 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();
+ PL_DestroyOptState(optstate);
+
+ if (mode == UNKNOWN)
+ Usage();
+
+ 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();
+ 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 0000000000..0e20ed77cf
--- /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 0000000000..b4ee091ef4
--- /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 0000000000..e67f6bedcb
--- /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 SHA256 digest)
+ $out .= "Content-Type: multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha256; 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 0000000000..13d3679f3b
--- /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 0000000000..bc7d35df4e
--- /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 0000000000..92302a1b8b
--- /dev/null
+++ b/security/nss/cmd/ssltap/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
+
+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 0000000000..619c93f8cd
--- /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 0000000000..0a9ec11eec
--- /dev/null
+++ b/security/nss/cmd/ssltap/ssltap.c
@@ -0,0 +1,2584 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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:
+ snprintf(buf, sizeof(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, "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);
+ if (NSS_Shutdown() != SECSuccess) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/security/nss/cmd/ssltap/ssltap.gyp b/security/nss/cmd/ssltap/ssltap.gyp
new file mode 100644
index 0000000000..9743ac262c
--- /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 0000000000..6e1d4ecdfc
--- /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 0000000000..fc00b69224
--- /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 0000000000..54f843d822
--- /dev/null
+++ b/security/nss/cmd/strsclnt/strsclnt.c
@@ -0,0 +1,1611 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_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;
+
+static const SSLSignatureScheme *enabledSigSchemes = NULL;
+static unsigned int enabledSigSchemeCount = 0;
+
+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(void)
+{
+ 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]\n"
+ " [-J signatureschemes] 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"
+ " -4 Enforce using an IPv4 destination address\n"
+ " -6 Enforce using an IPv6 destination address\n"
+ " Note: Default behavior is both IPv4 and IPv6 enabled\n"
+ " -J enable signature schemes\n"
+ " This takes a comma separated list of signature schemes in preference\n"
+ " order.\n"
+ " Possible values are:\n"
+ " rsa_pkcs1_sha1, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512,\n"
+ " ecdsa_sha1, ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384,\n"
+ " ecdsa_secp521r1_sha512,\n"
+ " rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512,\n"
+ " rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512,\n"
+ " dsa_sha1, dsa_sha256, dsa_sha384, dsa_sha512\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;
+ 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%s\n",
+ channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
+ suite.effectiveKeyBits, suite.symCipherName,
+ suite.macBits, suite.macAlgorithmName,
+ channel.isFIPS ? " FIPS" : "");
+ 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) &&
+ (!PK11_NeedLogin(cert->slot) ||
+ PR_TRUE == PK11_IsLoggedIn(cert->slot, NULL)) &&
+ (!PK11_NeedLogin(key->pkcs11Slot) ||
+ 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,
+ PRBool allowIPv4,
+ PRBool allowIPv6)
+{
+ 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;
+ }
+ for (;;) {
+ enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, port, &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");
+ 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;
+
+ 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 (enabledSigSchemes) {
+ rv = SSL_SignatureSchemePrefSet(model_sock, enabledSigSchemes,
+ enabledSigSchemeCount);
+ if (rv < 0) {
+ errExit("SSL_SignatureSchemePrefSet");
+ }
+ }
+
+ 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;
+ PRBool allowIPv4 = PR_TRUE;
+ PRBool allowIPv6 = PR_TRUE;
+ 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,
+ "46C:DJ:NP:TUV:W:a:c:d:f:gin:op:qst:uvw:z");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '4':
+ if (!allowIPv4) {
+ fprintf(stderr, "Only one of [-4, -6] can be specified.\n");
+ Usage();
+ }
+ allowIPv6 = PR_FALSE;
+ break;
+
+ case '6':
+ if (!allowIPv6) {
+ fprintf(stderr, "Only one of [-4, -6] can be specified.\n");
+ Usage();
+ }
+ allowIPv4 = PR_FALSE;
+ break;
+
+ case 'C':
+ cipherString = optstate->value;
+ break;
+
+ case 'D':
+ NoDelay = PR_TRUE;
+ break;
+
+ case 'I': /* reserved for OCSP multi-stapling */
+ break;
+
+ case 'J':
+ rv = parseSigSchemeList(optstate->value, &enabledSigSchemes, &enabledSigSchemeCount);
+ if (rv != SECSuccess) {
+ PL_DestroyOptState(optstate);
+ fprintf(stderr, "Bad signature scheme specified.\n");
+ Usage();
+ }
+ 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) {
+ fprintf(stderr, "Bad version specified.\n");
+ Usage();
+ }
+ 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();
+ }
+ hostName = PL_strdup(optstate->value);
+ break;
+
+ default:
+ case '?':
+ Usage();
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+
+ if (!hostName || status == PL_OPT_BAD)
+ Usage();
+
+ if (fullhs != NO_FULLHS_PERCENTAGE && (fullhs < 0 || fullhs > 100 || NoReuse))
+ Usage();
+
+ if (port == 0)
+ Usage();
+
+ 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, allowIPv4, allowIPv6);
+
+ /* 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);
+
+ PORT_Free((SSLSignatureScheme *)enabledSigSchemes);
+
+ /* 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 0000000000..4093017bf1
--- /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 0000000000..74ae200208
--- /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 0000000000..f87480e44d
--- /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 0000000000..e3c2e4c6e8
--- /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 0000000000..6545f389a3
--- /dev/null
+++ b/security/nss/cmd/symkeyutil/symkeyutil.c
@@ -0,0 +1,1105 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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);
+ if (!string) {
+ return NULL;
+ }
+
+ 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");
+ PORT_Free(name);
+}
+
+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;
+
+ if (!symKey) {
+ 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;
+ }
+ keyName = PK11_GetSymKeyNickname(symKey);
+ 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 0000000000..c39be293e7
--- /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 0000000000..a263d41aaa
--- /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 0000000000..b2bb2d681d
--- /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 0000000000..80a4ebb7ab
--- /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 0000000000..2deedbc065
--- /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 0000000000..f0062ea5e4
--- /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 0000000000..88b8347365
--- /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 0000000000..fc700407a7
--- /dev/null
+++ b/security/nss/cmd/tests/nonspr10.c
@@ -0,0 +1,88 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 "keyhi.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 0000000000..175ba923c3
--- /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 0000000000..2896ccf94c
--- /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 0000000000..148bb250e5
--- /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 0000000000..aae7b445cb
--- /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 0000000000..5c1e4f6114
--- /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 0000000000..3feaa1f0a5
--- /dev/null
+++ b/security/nss/cmd/tstclnt/tstclnt.c
@@ -0,0 +1,2438 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 "nssb64.h"
+#include "ocsp.h"
+#include "ssl.h"
+#include "sslproto.h"
+#include "sslexp.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 ZERO_RTT_MAX (2 << 16)
+
+#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;
+PRBool initializedServerSessionCache = PR_FALSE;
+
+static char *progName;
+static const char *requestFile;
+
+secuPWData pwdata = { PW_NONE, 0 };
+
+SSLNamedGroup *enabledGroups = NULL;
+unsigned int enabledGroupsCount = 0;
+const SSLSignatureScheme *enabledSigSchemes = NULL;
+unsigned int enabledSigSchemeCount = 0;
+SECItem psk = { siBuffer, NULL, 0 };
+SECItem pskLabel = { siBuffer, NULL, 0 };
+
+const char *
+signatureSchemeName(SSLSignatureScheme scheme)
+{
+ switch (scheme) {
+#define strcase(x) \
+ case ssl_sig_##x: \
+ return #x
+ strcase(none);
+ strcase(rsa_pkcs1_sha1);
+ strcase(rsa_pkcs1_sha256);
+ strcase(rsa_pkcs1_sha384);
+ strcase(rsa_pkcs1_sha512);
+ strcase(ecdsa_sha1);
+ strcase(ecdsa_secp256r1_sha256);
+ strcase(ecdsa_secp384r1_sha384);
+ strcase(ecdsa_secp521r1_sha512);
+ strcase(rsa_pss_rsae_sha256);
+ strcase(rsa_pss_rsae_sha384);
+ strcase(rsa_pss_rsae_sha512);
+ strcase(ed25519);
+ strcase(ed448);
+ strcase(rsa_pss_pss_sha256);
+ strcase(rsa_pss_pss_sha384);
+ strcase(rsa_pss_pss_sha512);
+ strcase(dsa_sha1);
+ strcase(dsa_sha256);
+ strcase(dsa_sha384);
+ strcase(dsa_sha512);
+#undef strcase
+ case ssl_sig_rsa_pkcs1_sha1md5:
+ return "RSA PKCS#1 SHA1+MD5";
+ default:
+ break;
+ }
+ return "Unknown Scheme";
+}
+
+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%s\n",
+ channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
+ suite.effectiveKeyBits, suite.symCipherName,
+ suite.macBits, suite.macAlgorithmName,
+ channel.isFIPS ? " FIPS" : "");
+ FPRINTF(stderr,
+ "tstclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n"
+ " Compression: %s, Extended Master Secret: %s\n"
+ " Signature Scheme: %s\n",
+ channel.authKeyBits, suite.authAlgorithmName,
+ channel.keaKeyBits, suite.keaTypeName,
+ channel.compressionMethodName,
+ channel.extendedMasterSecretUsed ? "Yes" : "No",
+ signatureSchemeName(channel.signatureScheme));
+ }
+ }
+ 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);
+ }
+ if (channel.peerDelegCred) {
+ fprintf(stderr, "Received a Delegated Credential\n");
+ }
+}
+
+static void
+PrintUsageHeader()
+{
+ 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] [-E]\n"
+ " [-V [min-version]:[max-version]] [-K] [-T] [-U]\n"
+ " [-r N] [-w passwd] [-W pwfile] [-q [-t seconds]]\n"
+ " [-I groups] [-J signatureschemes]\n"
+ " [-A requestfile] [-L totalconnections] [-P {client,server}]\n"
+ " [-N echConfigs] [-Q] [-z externalPsk]\n"
+ " [-i echGreaseSize]\n"
+ "\n",
+ progName);
+}
+
+static void
+PrintParameterUsage()
+{
+ 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\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 selection & 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 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 Enable the delegated credentials extension.\n", "-B");
+ 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 [RFC7919]\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"
+ "%-20s xyber768d00\n",
+ "-I", "", "", "");
+ fprintf(stderr, "%-20s Comma separated list of signature schemes in preference order.\n"
+ "%-20s The following values are valid:\n"
+ "%-20s rsa_pkcs1_sha1, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512,\n"
+ "%-20s ecdsa_sha1, ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384,\n"
+ "%-20s ecdsa_secp521r1_sha512,\n"
+ "%-20s rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512,\n"
+ "%-20s rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512,\n"
+ "%-20s dsa_sha1, dsa_sha256, dsa_sha384, dsa_sha512\n",
+ "-J", "", "", "", "", "", "", "");
+ fprintf(stderr, "%-20s Use DTLS\n", "-P {client, server}");
+ fprintf(stderr, "%-20s Exit after handshake\n", "-Q");
+ fprintf(stderr, "%-20s Use Encrypted Client Hello with the given Base64-encoded ECHConfigs\n", "-N");
+ fprintf(stderr, "%-20s Enable Encrypted Client Hello GREASEing with the given padding size (0-255) \n", "-i");
+ fprintf(stderr, "%-20s Enable post-handshake authentication\n"
+ "%-20s for TLS 1.3; need to specify -n\n",
+ "-E", "");
+ fprintf(stderr, "%-20s Export and print keying material after successful handshake.\n"
+ "%-20s The argument is a comma separated list of exporters in the form:\n"
+ "%-20s LABEL[:OUTPUT-LENGTH[:CONTEXT]]\n"
+ "%-20s where LABEL and CONTEXT can be either a free-form string or\n"
+ "%-20s a hex string if it is preceded by \"0x\"; OUTPUT-LENGTH\n"
+ "%-20s is a decimal integer.\n",
+ "-x", "", "", "", "", "");
+ fprintf(stderr,
+ "%-20s Configure a TLS 1.3 External PSK with the given hex string for a key\n"
+ "%-20s To specify a label, use ':' as a delimiter. For example\n"
+ "%-20s 0xAAAABBBBCCCCDDDD:mylabel. Otherwise, the default label of\n"
+ "%-20s 'Client_identity' will be used.\n",
+ "-z externalPsk", "", "", "");
+ fprintf(stderr, "%-20s Enable middlebox compatibility mode (TLS 1.3 only)\n", "-e");
+}
+
+static void
+Usage()
+{
+ PrintUsageHeader();
+ PrintParameterUsage();
+ exit(1);
+}
+
+static void
+PrintCipherUsage()
+{
+ PrintUsageHeader();
+ 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()
+{
+ 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;
+}
+
+struct clientCertAsyncParamsStr {
+ void *arg; /* The nickname used for selection, not owned */
+ struct CERTDistNamesStr *caNames; /* CA Names specified by Server, owned. */
+};
+
+/* tstclnt can only have a single handshake in progress at any instant. */
+PRBool clientCertAsyncSelect = PR_TRUE; /* Async by default */
+PRBool clientCertIsBlocked = PR_FALSE; /* Whether we waiting to finish ClientAuth */
+struct clientCertAsyncParamsStr *clientCertParams = NULL;
+
+SECStatus
+own_CompleteClientAuthData(PRFileDesc *fd, struct clientCertAsyncParamsStr *args)
+{
+ SECStatus rv;
+ CERTCertificate *pRetCert = NULL;
+ SECKEYPrivateKey *pRetKey = NULL;
+ rv = NSS_GetClientAuthData(args->arg, fd, args->caNames, &pRetCert, &pRetKey);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "Failed to load a suitable client certificate \n");
+ }
+ return SSL_ClientCertCallbackComplete(fd, rv, pRetKey, pRetCert);
+}
+
+SECStatus
+restartHandshakeAfterClientCertIfNeeded(PRFileDesc *fd)
+{
+ if (!clientCertIsBlocked) {
+ return SECFailure;
+ }
+ clientCertIsBlocked = PR_FALSE;
+ own_CompleteClientAuthData(fd, clientCertParams);
+ CERT_FreeDistNames(clientCertParams->caNames);
+ PORT_Free(clientCertParams);
+ clientCertParams = NULL;
+ return SECSuccess;
+}
+
+SECStatus
+own_GetClientAuthData(void *arg,
+ PRFileDesc *socket,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+ if (clientCertAsyncSelect) {
+ PR_ASSERT(!clientCertIsBlocked);
+ PR_ASSERT(!clientCertParams);
+
+ clientCertIsBlocked = PR_TRUE;
+ clientCertParams = PORT_Alloc(sizeof(struct clientCertAsyncParamsStr));
+ if (!clientCertParams) {
+ fprintf(stderr, "Unable to allocate buffer for client cert callback\n");
+ exit(1);
+ }
+
+ clientCertParams->arg = arg;
+ clientCertParams->caNames = caNames ? CERT_DupDistNames(caNames) : NULL;
+ if (caNames && !clientCertParams->caNames) {
+ fprintf(stderr, "Unable to allocate buffer for client cert callback\n");
+ exit(1);
+ }
+ return SECWouldBlock;
+ }
+
+ 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;
+ int wc, rc;
+ char buf[256];
+
+ if (requestFile) {
+ std_in = PR_Open(requestFile, PR_RDONLY, 0);
+ } else {
+ std_in = PR_GetSpecialFD(PR_StandardInput);
+ }
+
+#ifdef WIN32
+ if (!requestFile) {
+ /* 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);
+ if (requestFile) {
+ PR_Close(std_in);
+ }
+}
+
+#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(); \
+ }
+
+static SECStatus
+restartHandshakeAfterServerCertIfNeeded(PRFileDesc *fd,
+ ServerCertAuth *serverCertAuth,
+ PRBool override)
+{
+ SECStatus rv;
+ PRErrorCode error = 0;
+
+ if (!serverCertAuth->isPaused || clientCertIsBlocked)
+ 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;
+ } else {
+ /* restore the original error code, which could be reset by
+ * SSL_AuthCertificateComplete */
+ PORT_SetError(error);
+ }
+
+ return rv;
+}
+
+char *host = NULL;
+char *nickname = NULL;
+char *cipherString = NULL;
+int multiplier = 0;
+SSLVersionRange enabledVersions;
+int disableLocking = 0;
+int enableSessionTickets = 0;
+int enableFalseStart = 0;
+int enableCertStatus = 0;
+int enableSignedCertTimestamps = 0;
+int forceFallbackSCSV = 0;
+int enableExtendedMasterSecret = 0;
+PRBool requireDHNamedGroups = 0;
+PRBool middleboxCompatMode = 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;
+PRBool enableZeroRtt = PR_FALSE;
+PRUint8 *zeroRttData;
+unsigned int zeroRttLen = 0;
+PRBool enableAltServerHello = PR_FALSE;
+PRBool useDTLS = PR_FALSE;
+PRBool actAsServer = PR_FALSE;
+PRBool stopAfterHandshake = PR_FALSE;
+PRBool requestToExit = PR_FALSE;
+char *versionString = NULL;
+PRBool handshakeComplete = PR_FALSE;
+char *echConfigs = NULL;
+PRUint16 echGreaseSize = 0;
+PRBool enablePostHandshakeAuth = PR_FALSE;
+PRBool enableDelegatedCredentials = PR_FALSE;
+const secuExporter *enabledExporters = NULL;
+unsigned int enabledExporterCount = 0;
+
+static int
+writeBytesToServer(PRFileDesc *s, const PRUint8 *buf, int nb)
+{
+ SECStatus rv;
+ const PRUint8 *bufp = buf;
+ PRPollDesc pollDesc;
+
+ pollDesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ pollDesc.out_flags = 0;
+ pollDesc.fd = s;
+
+ 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;
+ }
+ FPRINTF(stderr, "%s: %d bytes written\n", progName, cc);
+ if (enableZeroRtt && !handshakeComplete) {
+ if (zeroRttLen + cc > ZERO_RTT_MAX) {
+ SECU_PrintError(progName, "too much early data to save");
+ return -1;
+ }
+ PORT_Memcpy(zeroRttData + zeroRttLen, bufp, cc);
+ zeroRttLen += cc;
+ }
+ 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;
+ }
+
+ rv = restartHandshakeAfterClientCertIfNeeded(s);
+ if (rv == SECSuccess) {
+ continue;
+ }
+
+ pollDesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ pollDesc.out_flags = 0;
+ FPRINTF(stderr,
+ "%s: about to call PR_Poll on writable socket !\n",
+ progName);
+ cc = PR_Poll(&pollDesc, 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;
+}
+
+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;
+ }
+ if (zeroRttLen) {
+ /* This data was sent in 0-RTT. */
+ SSLChannelInfo info;
+ SECStatus rv;
+
+ rv = SSL_GetChannelInfo(fd, &info, sizeof(info));
+ if (rv != SECSuccess)
+ return;
+
+ if (!info.earlyDataAccepted) {
+ FPRINTF(stderr, "Early data rejected. Re-sending %d bytes\n",
+ zeroRttLen);
+ writeBytesToServer(fd, zeroRttData, zeroRttLen);
+ zeroRttLen = 0;
+ }
+ }
+ if (stopAfterHandshake) {
+ requestToExit = PR_TRUE;
+ }
+ handshakeComplete = PR_TRUE;
+
+ if (enabledExporters) {
+ SECStatus rv;
+
+ rv = exportKeyingMaterials(fd, enabledExporters, enabledExporterCount);
+ if (rv != SECSuccess) {
+ PRErrorCode err = PR_GetError();
+ FPRINTF(stderr,
+ "couldn't export keying material: %s\n",
+ SECU_Strerror(err));
+ }
+ }
+}
+
+static SECStatus
+installServerCertificate(PRFileDesc *s, char *nick)
+{
+ CERTCertificate *cert;
+ SECKEYPrivateKey *privKey = NULL;
+
+ if (!nick) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ cert = PK11_FindCertFromNickname(nick, &pwdata);
+ if (cert == NULL) {
+ return SECFailure;
+ }
+
+ privKey = PK11_FindKeyByAnyCert(cert, &pwdata);
+ if (privKey == NULL) {
+ return SECFailure;
+ }
+ if (SSL_ConfigServerCert(s, cert, privKey, NULL, 0) != SECSuccess) {
+ return SECFailure;
+ }
+ SECKEY_DestroyPrivateKey(privKey);
+ CERT_DestroyCertificate(cert);
+
+ return SECSuccess;
+}
+
+static SECStatus
+bindToClient(PRFileDesc *s)
+{
+ PRStatus status;
+ status = PR_Bind(s, &addr);
+ if (status != PR_SUCCESS) {
+ return SECFailure;
+ }
+
+ for (;;) {
+ /* Bind the remote address on first packet. This must happen
+ * before we SSL-ize the socket because we need to get the
+ * peer's address before SSLizing. Recvfrom gives us that
+ * while not consuming any data. */
+ unsigned char tmp;
+ PRNetAddr remote;
+ int nb;
+
+ nb = PR_RecvFrom(s, &tmp, 1, PR_MSG_PEEK,
+ &remote, PR_INTERVAL_NO_TIMEOUT);
+ if (nb != 1)
+ continue;
+
+ status = PR_Connect(s, &remote, PR_INTERVAL_NO_TIMEOUT);
+ if (status != PR_SUCCESS) {
+ SECU_PrintError(progName, "server bind to remote end failed");
+ return SECFailure;
+ }
+ return SECSuccess;
+ }
+
+ /* Unreachable. */
+}
+
+static SECStatus
+connectToServer(PRFileDesc *s, PRPollDesc *pollset)
+{
+ PRStatus status;
+ PRInt32 filesReady;
+
+ 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)");
+ return SECFailure;
+ }
+ 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! */
+ SECU_PrintError(progName, "%s: PR_Poll returned zero!\n");
+ return SECFailure;
+ }
+ status = PR_GetConnectStatus(pollset);
+ if (status == PR_SUCCESS) {
+ break;
+ }
+ if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
+ SECU_PrintError(progName, "unable to connect (poll)");
+ return SECFailure;
+ }
+ SECU_PrintError(progName, "poll");
+ milliPause(50 * multiplier);
+ }
+ } else {
+ SECU_PrintError(progName, "unable to connect");
+ return SECFailure;
+ }
+ }
+
+ return SECSuccess;
+}
+
+static SECStatus
+importPsk(PRFileDesc *s)
+{
+ SECU_PrintAsHex(stdout, &psk, "Using External PSK", 0);
+ PK11SlotInfo *slot = NULL;
+ PK11SymKey *symKey = NULL;
+ slot = PK11_GetInternalSlot();
+ if (!slot) {
+ SECU_PrintError(progName, "PK11_GetInternalSlot failed");
+ return SECFailure;
+ }
+ symKey = PK11_ImportSymKey(slot, CKM_HKDF_KEY_GEN, PK11_OriginUnwrap,
+ CKA_DERIVE, &psk, NULL);
+ PK11_FreeSlot(slot);
+ if (!symKey) {
+ SECU_PrintError(progName, "PK11_ImportSymKey failed");
+ return SECFailure;
+ }
+
+ SECStatus rv = SSL_AddExternalPsk(s, symKey, (const PRUint8 *)pskLabel.data,
+ pskLabel.len, ssl_hash_sha256);
+ PK11_FreeSymKey(symKey);
+ return rv;
+}
+
+static SECStatus
+printEchRetryConfigs(PRFileDesc *s)
+{
+ if (PORT_GetError() == SSL_ERROR_ECH_RETRY_WITH_ECH) {
+ SECItem retries = { siBuffer, NULL, 0 };
+ SECStatus rv = SSL_GetEchRetryConfigs(s, &retries);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "SSL_GetEchRetryConfigs failed");
+ return SECFailure;
+ }
+ char *retriesBase64 = NSSBase64_EncodeItem(NULL, NULL, 0, &retries);
+ if (!retriesBase64) {
+ SECU_PrintError(progName, "NSSBase64_EncodeItem on retry_configs failed");
+ SECITEM_FreeItem(&retries, PR_FALSE);
+ return SECFailure;
+ }
+
+ // Remove the newline characters that NSSBase64_EncodeItem unhelpfully inserts.
+ char *newline = strstr(retriesBase64, "\r\n");
+ if (newline) {
+ memmove(newline, newline + 2, strlen(newline + 2) + 1);
+ }
+ fprintf(stderr, "Received ECH retry_configs: \n%s\n", retriesBase64);
+ PORT_Free(retriesBase64);
+ SECITEM_FreeItem(&retries, PR_FALSE);
+ }
+ return SECSuccess;
+}
+
+static int
+run()
+{
+ int headerSeparatorPtrnId = 0;
+ int error = 0;
+ SECStatus rv;
+ PRStatus status;
+ PRInt32 filesReady;
+ PRFileDesc *s = NULL;
+ PRFileDesc *std_out;
+ PRPollDesc pollset[2] = { { 0 }, { 0 } };
+ PRBool wrStarted = PR_FALSE;
+
+ handshakeComplete = PR_FALSE;
+
+ /* Create socket */
+ if (useDTLS) {
+ s = PR_OpenUDPSocket(addr.raw.family);
+ } else {
+ s = PR_OpenTCPSocket(addr.raw.family);
+ }
+
+ if (s == NULL) {
+ SECU_PrintError(progName, "error creating socket");
+ error = 1;
+ goto done;
+ }
+
+ if (actAsServer) {
+ if (bindToClient(s) != SECSuccess) {
+ return 1;
+ }
+ }
+ 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;
+ }
+
+ if (useDTLS) {
+ s = DTLS_ImportFD(NULL, s);
+ } else {
+ 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, actAsServer ? SSL_HANDSHAKE_AS_SERVER : 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();
+ ndx = tolower(ndx) - 'a';
+ if (ndx < PR_ARRAY_SIZE(ssl3CipherSuites)) {
+ cipher = ssl3CipherSuites[ndx];
+ }
+ }
+ if (cipher > 0) {
+ rv = SSL_CipherPrefSet(s, cipher, SSL_ALLOWED);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "SSL_CipherPrefSet()");
+ error = 1;
+ goto done;
+ }
+ } else {
+ Usage();
+ }
+ }
+ 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 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 negotiation of delegated credentials (draft-ietf-tls-subcerts) */
+ rv = SSL_OptionSet(s, SSL_ENABLE_DELEGATED_CREDENTIALS, enableDelegatedCredentials);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling delegated credentials");
+ 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;
+ }
+ }
+
+ /* Alternate ServerHello content type (TLS 1.3 only) */
+ if (enableAltServerHello) {
+ rv = SSL_UseAltServerHelloType(s, PR_TRUE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling alternate ServerHello type");
+ error = 1;
+ goto done;
+ }
+ }
+
+ /* Middlebox compatibility mode (TLS 1.3 only) */
+ if (middleboxCompatMode) {
+ rv = SSL_OptionSet(s, SSL_ENABLE_TLS13_COMPAT_MODE, PR_TRUE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling middlebox compatibility mode");
+ 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 (enablePostHandshakeAuth) {
+ rv = SSL_OptionSet(s, SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling post-handshake auth");
+ 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;
+ }
+ }
+
+ if (enabledSigSchemes) {
+ rv = SSL_SignatureSchemePrefSet(s, enabledSigSchemes, enabledSigSchemeCount);
+ if (rv < 0) {
+ SECU_PrintError(progName, "SSL_SignatureSchemePrefSet failed");
+ error = 1;
+ goto done;
+ }
+ }
+
+ if (echConfigs) {
+ SECItem echConfigsBin = { siBuffer, NULL, 0 };
+
+ if (!NSSBase64_DecodeBuffer(NULL, &echConfigsBin, echConfigs,
+ strlen(echConfigs))) {
+ SECU_PrintError(progName, "ECHConfigs record is invalid base64");
+ error = 1;
+ goto done;
+ }
+
+ rv = SSL_SetClientEchConfigs(s, echConfigsBin.data, echConfigsBin.len);
+ SECITEM_FreeItem(&echConfigsBin, PR_FALSE);
+ if (rv < 0) {
+ SECU_PrintError(progName, "SSL_SetClientEchConfigs failed");
+ error = 1;
+ goto done;
+ }
+ }
+
+ if (echGreaseSize) {
+ rv = SSL_EnableTls13GreaseEch(s, PR_TRUE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "SSL_EnableTls13GreaseEch failed");
+ error = 1;
+ goto done;
+ }
+ rv = SSL_SetTls13GreaseEchSize(s, echGreaseSize);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "SSL_SetTls13GreaseEchSize failed");
+ error = 1;
+ goto done;
+ }
+ }
+
+ if (psk.data) {
+ rv = importPsk(s);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "importPsk failed");
+ error = 1;
+ goto done;
+ }
+ }
+
+ serverCertAuth.dbHandle = CERT_GetDefaultCertDB();
+
+ SSL_AuthCertificateHook(s, ownAuthCertificate, &serverCertAuth);
+ if (override) {
+ SSL_BadCertHook(s, ownBadCertHandler, NULL);
+ }
+ if (actAsServer) {
+ rv = installServerCertificate(s, nickname);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error installing server cert");
+ return 1;
+ }
+ rv = SSL_ConfigServerSessionIDCache(1024, 0, 0, ".");
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error configuring session cache");
+ return 1;
+ }
+ initializedServerSessionCache = PR_TRUE;
+ } else {
+ SSL_GetClientAuthDataHook(s, own_GetClientAuthData, (void *)nickname);
+ }
+ SSL_HandshakeCallback(s, handshakeCallback, hs2SniHostName);
+ if (hs1SniHostName) {
+ SSL_SetURL(s, hs1SniHostName);
+ } else {
+ SSL_SetURL(s, host);
+ }
+
+ if (actAsServer) {
+ rv = SSL_ResetHandshake(s, PR_TRUE /* server */);
+ if (rv != SECSuccess) {
+ return 1;
+ }
+ } else {
+ /* Try to connect to the server */
+ rv = connectToServer(s, pollset);
+ if (rv != SECSuccess) {
+ error = 1;
+ goto done;
+ }
+ }
+
+ pollset[SSOCK_FD].fd = s;
+ pollset[SSOCK_FD].in_flags = PR_POLL_EXCEPT;
+ if (!actAsServer)
+ pollset[SSOCK_FD].in_flags |= (clientSpeaksFirst ? 0 : PR_POLL_READ);
+ else
+ pollset[SSOCK_FD].in_flags |= PR_POLL_READ;
+ if (requestFile) {
+ pollset[STDIN_FD].fd = PR_Open(requestFile, PR_RDONLY, 0);
+ if (!pollset[STDIN_FD].fd) {
+ fprintf(stderr, "%s: unable to open input file: %s\n",
+ progName, requestFile);
+ error = 1;
+ goto done;
+ }
+ } else {
+ pollset[STDIN_FD].fd = PR_GetSpecialFD(PR_StandardInput);
+ }
+ pollset[STDIN_FD].in_flags = PR_POLL_READ;
+ 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.
+ */
+ requestToExit = PR_FALSE;
+ FPRINTF(stderr, "%s: ready...\n", progName);
+ while (!requestToExit &&
+ (pollset[SSOCK_FD].in_flags || pollset[STDIN_FD].in_flags)) {
+ PRUint8 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;
+ }
+
+ rv = restartHandshakeAfterClientCertIfNeeded(s);
+ if (rv == SECSuccess) {
+ continue;
+ }
+
+ 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, PR_ARRAY_SIZE(pollset),
+ 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 (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;
+ if (actAsServer)
+ requestToExit = PR_TRUE;
+ } else {
+ error = writeBytesToServer(s, buf, nb);
+ if (error) {
+ if (echConfigs) {
+ (void)printEchRetryConfigs(s);
+ }
+ 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);
+ }
+#ifdef PR_POLL_HUP
+#define POLL_RECV_FLAGS (PR_POLL_READ | PR_POLL_ERR | PR_POLL_HUP)
+#else
+#define POLL_RECV_FLAGS (PR_POLL_READ | PR_POLL_ERR)
+#endif
+ if (pollset[SSOCK_FD].out_flags & POLL_RECV_FLAGS) {
+ /* 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, (char *)buf, nb, &wrStarted,
+ &headerSeparatorPtrnId);
+ }
+ if (verbose)
+ fputs("\n\n", stderr);
+ }
+ }
+ milliPause(50 * multiplier);
+ }
+
+done:
+ if (s) {
+ PR_Close(s);
+ }
+ if (requestFile && pollset[STDIN_FD].fd) {
+ PR_Close(pollset[STDIN_FD].fd);
+ }
+ return error;
+}
+
+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);
+ }
+ }
+
+ optstate = PL_CreateOptState(argc, argv,
+ "46A:BCDEFGHI:J:KL:M:N:OP:QR:STUV:W:X:YZa:bc:d:efgh:i:m:n:op:qr:st:uvw:x:z:");
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ default:
+ Usage();
+ break;
+
+ case '4':
+ allowIPv6 = PR_FALSE;
+ if (!allowIPv4)
+ Usage();
+ break;
+ case '6':
+ allowIPv4 = PR_FALSE;
+ if (!allowIPv6)
+ Usage();
+ break;
+
+ case 'A':
+ requestFile = PORT_Strdup(optstate->value);
+ break;
+
+ case 'B':
+ enableDelegatedCredentials = PR_TRUE;
+ break;
+
+ case 'C':
+ ++dumpServerChain;
+ break;
+
+ case 'D':
+ openDB = PR_FALSE;
+ break;
+
+ case 'E':
+ enablePostHandshakeAuth = PR_TRUE;
+ 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':
+ clientCertAsyncSelect = PR_FALSE;
+ 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 'N':
+ echConfigs = PORT_Strdup(optstate->value);
+ break;
+
+ case 'i':
+ echGreaseSize = PORT_Atoi(optstate->value);
+ if (!echGreaseSize || echGreaseSize > 255) {
+ fprintf(stderr, "ECH Grease size must be within 1..255 (inclusive).\n");
+ exit(-1);
+ }
+ break;
+
+ case 'P':
+ useDTLS = PR_TRUE;
+ if (!strcmp(optstate->value, "server")) {
+ actAsServer = 1;
+ } else {
+ if (strcmp(optstate->value, "client")) {
+ Usage();
+ }
+ }
+ break;
+
+ case 'Q':
+ stopAfterHandshake = PR_TRUE;
+ 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':
+ versionString = PORT_Strdup(optstate->value);
+ break;
+
+ case 'X':
+ if (!strcmp(optstate->value, "alt-server-hello")) {
+ enableAltServerHello = PR_TRUE;
+ } else {
+ Usage();
+ }
+ break;
+ case 'Y':
+ PrintCipherUsage();
+ exit(0);
+ break;
+
+ case 'Z':
+ enableZeroRtt = PR_TRUE;
+ zeroRttData = PORT_ZAlloc(ZERO_RTT_MAX);
+ if (!zeroRttData) {
+ fprintf(stderr, "Unable to allocate buffer for 0-RTT\n");
+ exit(1);
+ }
+ break;
+
+ case 'a':
+ if (!hs1SniHostName) {
+ hs1SniHostName = PORT_Strdup(optstate->value);
+ } else if (!hs2SniHostName) {
+ hs2SniHostName = PORT_Strdup(optstate->value);
+ } else {
+ Usage();
+ }
+ 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 'e':
+ middleboxCompatMode = PR_TRUE;
+ 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 'I':
+ rv = parseGroupList(optstate->value, &enabledGroups, &enabledGroupsCount);
+ if (rv != SECSuccess) {
+ PL_DestroyOptState(optstate);
+ fprintf(stderr, "Bad group specified.\n");
+ Usage();
+ }
+ break;
+
+ case 'J':
+ rv = parseSigSchemeList(optstate->value, &enabledSigSchemes, &enabledSigSchemeCount);
+ if (rv != SECSuccess) {
+ PL_DestroyOptState(optstate);
+ fprintf(stderr, "Bad signature scheme specified.\n");
+ Usage();
+ }
+ break;
+
+ case 'x':
+ rv = parseExporters(optstate->value,
+ &enabledExporters,
+ &enabledExporterCount);
+ if (rv != SECSuccess) {
+ PL_DestroyOptState(optstate);
+ fprintf(stderr, "Bad exporter specified.\n");
+ Usage();
+ }
+ break;
+
+ case 'z':
+ rv = readPSK(optstate->value, &psk, &pskLabel);
+ if (rv != SECSuccess) {
+ PL_DestroyOptState(optstate);
+ fprintf(stderr, "Bad PSK specified.\n");
+ Usage();
+ }
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+
+ SSL_VersionRangeGetSupported(useDTLS ? ssl_variant_datagram : ssl_variant_stream, &enabledVersions);
+
+ if (versionString) {
+ if (SECU_ParseSSLVersionRangeString(versionString,
+ enabledVersions, &enabledVersions) !=
+ SECSuccess) {
+ fprintf(stderr, "Bad version specified.\n");
+ Usage();
+ }
+ PORT_Free(versionString);
+ }
+
+ if (optstatus == PL_OPT_BAD) {
+ Usage();
+ }
+
+ if (!host || !portno) {
+ fprintf(stderr, "%s: parameters -h and -p are mandatory\n", progName);
+ Usage();
+ }
+
+ 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);
+ }
+
+ if (enablePostHandshakeAuth && !nickname) {
+ fprintf(stderr, "%s: -E requires the use of -n\n", progName);
+ exit(1);
+ }
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+ memset(&addr, 0, sizeof(addr));
+ status = PR_StringToNetAddr(host, &addr);
+ if (status == PR_SUCCESS) {
+ addr.inet.port = PR_htons(portno);
+ } else {
+ PRBool gotLoopbackIP = PR_FALSE;
+ if ((!strcmp(host, "localhost") || !strcmp(host, "localhost.localdomain"))
+ /* only check for preference if both types are allowed */
+ && allowIPv4 && allowIPv6) {
+ /* make a decision which IP to prefer */
+ status = PR_GetPrefLoopbackAddrInfo(&addr, portno);
+ if (status != PR_FAILURE) {
+ gotLoopbackIP = PR_TRUE;
+ }
+ }
+
+ if (!gotLoopbackIP) {
+ /* Lookup host */
+ PRAddrInfo *addrInfo;
+ void *enumPtr = NULL;
+
+ addrInfo = PR_GetAddrInfoByName(host, PR_AF_UNSPEC,
+ PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME);
+ if (!addrInfo) {
+ fprintf(stderr, "HOSTNAME=%s\n", host);
+ 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();
+ if (error) {
+ goto done;
+ }
+ }
+
+done:
+ if (s) {
+ PR_Close(s);
+ }
+
+ PORT_Free((void *)requestFile);
+ PORT_Free(hs1SniHostName);
+ PORT_Free(hs2SniHostName);
+ PORT_Free(nickname);
+ PORT_Free(pwdata.data);
+ PORT_Free(host);
+ PORT_Free(zeroRttData);
+ PORT_Free(echConfigs);
+ SECITEM_ZfreeItem(&psk, PR_FALSE);
+ SECITEM_ZfreeItem(&pskLabel, PR_FALSE);
+
+ if (enabledGroups) {
+ PORT_Free(enabledGroups);
+ }
+ if (NSS_IsInitialized()) {
+ SSL_ClearSessionCache();
+ if (initializedServerSessionCache) {
+ if (SSL_ShutdownServerSessionIDCache() != SECSuccess) {
+ error = 1;
+ }
+ }
+
+ 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 0000000000..81cbff3ed0
--- /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/validation/Makefile b/security/nss/cmd/validation/Makefile
new file mode 100644
index 0000000000..d7c879aec2
--- /dev/null
+++ b/security/nss/cmd/validation/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/validation/manifest.mn b/security/nss/cmd/validation/manifest.mn
new file mode 100644
index 0000000000..98fbe341d2
--- /dev/null
+++ b/security/nss/cmd/validation/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 = \
+ validation.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 = validation
+
+# USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/validation/validation.c b/security/nss/cmd/validation/validation.c
new file mode 100644
index 0000000000..72db89a3f1
--- /dev/null
+++ b/security/nss/cmd/validation/validation.c
@@ -0,0 +1,250 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 "nss.h"
+#include "secport.h"
+#include "secpkcs5.h"
+#include "sechash.h"
+#include "certdb.h"
+#include "secmod.h"
+
+static char *progName;
+PRBool debug = PR_FALSE;
+
+#define ERR_USAGE 2
+#define ERR_PK11GETSLOT 13
+
+static void
+Usage()
+{
+#define FPS PR_fprintf(PR_STDERR,
+ FPS "Usage: %s [-d certdir] [-P dbprefix] [-h tokenname]\n",
+ progName);
+ FPS "\t\t [-k slotpwfile | -K slotpw] [-v]\n");
+
+ exit(ERR_USAGE);
+}
+
+typedef enum {
+ tagULong,
+ tagVersion,
+ tagUtf8
+} tagType;
+
+typedef struct {
+ const char *attributeName;
+ tagType attributeStorageType;
+} attributeTag;
+
+enum {
+ opt_CertDir = 0,
+ opt_TokenName,
+ opt_SlotPWFile,
+ opt_SlotPW,
+ opt_DBPrefix,
+ opt_Debug
+};
+
+static secuCommandFlag validation_options[] = {
+ { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE },
+ { /* opt_SlotPWFile */ 'k', PR_TRUE, 0, PR_FALSE },
+ { /* opt_SlotPW */ 'K', PR_TRUE, 0, PR_FALSE },
+ { /* opt_DBPrefix */ 'P', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Debug */ 'v', PR_FALSE, 0, PR_FALSE }
+};
+
+void
+dump_Raw(char *label, CK_ATTRIBUTE *attr)
+{
+ int i;
+ unsigned char *value = (unsigned char *)attr->pValue;
+ printf("0x");
+ for (i = 0; i < attr->ulValueLen; i++) {
+ printf("%02x", value[i]);
+ }
+ printf("<%s>\n", label);
+}
+
+SECStatus
+dump_validations(CK_OBJECT_CLASS objc, CK_ATTRIBUTE *template, int count,
+ attributeTag *tags, PK11SlotInfo *slot)
+{
+ PK11GenericObject *objs, *obj;
+
+ objs = PK11_FindGenericObjects(slot, objc);
+
+ for (obj = objs; obj != NULL; obj = PK11_GetNextGenericObject(obj)) {
+ int i;
+ printf("Validation Object:\n");
+ PK11_ReadRawAttributes(NULL, PK11_TypeGeneric, obj, template, count);
+ for (i = 0; i < count; i++) {
+ CK_ULONG ulong;
+ CK_VERSION version;
+ int len = template[i].ulValueLen;
+ printf(" %s: ", tags[i].attributeName);
+ if (len < 0) {
+ printf("<failed>\n");
+ } else if (len == 0) {
+ printf("<empty>\n");
+ } else
+ switch (tags[i].attributeStorageType) {
+ case tagULong:
+ if (len != sizeof(CK_ULONG)) {
+ dump_Raw("bad ulong", &template[i]);
+ break;
+ }
+ ulong = *(CK_ULONG *)template[i].pValue;
+ printf("%ld\n", ulong);
+ break;
+ case tagVersion:
+ if (len != sizeof(CK_VERSION)) {
+ dump_Raw("bad version", &template[i]);
+ break;
+ }
+ version = *(CK_VERSION *)template[i].pValue;
+ printf("%d.%d\n", version.major, version.minor);
+ break;
+ case tagUtf8:
+ printf("%.*s\n", len, (char *)template[i].pValue);
+ break;
+ default:
+ dump_Raw("unknown tag", &template[i]);
+ break;
+ }
+ PORT_Free(template[i].pValue);
+ template[i].pValue = NULL;
+ template[i].ulValueLen = 0;
+ }
+ }
+ PK11_DestroyGenericObjects(objs);
+ return SECSuccess;
+}
+
+int
+main(int argc, char **argv)
+{
+ secuPWData slotPw = { PW_NONE, NULL };
+ secuPWData p12FilePw = { PW_NONE, NULL };
+ PK11SlotInfo *slot = NULL;
+ char *slotname = NULL;
+ char *dbprefix = "";
+ char *nssdir = NULL;
+ SECStatus rv;
+ secuCommand validation;
+ int local_errno = 0;
+
+ CK_ATTRIBUTE validation_template[] = {
+ { CKA_NSS_VALIDATION_TYPE, NULL, 0 },
+ { CKA_NSS_VALIDATION_VERSION, NULL, 0 },
+ { CKA_NSS_VALIDATION_LEVEL, NULL, 0 },
+ { CKA_NSS_VALIDATION_MODULE_ID, NULL, 0 }
+ };
+ attributeTag validation_tags[] = {
+ { "Validation Type", tagULong },
+ { "Validation Version", tagVersion },
+ { "Validation Level", tagULong },
+ { "Validation Module ID", tagUtf8 },
+ };
+
+#ifdef _CRTDBG_MAP_ALLOC
+ _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+#endif
+
+ validation.numCommands = 0;
+ validation.commands = 0;
+ validation.numOptions = PR_ARRAY_SIZE(validation_options);
+ validation.options = validation_options;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName + 1 : argv[0];
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &validation);
+
+ if (rv != SECSuccess)
+ Usage();
+
+ debug = validation.options[opt_Debug].activated;
+
+ slotname = SECU_GetOptionArg(&validation, opt_TokenName);
+
+ if (validation.options[opt_SlotPWFile].activated) {
+ slotPw.source = PW_FROMFILE;
+ slotPw.data = PORT_Strdup(validation.options[opt_SlotPWFile].arg);
+ }
+
+ if (validation.options[opt_SlotPW].activated) {
+ slotPw.source = PW_PLAINTEXT;
+ slotPw.data = PORT_Strdup(validation.options[opt_SlotPW].arg);
+ }
+
+ if (validation.options[opt_CertDir].activated) {
+ nssdir = validation.options[opt_CertDir].arg;
+ }
+ if (validation.options[opt_DBPrefix].activated) {
+ dbprefix = validation.options[opt_DBPrefix].arg;
+ }
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ if (nssdir == NULL && NSS_NoDB_Init("") == SECSuccess) {
+ rv = SECSuccess;
+ /* if the system isn't already in FIPS mode, we need
+ * to switch to FIPS mode */
+ if (!PK11_IsFIPS()) {
+ /* flip to FIPS mode */
+ SECMODModule *module = SECMOD_GetInternalModule();
+ rv = SECMOD_DeleteInternalModule(module->commonName);
+ }
+ } else if (nssdir != NULL) {
+ rv = NSS_Initialize(nssdir, dbprefix, dbprefix, "secmod.db", 0);
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ local_errno = -1;
+ goto done;
+ }
+
+ if (!slotname || PL_strcmp(slotname, "internal") == 0)
+ slot = PK11_GetInternalKeySlot();
+ else
+ slot = PK11_FindSlotByName(slotname);
+
+ if (!slot) {
+ SECU_PrintError(progName, "Invalid slot \"%s\"",
+ slotname ? "internal" : slotname);
+ local_errno = ERR_PK11GETSLOT;
+ goto done;
+ }
+
+ rv = dump_validations(CKO_NSS_VALIDATION,
+ validation_template,
+ PR_ARRAY_SIZE(validation_template),
+ validation_tags,
+ slot);
+
+done:
+ 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 (slotname) {
+ PORT_Free(slotname);
+ }
+ if (slot)
+ PK11_FreeSlot(slot);
+ if (NSS_Shutdown() != SECSuccess) {
+ local_errno = 1;
+ }
+ PL_ArenaFinish();
+ PR_Cleanup();
+ return local_errno;
+}
diff --git a/security/nss/cmd/validation/validation.gyp b/security/nss/cmd/validation/validation.gyp
new file mode 100644
index 0000000000..32edd30a4a
--- /dev/null
+++ b/security/nss/cmd/validation/validation.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': 'validation',
+ 'type': 'executable',
+ 'sources': [
+ 'validation.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/cmd/vfychain/Makefile b/security/nss/cmd/vfychain/Makefile
new file mode 100644
index 0000000000..a27a3ce97f
--- /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 0000000000..5b2ae25e7b
--- /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 0000000000..e61071814d
--- /dev/null
+++ b/security/nss/cmd/vfychain/vfychain.c
@@ -0,0 +1,821 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 12=IPsec\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++) {
+ snprintf(buff, sizeof(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 0000000000..775ba1f054
--- /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 0000000000..a27a3ce97f
--- /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 0000000000..c925be9660
--- /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 0000000000..3c6d014817
--- /dev/null
+++ b/security/nss/cmd/vfyserv/vfyserv.c
@@ -0,0 +1,575 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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(int connections)
+{
+ 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) {
+ SECStatus rv = SSL_CipherPrefSetDefault(cipher, PR_TRUE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName,
+ "error setting cipher default preference");
+ goto cleanup;
+ }
+ } else {
+ Usage(progName);
+ }
+ }
+ }
+
+ client_main(connections);
+
+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 0000000000..85001a1ec1
--- /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 0000000000..5bcc51a50d
--- /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 "keyhi.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 0000000000..8e62bc1449
--- /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 *allSuites = SSL_ImplementedCiphers;
+ int i = SSL_NumImplementedCiphers;
+ SECStatus rv;
+
+ /* disable all the SSL3 cipher suites */
+ while (--i >= 0) {
+ PRUint16 suite = allSuites[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);
+}