summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/libpkix
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /security/nss/lib/libpkix
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/nss/lib/libpkix')
-rw-r--r--security/nss/lib/libpkix/Makefile45
-rw-r--r--security/nss/lib/libpkix/include/Makefile46
-rw-r--r--security/nss/lib/libpkix/include/exports.gyp38
-rw-r--r--security/nss/lib/libpkix/include/include.gyp12
-rw-r--r--security/nss/lib/libpkix/include/manifest.mn29
-rw-r--r--security/nss/lib/libpkix/include/pkix.h301
-rw-r--r--security/nss/lib/libpkix/include/pkix_certsel.h1826
-rw-r--r--security/nss/lib/libpkix/include/pkix_certstore.h714
-rw-r--r--security/nss/lib/libpkix/include/pkix_checker.h394
-rw-r--r--security/nss/lib/libpkix/include/pkix_crlsel.h759
-rw-r--r--security/nss/lib/libpkix/include/pkix_errorstrings.h1099
-rw-r--r--security/nss/lib/libpkix/include/pkix_params.h1793
-rw-r--r--security/nss/lib/libpkix/include/pkix_pl_pki.h2735
-rw-r--r--security/nss/lib/libpkix/include/pkix_pl_system.h1545
-rw-r--r--security/nss/lib/libpkix/include/pkix_results.h425
-rw-r--r--security/nss/lib/libpkix/include/pkix_revchecker.h215
-rw-r--r--security/nss/lib/libpkix/include/pkix_sample_modules.h420
-rw-r--r--security/nss/lib/libpkix/include/pkix_util.h941
-rw-r--r--security/nss/lib/libpkix/include/pkixt.h485
-rw-r--r--security/nss/lib/libpkix/libpkix.gyp31
-rw-r--r--security/nss/lib/libpkix/manifest.mn13
-rw-r--r--security/nss/lib/libpkix/pkix/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/certsel.gyp24
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/exports.gyp26
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/manifest.mn20
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/pkix_certselector.c1637
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/pkix_certselector.h41
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.c1188
-rw-r--r--security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.h57
-rw-r--r--security/nss/lib/libpkix/pkix/checker/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/checker/checker.gyp35
-rw-r--r--security/nss/lib/libpkix/pkix/checker/exports.gyp37
-rw-r--r--security/nss/lib/libpkix/pkix/checker/manifest.mn42
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.c306
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.h42
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.c322
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.h36
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c438
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.h68
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c328
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.h92
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.c113
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.h30
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.c121
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.h30
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c340
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.h43
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c419
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.h67
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_policychecker.c2783
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_policychecker.h73
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c475
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.h151
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.c66
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.h81
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c443
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.h44
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c516
-rw-r--r--security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.h47
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/crlsel.gyp24
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/exports.gyp26
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/manifest.mn20
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.c826
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.h38
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.c870
-rw-r--r--security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.h40
-rw-r--r--security/nss/lib/libpkix/pkix/manifest.mn11
-rw-r--r--security/nss/lib/libpkix/pkix/params/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/params/exports.gyp28
-rw-r--r--security/nss/lib/libpkix/pkix/params/manifest.mn24
-rw-r--r--security/nss/lib/libpkix/pkix/params/params.gyp26
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_procparams.c1417
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_procparams.h50
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.c433
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.h36
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_trustanchor.c525
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_trustanchor.h35
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_valparams.c335
-rw-r--r--security/nss/lib/libpkix/pkix/params/pkix_valparams.h33
-rw-r--r--security/nss/lib/libpkix/pkix/results/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/results/exports.gyp28
-rw-r--r--security/nss/lib/libpkix/pkix/results/manifest.mn24
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_buildresult.c362
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_buildresult.h40
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_policynode.c1377
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_policynode.h74
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_valresult.c442
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_valresult.h43
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_verifynode.c1182
-rw-r--r--security/nss/lib/libpkix/pkix/results/pkix_verifynode.h75
-rw-r--r--security/nss/lib/libpkix/pkix/results/results.gyp26
-rw-r--r--security/nss/lib/libpkix/pkix/store/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/store/exports.gyp25
-rw-r--r--security/nss/lib/libpkix/pkix/store/manifest.mn18
-rw-r--r--security/nss/lib/libpkix/pkix/store/pkix_store.c415
-rw-r--r--security/nss/lib/libpkix/pkix/store/pkix_store.h41
-rw-r--r--security/nss/lib/libpkix/pkix/store/store.gyp23
-rw-r--r--security/nss/lib/libpkix/pkix/top/Makefile46
-rw-r--r--security/nss/lib/libpkix/pkix/top/exports.gyp27
-rw-r--r--security/nss/lib/libpkix/pkix/top/manifest.mn22
-rw-r--r--security/nss/lib/libpkix/pkix/top/pkix_build.c3763
-rw-r--r--security/nss/lib/libpkix/pkix/top/pkix_build.h120
-rw-r--r--security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c210
-rw-r--r--security/nss/lib/libpkix/pkix/top/pkix_lifecycle.h23
-rw-r--r--security/nss/lib/libpkix/pkix/top/pkix_validate.c1451
-rw-r--r--security/nss/lib/libpkix/pkix/top/pkix_validate.h42
-rw-r--r--security/nss/lib/libpkix/pkix/top/top.gyp25
-rw-r--r--security/nss/lib/libpkix/pkix/util/Makefile44
-rw-r--r--security/nss/lib/libpkix/pkix/util/exports.gyp28
-rw-r--r--security/nss/lib/libpkix/pkix/util/manifest.mn25
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_error.c565
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_error.h36
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_errpaths.c103
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_list.c1701
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_list.h95
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_logger.c1088
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_logger.h57
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_tools.c1525
-rw-r--r--security/nss/lib/libpkix/pkix/util/pkix_tools.h1588
-rw-r--r--security/nss/lib/libpkix/pkix/util/util.gyp27
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/Makefile44
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/manifest.mn11
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/Makefile66
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/exports.gyp36
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/manifest.mn34
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/module.gyp41
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c699
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.h65
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.c1292
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.h34
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c1147
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.h62
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c1654
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.h139
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.c1113
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.h75
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.c2494
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.h82
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c757
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.h86
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.c786
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.h96
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapt.h314
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaptemplates.c417
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.c389
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.h61
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.c1039
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.h31
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c1695
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.h209
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/Makefile47
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/exports.gyp41
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/manifest.mn50
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pki.gyp39
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.c407
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.h47
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c3734
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.h107
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.c371
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.h50
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.c386
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.h49
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.c365
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.h52
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c1068
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.h48
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.c151
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.h53
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c880
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.h46
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c466
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.h55
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c873
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.h49
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c874
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.h49
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.c1279
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.h68
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c251
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.h53
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.c441
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.h61
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c1069
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.h106
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c489
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.h38
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c667
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.h74
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/Makefile47
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/exports.gyp37
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/manifest.mn43
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c398
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.h40
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c504
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.h40
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c1073
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h159
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c26
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c383
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h29
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c279
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h91
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.c168
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h24
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.c136
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.h33
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.c163
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.h33
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c1440
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.h76
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c316
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h39
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c584
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.h102
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c217
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.h35
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.c628
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.h37
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/system/system.gyp36
221 files changed, 83509 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/Makefile b/security/nss/lib/libpkix/Makefile
new file mode 100644
index 0000000000..bb88772853
--- /dev/null
+++ b/security/nss/lib/libpkix/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). #
+#######################################################################
+
+#######################################################################
+# (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/lib/libpkix/include/Makefile b/security/nss/lib/libpkix/include/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/include/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). #
+#######################################################################
+
+
+#######################################################################
+# (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/lib/libpkix/include/exports.gyp b/security/nss/lib/libpkix/include/exports.gyp
new file mode 100644
index 0000000000..92baaaa9d2
--- /dev/null
+++ b/security/nss/lib/libpkix/include/exports.gyp
@@ -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/.
+{
+ 'includes': [
+ '../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_libpkix_include_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix.h',
+ 'pkix_certsel.h',
+ 'pkix_certstore.h',
+ 'pkix_checker.h',
+ 'pkix_crlsel.h',
+ 'pkix_errorstrings.h',
+ 'pkix_params.h',
+ 'pkix_pl_pki.h',
+ 'pkix_pl_system.h',
+ 'pkix_results.h',
+ 'pkix_revchecker.h',
+ 'pkix_sample_modules.h',
+ 'pkix_util.h',
+ 'pkixt.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/include/include.gyp b/security/nss/lib/libpkix/include/include.gyp
new file mode 100644
index 0000000000..c435015910
--- /dev/null
+++ b/security/nss/lib/libpkix/include/include.gyp
@@ -0,0 +1,12 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.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': [],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/include/manifest.mn b/security/nss/lib/libpkix/include/manifest.mn
new file mode 100644
index 0000000000..3792dbb869
--- /dev/null
+++ b/security/nss/lib/libpkix/include/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 = ../../..
+
+PRIVATE_EXPORTS = \
+ pkix.h \
+ pkix_crlsel.h \
+ pkix_errorstrings.h \
+ pkix_results.h \
+ pkixt.h \
+ pkix_certsel.h \
+ pkix_params.h \
+ pkix_revchecker.h \
+ pkix_certstore.h \
+ pkix_pl_pki.h \
+ pkix_sample_modules.h \
+ pkix_checker.h \
+ pkix_pl_system.h \
+ pkix_util.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ $(NULL)
+
+REQUIRES = dbm
diff --git a/security/nss/lib/libpkix/include/pkix.h b/security/nss/lib/libpkix/include/pkix.h
new file mode 100644
index 0000000000..4ef3cf1fbd
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkix.h
@@ -0,0 +1,301 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 file defines the public API for libpkix. These are the top-level
+ * functions in the library. They perform the primary operations of this
+ * library: building and validating chains of X.509 certificates.
+ *
+ */
+
+#ifndef _PKIX_H
+#define _PKIX_H
+
+#include "pkixt.h"
+#include "pkix_util.h"
+#include "pkix_results.h"
+#include "pkix_certstore.h"
+#include "pkix_certsel.h"
+#include "pkix_crlsel.h"
+#include "pkix_checker.h"
+#include "pkix_revchecker.h"
+#include "pkix_pl_system.h"
+#include "pkix_pl_pki.h"
+#include "pkix_params.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General
+ *
+ * Please refer to the libpkix Programmer's Guide for detailed information
+ * about how to use the libpkix library. Certain key warnings and notices from
+ * that document are repeated here for emphasis.
+ *
+ * All identifiers in this file (and all public identifiers defined in
+ * libpkix) begin with "PKIX_". Private identifiers only intended for use
+ * within the library begin with "pkix_".
+ *
+ * A function returns NULL upon success, and a PKIX_Error pointer upon failure.
+ *
+ * Unless otherwise noted, for all accessor (gettor) functions that return a
+ * PKIX_PL_Object pointer, callers should assume that this pointer refers to a
+ * shared object. Therefore, the caller should treat this shared object as
+ * read-only and should not modify this shared object. When done using the
+ * shared object, the caller should release the reference to the object by
+ * using the PKIX_PL_Object_DecRef function.
+ *
+ * While a function is executing, if its arguments (or anything referred to by
+ * its arguments) are modified, free'd, or destroyed, the function's behavior
+ * is undefined.
+ *
+ */
+
+/*
+ * FUNCTION: PKIX_Initialize
+ * DESCRIPTION:
+ *
+ * No PKIX_* types and functions should be used before this function is called
+ * and returns successfully. This function should only be called once. If it
+ * is called more than once, the behavior is undefined.
+ *
+ * NSS applications are expected to call NSS_Init, and need not know that
+ * NSS will call this function (with "platformInitNeeded" set to PKIX_FALSE).
+ * PKIX applications are expected instead to call this function with
+ * "platformInitNeeded" set to PKIX_TRUE.
+ *
+ * This function initializes data structures critical to the operation of
+ * libpkix. It also ensures that the API version (major.minor) desired by the
+ * caller (the "desiredMajorVersion", "minDesiredMinorVersion", and
+ * "maxDesiredMinorVersion") is compatible with the API version supported by
+ * the library. As such, the library must support the "desiredMajorVersion"
+ * of the API and must support a minor version that falls between
+ * "minDesiredMinorVersion" and "maxDesiredMinorVersion", inclusive. If
+ * compatibility exists, the function returns NULL and stores the library's
+ * actual minor version at "pActualMinorVersion" (which may be greater than
+ * "desiredMinorVersion"). If no compatibility exists, the function returns a
+ * PKIX_Error pointer. If the caller wishes to specify that the largest
+ * minor version available should be used, then maxDesiredMinorVersion should
+ * be set to the macro PKIX_MAX_MINOR_VERSION (defined in pkixt.h).
+ *
+ * PARAMETERS:
+ * "platformInitNeeded"
+ * Boolean indicating whether the platform layer initialization code
+ * has previously been run, or should be called from this function.
+ * "desiredMajorVersion"
+ * The major version of the libpkix API the application wishes to use.
+ * "minDesiredMinorVersion"
+ * The minimum minor version of the libpkix API the application wishes
+ * to use.
+ * "maxDesiredMinorVersion"
+ * The maximum minor version of the libpkix API the application wishes
+ * to use.
+ * "pActualMinorVersion"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "pPlContext"
+ * Address at which platform-specific context pointer is stored. Must
+ * be non-NULL.
+ * THREAD SAFETY:
+ * Not Thread Safe
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Initialize Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Initialize(
+ PKIX_Boolean platformInitNeeded,
+ PKIX_UInt32 desiredMajorVersion,
+ PKIX_UInt32 minDesiredMinorVersion,
+ PKIX_UInt32 maxDesiredMinorVersion,
+ PKIX_UInt32 *pActualMinorVersion,
+ void **pPlContext);
+
+/*
+ * FUNCTION: PKIX_Shutdown
+ * DESCRIPTION:
+ *
+ * This function deallocates any memory used by libpkix and shuts down any
+ * ongoing operations. This function should only be called once. If it is
+ * called more than once, the behavior is undefined.
+ *
+ * No PKIX_* types and functions should be used after this function is called
+ * and returns successfully.
+ * PARAMETERS:
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Shutdown(void *plContext);
+
+/*
+ * FUNCTION: PKIX_ValidateChain
+ * DESCRIPTION:
+ *
+ * This function attempts to validate the CertChain that has been set in the
+ * ValidateParams pointed to by "params" using an RFC 3280-compliant
+ * algorithm. If successful, this function returns NULL and stores the
+ * ValidateResult at "pResult", which holds additional information, such as
+ * the policy tree and the target's public key. If unsuccessful, an Error is
+ * returned. Note: This function does not currently support non-blocking I/O.
+ *
+ * If "pVerifyTree" is non-NULL, a chain of VerifyNodes is created which
+ * tracks the results of the validation. That is, either each node in the
+ * chain has a NULL Error component, or the last node contains an Error
+ * which indicates why the validation failed.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ValidateParams used to validate CertChain. Must be non-NULL.
+ * "pResult"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "pVerifyTree"
+ * Address where a VerifyTree is stored, if non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (See Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Validate Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ValidateChain(
+ PKIX_ValidateParams *params,
+ PKIX_ValidateResult **pResult,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ValidateChain_NB
+ * DESCRIPTION:
+ *
+ * This function is the equivalent of PKIX_ValidateChain, except that it
+ * supports non-blocking I/O. When called with "pNBIOContext" pointing to NULL
+ * it initiates a new chain validation as in PKIX_ValidateChain, ignoring the
+ * value in all input variables except "params". If forced to suspend
+ * processing by a WOULDBLOCK return from some operation, such as a CertStore
+ * request, it stores the platform-dependent I/O context at "pNBIOContext" and
+ * stores other intermediate variables at "pCertIndex", "pAnchorIndex",
+ * "pCheckerIndex", "pRevChecking", and "pCheckers".
+ *
+ * When called subsequently with that non-NULL value at "pNBIOContext", it
+ * relies on those intermediate values to be untouched, and it resumes chain
+ * validation where it left off. Its behavior is undefined if any of the
+ * intermediate values was not preserved.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ValidateParams used to validate CertChain. Must be non-NULL.
+ * "pCertIndex"
+ * The UInt32 value of the index to the Cert chain, indicating which Cert
+ * is currently being processed.
+ * "pAnchorIndex"
+ * The UInt32 value of the index to the Anchor chain, indicating which
+ * Trust Anchor is currently being processed.
+ * "pCheckerIndex"
+ * The UInt32 value of the index to the List of CertChainCheckers,
+ * indicating which Checker is currently processing.
+ * "pRevChecking"
+ * The Boolean flag indicating whether normal checking or revocation
+ * checking is occurring for the Cert indicated by "pCertIndex".
+ * "pCheckers"
+ * The address of the List of CertChainCheckers. Must be non-NULL.
+ * "pNBIOContext"
+ * The address of the platform-dependend I/O context. Must be a non-NULL
+ * pointer to a NULL value for the call to initiate chain validation.
+ * "pResult"
+ * Address where ValidateResult object pointer will be stored. Must be
+ * non-NULL.
+ * "pVerifyTree"
+ * Address where a VerifyTree is stored, if non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a VALIDATE Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */PKIX_Error *
+PKIX_ValidateChain_NB(
+ PKIX_ValidateParams *params,
+ PKIX_UInt32 *pCertIndex,
+ PKIX_UInt32 *pAnchorIndex,
+ PKIX_UInt32 *pCheckerIndex,
+ PKIX_Boolean *pRevChecking,
+ PKIX_List **pCheckers,
+ void **pNBIOContext,
+ PKIX_ValidateResult **pResult,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_BuildChain
+ * DESCRIPTION:
+ *
+ * If called with a NULL "state", this function attempts to build and validate
+ * a CertChain according to the ProcessingParams pointed to by "params", using
+ * an RFC 3280-compliant validation algorithm. If successful, this function
+ * returns NULL and stores the BuildResult at "pResult", which holds the built
+ * CertChain, as well as additional information, such as the policy tree and
+ * the target's public key. If unsuccessful, an Error is returned.
+ *
+ * If the chain building is blocked by a CertStore using non-blocking I/O, this
+ * function stores platform-dependent non-blocking I/O context at
+ * "pNBIOContext", its state at "pState", and NULL at "pResult". The caller
+ * may be able to determine, in a platform-dependent way, when the I/O has
+ * completed. In any case, calling the function again with "pState" containing
+ * the returned value will allow the chain building to resume.
+ *
+ * If chain building is completed, either successfully or unsuccessfully, NULL
+ * is stored at "pNBIOContext".
+ *
+ * If "pVerifyTree" is non-NULL, a tree of VerifyNodes is created which
+ * tracks the results of the building. That is, each node of the tree either
+ * has a NULL Error component, or it is a leaf node and it contains an Error
+ * which indicates why the chain building could not proceed on this branch.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams used to build and validate CertChain.
+ * Must be non-NULL.
+ * "pNBIOContext"
+ * Address where platform-dependent information is store if the build
+ * is suspended waiting for non-blocking I/O. Must be non-NULL.
+ * "pState"
+ * Address of BuildChain state. Must be NULL on initial call, and the
+ * value previously returned on subsequent calls.
+ * "pResult"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "pVerifyTree"
+ * Address where a VerifyTree is stored, if non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (See Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_BuildChain(
+ PKIX_ProcessingParams *params,
+ void **pNBIOContext,
+ void **pState,
+ PKIX_BuildResult **pResult,
+ PKIX_VerifyNode **pVerifyNode,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_H */
diff --git a/security/nss/lib/libpkix/include/pkix_certsel.h b/security/nss/lib/libpkix/include/pkix_certsel.h
new file mode 100644
index 0000000000..e6b20c8c50
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkix_certsel.h
@@ -0,0 +1,1826 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 file defines functions associated with the PKIX_CertSelector and the
+ * PKIX_ComCertSelParams types.
+ *
+ */
+
+#ifndef _PKIX_CERTSEL_H
+#define _PKIX_CERTSEL_H
+
+#include "pkixt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General
+ *
+ * Please refer to the libpkix Programmer's Guide for detailed information
+ * about how to use the libpkix library. Certain key warnings and notices from
+ * that document are repeated here for emphasis.
+ *
+ * All identifiers in this file (and all public identifiers defined in
+ * libpkix) begin with "PKIX_". Private identifiers only intended for use
+ * within the library begin with "pkix_".
+ *
+ * A function returns NULL upon success, and a PKIX_Error pointer upon failure.
+ *
+ * Unless otherwise noted, for all accessor (gettor) functions that return a
+ * PKIX_PL_Object pointer, callers should assume that this pointer refers to a
+ * shared object. Therefore, the caller should treat this shared object as
+ * read-only and should not modify this shared object. When done using the
+ * shared object, the caller should release the reference to the object by
+ * using the PKIX_PL_Object_DecRef function.
+ *
+ * While a function is executing, if its arguments (or anything referred to by
+ * its arguments) are modified, free'd, or destroyed, the function's behavior
+ * is undefined.
+ *
+ */
+
+/* PKIX_CertSelector
+ *
+ * PKIX_CertSelectors provide a standard way for the caller to select
+ * certificates based on particular criteria. A CertSelector is typically used
+ * by the caller to specify the constraints they wish to impose on the target
+ * certificate in a chain. (see pkix_params.h) A CertSelector is also often
+ * used to retrieve certificates from a CertStore that match the selector's
+ * criteria. (See pkix_certstore.h) For example, the caller may wish to only
+ * select those certificates that have a particular Subject Distinguished Name
+ * and a particular value for a private certificate extension. The
+ * MatchCallback allows the caller to specify the custom matching logic to be
+ * used by a CertSelector.
+ *
+ * By default, the MatchCallback is set to point to the default implementation
+ * provided by libpkix, which understands how to process the most common
+ * parameters. If the default implementation is used, the caller should set
+ * these common parameters using PKIX_CertSelector_SetCommonCertSelectorParams.
+ * Any common parameter that is not set is assumed to be disabled, which means
+ * the default MatchCallback implementation will select all certificates
+ * without regard to that particular disabled parameter. For example, if the
+ * SerialNumber parameter is not set, MatchCallback will not filter out any
+ * certificate based on its serial number. As such, if no parameters are set,
+ * all are disabled and any certificate will match. If a parameter is
+ * disabled, its associated PKIX_ComCertSelParams_Get* function returns a
+ * default value of NULL, or -1 for PKIX_ComCertSelParams_GetBasicConstraints
+ * and PKIX_ComCertSelParams_GetVersion, or 0 for
+ * PKIX_ComCertSelParams_GetKeyUsage.
+ *
+ * If a custom implementation is desired, the default implementation can be
+ * overridden by calling PKIX_CertSelector_SetMatchCallback. In this case, the
+ * CertSelector can be initialized with a certSelectorContext, which is where
+ * the caller can specify the desired parameters the caller wishes to match
+ * against. Note that this certSelectorContext must be an Object (although any
+ * object type), allowing it to be reference-counted and allowing it to
+ * provide the standard Object functions (Equals, Hashcode, ToString, Compare,
+ * Duplicate).
+ *
+ */
+
+/*
+ * FUNCTION: PKIX_CertSelector_MatchCallback
+ * DESCRIPTION:
+ *
+ * This callback function determines whether the specified Cert pointed to by
+ * "cert" matches the criteria of the CertSelector pointed to by "selector".
+ * If the Cert does not matches the CertSelector's criteria, an exception will
+ * be thrown.
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CertSelector whose MatchCallback logic and parameters are
+ * to be used. Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched using "selector".
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_CertSelector_MatchCallback)(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Cert *cert,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertSelector_Create
+ * DESCRIPTION:
+ *
+ * Creates a new CertSelector using the Object pointed to by
+ * "certSelectorContext" (if any) and stores it at "pSelector". As noted
+ * above, by default, the MatchCallback is set to point to the default
+ * implementation provided by libpkix, which understands how to process
+ * ComCertSelParams objects. This is overridden if the MatchCallback pointed
+ * to by "callback" is not NULL, in which case the parameters are specified
+ * using the certSelectorContext.
+ *
+ * PARAMETERS:
+ * "callback"
+ * The MatchCallback function to be used.
+ * "certSelectorContext"
+ * Address of Object representing the CertSelector's context (if any).
+ * "pSelector"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertSelector_Create(
+ PKIX_CertSelector_MatchCallback callback,
+ PKIX_PL_Object *certSelectorContext,
+ PKIX_CertSelector **pSelector,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertSelector_GetMatchCallback
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to "selector's" Match callback function and puts it in
+ * "pCallback".
+ *
+ * PARAMETERS:
+ * "selector"
+ * The CertSelector whose Match callback is desired. Must be non-NULL.
+ * "pCallback"
+ * Address where Match callback function pointer will be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertSelector_GetMatchCallback(
+ PKIX_CertSelector *selector,
+ PKIX_CertSelector_MatchCallback *pCallback,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertSelector_GetCertSelectorContext
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a PKIX_PL_Object representing the context (if any)
+ * of the CertSelector pointed to by "selector" and stores it at
+ * "pCertSelectorContext".
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CertSelector whose context is to be stored.
+ * Must be non-NULL.
+ * "pCertSelectorContext"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertSelector_GetCertSelectorContext(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Object **pCertSelectorContext,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertSelector_GetCommonCertSelectorParams
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the ComCertSelParams object that represent the
+ * common parameters of the CertSelector pointed to by "selector" and stores
+ * it at "pCommonCertSelectorParams". If there are no common parameters
+ * stored with the CertSelector, this function stores NULL at
+ * "pCommonCertSelectorParams".
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CertSelector whose ComCertSelParams object is to be stored.
+ * Must be non-NULL.
+ * "pCommonCertSelectorParams"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertSelector_GetCommonCertSelectorParams(
+ PKIX_CertSelector *selector,
+ PKIX_ComCertSelParams **pCommonCertSelectorParams,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertSelector_SetCommonCertSelectorParams
+ * DESCRIPTION:
+ *
+ * Sets the common parameters for the CertSelector pointed to by "selector"
+ * using the ComCertSelParams object pointed to by "commonCertSelectorParams".
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CertSelector whose common parameters are to be set.
+ * Must be non-NULL.
+ * "commonCertSelectorParams"
+ * Address of ComCertSelParams object representing the common parameters.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "selector"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertSelector_SetCommonCertSelectorParams(
+ PKIX_CertSelector *selector,
+ PKIX_ComCertSelParams *commonCertSelectorParams,
+ void *plContext);
+
+/* PKIX_ComCertSelParams
+ *
+ * PKIX_ComCertSelParams objects are X.509 parameters commonly used with
+ * CertSelectors, especially when enforcing constraints on a target
+ * certificate or determining which certificates to retrieve from a CertStore.
+ * ComCertSelParams objects are typically used with those CertSelectors that
+ * use the default implementation of MatchCallback, which understands how to
+ * process ComCertSelParams objects.
+ */
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_Create
+ * DESCRIPTION:
+ *
+ * Creates a new ComCertSelParams object and stores it at "pParams".
+ *
+ * PARAMETERS:
+ * "pParams"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_Create(
+ PKIX_ComCertSelParams **pParams,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubjAltNames
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of GeneralNames (if any) representing the
+ * subject alternative names criterion that is set in the ComCertSelParams
+ * object pointed to by "params" and stores it at "pNames". In order to match
+ * against this criterion, a certificate must contain all or at least one of
+ * the criterion's subject alternative names (depending on the result of
+ * PKIX_ComCertSelParams_GetMatchAllSubjAltNames). The default behavior
+ * requires a certificate to contain all of the criterion's subject
+ * alternative names in order to match.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pNames", in which case all certificates are considered to match this
+ * criterion.
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose subject alternative names
+ * criterion (if any) is to be stored. Must be non-NULL.
+ * "pNames"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_List **pNames, /* list of PKIX_PL_GeneralName */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubjAltNames
+ * DESCRIPTION:
+ *
+ * Sets the subject alternative names criterion of the ComCertSelParams object
+ * pointed to by "params" using a List of GeneralNames pointed to by "names".
+ * In order to match against this criterion, a certificate must contain all or
+ * at least one of the criterion's subject alternative names (depending on the
+ * result of PKIX_ComCertSelParams_GetMatchAllSubjAltNames). The default
+ * behavior requires a certificate to contain all of the criterion's subject
+ * alternative names in order to match.
+ *
+ * If "names" is NULL, all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose subject alternative
+ * names criterion is to be set. Must be non-NULL.
+ * "names"
+ * Address of List of GeneralNames used to set the criterion
+ * (or NULL to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_List *names, /* list of PKIX_PL_GeneralName */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_AddSubjAltName
+ * DESCRIPTION:
+ *
+ * Adds to the subject alternative names criterion of the ComCertSelParams
+ * object pointed to by "params" using the GeneralName pointed to by "name".
+ * In order to match against this criterion, a certificate must contain all
+ * or at least one of the criterion's subject alternative names (depending on
+ * the result of PKIX_ComCertSelParams_GetMatchAllSubjAltNames). The default
+ * behavior requires a certificate to contain all of the criterion's subject
+ * alternative names in order to match.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose subject alternative names
+ * criterion is to be added to. Must be non-NULL.
+ * "name"
+ * Address of GeneralName to be added.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_AddSubjAltName(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_GeneralName *name,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetPathToNames
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of GeneralNames (if any) representing the
+ * path to names criterion that is set in the ComCertSelParams object pointed
+ * to by "params" and stores it at "pNames". In order to match against this
+ * criterion, a certificate must not include name constraints that would
+ * prohibit building a path to the criterion's specified names.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pNames", in which case all certificates are considered to match this
+ * criterion.
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose path to names criterion
+ * (if any) is to be stored. Must be non-NULL.
+ * "pNames"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetPathToNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_List **pNames, /* list of PKIX_PL_GeneralName */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetPathToNames
+ * DESCRIPTION:
+ *
+ * Sets the path to names criterion of the ComCertSelParams object pointed to
+ * by "params" using a List of GeneralNames pointed to by "names". In order to
+ * match against this criterion, a certificate must not include name
+ * constraints that would prohibit building a path to the criterion's
+ * specified names.
+ *
+ * If "names" is NULL, all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose path to names criterion
+ * is to be set. Must be non-NULL.
+ * "names"
+ * Address of List of GeneralNames used to set the criterion
+ * (or NULL to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetPathToNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_List *names, /* list of PKIX_PL_GeneralName */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_AddPathToName
+ * DESCRIPTION:
+ *
+ * Adds to the path to names criterion of the ComCertSelParams object pointed
+ * to by "params" using the GeneralName pointed to by "pathToName". In order
+ * to match against this criterion, a certificate must not include name
+ * constraints that would prohibit building a path to the criterion's
+ * specified names.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose path to names criterion is to
+ * be added to. Must be non-NULL.
+ * "pathToName"
+ * Address of GeneralName to be added.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_AddPathToName(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_GeneralName *pathToName,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetAuthorityKeyIdentifier
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the ByteArray (if any) representing the authority
+ * key identifier criterion that is set in the ComCertSelParams object
+ * pointed to by "params" and stores it at "pAuthKeyId". In order to match
+ * against this criterion, a certificate must contain an
+ * AuthorityKeyIdentifier extension whose value matches the criterion's
+ * authority key identifier value.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pAuthKeyId", in which case all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose authority key identifier
+ * criterion (if any) is to be stored. Must be non-NULL.
+ * "pAuthKeyId"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetAuthorityKeyIdentifier(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray **pAuthKeyId,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetAuthorityKeyIdentifier
+ * DESCRIPTION:
+ *
+ * Sets the authority key identifier criterion of the ComCertSelParams object
+ * pointed to by "params" to the ByteArray pointed to by "authKeyId". In
+ * order to match against this criterion, a certificate must contain an
+ * AuthorityKeyIdentifier extension whose value matches the criterion's
+ * authority key identifier value.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose authority key identifier
+ * criterion is to be set. Must be non-NULL.
+ * "authKeyId"
+ * Address of ByteArray used to set the criterion
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetAuthorityKeyIdentifier(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray *authKeyId,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubjKeyIdentifier
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the ByteArray (if any) representing the subject key
+ * identifier criterion that is set in the ComCertSelParams object pointed to
+ * by "params" and stores it at "pSubjKeyId". In order to match against this
+ * criterion, a certificate must contain a SubjectKeyIdentifier extension
+ * whose value matches the criterion's subject key identifier value.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pSubjKeyId", in which case all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose subject key identifier
+ * criterion (if any) is to be stored. Must be non-NULL.
+ * "pSubjKeyId"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubjKeyIdentifier(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray **pSubjKeyId,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubjKeyIdentifier
+ * DESCRIPTION:
+ *
+ * Sets the subject key identifier criterion of the ComCertSelParams object
+ * pointed to by "params" using a ByteArray pointed to by "subjKeyId". In
+ * order to match against this criterion, a certificate must contain an
+ * SubjectKeyIdentifier extension whose value matches the criterion's subject
+ * key identifier value.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose subject key identifier
+ * criterion is to be set. Must be non-NULL.
+ * "subjKeyId"
+ * Address of ByteArray used to set the criterion
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubjKeyIdentifier(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray *subKeyId,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubjPubKey
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the PublicKey (if any) representing the subject
+ * public key criterion that is set in the ComCertSelParams object pointed to
+ * by "params" and stores it at "pPubKey". In order to match against this
+ * criterion, a certificate must contain a SubjectPublicKey that matches the
+ * criterion's public key.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pPubKey", in which case all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose subject public key criterion
+ * (if any) is to be stored. Must be non-NULL.
+ * "pPubKey"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubjPubKey(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_PublicKey **pPubKey,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubjPubKey
+ * DESCRIPTION:
+ *
+ * Sets the subject public key criterion of the ComCertSelParams object
+ * pointed to by "params" using a PublicKey pointed to by "pubKey". In order
+ * to match against this criterion, a certificate must contain a
+ * SubjectPublicKey that matches the criterion's public key.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose subject public key
+ * criterion is to be set. Must be non-NULL.
+ * "pubKey"
+ * Address of PublicKey used to set the criterion
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubjPubKey(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_PublicKey *pubKey,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubjPKAlgId
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the OID (if any) representing the subject public key
+ * algorithm identifier criterion that is set in the ComCertSelParams object
+ * pointed to by "params" and stores it at "pPubKey". In order to match
+ * against this criterion, a certificate must contain a SubjectPublicKey with
+ * an algorithm that matches the criterion's algorithm.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pAlgId", in which case all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose subject public key algorithm
+ * identifier (if any) is to be stored. Must be non-NULL.
+ * "pAlgId"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubjPKAlgId(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_OID **pAlgId,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubjPKAlgId
+ * DESCRIPTION:
+ *
+ * Sets the subject public key algorithm identifier criterion of the
+ * ComCertSelParams object pointed to by "params" using an OID pointed to by
+ * "algId". In order to match against this criterion, a certificate must
+ * contain a SubjectPublicKey with an algorithm that matches the criterion's
+ * algorithm.
+ *
+ * If "algId" is NULL, all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose subject public key
+ * algorithm identifier criterion is to be set. Must be non-NULL.
+ * "algId"
+ * Address of OID used to set criterion
+ * (or NULL to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubjPKAlgId(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_OID *algId,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetBasicConstraints
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the minimum path length (if any) representing the
+ * basic constraints criterion that is set in the ComCertSelParams object
+ * pointed to by "params" and stores it at "pMinPathLength". In order to
+ * match against this criterion, there are several possibilities.
+ *
+ * 1) If the criterion's minimum path length is greater than or equal to zero,
+ * a certificate must include a BasicConstraints extension with a pathLen of
+ * at least this value.
+ *
+ * 2) If the criterion's minimum path length is -2, a certificate must be an
+ * end-entity certificate.
+ *
+ * 3) If the criterion's minimum path length is -1, no basic constraints check
+ * is done and all certificates are considered to match this criterion.
+ *
+ * The semantics of other values of the criterion's minimum path length are
+ * undefined but may be defined in future versions of the API.
+ *
+ * If "params" does not have this criterion set, this function stores -1 at
+ * "pMinPathLength", in which case all certificates are considered to match
+ * this criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose basic constraints criterion
+ * (if any) is to be stored. Must be non-NULL.
+ * "pMinPathLength"
+ * Address where PKIX_Int32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetBasicConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_Int32 *pMinPathLength,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetBasicConstraints
+ * DESCRIPTION:
+ *
+ * Sets the basic constraints criterion of the ComCertSelParams object
+ * pointed to by "params" using the integer value of "minPathLength". In
+ * order to match against this criterion, there are several possibilities.
+ *
+ * 1) If the criterion's minimum path length is greater than or equal to zero,
+ * a certificate must include a BasicConstraints extension with a pathLen of
+ * at least this value.
+ *
+ * 2) If the criterion's minimum path length is -2, a certificate must be an
+ * end-entity certificate.
+ *
+ * 3) If the criterion's minimum path length is -1, no basic constraints check
+ * is done and all certificates are considered to match this criterion.
+ *
+ * The semantics of other values of the criterion's minimum path length are
+ * undefined but may be defined in future versions of the API.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose basic constraints
+ * criterion is to be set. Must be non-NULL.
+ * "minPathLength"
+ * Value of PKIX_Int32 used to set the criterion
+ * (or -1 to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetBasicConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_Int32 minPathLength,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetCertificate
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the Cert (if any) representing the certificate
+ * criterion that is set in the ComCertSelParams object pointed to by
+ * "params" and stores it at "pCert". In order to match against this
+ * criterion, a certificate must be equal to the criterion's certificate. If
+ * this criterion is specified, it is usually not necessary to specify any
+ * other criteria, since this criterion requires an exact certificate match.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pCert", in which case all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose certificate criterion
+ * (if any) is to be stored. Must be non-NULL.
+ * "pCert"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetCertificate(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert **pCert,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetCertificate
+ * DESCRIPTION:
+ *
+ * Sets the certificate criterion of the ComCertSelParams object pointed to by
+ * "params" using a Cert pointed to by "cert". In order to match against this
+ * criterion, a certificate must be equal to the criterion's certificate.
+ * If this criterion is specified, it is usually not necessary to specify
+ * any other criteria, since this criterion requires an exact certificate
+ * match.
+ *
+ * If "cert" is NULL, all certificates are considered to match this criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose certificate criterion is to be
+ * set. Must be non-NULL.
+ * "cert"
+ * Address of Cert used to set the criterion
+ * (or NULL to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetCertificate(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetCertificateValid
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the Date (if any) representing the certificate
+ * validity criterion that is set in the ComCertSelParams object pointed to by
+ * "params" and stores it at "pDate". In order to match against this
+ * criterion, a certificate's validity period must include the criterion's
+ * Date.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pDate", in which case all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose certificate validity criterion
+ * (if any) is to be stored. Must be non-NULL.
+ * "pDate"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetCertificateValid(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Date **pDate,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetCertificateValid
+ * DESCRIPTION:
+ *
+ * Sets the certificate validity criterion of the ComCertSelParams object
+ * pointed to by "params" using a Date pointed to by "date". In order to
+ * match against this criterion, a certificate's validity period must include
+ * the criterion's Date.
+ *
+ * If "date" is NULL, all certificates are considered to match this criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose certificate validity criterion
+ * is to be set. Must be non-NULL.
+ * "date"
+ * Address of Date used to set the criterion
+ * (or NULL to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetCertificateValid(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Date *date,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSerialNumber
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the BigInt (if any) representing the serial number
+ * criterion that is set in the ComCertSelParams object pointed to by
+ * "params" and stores it at "pSerialNumber". In order to match against this
+ * criterion, a certificate must have a serial number equal to the
+ * criterion's serial number.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pSerialNumber", in which case all certificates are considered to match
+ * this criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose serial number criterion
+ * (if any) is to be stored. Must be non-NULL.
+ * "pSerialNumber"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSerialNumber(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_BigInt **pSerialNumber,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSerialNumber
+ * DESCRIPTION:
+ *
+ * Sets the serial number criterion of the ComCertSelParams object pointed to
+ * by "params" using a BigInt pointed to by "serialNumber". In order to match
+ * against this criterion, a certificate must have a serial number equal to
+ * the criterion's serial number.
+ *
+ * If "serialNumber" is NULL, all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose serial number criterion is to
+ * be set. Must be non-NULL.
+ * "serialNumber"
+ * Address of BigInt used to set the criterion
+ * (or NULL to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSerialNumber(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_BigInt *serialNumber,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetVersion
+ * DESCRIPTION:
+ *
+ * Retrieves a PKIX_UInt32 (if any) representing the version criterion that is
+ * set in the ComCertSelParams object pointed to by "params" and stores it at
+ * "pVersion". In order to match against this criterion, a certificate's
+ * version must be equal to the criterion's version.
+ *
+ * The version number will either be 0, 1, or 2 (corresponding to
+ * v1, v2, or v3, respectively).
+ *
+ * If "params" does not have this criterion set, this function stores
+ * 0xFFFFFFFF at "pVersion", in which case all certificates are considered
+ * to match this criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose version criterion (if any) is
+ * to be stored. Must be non-NULL.
+ * "pVersion"
+ * Address where PKIX_Int32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetVersion(
+ PKIX_ComCertSelParams *params,
+ PKIX_UInt32 *pVersion,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetVersion
+ * DESCRIPTION:
+ *
+ * Sets the version criterion of the ComCertSelParams object pointed to by
+ * "params" using the integer value of "version". In order to match against
+ * this criterion, a certificate's version must be equal to the criterion's
+ * version. If the criterion's version is -1, no version check is done and
+ * all certificates are considered to match this criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose version criterion is to be
+ * set. Must be non-NULL.
+ * "version"
+ * Value of PKIX_Int32 used to set the criterion
+ * (or -1 to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetVersion(
+ PKIX_ComCertSelParams *params,
+ PKIX_Int32 version,
+ void *plContext);
+
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetKeyUsage
+ * DESCRIPTION:
+ *
+ * Retrieves a PKIX_UInt32 (if any) representing the key usage criterion that
+ * is set in the ComCertSelParams object pointed to by "params" and stores it
+ * at "pKeyUsage". In order to match against this criterion, a certificate
+ * must allow the criterion's key usage values. Note that a certificate that
+ * has no KeyUsage extension implicity allows all key usages. Note also that
+ * this functions supports a maximum of 32 key usage bits.
+ *
+ * If "params" does not have this criterion set, this function stores zero at
+ * "pKeyUsage", in which case all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose key usage criterion (if any)
+ * is to be stored. Must be non-NULL.
+ * "pKeyUsage"
+ * Address where PKIX_UInt32 will be stored. Must not be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_UInt32 *pKeyUsage,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetKeyUsage
+ * DESCRIPTION:
+ *
+ * Sets the key usage criterion of the ComCertSelParams object pointed to by
+ * "params" using the integer value of "keyUsage". In order to match against
+ * this criterion, a certificate must allow the criterion's key usage values.
+ * Note that a certificate that has no KeyUsage extension implicity allows
+ * all key usages. Note also that this functions supports a maximum of 32 key
+ * usage bits.
+ *
+ * If the criterion's key usage value is zero, no key usage check is done and
+ * all certificates are considered to match this criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose key usage criterion is to be
+ * set. Must be non-NULL.
+ * "keyUsage"
+ * Value of PKIX_Int32 used to set the criterion
+ * (or zero to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_UInt32 keyUsage,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetExtendedKeyUsage
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of OIDs (if any) representing the extended
+ * key usage criterion that is set in the ComCertSelParams object pointed to
+ * by "params" and stores it at "pExtKeyUsage". In order to match against this
+ * criterion, a certificate's ExtendedKeyUsage extension must allow the
+ * criterion's extended key usages. Note that a certificate that has no
+ * ExtendedKeyUsage extension implicity allows all key purposes.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pExtKeyUsage", in which case all certificates are considered to match
+ * this criterion.
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose extended key usage criterion
+ * (if any) is to be stored. Must be non-NULL.
+ * "pExtKeyUsage"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetExtendedKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_List **pExtKeyUsage, /* list of PKIX_PL_OID */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetExtendedKeyUsage
+ * DESCRIPTION:
+ *
+ * Sets the extended key usage criterion of the ComCertSelParams object
+ * pointed to by "params" using a List of OIDs pointed to by "extKeyUsage".
+ * In order to match against this criterion, a certificate's ExtendedKeyUsage
+ * extension must allow the criterion's extended key usages. Note that a
+ * certificate that has no ExtendedKeyUsage extension implicitly allows all
+ * key purposes.
+ *
+ * If "extKeyUsage" is NULL, all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose extended key usage criterion
+ * is to be set. Must be non-NULL.
+ * "extKeyUsage"
+ * Address of List of OIDs used to set the criterion
+ * (or NULL to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetExtendedKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_List *extKeyUsage, /* list of PKIX_PL_OID */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetPolicy
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of OIDs (if any) representing the policy
+ * criterion that is set in the ComCertSelParams object pointed to by
+ * "params" and stores it at "pPolicy". In order to match against this
+ * criterion, a certificate's CertificatePolicies extension must include at
+ * least one of the criterion's policies. If "params" has this criterion set,
+ * but the List of OIDs is empty, then a certificate's CertificatePolicies
+ * extension must include at least some policy.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pPolicy", in which case all certificates are considered to match this
+ * criterion.
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose policy criterion (if any) is
+ * to be stored. Must be non-NULL.
+ * "pPolicy"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetPolicy(
+ PKIX_ComCertSelParams *params,
+ PKIX_List **pPolicy, /* list of PKIX_PL_OID */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetPolicy
+ * DESCRIPTION:
+ *
+ * Sets the policy criterion of the ComCertSelParams object pointed to by
+ * "params" using a List of OIDs pointed to by "policy". In order to match
+ * against this criterion, a certificate's CertificatePolicies extension must
+ * include at least one of the criterion's policies. If "params" has this
+ * criterion set, but the List of OIDs is empty, then a certificate's
+ * CertificatePolicies extension must include at least some policy.
+ *
+ * If "policy" is NULL, all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose policy criterion is to be set.
+ * Must be non-NULL.
+ * "policy"
+ * Address of List of OIDs used to set the criterion
+ * (or NULL to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetPolicy(
+ PKIX_ComCertSelParams *params,
+ PKIX_List *policy, /* list of PKIX_PL_OID */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetIssuer
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the X500Name (if any) representing the issuer
+ * criterion that is set in the ComCertSelParams object pointed to by
+ * "params" and stores it at "pIssuer". In order to match against this
+ * criterion, a certificate's IssuerName must match the criterion's issuer
+ * name.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pIssuer", in which case all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose issuer criterion (if any) is
+ * to be stored. Must be non-NULL.
+ * "pIssuer"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetIssuer(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_X500Name **pIssuer,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetIssuer
+ * DESCRIPTION:
+ *
+ * Sets the issuer criterion of the ComCertSelParams object pointed to by
+ * "params" using an X500Name pointed to by "issuer". In order to match
+ * against this criterion, a certificate's IssuerName must match the
+ * criterion's issuer name.
+ *
+ * If "issuer" is NULL, all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose issuer criterion is to be set.
+ * Must be non-NULL.
+ * "issuer"
+ * Address of X500Name used to set the criterion
+ * (or NULL to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetIssuer(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_X500Name *issuer,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubject
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the X500Name (if any) representing the subject
+ * criterion that is set in the ComCertSelParams object pointed to by
+ * "params" and stores it at "pSubject". In order to match against this
+ * criterion, a certificate's SubjectName must match the criterion's subject
+ * name.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pSubject", in which case all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose subject criterion (if any) is
+ * to be stored. Must be non-NULL.
+ * "pSubject"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubject(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_X500Name **pSubject,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubject
+ * DESCRIPTION:
+ *
+ * Sets the subject criterion of the ComCertSelParams object pointed to by
+ * "params" using an X500Name pointed to by "subject". In order to match
+ * against this criterion, a certificate's SubjectName must match the
+ * criterion's subject name.
+ *
+ * If "subject" is NULL, all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose subject criterion is to be
+ * set. Must be non-NULL.
+ * "subject"
+ * Address of X500Name used to set the criterion
+ * (or NULL to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubject(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_X500Name *subject,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubjectAsByteArray
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the ByteArray (if any) representing the subject
+ * criterion that is set in the ComCertSelParams object pointed to by
+ * "params" and stores it at "pSubject". In order to match against this
+ * criterion, a certificate's SubjectName must match the criterion's subject
+ * name.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pSubject", in which case all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose subject criterion (if any) is
+ * to be stored. Must be non-NULL.
+ * "pSubject"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubjectAsByteArray(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray **pSubject,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubjectAsByteArray
+ * DESCRIPTION:
+ *
+ * Sets the subject criterion of the ComCertSelParams object pointed to by
+ * "params" using a ByteArray pointed to by "subject". In order to match
+ * against this criterion, a certificate's SubjectName must match the
+ * criterion's subject name.
+ *
+ * If "subject" is NULL, all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose subject criterion is to be
+ * set. Must be non-NULL.
+ * "subject"
+ * Address of ByteArray used to set the criterion
+ * (or NULL to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubjectAsByteArray(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray *subject,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetNameConstraints
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the X500Name (if any) representing the name
+ * constraints criterion that is set in the ComCertSelParams object pointed
+ * to by "params" and stores it at "pConstraints". In order to match against
+ * this criterion, a certificate's subject and subject alternative names must
+ * be allowed by the criterion's name constraints.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pConstraints", in which case all certificates are considered to match
+ * this criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose name constraints criterion
+ * (if any) is to be stored. Must be non-NULL.
+ * "pConstraints"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetNameConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_CertNameConstraints **pConstraints,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetNameConstraints
+ * DESCRIPTION:
+ *
+ * Sets the name constraints criterion of the ComCertSelParams object pointed
+ * to by "params" using the CertNameConstraints pointed to by "constraints".
+ * In order to match against this criterion, a certificate's subject and
+ * subject alternative names must be allowed by the criterion's name
+ * constraints.
+ *
+ * If "constraints" is NULL, all certificates are considered to match this
+ * criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose name constraints criterion is
+ * to be set. Must be non-NULL.
+ * "constraints"
+ * Address of CertNameConstraints used to set the criterion
+ * (or NULL to disable the criterion).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetNameConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_CertNameConstraints *constraints,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetMatchAllSubjAltNames
+ * DESCRIPTION:
+ *
+ * Checks whether the ComCertSelParams object pointed to by "params" indicate
+ * that all subject alternative names are to be matched and stores the Boolean
+ * result at "pMatch". This Boolean value determines the behavior of the
+ * subject alternative names criterion.
+ *
+ * In order to match against the subject alternative names criterion, if the
+ * Boolean value at "pMatch" is PKIX_TRUE, a certificate must contain all of
+ * the criterion's subject alternative names. If the Boolean value at
+ * "pMatch" is PKIX_FALSE, a certificate must contain at least one of the
+ * criterion's subject alternative names. The default behavior is as if the
+ * Boolean value at "pMatch" is PKIX_TRUE.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object used to determine whether all
+ * subject alternative names must be matched. Must be non-NULL.
+ * "pMatch"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetMatchAllSubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_Boolean *pMatch,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetMatchAllSubjAltNames
+ * DESCRIPTION:
+ *
+ * Sets the match flag of the ComCertSelParams object pointed to by "params"
+ * using the Boolean value of "match". This Boolean value determines the
+ * behavior of the subject alternative names criterion.
+ *
+ * In order to match against the subject alternative names criterion, if the
+ * "match" is PKIX_TRUE, a certificate must contain all of the criterion's
+ * subject alternative names. If the "match" is PKIX_FALSE, a certificate
+ * must contain at least one of the criterion's subject alternative names.
+ * The default behavior is as if "match" is PKIX_TRUE.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose match flag is to be set.
+ * Must be non-NULL.
+ * "match"
+ * Boolean value used to set the match flag.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetMatchAllSubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_Boolean match,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetLeafCertFlag
+ * DESCRIPTION:
+ *
+ * Return "leafCert" flag of the ComCertSelParams structure. If set to true,
+ * the flag indicates that a selector should filter out all cert that are not
+ * qualified to be a leaf cert according to the specified key/ekey usages.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object used to determine whether all
+ * subject alternative names must be matched. Must be non-NULL.
+ * "pLeafFlag"
+ * Address of returned value.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error*
+PKIX_ComCertSelParams_GetLeafCertFlag(
+ PKIX_ComCertSelParams *params,
+ PKIX_Boolean *pLeafFlag,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetLeafCertFlag
+ * DESCRIPTION:
+ *
+ * Sets a flag that if its value is true, indicates that the selector
+ * should only pick certs that qualifies to be leaf for this cert path
+ * validation.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams object whose match flag is to be set.
+ * Must be non-NULL.
+ * "leafFlag"
+ * Boolean value used to set the leaf flag.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetLeafCertFlag(
+ PKIX_ComCertSelParams *params,
+ PKIX_Boolean leafFlag,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_CERTSEL_H */
diff --git a/security/nss/lib/libpkix/include/pkix_certstore.h b/security/nss/lib/libpkix/include/pkix_certstore.h
new file mode 100644
index 0000000000..fb705644eb
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkix_certstore.h
@@ -0,0 +1,714 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 file defines functions associated with the PKIX_CertStore type.
+ *
+ */
+
+#ifndef _PKIX_CERTSTORE_H
+#define _PKIX_CERTSTORE_H
+
+#include "pkixt.h"
+#include "certt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General
+ *
+ * Please refer to the libpkix Programmer's Guide for detailed information
+ * about how to use the libpkix library. Certain key warnings and notices from
+ * that document are repeated here for emphasis.
+ *
+ * All identifiers in this file (and all public identifiers defined in
+ * libpkix) begin with "PKIX_". Private identifiers only intended for use
+ * within the library begin with "pkix_".
+ *
+ * A function returns NULL upon success, and a PKIX_Error pointer upon failure.
+ *
+ * Unless otherwise noted, for all accessor (gettor) functions that return a
+ * PKIX_PL_Object pointer, callers should assume that this pointer refers to a
+ * shared object. Therefore, the caller should treat this shared object as
+ * read-only and should not modify this shared object. When done using the
+ * shared object, the caller should release the reference to the object by
+ * using the PKIX_PL_Object_DecRef function.
+ *
+ * While a function is executing, if its arguments (or anything referred to by
+ * its arguments) are modified, free'd, or destroyed, the function's behavior
+ * is undefined.
+ *
+ */
+
+/* PKIX_CertStore
+ *
+ * A PKIX_CertStore provides a standard way for the caller to retrieve
+ * certificates and CRLs from a particular repository (or "store") of
+ * certificates and CRLs, including LDAP directories, flat files, local
+ * databases, etc. The CertCallback allows custom certificate retrieval logic
+ * to be used while the CRLCallback allows custom CRL retrieval logic to be
+ * used. Additionally, a CertStore can be initialized with a certStoreContext,
+ * which is where the caller can specify configuration data such as the host
+ * name of an LDAP server. Note that this certStoreContext must be an
+ * Object (although any object type), allowing it to be reference-counted and
+ * allowing it to provide the standard Object functions (Equals, Hashcode,
+ * ToString, Compare, Duplicate). Please note that each certStoreContext must
+ * provide Equals and Hashcode functions in order for the caching (on Cert and
+ * CertChain) to work correctly. When providing those two functions, it is not
+ * required that all the components of the object be hashed or checked for
+ * equality, but merely that the functions distinguish between unique
+ * instances of the certStoreContext.
+ *
+ * Once the caller has created the CertStore object, the caller then specifies
+ * these CertStore objects in a ProcessingParams object and passes that object
+ * to PKIX_ValidateChain or PKIX_BuildChain, which uses the objects to call the
+ * user's callback functions as needed during the validation or building
+ * process.
+ *
+ * The order of CertStores stored (as a list) at ProcessingParams determines
+ * the order in which certificates are retrieved. Trusted CertStores should
+ * precede non-trusted ones on the list of CertStores so their certificates
+ * are evaluated ahead of other certificates selected on the basis of the same
+ * selector criteria.
+ *
+ * The CheckTrustCallback function is used when the CertStore object
+ * supports trust status, which means a Cert's trust status can be altered
+ * dynamically. When a CertStore object is created, if the
+ * CheckTrustCallback is initialized to be non-NULL, this CertStore is
+ * defaulted as supporting trust. Then whenever a Cert needs to (re)check its
+ * trust status, this callback can be invoked. When a Cert is retrieved by
+ * a CertStore supports trust, at its GetCertCallback, the CertStore
+ * information should be updated in Cert's data structure so the link between
+ * the Cert and CertStore exists.
+ *
+ */
+
+/*
+ * FUNCTION: PKIX_CertStore_CertCallback
+ * DESCRIPTION:
+ *
+ * This callback function retrieves from the CertStore pointed to by "store"
+ * all the certificates that match the CertSelector pointed to by "selector".
+ * It places these certificates in a List and stores a pointer to the List at
+ * "pCerts". If no certificates are found which match the CertSelector's
+ * criteria, this function stores an empty List at "pCerts". In either case, if
+ * the operation is completed, NULL is stored at "pNBIOContext".
+ *
+ * A CertStore which uses non-blocking I/O may store platform-dependent
+ * information at "pNBIOContext" and NULL at "pCerts" to indicate that I/O is
+ * pending. A subsequent call to PKIX_CertStore_CertContinue is required to
+ * finish the operation and to obtain the List of Certs.
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore from which Certs are to be retrieved.
+ * Must be non-NULL.
+ * "selector"
+ * Address of CertSelector whose criteria must be satisfied.
+ * Must be non-NULL.
+ * "verifyNode"
+ * Parent log node for tracking of filtered out certs.
+ * "pNBIOContext"
+ * Address at which platform-dependent information is stored if the
+ * operation is suspended for non-blocking I/O. Must be non-NULL.
+ * "pCerts"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_CertStore_CertCallback)(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ PKIX_VerifyNode *verifyNode,
+ void **pNBIOContext,
+ PKIX_List **pCerts, /* list of PKIX_PL_Cert */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_CertContinue
+ * DESCRIPTION:
+ *
+ * This function continues the non-blocking operation initiated by an earlier
+ * call to the CertCallback function, for the CertStore pointed to by "store".
+ * If an earlier call did not terminate with the WOULDBLOCK indication (non-NULL
+ * value returned in "pNBIOContext") calling this function will return a fatal
+ * error. If the operation is completed the certificates found are placed in a
+ * List, a pointer to which is stored at "pCerts". If no certificates are found
+ * which match the CertSelector's criteria, this function stores an empty List
+ * at "pCerts". In either case, if the operation is completed, NULL is stored
+ * at "pNBIOContext".
+ *
+ * If non-blocking I/O is still pending this function stores platform-dependent
+ * information at "pNBIOContext" and NULL at "pCerts". A subsequent call to
+ * PKIX_CertStore_CertContinue is required to finish the operation and to
+ * obtain the List of Certs.
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore from which Certs are to be retrieved.
+ * Must be non-NULL.
+ * "selector"
+ * Address of CertSelector whose criteria must be satisfied.
+ * Must be non-NULL.
+ * "verifyNode"
+ * Parent log node for tracking of filtered out certs.
+ * "pNBIOContext"
+ * Address at which platform-dependent information is stored if the
+ * operation is suspended for non-blocking I/O. Must be non-NULL.
+ * "pCerts"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertStore_CertContinue(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ PKIX_VerifyNode *verifyNode,
+ void **pNBIOContext,
+ PKIX_List **pCerts, /* list of PKIX_PL_Cert */
+ void *plContext);
+
+typedef PKIX_Error *
+(*PKIX_CertStore_CertContinueFunction)(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ PKIX_VerifyNode *verifyNode,
+ void **pNBIOContext,
+ PKIX_List **pCerts, /* list of PKIX_PL_Cert */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_CRLCallback
+ * DESCRIPTION:
+ *
+ * This callback function retrieves from the CertStore pointed to by "store"
+ * all the CRLs that match the CRLSelector pointed to by "selector". It
+ * places these CRLs in a List and stores a pointer to the List at "pCRLs".
+ * If no CRLs are found which match the CRLSelector's criteria, this function
+ * stores an empty List at "pCRLs". In either case, if the operation is
+ * completed, NULL is stored at "pNBIOContext".
+ *
+ * A CertStore which uses non-blocking I/O may store platform-dependent
+ * information at "pNBIOContext" and NULL at "pCrls" to indicate that I/O is
+ * pending. A subsequent call to PKIX_CertStore_CRLContinue is required to
+ * finish the operation and to obtain the List of Crls.
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore from which CRLs are to be retrieved.
+ * Must be non-NULL.
+ * "selector"
+ * Address of CRLSelector whose criteria must be satisfied.
+ * Must be non-NULL.
+ * "pCrls"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_CertStore_CRLCallback)(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrls, /* list of PKIX_PL_CRL */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_ImportCrlCallback
+ * DESCRIPTION:
+ *
+ * The function imports crl list into a cert store. Stores that
+ * have local cache may only have that function defined.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore from which CRLs are to be retrieved.
+ * Must be non-NULL.
+ * "issuerName"
+ * Name of the issuer that will be used to track bad der crls.
+ * "crlList"
+ * Address on the importing crl list.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_CertStore_ImportCrlCallback)(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *issuerName,
+ PKIX_List *crlList,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_CheckRevokationByCrlCallback
+ * DESCRIPTION:
+ *
+ * The function checks revocation status of a cert with specified
+ * issuer, date. It returns revocation status of a cert and
+ * a reason code(if any) if a cert was revoked.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore from which CRLs are to be retrieved.
+ * Must be non-NULL.
+ * "cert"
+ * Certificate which revocation status will be checked.
+ * "issuer"
+ * Issuer certificate of the "crl".
+ * "date"
+ * Date of the revocation check.
+ * "crlDownloadDone"
+ * Indicates, that all needed crl downloads are done by the time of
+ * the revocation check.
+ * "reasonCode"
+ * If cert is revoked, returned reason code for which a cert was revoked.
+ * "revStatus"
+ * Returned revocation status of the cert. See PKIX_RevocationStatus
+ * for more details
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_CertStore_CheckRevokationByCrlCallback)(
+ PKIX_CertStore *store,
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ PKIX_Boolean crlDownloadDone,
+ CERTCRLEntryReasonCode *reasonCode,
+ PKIX_RevocationStatus *revStatus,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_CrlContinue
+ * DESCRIPTION:
+ *
+ * This function continues the non-blocking operation initiated by an earlier
+ * call to the CRLCallback function, for the CertStore pointed to by "store".
+ * If an earlier call did not terminate with the WOULDBLOCK indication (non-NULL
+ * value returned in "pNBIOContext") calling this function will return a fatal
+ * error. If the operation is completed the crls found are placed in a List, a
+ * pointer to which is stored at "pCrls". If no crls are found which match the
+ * CRLSelector's criteria, this function stores an empty List at "pCrls". In
+ * either case, if the operation is completed, NULL is stored at "pNBIOContext".
+ *
+ * If non-blocking I/O is still pending this function stores platform-dependent
+ * information at "pNBIOContext" and NULL at "pCrls". A subsequent call to
+ * PKIX_CertStore_CrlContinue is required to finish the operation and to
+ * obtain the List of Crls.
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore from which Crls are to be retrieved.
+ * Must be non-NULL.
+ * "selector"
+ * Address of CRLSelector whose criteria must be satisfied.
+ * Must be non-NULL.
+ * "pNBIOContext"
+ * Address at which platform-dependent information is stored if the
+ * operation is suspended for non-blocking I/O. Must be non-NULL.
+ * "pCrls"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertStore_CrlContinue(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrls, /* list of PKIX_PL_CRL */
+ void *plContext);
+
+typedef PKIX_Error *
+(*PKIX_CertStore_CrlContinueFunction)(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrls, /* list of PKIX_PL_CRL */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_CheckTrustCallback
+ * DESCRIPTION:
+ *
+ * This callback function rechecks "cert's" trust status from the CertStore
+ * pointed to by "store".
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore from which Certs are to be checked.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert whose trust status needs to be rechecked.
+ * Must be non-NULL.
+ * "pTrusted"
+ * Address of PKIX_Boolean where the trust status is returned.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_CertStore_CheckTrustCallback)(
+ PKIX_CertStore *store,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pTrusted,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_Create
+ * DESCRIPTION:
+ *
+ * Creates a new CertStore and stores it at "pStore". The new CertStore uses
+ * the CertCallback pointed to by "certCallback" and the CRLCallback pointed
+ * to by "crlCallback" as its callback functions and uses the Object pointed
+ * to by "certStoreContext" as its context . Note that this certStoreContext
+ * must be an Object (although any object type), allowing it to be
+ * reference-counted and allowing it to provide the standard Object functions
+ * (Equals, Hashcode, ToString, Compare, Duplicate). Once created, a
+ * CertStore object is immutable, although the underlying repository can
+ * change. For example, a CertStore will often be a front-end for a database
+ * or directory. The contents of that directory can change after the
+ * CertStore object is created, but the CertStore object remains immutable.
+ *
+ * PARAMETERS:
+ * "certCallback"
+ * The CertCallback function to be used. Must be non-NULL.
+ * "crlCallback"
+ * The CRLCallback function to be used. Must be non-NULL.
+ * "certContinue"
+ * The function to be used to resume a certCallback that returned with a
+ * WOULDBLOCK condition. Must be non-NULL if certStore supports non-blocking
+ * I/O.
+ * "crlContinue"
+ * The function to be used to resume a crlCallback that returned with a
+ * WOULDBLOCK condition. Must be non-NULL if certStore supports non-blocking
+ * I/O.
+ * "trustCallback"
+ * Address of PKIX_CertStore_CheckTrustCallback which is called to
+ * verify the trust status of Certs in this CertStore.
+ * "certStoreContext"
+ * Address of Object representing the CertStore's context (if any).
+ * "cachedFlag"
+ * If TRUE indicates data retrieved from CertStore should be cached.
+ * "localFlag"
+ * Boolean value indicating whether this CertStore is local.
+ * "pStore"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertStore_Create(
+ PKIX_CertStore_CertCallback certCallback,
+ PKIX_CertStore_CRLCallback crlCallback,
+ PKIX_CertStore_CertContinueFunction certContinue,
+ PKIX_CertStore_CrlContinueFunction crlContinue,
+ PKIX_CertStore_CheckTrustCallback trustCallback,
+ PKIX_CertStore_ImportCrlCallback importCrlCallback,
+ PKIX_CertStore_CheckRevokationByCrlCallback checkRevByCrlCallback,
+ PKIX_PL_Object *certStoreContext,
+ PKIX_Boolean cachedFlag,
+ PKIX_Boolean localFlag,
+ PKIX_CertStore **pStore,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCertCallback
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to "store's" Cert callback function and put it in
+ * "pCallback".
+ *
+ * PARAMETERS:
+ * "store"
+ * The CertStore whose Cert callback is desired. Must be non-NULL.
+ * "pCallback"
+ * Address where Cert callback function pointer will be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertStore_GetCertCallback(
+ PKIX_CertStore *store,
+ PKIX_CertStore_CertCallback *pCallback,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCRLCallback
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to "store's" CRL callback function and put it in
+ * "pCallback".
+ *
+ * PARAMETERS:
+ * "store"
+ * The CertStore whose CRL callback is desired. Must be non-NULL.
+ * "pCallback"
+ * Address where CRL callback function pointer will be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertStore_GetCRLCallback(
+ PKIX_CertStore *store,
+ PKIX_CertStore_CRLCallback *pCallback,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_GetImportCrlCallback
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to "store's" Import CRL callback function and put it in
+ * "pCallback".
+ *
+ * PARAMETERS:
+ * "store"
+ * The CertStore whose CRL callback is desired. Must be non-NULL.
+ * "pCallback"
+ * Address where CRL callback function pointer will be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertStore_GetImportCrlCallback(
+ PKIX_CertStore *store,
+ PKIX_CertStore_ImportCrlCallback *pCallback,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCheckRevByCrl
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to "store's" CRL revocation checker callback function
+ * and put it in "pCallback".
+ *
+ * PARAMETERS:
+ * "store"
+ * The CertStore whose CRL callback is desired. Must be non-NULL.
+ * "pCallback"
+ * Address where CRL callback function pointer will be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertStore_GetCrlCheckerFn(
+ PKIX_CertStore *store,
+ PKIX_CertStore_CheckRevokationByCrlCallback *pCallback,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_GetTrustCallback
+ * DESCRIPTION:
+ *
+ * Retrieves the function pointer to the CheckTrust callback function of the
+ * CertStore pointed to by "store" and stores it at "pCallback".
+ *
+ * PARAMETERS:
+ * "store"
+ * The CertStore whose CheckTrust callback is desired. Must be non-NULL.
+ * "pCallback"
+ * Address where CheckTrust callback function pointer will be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertStore_GetTrustCallback(
+ PKIX_CertStore *store,
+ PKIX_CertStore_CheckTrustCallback *pCallback,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCertStoreContext
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the Object representing the context (if any)
+ * of the CertStore pointed to by "store" and stores it at
+ * "pCertStoreContext".
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore whose context is to be stored. Must be non-NULL.
+ * "pCertStoreContext"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertStore_GetCertStoreContext(
+ PKIX_CertStore *store,
+ PKIX_PL_Object **pCertStoreContext,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCertStoreCacheFlag
+ * DESCRIPTION:
+ *
+ * Retrieves the Boolean cache flag of the CertStore pointed to by "store" and
+ * stores it at "pCachedFlag".
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore whose cache flag is to be stored. Must be non-NULL.
+ * "pCacheFlag"
+ * Address where the result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertStore_GetCertStoreCacheFlag(
+ PKIX_CertStore *store,
+ PKIX_Boolean *pCacheFlag,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertStore_GetLocalFlag
+ * DESCRIPTION:
+ *
+ * Retrieves the Boolean localFlag for the CertStore pointed to by "store" and
+ * stores it at "pLocalFlag". The localFlag is TRUE if the CertStore can
+ * fulfill a request without performing network I/O.
+ *
+ * PARAMETERS:
+ * "store"
+ * The CertStore whose Local flag is desired. Must be non-NULL.
+ * "pCallback"
+ * Address where the Boolean LocalFlag will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertStore_GetLocalFlag(
+ PKIX_CertStore *store,
+ PKIX_Boolean *pLocalFlag,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_CERTSTORE_H */
diff --git a/security/nss/lib/libpkix/include/pkix_checker.h b/security/nss/lib/libpkix/include/pkix_checker.h
new file mode 100644
index 0000000000..97e29a8403
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkix_checker.h
@@ -0,0 +1,394 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 file defines functions associated with the PKIX_CertChainChecker type.
+ *
+ */
+
+#ifndef _PKIX_CHECKER_H
+#define _PKIX_CHECKER_H
+
+#include "pkixt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General
+ *
+ * Please refer to the libpkix Programmer's Guide for detailed information
+ * about how to use the libpkix library. Certain key warnings and notices from
+ * that document are repeated here for emphasis.
+ *
+ * All identifiers in this file (and all public identifiers defined in
+ * libpkix) begin with "PKIX_". Private identifiers only intended for use
+ * within the library begin with "pkix_".
+ *
+ * A function returns NULL upon success, and a PKIX_Error pointer upon failure.
+ *
+ * Unless otherwise noted, for all accessor (gettor) functions that return a
+ * PKIX_PL_Object pointer, callers should assume that this pointer refers to a
+ * shared object. Therefore, the caller should treat this shared object as
+ * read-only and should not modify this shared object. When done using the
+ * shared object, the caller should release the reference to the object by
+ * using the PKIX_PL_Object_DecRef function.
+ *
+ * While a function is executing, if its arguments (or anything referred to by
+ * its arguments) are modified, free'd, or destroyed, the function's behavior
+ * is undefined.
+ *
+ */
+
+/* PKIX_CertChainChecker
+ *
+ * PKIX_CertChainCheckers provide a standard way for the caller to insert their
+ * own custom checks to validate certificates. This may be useful in many
+ * scenarios, including when the caller wishes to validate private certificate
+ * extensions. The CheckCallback allows custom certificate processing to take
+ * place. Additionally, a CertChainChecker can optionally maintain state
+ * between successive calls to the CheckCallback. This certChainCheckerState
+ * must be an Object (although any object type), allowing it to be
+ * reference-counted and allowing it to provide the standard Object functions
+ * (Equals, Hashcode, ToString, Compare, Duplicate). If the caller wishes
+ * their CertChainChecker to be used during chain building, their
+ * certChainCheckerState object must implement an appropriate Duplicate
+ * function. The builder uses this Duplicate function when backtracking.
+ *
+ * Once the caller has created a CertChainChecker object, the caller then
+ * specifies a CertChainChecker object in a ProcessingParams object
+ * and passes the ProcessingParams object to PKIX_ValidateChain or
+ * PKIX_BuildChain, which uses the objects to call the user's callback
+ * functions as needed during the validation or building process.
+ *
+ * A CertChainChecker may be presented certificates in the "reverse" direction
+ * (from trust anchor to target) or in the "forward" direction (from target to
+ * trust anchor). All CertChainCheckers must support "reverse checking", while
+ * support for "forward checking" is optional, but recommended. If "forward
+ * checking" is not supported, building chains may be much less efficient. The
+ * PKIX_CertChainChecker_IsForwardCheckingSupported function is used to
+ * determine whether forward checking is supported, and the
+ * PKIX_CertChainChecker_IsForwardDirectionExpected function is used to
+ * determine whether the CertChainChecker has been initialized to expect the
+ * certificates to be presented in the "forward" direction.
+ */
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_CheckCallback
+ * DESCRIPTION:
+ *
+ * This callback function checks whether the specified Cert pointed to by
+ * "cert" is valid using "checker's" internal certChainCheckerState (if any)
+ * and removes the critical extensions that it processes (if any) from the
+ * List of OIDs (possibly empty) pointed to by "unresolvedCriticalExtensions".
+ * If the checker finds that the certificate is not valid, an Error pointer is
+ * returned.
+ *
+ * If the checker uses non-blocking I/O, the address of a platform-dependent
+ * non-blocking I/O context ("nbioContext") will be stored at "pNBIOContext",
+ * which the caller may use, in a platform-dependent way, to wait, poll, or
+ * otherwise determine when to try again. If the checker does not use
+ * non-blocking I/O, NULL will always be stored at "pNBIOContext". If a non-NULL
+ * value was stored, on a subsequent call the checker will attempt to complete
+ * the pending I/O and, if successful, NULL will be stored at "pNBIOContext".
+ *
+ * PARAMETERS:
+ * "checker"
+ * Address of CertChainChecker whose certChainCheckerState and
+ * CheckCallback logic is to be used. Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be validated using "checker".
+ * Must be non-NULL.
+ * "unresolvedCriticalExtensions"
+ * Address of List of OIDs that represents the critical certificate
+ * extensions that have yet to be resolved. This parameter may be
+ * modified during the function call. Must be non-NULL.
+ * "pNBIOContext"
+ * Address at which is stored a platform-dependent structure indicating
+ * whether checking was suspended for non-blocking I/O. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_CertChainChecker_CheckCallback)(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions, /* list of PKIX_PL_OID */
+ void **pNBIOContext,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_Create
+ * DESCRIPTION:
+ *
+ * Creates a new CertChainChecker and stores it at "pChecker". The new
+ * CertChainChecker uses the CheckCallback pointed to by "callback" as its
+ * callback function. It uses the Object pointed to by "initialState" (if
+ * any) as its initial state. As noted above, the initial state Object must
+ * provide a custom implementation of PKIX_PL_Object_Duplicate if the
+ * CertChainChecker is to be used during certificate chain building.
+ *
+ * A CertChainChecker may be presented certificates in the "reverse"
+ * direction (from trust anchor to target) or in the "forward" direction
+ * (from target to trust anchor). All CertChainCheckers must support
+ * "reverse checking", while support for "forward checking" is optional. The
+ * CertChainChecker is initialized with two Boolean flags that deal with this
+ * distinction: "forwardCheckingSupported" and "forwardDirectionExpected".
+ * If the "forwardCheckingSupported" Boolean flag is TRUE, it indicates that
+ * this CertChainChecker is capable of checking certificates in the "forward"
+ * direction (as well as the "reverse" direction, which all CertChainCheckers
+ * MUST support). The "forwardDirectionExpected" Boolean flag indicates in
+ * which direction the CertChainChecker should expect the certificates to be
+ * presented. This is particularly useful for CertChainCheckers that are
+ * capable of checking in either the "forward" direction or the "reverse"
+ * direction, but have different processing steps depending on the direction.
+ *
+ * The CertChainChecker also uses the List of OIDs pointed to by "extensions"
+ * as the supported certificate extensions. All certificate extensions that
+ * the CertChainChecker might possibly recognize and be able to process
+ * should be included in the List of supported extensions. If "checker" does
+ * not recognize or process any certificate extensions, "extensions" should
+ * be set to NULL.
+ *
+ * PARAMETERS:
+ * "callback"
+ * The CheckCallback function to be used. Must be non-NULL.
+ * "forwardCheckingSupported"
+ * A Boolean value indicating whether or not this CertChainChecker is
+ * capable of checking certificates in the "forward" direction.
+ * "forwardDirectionExpected"
+ * A Boolean value indicating whether or not this CertChainChecker should
+ * be used to check in the "forward" direction.
+ * "extensions"
+ * Address of List of OIDs representing the supported extensions.
+ * "initialState"
+ * Address of Object representing the CertChainChecker's initial state
+ * (if any).
+ * "pChecker"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertChainChecker_Create(
+ PKIX_CertChainChecker_CheckCallback callback,
+ PKIX_Boolean forwardCheckingSupported,
+ PKIX_Boolean forwardDirectionExpected,
+ PKIX_List *extensions, /* list of PKIX_PL_OID */
+ PKIX_PL_Object *initialState,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_GetCheckCallback
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to "checker's" Check callback function and puts it in
+ * "pCallback".
+ *
+ * PARAMETERS:
+ * "checker"
+ * The CertChainChecker whose Check callback is desired. Must be non-NULL.
+ * "pCallback"
+ * Address where Check callback function pointer will be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertChainChecker_GetCheckCallback(
+ PKIX_CertChainChecker *checker,
+ PKIX_CertChainChecker_CheckCallback *pCallback,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_IsForwardCheckingSupported
+ * DESCRIPTION:
+ *
+ * Checks whether forward checking is supported by the CertChainChecker
+ * pointed to by "checker" and stores the Boolean result at
+ * "pForwardCheckingSupported".
+ *
+ * A CertChainChecker may be presented certificates in the "reverse"
+ * direction (from trust anchor to target) or in the "forward" direction
+ * (from target to trust anchor). All CertChainCheckers must support
+ * "reverse checking", while support for "forward checking" is optional. This
+ * function is used to determine whether forward checking is supported.
+ *
+ * PARAMETERS:
+ * "checker"
+ * The CertChainChecker whose ability to validate certificates in the
+ * "forward" direction is to be checked. Must be non-NULL.
+ * "pForwardCheckingSupported"
+ * Destination of the Boolean result. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertChainChecker_IsForwardCheckingSupported(
+ PKIX_CertChainChecker *checker,
+ PKIX_Boolean *pForwardCheckingSupported,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_IsForwardDirectionExpected
+ * DESCRIPTION:
+ *
+ * Checks whether the CertChainChecker pointed to by "checker" has been
+ * initialized to expect the certificates to be presented in the "forward"
+ * direction and stores the Boolean result at "pForwardDirectionExpected".
+ *
+ * A CertChainChecker may be presented certificates in the "reverse"
+ * direction (from trust anchor to target) or in the "forward" direction
+ * (from target to trust anchor). All CertChainCheckers must support
+ * "reverse checking", while support for "forward checking" is optional. This
+ * function is used to determine in which direction the CertChainChecker
+ * expects the certificates to be presented.
+ *
+ * PARAMETERS:
+ * "checker"
+ * The CertChainChecker that has been initialized to expect certificates
+ * in either the "forward" or "reverse" directions. Must be non-NULL.
+ * "pForwardDirectionExpected"
+ * Destination of the Boolean result. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertChainChecker_IsForwardDirectionExpected(
+ PKIX_CertChainChecker *checker,
+ PKIX_Boolean *pForwardDirectionExpected,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_GetSupportedExtensions
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a List of OIDs (each OID corresponding to a
+ * certificate extension supported by the CertChainChecker pointed to by
+ * "checker") and stores it at "pExtensions". All certificate extensions that
+ * the CertChainChecker might possibly recognize and be able to process
+ * should be included in the List of supported extensions. If "checker" does
+ * not recognize or process any certificate extensions, this function stores
+ * NULL at "pExtensions".
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "checker"
+ * Address of CertChainChecker whose supported extension OIDs are to be
+ * stored. Must be non-NULL.
+ * "pExtensions"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertChainChecker_GetSupportedExtensions(
+ PKIX_CertChainChecker *checker,
+ PKIX_List **pExtensions, /* list of PKIX_PL_OID */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_GetCertChainCheckerState
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a PKIX_PL_Object representing the internal state
+ * (if any) of the CertChainChecker pointed to by "checker" and stores it at
+ * "pCertChainCheckerState".
+ *
+ * PARAMETERS:
+ * "checker"
+ * Address of CertChainChecker whose state is to be stored.
+ * Must be non-NULL.
+ * "pCertChainCheckerState"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertChainChecker_GetCertChainCheckerState(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Object **pCertChainCheckerState,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_SetCertChainCheckerState
+ * DESCRIPTION:
+ *
+ * Sets the internal state of the CertChainChecker pointed to by "checker"
+ * using the Object pointed to by "certChainCheckerState". If "checker" needs
+ * a NULL internal state, "certChainCheckerState" should be set to NULL.
+ *
+ * PARAMETERS:
+ * "checker"
+ * Address of CertChainChecker whose state is to be set. Must be non-NULL.
+ * "certChainCheckerState"
+ * Address of Object representing internal state.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "checker"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CertChainChecker_SetCertChainCheckerState(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Object *certChainCheckerState,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_CHECKER_H */
diff --git a/security/nss/lib/libpkix/include/pkix_crlsel.h b/security/nss/lib/libpkix/include/pkix_crlsel.h
new file mode 100644
index 0000000000..491e72f43b
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkix_crlsel.h
@@ -0,0 +1,759 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 file defines functions associated with the PKIX_CRLSelector and the
+ * PKIX_ComCRLSelParams types.
+ *
+ */
+
+
+#ifndef _PKIX_CRLSEL_H
+#define _PKIX_CRLSEL_H
+
+#include "pkixt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General
+ *
+ * Please refer to the libpkix Programmer's Guide for detailed information
+ * about how to use the libpkix library. Certain key warnings and notices from
+ * that document are repeated here for emphasis.
+ *
+ * All identifiers in this file (and all public identifiers defined in
+ * libpkix) begin with "PKIX_". Private identifiers only intended for use
+ * within the library begin with "pkix_".
+ *
+ * A function returns NULL upon success, and a PKIX_Error pointer upon failure.
+ *
+ * Unless otherwise noted, for all accessor (gettor) functions that return a
+ * PKIX_PL_Object pointer, callers should assume that this pointer refers to a
+ * shared object. Therefore, the caller should treat this shared object as
+ * read-only and should not modify this shared object. When done using the
+ * shared object, the caller should release the reference to the object by
+ * using the PKIX_PL_Object_DecRef function.
+ *
+ * While a function is executing, if its arguments (or anything referred to by
+ * its arguments) are modified, free'd, or destroyed, the function's behavior
+ * is undefined.
+ *
+ */
+
+/* PKIX_CRLSelector
+ *
+ * PKIX_CRLSelectors provide a standard way for the caller to select CRLs
+ * based on particular criteria. A CRLSelector is typically used by libpkix
+ * to retrieve CRLs from a CertStore during certificate chain validation or
+ * building. (see pkix_certstore.h) For example, the caller may wish to only
+ * select those CRLs that have a particular issuer or a particular value for a
+ * private CRL extension. The MatchCallback allows the caller to specify the
+ * custom matching logic to be used by a CRLSelector.
+
+ * By default, the MatchCallback is set to point to the default implementation
+ * provided by libpkix, which understands how to process the most common
+ * parameters. If the default implementation is used, the caller should set
+ * these common parameters using PKIX_CRLSelector_SetCommonCRLSelectorParams.
+ * Any common parameter that is not set is assumed to be disabled, which means
+ * the default MatchCallback implementation will select all CRLs without
+ * regard to that particular disabled parameter. For example, if the
+ * MaxCRLNumber parameter is not set, MatchCallback will not filter out any
+ * CRL based on its CRL number. As such, if no parameters are set, all are
+ * disabled and any CRL will match. If a parameter is disabled, its associated
+ * PKIX_ComCRLSelParams_Get* function returns a default value of NULL.
+ *
+ * If a custom implementation is desired, the default implementation can be
+ * overridden by calling PKIX_CRLSelector_SetMatchCallback. In this case, the
+ * CRLSelector can be initialized with a crlSelectorContext, which is where
+ * the caller can specify the desired parameters the caller wishes to match
+ * against. Note that this crlSelectorContext must be a PKIX_PL_Object,
+ * allowing it to be reference-counted and allowing it to provide the standard
+ * PKIX_PL_Object functions (Equals, Hashcode, ToString, Compare, Duplicate).
+ *
+ */
+
+/*
+ * FUNCTION: PKIX_CRLSelector_MatchCallback
+ * DESCRIPTION:
+ *
+ * This callback function determines whether the specified CRL pointed to by
+ * "crl" matches the criteria of the CRLSelector pointed to by "selector".
+ * If the CRL matches the CRLSelector's criteria, PKIX_TRUE is stored at
+ * "pMatch". Otherwise PKIX_FALSE is stored at "pMatch".
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CRLSelector whose MatchCallback logic and parameters are
+ * to be used. Must be non-NULL.
+ * "crl"
+ * Address of CRL that is to be matched using "selector". Must be non-NULL.
+ * "pMatch"
+ * Address at which Boolean result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same objects.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_CRLSelector_MatchCallback)(
+ PKIX_CRLSelector *selector,
+ PKIX_PL_CRL *crl,
+ PKIX_Boolean *pMatch,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CRLSelector_Create
+ * DESCRIPTION:
+ *
+ * Creates a new CRLSelector using the Object pointed to by
+ * "crlSelectorContext" (if any) and stores it at "pSelector". As noted
+ * above, by default, the MatchCallback is set to point to the default
+ * implementation provided by libpkix, which understands how to process
+ * ComCRLSelParams. This is overridden if the MatchCallback pointed to by
+ * "callback" is not NULL, in which case the parameters are specified using
+ * the Object pointed to by "crlSelectorContext".
+ *
+ * PARAMETERS:
+ * "issue"
+ * crl issuer.
+ * "crlDpList"
+ * distribution points list
+ * "callback"
+ * The MatchCallback function to be used.
+ * "pSelector"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CRLSelector_Create(
+ PKIX_PL_Cert *issuer,
+ PKIX_List *crlDpList,
+ PKIX_PL_Date *date,
+ PKIX_CRLSelector **pSelector,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CRLSelector_GetMatchCallback
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to "selector's" Match callback function and puts it in
+ * "pCallback".
+ *
+ * PARAMETERS:
+ * "selector"
+ * The CRLSelector whose Match callback is desired. Must be non-NULL.
+ * "pCallback"
+ * Address where Match callback function pointer will be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CRLSelector_GetMatchCallback(
+ PKIX_CRLSelector *selector,
+ PKIX_CRLSelector_MatchCallback *pCallback,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CRLSelector_GetCRLSelectorContext
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a PKIX_PL_Object representing the context (if any)
+ * of the CRLSelector pointed to by "selector" and stores it at
+ * "pCRLSelectorContext".
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CRLSelector whose context is to be stored. Must be non-NULL.
+ * "pCRLSelectorContext"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CRLSelector_GetCRLSelectorContext(
+ PKIX_CRLSelector *selector,
+ void **pCRLSelectorContext,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CRLSelector_GetCommonCRLSelectorParams
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the ComCRLSelParams object that represent the common
+ * parameters of the CRLSelector pointed to by "selector" and stores it at
+ * "pCommonCRLSelectorParams". If there are no common parameters stored with
+ * the CRLSelector, this function stores NULL at "pCommonCRLSelectorParams".
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CRLSelector whose ComCRLSelParams are to be stored.
+ * Must be non-NULL.
+ * "pCommonCRLSelectorParams"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CRLSelector_GetCommonCRLSelectorParams(
+ PKIX_CRLSelector *selector,
+ PKIX_ComCRLSelParams **pCommonCRLSelectorParams,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_CRLSelector_SetCommonCRLSelectorParams
+ * DESCRIPTION:
+ *
+ * Sets the common parameters for the CRLSelector pointed to by "selector"
+ * using the ComCRLSelParams pointed to by "commonCRLSelectorParams".
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CRLSelector whose common parameters are to be set.
+ * Must be non-NULL.
+ * "commonCRLSelectorParams"
+ * Address of ComCRLSelParams representing the common parameters.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "selector"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_CRLSelector_SetCommonCRLSelectorParams(
+ PKIX_CRLSelector *selector,
+ PKIX_ComCRLSelParams *commonCRLSelectorParams,
+ void *plContext);
+
+/* PKIX_ComCRLSelParams
+ *
+ * PKIX_ComCRLSelParams are X.509 parameters commonly used with CRLSelectors,
+ * especially determining which CRLs to retrieve from a CertStore.
+ * PKIX_ComCRLSelParams are typically used with those CRLSelectors that use
+ * the default implementation of MatchCallback, which understands how to
+ * process ComCRLSelParams.
+ */
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_Create
+ * DESCRIPTION:
+ *
+ * Creates a new ComCRLSelParams object and stores it at "pParams".
+ *
+ * PARAMETERS:
+ * "pParams"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_Create(
+ PKIX_ComCRLSelParams **pParams,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetIssuerNames
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of X500Names (if any) representing the
+ * issuer names criterion that is set in the ComCRLSelParams pointed to by
+ * "params" and stores it at "pNames". In order to match against this
+ * criterion, a CRL's IssuerName must match at least one of the criterion's
+ * issuer names.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pNames", in which case all CRLs are considered to match.
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParams whose issuer names criterion (if any) is to
+ * be stored. Must be non-NULL.
+ * "pNames"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetIssuerNames(
+ PKIX_ComCRLSelParams *params,
+ PKIX_List **pNames, /* list of PKIX_PL_X500Name */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetIssuerNames
+ * DESCRIPTION:
+ *
+ * Sets the issuer names criterion of the ComCRLSelParams pointed to by
+ * "params" using a List of X500Names pointed to by "names". In order to match
+ * against this criterion, a CRL's IssuerName must match at least one of the
+ * criterion's issuer names.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParamsParams whose issuer names criterion is to be
+ * set. Must be non-NULL.
+ * "names"
+ * Address of List of X500Names used to set the criterion
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetIssuerNames(
+ PKIX_ComCRLSelParams *params,
+ PKIX_List *names, /* list of PKIX_PL_X500Name */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_AddIssuerName
+ * DESCRIPTION:
+ *
+ * Adds to the issuer names criterion of the ComCRLSelParams pointed to by
+ * "params" using the X500Name pointed to by "name". In order to match
+ * against this criterion, a CRL's IssuerName must match at least one of the
+ * criterion's issuer names.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParams whose issuer names criterion is to be added
+ * to. Must be non-NULL.
+ * "name"
+ * Address of X500Name to be added.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_AddIssuerName(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_X500Name *name,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetCertificateChecking
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the Cert (if any) representing the certificate whose
+ * revocation status is being checked. This is not a criterion. It is simply
+ * optional information that may help a CertStore find relevant CRLs.
+ *
+ * If "params" does not have a certificate set, this function stores NULL at
+ * "pCert", in which case there is no optional information to provide.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParams whose certificate being checked (if any) is
+ * to be stored. Must be non-NULL.
+ * "pCert"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetCertificateChecking(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_Cert **pCert,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetCertificateChecking
+ * DESCRIPTION:
+ *
+ * Sets the ComCRLSelParams pointed to by "params" with the certificate
+ * (pointed to by "cert") whose revocation status is being checked. This is
+ * not a criterion. It is simply optional information that may help a
+ * CertStore find relevant CRLs.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParams whose certificate being checked is to be
+ * set. Must be non-NULL.
+ * "cert"
+ * Address of Cert whose revocation status is being checked
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetCertificateChecking(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_Cert *cert,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetDateAndTime
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the Date (if any) representing the dateAndTime
+ * criterion that is set in the ComCRLSelParams pointed to by "params" and
+ * stores it at "pDate". In order to match against this criterion, a CRL's
+ * thisUpdate component must be less than or equal to the criterion's
+ * dateAndTime and the CRL's nextUpdate component must be later than the
+ * criterion's dateAndTime. There is no match if the CRL does not contain a
+ * nextUpdate component.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pDate", in which case all CRLs are considered to match.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParams whose dateAndTime criterion (if any) is to
+ * be stored. Must be non-NULL.
+ * "pDate"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetDateAndTime(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_Date **pDate,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetDateAndTime
+ * DESCRIPTION:
+ *
+ * Sets the dateAndTime criterion of the ComCRLSelParams pointed to by
+ * "params" using a Date pointed to by "date". In order to match against this
+ * criterion, a CRL's thisUpdate component must be less than or equal to the
+ * criterion's dateAndTime and the CRL's nextUpdate component must be later
+ * than the criterion's dateAndTime. There is no match if the CRL does not
+ * contain a nextUpdate component.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParamsParams whose dateAndTime criterion is to be
+ * set. Must be non-NULL.
+ * "date"
+ * Address of Date used to set the criterion
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetDateAndTime(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_Date *date,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetNISTPolicyEnabled
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the Boolean representing the NIST CRL policy
+ * activation flag that is set in the ComCRLSelParams pointed to by "params"
+ * and stores it at "enabled". If enabled, a CRL must have nextUpdate field.
+ *
+ * Default value for this flag is TRUE.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParams whose NIST CRL policy criterion is to
+ * be stored. Must be non-NULL.
+ * "pEnabled"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetNISTPolicyEnabled(
+ PKIX_ComCRLSelParams *params,
+ PKIX_Boolean *pEnabled,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetNISTPolicyEnabled
+ * DESCRIPTION:
+ *
+ * Sets the NIST crl policy criterion of the ComCRLSelParams pointed to by
+ * "params" using a "enabled" flag. In order to match against this
+ * criterion, a CRL's nextUpdate must be available and criterion's
+ * dataAndTime must be within thisUpdate and nextUpdate time period.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParamsParams whose NIST CRL policy criterion
+ * is to be set. Must be non-NULL.
+ * "enabled"
+ * Address of Bollean used to set the criterion
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetNISTPolicyEnabled(
+ PKIX_ComCRLSelParams *params,
+ PKIX_Boolean enabled,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetMaxCRLNumber
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the BigInt (if any) representing the maxCRLNumber
+ * criterion that is set in the ComCRLSelParams pointed to by "params" and
+ * stores it at "pNumber". In order to match against this criterion, a CRL
+ * must have a CRL number extension whose value is less than or equal to the
+ * criterion's value.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pNumber", in which case all CRLs are considered to match.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParams whose maxCRLNumber criterion (if any) is to
+ * be stored. Must be non-NULL.
+ * "pNumber"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetMaxCRLNumber(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_BigInt **pNumber,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetMaxCRLNumber
+ * DESCRIPTION:
+ *
+ * Sets the maxCRLNumber criterion of the ComCRLSelParams pointed to by
+ * "params" using a BigInt pointed to by "number". In order to match against
+ * this criterion, a CRL must have a CRL number extension whose value is less
+ * than or equal to the criterion's value.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParamsParams whose maxCRLNumber criterion is to be
+ * set. Must be non-NULL.
+ * "number"
+ * Address of BigInt used to set the criterion
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetMaxCRLNumber(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_BigInt *number,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetMinCRLNumber
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the BigInt (if any) representing the minCRLNumber
+ * criterion that is set in the ComCRLSelParams pointed to by "params" and
+ * stores it at "pNumber". In order to match against this criterion, a CRL
+ * must have a CRL number extension whose value is greater than or equal to
+ * the criterion's value.
+ *
+ * If "params" does not have this criterion set, this function stores NULL at
+ * "pNumber", in which case all CRLs are considered to match.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParams whose minCRLNumber criterion (if any) is to
+ * be stored. Must be non-NULL.
+ * "pNumber"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetMinCRLNumber(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_BigInt **pNumber,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetMinCRLNumber
+ * DESCRIPTION:
+ *
+ * Sets the minCRLNumber criterion of the ComCRLSelParams pointed to by
+ * "params" using a BigInt pointed to by "number". In order to match against
+ * this criterion, a CRL must have a CRL number extension whose value is
+ * greater than or equal to the criterion's value.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParamsParams whose minCRLNumber criterion is to be
+ * set. Must be non-NULL.
+ * "number"
+ * Address of BigInt used to set the criterion
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetMinCRLNumber(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_BigInt *number,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetCrlDp
+ * DESCRIPTION:
+ *
+ * Sets crldp list that can be used to download a crls.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCRLSelParamsParams whose minCRLNumber criterion is to be
+ * set. Must be non-NULL.
+ * "crldpList"
+ * A list of CRLDPs. Can be an emptry list.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error*
+PKIX_ComCRLSelParams_SetCrlDp(
+ PKIX_ComCRLSelParams *params,
+ PKIX_List *crldpList,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_CRLSEL_H */
diff --git a/security/nss/lib/libpkix/include/pkix_errorstrings.h b/security/nss/lib/libpkix/include/pkix_errorstrings.h
new file mode 100644
index 0000000000..0519bff0e6
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkix_errorstrings.h
@@ -0,0 +1,1099 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 file is intended to be included after different definitions of
+ * PKIX_ERRORENTRY. It is included in pkixt.h to define a number for each error
+ * by defining PKIX_ERRORENTRY(x,y) as PKIX_ ## x and then listing thim within
+ * an enum. It is included in pkix_error.c to define an array of error strings
+ * by defining PKIX_ERRORENTRY(x,y) #y and then listing thim within an array
+ * const char * const PKIX_ErrorText[]
+ */
+/* ALLOCERROR should always be the first */
+PKIX_ERRORENTRY(ALLOCERROR,Allocation Error,SEC_ERROR_NO_MEMORY),
+PKIX_ERRORENTRY(ADDHEADERFUNCTIONNOTSUPPORTED,AddHeader function not supported,0),
+PKIX_ERRORENTRY(ADDTOVERIFYLOGFAILED,pkix_AddToVerifyLog failed,0),
+PKIX_ERRORENTRY(AIAMGRCREATEFAILED,PKIX_PL_AIAMgr_Create failed,0),
+PKIX_ERRORENTRY(AIAMGRFINDLDAPCLIENTFAILED,pkix_pl_AiaMgr_FindLDAPClient failed,0),
+PKIX_ERRORENTRY(AIAMGRGETAIACERTSFAILED,PKIX_PL_AIAMgr_GetAIACerts failed,SEC_ERROR_UNKNOWN_ISSUER),
+PKIX_ERRORENTRY(AIAMGRGETHTTPCERTSFAILED,pkix_pl_AIAMgr_GetHTTPCerts failed,0),
+PKIX_ERRORENTRY(AIAMGRGETLDAPCERTSFAILED,pkix_pl_AIAMgr_GetLDAPCerts failed,0),
+PKIX_ERRORENTRY(ALGORITHMBYTESLENGTH0,Algorithm bytes length is 0,0),
+PKIX_ERRORENTRY(ALLOCATENEWCERTGENERALNAMEFAILED,Allocate new CERTGeneralName failed,0),
+PKIX_ERRORENTRY(AMBIGUOUSPARENTAGEOFVERIFYNODE,Ambiguous parentage of VerifyNode,0),
+PKIX_ERRORENTRY(ANCHORDIDNOTCHAINTOCERT,Anchor did not chain to Cert,SEC_ERROR_UNKNOWN_ISSUER),
+PKIX_ERRORENTRY(ANCHORDIDNOTPASSCERTSELECTORCRITERIA,Anchor did not pass CertSelector criteria,0),
+PKIX_ERRORENTRY(APPENDLISTFAILED,pkix_pl_AppendList failed,0),
+PKIX_ERRORENTRY(ARGUMENTNOTSTRING,Argument is not a String,0),
+PKIX_ERRORENTRY(ARGUMENTSNOTBIGINTS,Arguments are not BigInts,0),
+PKIX_ERRORENTRY(ARGUMENTSNOTBYTEARRAYS,Arguments are not Byte Arrays,0),
+PKIX_ERRORENTRY(ARGUMENTSNOTDATES,Arguments are not Dates,0),
+PKIX_ERRORENTRY(ARGUMENTSNOTOIDS,Arguments are not OIDs,0),
+PKIX_ERRORENTRY(ATTEMPTTOADDDUPLICATEKEY,Attempt to add duplicate key,0),
+PKIX_ERRORENTRY(ATTEMPTTODECODEANINCOMPLETERESPONSE,Attempt to decode an incomplete response,SEC_ERROR_BAD_DER),
+PKIX_ERRORENTRY(ATTEMPTTODECREFALLOCERROR,Attempt to DecRef Alloc Error,0),
+PKIX_ERRORENTRY(ATTEMPTTOINCREFALLOCERROR,Attempt to IncRef Alloc Error,0),
+PKIX_ERRORENTRY(BADHTTPRESPONSE,Bad Http Response,SEC_ERROR_BAD_HTTP_RESPONSE),
+PKIX_ERRORENTRY(BASICCONSTRAINTSCHECKERINITIALIZEFAILED,pkix_BasicConstraintsChecker_Initialize failed,0),
+PKIX_ERRORENTRY(BASICCONSTRAINTSCHECKERSTATECREATEFAILED,PKIX_BasicConstraintsCheckerState_Create failed,0),
+PKIX_ERRORENTRY(BASICCONSTRAINTSGETCAFLAGFAILED,PKIX_PL_BasicConstraints_GetCAFlag failed,0),
+PKIX_ERRORENTRY(BASICCONSTRAINTSGETPATHLENCONSTRAINTFAILED,PKIX_PL_BasicConstraints_GetPathLenConstraint failed,0),
+PKIX_ERRORENTRY(BASICCONSTRAINTSVALIDATIONFAILEDCA,PKIX_BasicConstraints validation failed: CA Flag not set,SEC_ERROR_CA_CERT_INVALID),
+PKIX_ERRORENTRY(BASICCONSTRAINTSVALIDATIONFAILEDLN,PKIX_BasicConstraints validation failed: maximum length mismatch,SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID),
+PKIX_ERRORENTRY(BIGINTCOMPARATORFAILED,pkix_pl_BigInt_Comparator failed,0),
+PKIX_ERRORENTRY(BIGINTCREATEWITHBYTESFAILED,pkix_pl_BigInt_CreateWithBytes failed,0),
+PKIX_ERRORENTRY(BIGINTEQUALSFAILED,PKIX_PL_BigInt_Equals failed,0),
+PKIX_ERRORENTRY(BIGINTLENGTH0INVALID,BigInt length 0 is invalid,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(BIGINTTOSTRINGFAILED,pkix_pl_BigInt_ToString failed,0),
+PKIX_ERRORENTRY(BIGINTTOSTRINGHELPERFAILED,PKIX_PL_BigInt_ToString_Helper failed,0),
+PKIX_ERRORENTRY(BINDREJECTEDBYSERVER,BIND rejected by server,SEC_ERROR_BAD_LDAP_RESPONSE),
+PKIX_ERRORENTRY(BUILDANDVALIDATECHAINFAILED,Failed to build and validate a chain,0),
+PKIX_ERRORENTRY(BUILDBUILDSELECTORANDPARAMSFAILED,pkix_Build_BuildSelectorAndParams failed,0),
+PKIX_ERRORENTRY(BUILDCOMBINEWITHTRUSTFAILED,pkix_Build_CombineWithTrust failed,0),
+PKIX_ERRORENTRY(BUILDFORWARDDEPTHFIRSTSEARCHFAILED,pkix_BuildForwardDepthFirstSearch failed,0),
+PKIX_ERRORENTRY(BUILDGATHERCERTSFAILED,pkix_Build_GatherCerts failed,0),
+PKIX_ERRORENTRY(BUILDGETRESOURCELIMITSFAILED,pkix_Build_GetResourceLimits failed,0),
+PKIX_ERRORENTRY(BUILDINITIATEBUILDCHAINFAILED,pkix_Build_InitiateBuildChain failed,0),
+PKIX_ERRORENTRY(BUILDRESULTCREATEFAILED,pkix_BuildResult_Create failed,0),
+PKIX_ERRORENTRY(BUILDRESULTGETCERTCHAINFAILED,PKIX_BuildResult_GetCertChain failed,0),
+PKIX_ERRORENTRY(BUILDRESULTGETVALIDATERESULTFAILED,PKIX_BuildResult_GetValidateResult failed,0),
+PKIX_ERRORENTRY(BUILDREVCHECKPREPFAILED,pkix_Build_RevCheckPrep failed,0),
+PKIX_ERRORENTRY(BUILDSORTCANDIDATECERTSFAILED,pkix_Build_SortCandidateCerts failed,0),
+PKIX_ERRORENTRY(BUILDSTATECREATEFAILED,pkix_BuildState_Create failed,0),
+PKIX_ERRORENTRY(BUILDTRYSHORTCUTFAILED,pkix_Build_TryShortcut failed,0),
+PKIX_ERRORENTRY(BUILDUPDATEDATEFAILED,pkix_Build_UpdateDate failed,0),
+PKIX_ERRORENTRY(BUILDVALIDATEENTIRECHAINFAILED,pkix_Build_ValidateEntireChain failed,0),
+PKIX_ERRORENTRY(BUILDVALIDATIONCHECKERSFAILED,pkix_Build_ValidationCheckers failed,0),
+PKIX_ERRORENTRY(BUILDVERIFYCERTIFICATEFAILED,pkix_Build_VerifyCertificate failed,0),
+PKIX_ERRORENTRY(BYTEARRAYCOMPARATORFAILED,pkix_pl_ByteArray_Comparator failed,0),
+PKIX_ERRORENTRY(BYTEARRAYCREATEFAILED,PKIX_PL_ByteArray_Create failed,0),
+PKIX_ERRORENTRY(BYTEARRAYEQUALSFAILED,PKIX_PL_ByteArray_Equals failed,0),
+PKIX_ERRORENTRY(BYTEARRAYGETLENGTHFAILED,PKIX_PL_ByteArray_GetLength failed,0),
+PKIX_ERRORENTRY(BYTEARRAYGETPOINTERFAILED,PKIX_PL_ByteArray_GetPointer failed,0),
+PKIX_ERRORENTRY(BYTEARRAYTOHEXSTRINGFAILED,pkix_pl_ByteArray_ToHexString failed,0),
+PKIX_ERRORENTRY(BYTEARRAYTOSTRINGFAILED,PKIX_PL_ByteArray_ToString failed,0),
+PKIX_ERRORENTRY(CACHECERTADDFAILED,pkix_CacheCert_Add failed,0),
+PKIX_ERRORENTRY(CACHECERTCHAINADDFAILED,pkix_CacheCertChain_Add failed,0),
+PKIX_ERRORENTRY(CACHECERTCHAINLOOKUPFAILED,pkix_CacheCertChain_Lookup failed,0),
+PKIX_ERRORENTRY(CACHECERTCHAINREMOVEFAILED,pkix_CacheCertChain_Remove failed,0),
+PKIX_ERRORENTRY(CACHECRLENTRYADDFAILED,pkix_CacheCrlEntry_Add failed,0),
+PKIX_ERRORENTRY(CACHECRLENTRYLOOKUPFAILED,pkix_CacheCrlEntry_Lookup failed,0),
+PKIX_ERRORENTRY(CALLOCFAILED,PKIX_PL_Calloc failed,0),
+PKIX_ERRORENTRY(CANNOTAQUIRECRLDER,Failed to get DER CRL,0),
+PKIX_ERRORENTRY(CANNOTCONVERTCERTUSAGETOPKIXKEYANDEKUSAGES, Fail to convert certificate usage to pkix KU and EKU,0),
+PKIX_ERRORENTRY(CANNOTOPENCOLLECTIONCERTSTORECONTEXTDIRECTORY,Cannot open CollectionCertStoreContext directory,0),
+PKIX_ERRORENTRY(CANTCREATESTRING,Cannot create PKIX_PL_String,0),
+PKIX_ERRORENTRY(CANTDECODEBINDRESPONSEFROMSERVER,Cannot decode BIND response from server,SEC_ERROR_BAD_LDAP_RESPONSE),
+PKIX_ERRORENTRY(CANTDECODESEARCHRESPONSEFROMSERVER,Cannot decode SEARCH response from server,SEC_ERROR_BAD_LDAP_RESPONSE),
+PKIX_ERRORENTRY(CANTENABLEREVOCATIONWITHOUTCERTSTORE,Cannot enable Revocation without CertStore,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(CANTLOADLIBSMIME,Cannot load smime3 library,0),
+PKIX_ERRORENTRY(CANTREREGISTERSYSTEMTYPE,Cannot reregister system type,0),
+PKIX_ERRORENTRY(CERTARECERTPOLICIESCRITICALFAILED,PKIX_PL_Cert_AreCertPoliciesCritical failed,0),
+PKIX_ERRORENTRY(CERTBASICCONSTRAINTSCREATEFAILED,pkix_pl_CertBasicConstraints_Create failed,0),
+PKIX_ERRORENTRY(CERTBASICCONSTRAINTSTOSTRINGFAILED,PKIX_PL_CertBasicConstraints_ToString failed,0),
+PKIX_ERRORENTRY(CERTCHAINCHECKERCHECKCALLBACKFAILED,PKIX_CertChainChecker_CheckCallback failed,0),
+PKIX_ERRORENTRY(CERTCHAINCHECKERCHECKFAILED,PKIX_CertChainChecker_Check failed,0),
+PKIX_ERRORENTRY(CERTCHAINCHECKERCREATEFAILED,PKIX_CertChainChecker_Create failed,0),
+PKIX_ERRORENTRY(CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED,PKIX_CertChainChecker_GetCertChainCheckerState failed,0),
+PKIX_ERRORENTRY(CERTCHAINCHECKERGETCHECKCALLBACKFAILED,PKIX_CertChainChecker_GetCheckCallback failed,0),
+PKIX_ERRORENTRY(CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED,PKIX_CertChainChecker_GetSupportedExtensions failed,0),
+PKIX_ERRORENTRY(CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED,PKIX_CertChainChecker_IsForwardCheckingSupported failed,0),
+PKIX_ERRORENTRY(CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED,PKIX_CertChainChecker_SetCertChainCheckerState failed,0),
+PKIX_ERRORENTRY(CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION,CertChain fails Certificate Policy validation,SEC_ERROR_POLICY_VALIDATION_FAILED),
+PKIX_ERRORENTRY(CERTCHAINTONSSCHAINFAILED,Fail to convert pkix cert chain to nss cert chain,0),
+PKIX_ERRORENTRY(CERTCHAINTOPKIXCERTLISTFAILED,Failed to convert nss cert chain to pkix cert chain,0),
+PKIX_ERRORENTRY(CERTCHECKCERTTYPEFAILED,Check cert type failed,SEC_ERROR_INADEQUATE_CERT_TYPE),
+PKIX_ERRORENTRY(CERTCHECKCERTVALIDTIMESFAILED,CERT_CheckCertValidTimes failed,SEC_ERROR_EXPIRED_CERTIFICATE),
+PKIX_ERRORENTRY(CERTCHECKCRLFAILED,Fail to get crl cache issued by cert,0),
+PKIX_ERRORENTRY(CERTCHECKEXTENDEDKEYUSAGEFAILED,pkix_pl_Cert_CheckExtendedKeyUsage failed,0),
+PKIX_ERRORENTRY(CERTCHECKKEYUSAGEFAILED,CERT_CheckKeyUsage failed,SEC_ERROR_INADEQUATE_KEY_USAGE),
+PKIX_ERRORENTRY(CERTCHECKNAMECONSTRAINTSFAILED,PKIX_PL_Cert_CheckNameConstraints failed,0),
+PKIX_ERRORENTRY(CERTCHECKVALIDITYFAILED,PKIX_PL_Cert_CheckValidity failed,0),
+PKIX_ERRORENTRY(CERTCOMPLETECRLDECODEDENTRIESFAILED,CERT_CompleteCRLDecodedEntries failed,0),
+PKIX_ERRORENTRY(CERTCOPYNAMECONSTRAINTFAILED,CERT_CopyNameConstraint failed,0),
+PKIX_ERRORENTRY(CERTCOPYNAMEFAILED,CERT_CopyName failed,0),
+PKIX_ERRORENTRY(CERTCREATEFAILED,PKIX_PL_Cert_Create failed,0),
+PKIX_ERRORENTRY(CERTCREATEGENERALNAMELISTFAILED,CERT_CreateGeneralNameList failed,0),
+PKIX_ERRORENTRY(CERTCREATETOLISTFAILED,pkix_pl_Cert_CreateToList failed,0),
+PKIX_ERRORENTRY(CERTCREATEWITHNSSCERTFAILED,pkix_pl_Cert_CreateWithNSSCert failed,0),
+PKIX_ERRORENTRY(CERTDECODEALTNAMEEXTENSIONFAILED,CERT_DecodeAltNameExtension failed,0),
+PKIX_ERRORENTRY(CERTDECODECERTIFICATEPOLICIESEXTENSIONFAILED,CERT_DecodeCertificatePoliciesExtension failed,0),
+PKIX_ERRORENTRY(CERTDECODEDERCERTIFICATEFAILED,CERT_DecodeDERCertificate failed,0),
+PKIX_ERRORENTRY(CERTDECODEDERCRLFAILED,CERT_DecodeDERCrl failed,0),
+PKIX_ERRORENTRY(CERTDECODEINHIBITANYEXTENSIONFAILED,CERT_DecodeInhibitAnyExtension failed,0),
+PKIX_ERRORENTRY(CERTDECODEINHIBITANYPOLICYFAILED,pkix_pl_Cert_DecodeInhibitAnyPolicy failed,0),
+PKIX_ERRORENTRY(CERTDECODEOIDSEQUENCEFAILED,CERT_DecodeOidSequence failed,0),
+PKIX_ERRORENTRY(CERTDECODEPOLICYCONSTRAINTSEXTENSIONFAILED,CERT_DecodePolicyConstraintsExtension failed,0),
+PKIX_ERRORENTRY(CERTDECODEPOLICYCONSTRAINTSFAILED,pkix_pl_Cert_DecodePolicyConstraints failed,0),
+PKIX_ERRORENTRY(CERTDECODEPOLICYINFOFAILED,pkix_pl_Cert_DecodePolicyInfo failed,0),
+PKIX_ERRORENTRY(CERTDECODEPOLICYMAPPINGFAILED,pkix_pl_Cert_DecodePolicyMapping failed,0),
+PKIX_ERRORENTRY(CERTDECODEPOLICYMAPPINGSEXTENSIONFAILED,CERT_DecodePolicyMappingsExtension failed,0),
+PKIX_ERRORENTRY(CERTEQUALSFAILED,pkix_pl_Cert_Equals failed,0),
+PKIX_ERRORENTRY(CERTFAILEDNAMECONSTRAINTSCHECKING,Cert failed NameConstraints checking,SEC_ERROR_CERT_NOT_IN_NAME_SPACE),
+PKIX_ERRORENTRY(CERTGETALLSUBJECTNAMESFAILED,PKIX_PL_Cert_GetAllSubjectNames failed,0),
+PKIX_ERRORENTRY(CERTGETAUTHORITYINFOACCESSFAILED,PKIX_PL_Cert_GetAuthorityInfoAccess failed,0),
+PKIX_ERRORENTRY(CERTGETAUTHORITYKEYIDENTIFIERFAILED,PKIX_PL_Cert_GetAuthorityKeyIdentifier failed,0),
+PKIX_ERRORENTRY(CERTGETBASICCONSTRAINTFAILED,PKIX_PL_Cert_GetBasicConstraint failed,0),
+PKIX_ERRORENTRY(CERTGETBASICCONSTRAINTSFAILED,PKIX_PL_Cert_GetBasicConstraints failed,0),
+PKIX_ERRORENTRY(CERTGETCACHEFLAGFAILED,PKIX_Cert_GetCacheFlag failed,0),
+PKIX_ERRORENTRY(CERTGETCERTCERTIFICATEFAILED,PKIX_PL_Cert_GetCERTCertificate failed,0),
+PKIX_ERRORENTRY(CERTGETCRITICALEXTENSIONOIDSFAILED,PKIX_PL_Cert_GetCriticalExtensionOIDs failed,0),
+PKIX_ERRORENTRY(CERTGETCRLDPFAILED,Failed to get cert crldp extension, 0),
+PKIX_ERRORENTRY(CERTGETEXTENDEDKEYUSAGEFAILED,PKIX_PL_Cert_GetExtendedKeyUsage failed,0),
+PKIX_ERRORENTRY(CERTGETINHIBITANYPOLICYFAILED,PKIX_PL_Cert_GetInhibitAnyPolicy failed,0),
+PKIX_ERRORENTRY(CERTGETISSUERFAILED,PKIX_PL_Cert_GetIssuer failed,0),
+PKIX_ERRORENTRY(CERTGETNAMECONSTRAINTSFAILED,PKIX_PL_CertGetNameConstraints failed,0),
+PKIX_ERRORENTRY(CERTGETNSSSUBJECTALTNAMESFAILED,pkix_pl_Cert_GetNssSubjectAltNames failed,0),
+PKIX_ERRORENTRY(CERTGETPOLICYINFORMATIONFAILED,PKIX_PL_Cert_GetPolicyInformation failed,0),
+PKIX_ERRORENTRY(CERTGETPOLICYMAPPINGINHIBITEDFAILED,PKIX_PL_Cert_GetPolicyMappingInhibited failed,0),
+PKIX_ERRORENTRY(CERTGETPOLICYMAPPINGSFAILED,PKIX_PL_Cert_GetPolicyMappings failed,0),
+PKIX_ERRORENTRY(CERTGETREQUIREEXPLICITPOLICYFAILED,PKIX_PL_Cert_GetRequireExplicitPolicy failed,0),
+PKIX_ERRORENTRY(CERTGETSERIALNUMBERFAILED,PKIX_PL_Cert_GetSerialNumber failed,0),
+PKIX_ERRORENTRY(CERTGETSUBJALTNAMESFAILED,PKIX_PL_Cert_GetSubjAltNames failed,0),
+PKIX_ERRORENTRY(CERTGETSUBJECTALTNAMESFAILED,PKIX_PL_Cert_GetSubjectAltNames failed,0),
+PKIX_ERRORENTRY(CERTGETSUBJECTFAILED,PKIX_PL_Cert_GetSubject failed,0),
+PKIX_ERRORENTRY(CERTGETSUBJECTINFOACCESSFAILED,PKIX_PL_Cert_GetSubjectInfoAccess failed,0),
+PKIX_ERRORENTRY(CERTGETSUBJECTKEYIDENTIFIERFAILED,PKIX_PL_Cert_GetSubjectKeyIdentifier failed,0),
+PKIX_ERRORENTRY(CERTGETSUBJECTPUBLICKEYALGIDFAILED,PKIX_PL_Cert_GetSubjectPublicKeyAlgId failed,0),
+PKIX_ERRORENTRY(CERTGETSUBJECTPUBLICKEYFAILED,PKIX_PL_Cert_GetSubjectPublicKey failed,0),
+PKIX_ERRORENTRY(CERTGETVALIDITYNOTAFTERFAILED,PKIX_PL_Cert_GetValidityNotAfter failed,0),
+PKIX_ERRORENTRY(CERTGETVERSIONFAILED,PKIX_PL_Cert_GetVersion failed,0),
+PKIX_ERRORENTRY(CERTHASHCODEFAILED,PKIX_PL_Cert_Hashcode failed,0),
+PKIX_ERRORENTRY(CERTIFICATEDOESNTHAVEVALIDCRL,Certificate does not have a valid CRL,SEC_ERROR_CRL_NOT_FOUND),
+PKIX_ERRORENTRY(CERTIFICATEREVOKED,Certificate is revoked,SEC_ERROR_REVOKED_CERTIFICATE),
+PKIX_ERRORENTRY(CERTIMPORTCERTIFICATEFUNCTIONFAILED,CERTImportCertificate function failed,0),
+PKIX_ERRORENTRY(CERTISCERTTRUSTEDFAILED,PKIX_PL_Cert_IsCertTrusted failed,SEC_ERROR_UNTRUSTED_CERT),
+PKIX_ERRORENTRY(CERTISEXTENSIONCRITICALFAILED,pkix_pl_Cert_IsExtensionCritical failed,0),
+PKIX_ERRORENTRY(CERTMERGENAMECONSTRAINTSFAILED,PKIX_PL_Cert_MergeNameConstraints failed,0),
+PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCHECKNAMEINNAMESPACEFAILED,PKIX_PL_CertNameConstraints_CheckNameInNameSpace failed,SEC_ERROR_CERT_NOT_IN_NAME_SPACE),
+PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCHECKNAMESINNAMESPACEFAILED,PKIX_PL_CertNameConstraints_CheckNamesInNameSpace failed,SEC_ERROR_CERT_NOT_IN_NAME_SPACE),
+PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCHECKNAMESPACENSSNAMESFAILED,pkix_pl_CertNameConstraints_CheckNameSpaceNssNames failed,SEC_ERROR_CERT_NOT_IN_NAME_SPACE),
+PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCOPYNSSNAMECONSTRAINTSFAILED,pkix_pl_CertNameConstraints_CopyNssNameConstraints failed,0),
+PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCREATEBYMERGEFAILED,pkix_pl_CertNameConstraints_CreateByMerge failed,0),
+PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCREATEFAILED,pkix_pl_CertNameConstraints_Create failed,0),
+PKIX_ERRORENTRY(CERTNAMECONSTRAINTSCREATEHELPERFAILED,pkix_pl_CertNameConstraints_Create_Helper failed,0),
+PKIX_ERRORENTRY(CERTNAMECONSTRAINTSGETEXCLUDEDFAILED,pkix_pl_CertNameConstraints_GetExcluded failed,0),
+PKIX_ERRORENTRY(CERTNAMECONSTRAINTSGETPERMITTEDFAILED,pkix_pl_CertNameConstraints_GetPermitted failed,0),
+PKIX_ERRORENTRY(CERTNAMECONSTRAINTSMERGEFAILED,pkix_pl_CertNameConstraints_Merge failed,0),
+PKIX_ERRORENTRY(CERTNAMECONSTRAINTSTOSTRINGHELPERFAILED,pkix_pl_CertNameConstraints_ToString_Helper failed,0),
+PKIX_ERRORENTRY(CERTNAMETOASCIIFAILED,CERT_NameToAscii failed,0),
+PKIX_ERRORENTRY(CERTNOTALLOWEDTOSIGNCERTIFICATES,Cert not allowed to sign certificates,SEC_ERROR_CA_CERT_INVALID),
+PKIX_ERRORENTRY(CERTPOLICYINFOCREATEFAILED,pkix_pl_CertPolicyInfo_Create failed,0),
+PKIX_ERRORENTRY(CERTPOLICYINFOGETPOLICYIDFAILED,PKIX_PL_CertPolicyInfo_GetPolicyId failed,0),
+PKIX_ERRORENTRY(CERTPOLICYINFOGETPOLQUALIFIERSFAILED,PKIX_PL_CertPolicyInfo_GetPolQualifiers failed,0),
+PKIX_ERRORENTRY(CERTPOLICYMAPCREATEFAILED,pkix_pl_CertPolicyMap_Create failed,0),
+PKIX_ERRORENTRY(CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED,PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy failed,0),
+PKIX_ERRORENTRY(CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED,PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy failed,0),
+PKIX_ERRORENTRY(CERTPOLICYQUALIFIERCREATEFAILED,pkix_pl_CertPolicyQualifier_Create failed,0),
+PKIX_ERRORENTRY(CERTREJECTEDBYREVOCATIONCHECKER,Cert rejected by revocation checker,0),
+PKIX_ERRORENTRY(CERTSELECTORCHECKFAILED,Validation failed: CertSelector check failed,0),
+PKIX_ERRORENTRY(CERTSELECTORCREATEFAILED,PKIX_CertSelector_Create failed,0),
+PKIX_ERRORENTRY(CERTSELECTORFAILED,certSelector failed,0),
+PKIX_ERRORENTRY(CERTSELECTORGETCOMCERTSELPARAMSFAILED,PKIX_CertSelector_GetComCertSelParams failed,0),
+PKIX_ERRORENTRY(CERTSELECTORGETCOMMONCERTSELECTORPARAMFAILED,PKIX_CertSelector_GetCommonCertSelectorParam failed,0),
+PKIX_ERRORENTRY(CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED,PKIX_CertSelector_GetCommonCertSelectorParams failed,0),
+PKIX_ERRORENTRY(CERTSELECTORGETMATCHCALLBACKFAILED,PKIX_CertSelector_GetMatchCallback failed,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHAUTHKEYIDFAILED,pkix_CertSelector_Match_AuthKeyId failed,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHBASICCONSTRAINTFAILED,pkix_CertSelector_Match_BasicConstraint failed,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHCALLBACKFAILED,PKIX_CertSelector_MatchCallback failed,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHCERTIFICATEVALIDFAILED,pkix_CertSelector_Match_CertificateValid failed,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHCERTISSUERFAILED,cert does not match issuer name,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHCERTOBJECTFAILED,cert does not match cert object,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHCERTSERIALNUMFAILED,cert does not match serial number,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHCERTSUBJECTFAILED,cert does not match subject name,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHCERTVERSIONFAILED,cert does not match cert version,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHEXTENDEDKEYUSAGEFAILED,pkix_CertSelector_Match_ExtendedKeyUsage failed,SEC_ERROR_INADEQUATE_CERT_TYPE),
+PKIX_ERRORENTRY(CERTSELECTORMATCHFAILED,certSelectorMatch failed,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHKEYUSAGEFAILED,pkix_CertSelector_Match_KeyUsage failed,SEC_ERROR_INADEQUATE_KEY_USAGE),
+PKIX_ERRORENTRY(CERTSELECTORMATCHNAMECONSTRAINTSFAILED,pkix_CertSelector_Match_NameConstraints failed,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHPATHTONAMESFAILED,pkix_CertSelector_Match_PathToNames failed,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHPOLICIESFAILED,pkix_CertSelector_Match_Policies failed,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHSUBJALTNAMESFAILED,pkix_CertSelector_Match_SubjAltNames failed,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHSUBJKEYIDFAILED,pkix_CertSelector_Match_SubjKeyId failed,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHSUBJPKALGIDFAILED,pkix_CertSelector_Match_SubjPKAlgId failed,0),
+PKIX_ERRORENTRY(CERTSELECTORMATCHSUBJPUBKEYFAILED,pkix_CertSelector_Match_SubjPubKey failed,0),
+PKIX_ERRORENTRY(CERTSELECTORSELECTFAILED,pkix_CertSelector_Select failed,0),
+PKIX_ERRORENTRY(CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED,PKIX_CertSelector_SetCommonCertSelectorParams failed,0),
+PKIX_ERRORENTRY(CERTSETASTRUSTANCHORFAILED, PKIX_PL_Cert_SetAsTrustAnchor failed, 0),
+PKIX_ERRORENTRY(CERTSETCACHEFLAGFAILED,PKIX_PL_Cert_SetCacheFlag failed,0),
+PKIX_ERRORENTRY(CERTSETTRUSTCERTSTOREFAILED,PKIX_PL_Cert_SetTrustCertStore failed,0),
+PKIX_ERRORENTRY(CERTSTORECERTCONTINUEFAILED,PKIX_CertStore_CertContinue failed,0),
+PKIX_ERRORENTRY(CERTSTORECERTCONTINUEFUNCTIONFAILED,PKIX_CertStore_CertContinueFunction failed,0),
+PKIX_ERRORENTRY(CERTSTORECREATEFAILED,PKIX_CertStore_Create failed,0),
+PKIX_ERRORENTRY(CERTSTORECRLCONTINUEFAILED,PKIX_CertStore_CrlContinue failed,0),
+PKIX_ERRORENTRY(CERTSTOREEQUALSFAILED,pkix_CertStore_Equals failed,0),
+PKIX_ERRORENTRY(CERTSTORECRLCHECKFAILED,Fail to check cert crl revocation,0),
+PKIX_ERRORENTRY(CERTSTOREGETCHECKREVBYCRLFAILED,Can not get revocation check function,0),
+PKIX_ERRORENTRY(CERTSTOREFAILTOIMPORTCRLLIST,Fail to import crls,0),
+PKIX_ERRORENTRY(CERTSTOREGETCERTCALLBACKFAILED,PKIX_CertStore_GetCertCallback failed,0),
+PKIX_ERRORENTRY(CERTSTOREGETCERTSTORECACHEFLAGFAILED,PKIX_CertStore_GetCertStoreCacheFlag failed,0),
+PKIX_ERRORENTRY(CERTSTOREGETCERTSTORECONTEXTFAILED,PKIX_CertStore_GetCertStoreContext failed,0),
+PKIX_ERRORENTRY(CERTSTOREGETCRLCALLBACKFAILED,PKIX_CertStore_GetCRLCallback failed,0),
+PKIX_ERRORENTRY(CERTSTOREGETLOCALFLAGFAILED,PKIX_CertStore_GetLocalFlag failed,0),
+PKIX_ERRORENTRY(CERTSTOREGETTRUSTCALLBACKFAILED,PKIX_CertStore_GetTrustCallback failed,0),
+PKIX_ERRORENTRY(CERTSTOREHASHCODEFAILED,pkix_CertStore_Hashcode failed,0),
+PKIX_ERRORENTRY(CERTTOSTRINGFAILED,PKIX_PL_Cert_ToString failed,0),
+PKIX_ERRORENTRY(CERTTOSTRINGHELPERFAILED,pkix_pl_Cert_ToString_Helper failed,0),
+PKIX_ERRORENTRY(CERTVERIFYCERTTYPEFAILED,PKIX_PL_Cert_VerifyCertAndKeyType failed,0),
+PKIX_ERRORENTRY(CERTVERIFYKEYUSAGEFAILED,PKIX_PL_Cert_VerifyKeyUsage failed,0),
+PKIX_ERRORENTRY(CERTVERIFYSIGNATUREFAILED,PKIX_PL_Cert_VerifySignature failed,0),
+PKIX_ERRORENTRY(CHAINVERIFYCALLBACKFAILED,Chain rejected by Application Callback,SEC_ERROR_APPLICATION_CALLBACK_ERROR),
+PKIX_ERRORENTRY(CHECKCERTAGAINSTANCHORFAILED,pkix_CheckCertAgainstAnchor failed,0),
+PKIX_ERRORENTRY(CHECKCERTFAILED,pkix_CheckCert failed,0),
+PKIX_ERRORENTRY(CHECKCHAINFAILED,pkix_CheckChain failed,0),
+PKIX_ERRORENTRY(CHECKTRUSTCALLBACKFAILED,CheckTrustCallback failed,0),
+PKIX_ERRORENTRY(COLLECTIONCERTSTOREPOPULATECERTFAILED,pkix_pl_CollectionCertStoreContext_PopulateCert failed,0),
+PKIX_ERRORENTRY(COLLECTIONCERTSTOREPOPULATECRLFAILED,pkix_pl_CollectionCertStoreContext_PopulateCrl failed,0),
+PKIX_ERRORENTRY(COLLECTIONCERTSTORECONTEXTCREATECERTFAILED,pkix_pl_CollectionCertStoreContext_CreateCert failed,0),
+PKIX_ERRORENTRY(COLLECTIONCERTSTORECONTEXTCREATECRLFAILED,pkix_pl_CollectionCertStoreContext_CreateCRL failed,0),
+PKIX_ERRORENTRY(COLLECTIONCERTSTORECONTEXTGETSELECTCERTFAILED,pkix_pl_CollectionCertStoreContext_GetSelectCert failed,0),
+PKIX_ERRORENTRY(COLLECTIONCERTSTORECONTEXTGETSELECTCRLFAILED,pkix_pl_CollectionCertStoreContext_GetSelectCRL failed,0),
+PKIX_ERRORENTRY(COLLECTIONCERTSTORECONTEXTPOPULATECERTFAILED,pkix_pl_CollectionCertStoreContext_PopulateCert failed,0),
+PKIX_ERRORENTRY(COLLECTIONCERTSTORECONTEXTPOPULATECRLFAILED,pkix_pl_CollectionCertStoreContext_PopulateCRL failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSCREATEFAILED,PKIX_ComCertSelParams_Create failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETAUTHORITYKEYIDENTIFIERFAILED,PKIX_ComCertSelParams_GetAuthorityKeyIdentifier failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETBASICCONSTRAINTSFAILED,PKIX_ComCertSelParams_GetBasicConstraints failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETCERTIFICATEFAILED,PKIX_ComCertSelParams_GetCertificate failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED,PKIX_ComCertSelParams_GetCertificateValid failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED,PKIX_ComCertSelParams_GetExtendedKeyUsage failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETISSUERFAILED,PKIX_ComCertSelParams_GetIssuer failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETKEYUSAGEFAILED,PKIX_ComCertSelParams_GetKeyUsage failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETLEAFCERTFLAGFAILED,PKIX_ComCertSelParams_GetLeafCertFlag failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETMATCHALLSUBJALTNAMESFAILED,PKIX_ComCertSelParams_GetMatchAllSubjAltNames failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETNAMECONSTRAINTSFAILED,PKIX_ComCertSelParams_GetNameConstraints failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETPATHTONAMESFAILED,PKIX_ComCertSelParams_GetPathToNames failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETPOLICYFAILED,PKIX_ComCertSelParams_GetPolicy failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETSERIALNUMBERFAILED,PKIX_ComCertSelParams_GetSerialNumber failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETSUBJALTNAMESFAILED,PKIX_ComCertSelParams_GetSubjAltNames failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETSUBJECTFAILED,PKIX_ComCertSelParams_GetSubject failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETSUBJKEYIDENTIFIERFAILED,PKIX_ComCertSelParams_GetSubjKeyIdentifier failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETSUBJPKALGIDFAILED,PKIX_ComCertSelParams_GetSubjPKAlgId failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETSUBJPUBKEYFAILED,PKIX_ComCertSelParams_GetSubjPubKey failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSGETVERSIONFAILED,PKIX_ComCertSelParams_GetVersion failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSSETBASICCONSTRAINTSFAILED,PKIX_ComCertSelParams_SetBasicConstraints failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSSETCERTIFICATEFAILED,PKIX_ComCertSelParams_SetCertificate failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED,PKIX_ComCertSelParams_SetCertificateValid failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSSETEXTKEYUSAGEFAILED,PKIX_ComCertSelParams_SetExtendedKeyUsage failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSSETKEYUSAGEFAILED,PKIX_ComCertSelParams_SetKeyUsage failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSSETLEAFCERTFLAGFAILED,PKIX_ComCertSelParams_SetLeafCertFlag failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSSETNISTPOLICYENABLEDFAILED,PKIX_ComCertSelParams_SetNISTPolicyEnabled failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSSETPATHTONAMESFAILED,PKIX_ComCertSelParams_SetPathToNames failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSSETSUBJECTFAILED,PKIX_ComCertSelParams_SetSubject failed,0),
+PKIX_ERRORENTRY(COMCERTSELPARAMSSETSUBJKEYIDENTIFIERFAILED,PKIX_ComCertSelParams_SetSubjKeyIdentifier failed,0),
+PKIX_ERRORENTRY(COMCRLSELPARAMSADDISSUERNAMEFAILED,PKIX_ComCRLSelParams_AddIssuerName failed,0),
+PKIX_ERRORENTRY(COMCRLSELPARAMSCREATEFAILED,PKIX_ComCRLSelParams_Create failed,0),
+PKIX_ERRORENTRY(COMCRLSELPARAMSEQUALSFAILED,pkix_ComCRLSelParams_Equals failed,0),
+PKIX_ERRORENTRY(COMCRLSELPARAMSGETDATEANDTIMEFAILED,PKIX_ComCRLSelParams_GetDateAndTime failed,0),
+PKIX_ERRORENTRY(COMCRLSELPARAMSGETISSUERNAMESFAILED,PKIX_ComCRLSelParams_GetIssuerNames failed,0),
+PKIX_ERRORENTRY(COMCRLSELPARAMSGETMAXCRLNUMBERFAILED,PKIX_ComCRLSelParams_GetMaxCRLNumber failed,0),
+PKIX_ERRORENTRY(COMCRLSELPARAMSGETMINCRLNUMBERFAILED,PKIX_ComCRLSelParams_GetMinCRLNumber failed,0),
+PKIX_ERRORENTRY(COMCRLSELPARAMSGETNISTPOLICYENABLEDFAILED,PKIX_ComCRLSelParams_GetNISTPolicyEnabled failed,0),
+PKIX_ERRORENTRY(COMCRLSELPARAMSSETCERTFAILED,PKIX_ComCRLSelParams_SetCertificateChecking failed,0),
+PKIX_ERRORENTRY(COMCRLSELPARAMSSETDATEANDTIMEFAILED,PKIX_ComCRLSelParams_SetDateAndTime failed,0),
+PKIX_ERRORENTRY(COMCRLSELPARAMSTOSTRINGFAILED,pkix_ComCRLSelParams_ToString failed,0),
+PKIX_ERRORENTRY(COMCRLSELPARAMSTOSTRINGHELPERFAILED,pkix_ComCRLSelParams_ToString_Helper failed,0),
+PKIX_ERRORENTRY(COMPARATORCALLBACKFAILED,comparator callback failed,0),
+PKIX_ERRORENTRY(CONTENTTYPENOTPKCS7MIME,Content type is not application/pkcs7-mime,0),
+PKIX_ERRORENTRY(CONTENTTYPENOTPKIXCRL,Content type is not application/pkix-crl,SEC_ERROR_BAD_HTTP_RESPONSE),
+PKIX_ERRORENTRY(COULDNOTALLOCATEMEMORY,Could not allocate memory,0),
+PKIX_ERRORENTRY(COULDNOTALLOCATENEWSTRINGOBJECT,Could not allocate new string object,0),
+PKIX_ERRORENTRY(COULDNOTAPPENDCHILDTOPARENTSPOLICYNODELIST,Could not append child to parent PolicyNode list,0),
+PKIX_ERRORENTRY(COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST,Could not append child to parent VerifyNode list,0),
+PKIX_ERRORENTRY(COULDNOTCREATEAIAMGROBJECT,Could not create AiaMgr object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEBASICCONSTRAINTSSTATEOBJECT,Could not create basic constraints state object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEBUILDPARAMSOBJECT,Could not create build params object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEBUILDRESULTOBJECT,Could not create build result object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECERTBASICCONSTRAINTSOBJECT,Could not create a CertBasicConstraints object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECERTCHAINCHECKEROBJECT,Could not create cert chain checker object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECERTNAMECONSTRAINTSOBJECT,Could not create CertNameConstraints object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECERTPOLICYINFOOBJECT,Could not create a CertPolicyInfo object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECERTPOLICYMAPOBJECT,Could not create a CertPolicyMap object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECERTPOLICYQUALIFIEROBJECT,Could not create a CertPolicyQualifier object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECERTSELECTOROBJECT,Could not create cert selector object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECERTSTOREOBJECT,Could not create CertStore object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECOLLECTIONCERTSTORECONTEXTOBJECT,Could not create CollectionCertStoreContext object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECOMMONCERTSELPARAMSOBJECT,Could not create common certsel params object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECOMMONCRLSELECTORPARAMSOBJECT,Could not create common crl selector params object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECRLENTRYOBJECT,Could not create CRLENTRY object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECRLOBJECT,Could not create CRL object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECRLSELECTOROBJECT,Could not create CRLSelector object,0),
+PKIX_ERRORENTRY(COULDNOTCREATECRLCHECKEROBJECT,Could not create CRLChecker object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEOCSPCHECKEROBJECT,Could not create OcspChecker object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEREVOCATIONMETHODOBJECT,Could not create RevocationMethod object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEDEFAULTREVOCATIONCHECKEROBJECT,Could not create DefaultRevocationChecker object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEEKUCHECKERSTATEOBJECT,Could not create EkuCheckerState object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEFORWARDBUILDERSTATEOBJECT,Could not create forwardBuilder state object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEHASHTABLEOBJECT,Could not create HashTable object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEHTTPDEFAULTCLIENTOBJECT,Could not create HttpDefaultClient object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEINFOACCESSOBJECT,Could not create InfoAccess object,0),
+PKIX_ERRORENTRY(COULDNOTCREATELDAPDEFAULTCLIENTOBJECT,Could not create LdapDefaultClient object,0),
+PKIX_ERRORENTRY(COULDNOTCREATELOCKOBJECT,Could not create lock object,0),
+PKIX_ERRORENTRY(COULDNOTCREATELOGGEROBJECT,Could not create Logger object,0),
+PKIX_ERRORENTRY(COULDNOTCREATENAMECONSTRAINTSCHECKERSTATEOBJECT,Could not create NameConstraintsCheckerState object,0),
+PKIX_ERRORENTRY(COULDNOTCREATENSSDN,Could not create NSS DN,0),
+PKIX_ERRORENTRY(COULDNOTCREATEOBJECT,Could not create object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEOBJECTSTORAGE,Could not create object storage,0),
+PKIX_ERRORENTRY(COULDNOTCREATEPOLICYCHECKERSTATEOBJECT,Could not create policyChecker state object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEPOLICYNODEOBJECT,Could not create a PolicyNode object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEPROCESSINGPARAMSOBJECT,Could not create processing params object,0),
+PKIX_ERRORENTRY(COULDNOTCREATERESOURCELIMITOBJECT,Could not create ResourceLimit object,0),
+PKIX_ERRORENTRY(COULDNOTCREATESIGNATURECHECKERSTATEOBJECT,Could not create SignatureCheckerState object,0),
+PKIX_ERRORENTRY(COULDNOTCREATESOCKETOBJECT,Could not create Socket object,0),
+PKIX_ERRORENTRY(COULDNOTCREATESTRING,Could not create string,0),
+PKIX_ERRORENTRY(COULDNOTCREATETARGETCERTCHECKERSTATEOBJECT,Could not create target cert checker state object,0),
+PKIX_ERRORENTRY(COULDNOTCREATETRUSTANCHOROBJECT,Could not create trust anchor object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEVALIDATEPARAMSOBJECT,Could not create validate params object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEVALIDATERESULTOBJECT,Could not create validate result object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEVERIFYNODEOBJECT,Could not create a VerifyNode object,0),
+PKIX_ERRORENTRY(COULDNOTCREATEX500NAMEOBJECT,Could not create X500Name object,0),
+PKIX_ERRORENTRY(COULDNOTGETFIRSTOBJECTTYPE,Could not get first object type,0),
+PKIX_ERRORENTRY(COULDNOTGETSECONDOBJECTTYPE,Could not get second object type,0),
+PKIX_ERRORENTRY(COULDNOTGETTYPEOFSECONDARGUMENT,Could not get type of second argument,0),
+PKIX_ERRORENTRY(COULDNOTLOOKUPINHASHTABLE,Could not lookup in hashtable,0),
+PKIX_ERRORENTRY(COULDNOTMALLOCNEWKEY,Could not malloc new key,0),
+PKIX_ERRORENTRY(COULDNOTTESTWHETHERKEYSEQUAL,Could not test whether keys are equal,0),
+PKIX_ERRORENTRY(CREATECERTFAILED,CreateCert failed,0),
+PKIX_ERRORENTRY(CREATECRLSELECTORDUPLICATEOBJECTFAILED,Create CRLSelector Duplicate Object failed,0),
+PKIX_ERRORENTRY(CREATEPROCESSINGPARAMSFAILED,Failed to create processing parameters,0),
+PKIX_ERRORENTRY(CRLCHECKERCREATEFAILED,pkix_CRLChecker_Create failed,0),
+PKIX_ERRORENTRY(CRLCHECKERINITIALIZEFAILED,pkix_CRLChecker_Initialize failed,0),
+PKIX_ERRORENTRY(CRLCHECKERNOLOCALCERTSTOREFOUND,No local cert store found, 0),
+PKIX_ERRORENTRY(CRLCHECKERSETSELECTORFAILED,pkix_CRLChecker_SetSelector failed,0),
+PKIX_ERRORENTRY(CRLCREATEFAILED,PKIX_PL_CRL_Create failed,0),
+PKIX_ERRORENTRY(CRLCREATETOLISTFAILED,pkix_pl_CRL_CreateToList failed,0),
+PKIX_ERRORENTRY(CRLCREATEWITHSIGNEDCRLFAILED,pkix_pl_CRL_CreateWithSignedCRL failed,0),
+PKIX_ERRORENTRY(CRLCRITICALEXTENSIONOIDSNOTPROCESSED,CRL Critical Extension OIDs not processed,0),
+PKIX_ERRORENTRY(CRLDPCREATEFAILED, Failed to create CRL DP,0),
+PKIX_ERRORENTRY(CRLENTRYCREATEFAILED,pkix_pl_CRLEntry_Create failed,0),
+PKIX_ERRORENTRY(CRLENTRYCRITICALEXTENSIONWASNOTPROCESSED,CRLEntry Critical Extension was not processed,0),
+PKIX_ERRORENTRY(CRLENTRYEXTENSIONSEQUALSFAILED,PKIX_PL_CRLEntry_Extensions_Equals failed,0),
+PKIX_ERRORENTRY(CRLENTRYEXTENSIONSHASHCODEFAILED,pkix_pl_CRLEntry_Extensions_Hashcode failed,0),
+PKIX_ERRORENTRY(CRLENTRYGETCRITICALEXTENSIONOIDSFAILED,PKIX_PL_CRLEntry_GetCriticalExtensionOIDs failed,0),
+PKIX_ERRORENTRY(CRLENTRYGETCRLENTRYREASONCODEFAILED,PKIX_PL_CRLEntry_GetCRLEntryReasonCode failed,0),
+PKIX_ERRORENTRY(CRLENTRYTOSTRINGHELPERFAILED,pkix_pl_CRLEntry_ToString_Helper failed,0),
+PKIX_ERRORENTRY(CRLGETCRITICALEXTENSIONOIDSFAILED,PKIX_PL_CRL_GetCriticalExtensionOIDs failed,0),
+PKIX_ERRORENTRY(CRLGETCRLENTRIESFAILED,pkix_pl_CRL_GetCRLEntries failed,0),
+PKIX_ERRORENTRY(CRLGETCRLENTRYFORSERIALNUMBERFAILED,PKIX_PL_CRL_GetCRLEntryForSerialNumber failed,0),
+PKIX_ERRORENTRY(CRLGETCRLNUMBERFAILED,PKIX_PL_CRL_GetCRLNumber failed,0),
+PKIX_ERRORENTRY(CRLGETISSUERFAILED,PKIX_PL_CRL_GetIssuer failed,0),
+PKIX_ERRORENTRY(CRLGETPARTITIONEDFLAGFAILED,PKIX_PL_CRL_IsPartitioned failed,0),
+PKIX_ERRORENTRY(CRLGETSIGNATUREALGIDFAILED,pkix_pl_CRL_GetSignatureAlgId failed,0),
+PKIX_ERRORENTRY(CRLGETVERSIONFAILED,pkix_pl_CRL_GetVersion failed,0),
+PKIX_ERRORENTRY(CRLISSUECERTEXPIRED,CRL issue cert has expired,0),
+PKIX_ERRORENTRY(CRLMAXNUMBERRANGEMATCHFAILED,CRL MaxNumber Range Match Failed,0),
+PKIX_ERRORENTRY(CRLSELECTORCREATEFAILED,PKIX_CRLSelector_Create failed,0),
+PKIX_ERRORENTRY(CRLSELECTORFAILED,crlSelector failed,0),
+PKIX_ERRORENTRY(CRLSELECTORGETCOMCERTSELPARAMSFAILED,PKIX_CRLSelector_GetComCertSelParams failed,0),
+PKIX_ERRORENTRY(CRLSELECTORGETMATCHCALLBACKFAILED,PKIX_CRLSelector_GetMatchCallback failed,0),
+PKIX_ERRORENTRY(CRLSELECTORMATCHCALLBACKFAILED,PKIX_CRLSelector_MatchCallback failed,0),
+PKIX_ERRORENTRY(CRLSELECTORMATCHFAILED,crlSelectorMatch failed,0),
+PKIX_ERRORENTRY(CRLSELECTORSELECTFAILED,pkix_CRLSelector_Select failed,0),
+PKIX_ERRORENTRY(CRLSELECTORSETCOMMONCRLSELECTORPARAMSFAILED,PKIX_CRLSelector_SetCommonCRLSelectorParams failed,0),
+PKIX_ERRORENTRY(CRLSELECTORTOSTRINGHELPERFAILED,pkix_CRLSelector_ToString_Helper failed,0),
+PKIX_ERRORENTRY(CRLTOSTRINGHELPERFAILED,pkix_pl_CRL_ToString_Helper failed,0),
+PKIX_ERRORENTRY(CRLVERIFYUPDATETIMEFAILED,pkix_pl_CRL_VerifyUpdateTime failed,0),
+PKIX_ERRORENTRY(DATECREATECURRENTOFFBYSECONDSFAILED,PKIX_PL_Date_Create_CurrentOffBySeconds failed,0),
+PKIX_ERRORENTRY(DATECREATEFROMPRTIMEFAILED,pkix_pl_Date_CreateFromPRTime failed,0),
+PKIX_ERRORENTRY(DATECREATEUTCTIMEFAILED,PKIX_PL_Date_Create_UTCTime failed,0),
+PKIX_ERRORENTRY(DATEDERTIMETOPRTIMEFAILED,Fail to convert encoded time to PRTime,0),
+PKIX_ERRORENTRY(DATEEQUALSFAILED,PKIX_PL_Date_Equals failed,0),
+PKIX_ERRORENTRY(DATEGETPRTIMEFAILED,pkix_pl_Date_GetPRTime failed,0),
+PKIX_ERRORENTRY(DATEHASHCODEFAILED,PKIX_PL_Date_Hashcode failed,0),
+PKIX_ERRORENTRY(DATETOSTRINGFAILED,PKIX_Date_ToString failed,0),
+PKIX_ERRORENTRY(DATETOSTRINGHELPERFAILED,pkix_pl_Date_ToString_Helper failed,0),
+PKIX_ERRORENTRY(DECIPHERONLYKEYUSAGENOTSUPPORTED,decipherOnly key usage not supported,0),
+PKIX_ERRORENTRY(DECODINGCERTNAMECONSTRAINTSFAILED,Decoding Cert NameConstraints failed,0),
+PKIX_ERRORENTRY(DEFAULTREVCHECKERCREATEFAILED,pkix_DefaultRevChecker_Create failed,0),
+PKIX_ERRORENTRY(DEFAULTREVCHECKERINITIALIZEFAILED,pkix_DefaultRevChecker_Initialize failed,0),
+PKIX_ERRORENTRY(DEPTHWOULDEXCEEDRESOURCELIMITS,Depth would exceed Resource Limits,SEC_ERROR_OUT_OF_SEARCH_LIMITS),
+PKIX_ERRORENTRY(DERASCIITOTIMEFAILED,DER_AsciiToTime failed,0),
+PKIX_ERRORENTRY(DERDECODETIMECHOICEFAILED,DER_DecodeTimeChoice failed,0),
+PKIX_ERRORENTRY(DERDECODETIMECHOICEFORLASTUPDATEFAILED,DER_DecodeTimeChoice for lastUpdate failed,0),
+PKIX_ERRORENTRY(DERDECODETIMECHOICEFORNEXTUPDATEFAILED,DER_DecodeTimeChoice for nextUpdate failed,0),
+PKIX_ERRORENTRY(DERENCODETIMECHOICEFAILED,DER_EncodeTimeChoice failed,0),
+PKIX_ERRORENTRY(DERGENERALIZEDDAYTOASCIIFAILED,DER_GeneralizedDayToAscii failed,0),
+PKIX_ERRORENTRY(DERTIMETOUTCTIMEFAILED,DER_TimeToUTCTime failed,0),
+PKIX_ERRORENTRY(DERUTCTIMETOASCIIFAILED,DER_UTCTimeToAscii failed,0),
+PKIX_ERRORENTRY(DESTROYSPKIFAILED,pkix_pl_DestroySPKI failed,0),
+PKIX_ERRORENTRY(DIRECTORYNAMECREATEFAILED,pkix_pl_DirectoryName_Create failed,0),
+PKIX_ERRORENTRY(DUPLICATEIMMUTABLEFAILED,pkix_duplicateImmutable failed,0),
+PKIX_ERRORENTRY(CANNOTSORTIMMUTABLELIST,pkix_List_BubbleSort can not sort immutable list,0),
+PKIX_ERRORENTRY(EKUCHECKERGETREQUIREDEKUFAILED,pkix_pl_EkuChecker_GetRequiredEku failed,0),
+PKIX_ERRORENTRY(EKUCHECKERINITIALIZEFAILED,PKIX_PL_EkuChecker_Initialize failed,0),
+PKIX_ERRORENTRY(EKUCHECKERSTATECREATEFAILED,pkix_pl_EkuCheckerState_Create failed,0),
+PKIX_ERRORENTRY(ENABLEREVOCATIONWITHOUTCERTSTORE,Enable Revocation without CertStore,0),
+PKIX_ERRORENTRY(ERRORALLOCATINGMONITORLOCK,Error Allocating MonitorLock,0),
+PKIX_ERRORENTRY(ERRORALLOCATINGRWLOCK,Error Allocating RWLock,0),
+PKIX_ERRORENTRY(ERRORCREATINGCHILDSTRING,Error creating child string,0),
+PKIX_ERRORENTRY(ERRORCREATINGFORMATSTRING,Error creating format string,0),
+PKIX_ERRORENTRY(ERRORCREATINGINDENTSTRING,Error creating indent string,0),
+PKIX_ERRORENTRY(ERRORCREATINGITEMSTRING,Error creating item string,0),
+PKIX_ERRORENTRY(ERRORCREATINGLISTITEM,Error Creating List Item,0),
+PKIX_ERRORENTRY(ERRORCREATINGSUBTREESTRING,Error creating subtree string,0),
+PKIX_ERRORENTRY(ERRORCREATINGTABLELOCK,Error creating table lock,0),
+PKIX_ERRORENTRY(ERRORFINDINGORPROCESSINGURI,Error finding or processing URI,0),
+PKIX_ERRORENTRY(ERRORGETTINGCAUSESTRING,Error getting cause string,0),
+PKIX_ERRORENTRY(ERRORGETTINGCLASSTABLEENTRY,Error getting class table entry,0),
+PKIX_ERRORENTRY(ERRORGETTINGHASHCODE,Error getting hashcode,0),
+PKIX_ERRORENTRY(ERRORGETTINGSECONDOBJECTTYPE,Error getting second object type,0),
+PKIX_ERRORENTRY(ERRORINBYTEARRAYHASHCODE,Error in PKIX_PL_ByteArray_Hashcode,0),
+PKIX_ERRORENTRY(ERRORINGETTINGDESTRUCTOR,Error in getting destructor,0),
+PKIX_ERRORENTRY(ERRORINHASH,Error in pkix_hash,0),
+PKIX_ERRORENTRY(ERRORINLISTHASHCODE,Error in PKIX_List_Hashcode,0),
+PKIX_ERRORENTRY(ERRORINOBJECTDEFINEDESTROY,Error in object-defined destroy callback,0),
+PKIX_ERRORENTRY(ERRORINOIDHASHCODE,Error in PKIX_PL_OID_Hashcode,0),
+PKIX_ERRORENTRY(ERRORINRECURSIVEEQUALSCALL,Error in recursive equals call,0),
+PKIX_ERRORENTRY(ERRORINSINGLEPOLICYNODETOSTRING,Error in pkix_SinglePolicyNode_ToString,0),
+PKIX_ERRORENTRY(ERRORINSINGLEVERIFYNODETOSTRING,Error in pkix_SingleVerifyNode_ToString,0),
+PKIX_ERRORENTRY(ERRORINSPRINTF,Error in PKIX_PL_Sprintf,0),
+PKIX_ERRORENTRY(ERRORINSTRINGCREATE,Error in PKIX_PL_String_Create,0),
+PKIX_ERRORENTRY(ERRORLOCKINGOBJECT,Error locking object,0),
+PKIX_ERRORENTRY(ERRORTOSTRINGFAILED,PKIX_Error_ToString failed,0),
+PKIX_ERRORENTRY(ERRORTRAVERSINGBUCKET,Error traversing bucket,0),
+PKIX_ERRORENTRY(ERRORUNLOCKINGMUTEX,Error unlocking mutex,0),
+PKIX_ERRORENTRY(ERRORUNLOCKINGOBJECT,Error unlocking object,0),
+PKIX_ERRORENTRY(ESCASCIITOUTF16FAILED,pkix_EscASCII_to_UTF16 failed,0),
+PKIX_ERRORENTRY(EXPIRATIONCHECKERINITIALIZEFAILED,pkix_ExpirationChecker_Initialize failed,0),
+PKIX_ERRORENTRY(EXTENDEDKEYUSAGECHECKINGFAILED,Extended Key Usage Checking failed,SEC_ERROR_INADEQUATE_CERT_TYPE),
+PKIX_ERRORENTRY(EXTENDEDKEYUSAGEUSEROBJECT,Extended Key Usage User Object,0),
+PKIX_ERRORENTRY(EXTRACTPARAMETERSFAILED,pkix_ExtractParameters failed,0),
+PKIX_ERRORENTRY(FAILEDINENCODINGSEARCHREQUEST,failed in encoding searchRequest,SEC_ERROR_FAILED_TO_ENCODE_DATA),
+PKIX_ERRORENTRY(FAILEDTODECODECRL, failed to decode CRL,SEC_ERROR_BAD_DER),
+PKIX_ERRORENTRY(FAILEDTOGETNSSTRUSTANCHORS,Failed to get nss trusted roots,0),
+PKIX_ERRORENTRY(FAILEDTOGETTRUST, failed to get trust from the cert,0),
+PKIX_ERRORENTRY(FAILTOREMOVEDPFROMLIST, failed to remove dp from the list,0),
+PKIX_ERRORENTRY(FAILTOSELECTCERTSFROMANCHORS,failed to select certs from anchors,0),
+PKIX_ERRORENTRY(FAILUREHASHINGCERT,Failure hashing Cert,0),
+PKIX_ERRORENTRY(FAILUREHASHINGERROR,Failure hashing Error,0),
+PKIX_ERRORENTRY(FAILUREHASHINGLISTEXPECTEDPOLICYSET,Failure hashing PKIX_List expectedPolicySet,0),
+PKIX_ERRORENTRY(FAILUREHASHINGLISTQUALIFIERSET,Failure hashing PKIX_List qualifierSet,0),
+PKIX_ERRORENTRY(FAILUREHASHINGOIDVALIDPOLICY,Failure hashing PKIX_PL_OID validPolicy,0),
+PKIX_ERRORENTRY(FANOUTEXCEEDSRESOURCELIMITS,Fanout exceeds Resource Limits,0),
+PKIX_ERRORENTRY(FETCHINGCACHEDCRLFAILED,Fetching Cached CRLfailed,0),
+PKIX_ERRORENTRY(FILLINPROCESSINGPARAMSFAILED,Fail to fill in parameters,0),
+PKIX_ERRORENTRY(FILLINRETURNRESULTSFAILED,Fail to fill in return results,0),
+PKIX_ERRORENTRY(FIRSTARGUMENTNOTBYTEARRAY,FirstObject is not a ByteArray,0),
+PKIX_ERRORENTRY(FIRSTARGUMENTNOTCERTBASICCONSTRAINTSOBJECT,First argument is not a CertBasicConstraints Object,0),
+PKIX_ERRORENTRY(FIRSTDOUBLEHEXMUSTNOTBE00,First DoubleHex MUST NOT be 00,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(FIRSTFIELDMUSTBEBETWEEN02,First field must be between 0-2,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(FIRSTOBJARGUMENTNOTANOCSPRESPONSE,FirstObject is not an OcspResponse,0),
+PKIX_ERRORENTRY(FIRSTOBJARGUMENTNOTLDAPREQUEST,FirstObject is not a LdapRequest,0),
+PKIX_ERRORENTRY(FIRSTOBJARGUMENTNOTLDAPRESPONSE,FirstObject is not a LdapResponse,0),
+PKIX_ERRORENTRY(FIRSTOBJARGUMENTNOTOCSPREQUEST,FirstObject is not a OcspRequest,0),
+PKIX_ERRORENTRY(FIRSTOBJECTARGUMENTNOTANX500NAME,FirstObject is not an X500Name,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTANERROROBJECT,FirstObject is not an Error object,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTBIGINT,FirstObject not a BigInt,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTBUILDPARAMS,FirstObject is not a BuildParams,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTBUILDRESULT,FirstObject is not a BuildResult,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTCERT,FirstObject is not a Cert,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTCERTBASICCONSTRAINTS,FirstObject is not a CertBasicConstraints,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTCERTNAMECONSTRAINTS,FirstObject is not a CertNameConstraints,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTCERTPOLICYINFO,FirstObject is not a CertPolicyInfo,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTCERTPOLICYMAP,FirstObject is not a CertPolicyMap,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTCERTPOLICYQUALIFIER,FirstObject is not a CertPolicyQualifier,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTCOMCRLSELPARAMS,FirstObject is not a ComCRLSelParams,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTCRL,FirstObject is not a CRL,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTCRLENTRY,FirstObject is not a CRLEntry,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTCRLSELECTOR,FirstObject is not a CRLSelector,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTDATE,FirstObject is not a Date,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTERROR,FirstObject is not an Error,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTGENERALNAME,FirstObject is not a GeneralName,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTINFOACCESS,FirstObject is not a InfoAccess,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTLIST,FirstObject is not a List,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTLOGGER,FirstObject is not a Logger,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTPOLICYNODE,FirstObject is not a PolicyNode,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTPROCESSINGPARAMS,FirstObject is not a ProcessingParams,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTPUBLICKEY,FirstObject is not a PublicKey,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTRESOURCELIMITS,FirstObject is not a ResourceLimits,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTSTRING,FirstObject is not a String,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTTRUSTANCHOR,FirstObject is not a TrustAnchor,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTVALIDATEPARAMS,FirstObject is not a ValidateParams,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTVALIDATERESULT,FirstObject is not a ValidateResult,0),
+PKIX_ERRORENTRY(FIRSTOBJECTNOTVERIFYNODE,FirstObject is not a VerifyNode,0),
+PKIX_ERRORENTRY(FIRSTPUBKEYTYPENULLKEY,firstPubKeyType is nullKey,0),
+PKIX_ERRORENTRY(FUNCTIONMUSTNOTBEUSED,Function MUST not be used,SEC_ERROR_LIBPKIX_INTERNAL),
+PKIX_ERRORENTRY(FORWARDBUILDERSTATEDUMPSTATEFAILED,pkix_ForwardBuilderState_DumpState failed,0),
+PKIX_ERRORENTRY(FORWARDBUILDERSTATEISIOPENDINGFAILED,pkix_ForwardBuilderState_IsIOPending failed,0),
+PKIX_ERRORENTRY(FORWARDBUILDSTATECREATEFAILED,pkix_ForwardBuildState_Create failed,0),
+PKIX_ERRORENTRY(FREEFAILED,PKIX_PL_Free failed,0),
+PKIX_ERRORENTRY(GENERALNAMECREATEFAILED,pkix_pl_GeneralName_Create failed,0),
+PKIX_ERRORENTRY(GENERALNAMEGETNSSGENERALNAMEFAILED,pkix_pl_GeneralName_GetNssGeneralName failed,0),
+PKIX_ERRORENTRY(GENERALNAMESTRINGMISSINGDOUBLESLASH,GeneralName string missing double slash,SEC_ERROR_BAD_INFO_ACCESS_LOCATION),
+PKIX_ERRORENTRY(GENERALNAMESTRINGMISSINGLOCATIONTYPE,GeneralName string missing location type,SEC_ERROR_BAD_INFO_ACCESS_LOCATION),
+PKIX_ERRORENTRY(GENERALNAMESTRINGMISSINGSERVERSITE,GeneralName string missing server-site,SEC_ERROR_BAD_INFO_ACCESS_LOCATION),
+PKIX_ERRORENTRY(GENERALNAMETOSTRINGFAILED,pkix_pl_GeneralName_ToString failed,0),
+PKIX_ERRORENTRY(GENERALNAMETOSTRINGHELPERFAILED,pkix_pl_GeneralName_ToString_Helper failed,0),
+PKIX_ERRORENTRY(GENERICCLIENTNOTANLDAPDEFAULTCLIENT,genericClient is not an LdapDefaultClient,0),
+PKIX_ERRORENTRY(GETATTRIBUTESCALLEDFORNONENTRYMESSAGE,GetAttributes called for non-Entry message,SEC_ERROR_BAD_LDAP_RESPONSE),
+PKIX_ERRORENTRY(GETCERTSFAILED,getCerts failed,0),
+PKIX_ERRORENTRY(GETCRITICALEXTENSIONOIDSFAILED,pkix_GetCriticalExtensionOIDs failed,0),
+PKIX_ERRORENTRY(GETCRLSFAILED,getCrls failed,0),
+PKIX_ERRORENTRY(GETOIDTOKENFAILED,pkix_pl_getOIDToken failed,0),
+PKIX_ERRORENTRY(GETPKIXERRORCODEFAILED,Get PKIX error code failed,0),
+PKIX_ERRORENTRY(GETREQCERTIFICATEUSAGESFAILED,Fail to get required certificate usages,0),
+PKIX_ERRORENTRY(GETRESULTCODECALLEDFORNONRESULTMESSAGE,GetResultCode called for non-Result message,SEC_ERROR_BAD_LDAP_RESPONSE),
+PKIX_ERRORENTRY(GETRETCERTIFICATEUSAGESFAILED,Fail to get returned certificate usages,0),
+PKIX_ERRORENTRY(GETTRUSTEDCERTLISTFAILED,Fail to get trusted cert list,0),
+PKIX_ERRORENTRY(HASHFAILED,pkix_hash failed,0),
+PKIX_ERRORENTRY(HASHTABLEADDFAILED,PKIX_PL_HashTable_Add failed,0),
+PKIX_ERRORENTRY(HASHTABLECREATEFAILED,PKIX_PL_HashTable_Create failed,0),
+PKIX_ERRORENTRY(HASHTABLELOOKUPFAILED,PKIX_PL_HashTable_Lookup failed,0),
+PKIX_ERRORENTRY(HASHTABLEREMOVEFAILED,PKIX_PL_HashTable_Remove failed,0),
+PKIX_ERRORENTRY(HELPERBYTES2ASCIIFAILED,pkix_pl_helperBytes2Ascii failed,0),
+PKIX_ERRORENTRY(HELPERBYTES2ASCIINUMTOKENSZERO,pkix_pl_helperBytes2Ascii: numTokens is zero,0),
+PKIX_ERRORENTRY(HTTPCERTSTORECREATEREQUESTSESSIONFAILED,pkix_pl_HttpCertStore_CreateRequestSession failed,0),
+PKIX_ERRORENTRY(HTTPCERTSTORECREATEWITHASCIINAMEFAILED,PKIX_PL_HttpCertStore_CreateWithAsciiName failed,0),
+PKIX_ERRORENTRY(HTTPCERTSTOREDECODECERTPACKAGEFAILED,pkix_pl_HttpCertStore_DecodeCertPackage failed,0),
+PKIX_ERRORENTRY(HTTPCERTSTOREFINDSOCKETCONNECTIONFAILED,pkix_HttpCertStore_FindSocketConnection failed,0),
+PKIX_ERRORENTRY(HTTPCERTSTOREPROCESSCERTRESPONSEFAILED,pkix_pl_HttpCertStore_ProcessCertResponse failed,0),
+PKIX_ERRORENTRY(HTTPCERTSTOREPROCESSCRLRESPONSEFAILED,pkix_pl_HttpCertStore_ProcessCrlResponse failed,0),
+PKIX_ERRORENTRY(HTTPCLIENTCREATESESSIONFAILED,HttpClient->CreateSession failed,0),
+PKIX_ERRORENTRY(HTTPCLIENTININVALIDSTATE,HttpClient in invalid state,0),
+PKIX_ERRORENTRY(HTTPDEFAULTCLIENTCONNECTCONTINUEFAILED,pkix_pl_HttpDefaultClient_ConnectContinue failed,0),
+PKIX_ERRORENTRY(HTTPDEFAULTCLIENTCREATEFAILED,pkix_pl_HttpDefaultClient_Create failed,0),
+PKIX_ERRORENTRY(HTTPDEFAULTCLIENTDISPATCHFAILED,pkix_pl_HttpDefaultClient_Dispatch failed,0),
+PKIX_ERRORENTRY(HTTPDEFAULTCLIENTHDRCHECKCOMPLETEFAILED,pkix_pl_HttpDefaultClient_HdrCheckComplete failed,0),
+PKIX_ERRORENTRY(HTTPDEFAULTCLIENTINILLEGALSTATE,HttpDefaultClient in illegal state,0),
+PKIX_ERRORENTRY(HTTPDEFAULTCLIENTRECVBODYCONTINUEFAILED,pkix_pl_HttpDefaultClient_RecvBodyContinue failed,0),
+PKIX_ERRORENTRY(HTTPDEFAULTCLIENTRECVBODYFAILED,pkix_pl_HttpDefaultClient_RecvBody failed,0),
+PKIX_ERRORENTRY(HTTPDEFAULTCLIENTRECVHDRCONTINUEFAILED,pkix_pl_HttpDefaultClient_RecvHdrContinue failed,0),
+PKIX_ERRORENTRY(HTTPDEFAULTCLIENTRECVHDRFAILED,pkix_pl_HttpDefaultClient_RecvHdr failed,0),
+PKIX_ERRORENTRY(HTTPDEFAULTCLIENTSENDCONTINUEFAILED,pkix_pl_HttpDefaultClient_SendContinue failed,0),
+PKIX_ERRORENTRY(HTTPDEFAULTCLIENTSENDFAILED,pkix_pl_HttpDefaultClient_Send failed,0),
+PKIX_ERRORENTRY(HTTPSERVERERROR,HTTP Server Error,0),
+PKIX_ERRORENTRY(ILLEGALCHARACTERINESCAPEDASCII,Illegal character in Escaped ASCII String,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(ILLEGALCHARACTERINOID,Illegal character in OID,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(ILLEGALDOTINOID,Illegal period in OID,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(ILLEGALSURROGATEPAIR,Illegal surrogate pair in EscapedASCII,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(ILLEGALUNICODECHARACTER,Illegal Unicode character in EscapedASCII,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(ILLEGALUSEOFAMP,Illegal use of ampersand character,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(IMPOSSIBLECRITERIONFORCRLQUERY,Impossible criterion for Crl Query,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(INDEXOUTOFBOUNDS,Index out of bounds,SEC_ERROR_LIBPKIX_INTERNAL),
+PKIX_ERRORENTRY(INESCAPEDASCII,in EscapedASCII,0),
+PKIX_ERRORENTRY(INFOACCESSCREATEFAILED,pkix_pl_InfoAccess_Create failed,0),
+PKIX_ERRORENTRY(INFOACCESSCREATELISTFAILED,pkix_pl_InfoAccess_CreateList failed,0),
+PKIX_ERRORENTRY(INFOACCESSGETLOCATIONFAILED,PKIX_PL_InfoAccess_GetLocation failed,0),
+PKIX_ERRORENTRY(INFOACCESSGETLOCATIONTYPEFAILED,PKIX_PL_InfoAccess_GetLocationType failed,0),
+PKIX_ERRORENTRY(INFOACCESSGETMETHODFAILED,PKIX_PL_InfoAccess_GetMethod failed,0),
+#ifndef NSS_PKIX_NO_LDAP
+PKIX_ERRORENTRY(INFOACCESSPARSELOCATIONFAILED,pkix_pl_InfoAccess_ParseLocation failed,SEC_ERROR_BAD_INFO_ACCESS_LOCATION),
+#endif
+PKIX_ERRORENTRY(INFOACCESSPARSETOKENSFAILED,pkix_pl_InfoAccess_ParseTokens failed,SEC_ERROR_BAD_INFO_ACCESS_LOCATION),
+PKIX_ERRORENTRY(INITIALIZECHECKERSFAILED,pkix_InitializeCheckers failed,0),
+PKIX_ERRORENTRY(INITIALIZEFAILED,PKIX_PL_Initialize failed,0),
+PKIX_ERRORENTRY(INPUTLISTMUSTBEHEADER,Input List must be header,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(INPUTLISTSMUSTBELISTHEADERS,Input Lists must be list headers,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(INSUFFICIENTCRITERIAFORCERTQUERY,Insufficient criteria for Cert query,0),
+PKIX_ERRORENTRY(INSUFFICIENTCRITERIAFORCRLQUERY,Insufficient criteria for Crl Query,0),
+PKIX_ERRORENTRY(INTRUSTEDCERT,in Trusted Cert,0),
+PKIX_ERRORENTRY(INVALIDCHARACTERINBIGINT,Invalid character in BigInt,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(INVALIDDERENCODINGFOROID,Invalid DER-encoding for OID,0),
+PKIX_ERRORENTRY(INVALIDENCODINGOIDTOKENVALUETOOBIG,Invalid encoding: OID token value too big,0),
+PKIX_ERRORENTRY(INVALIDPOLICYMAPPINGINCLUDESANYPOLICY,Invalid policyMapping includes anyPolicy,SEC_ERROR_INVALID_POLICY_MAPPING),
+PKIX_ERRORENTRY(INVALIDREVOCATIONMETHOD,Invalid revocation method,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(INVALIDSIGNINGCERTINOCSPRESPONSE,Invalid signing Cert in OCSP response,SEC_ERROR_OCSP_INVALID_SIGNING_CERT),
+PKIX_ERRORENTRY(INVALIDSTATUS,INVALID STATUS,0),
+PKIX_ERRORENTRY(INVALIDSTORETYPEFORSETTINGCONFIGDIR,Invalid Store type for Setting ConfigDir,0),
+PKIX_ERRORENTRY(IPADDRBYTES2ASCIIDATALENGTHZERO,pkix_pl_ipAddrBytes2Ascii: data length is zero,0),
+PKIX_ERRORENTRY(IPADDRBYTES2ASCIIFAILED,pkix_pl_ipAddrBytes2Ascii failed,0),
+PKIX_ERRORENTRY(ISCERTSELFISSUEDFAILED,pkix_IsCertSelfIssued failed,0),
+PKIX_ERRORENTRY(ISCERTSELFISSUEFAILED,pkix_IsCertSelfIssue failed,0),
+PKIX_ERRORENTRY(KEYUSAGEKEYCERTSIGNBITNOTON,Validation failed: KeyUsage KeyCertSign bit is not on,SEC_ERROR_CA_CERT_INVALID),
+PKIX_ERRORENTRY(KEYUSAGEKEYCRLSIGNBITNOTON,Validation failed: KeyUsage CRLSign bit is not on,0),
+PKIX_ERRORENTRY(LDAPCERTSTOREBUILDCERTLISTFAILED,pkix_pl_LdapCertStore_BuildCertList failed,0),
+PKIX_ERRORENTRY(LDAPCERTSTOREBUILDCRLLISTFAILED,pkix_pl_LdapCertStore_BuildCrlList failed,0),
+PKIX_ERRORENTRY(LDAPCERTSTOREDECODECROSSCERTPAIRFAILED,pkix_pl_LdapCertStore_DecodeCrossCertPair failed,0),
+PKIX_ERRORENTRY(LDAPCERTSTOREDESTROYAVALISTFAILED,pkix_pl_LdapCertStore_DestroyAVAList failed,0),
+PKIX_ERRORENTRY(LDAPCERTSTOREINILLEGALSTATE,LDAP CertStore in illegal state,0),
+PKIX_ERRORENTRY(LDAPCERTSTOREMAKENAMEAVALISTFAILED,pkix_pl_LdapCertStore_MakeNameAVAList failed,0),
+PKIX_ERRORENTRY(LDAPCLIENTINITIATEREQUESTFAILED,PKIX_PL_LdapClient_InitiateRequest failed,0),
+PKIX_ERRORENTRY(LDAPCLIENTRESUMEREQUESTFAILED,PKIX_PL_LdapClient_ResumeRequest failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTABANDONCONTINUEFAILED,pkix_pl_LdapDefaultClient_AbandonContinue failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTBINDCONTINUEFAILED,pkix_pl_LdapDefaultClient_BindContinue failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTBINDFAILED,pkix_pl_LdapDefaultClient_Bind failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTBINDRESPONSECONTINUEFAILED,pkix_pl_LdapDefaultClient_BindResponseContinue failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTBINDRESPONSEFAILED,pkix_pl_LdapDefaultClient_BindResponse failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTCONNECTCONTINUEFAILED,pkix_pl_LdapDefaultClient_ConnectContinue failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTCREATEBYNAMEFAILED,PKIX_PL_LdapDefaultClient_CreateByName failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTCREATEHELPERFAILED,pkix_pl_LdapDefaultClient_CreateHelper failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTDECODEBINDRESPONSEFAILED,pkix_pl_LdapDefaultClient_DecodeBindResponse failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTDISPATCHFAILED,pkix_pl_LdapDefaultClient_Dispatch failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTINILLEGALSTATE,LDAP DefaultClient in illegal state,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTMAKEABANDONFAILED,pkix_pl_LdapDefaultClient_MakeAbandon failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTMAKEANDFILTERFAILED,pkix_pl_LdapDefaultClient_MakeAndFilter failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTMAKEBINDFAILED,pkix_pl_LdapDefaultClient_MakeBind failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTMAKEUNBINDFAILED,pkix_pl_LdapDefaultClient_MakeUnbind failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTRECVCHECKCOMPLETEFAILED,pkix_pl_LdapDefaultClient_RecvCheckComplete failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTRECVCONTINUEFAILED,pkix_pl_LdapDefaultClient_RecvContinue failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTRECVFAILED,pkix_pl_LdapDefaultClient_Recv failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTRECVINITIALFAILED,pkix_pl_LdapDefaultClient_RecvInitial failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTRECVNONINITIALFAILED,pkix_pl_LdapDefaultClient_RecvNonInitial failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTSENDCONTINUEFAILED,pkix_pl_LdapDefaultClient_SendContinue failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTSENDFAILED,pkix_pl_LdapDefaultClient_Send failed,0),
+PKIX_ERRORENTRY(LDAPDEFAULTCLIENTVERIFYBINDRESPONSEFAILED,pkix_pl_LdapDefaultClient_VerifyBindResponse failed,0),
+PKIX_ERRORENTRY(LDAPREQUESTATTRSTRINGTOBITFAILED,pkix_pl_LdapRequest_AttrStringToBit failed,0),
+PKIX_ERRORENTRY(LDAPREQUESTATTRTYPETOBITFAILED,pkix_pl_LdapRequest_AttrTypeToBit failed,0),
+PKIX_ERRORENTRY(LDAPREQUESTCREATEFAILED,pkix_pl_LdapRequest_Create failed,0),
+PKIX_ERRORENTRY(LDAPREQUESTENCODEATTRSFAILED,pkix_pl_LdapRequest_EncodeAttrs failed,0),
+PKIX_ERRORENTRY(LDAPREQUESTGETENCODEDFAILED,pkix_pl_LdapRequest_GetEncoded failed,0),
+PKIX_ERRORENTRY(LDAPRESPONSEAPPENDFAILED,pkix_pl_LdapResponse_Append failed,0),
+PKIX_ERRORENTRY(LDAPRESPONSECREATEFAILED,pkix_pl_LdapResponseCreate failed,0),
+PKIX_ERRORENTRY(LDAPRESPONSEDECODEFAILED,pkix_pl_LDAPResponse_Decode failed,0),
+PKIX_ERRORENTRY(LDAPRESPONSEGETCAPACITYFAILED,pkix_pl_LdapResponse_GetCapacity failed,0),
+PKIX_ERRORENTRY(LDAPRESPONSEGETMESSAGEFAILED,pkix_pl_LdapResponse_GetMessage failed,0),
+PKIX_ERRORENTRY(LDAPRESPONSEGETMESSAGETYPEFAILED,pkix_pl_LdapResponse_GetMessageType failed,0),
+PKIX_ERRORENTRY(LDAPRESPONSEGETRESULTCODEFAILED,pkix_pl_LdapResponse_GetResultCode failed,0),
+PKIX_ERRORENTRY(LDAPRESPONSEISCOMPLETEFAILED,pkix_pl_LdapResponse_IsComplete failed,0),
+PKIX_ERRORENTRY(LISTAPPENDFAILED,PKIX_List_Append failed,0),
+PKIX_ERRORENTRY(LISTAPPENDITEMFAILED,PKIX_List_AppendItem failed,0),
+PKIX_ERRORENTRY(LISTAPPENDLISTFAILED,pkix_List_AppendList failed,0),
+PKIX_ERRORENTRY(LISTAPPENDUNIQUEFAILED,pkix_List_AppendUnique failed,0),
+PKIX_ERRORENTRY(LISTBUBBLESORTFAILED,pkix_List_BubbleSort failed,0),
+PKIX_ERRORENTRY(LISTCONTAINSFAILED,pkix_List_Contains failed,0),
+PKIX_ERRORENTRY(LISTCREATEFAILED,PKIX_List_Create failed,0),
+PKIX_ERRORENTRY(LISTCREATEINTERNALFAILED,pkix_List_Create_Internal failed,0),
+PKIX_ERRORENTRY(LISTDELETEITEMFAILED,PKIX_List_DeleteItem failed,0),
+PKIX_ERRORENTRY(LISTDUPLICATEFAILED,pkix_List_Duplicate failed,0),
+PKIX_ERRORENTRY(LISTEQUALSFAILED,PKIX_List_Equals failed,0),
+PKIX_ERRORENTRY(LISTGETELEMENTFAILED,pkix_List_GetElement failed,0),
+PKIX_ERRORENTRY(LISTGETITEMFAILED,PKIX_List_GetItem failed,0),
+PKIX_ERRORENTRY(LISTGETLENGTHFAILED,PKIX_List_GetLength failed,0),
+PKIX_ERRORENTRY(LISTHASHCODEFAILED,pkix_List_Hashcode failed,0),
+PKIX_ERRORENTRY(LISTINSERTITEMFAILED,PKIX_List_InsertItem failed,0),
+PKIX_ERRORENTRY(LISTISEMPTYFAILED,PKIX_List_IsEmpty failed,0),
+PKIX_ERRORENTRY(LISTMERGEFAILED,pkix_List_MergeList failed,0),
+PKIX_ERRORENTRY(LISTQUICKSORTFAILED,pkix_List_QuickSort failed,0),
+PKIX_ERRORENTRY(LISTREMOVEFAILED,pkix_List_Remove failed,0),
+PKIX_ERRORENTRY(LISTREMOVEITEMSFAILED,pkix_List_RemoveItems failed,0),
+PKIX_ERRORENTRY(LISTREVERSELISTFAILED,PKIX_List_ReverseList failed,0),
+PKIX_ERRORENTRY(LISTSETIMMUTABLEFAILED,PKIX_List_SetImmutable failed,0),
+PKIX_ERRORENTRY(LISTSETITEMFAILED,PKIX_List_SetItem failed,0),
+PKIX_ERRORENTRY(LISTTOSTRINGFAILED,pkix_List_ToString failed,0),
+PKIX_ERRORENTRY(LISTTOSTRINGHELPERFAILED,pkix_List_ToString Helper failed,0),
+PKIX_ERRORENTRY(LOCATIONSTRINGNOTPROPERLYTERMINATED,Location string not properly terminated,0),
+PKIX_ERRORENTRY(LOCKHASNONZEROREADCOUNT,Lock has non-zero read count,0),
+PKIX_ERRORENTRY(LOCKOBJECTFAILED,pkix_LockObject failed,0),
+PKIX_ERRORENTRY(LOGGERDUPLICATEFAILED,pkix_Logger_Duplicate failed,0),
+PKIX_ERRORENTRY(LOGGINGLEVELEXCEEDSMAXIMUM,Logging Level exceeds Maximum,0),
+PKIX_ERRORENTRY(LOOPDISCOVEREDDUPCERTSNOTALLOWED,Loop discovered: duplicate certificates not allowed,SEC_ERROR_UNTRUSTED_ISSUER),
+PKIX_ERRORENTRY(LOOPOFERRORCAUSEDETECTED,Loop of error causes detected,0),
+PKIX_ERRORENTRY(MAJORVERSIONSDONTMATCH,Major versions do not match,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(MALLOCFAILED,PKIX_PL_Malloc failed,0),
+PKIX_ERRORENTRY(MEMLEAKGENERATEDERROR,Error generated for memory leak testing,SEC_ERROR_NO_MEMORY),
+PKIX_ERRORENTRY(MINORVERSIONNOTBETWEENDESIREDMINANDMAX,Minor version does not fall between desired minimum and maximum,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(MISSINGDSAPARAMETERS,Missing DSA parameters in Trusted Cert,SEC_ERROR_INVALID_KEY),
+PKIX_ERRORENTRY(MONITORLOCKCREATEFAILED,PKIX_PL_MonitorLock_Create failed,0),
+PKIX_ERRORENTRY(MONITORLOCKENTERFAILED,PKIX_PL_MonitorLock_Enter failed,0),
+PKIX_ERRORENTRY(MONITORLOCKEXITFAILED,PKIX_PL_MonitorLock_Exit failed,0),
+PKIX_ERRORENTRY(MUTEXLOCKFAILED,PKIX_PL_Mutex_Lock failed,0),
+PKIX_ERRORENTRY(NAMECHAININGCHECKERINITIALIZEFAILED,pkix_NameChainingChecker_Initialize failed,0),
+PKIX_ERRORENTRY(NAMECHAININGCHECKFAILED,Name Chaining Check failed,SEC_ERROR_UNKNOWN_ISSUER),
+PKIX_ERRORENTRY(NAMECOMPONENTWITHNOEQ,Name Component with no equal sign,SEC_ERROR_BAD_INFO_ACCESS_LOCATION),
+PKIX_ERRORENTRY(NAMECONSTRAINTSCHECKERINITIALIZEFAILED,pkix_NameConstraintsChecker_Initialize failed,0),
+PKIX_ERRORENTRY(NAMECONSTRAINTSCHECKERSTATECREATEFAILED,pkix_NameConstraintsCheckerState_Create failed,0),
+PKIX_ERRORENTRY(NAMETYPENOTSUPPORTED,name type not supported,0),
+PKIX_ERRORENTRY(NOCONTENTTYPEINHTTPRESPONSE,No content type in Http Response,SEC_ERROR_BAD_HTTP_RESPONSE),
+PKIX_ERRORENTRY(NODESMISSINGFROMCHAIN,Nodes missing from chain,0),
+PKIX_ERRORENTRY(NOREGISTEREDHTTPCLIENT,No registered Http Client,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(NORESPONSEDATAINHTTPRESPONSE,No responseData in Http Response,SEC_ERROR_BAD_HTTP_RESPONSE),
+PKIX_ERRORENTRY(NOTARGETCERTSUPPLIED,No target cert supplied,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(NOTCONFORMINGCRLDP,Cert CRL DP does not conform to the rfc, 0),
+PKIX_ERRORENTRY(NOTDERPACKAGE,Not a DER package,0),
+PKIX_ERRORENTRY(NOTENOUGHNAMECOMPONENTSINGENERALNAME,Not enough name components in GeneralName,SEC_ERROR_BAD_INFO_ACCESS_LOCATION),
+PKIX_ERRORENTRY(NSSCERTIFICATEUSAGETOPKIXKUANDEKUFAILED,Failed to convert nss certificate usage to pkix ku and eku data structures,0),
+PKIX_ERRORENTRY(NSSCONTEXTCREATEFAILED,PKIX_PL_NssContext_Create failed,0),
+PKIX_ERRORENTRY(NSSCONTEXTDESTROYFAILED,PKIX_PL_NssContext_Destroy failed,0),
+PKIX_ERRORENTRY(NSSCONTEXTGETCHECKALLUSAGESFAILED, pkix_pl_NssContext_GetCheckAllUsages failed,0),
+PKIX_ERRORENTRY(NSSCONTEXTGETRETURNUSAGESFAILED, pkix_pl_NssContext_GetReturnUsages failed,0),
+PKIX_ERRORENTRY(NSSCONTEXTGETWINCXFAILED,pkix_pl_NssContext_GetWincx failed,0),
+PKIX_ERRORENTRY(NSSCONTEXTSETCERTSIGNCHECKFAILED, pkix_pl_NssContext_SetCertSignatureCheck,0),
+PKIX_ERRORENTRY(NSSCONTEXTSETCERTUSAGEFAILED, pkix_pl_NssContext_SetCertUsage failed,0),
+PKIX_ERRORENTRY(NSSCONTEXTSETCHECKALLUSAGESFAILED, pkix_pl_NssContext_SetCheckAllUsages failed,0),
+PKIX_ERRORENTRY(NSSCONTEXTSETRETURNEDCERTUSAGEFAILED, pkix_pl_NssContext_SetReturnedCertUsage,0),
+PKIX_ERRORENTRY(NSSCONTEXTSETRETURNUSAGESFAILED, pkix_pl_NssContext_SetReturnUsages failed,0),
+PKIX_ERRORENTRY(NSSCONTEXTVALIDATINGRESPONDERCERTFAILED,pkix_pl_NssContext_ValidatingResponderCert failed,0),
+PKIX_ERRORENTRY(NSSTRUSTEDLISTISEMPTY,nss trusted roots list is empty,0),
+PKIX_ERRORENTRY(NULLARGUMENT,Null argument,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(NUMBUCKETSEQUALSZERO,NumBuckets equals zero,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(OBJECTALLOCFAILED,PKIX_PL_Object_Alloc failed,0),
+PKIX_ERRORENTRY(OBJECTARGUMENTNOTPOLICYMAP,object argument is not a PolicyMap,0),
+PKIX_ERRORENTRY(OBJECTCOMPARATORFAILED,PKIX_PL_Object_Comparator failed,0),
+PKIX_ERRORENTRY(OBJECTDEFINED,object-defined ,0),
+PKIX_ERRORENTRY(OBJECTDUPLICATECERTFAILED,PKIX_PL_Object_Duplicate Cert failed,0),
+PKIX_ERRORENTRY(OBJECTDUPLICATECONTEXTFAILED,PKIX_PL_Object_Duplicate Context failed,0),
+PKIX_ERRORENTRY(OBJECTDUPLICATEDATEFAILED,PKIX_PL_Object_Duplicate Date failed,0),
+PKIX_ERRORENTRY(OBJECTDUPLICATEFAILED,PKIX_PL_Object_Duplicate failed,0),
+PKIX_ERRORENTRY(OBJECTDUPLICATEISSUERNAMESFAILED,PKIX_PL_Object_Duplicate IssuerNames failed,0),
+PKIX_ERRORENTRY(OBJECTDUPLICATELISTFAILED,PKIX_PL_Object_Duplicate List failed,0),
+PKIX_ERRORENTRY(OBJECTDUPLICATEMAXCRLNUMBERFAILED,PKIX_PL_Object_Duplicate maxCRLNumber failed,0),
+PKIX_ERRORENTRY(OBJECTDUPLICATEMINCRLNUMBERFAILED,PKIX_PL_Object_Duplicate minCRLNumber failed,0),
+PKIX_ERRORENTRY(OBJECTDUPLICATEPARAMSFAILED,PKIX_PL_Object_Duplicate Params failed,0),
+PKIX_ERRORENTRY(OBJECTEQUALSFAILED,PKIX_PL_Object_Equals failed,0),
+PKIX_ERRORENTRY(OBJECTEQUALSFAILEDONCHILDREN,PKIX_PL_Object_Equals failed on children,0),
+PKIX_ERRORENTRY(OBJECTEQUALSFAILEDONEXPECTEDPOLICYSETS,PKIX_PL_Object_Equals failed on expectedPolicySets,0),
+PKIX_ERRORENTRY(OBJECTGETTYPEFAILED,PKIX_PL_Object_GetType failed,0),
+PKIX_ERRORENTRY(OBJECTHASHCODEFAILED,PKIX_PL_Object_Hashcode failed,0),
+PKIX_ERRORENTRY(OBJECTINVALIDATECACHEFAILED,PKIX_PL_Object_InvalidateCache failed,0),
+PKIX_ERRORENTRY(OBJECTISTYPEREGISTEREDFAILED,PKIX_PL_Object_IsTypeRegistered failed,0),
+PKIX_ERRORENTRY(OBJECTLOCKFAILED,PKIX_PL_Object_Lock failed,0),
+PKIX_ERRORENTRY(OBJECTNOTAIAMGR,Object is not a AIAMgr,0),
+PKIX_ERRORENTRY(OBJECTNOTANEKUCHECKERSTATE,Object is not an EKU Checker State,0),
+PKIX_ERRORENTRY(OBJECTNOTANERROR,Object is not an Error,0),
+PKIX_ERRORENTRY(OBJECTNOTANHTTPCERTSTORECONTEXT,Object is not an HttpCertStoreContext,0),
+PKIX_ERRORENTRY(OBJECTNOTANHTTPDEFAULTCLIENT,Object is not an HttpDefaultClient,0),
+PKIX_ERRORENTRY(OBJECTNOTANINFOACCESS,Object is not an InfoAccess,0),
+PKIX_ERRORENTRY(OBJECTNOTANLDAPDEFAULTCLIENT,Object is not an LdapDefaultClient,0),
+PKIX_ERRORENTRY(OBJECTNOTANOCSPRESPONSE,Object is not an OcspResponse,0),
+PKIX_ERRORENTRY(OBJECTNOTANOID,Object is not an OID,0),
+PKIX_ERRORENTRY(OBJECTNOTANSOCKET,Object is not an Socket,0),
+PKIX_ERRORENTRY(OBJECTNOTANX500NAME,Object is not an X500Name,0),
+PKIX_ERRORENTRY(OBJECTNOTBASICCONSTRAINTSCHECKERSTATE,Object is not a basic constraints checker state,0),
+PKIX_ERRORENTRY(OBJECTNOTBIGINT,Object is not a BigInt,0),
+PKIX_ERRORENTRY(OBJECTNOTBUILDPARAMS,Object is not a BuildParams,0),
+PKIX_ERRORENTRY(OBJECTNOTBUILDRESULT,Object is not a BuildResult,0),
+PKIX_ERRORENTRY(OBJECTNOTBYTEARRAY,Object is not a bytearray,0),
+PKIX_ERRORENTRY(OBJECTNOTCERT,Object is not a Cert,0),
+PKIX_ERRORENTRY(OBJECTNOTCERTBASICCONSTRAINTS,Object is not a CertBasicConstraints,0),
+PKIX_ERRORENTRY(OBJECTNOTCERTCHAINCHECKER,Object is not a cert chain checker,0),
+PKIX_ERRORENTRY(OBJECTNOTCERTNAMECONSTRAINTS,Object is not a CertNameConstraints,0),
+PKIX_ERRORENTRY(OBJECTNOTCERTPOLICYINFO,Object is not a CertPolicyInfo,0),
+PKIX_ERRORENTRY(OBJECTNOTCERTPOLICYMAP,Object is not a CertPolicyMap,0),
+PKIX_ERRORENTRY(OBJECTNOTCERTPOLICYQUALIFIER,Object is not a CertPolicyQualifier,0),
+PKIX_ERRORENTRY(OBJECTNOTCERTSELECTOR,Object is not a cert selector,0),
+PKIX_ERRORENTRY(OBJECTNOTCERTSTORE,Object is not a CertStore,0),
+PKIX_ERRORENTRY(OBJECTNOTCOLLECTIONCERTSTORECONTEXT,Object is not a CollectionCertStoreContext,0),
+PKIX_ERRORENTRY(OBJECTNOTCOMCERTSELPARAMS,Object is not a comCertSelParams,0),
+PKIX_ERRORENTRY(OBJECTNOTCOMCRLSELPARAMS,Object is not a ComCRLSelParams,0),
+PKIX_ERRORENTRY(OBJECTNOTCRL,Object is not a CRL,0),
+PKIX_ERRORENTRY(OBJECTNOTCRLENTRY,Object is not a CRLEntry,0),
+PKIX_ERRORENTRY(OBJECTNOTCRLSELECTOR,Object is not a CRLSelector,0),
+PKIX_ERRORENTRY(OBJECTNOTDATE,Object is not a Date,0),
+PKIX_ERRORENTRY(OBJECTNOTCRLCHECKER,Object is not a CRLChecker,0),
+PKIX_ERRORENTRY(OBJECTNOTDEFAULTREVOCATIONCHECKER,Object is not a DefaultRevocationChecker,0),
+PKIX_ERRORENTRY(OBJECTNOTFORWARDBUILDERSTATE,Object is not a PKIX_ForwardBuilderState,0),
+PKIX_ERRORENTRY(OBJECTNOTGENERALNAME,Object is not a GeneralName,0),
+PKIX_ERRORENTRY(OBJECTNOTHASHTABLE,Object is not a hashtable,0),
+PKIX_ERRORENTRY(OBJECTNOTINFOACCESS,Object is not a InfoAccess,0),
+PKIX_ERRORENTRY(OBJECTNOTLDAPREQUEST,Object is not a LdapRequest,0),
+PKIX_ERRORENTRY(OBJECTNOTLDAPRESPONSE,Object is not a LdapResponse,0),
+PKIX_ERRORENTRY(OBJECTNOTLIST,Object is not a list,0),
+PKIX_ERRORENTRY(OBJECTNOTLOGGER,Object is not a Logger,0),
+PKIX_ERRORENTRY(OBJECTNOTMONITORLOCK,Object is not a MonitorLock,0),
+PKIX_ERRORENTRY(OBJECTNOTMUTEX,Object is not a Mutex,0),
+PKIX_ERRORENTRY(OBJECTNOTNAMECONSTRAINTSCHECKERSTATE,Object is not a name constraints checker state,0),
+PKIX_ERRORENTRY(OBJECTNOTOCSPCERTID,Object is not an OcspCertID,0),
+PKIX_ERRORENTRY(OBJECTNOTOCSPCHECKER,Object is not an OCSPChecker,0),
+PKIX_ERRORENTRY(OBJECTNOTOCSPREQUEST,Object is not an OcspRequest,0),
+PKIX_ERRORENTRY(OBJECTNOTPOLICYCHECKERSTATE,Object is not a PKIX_PolicyCheckerState,0),
+PKIX_ERRORENTRY(OBJECTNOTPOLICYNODE,Object is not a PolicyNode,0),
+PKIX_ERRORENTRY(OBJECTNOTPROCESSINGPARAMS,Object is not a ProcessingParams,0),
+PKIX_ERRORENTRY(OBJECTNOTPUBLICKEY,Object is not a PublicKey,0),
+PKIX_ERRORENTRY(OBJECTNOTRESOURCELIMITS,Object is not a ResourceLimits,0),
+PKIX_ERRORENTRY(OBJECTNOTREVOCATIONCHECKER,Object is not a revocation checker,0),
+PKIX_ERRORENTRY(OBJECTNOTRWLOCK,Object is not a RWLock,0),
+PKIX_ERRORENTRY(OBJECTNOTSIGNATURECHECKERSTATE,Object is not a signature checker state,0),
+PKIX_ERRORENTRY(OBJECTNOTSOCKET,Object is not a Socket,0),
+PKIX_ERRORENTRY(OBJECTNOTSTRING,Object is not a string,0),
+PKIX_ERRORENTRY(OBJECTNOTTARGETCERTCHECKERSTATE,Object is not a target cert checker state,0),
+PKIX_ERRORENTRY(OBJECTNOTTRUSTANCHOR,Object is not a trustAnchor,0),
+PKIX_ERRORENTRY(OBJECTNOTVALIDATEPARAMS,Object is not a ValidateParams,0),
+PKIX_ERRORENTRY(OBJECTNOTVALIDATERESULT,Object is not a ValidateResult,0),
+PKIX_ERRORENTRY(OBJECTNOTVERIFYNODE,Object is not a VerifyNode,0),
+PKIX_ERRORENTRY(OBJECTREGISTERTYPEFAILED,PKIX_PL_Object_RegisterType failed,0),
+PKIX_ERRORENTRY(OBJECTRETRIEVEEQUALSCALLBACKFAILED,pkix_pl_Object_RetrieveEqualsCallback failed,0),
+PKIX_ERRORENTRY(OBJECTSPECIFICFUNCTIONFAILED,object-specific function failed,0),
+PKIX_ERRORENTRY(OBJECTSTILLREFERENCED,Object is still referenced,0),
+PKIX_ERRORENTRY(OBJECTTOSTRINGFAILED,PKIX_PL_Object_ToString failed,0),
+PKIX_ERRORENTRY(OBJECTTYPESDONOTMATCH,Object types do not match,0),
+PKIX_ERRORENTRY(OBJECTWITHNONPOSITIVEREFERENCES,Object with non-positive references,0),
+PKIX_ERRORENTRY(OCSPCERTIDCREATEFAILED,PKIX_PL_OcspCertID_Create failed,0),
+PKIX_ERRORENTRY(OCSPCERTIDGETFRESHCACHESTATUSFAILED,PKIX_PL_OcspCertID_GetFreshCacheStatus returned an error,0),
+PKIX_ERRORENTRY(OCSPCERTIDREMEMBEROCSPFAILUREDFAILED,PKIX_PL_OcspCertID_RememberOCSPProcessingFailure,0),
+PKIX_ERRORENTRY(OCSPCHECKERCREATEFAILED,PKIX_OcspChecker_Create failed,0),
+PKIX_ERRORENTRY(OCSPBADHTTPRESPONSE,Bad Http Response,SEC_ERROR_OCSP_BAD_HTTP_RESPONSE),
+PKIX_ERRORENTRY(OCSPREQUESTCREATEFAILED,PKIX_PL_OcspRequest_Create failed,0),
+PKIX_ERRORENTRY(OCSPREQUESTGETCERTIDFAILED,pkix_pl_OcspRequest_GetCertID failed,0),
+PKIX_ERRORENTRY(OCSPREQUESTGETENCODEDFAILED,pkix_pl_OcspRequest_GetEncoded failed,0),
+PKIX_ERRORENTRY(OCSPREQUESTGETLOCATIONFAILED,pkix_pl_OcspRequest_GetLocation failed,0),
+PKIX_ERRORENTRY(OCSPRESPONSECREATEFAILED,pkix_pl_OcspResponse_Create failed,0),
+PKIX_ERRORENTRY(OCSPRESPONSEDECODEFAILED,pkix_pl_OcspResponse_Decode failed,0),
+PKIX_ERRORENTRY(OCSPRESPONSEGETSTATUSFORCERTFAILED,pkix_pl_OcspResponse_GetStatusForCert failed,0),
+PKIX_ERRORENTRY(OCSPRESPONSEGETSTATUSRETURNEDANERROR,pkix_pl_OcspResponse_GetStatus returned an error,0),
+PKIX_ERRORENTRY(OCSPRESPONSESAYSCERTREVOKED,OCSP response says Cert revoked,SEC_ERROR_REVOKED_CERTIFICATE_OCSP),
+PKIX_ERRORENTRY(OCSPRESPONSEVERIFYSIGNATUREFAILED,pkix_pl_OcspResponse_VerifySignature failed,0),
+PKIX_ERRORENTRY(OCSPSERVERERROR,OCSP Server Error,SEC_ERROR_OCSP_SERVER_ERROR),
+PKIX_ERRORENTRY(OIDBYTES2ASCIIDATALENGTHZERO,pkix_pl_oidBytes2Ascii: data length is zero,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(OIDBYTES2ASCIIFAILED,pkix_pl_oidBytes2Ascii failed,0),
+PKIX_ERRORENTRY(OIDBYTESLENGTH0,Oid bytes length is 0,0),
+PKIX_ERRORENTRY(OIDCOMPARATORFAILED,pkix_pl_OID_Comparator failed,0),
+PKIX_ERRORENTRY(OIDCOMPONENTTOOBIG,Overflow error: OID component > 2^32,0),
+PKIX_ERRORENTRY(OIDCREATEFAILED,PKIX_PL_OID_Create failed,0),
+PKIX_ERRORENTRY(OIDEQUALFAILED,PKIX_PL_OID_Equal failed,0),
+PKIX_ERRORENTRY(OIDEQUALSFAILED,PKIX_PL_OID_Equals failed,0),
+PKIX_ERRORENTRY(OIDGETNEXTTOKENFAILED,pkix_pl_OID_GetNextToken failed,0),
+PKIX_ERRORENTRY(OIDHASHCODEFAILED,PKIX_PL_OID_Hashcode failed,0),
+PKIX_ERRORENTRY(OIDLENGTHTOOSHORT,OID length too short,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(OIDNEEDS2ORMOREFIELDS,OID needs 2 or more fields,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(OIDTOSTRINGFAILED,PKIX_PL_OID_ToString failed,0),
+PKIX_ERRORENTRY(OPERATIONNOTPERMITTEDONIMMUTABLELIST,Operation not permitted on Immutable List,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(OTHERNAMECREATEFAILED,pkix_pl_OtherName_Create failed,0),
+PKIX_ERRORENTRY(OUTOFMEMORY,Out of Memory,0),
+PKIX_ERRORENTRY(PATHLENCONSTRAINTINVALID,Certificate path length constraint is invalid,SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID),
+PKIX_ERRORENTRY(PK11CERTSTORECERTQUERYFAILED,pkix_pl_Pk11CertStore_CertQuery failed,0),
+PKIX_ERRORENTRY(PK11CERTSTORECREATEFAILED,PKIX_PL_Pk11CertStore_Create failed,0),
+PKIX_ERRORENTRY(PK11CERTSTORECRLQUERYFAILED,pkix_pl_Pk11CertStore_CrlQuery failed,0),
+PKIX_ERRORENTRY(PKIXUNKNOWNERROR,PKIX uninitialized error code,0),
+PKIX_ERRORENTRY(POLICYCHECKERCALCULATEINTERSECTIONFAILED,pkix_PolicyChecker_CalculateIntersection failed,0),
+PKIX_ERRORENTRY(POLICYCHECKERCHECKANYFAILED,pkix_PolicyChecker_CheckAny failed,0),
+PKIX_ERRORENTRY(POLICYCHECKERCHECKPOLICYRECURSIVEFAILED,pkix_PolicyChecker_CheckPolicyRecursive failed,0),
+PKIX_ERRORENTRY(POLICYCHECKERERROR,PolicyChecker Error,0),
+PKIX_ERRORENTRY(POLICYCHECKERINITIALIZEFAILED,pkix_PolicyChecker_Initialize failed,0),
+PKIX_ERRORENTRY(POLICYCHECKERMAKEMUTABLECOPYFAILED,pkix_PolicyChecker_MakeMutableCopy failed,0),
+PKIX_ERRORENTRY(POLICYCHECKERMAKESINGLETONFAILED,pkix_PolicyChecker_MakeSingleton failed,0),
+PKIX_ERRORENTRY(POLICYCHECKERMAPCONTAINSFAILED,pkix_PolicyChecker_MapContains failed,0),
+PKIX_ERRORENTRY(POLICYCHECKERMAPGETMAPPEDPOLICIESFAILED,pkix_PolicyChecker_MapGetMappedPolicies failed,0),
+PKIX_ERRORENTRY(POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED,pkix_PolicyChecker_MapGetSubjectDomainPolicies failed,0),
+PKIX_ERRORENTRY(POLICYCHECKERSPAWNFAILED,pkix_PolicyChecker_Spawn failed,0),
+PKIX_ERRORENTRY(POLICYCHECKERSTATECREATEFAILED,PKIX_PolicyCheckerState_Create failed,0),
+PKIX_ERRORENTRY(POLICYNODEADDTOPARENTFAILED,pkix_PolicyNode_AddToParent failed,0),
+PKIX_ERRORENTRY(POLICYNODECREATEFAILED,pkix_PolicyNode_Create failed,0),
+PKIX_ERRORENTRY(POLICYNODEDUPLICATEHELPERFAILED,pkix_PolicyNode_DuplicateHelper failed,0),
+PKIX_ERRORENTRY(POLICYNODEGETCHILDRENMUTABLEFAILED,pkix_PolicyNode_GetChildrenMutable failed,0),
+PKIX_ERRORENTRY(POLICYNODEGETDEPTHFAILED,PKIX_PolicyNode_GetDepth failed,0),
+PKIX_ERRORENTRY(POLICYNODEGETEXPECTEDPOLICIESFAILED,PKIX_PolicyNode_GetExpectedPolicies failed,0),
+PKIX_ERRORENTRY(POLICYNODEGETPARENTFAILED,PKIX_PolicyNode_GetParent failed,0),
+PKIX_ERRORENTRY(POLICYNODEGETPOLICYQUALIFIERSFAILED,PKIX_PolicyNode_GetPolicyQualifiers failed,0),
+PKIX_ERRORENTRY(POLICYNODEGETVALIDPOLICYFAILED,PKIX_PolicyNode_GetValidPolicy failed,0),
+PKIX_ERRORENTRY(POLICYNODEISCRITICALFAILED,PKIX_PolicyNode_IsCritical failed,0),
+PKIX_ERRORENTRY(POLICYNODEPRUNEFAILED,pkix_PolicyNode_Prune failed,0),
+PKIX_ERRORENTRY(POLICYTREETOOIDSFAILED,Failed to convert policy tree to oid,0),
+PKIX_ERRORENTRY(PORTARENAALLOCFAILED,PORT Arena Allocation failed, 0),
+PKIX_ERRORENTRY(PORTUCS2UTF8CONVERSIONFAILED,PORT_UCS2_UTF8Conversion failed.,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(PRACCEPTFAILED,PR_Accept failed,0),
+PKIX_ERRORENTRY(PRBINDFAILED,PR_Bind failed,0),
+PKIX_ERRORENTRY(PRCONNECTCONTINUEFAILED,PR_ConnectContinue failed,0),
+PKIX_ERRORENTRY(PRCONNECTFAILED,PR_Connect failed,0),
+PKIX_ERRORENTRY(PRECONDITIONFAILED,Function precondition failed,SEC_ERROR_LIBPKIX_INTERNAL),
+PKIX_ERRORENTRY(PRENUMERATEHOSTENTFAILED,PR_EnumerateHostEnt failed.,0),
+PKIX_ERRORENTRY(PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT,PR_GetHostByName rejects hostname argument.,0),
+PKIX_ERRORENTRY(PRIMHASHTABLEADDFAILED,pkix_pl_PrimHashTable_Add failed,0),
+PKIX_ERRORENTRY(PRIMHASHTABLECREATEFAILED,pkix_pl_PrimHashTable_Create failed,0),
+PKIX_ERRORENTRY(PRIMHASHTABLEDESTROYFAILED,pkix_pl_PrimHashTable_Destroy failed,0),
+PKIX_ERRORENTRY(PRIMHASHTABLEGETBUCKETSIZEFAILED,pkix_pl_PrimHashTable_GetBucketSize failed,0),
+PKIX_ERRORENTRY(PRIMHASHTABLELOOKUPFAILED,pkix_pl_PrimHashTable_Lookup failed,0),
+PKIX_ERRORENTRY(PRIMHASHTABLEREMOVEFAILED,pkix_pl_PrimHashTable_Remove failed,0),
+PKIX_ERRORENTRY(PRLISTENFAILED,PR_Listen failed,0),
+PKIX_ERRORENTRY(PRNEWTCPSOCKETFAILED,PR_NewTCPSocket failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSADDCERTCHAINCHECKERFAILED,PKIX_ProcessingParams_AddCertChainChecker failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSADDCERTSTOREFAILED,PKIX_ProcessingParams_AddCertStore failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSADDREVMETHODFAILED,PKIX_ProcessingParams_AddRevocationMethod failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSCREATEFAILED,PKIX_ProcessingParams_Create failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED,PKIX_ProcessingParams_GetCertChainCheckers failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSGETCERTSTORESFAILED,PKIX_ProcessingParams_GetCertStores failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSGETDATEFAILED,PKIX_ProcessingParams_GetDate failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSGETHINTCERTSFAILED,PKIX_ProcessingParams_GetHintCerts failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSGETINITIALPOLICIESFAILED,PKIX_ProcessingParams_GetInitialPolicies failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSGETNISTREVPOLICYENABLEDFAILED,pkix_ProcessingParams_GetNISTRevocationPolicyEnabled failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED,PKIX_ProcessingParams_GetPolicyQualifiersRejected failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSGETRESOURCELIMITSFAILED,PKIX_ProcessingParams_GetResourceLimits failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED,PKIX_ProcessingParams_GetRevocationChecker failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSGETREVOCATIONENABLEDFAILED,PKIX_ProcessingParams_GetRevocationEnabled failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED,PKIX_ProcessingParams_GetTargetCertConstraints failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSGETTRUSTANCHORSFAILED,PKIX_ProcessingParams_GetTrustAnchors failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED,PKIX_ProcessingParams_IsAnyPolicyInhibited failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED,PKIX_ProcessingParams_IsExplicitPolicyRequired failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED,PKIX_ProcessingParams_IsPolicyMappingInhibited failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSSETANYPOLICYINHIBITED,PKIX_ProcessingParams_SetAnyPolicyInhibited failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSSETCERTSTORESFAILED,PKIX_ProcessingParams_SetCertStores failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSSETDATEFAILED,PKIX_ProcessingParams_SetDate failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSSETEXPLICITPOLICYREQUIRED,PKIX_ProcessingParams_SetExplicitPolicyRequired failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSSETHINTCERTSFAILED,PKIX_ProcessingParams_SetHintCerts failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSSETINITIALPOLICIESFAILED,PKIX_ProcessingParams_SetInitialPolicies failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSSETNISTREVOCATIONENABLEDFAILED,PKIX_ProcessingParams_SetNISTRevocationEnabled failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSSETPOLICYMAPPINGINHIBITED,PKIX_ProcessingParams_SetPolicyMappingInhibited failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSSETREVOCATIONCHECKERFAILED,PKIX_ProcessingParams_SetRevocationChecker failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED,PKIX_ProcessingParams_SetTargetCertConstraints failed,0),
+PKIX_ERRORENTRY(PROCESSINGPARAMSSETQUALIFYTARGETCERTFLAGFAILED,ProcessingParams_SetQualifyTargetCertFlag failed,0),
+PKIX_ERRORENTRY(PRPOLLFAILED,PR_Poll failed,0),
+PKIX_ERRORENTRY(PRPOLLRETBADFILENUM,PR_Poll failed,0),
+PKIX_ERRORENTRY(PRRECVFAILED,PR_Recv failed,0),
+PKIX_ERRORENTRY(PRRECVREPORTSNETWORKCONNECTIONCLOSED,PR_Recv reports network connection is closed,0),
+PKIX_ERRORENTRY(PRSENDFAILED,PR_Send failed,0),
+PKIX_ERRORENTRY(PRSHUTDOWNFAILED,PR_Shutdown failed,0),
+PKIX_ERRORENTRY(PRSMPRINTFFAILED,PR_smprintf failed,0),
+PKIX_ERRORENTRY(PRSNPRINTFFAILED,PR_snprintf failed,0),
+PKIX_ERRORENTRY(PUBKEYTYPENULLKEY,pubKeyType is nullKey,0),
+PKIX_ERRORENTRY(PUBLICKEYMAKEINHERITEDDSAPUBLICKEYFAILED,PKIX_PL_PublicKey_MakeInheritedDSAPublicKey failed,0),
+PKIX_ERRORENTRY(PUBLICKEYNEEDSDSAPARAMETERSFAILED,PKIX_PL_PublicKey_NeedsDSAParameters failed,0),
+PKIX_ERRORENTRY(PUBLICKEYTOSTRINGFAILED,PKIX_PL_PublicKey_ToString failed,0),
+PKIX_ERRORENTRY(PUBLICKEYTOSTRINGHELPERFAILED,pkix_pl_PublicKey_ToString_Helper failed,0),
+PKIX_ERRORENTRY(QUALIFIERSINCRITICALCERTIFICATEPOLICYEXTENSION,Qualifiers in critical Certificate Policy extension,0),
+PKIX_ERRORENTRY(REALLOCFAILED,PKIX_PL_Realloc failed,0),
+PKIX_ERRORENTRY(RECEIVEDCORRUPTEDOBJECTARGUMENT,Received corrupted object argument,0),
+PKIX_ERRORENTRY(REGISTERCERTSTOREFAILED,RegisterCertStores failed,0),
+PKIX_ERRORENTRY(REMOVEDUPUNTRUSTEDCERTSFAILED, pkix_Build_RemoveDupUntrustedCerts failed,0),
+PKIX_ERRORENTRY(REQUESTNOTANHTTPDEFAULTCLIENT,request is not an HttpDefaultClient,0),
+PKIX_ERRORENTRY(RESOURCELIMITSGETMAXDEPTHFAILED,PKIX_ResourceLimits_GetMaxDepth failed,0),
+PKIX_ERRORENTRY(RESOURCELIMITSGETMAXFANOUTFAILED,PKIX_ResourceLimits_GetMaxFanout failed,0),
+PKIX_ERRORENTRY(RESOURCELIMITSGETMAXTIMEFAILED,PKIX_ResourceLimits_GetMaxTime failed,0),
+PKIX_ERRORENTRY(RETRIEVEOUTPUTSFAILED,pkix_RetrieveOutputs failed,0),
+PKIX_ERRORENTRY(REVCHECKCERTFAILED,pkix_RevCheckCert failed,0),
+PKIX_ERRORENTRY(REVCHECKERCHECKFAILED,revCheckerCheck failed,0),
+PKIX_ERRORENTRY(REVOCATIONCHECKERADDMETHODFAILED,Can not add revocation method,0),
+PKIX_ERRORENTRY(REVOCATIONCHECKERCREATEFAILED,PKIX_RevocationChecker_Create failed,0),
+PKIX_ERRORENTRY(REVOCATIONCHECKERGETREVCALLBACKFAILED,PKIX_RevocationChecker_GetRevCallback failed,0),
+PKIX_ERRORENTRY(REVOCATIONCHECKERGETREVCHECKERCONTEXTFAILED,PKIX_RevocationChecker_GetRevCheckerContext failed,0),
+PKIX_ERRORENTRY(REVOCATIONCHECKERWASNOTSET,Revocation chekcer was not set,0),
+PKIX_ERRORENTRY(REVOKEDBYUNKNOWNCRLREASONCODE,Revoked by Unknown CRL ReasonCode,0),
+PKIX_ERRORENTRY(SEARCHRESPONSEPACKETOFUNKNOWNTYPE,SearchResponse packet of unknown type,SEC_ERROR_BAD_LDAP_RESPONSE),
+PKIX_ERRORENTRY(SECASN1ENCODEITEMFAILED,SEC_ASN1EncodeItem failed,SEC_ERROR_FAILED_TO_ENCODE_DATA),
+PKIX_ERRORENTRY(SECERRORUNKNOWNISSUER,Nss legacy err code: build failed. Issuer is unknown.,SEC_ERROR_UNKNOWN_ISSUER),
+PKIX_ERRORENTRY(SECKEYCOPYSUBJECTPUBLICKEYINFOFAILED,SECKEY_CopySubjectPublicKeyInfo failed,0),
+PKIX_ERRORENTRY(SECKEYEXTRACTPUBLICKEYFAILED,SECKEY_ExtractPublicKey failed,0),
+PKIX_ERRORENTRY(SECOIDCOPYALGORITHMIDFAILED,SECOID_CopyAlgorithmID failed,0),
+PKIX_ERRORENTRY(SECOIDFINDOIDTAGDESCRIPTIONFAILED,SECOID_FindOIDTag Description failed,0),
+PKIX_ERRORENTRY(SECONDFIELDMUSTBEBETWEEN039,Second field must be between 0-39,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(SECONDKEYDSAPUBLICKEY,Second key is a DSA public key but has null parameters,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(SECONDKEYNOTDSAPUBLICKEY,Second key is not a DSA public key,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(SECONDPUBKEYTYPENULLKEY,secondPubKeyType is nullKey,0),
+PKIX_ERRORENTRY(SECQUICKDERDECODERFAILED,SEC_QuickDERDecodeItem failed,0),
+PKIX_ERRORENTRY(SECREADPKCS7CERTSFAILED,SEC_ReadPKCS7Certs failed,0),
+PKIX_ERRORENTRY(SELECTORMATCHFAILED,selectorMatch failed,0),
+PKIX_ERRORENTRY(SESSIONNOTANHTTPDEFAULTCLIENT,session is not an HttpDefaultClient,0),
+PKIX_ERRORENTRY(SETPOLICIESFAILED,Fail to set cert validation policies,0),
+PKIX_ERRORENTRY(SHUTDOWNFAILED,PKIX_PL_Shutdown failed,0),
+PKIX_ERRORENTRY(SIGNATURECHECKERINITIALIZEFAILED,pkix_SignatureChecker_Initialize failed,0),
+PKIX_ERRORENTRY(SIGNATURECHECKERSTATECREATEFAILED,pkix_SignatureCheckerState_Create failed,0),
+PKIX_ERRORENTRY(SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY,Signature did not verify with the public key,0),
+PKIX_ERRORENTRY(SINGLEPOLICYNODEEQUALSFAILED,PKIX_PL_SinglePolicyNode_Equals failed,0),
+PKIX_ERRORENTRY(SINGLEPOLICYNODEHASHCODEFAILED,pkix_SinglePolicyNode_Hashcode failed,0),
+PKIX_ERRORENTRY(SINGLEPOLICYNODETOSTRINGFAILED,pkix_SinglePolicyNode_ToString failed,0),
+PKIX_ERRORENTRY(SINGLEVERIFYNODEEQUALSFAILED,PKIX_PL_SingleVerifyNode_Equals failed,0),
+PKIX_ERRORENTRY(SINGLEVERIFYNODEHASHCODEFAILED,pkix_SingleVerifyNode_Hashcode failed,0),
+PKIX_ERRORENTRY(SOCKETCONNECTCONTINUEFAILED,pkix_pl_Socket_ConnectContinue failed,0),
+PKIX_ERRORENTRY(SOCKETCONNECTFAILED,pkix_pl_Socket_Connect failed,0),
+PKIX_ERRORENTRY(SOCKETCREATEBYHOSTANDPORTFAILED,pkix_pl_Socket_CreateByHostAndPort failed,0),
+PKIX_ERRORENTRY(SOCKETCREATEBYNAMEFAILED,pkix_pl_Socket_CreateByName failed,0),
+PKIX_ERRORENTRY(SOCKETCREATECLIENTFAILED,pkix_pl_Socket_CreateClient failed,0),
+PKIX_ERRORENTRY(SOCKETCREATEFAILED,pkix_pl_Socket_Create failed,0),
+PKIX_ERRORENTRY(SOCKETCREATESERVERFAILED,pkix_pl_Socket_CreateServer failed,0),
+PKIX_ERRORENTRY(SOCKETEQUALSFAILED,PKIX_PL_Socket_Equals failed,0),
+PKIX_ERRORENTRY(SOCKETGETCALLBACKLISTFAILED,pkix_pl_Socket_GetCallbackList failed,0),
+PKIX_ERRORENTRY(SOCKETGETPRFILEDESCFAILED,pkix_pl_Socket_GetPRFileDesc failed,0),
+PKIX_ERRORENTRY(SOCKETHASHCODEFAILED,PKIX_PL_Socket_Hashcode failed,0),
+PKIX_ERRORENTRY(SOCKETPOLLFAILED,pkix_pl_Socket_Poll failed,0),
+PKIX_ERRORENTRY(SOCKETRECVFAILED,pkix_pl_Socket_Recv failed,0),
+PKIX_ERRORENTRY(SOCKETSENDFAILED,pkix_pl_Socket_Send failed,0),
+PKIX_ERRORENTRY(SOCKETSETNONBLOCKINGFAILED,pkix_pl_Socket_SetNonBlocking failed,0),
+PKIX_ERRORENTRY(SOURCESTRINGHASINVALIDLENGTH,Source string has invalid length,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(SPRINTFFAILED,PKIX_PL_Sprintf failed,0),
+PKIX_ERRORENTRY(STRINGCOMPARATORFAILED,pkix_pl_String_Comparator failed,0),
+PKIX_ERRORENTRY(STRINGCREATEFAILED,PKIX_PL_String_Create failed,0),
+PKIX_ERRORENTRY(STRINGEQUALSFAILED,pkix_pl_String_Equals failed,0),
+PKIX_ERRORENTRY(STRINGGETENCODEDFAILED,PKIX_PL_String_GetEncoded failed,0),
+PKIX_ERRORENTRY(STRINGHASHCODEFAILED,pkix_pl_String_Hashcode failed,0),
+PKIX_ERRORENTRY(SUBJALTNAMECHECKFAILED,Validation failed: SubjAltNamecheck failed,0),
+PKIX_ERRORENTRY(TARGETCERTCHECKERINITIALIZEFAILED,pkix_TargetCertChecker_Initialize failed,0),
+PKIX_ERRORENTRY(TARGETCERTCHECKERSTATECREATEFAILED,pkix_TargetCertCheckerState_Create failed,0),
+PKIX_ERRORENTRY(TESTANOTHERERRORMESSAGE, Another Error Message,0),
+PKIX_ERRORENTRY(TESTERRORMESSAGE, Error Message,0),
+PKIX_ERRORENTRY(TESTNOMATCHINGPOLICY, No Matching Policy,0),
+PKIX_ERRORENTRY(TESTNOTANERRORCRLSELECTMISMATCH, Not an error CRL Select mismatch,0),
+PKIX_ERRORENTRY(TESTPOLICYEXTWITHNOPOLICYQUALIFIERS, Policies extension but no Policy Qualifiers,0),
+PKIX_ERRORENTRY(TIMECONSUMEDEXCEEDSRESOURCELIMITS,Time consumed exceeds Resource Limits,SEC_ERROR_OUT_OF_SEARCH_LIMITS),
+PKIX_ERRORENTRY(TOOLITTLEDATAINDERSEQUENCE,Too little data in DER Sequence,0),
+PKIX_ERRORENTRY(TOOMUCHDATAINDERSEQUENCE,Too much data in DER Sequence,0),
+PKIX_ERRORENTRY(TOSTRINGFORTHISGENERALNAMETYPENOTSUPPORTED,ToString for this GeneralName type not supported,0),
+PKIX_ERRORENTRY(TRUNCATEDUNICODEINESCAPEDASCII,Truncated Unicode in EscapedASCII,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(TRUSTANCHORCREATEWITHCERTFAILED,PKIX_TrustAnchor_CreateWithCert failed,0),
+PKIX_ERRORENTRY(TRUSTANCHORGETCANAMEFAILED,PKIX_TrustAnchor_GetCAName failed,0),
+PKIX_ERRORENTRY(TRUSTANCHORGETCAPUBLICKEYFAILED,PKIX_TrustAnchor_GetCAPublicKey failed,0),
+PKIX_ERRORENTRY(TRUSTANCHORGETNAMECONSTRAINTSFAILED,PKIX_TrustAnchor_GetNameConstraints failed,0),
+PKIX_ERRORENTRY(TRUSTANCHORGETTRUSTEDCERTFAILED,PKIX_TrustAnchor_GetTrustedCert failed,0),
+PKIX_ERRORENTRY(TRUSTANCHORTOCERTFAILED,Fail to convert trust anchor to cert,0),
+PKIX_ERRORENTRY(TYPEALREADYREGISTERED,Type is already registered,0),
+PKIX_ERRORENTRY(UNABLETOADDACCEPTABLERESPONSESTOREQUEST,Unable to add acceptableResponses to request,0),
+PKIX_ERRORENTRY(UNABLETOADDCERTTOCERTLIST,Unable to add Cert to CertList,0),
+PKIX_ERRORENTRY(UNABLETOBUILDCHAIN,Unable to build chain,0),
+PKIX_ERRORENTRY(UNABLETOCREATECERTOCSPREQUEST,Unable to create a CertOCSPRequest,0),
+PKIX_ERRORENTRY(UNABLETOCREATECRLSTRING,Unable to create crlString,0),
+PKIX_ERRORENTRY(UNABLETOCREATEGENERALNAMEOFTHISTYPE,Unable to create GeneralName of this type,0),
+PKIX_ERRORENTRY(UNABLETOCREATEISSUER,Unable to create Issuer,0),
+PKIX_ERRORENTRY(UNABLETOCREATELIST,Unable to create list,0),
+PKIX_ERRORENTRY(UNABLETOCREATENEWCERTLIST,Unable to create a new CertList,0),
+PKIX_ERRORENTRY(UNABLETOCREATEPSTRING,Unable to create pString,0),
+PKIX_ERRORENTRY(UNABLETOFINDSTATUSINOCSPRESPONSE,Unable to find status in OCSP response,SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS),
+PKIX_ERRORENTRY(UNABLETOMAKELISTIMMUTABLE,Unable to make list immutable,0),
+PKIX_ERRORENTRY(UNABLETOOPENCERTFILE,Unable to open cert file,0),
+PKIX_ERRORENTRY(UNABLETOOPENCRLFILE,Unable to open crl file,0),
+PKIX_ERRORENTRY(UNABLETOPARSEOCSPRESPONSE,Unable to parse OCSP response,SEC_ERROR_OCSP_MALFORMED_RESPONSE),
+PKIX_ERRORENTRY(UNABLETOREADDERFROMCERTFILE,Unable to read DER from cert file,0),
+PKIX_ERRORENTRY(UNABLETOREADDERFROMCRLFILE,Unable to read DER from crl file,0),
+PKIX_ERRORENTRY(UNABLETOSETSOCKETTONONBLOCKING,Unable to set socket to non-blocking I/O,0),
+PKIX_ERRORENTRY(UNDEFINEDCALLBACK,Undefined callback,0),
+PKIX_ERRORENTRY(UNDEFINEDCLASSTABLEENTRY,Undefined class table entry,0),
+PKIX_ERRORENTRY(UNDEFINEDCOMPARATOR,Undefined Comparator,0),
+PKIX_ERRORENTRY(UNDEFINEDDUPLICATEFUNCTION,Undefined Duplicate function,0),
+PKIX_ERRORENTRY(UNDEFINEDEQUALSCALLBACK,Undefined equals callback,0),
+PKIX_ERRORENTRY(UNEXPECTEDERRORINESTABLISHINGCONNECTION,Unexpected error in establishing connection,0),
+PKIX_ERRORENTRY(UNEXPECTEDRESULTCODEINRESPONSE,Unexpected result code in Response,SEC_ERROR_BAD_LDAP_RESPONSE),
+PKIX_ERRORENTRY(UNKNOWNFORMAT,Unknown format,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(UNKNOWNINFOACCESSMETHOD,Unknown InfoAccess method,SEC_ERROR_BAD_INFO_ACCESS_METHOD),
+PKIX_ERRORENTRY(UNKNOWNOBJECTOID,Unknown object OID,0),
+PKIX_ERRORENTRY(UNKNOWNOBJECTTYPE,Unknown object type,0),
+PKIX_ERRORENTRY(UNKNOWNTYPEARGUMENT,Unknown type argument,0),
+PKIX_ERRORENTRY(UNLOCKOBJECTFAILED,pkix_UnlockObject failed,0),
+PKIX_ERRORENTRY(UNRECOGNIZEDCRITICALEXTENSION,Unrecognized Critical Extension,SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION),
+PKIX_ERRORENTRY(UNRECOGNIZEDCRLENTRYCRITICALEXTENSION,Unrecognized CRLEntry Critical Extension,SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION),
+PKIX_ERRORENTRY(UNRECOGNIZEDPROTOCOLREQUESTED,Unrecognized protocol requested,0),
+PKIX_ERRORENTRY(UNRECOGNIZEDREQUESTMETHOD,Unrecognized request method,0),
+PKIX_ERRORENTRY(UNRECOGNIZEDTIMETYPE,Unrecognized time type,0),
+PKIX_ERRORENTRY(UNSUPPORTEDCRLDPTYPE,CrlDp type is not supported,0),
+PKIX_ERRORENTRY(UNSUPPORTEDVERSIONOFHTTPCLIENT,Unsupported version of Http Client,0),
+PKIX_ERRORENTRY(UNSUPPORTEDCERTUSAGE,Specified certificate usage is unsupported,SEC_ERROR_CERT_USAGES_INVALID),
+PKIX_ERRORENTRY(URLPARSINGFAILED,URL Parsing failed,0),
+PKIX_ERRORENTRY(USERCHECKERCHECKFAILED,userCheckerCheck failed,0),
+PKIX_ERRORENTRY(UTF16ALIGNMENTERROR,UTF16 Alignment Error,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(UTF16HIGHZONEALIGNMENTERROR,UTF16 High Zone Alignment Error,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(UTF16LOWZONEERROR,UTF16 Low Zone Error,SEC_ERROR_INVALID_ARGS),
+PKIX_ERRORENTRY(UTF16TOESCASCIIFAILED,pkix_UTF16_to_EscASCII failed,0),
+PKIX_ERRORENTRY(UTF16TOUTF8FAILED,pkix_UTF16_to_UTF8 failed,0),
+PKIX_ERRORENTRY(UTF8TOUTF16FAILED,pkix_UTF8_to_UTF16 failed,0),
+PKIX_ERRORENTRY(VALIDATEBUILDUSEROIDSFAILED,pkix_Validate_BuildUserOIDs failed,0),
+PKIX_ERRORENTRY(VALIDATECERTCHAINFAILED,Failed to validate cert chain,0),
+PKIX_ERRORENTRY(VALIDATECHAINFAILED,PKIX_ValidateChain failed,0),
+PKIX_ERRORENTRY(VALIDATEPARAMSGETCERTCHAINFAILED,PKIX_ValidateParams_GetCertChain failed,0),
+PKIX_ERRORENTRY(VALIDATEPARAMSGETPROCESSINGPARAMSFAILED,PKIX_ValidateParams_GetProcessingParams failed,0),
+PKIX_ERRORENTRY(VALIDATERESULTCREATEFAILED,pkix_ValidateResult_Create failed,0),
+PKIX_ERRORENTRY(VALIDATERESULTGETPOLICYTREEFAILED,PKIX_ValidateResult_GetPolicyTree failed,0),
+PKIX_ERRORENTRY(VALIDATERESULTGETTRUSTANCHORFAILED,PKIX_ValidateResult_GetTrustAnchor failed,0),
+PKIX_ERRORENTRY(VALIDATIONFAILEDCERTSIGNATURECHECKING,Validation failed: Cert Signature checking,0),
+PKIX_ERRORENTRY(VALIDATIONFAILEDNULLCERTPOINTER,Validation failed: NULL Cert pointer,0),
+PKIX_ERRORENTRY(VALIDATIONFAILEDPATHTONAMECHECKFAILED,Validation failed: PathToName check failed,SEC_ERROR_CERT_NOT_IN_NAME_SPACE),
+PKIX_ERRORENTRY(VALUEINESCAPEDASCII,value in EscapedASCII,0),
+PKIX_ERRORENTRY(VERIFYNODEADDTOCHAINFAILED,pkix_VerifyNode_AddToChain failed,0),
+PKIX_ERRORENTRY(VERIFYNODEADDTOTREEFAILED,pkix_VerifyNode_AddToTree failed,0),
+PKIX_ERRORENTRY(VERIFYNODECREATEFAILED,pkix_VerifyNode_Create failed,0),
+PKIX_ERRORENTRY(VERIFYNODEDUPLICATEHELPERFAILED,pkix_VerifyNode_DuplicateHelper failed,0),
+PKIX_ERRORENTRY(VERIFYNODEFINDERRORFAILED,pkix_VerifyNode_FindError failed,0),
+PKIX_ERRORENTRY(VERIFYNODESETDEPTHFAILED,pkix_VerifyNode_SetDepth failed,0),
+PKIX_ERRORENTRY(VERIFYNODESETERRORFAILED,pkix_VerifyNode_SetError failed,0),
+PKIX_ERRORENTRY(VERSIONVALUEMUSTBEV1ORV2,Version value must be V1(0) or V2(1),SEC_ERROR_CRL_INVALID),
+PKIX_ERRORENTRY(VERSIONVALUEMUSTBEV1V2ORV3,Version value must be v1(0) v2(1) or v3(2),SEC_ERROR_CERT_VALID),
+PKIX_ERRORENTRY(X500NAMECOMPAREDERBYTESFAILED,pkix_pl_X500Name_CompareDERBytes failed,0),
+PKIX_ERRORENTRY(X500NAMECREATEFAILED,PKIX_PL_X500Name_Create failed,0),
+PKIX_ERRORENTRY(X500NAMECREATEFROMCERTNAMEFAILED,pkix_pl_X500Name_CreateFromCERTName failed,0),
+PKIX_ERRORENTRY(X500NAMECREATEFROMUTF8FAILED,pkix_pl_X500Name_CreateFromUtf8 failed,0),
+PKIX_ERRORENTRY(X500NAMEEQUALSFAILED,PKIX_PL_X500Name_Equals failed,0),
+PKIX_ERRORENTRY(X500NAMEGETCOMMONNAMEFAILED,pkix_pl_X500Name_GetCommonName failed,0),
+PKIX_ERRORENTRY(X500NAMEGETCOUNTRYNAMEFAILED,pkix_pl_X500Name_GetCountryName failed,0),
+PKIX_ERRORENTRY(X500NAMEGETORGNAMEFAILED,pkix_pl_X500Name_GetOrgName failed,0),
+PKIX_ERRORENTRY(X500NAMEGETSECNAMEFAILED,pkix_pl_X500Name_GetSECName failed,0),
+PKIX_ERRORENTRY(X500NAMEHASHCODEFAILED,PKIX_PL_X500Name_Hashcode failed,0),
+PKIX_ERRORENTRY(X500NAMEMATCHFAILED,PKIX_PL_X500Name_Match failed,0),
+PKIX_ERRORENTRY(X500NAMETOSTRINGFAILED,PKIX_PL_X500Name_ToString failed,0),
+PKIX_ERRORENTRY(ZEROLENGTHBYTEARRAYFORCRLENCODING,Zero-length ByteArray for CRL encoding,0),
+PKIX_ERRORENTRY(INVALIDOCSPHTTPMETHOD,Unsupported HTTP Method for OCSP retrieval,0),
+PKIX_ERRORENTRY(OCSPGETREQUESTTOOBIG,OCSP request too big for HTTP GET method,0),
+PKIX_ERRORENTRY(CERTISBLOCKLISTEDATISSUANCETIME,Issuer Certificate is distrusted at the time the subordinate certifiate was issued,SEC_ERROR_UNTRUSTED_ISSUER)
diff --git a/security/nss/lib/libpkix/include/pkix_params.h b/security/nss/lib/libpkix/include/pkix_params.h
new file mode 100644
index 0000000000..a4d8e485cb
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkix_params.h
@@ -0,0 +1,1793 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 file defines functions associated with the various parameters used
+ * by the top-level functions.
+ *
+ */
+
+#ifndef _PKIX_PARAMS_H
+#define _PKIX_PARAMS_H
+
+#include "pkixt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General
+ *
+ * Please refer to the libpkix Programmer's Guide for detailed information
+ * about how to use the libpkix library. Certain key warnings and notices from
+ * that document are repeated here for emphasis.
+ *
+ * All identifiers in this file (and all public identifiers defined in
+ * libpkix) begin with "PKIX_". Private identifiers only intended for use
+ * within the library begin with "pkix_".
+ *
+ * A function returns NULL upon success, and a PKIX_Error pointer upon failure.
+ *
+ * Unless otherwise noted, for all accessor (gettor) functions that return a
+ * PKIX_PL_Object pointer, callers should assume that this pointer refers to a
+ * shared object. Therefore, the caller should treat this shared object as
+ * read-only and should not modify this shared object. When done using the
+ * shared object, the caller should release the reference to the object by
+ * using the PKIX_PL_Object_DecRef function.
+ *
+ * While a function is executing, if its arguments (or anything referred to by
+ * its arguments) are modified, free'd, or destroyed, the function's behavior
+ * is undefined.
+ *
+ */
+
+/* PKIX_ProcessingParams
+ *
+ * PKIX_ProcessingParams are parameters used when validating or building a
+ * chain of certificates. Using the parameters, the caller can specify several
+ * things, including the various inputs to the PKIX chain validation
+ * algorithm (such as trust anchors, initial policies, etc), any customized
+ * functionality (such as CertChainCheckers, RevocationCheckers, CertStores),
+ * and whether revocation checking should be disabled.
+ *
+ * Once the caller has created the ProcessingParams object, the caller then
+ * passes it to PKIX_ValidateChain or PKIX_BuildChain, which uses it to call
+ * the user's callback functions as needed during the validation or building
+ * process.
+ *
+ * If a parameter is not set (or is set to NULL), it will be set to the
+ * default value for that parameter. The default value for the Date parameter
+ * is NULL, which indicates the current time when the path is validated. The
+ * default for the remaining parameters is the least constrained.
+ */
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_Create
+ * DESCRIPTION:
+ *
+ * Creates a new ProcessingParams object. Trust anchor list is set to
+ * newly created empty list of trust. In this case trust anchors will
+ * be taken from provided cert store. Pointed to the created
+ * ProcessingParams object is stored in "pParams".
+ *
+ * PARAMETERS:
+ * "anchors"
+ * Address of List of (non-empty) TrustAnchors to be used.
+ * Must be non-NULL.
+ * "pParams"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_Create(
+ PKIX_ProcessingParams **pParams,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetCertChainCheckers
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of CertChainCheckers (if any) that are set
+ * in the ProcessingParams pointed to by "params" and stores it at
+ * "pCheckers". Each CertChainChecker represents a custom certificate
+ * validation check used by PKIX_ValidateChain or PKIX_BuildChain as needed
+ * during the validation or building process. If "params" does not have any
+ * CertChainCheckers, this function stores an empty List at "pCheckers".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose List of CertChainCheckers (if any)
+ * are to be stored. Must be non-NULL.
+ * "pCheckers"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetCertChainCheckers(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pCheckers, /* list of PKIX_CertChainChecker */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetCertChainCheckers
+ * DESCRIPTION:
+ *
+ * Sets the ProcessingParams pointed to by "params" with a List of
+ * CertChainCheckers pointed to by "checkers". Each CertChainChecker
+ * represents a custom certificate validation check used by
+ * PKIX_ValidateChain or PKIX_BuildChain as needed during the validation or
+ * building process. If "checkers" is NULL, no CertChainCheckers will be used.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose List of CertChainCheckers is to be
+ * set. Must be non-NULL.
+ * "checkers"
+ * Address of List of CertChainCheckers to be set. If NULL, no
+ * CertChainCheckers will be used.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params" and "checkers"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetCertChainCheckers(
+ PKIX_ProcessingParams *params,
+ PKIX_List *checkers, /* list of PKIX_CertChainChecker */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_AddCertChainChecker
+ * DESCRIPTION:
+ *
+ * Adds the CertChainChecker pointed to by "checker" to the ProcessingParams
+ * pointed to by "params". The CertChainChecker represents a custom
+ * certificate validation check used by PKIX_ValidateChain or PKIX_BuildChain
+ * as needed during the validation or building process.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams to be added to. Must be non-NULL.
+ * "checker"
+ * Address of CertChainChecker to be added. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_AddCertChainChecker(
+ PKIX_ProcessingParams *params,
+ PKIX_CertChainChecker *checker,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetRevocationChecker
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the RevocationChecker that are set
+ * in the ProcessingParams pointed to by "params" and stores it at
+ * "pRevChecker". Each RevocationChecker represents a revocation
+ * check used by PKIX_ValidateChain or PKIX_BuildChain as needed during the
+ * validation or building process. If "params" does not have any
+ * RevocationCheckers, this function stores an empty List at "pRevChecker".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose List of RevocationCheckers
+ * is to be stored. Must be non-NULL.
+ * "pRevChecker"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetRevocationChecker(
+ PKIX_ProcessingParams *params,
+ PKIX_RevocationChecker **pChecker,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetRevocationChecker
+ * DESCRIPTION:
+ *
+ * Sets the ProcessingParams pointed to by "params" with a
+ * RevocationChecker pointed to by "revChecker". Revocation
+ * checker object should be created and assigned to processing
+ * parameters before chain build or validation can begin.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose List of RevocationCheckers is to be
+ * set. Must be non-NULL.
+ * "revChecker"
+ * Address of RevocationChecker to be set. Must be set before chain
+ * building or validation.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetRevocationChecker(
+ PKIX_ProcessingParams *params,
+ PKIX_RevocationChecker *revChecker,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetCertStores
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of CertStores (if any) that are set in the
+ * ProcessingParams pointed to by "params" and stores it at "pStores". Each
+ * CertStore represents a particular repository from which certificates and
+ * CRLs can be retrieved by PKIX_ValidateChain or PKIX_BuildChain as needed
+ * during the validation or building process. If "params" does not have any
+ * CertStores, this function stores an empty List at "pStores".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose List of CertStores (if any) are to
+ * be stored. Must be non-NULL.
+ * "pStores"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetCertStores(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pStores, /* list of PKIX_CertStore */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetCertStores
+ * DESCRIPTION:
+ *
+ * Sets the ProcessingParams pointed to by "params" with a List of CertStores
+ * pointed to by "stores". Each CertStore represents a particular repository
+ * from which certificates and CRLs can be retrieved by PKIX_ValidateChain or
+ * PKIX_BuildChain as needed during the validation or building process. If
+ * "stores" is NULL, no CertStores will be used.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose List of CertStores is to be set.
+ * Must be non-NULL.
+ * "stores"
+ * Address of List of CertStores to be set. If NULL, no CertStores will
+ * be used.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetCertStores(
+ PKIX_ProcessingParams *params,
+ PKIX_List *stores, /* list of PKIX_CertStore */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_AddCertStore
+ * DESCRIPTION:
+ *
+ * Adds the CertStore pointed to by "store" to the ProcessingParams pointed
+ * to by "params". The CertStore represents a particular repository from
+ * which certificates and CRLs can be retrieved by PKIX_ValidateChain or
+ * PKIX_BuildChain as needed during the validation or building process.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams to be added to. Must be non-NULL.
+ * "store"
+ * Address of CertStore to be added.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_AddCertStore(
+ PKIX_ProcessingParams *params,
+ PKIX_CertStore *store,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetDate
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the Date (if any) that is set in the
+ * ProcessingParams pointed to by "params" and stores it at "pDate". The
+ * Date represents the time for which the validation of the certificate chain
+ * should be determined. If "params" does not have any Date set, this function
+ * stores NULL at "pDate".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose Date (if any) is to be stored.
+ * Must be non-NULL.
+ * "pDate"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetDate(
+ PKIX_ProcessingParams *params,
+ PKIX_PL_Date **pDate,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetDate
+ * DESCRIPTION:
+ *
+ * Sets the ProcessingParams pointed to by "params" with a Date pointed to by
+ * "date". The Date represents the time for which the validation of the
+ * certificate chain should be determined. If "date" is NULL, the current
+ * time is used during validation.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose Date is to be set. Must be non-NULL.
+ * "date"
+ * Address of Date to be set. If NULL, current time is used.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetDate(
+ PKIX_ProcessingParams *params,
+ PKIX_PL_Date *date,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetInitialPolicies
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of OIDs (if any) that are set in the
+ * ProcessingParams pointed to by "params" and stores it at "pInitPolicies".
+ * Each OID represents an initial policy identifier, indicating that any
+ * one of these policies would be acceptable to the certificate user for
+ * the purposes of certification path processing. If "params" does not have
+ * any initial policies, this function stores an empty List at
+ * "pInitPolicies".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose List of OIDs (if any) are to be
+ * stored. Must be non-NULL.
+ * "pInitPolicies"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetInitialPolicies(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pInitPolicies, /* list of PKIX_PL_OID */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetInitialPolicies
+ * DESCRIPTION:
+ *
+ * Sets the ProcessingParams pointed to by "params" with a List of OIDs
+ * pointed to by "initPolicies".
+ *
+ * Each OID represents an initial policy identifier, indicating that any
+ * one of these policies would be acceptable to the certificate user for
+ * the purposes of certification path processing. By default, any policy
+ * is acceptable (i.e. all policies), so a user that wants to allow any
+ * policy as acceptable does not need to call this method. Similarly, if
+ * initPolicies is NULL or points to an empty List, all policies are
+ * acceptable.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose List of OIDs is to be set.
+ * Must be non-NULL.
+ * "initPolicies"
+ * Address of List of OIDs to be set. If NULL or if pointing to an empty
+ * List, all policies are acceptable.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetInitialPolicies(
+ PKIX_ProcessingParams *params,
+ PKIX_List *initPolicies, /* list of PKIX_PL_OID */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetPolicyQualifiersRejected
+ * DESCRIPTION:
+ *
+ * Checks whether the ProcessingParams pointed to by "params" indicate that
+ * policy qualifiers should be rejected and stores the Boolean result at
+ * "pRejected".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams used to determine whether or not policy
+ * qualifiers should be rejected. Must be non-NULL.
+ * "pRejected"
+ * Address where Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetPolicyQualifiersRejected(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pRejected,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetPolicyQualifiersRejected
+ * DESCRIPTION:
+ *
+ * Specifies in the ProcessingParams pointed to by "params" whether policy
+ * qualifiers are rejected using the Boolean value of "rejected".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams to be set. Must be non-NULL.
+ * "rejected"
+ * Boolean value indicating whether policy qualifiers are to be rejected.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetPolicyQualifiersRejected(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean rejected,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetTargetCertConstraints
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the CertSelector (if any) that is set in the
+ * ProcessingParams pointed to by "params" and stores it at "pConstraints".
+ * The CertSelector represents the constraints to be placed on the target
+ * certificate. If "params" does not have any CertSelector set, this function
+ * stores NULL at "pConstraints".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose CertSelector (if any) is to be
+ * stored. Must be non-NULL.
+ * "pConstraints"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetTargetCertConstraints(
+ PKIX_ProcessingParams *params,
+ PKIX_CertSelector **pConstraints,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetTargetCertConstraints
+ * DESCRIPTION:
+ *
+ * Sets the ProcessingParams pointed to by "params" with a CertSelector
+ * pointed to by "constraints". The CertSelector represents the constraints
+ * to be placed on the target certificate. If "constraints" is NULL, no
+ * constraints are defined.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose CertSelector is to be set.
+ * Must be non-NULL.
+ * "constraints"
+ * Address of CertSelector to be set. If NULL, no constraints are defined.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetTargetCertConstraints(
+ PKIX_ProcessingParams *params,
+ PKIX_CertSelector *constraints,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetTrustAnchors
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of TrustAnchors that are set in
+ * the ProcessingParams pointed to by "params" and stores it at "pAnchors".
+ * If the function succeeds, the pointer to the List is guaranteed to be
+ * non-NULL and the List is guaranteed to be non-empty.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose List of TrustAnchors are to
+ * be stored. Must be non-NULL.
+ * "pAnchors"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetTrustAnchors(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pAnchors, /* list of TrustAnchor */
+ void *plContext);
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetTrustAnchors
+ * DESCRIPTION:
+ *
+ * Sets user defined set of trust anchors. The handling of the trust anchors
+ * may be furthered alter via PKIX_ProcessingParams_SetUseOnlyTrustAnchors.
+ * By default, a certificate will be considered invalid if it does not chain
+ * to a trusted anchor from this list.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose List of TrustAnchors are to
+ * be stored. Must be non-NULL.
+ * "anchors"
+ * Address of the trust anchors list object. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetTrustAnchors(
+ PKIX_ProcessingParams *params,
+ PKIX_List *pAnchors, /* list of TrustAnchor */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetUseOnlyTrustAnchors
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the Boolean. The boolean value represents
+ * the switch value that is used to identify whether trust anchors, if
+ * specified, should be the exclusive source of trust information.
+ * If the function succeeds, the pointer to the Boolean is guaranteed to be
+ * non-NULL.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams. Must be non-NULL.
+ * "pUseOnlyTrustAnchors"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetUseOnlyTrustAnchors(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pUseOnlyTrustAnchors,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetUseOnlyTrustAnchors
+ * DESCRIPTION:
+ *
+ * Configures whether trust anchors are used as the exclusive source of trust.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams. Must be non-NULL.
+ * "useOnlyTrustAnchors"
+ * If true, indicates that trust anchors should be used exclusively when
+ * they have been specified via PKIX_ProcessingParams_SetTrustAnchors. A
+ * certificate will be considered invalid if it does not chain to a
+ * trusted anchor from that list.
+ * If false, indicates that the trust anchors are additive to whatever
+ * existing trust stores are configured. A certificate is considered
+ * valid if it chains to EITHER a trusted anchor from that list OR a
+ * certificate marked trusted in a trust store.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetUseOnlyTrustAnchors(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean useOnlyTrustAnchors,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetUseAIAForCertFetching
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the Boolean. The boolean value represents
+ * the switch value that is used to identify if url in cert AIA extension
+ * may be used for cert fetching.
+ * If the function succeeds, the pointer to the Boolean is guaranteed to be
+ * non-NULL.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams. Must be non-NULL.
+ * "pUseAIA"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetUseAIAForCertFetching(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pUseAIA, /* list of TrustAnchor */
+ void *plContext);
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetTrustAnchors
+ * DESCRIPTION:
+ *
+ * Sets switch value that defines if url in cert AIA extension
+ * may be used for cert fetching.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams.
+ * "useAIA"
+ * Address of the trust anchors list object. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetUseAIAForCertFetching(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean useAIA,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetQualifyTargetCert
+ * DESCRIPTION:
+ *
+ * Sets a boolean value that tells if libpkix needs to check that
+ * the target certificate satisfies the conditions set in processing
+ * parameters. Includes but not limited to date, ku and eku checks.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose List of TrustAnchors are to
+ * be stored. Must be non-NULL.
+ * "qualifyTargetCert"
+ * boolean value if set to true will trigger qualification of the
+ * target certificate.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetQualifyTargetCert(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean qualifyTargetCert,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetHintCerts
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a List of Certs supplied by the user as a suggested
+ * partial CertChain (subject to verification), that are set in the
+ * ProcessingParams pointed to by "params", and stores it at "pHintCerts".
+ * The List returned may be empty or NULL.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose List of TrustAnchors are to
+ * be stored. Must be non-NULL.
+ * "pHintCerts"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetHintCerts(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pHintCerts,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetHintCerts
+ * DESCRIPTION:
+ *
+ * Stores a pointer to a List of Certs supplied by the user as a suggested
+ * partial CertChain (subject to verification), as an element in the
+ * ProcessingParams pointed to by "params". The List may be empty or NULL.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose List of HintCerts is to be stored.
+ * Must be non-NULL.
+ * "hintCerts"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetHintCerts(
+ PKIX_ProcessingParams *params,
+ PKIX_List *hintCerts,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetResourceLimits
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the ResourceLimits (if any) that is set in the
+ * ProcessingParams pointed to by "params" and stores it at "pResourceLimits".
+ * The ResourceLimits represent the maximum resource usage that the caller
+ * desires (such as MaxTime). The ValidateChain or BuildChain call will not
+ * exceed these maximum limits. If "params" does not have any ResourceLimits
+ * set, this function stores NULL at "pResourceLimits".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose ResourceLimits (if any) are to be
+ * stored. Must be non-NULL.
+ * "pResourceLimits"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetResourceLimits(
+ PKIX_ProcessingParams *params,
+ PKIX_ResourceLimits **pResourceLimits,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetResourceLimits
+ * DESCRIPTION:
+ *
+ * Sets the ProcessingParams pointed to by "params" with a ResourceLimits
+ * object pointed to by "resourceLimits". The ResourceLimits represent the
+ * maximum resource usage that the caller desires (such as MaxTime). The
+ * ValidateChain or BuildChain call will not exceed these maximum limits.
+ * If "resourceLimits" is NULL, no ResourceLimits are defined.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams whose ResourceLimits are to be set.
+ * Must be non-NULL.
+ * "resourceLimits"
+ * Address of ResourceLimits to be set. If NULL, no limits are defined.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetResourceLimits(
+ PKIX_ProcessingParams *params,
+ PKIX_ResourceLimits *resourceLimits,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_IsAnyPolicyInhibited
+ * DESCRIPTION:
+ *
+ * Checks whether the ProcessingParams pointed to by "params" indicate that
+ * anyPolicy is inhibited and stores the Boolean result at "pInhibited".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams used to determine whether or not anyPolicy
+ * inhibited. Must be non-NULL.
+ * "pInhibited"
+ * Address where Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_IsAnyPolicyInhibited(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pInhibited,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetAnyPolicyInhibited
+ * DESCRIPTION:
+ *
+ * Specifies in the ProcessingParams pointed to by "params" whether anyPolicy
+ * is inhibited using the Boolean value of "inhibited".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams to be set. Must be non-NULL.
+ * "inhibited"
+ * Boolean value indicating whether anyPolicy is to be inhibited.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetAnyPolicyInhibited(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean inhibited,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_IsExplicitPolicyRequired
+ * DESCRIPTION:
+ *
+ * Checks whether the ProcessingParams pointed to by "params" indicate that
+ * explicit policies are required and stores the Boolean result at
+ * "pRequired".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams used to determine whether or not explicit
+ * policies are required. Must be non-NULL.
+ * "pRequired"
+ * Address where Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_IsExplicitPolicyRequired(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pRequired,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetExplicitPolicyRequired
+ * DESCRIPTION:
+ *
+ * Specifies in the ProcessingParams pointed to by "params" whether explicit
+ * policies are required using the Boolean value of "required".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams to be set. Must be non-NULL.
+ * "required"
+ * Boolean value indicating whether explicit policies are to be required.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetExplicitPolicyRequired(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean required,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_IsPolicyMappingInhibited
+ * DESCRIPTION:
+ *
+ * Checks whether the ProcessingParams pointed to by "params" indicate that
+ * policyMapping is inhibited and stores the Boolean result at "pInhibited".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams used to determine whether or not policy
+ * mappings are inhibited. Must be non-NULL.
+ * "pInhibited"
+ * Address where Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_IsPolicyMappingInhibited(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pInhibited,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetPolicyMappingInhibited
+ * DESCRIPTION:
+ *
+ * Specifies in the ProcessingParams pointed to by "params" whether policy
+ * mapping is inhibited using the Boolean value of "inhibited".
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ProcessingParams to be set. Must be non-NULL.
+ * "inhibited"
+ * Boolean value indicating whether policy mapping is to be inhibited.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetPolicyMappingInhibited(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean inhibited,
+ void *plContext);
+
+
+/* PKIX_ValidateParams
+ *
+ * PKIX_ValidateParams consists of a ProcessingParams object as well as the
+ * List of Certs (certChain) that the caller is trying to validate.
+ */
+
+/*
+ * FUNCTION: PKIX_ValidateParams_Create
+ * DESCRIPTION:
+ *
+ * Creates a new ValidateParams object and stores it at "pParams".
+ *
+ * PARAMETERS:
+ * "procParams"
+ * Address of ProcessingParams to be used. Must be non-NULL.
+ * "chain"
+ * Address of List of Certs (certChain) to be validated. Must be non-NULL.
+ * "pParams"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ValidateParams_Create(
+ PKIX_ProcessingParams *procParams,
+ PKIX_List *chain,
+ PKIX_ValidateParams **pParams,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ValidateParams_GetProcessingParams
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the ProcessingParams that represent the basic
+ * certificate processing parameters used during chain validation and chain
+ * building from the ValidateParams pointed to by "valParams" and stores it
+ * at "pProcParams". If the function succeeds, the pointer to the
+ * ProcessingParams is guaranteed to be non-NULL.
+ *
+ * PARAMETERS:
+ * "valParams"
+ * Address of ValidateParams whose ProcessingParams are to be stored.
+ * Must be non-NULL.
+ * "pProcParams"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ValidateParams_GetProcessingParams(
+ PKIX_ValidateParams *valParams,
+ PKIX_ProcessingParams **pProcParams,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ValidateParams_GetCertChain
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of Certs (certChain) that is set in the
+ * ValidateParams pointed to by "valParams" and stores it at "pChain". If the
+ * function succeeds, the pointer to the CertChain is guaranteed to be
+ * non-NULL.
+ *
+ * PARAMETERS:
+ * "valParams"
+ * Address of ValidateParams whose CertChain is to be stored.
+ * Must be non-NULL.
+ * "pChain"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ValidateParams_GetCertChain(
+ PKIX_ValidateParams *valParams,
+ PKIX_List **pChain,
+ void *plContext);
+
+/* PKIX_TrustAnchor
+ *
+ * A PKIX_TrustAnchor represents a trusted entity and can be specified using a
+ * self-signed certificate or using the trusted CA's name and public key. In
+ * order to limit the trust in the trusted entity, name constraints can also
+ * be imposed on the trust anchor.
+ */
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_CreateWithCert
+ * DESCRIPTION:
+ *
+ * Creates a new TrustAnchor object using the Cert pointed to by "cert" as
+ * the trusted certificate and stores it at "pAnchor". Once created, a
+ * TrustAnchor is immutable.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert to use as trusted certificate. Must be non-NULL.
+ * "pAnchor"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_TrustAnchor_CreateWithCert(
+ PKIX_PL_Cert *cert,
+ PKIX_TrustAnchor **pAnchor,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_CreateWithNameKeyPair
+ * DESCRIPTION:
+ *
+ * Creates a new TrustAnchor object using the X500Name pointed to by "name",
+ * and the PublicKey pointed to by "pubKey" and stores it at "pAnchor". The
+ * CertNameConstraints pointed to by "nameConstraints" (if any) are used to
+ * limit the trust placed in this trust anchor. To indicate that name
+ * constraints don't apply, set "nameConstraints" to NULL. Once created, a
+ * TrustAnchor is immutable.
+ *
+ * PARAMETERS:
+ * "name"
+ * Address of X500Name to use as name of trusted CA. Must be non-NULL.
+ * "pubKey"
+ * Address of PublicKey to use as trusted public key. Must be non-NULL.
+ * "nameConstraints"
+ * Address of CertNameConstraints to use as initial name constraints.
+ * If NULL, no name constraints are applied.
+ * "pAnchor"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_TrustAnchor_CreateWithNameKeyPair(
+ PKIX_PL_X500Name *name,
+ PKIX_PL_PublicKey *pubKey,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_TrustAnchor **pAnchor,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_GetTrustedCert
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the Cert that is set in the TrustAnchor pointed to
+ * by "anchor" and stores it at "pCert". If "anchor" does not have a Cert
+ * set, this function stores NULL at "pCert".
+ *
+ * PARAMETERS:
+ * "anchor"
+ * Address of TrustAnchor whose Cert is to be stored. Must be non-NULL.
+ * "pChain"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_TrustAnchor_GetTrustedCert(
+ PKIX_TrustAnchor *anchor,
+ PKIX_PL_Cert **pCert,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_GetCAName
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the CA's X500Name (if any) that is set in the
+ * TrustAnchor pointed to by "anchor" and stores it at "pCAName". If "anchor"
+ * does not have an X500Name set, this function stores NULL at "pCAName".
+ *
+ * PARAMETERS:
+ * "anchor"
+ * Address of TrustAnchor whose CA Name is to be stored. Must be non-NULL.
+ * "pCAName"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_TrustAnchor_GetCAName(
+ PKIX_TrustAnchor *anchor,
+ PKIX_PL_X500Name **pCAName,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_GetCAPublicKey
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the CA's PublicKey (if any) that is set in the
+ * TrustAnchor pointed to by "anchor" and stores it at "pPubKey". If "anchor"
+ * does not have a PublicKey set, this function stores NULL at "pPubKey".
+ *
+ * PARAMETERS:
+ * "anchor"
+ * Address of TrustAnchor whose CA PublicKey is to be stored.
+ * Must be non-NULL.
+ * "pPubKey"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_TrustAnchor_GetCAPublicKey(
+ PKIX_TrustAnchor *anchor,
+ PKIX_PL_PublicKey **pPubKey,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_GetNameConstraints
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the CertNameConstraints (if any) set in the
+ * TrustAnchor pointed to by "anchor" and stores it at "pConstraints". If
+ * "anchor" does not have any CertNameConstraints set, this function stores
+ * NULL at "pConstraints".
+ *
+ * PARAMETERS:
+ * "anchor"
+ * Address of TrustAnchor whose CertNameConstraints are to be stored.
+ * Must be non-NULL.
+ * "pConstraints"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Params Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_TrustAnchor_GetNameConstraints(
+ PKIX_TrustAnchor *anchor,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext);
+
+/* PKIX_ResourceLimits
+ *
+ * A PKIX_ResourceLimits object represents the maximum resource usage that
+ * the caller desires. The ValidateChain or BuildChain call
+ * will not exceed these maximum limits. For example, the caller may want
+ * a timeout value of 1 minute, meaning that if the ValidateChain or
+ * BuildChain function is unable to finish in 1 minute, it should abort
+ * with an Error.
+ */
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_Create
+ * DESCRIPTION:
+ *
+ * Creates a new ResourceLimits object and stores it at "pResourceLimits".
+ *
+ * PARAMETERS:
+ * "pResourceLimits"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a ResourceLimits Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ResourceLimits_Create(
+ PKIX_ResourceLimits **pResourceLimits,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxTime
+ * DESCRIPTION:
+ *
+ * Retrieves a PKIX_UInt32 (if any) representing the maximum time that is
+ * set in the ResourceLimits object pointed to by "resourceLimits" and stores
+ * it at "pMaxTime". This maximum time (in seconds) should not be exceeded
+ * by the function whose ProcessingParams contain this ResourceLimits object
+ * (typically ValidateChain or BuildChain). It essentially functions as a
+ * time-out value and is only appropriate if blocking I/O is being used.
+ *
+ * PARAMETERS:
+ * "resourceLimits"
+ * Address of ResourceLimits object whose maximum time (in seconds) is
+ * to be stored. Must be non-NULL.
+ * "pMaxTime"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a ResourceLimits Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxTime(
+ PKIX_ResourceLimits *resourceLimits,
+ PKIX_UInt32 *pMaxTime,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxTime
+ * DESCRIPTION:
+ *
+ * Sets the maximum time of the ResourceLimits object pointed to by
+ * "resourceLimits" using the PKIX_UInt32 value of "maxTime". This
+ * maximum time (in seconds) should not be exceeded by the function
+ * whose ProcessingParams contain this ResourceLimits object
+ * (typically ValidateChain or BuildChain). It essentially functions as a
+ * time-out value and is only appropriate if blocking I/O is being used.
+ *
+ * PARAMETERS:
+ * "resourceLimits"
+ * Address of ResourceLimits object whose maximum time (in seconds) is
+ * to be set. Must be non-NULL.
+ * "maxTime"
+ * Value of PKIX_UInt32 representing the maximum time (in seconds)
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a ResourceLimits Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxTime(
+ PKIX_ResourceLimits *resourceLimits,
+ PKIX_UInt32 maxTime,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxFanout
+ * DESCRIPTION:
+ *
+ * Retrieves a PKIX_UInt32 (if any) representing the maximum fanout that is
+ * set in the ResourceLimits object pointed to by "resourceLimits" and stores
+ * it at "pMaxFanout". This maximum fanout (number of certs) should not be
+ * exceeded by the function whose ProcessingParams contain this ResourceLimits
+ * object (typically ValidateChain or BuildChain). If the builder encounters
+ * more than this maximum number of certificates when searching for the next
+ * candidate certificate, it should abort and return an error. This
+ * parameter is only relevant for ValidateChain if it needs to internally call
+ * BuildChain (e.g. in order to build the chain to a CRL's issuer).
+ *
+ * PARAMETERS:
+ * "resourceLimits"
+ * Address of ResourceLimits object whose maximum fanout (number of certs)
+ * is to be stored. Must be non-NULL.
+ * "pMaxFanout"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a ResourceLimits Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxFanout(
+ PKIX_ResourceLimits *resourceLimits,
+ PKIX_UInt32 *pMaxFanout,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxFanout
+ * DESCRIPTION:
+ *
+ * Sets the maximum fanout of the ResourceLimits object pointed to by
+ * "resourceLimits" using the PKIX_UInt32 value of "maxFanout". This maximum
+ * fanout (number of certs) should not be exceeded by the function whose
+ * ProcessingParams contain this ResourceLimits object (typically ValidateChain
+ * or BuildChain). If the builder encounters more than this maximum number of
+ * certificates when searching for the next candidate certificate, it should
+ * abort and return an Error. This parameter is only relevant for ValidateChain
+ * if it needs to internally call BuildChain (e.g. in order to build the
+ * chain to a CRL's issuer).
+ *
+ * PARAMETERS:
+ * "resourceLimits"
+ * Address of ResourceLimits object whose maximum fanout (number of certs)
+ * is to be set. Must be non-NULL.
+ * "maxFanout"
+ * Value of PKIX_UInt32 representing the maximum fanout (number of certs)
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a ResourceLimits Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxFanout(
+ PKIX_ResourceLimits *resourceLimits,
+ PKIX_UInt32 maxFanout,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxDepth
+ * DESCRIPTION:
+ *
+ * Retrieves a PKIX_UInt32 (if any) representing the maximum depth that is
+ * set in the ResourceLimits object pointed to by "resourceLimits" and stores
+ * it at "pMaxDepth". This maximum depth (number of certs) should not be
+ * exceeded by the function whose ProcessingParams contain this ResourceLimits
+ * object (typically ValidateChain or BuildChain). If the builder encounters
+ * more than this maximum number of certificates when searching for the next
+ * candidate certificate, it should abort and return an error. This
+ * parameter is only relevant for ValidateChain if it needs to internally call
+ * BuildChain (e.g. in order to build the chain to a CRL's issuer).
+ *
+ * PARAMETERS:
+ * "resourceLimits"
+ * Address of ResourceLimits object whose maximum depth (number of certs)
+ * is to be stored. Must be non-NULL.
+ * "pMaxDepth"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a ResourceLimits Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxDepth(
+ PKIX_ResourceLimits *resourceLimits,
+ PKIX_UInt32 *pMaxDepth,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxDepth
+ * DESCRIPTION:
+ *
+ * Sets the maximum depth of the ResourceLimits object pointed to by
+ * "resourceLimits" using the PKIX_UInt32 value of "maxDepth". This maximum
+ * depth (number of certs) should not be exceeded by the function whose
+ * ProcessingParams contain this ResourceLimits object (typically ValidateChain
+ * or BuildChain). If the builder encounters more than this maximum number of
+ * certificates when searching for the next candidate certificate, it should
+ * abort and return an Error. This parameter is only relevant for ValidateChain
+ * if it needs to internally call BuildChain (e.g. in order to build the
+ * chain to a CRL's issuer).
+ *
+ * PARAMETERS:
+ * "resourceLimits"
+ * Address of ResourceLimits object whose maximum depth (number of certs)
+ * is to be set. Must be non-NULL.
+ * "maxDepth"
+ * Value of PKIX_UInt32 representing the maximum depth (number of certs)
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a ResourceLimits Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxDepth(
+ PKIX_ResourceLimits *resourceLimits,
+ PKIX_UInt32 maxDepth,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxNumberOfCerts
+ * DESCRIPTION:
+ *
+ * Retrieves a PKIX_UInt32 (if any) representing the maximum number of traversed
+ * certs that is set in the ResourceLimits object pointed to by "resourceLimits"
+ * and stores it at "pMaxNumber". This maximum number of traversed certs should
+ * not be exceeded by the function whose ProcessingParams contain this ResourceLimits
+ * object (typically ValidateChain or BuildChain). If the builder traverses more
+ * than this number of certs during the build process, it should abort and
+ * return an Error. This parameter is only relevant for ValidateChain if it
+ * needs to internally call BuildChain (e.g. in order to build the chain to a
+ * CRL's issuer).
+ *
+ * PARAMETERS:
+ * "resourceLimits"
+ * Address of ResourceLimits object whose maximum number of traversed certs
+ * is to be stored. Must be non-NULL.
+ * "pMaxNumber"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a ResourceLimits Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxNumberOfCerts(
+ PKIX_ResourceLimits *resourceLimits,
+ PKIX_UInt32 *pMaxNumber,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxNumberOfCerts
+ * DESCRIPTION:
+ *
+ * Sets the maximum number of traversed certs of the ResourceLimits object
+ * pointed to by "resourceLimits" using the PKIX_UInt32 value of "maxNumber".
+ * This maximum number of traversed certs should not be exceeded by the function
+ * whose ProcessingParams contain this ResourceLimits object (typically ValidateChain
+ * or BuildChain). If the builder traverses more than this number of certs
+ * during the build process, it should abort and return an Error. This parameter
+ * is only relevant for ValidateChain if it needs to internally call BuildChain
+ * (e.g. in order to build the chain to a CRL's issuer).
+ *
+ * PARAMETERS:
+ * "resourceLimits"
+ * Address of ResourceLimits object whose maximum number of traversed certs
+ * is to be set. Must be non-NULL.
+ * "maxNumber"
+ * Value of PKIX_UInt32 representing the maximum number of traversed certs
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a ResourceLimits Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxNumberOfCerts(
+ PKIX_ResourceLimits *resourceLimits,
+ PKIX_UInt32 maxNumber,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxNumberOfCRLs
+ * DESCRIPTION:
+ *
+ * Retrieves a PKIX_UInt32 (if any) representing the maximum number of traversed
+ * CRLs that is set in the ResourceLimits object pointed to by "resourceLimits"
+ * and stores it at "pMaxNumber". This maximum number of traversed CRLs should
+ * not be exceeded by the function whose ProcessingParams contain this ResourceLimits
+ * object (typically ValidateChain or BuildChain). If the builder traverses more
+ * than this number of CRLs during the build process, it should abort and
+ * return an Error. This parameter is only relevant for ValidateChain if it
+ * needs to internally call BuildChain (e.g. in order to build the chain to a
+ * CRL's issuer).
+ *
+ * PARAMETERS:
+ * "resourceLimits"
+ * Address of ResourceLimits object whose maximum number of traversed CRLs
+ * is to be stored. Must be non-NULL.
+ * "pMaxNumber"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a ResourceLimits Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxNumberOfCRLs(
+ PKIX_ResourceLimits *resourceLimits,
+ PKIX_UInt32 *pMaxNumber,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxNumberOfCRLs
+ * DESCRIPTION:
+ *
+ * Sets the maximum number of traversed CRLs of the ResourceLimits object
+ * pointed to by "resourceLimits" using the PKIX_UInt32 value of "maxNumber".
+ * This maximum number of traversed CRLs should not be exceeded by the function
+ * whose ProcessingParams contain this ResourceLimits object (typically ValidateChain
+ * or BuildChain). If the builder traverses more than this number of CRLs
+ * during the build process, it should abort and return an Error. This parameter
+ * is only relevant for ValidateChain if it needs to internally call BuildChain
+ * (e.g. in order to build the chain to a CRL's issuer).
+ *
+ * PARAMETERS:
+ * "resourceLimits"
+ * Address of ResourceLimits object whose maximum number of traversed CRLs
+ * is to be set. Must be non-NULL.
+ * "maxNumber"
+ * Value of PKIX_UInt32 representing the maximum number of traversed CRLs
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "params"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a ResourceLimits Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxNumberOfCRLs(
+ PKIX_ResourceLimits *resourceLimits,
+ PKIX_UInt32 maxNumber,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PARAMS_H */
diff --git a/security/nss/lib/libpkix/include/pkix_pl_pki.h b/security/nss/lib/libpkix/include/pkix_pl_pki.h
new file mode 100644
index 0000000000..0a449b94a7
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkix_pl_pki.h
@@ -0,0 +1,2735 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 file defines several platform independent functions to
+ * manipulate certificates and CRLs in a portable manner.
+ *
+ */
+
+#ifndef _PKIX_PL_PKI_H
+#define _PKIX_PL_PKI_H
+
+#include "pkixt.h"
+#include "seccomon.h"
+#include "certt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General
+ *
+ * Please refer to the libpkix Programmer's Guide for detailed information
+ * about how to use the libpkix library. Certain key warnings and notices from
+ * that document are repeated here for emphasis.
+ *
+ * All identifiers in this file (and all public identifiers defined in
+ * libpkix) begin with "PKIX_". Private identifiers only intended for use
+ * within the library begin with "pkix_".
+ *
+ * A function returns NULL upon success, and a PKIX_Error pointer upon failure.
+ *
+ * Unless otherwise noted, for all accessor (gettor) functions that return a
+ * PKIX_PL_Object pointer, callers should assume that this pointer refers to a
+ * shared object. Therefore, the caller should treat this shared object as
+ * read-only and should not modify this shared object. When done using the
+ * shared object, the caller should release the reference to the object by
+ * using the PKIX_PL_Object_DecRef function.
+ *
+ * While a function is executing, if its arguments (or anything referred to by
+ * its arguments) are modified, free'd, or destroyed, the function's behavior
+ * is undefined.
+ *
+ */
+
+/*
+ * Cert
+ *
+ * A Cert represents an X.509 certificate. It can be created using the bytes
+ * of a valid ASN.1 DER encoding. Once created, a Cert is immutable. The
+ * following functions include accessors (gettors) for the various components
+ * of an X.509 certificate. Also included are functions to perform various
+ * checks on a certificate, including name constraints, key usage, validity
+ * (expiration), and signature verification.
+ */
+
+/*
+ * FUNCTION: PKIX_PL_Cert_Create
+ * DESCRIPTION:
+ *
+ * Creates a new certificate using the bytes in the ByteArray pointed to by
+ * "byteArray" and stores it at "pCert". If the bytes are not a valid ASN.1
+ * DER encoding of a certificate, a PKIX_Error pointer is returned. Once
+ * created, a Cert is immutable.
+ *
+ * Certificate ::= SEQUENCE {
+ * tbsCertificate TBSCertificate,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ *
+ * TBSCertificate ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ * -- If present, version MUST be v2 or v3
+ * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ * -- If present, version MUST be v2 or v3
+ * extensions [3] EXPLICIT Extensions OPTIONAL
+ * -- If present, version MUST be v3
+ * }
+ *
+ * Version ::= INTEGER { v1(0), v2(1), v3(2) }
+ *
+ * CertificateSerialNumber ::= INTEGER
+ *
+ * Validity ::= SEQUENCE {
+ * notBefore Time,
+ * notAfter Time }
+ *
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ *
+ * UniqueIdentifier ::= BIT STRING
+ *
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ *
+ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+ *
+ * Extension ::= SEQUENCE {
+ * extnID OBJECT IDENTIFIER,
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING }
+ *
+ * PARAMETERS:
+ * "byteArray"
+ * Address of ByteArray representing the CERT's DER encoding.
+ * Must be non-NULL.
+ * "pCert"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_Create(
+ PKIX_PL_ByteArray *byteArray,
+ PKIX_PL_Cert **pCert,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_CreateFromCERTCertificate
+ * DESCRIPTION:
+ *
+ * Creates a new certificate using passed in CERTCertificate object.
+ *
+ * PARAMETERS:
+ * "nssCert"
+ * The object that will be used to create new PKIX_PL_Cert.
+ * "pCert"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_CreateFromCERTCertificate(
+ const CERTCertificate *nssCert,
+ PKIX_PL_Cert **pCert,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetCERTCertificate
+ * DESCRIPTION:
+ *
+ * Returns underlying CERTCertificate structure. Return CERTCertificate
+ * object is duplicated and should be destroyed by caller.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of PKIX_PL_Cert. Must be non-NULL.
+ * "pCert"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetCERTCertificate(
+ PKIX_PL_Cert *cert,
+ CERTCertificate **pnssCert,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetVersion
+ * DESCRIPTION:
+ *
+ * Retrieves the version of the Cert pointed to by "cert" and stores it at
+ * "pVersion". The version number will either be 0, 1, or 2 (corresponding to
+ * v1, v2, or v3, respectively).
+ *
+ * Version ::= INTEGER { v1(0), v2(1), v3(2) }
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose version is to be stored. Must be non-NULL.
+ * "pVersion"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetVersion(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 *pVersion,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSerialNumber
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the BigInt that represents the serial number of the
+ * Cert pointed to by "cert" and stores it at "pSerialNumber".
+ *
+ * CertificateSerialNumber ::= INTEGER
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose serial number is to be stored. Must be non-NULL.
+ * "pSerial"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSerialNumber(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_BigInt **pSerial,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetIssuer
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the X500Name that represents the issuer DN of the
+ * Cert pointed to by "cert" and stores it at "pIssuer".
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose issuer is to be stored. Must be non-NULL.
+ * "pIssuer"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetIssuer(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_X500Name **pIssuer,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubject
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the X500Name that represents the subject DN of the
+ * Cert pointed to by "cert" and stores it at "pSubject". If the Cert does not
+ * have a subject DN, this function stores NULL at "pSubject".
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose subject is to be stored. Must be non-NULL.
+ * "pSubject"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubject(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_X500Name **pSubject,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKeyAlgId
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the OID that represents the subject public key
+ * algorithm of the Cert pointed to by "cert" and stores it at
+ * "pSubjKeyAlgId".
+ *
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose subject public key algorithm OID is to be stored.
+ * Must be non-NULL.
+ * "pSubjKeyAlgId"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectPublicKeyAlgId(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_OID **pSubjKeyAlgId,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKey
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the PublicKey that represents the subject public key
+ * of the Cert pointed to by "cert" and stores it at "pPublicKey".
+ *
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose subject public key is to be stored.
+ * Must be non-NULL.
+ * "pPublicKey"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectPublicKey(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_PublicKey **pPublicKey,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_PublicKey_NeedsDSAParameters
+ * DESCRIPTION:
+ *
+ * Determines if the PublicKey pointed to by "pubKey" is a DSA Key with null
+ * parameters and stores the result at "pNeedsParams".
+ *
+ * PARAMETERS:
+ * "pubKey"
+ * Address of the Public Key of interest. Must be non-NULL.
+ * "pNeedsParams"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a PublicKey Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_PublicKey_NeedsDSAParameters(
+ PKIX_PL_PublicKey *pubKey,
+ PKIX_Boolean *pNeedsParams,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_PublicKey_MakeInheritedDSAPublicKey
+ * DESCRIPTION:
+ *
+ * This function is used for DSA key parameter inheritance, which allows a
+ * first DSA key with omitted parameters (pointed to by "firstKey") to inherit
+ * the PQG parameters of a second DSA key that does have parameters. (pointed
+ * to by "secondKey"). Once created, a PublicKey is immutable.
+ *
+ * Specifically, the algorithm used by the function is:
+ *
+ * If the first PublicKey is not a DSA public key with omitted parameters,
+ * the function stores NULL at "pResultKey". (No Error is returned)
+ * Else if the second PublicKey is not a DSA public key with non-NULL,
+ * parameters, the function returns an Error.
+ * Else
+ * the function creates a third PublicKey with a "Y" value from the
+ * first PublicKey and the DSA parameters from the second PublicKey,
+ * and stores it at "pResultKey".
+ *
+ * PARAMETERS:
+ * "firstKey"
+ * Address of a Public Key that needs to inherit DSA parameters.
+ * Must be non-NULL.
+ * "secondKey"
+ * Address of a Public Key that has DSA parameters that will be inherited
+ * by "firstKey". Must be non-NULL.
+ * "pResultKey"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a PublicKey Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_PublicKey_MakeInheritedDSAPublicKey(
+ PKIX_PL_PublicKey *firstKey,
+ PKIX_PL_PublicKey *secondKey,
+ PKIX_PL_PublicKey **pResultKey,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetCriticalExtensionOIDs
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of OIDs (each OID corresponding to a
+ * critical extension of the Cert pointed to by "cert") and stores it at
+ * "pExtensions". If "cert" does not have any critical extensions, this
+ * function stores an empty List at "pExtensions".
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose critical extension OIDs are to be stored.
+ * Must be non-NULL.
+ * "pExtensions"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetCriticalExtensionOIDs(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pExtensions, /* list of PKIX_PL_OID */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetAuthorityKeyIdentifier
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a ByteArray representing the authority key
+ * identifier extension of the Cert pointed to by "cert" and stores it at
+ * "pAuthKeyId".
+ *
+ * Note that this function only retrieves the keyIdentifier component
+ * (OCTET STRING) of the AuthorityKeyIdentifier extension, when present.
+ *
+ * If "cert" does not have an AuthorityKeyIdentifier extension or if the
+ * keyIdentifier component of the AuthorityKeyIdentifier extension is not
+ * present, this function stores NULL at "pAuthKeyId".
+ *
+ * AuthorityKeyIdentifier ::= SEQUENCE {
+ * keyIdentifier [0] KeyIdentifier OPTIONAL,
+ * authorityCertIssuer [1] GeneralNames OPTIONAL,
+ * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose authority key identifier is to be stored.
+ * Must be non-NULL.
+ * "pAuthKeyId"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetAuthorityKeyIdentifier(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_ByteArray **pAuthKeyId,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectKeyIdentifier
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a ByteArray representing the subject key identifier
+ * extension of the Cert pointed to by "cert" and stores it at "pSubjKeyId".
+ * If "cert" does not have a SubjectKeyIdentifier extension, this function
+ * stores NULL at "pSubjKeyId".
+ *
+ * SubjectKeyIdentifier ::= KeyIdentifier
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose subject key identifier is to be stored.
+ * Must be non-NULL.
+ * "pSubjKeyId"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectKeyIdentifier(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_ByteArray **pSubjKeyId,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of GeneralNames (each GeneralName
+ * representing a subject alternative name found in the subject alternative
+ * names extension of the Cert pointed to by "cert") and stores it at
+ * "pSubjectAltNames". If "cert" does not have a SubjectAlternativeNames
+ * extension, this function stores NULL at "pSubjectAltNames".
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * SubjectAltName ::= GeneralNames
+ *
+ * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+ *
+ * GeneralName ::= CHOICE {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER }
+ *
+ * OtherName ::= SEQUENCE {
+ * type-id OBJECT IDENTIFIER,
+ * value [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * EDIPartyName ::= SEQUENCE {
+ * nameAssigner [0] DirectoryString OPTIONAL,
+ * partyName [1] DirectoryString }
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose subjectAltNames are to be stored.
+ * Must be non-NULL.
+ * "pSubjectAltNames"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectAltNames(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pSubjectAltNames, /* list of PKIX_PL_GeneralName */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of GeneralNames (each GeneralName
+ * representing a subject DN or a subject alternative name found in the
+ * subject alternative names extension of the Cert pointed to by "cert") and
+ * stores it at "pAllSubjectNames".If the Subject DN of "cert" is empty and
+ * it does not have a SubjectAlternativeNames extension, this function stores
+ * NULL at "pAllSubjectNames".
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose subject DN and subjectAltNames are to be stored.
+ * Must be non-NULL.
+ * "pAllSubjectNames"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetAllSubjectNames(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pAllSubjectNames, /* list of PKIX_PL_GeneralName */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetExtendedKeyUsage
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a List of OIDs (each OID corresponding to an
+ * extended key usage of the Cert pointed to by "cert") and stores it at
+ * "pKeyUsage". If "cert" does not have an extended key usage extension, this
+ * function stores a NULL at "pKeyUsage".
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+ *
+ * KeyPurposeId ::= OBJECT IDENTIFIER
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose extended key usage OIDs are to be stored.
+ * Must be non-NULL.
+ * "pKeyUsage"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetExtendedKeyUsage(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pKeyUsage, /* list of PKIX_PL_OID */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetNameConstraints
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a CertNameConstraints object representing the name
+ * constraints extension of the Cert pointed to by "cert" and stores it at
+ * "pNameConstraints".
+ *
+ * If "cert" does not have a name constraints extension, this function stores
+ * NULL at "pNameConstraints".
+ *
+ * NameConstraints ::= SEQUENCE {
+ * permittedSubtrees [0] GeneralSubtrees OPTIONAL,
+ * excludedSubtrees [1] GeneralSubtrees OPTIONAL }
+ *
+ * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
+ *
+ * GeneralSubtree ::= SEQUENCE {
+ * base GeneralName,
+ * minimum [0] BaseDistance DEFAULT 0,
+ * maximum [1] BaseDistance OPTIONAL }
+ *
+ * BaseDistance ::= INTEGER (0..MAX)
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose name constraints extension is to be stored.
+ * Must be non-NULL.
+ * "pNameConstraints"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetNameConstraints(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetBasicConstraints
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a CertBasicConstraints object representing the basic
+ * constraints extension of the Cert pointed to by "cert" and stores it at
+ * "pBasicConstraints".
+ *
+ * If "cert" does not have a basic constraints extension, this function stores
+ * NULL at "pBasicConstraints". Once created, a CertBasicConstraints object
+ * is immutable.
+ *
+ * BasicConstraints ::= SEQUENCE {
+ * cA BOOLEAN DEFAULT FALSE,
+ * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose basic constraints extension is to be stored.
+ * Must be non-NULL.
+ * "pBasicConstraints"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetBasicConstraints(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_CertBasicConstraints **pBasicConstraints,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_BasicConstraints_GetCAFlag
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a Boolean value representing the cA Flag component
+ * of the CertBasicConstraints object pointed to by "basicConstraints" and
+ * stores it at "pResult".
+ *
+ * BasicConstraints ::= SEQUENCE {
+ * cA BOOLEAN DEFAULT FALSE,
+ * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
+ *
+ * PARAMETERS:
+ * "basicConstraints"
+ * Address of CertBasicConstraints whose cA Flag is to be stored.
+ * Must be non-NULL.
+ * "pResult"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_BasicConstraints_GetCAFlag(
+ PKIX_PL_CertBasicConstraints *basicConstraints,
+ PKIX_Boolean *pResult,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_BasicConstraints_GetPathLenConstraint
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to an integer value representing the pathLenConstraint
+ * component of the CertBasicConstraints object pointed to by
+ * "basicConstraints" and stores it at "pPathLenConstraint". If the
+ * pathLenConstraint component is not present, this function stores -1 at
+ * "pPathLenConstraint".
+ *
+ * PARAMETERS:
+ * "basicConstraints"
+ * Address of CertBasicConstraints whose pathLen is to be stored.
+ * Must be non-NULL.
+ * "pPathLenConstraint"
+ * Address where PKIX_Int32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_BasicConstraints_GetPathLenConstraint(
+ PKIX_PL_CertBasicConstraints *basicConstraints,
+ PKIX_Int32 *pPathLenConstraint,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetPolicyInformation
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a List of CertPolicyInfos found in the certificate
+ * policies extension of the Cert pointed to by "cert" and stores it at
+ * "pPolicyInfo". If "cert" does not have a certificate policies extension,
+ * this function stores NULL at "pPolicyInfo". Once created, a CertPolicyInfo
+ * object is immutable.
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
+ *
+ * PolicyInformation ::= SEQUENCE {
+ * policyIdentifier CertPolicyId,
+ * policyQualifiers SEQUENCE SIZE (1..MAX) OF
+ * PolicyQualifierInfo OPTIONAL }
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose CertPolicyInfos are to be stored.
+ * Must be non-NULL.
+ * "pPolicyInfo"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetPolicyInformation(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pPolicyInfo, /* list of PKIX_PL_CertPolicyInfo */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_CertPolicyInfo_GetPolicyId
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to an OID representing the policyIdentifier of the
+ * CertPolicyInfo pointed to by "policyInfo" and stores it at "pCertPolicyId".
+ *
+ * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
+ *
+ * PolicyInformation ::= SEQUENCE {
+ * policyIdentifier CertPolicyId,
+ * policyQualifiers SEQUENCE SIZE (1..MAX) OF
+ * PolicyQualifierInfo OPTIONAL }
+ *
+ * CertPolicyId ::= OBJECT IDENTIFIER
+ *
+ * PARAMETERS:
+ * "policyInfo"
+ * Address of CertPolicyInfo whose policy identifier is to be stored.
+ * Must be non-NULL.
+ * "pCertPolicyId"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CertPolicyInfo_GetPolicyId(
+ PKIX_PL_CertPolicyInfo *policyInfo,
+ PKIX_PL_OID **pCertPolicyId,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_CertPolicyInfo_GetPolQualifiers
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a List of the CertPolicyQualifiers representing
+ * the policyQualifiers of the CertPolicyInfo pointed to by "policyInfo" and
+ * stores it at "pPolicyQualifiers". If "policyInfo" does not have any
+ * policyQualifiers, this function stores NULL at "pPolicyQualifiers". Once
+ * created, a CertPolicyQualifier is immutable.
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
+ *
+ * PolicyInformation ::= SEQUENCE {
+ * policyIdentifier CertPolicyId,
+ * policyQualifiers SEQUENCE SIZE (1..MAX) OF
+ * PolicyQualifierInfo OPTIONAL }
+ *
+ * PolicyQualifierInfo ::= SEQUENCE {
+ * policyQualifierId PolicyQualifierId,
+ * qualifier ANY DEFINED BY policyQualifierId }
+ *
+ * PARAMETERS:
+ * "policyInfo"
+ * Address of CertPolicyInfo whose policy qualifiers List is to be stored.
+ * Must be non-NULL.
+ * "pPolicyQualifiers"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CertPolicyInfo_GetPolQualifiers(
+ PKIX_PL_CertPolicyInfo *policyInfo,
+ PKIX_List **pPolicyQualifiers, /* list of PKIX_PL_CertPolicyQualifier */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_PolicyQualifier_GetPolicyQualifierId
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to an OID representing the policyQualifierId of the
+ * CertPolicyQualifier pointed to by "policyQualifier" and stores it at
+ * "pPolicyQualifierId".
+ *
+ * PolicyQualifierInfo ::= SEQUENCE {
+ * policyQualifierId PolicyQualifierId,
+ * qualifier ANY DEFINED BY policyQualifierId }
+ *
+ * PolicyQualifierId ::=
+ * OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
+ *
+ * PARAMETERS:
+ * "policyQualifier"
+ * Address of CertPolQualifier whose policyQualifierId is to be stored.
+ * Must be non-NULL.
+ * "pPolicyQualifierId"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_PolicyQualifier_GetPolicyQualifierId(
+ PKIX_PL_CertPolicyQualifier *policyQualifier,
+ PKIX_PL_OID **pPolicyQualifierId,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_PolicyQualifier_GetQualifier
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a ByteArray representing the qualifier of the
+ * CertPolicyQualifier pointed to by "policyQualifier" and stores it at
+ * "pQualifier".
+ *
+ * PolicyQualifierInfo ::= SEQUENCE {
+ * policyQualifierId PolicyQualifierId,
+ * qualifier ANY DEFINED BY policyQualifierId }
+ *
+ * PARAMETERS:
+ * "policyQualifier"
+ * Address of CertPolicyQualifier whose qualifier is to be stored.
+ * Must be non-NULL.
+ * "pQualifier"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_PolicyQualifier_GetQualifier(
+ PKIX_PL_CertPolicyQualifier *policyQualifier,
+ PKIX_PL_ByteArray **pQualifier,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetPolicyMappings
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a List of CertPolicyMaps found in the policy
+ * mappings extension of the Cert pointed to by "cert" and stores it at
+ * "pPolicyMappings". If "cert" does not have a policy mappings extension,
+ * this function stores NULL at "pPolicyMappings". Once created, a
+ * CertPolicyMap is immutable.
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
+ * issuerDomainPolicy CertPolicyId,
+ * subjectDomainPolicy CertPolicyId }
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose CertPolicyMaps are to be stored.
+ * Must be non-NULL.
+ * "pPolicyMappings"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetPolicyMappings(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pPolicyMappings, /* list of PKIX_PL_CertPolicyMap */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to an OID representing the issuerDomainPolicy of the
+ * CertPolicyMap pointed to by "policyMapping" and stores it at
+ * "pIssuerDomainPolicy".
+ *
+ * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
+ * issuerDomainPolicy CertPolicyId,
+ * subjectDomainPolicy CertPolicyId }
+ *
+ * PARAMETERS:
+ * "policyMapping"
+ * Address of CertPolicyMap whose issuerDomainPolicy is to be stored.
+ * Must be non-NULL.
+ * "pIssuerDomainPolicy"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy(
+ PKIX_PL_CertPolicyMap *policyMapping,
+ PKIX_PL_OID **pIssuerDomainPolicy,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to an OID representing the subjectDomainPolicy of the
+ * CertPolicyMap pointed to by "policyMapping" and stores it at
+ * "pSubjectDomainPolicy".
+ *
+ * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
+ * issuerDomainPolicy CertPolicyId,
+ * subjectDomainPolicy CertPolicyId }
+ *
+ * PARAMETERS:
+ * "policyMapping"
+ * Address of CertPolicyMap whose subjectDomainPolicy is to be stored.
+ * Must be non-NULL.
+ * "pSubjectDomainPolicy"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy(
+ PKIX_PL_CertPolicyMap *policyMapping,
+ PKIX_PL_OID **pSubjectDomainPolicy,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetRequireExplicitPolicy
+ * DESCRIPTION:
+ *
+ * Retrieves the requireExplicitPolicy value of the policy constraints
+ * extension of the Cert pointed to by "cert" and stores it at "pSkipCerts".
+ * If "cert" does not have a policy constraints extension or the
+ * requireExplicitPolicy component is not populated, this function stores -1
+ * at "pSkipCerts".
+ *
+ * PolicyConstraints ::= SEQUENCE {
+ * requireExplicitPolicy [0] SkipCerts OPTIONAL,
+ * inhibitPolicyMapping [1] SkipCerts OPTIONAL }
+ *
+ * SkipCerts ::= INTEGER (0..MAX)
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose requireExplicitPolicy value is to be stored.
+ * Must be non-NULL.
+ * "pSkipCerts"
+ * Address where PKIX_Int32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetRequireExplicitPolicy(
+ PKIX_PL_Cert *cert,
+ PKIX_Int32 *pSkipCerts,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetPolicyMappingInhibited
+ * DESCRIPTION:
+ *
+ * Retrieves the inhibitPolicyMapping value of the policy constraints
+ * extension of the Cert pointed to by "cert" and stores it at "pSkipCerts".
+ * If "cert" does not have a policy constraints extension or the
+ * inhibitPolicyMapping component is not populated, this function stores -1
+ * at "pSkipCerts".
+ *
+ * PolicyConstraints ::= SEQUENCE {
+ * requireExplicitPolicy [0] SkipCerts OPTIONAL,
+ * inhibitPolicyMapping [1] SkipCerts OPTIONAL }
+ *
+ * SkipCerts ::= INTEGER (0..MAX)
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose requireExplicitPolicy value is to be stored.
+ * Must be non-NULL.
+ * "pSkipCerts"
+ * Address where PKIX_Int32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetPolicyMappingInhibited(
+ PKIX_PL_Cert *cert,
+ PKIX_Int32 *pSkipCerts,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetInhibitAnyPolicy
+ * DESCRIPTION:
+ *
+ * Retrieves the value of the inhibit any-policy extension of the Cert
+ * pointed to by "cert" and stores it at "pSkipCerts". If "cert" does not have
+ * an inhibit any-policy extension, this function stores -1 at "pSkipCerts".
+ *
+ * InhibitAnyPolicy ::= SkipCerts
+ *
+ * SkipCerts ::= INTEGER (0..MAX)
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose inhibit any-policy extensions value is to be
+ * stored. Must be non-NULL.
+ * "pSkipCerts"
+ * Address where PKIX_Int32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetInhibitAnyPolicy(
+ PKIX_PL_Cert *cert,
+ PKIX_Int32 *pSkipCerts,
+ void *plContext);
+
+/* policy processing functions */
+
+/*
+ * FUNCTION: PKIX_PL_Cert_AreCertPoliciesCritical
+ * DESCRIPTION:
+ *
+ * Checks whether the certificate policies extension of the Cert pointed to
+ * by "cert" is critical and stores the Boolean result at "pCritical". If
+ * "cert" does not have a certificate policies extension, this function
+ * stores NULL at "pCritical".
+ *
+ * XXX what distinguishes NULL from PKIX_FALSE?
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose certificate policies extension's criticality is
+ * to be determined. Must be non-NULL.
+ * "pCritical"
+ * Address where PKIX_Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_AreCertPoliciesCritical(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pCritical,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_CheckNameConstraints
+ * DESCRIPTION:
+ *
+ * Checks whether the subject distinguished name and subject alternative names
+ * of the Cert pointed to by "cert" satisfy the CertNameConstraints pointed
+ * to by "nameConstraints". If the CertNameConstraints are not satisfied, a
+ * PKIX_Error pointer is returned. If "nameConstraints" is NULL, the function
+ * does nothing.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose subject names are to be checked.
+ * Must be non-NULL.
+ * "nameConstraints"
+ * Address of CertNameConstraints that need to be satisfied.
+ * "treatCommonNameAsDNSName"
+ * PKIX_TRUE if the subject common name should be considered a dNSName
+ * when evaluating name constraints.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_CheckNameConstraints(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean treatCommonNameAsDNSName,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_MergeNameConstraints
+ * DESCRIPTION:
+ *
+ * Merges the CertNameConstraints pointed to by "firstNC" and the
+ * CertNameConstraints pointed to by "secondNC" and stores the merged
+ * CertNameConstraints at "pResultNC". If "secondNC" is NULL, the
+ * CertNameConstraints pointed to by "firstNC" is stored at "pResultNC".
+ *
+ * Once created, a CertNameConstraints object is immutable.
+ *
+ * PARAMETERS:
+ * "firstNC"
+ * Address of first CertNameConstraints to be merged. Must be non-NULL.
+ * "secondNC"
+ * Address of second CertNameConstraints to be merged
+ * "pResultNC"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_MergeNameConstraints(
+ PKIX_PL_CertNameConstraints *firstNC,
+ PKIX_PL_CertNameConstraints *secondNC,
+ PKIX_PL_CertNameConstraints **pResultNC,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_VerifyKeyUsage
+ * DESCRIPTION:
+ *
+ * Verifies that the keyUsage bit(s) specified by "keyUsage" appear in the
+ * keyUsage extension of the Cert pointed to by "cert". The keyUsage bit
+ * values specified in pkixt.h are supported, and can be bitwise or'ed if
+ * multiple bit values are to be verified. If the keyUsages do not all appear
+ * in the keyUsage extension of "cert", a PKIX_Error pointer is returned.
+ *
+ * KeyUsage ::= BIT STRING {
+ * digitalSignature (0),
+ * nonRepudiation (1),
+ * keyEncipherment (2),
+ * dataEncipherment (3),
+ * keyAgreement (4),
+ * keyCertSign (5),
+ * cRLSign (6),
+ * encipherOnly (7),
+ * decipherOnly (8) }
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose keyUsage bits are to be verified.
+ * Must be non-NULL.
+ * "keyUsage"
+ * Constant representing keyUsage bit(s) that all must appear in keyUsage
+ * extension of "cert".
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_VerifyKeyUsage(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 keyUsage,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_VerifyCertAndKeyType
+ * DESCRIPTION:
+ *
+ * Verifies cert and key types against certificate usage that is
+ * a part of plContext(pkix_pl_nsscontext) structure. Throws an error
+ * if cert or key types does not match.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose keyUsage bits are to be verified.
+ * Must be non-NULL.
+ * "isLeafCert"
+ * What type of a cert has been verified.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_VerifyCertAndKeyType(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean isChainCert,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_CheckValidity
+ * DESCRIPTION:
+ *
+ * Checks whether the Cert pointed to by "cert" would be valid at the time
+ * represented by the Date pointed to by "date". If "date" is NULL, then this
+ * function checks whether the Cert would be valid at the current time. If the
+ * Cert would not be valid at the specified Date, a PKIX_Error pointer is
+ * returned.
+ *
+ * Validity ::= SEQUENCE {
+ * notBefore Time,
+ * notAfter Time }
+ *
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose validity is to be checked. Must be non-NULL.
+ * "date"
+ * Address of Date at which the Cert is being checked for validity.
+ * If NULL, the current time is used for the Date.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_CheckValidity(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Date *date,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetValidityNotAfter
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the Date that represents the notAfter time of the
+ * Certificate pointed to by "cert" and stores it at "pDate".
+ *
+ * Validity ::= SEQUENCE {
+ * notBefore Time,
+ * notAfter Time }
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose validity time is to be retrieved. Must be
+ * non-NULL.
+ * "date"
+ * Address of Date at which the Cert's notAfter time is being retrieved.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetValidityNotAfter(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Date **pDate,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_VerifySignature
+ * DESCRIPTION:
+ *
+ * Verifies the signature on the Cert pointed to by "cert" using the
+ * PublicKey pointed to by "pubKey". If the signature doesn't verify, an
+ * Error pointer is returned.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose signature is to be verified. Must be non-NULL.
+ * "pubKey"
+ * Address of a Public Key used to verify the signature. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_VerifySignature(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_PublicKey *pubKey,
+ void *plContext);
+
+/* A set of flags to indicate how explicitly configured trust anchors should be
+ * handled by PKIX_PL_Cert_IsCertTrusted
+ */
+typedef enum PKIX_PL_TrustAnchorModeEnum {
+ /* Indicates trust anchors should be ignored; only the underlying
+ * platform's trust settings should be used.
+ */
+ PKIX_PL_TrustAnchorMode_Ignore,
+
+ /* Indicates that explicitly configured trust anchors may be considered
+ * trustworthy, if present.
+ * Note: If the underlying platform supports marking a certificate as
+ * explicitly untrustworthy, explicitly configured trust anchors
+ * MAY be ignored/rejected.
+ */
+ PKIX_PL_TrustAnchorMode_Additive,
+
+ /* Indicates that ONLY trust anchors should be considered as
+ * trustworthy.
+ * Note: If the underlying platform supports marking a certificate as
+ * explicitly untrustworthy, explicitly configured trust anchors
+ * MAY be ignored/rejected.
+ */
+ PKIX_PL_TrustAnchorMode_Exclusive
+} PKIX_PL_TrustAnchorMode;
+
+/*
+ * FUNCTION: PKIX_PL_Cert_IsCertTrusted
+ * DESCRIPTION:
+ *
+ * Checks the Cert specified by "cert" to determine, in a manner that depends
+ * on the underlying platform, whether it is trusted, and stores the result in
+ * "pTrusted". If a certificate is trusted it means that a chain built to that
+ * certificate, and satisfying all the usage, policy, validity, and other
+ * tests, is a valid chain and the End Entity certificate from which it was
+ * built can be trusted.
+ *
+ * If the Certificate is not intrinsically trustworthy, it still might end up a
+ * component in a successful chain.
+ *
+ * If the Certificate is intrinsically untrustworthy, this function will return
+ * an error.
+ *
+ * PARAMETERS
+ * "cert"
+ * Address of Cert whose trustworthiness is to be determined. Must be
+ * non-NULL.
+ * "trustAnchorMode"
+ * A PKIX_PL_TrustAnchorMode that indicates how explicitly defined user
+ * trust anchors should be handled.
+ * "pTrusted"
+ * Address where the Boolean value will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CERT Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_IsCertTrusted(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_TrustAnchorMode trustAnchorMode,
+ PKIX_Boolean *pTrusted,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_IsLeafCertTrusted
+ * DESCRIPTION:
+ *
+ * Checks the Leaf Cert specified by "cert" to determine, in a manner that
+ * depends on the underlying platform, whether it is trusted, and stores the
+ * result in "pTrusted". If a certificate is trusted it means that this
+ * End Entify certificate has been marked as trusted for the requested usage,
+ * policy, validity, and other tests.
+ *
+ * If the Certificate is not intrinsically trustworthy, we can still try to
+ * build a successful chain.
+ *
+ * If the Certificate is intrinsically untrustworthy, this function will return
+ * an error.
+ *
+ * PARAMETERS
+ * "cert"
+ * Address of Cert whose trustworthiness is to be determined. Must be
+ * non-NULL.
+ * "pTrusted"
+ * Address where the Boolean value will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CERT Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_IsLeafCertTrusted(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pTrusted,
+ void *plContext);
+
+/* FUNCTION: PKIX_PL_Cert_SetAsTrustAnchor */
+PKIX_Error*
+PKIX_PL_Cert_SetAsTrustAnchor(PKIX_PL_Cert *cert,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetCacheFlag
+ * DESCRIPTION:
+ *
+ * Retrieves the value of the cache flag in "cert" and return it at address
+ * pointed by "pCacheFlag". The initila cache flag is determined by the
+ * CertStore this "cert" is fetched from. When CertStore is created, user
+ * need to specify if the data should be cached.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose cache flag is fetched. Must be non-NULL.
+ * "pCacheFlag"
+ * Address where PKIX_Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetCacheFlag(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pCacheFlag,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_SetCacheFlag
+ * DESCRIPTION:
+ *
+ * Set the value of the cache flag in "cert" base on the boolean value stored
+ * at "cacheFlag". This function is meant to be used by CertStore after a
+ * Cert is created.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert where "cacheFlag" is stored. Must be non-NULL.
+ * "cacheFlag"
+ * PKIX_Boolean flag for cache flag.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_SetCacheFlag(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean cacheFlag,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetTrustCertStore
+ * DESCRIPTION:
+ *
+ * Retrieves the value of the CertStore in "cert" and return it at address
+ * pointed by "pCertStore".
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose CertStore is fetched. Must be non-NULL.
+ * "pTrustCertStore"
+ * Address where CertStore will be stored and returned. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetTrustCertStore(
+ PKIX_PL_Cert *cert,
+ PKIX_CertStore **pTrustCertStore,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Cert_SetTrustCertStore
+ * DESCRIPTION:
+ *
+ * Set the value of the CertStore "certStore" in "cert".
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert where "certStore" will be stored. Must be non-NULL.
+ * "trustCertStore"
+ * Address where the CertStore is. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_SetTrustCertStore(
+ PKIX_PL_Cert *cert,
+ PKIX_CertStore *trustCertStore,
+ void *plContext);
+
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetAuthorityInfoAccess
+ * DESCRIPTION:
+ *
+ * Retrieves the value(s) of the Authority Information Access in "cert" and
+ * returns it in a list at address pointed by "pAuthorityInfoAccess".
+ *
+ * SubjectInfoAccess ::=
+ * SEQUENCE SIZE (1..MAX) of AccessDescription
+ * AccessDescription ::= SEQUENCE {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName
+ * }
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose Authority Information Access is fetched.
+ * Must be non-NULL.
+ * "pAuthorityInfoAccess"
+ * Address where Authority InfoAccess will be stored and returned.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetAuthorityInfoAccess(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */
+ void *plContext);
+
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectInfoAccess
+ * DESCRIPTION:
+ *
+ * Retrieves the value(s) of the Subject Information Access in "cert" and
+ * returns it in a list at address pointed by "pSubjectInfoAccess".
+ *
+ * SubjectInfoAccess ::=
+ * SEQUENCE SIZE (1..MAX) of AccessDescription
+ * AccessDescription ::= SEQUENCE {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName
+ * }
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose Subject Information Access is fetched.
+ * Must be non-NULL.
+ * "pSubjectInfoAccess"
+ * Address where Subject InfoAccess will be stored and returned.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectInfoAccess(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pSiaList, /* of PKIX_PL_InfoAccess */
+ void *plContext);
+
+
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetCrlDp
+ * DESCRIPTION:
+ *
+ * Retrieves the value(s) of the CRL Distribution Point Extension and
+ * returns it in a list at address pointed by "pDpList".
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose Subject Information Access is fetched.
+ * Must be non-NULL.
+ * "pDpList"
+ * Address where CRL DP will be stored and returned.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetCrlDp(PKIX_PL_Cert *cert,
+ PKIX_List **pDpList,
+ void *plContext);
+
+
+/*
+ * InfoAccess
+ *
+ * To hold Authority Information Access or Subject Information Access
+ * retrieved from a Certificate.
+ */
+
+#define PKIX_INFOACCESS_OCSP 1
+#define PKIX_INFOACCESS_CA_ISSUERS 2
+#define PKIX_INFOACCESS_TIMESTAMPING 3
+#define PKIX_INFOACCESS_CA_REPOSITORY 5
+
+#define PKIX_INFOACCESS_LOCATION_UNKNOWN 0
+#define PKIX_INFOACCESS_LOCATION_HTTP 1
+#ifndef NSS_PKIX_NO_LDAP
+#define PKIX_INFOACCESS_LOCATION_LDAP 2
+#endif
+
+/*
+ * FUNCTION: PKIX_PL_InfoAccess_GetMethod
+ * DESCRIPTION:
+ *
+ * Stores the method of the Information Access from "infoAccess" and
+ * returns in "pMethod".
+ *
+ * SubjectInfoAccess ::=
+ * AccessDescription ::= SEQUENCE {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName
+ * }
+ *
+ * PARAMETERS:
+ * "infoAccess"
+ * Address of PKIX_PL_InfoAccess that has the access data.
+ * Must be non-NULL.
+ * "pMethod"
+ * Address where access method will be stored and returned.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_InfoAccess_GetMethod(
+ PKIX_PL_InfoAccess *infoAccess,
+ PKIX_UInt32 *pMethod,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_InfoAccess_GetLocation
+ * DESCRIPTION:
+ *
+ * Stores the location of the Information Access from "infoAccess" and
+ * returns in "pLocation".
+ *
+ * SubjectInfoAccess ::=
+ * AccessDescription ::= SEQUENCE {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName
+ * }
+ *
+ * PARAMETERS:
+ * "infoAccess"
+ * Address of PKIX_PL_InfoAccess that has the access data.
+ * Must be non-NULL.
+ * "pLocation"
+ * Address where access location will be stored and returned.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_InfoAccess_GetLocation(
+ PKIX_PL_InfoAccess *infoAccess,
+ PKIX_PL_GeneralName **pLocation,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_InfoAccess_GetLocationType
+ * DESCRIPTION:
+ *
+ * Stores the type of location of the Information Access from "infoAccess" and
+ * returns in "pType".
+ *
+ * SubjectInfoAccess ::=
+ * AccessDescription ::= SEQUENCE {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName
+ * }
+ *
+ * PARAMETERS:
+ * "infoAccess"
+ * Address of PKIX_PL_InfoAccess that has the access data.
+ * Must be non-NULL.
+ * "pType"
+ * Address where access location type will be stored and returned.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_InfoAccess_GetLocationType(
+ PKIX_PL_InfoAccess *infoAccess,
+ PKIX_UInt32 *pType,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_InfoAccess_GetAIACerts(
+ PKIX_PL_InfoAccess *ia,
+ void **pNBIOContext,
+ void **pHandle,
+ PKIX_List **pCerts,
+ void *plContext);
+
+/*
+ * CRL
+ *
+ * A CRL represents an X.509 certificate revocation list. It can be created
+ * using the bytes of a valid ASN.1 DER encoding. Once created, a CRL is
+ * immutable. The following functions include accessors (gettors) for the
+ * various components of an X.509 CRL, as well as a function for signature
+ * verification.
+ */
+
+/*
+ * FUNCTION: PKIX_PL_CRL_Create
+ * DESCRIPTION:
+ *
+ * Creates a new CRL using the bytes in the ByteArray pointed to by
+ * "byteArray" and stores it at "pCRL". If the bytes are not a valid ASN.1
+ * DER encoding of a CRL, a PKIX_Error pointer is returned. Once created, a
+ * CRL is immutable.
+ *
+ * CertificateList ::= SEQUENCE {
+ * tbsCertList TBSCertList,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING }
+ *
+ * TBSCertList ::= SEQUENCE {
+ * version Version OPTIONAL,
+ * -- if present, MUST be v2
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * thisUpdate Time,
+ * nextUpdate Time OPTIONAL,
+ * revokedCertificates SEQUENCE OF SEQUENCE {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate Time,
+ * crlEntryExtensions Extensions OPTIONAL
+ * -- if present, MUST be v2
+ * } OPTIONAL,
+ * crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ * -- if present, MUST be v2
+ * }
+ *
+ * PARAMETERS:
+ * "byteArray"
+ * Address of ByteArray representing the CRL's DER encoding.
+ * Must be non-NULL.
+ * "pCRL"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CRL_Create(
+ PKIX_PL_ByteArray *byteArray,
+ PKIX_PL_CRL **pCRL,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_CRL_GetIssuer
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the X500Name that represents the issuer of the CRL
+ * pointed to by "crl" and stores it at "pCRLIssuer".
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose issuer is to be stored. Must be non-NULL.
+ * "pCRLIssuer"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CRL_GetIssuer(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_X500Name **pCRLIssuer,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_CRL_GetCriticalExtensionOIDs
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of OIDs (each OID corresponding to a
+ * critical extension of the CRL pointed to by "crl") and stores it at
+ * "pExtensions". If "crl" does not have any critical extensions, this
+ * function stores an empty List at "pExtensions".
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose critical extension OIDs are to be stored.
+ * Must be non-NULL.
+ * "pExtensions"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CRL_GetCriticalExtensionOIDs(
+ PKIX_PL_CRL *crl,
+ PKIX_List **pExtensions, /* list of PKIX_PL_OID */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_CRL_GetCRLEntryForSerialNumber
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the CRLEntry (found in the CRL pointed to by "crl")
+ * corresponding to the BigInt pointed to by "serialNumber" and stores it at
+ * "pCRLEntry". If there is no such CRLEntry, this functions stores NULL at
+ * "pCRLEntry". Once created, a CRLEntry is immutable.
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose CRL Entries are to be searched. Must be non-NULL.
+ * "serialNumber"
+ * Address of BigInt representing serial number of certificate whose
+ * CRLEntry is to be found. Must be non-NULL.
+ * "pCRLEntry"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CRL_GetCRLEntryForSerialNumber(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_BigInt *serialNumber,
+ PKIX_PL_CRLEntry **pCRLEntry,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_CRL_GetCRLNumber
+ * DESCRIPTION:
+ * Retrieves the CRL Number from extension. This is non-critical extension.
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose version is to be stored. Must be non-NULL.
+ * "pCrlNumber"
+ * Address where a CRL Number will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CRL_GetCRLNumber(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_BigInt **pCrlNumber,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_CRL_VerifyUpdateTime
+ * DESCRIPTION:
+ *
+ * Checks whether the CRL pointed to by "crl" would be valid at the time
+ * represented by the Date pointed to by "date" and stores the Boolean result
+ * at "pResult". This check is done only when NIST policy is enforced.
+ *
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose validity is to be checked. Must be non-NULL.
+ * "date"
+ * Address of Date at which the CRL is being checked for validity.
+ * Must be non-NULL.
+ * "pResult"
+ * Address of Boolean result. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CRL_VerifyUpdateTime(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_Date *date,
+ PKIX_Boolean *pResult,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_CRL_VerifySignature
+ * DESCRIPTION:
+ *
+ * Verifies the signature on the CRL pointed to by "crl" using the PublicKey
+ * pointed to by "pubKey". If the signature doesn't verify, a PKIX_Error
+ * pointer is returned.
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose signature is to be verified. Must be non-NULL.
+ * "pubKey"
+ * Address of a Public Key used to verify the signature. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CRL_VerifySignature(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_PublicKey *pubKey,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_CRL_ReleaseDerCrl
+ * DESCRIPTION:
+ *
+ * Relinguish the ownership for the crl der. The operation will succeed if
+ * a crl owns the der. If the crl was created from existing crl and does not
+ * own the der, then the function will return null.
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose signature is to be verified. Must be non-NULL.
+ * "derCrl"
+ * Pointer to a SECItem that has der crl.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CRL_ReleaseDerCrl(PKIX_PL_CRL *crl,
+ SECItem **derCrl,
+ void *plContext);
+/*
+ * FUNCTION: PKIX_PL_CRL_AdoptDerCrl
+ * DESCRIPTION:
+ *
+ * Adopt memory of the der. The secItem that contains der will be
+ * freed with destruction of parent pkix crl structure.
+ *
+ * * PARAMETERS:
+ * "crl"
+ * Address of CRL whose signature is to be verified. Must be non-NULL.
+ * "derCrl"
+ * Pointer to a SECItem that has der crl.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CRL_AdoptDerCrl(PKIX_PL_CRL *crl,
+ SECItem *derCrl,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_CRLEntry_GetCRLEntryReasonCode
+ * DESCRIPTION:
+ *
+ * Retrieves the value of the reason code extension of the CRLEntry pointed
+ * to by "crlEntry" and stores it at "pReason". If the "crlEntry" has no
+ * reason code extension, this function stores -1 at "pReason".
+ *
+ * CRLReason ::= ENUMERATED {
+ * unspecified (0),
+ * keyCompromise (1),
+ * cACompromise (2),
+ * affiliationChanged (3),
+ * superseded (4),
+ * cessationOfOperation (5),
+ * certificateHold (6),
+ * removeFromCRL (8),
+ * privilegeWithdrawn (9),
+ * aACompromise (10) }
+ *
+ * PARAMETERS:
+ * "crlEntry"
+ * Address of CRLEntry whose reason code bit values are to be returned
+ * at "pReason". Must be non-NULL.
+ * "pReason"
+ * Address of PKIX_Int32 where reason code is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CRLEntry_GetCRLEntryReasonCode(
+ PKIX_PL_CRLEntry *crlEntry,
+ PKIX_Int32 *pReason,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_CRLEntry_GetCriticalExtensionOIDs
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of OIDs (each OID corresponding to a
+ * critical extension of the CRLEntry pointed to by "crlEntry") and stores it
+ * at "pExtensions". If "crlEntry" does not have any critical extensions, this
+ * function stores an empty List at "pExtensions".
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "crlEntry"
+ * Address of CRLEntry whose critical extension OIDs are to be stored.
+ * Must be non-NULL.
+ * "pExtensions"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CRLEntry_GetCriticalExtensionOIDs(
+ PKIX_PL_CRLEntry *crlEntry,
+ PKIX_List **pExtensions, /* list of PKIX_PL_OID */
+ void *plContext);
+
+#ifdef BUILD_LIBPKIX_TESTS
+/*
+ * FUNCTION: PKIX_PL_X500Name_Create
+ * DESCRIPTION:
+ *
+ * Creates a new X500Name using the UTF8 string representation pointed to by
+ * "stringRep" and stores it at "pName". Once created, an X500Name is
+ * immutable.
+ *
+ * Name ::= CHOICE {
+ * RDNSequence }
+ *
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ *
+ * RelativeDistinguishedName ::=
+ * SET OF AttributeTypeAndValue
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type AttributeType,
+ * value AttributeValue }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ *
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ *
+ * DirectoryString ::= CHOICE {
+ * teletexString TeletexString (SIZE (1..MAX)),
+ * printableString PrintableString (SIZE (1..MAX)),
+ * universalString UniversalString (SIZE (1..MAX)),
+ * utf8String UTF8String (SIZE (1..MAX)),
+ * bmpString BMPString (SIZE (1..MAX)) }
+ *
+ * PARAMETERS:
+ * "stringRep"
+ * Address of UTF8 String representation of X500Name. Must be non-NULL.
+ * "pName"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an X500Name Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_X500Name_Create (
+ PKIX_PL_String *stringRep,
+ PKIX_PL_X500Name **pName,
+ void *plContext);
+
+#endif /* BUILD_LIBPKIX_TESTS */
+
+/*
+ * FUNCTION: PKIX_PL_X500Name_CreateFromCERTName
+ * DESCRIPTION:
+ *
+ * The function creates x500Name using der encoded DN and/or pointer to
+ * CERTName. If arument "name" is NULL, but derName is supplied when
+ * the function generates nssDN(CERTName type) from der data. If derName
+ * is not supplied, CERTName *name will not be used to generate DN DER
+ * encoding.
+ *
+ * PARAMETERS:
+ * "derName"
+ * Address of DER representation of X500Name. Can be NULL
+ * "name"
+ * Address of CERTName representation of X500Name. Can be NULL
+ * "pName"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an X500Name Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_X500Name_CreateFromCERTName(
+ SECItem *derName,
+ CERTName *name,
+ PKIX_PL_X500Name **pName,
+ void *plContext);
+
+
+/*
+ * TYPE: PKIX_PL_X500Name_Match
+ * DESCRIPTION:
+ * Checks whether the X500Name pointed to by "firstX500Name" MATCHES the
+ * X500Name pointed to by "secondX500Name" and stores the boolean result at
+ * "pResult". Two X500Names MATCH if they meet the conditions specified by
+ * RFC 3280 (section 4.1.2.4). Namely:
+ *
+ * "This specification requires only a subset of the name comparison
+ * functionality specified in the X.500 series of specifications.
+ * Conforming implementations are REQUIRED to implement the following
+ * name comparison rules:
+ *
+ * (a) attribute values encoded in different types (e.g., PrintableString
+ * and BMPString) MAY be assumed to represent different strings;
+ *
+ * (b) attribute values in types other than PrintableString are case
+ * sensitive (this permits matching of attribute values as binary objects)
+ *
+ * (c) attribute values in PrintableString are not case sensitive
+ * (e.g., "Marianne Swanson" is the same as "MARIANNE SWANSON"); and
+ *
+ * (d) attribute values in PrintableString are compared after removing
+ * leading and trailing white space and converting internal substrings of
+ * one or more consecutive white space characters to a single space."
+ *
+ * PARAMETERS:
+ * "firstX500Name"
+ * Address of first X500Name to compare. Must be non-NULL.
+ * "secondX500Name"
+ * Address of second X500Name to compare. Must be non-NULL.
+ * "pResult"
+ * Address of Boolean result. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an X500Name Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_X500Name_Match(
+ PKIX_PL_X500Name *firstX500Name,
+ PKIX_PL_X500Name *secondX500Name,
+ PKIX_Boolean *pResult,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Date_Create_UTCTime
+ * DESCRIPTION:
+ * Creates a new Date of type UTCTime using the string representation pointed
+ * to by "stringRep" and stores it at "pDate". The UTCTime restriction means
+ * that the year can only be specified by the least significant two digits
+ * (YY). As such, Only the years 1950-2049 can be represented. If "stringRep"
+ * is NULL, this function creates a new Date representing the current time
+ * and stores it at "pDate". Once created, a Date is immutable.
+ *
+ * If YY is greater than or equal to 50, the year is interpreted as 19YY.
+ * If YY is less than 50, the year is interpreted as 20YY.
+ *
+ * The string representation of the date must be in the following form:
+ * "YYMMDDhhmmssZ" where:
+ *
+ * YY is the least significant two digits of the year
+ * MM is the month (01 to 12)
+ * DD is the day (01 to 31)
+ * hh is the hour (00 to 23)
+ * mm are the minutes (00 to 59)
+ * ss are the seconds (00 to 59)
+ * Z indicates that local time is GMT
+ *
+ * PARAMETERS:
+ * "stringRep"
+ * Address of String representation of Date.
+ * If NULL, current time is used.
+ * "pDate"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Date Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Date_Create_UTCTime (
+ PKIX_PL_String *stringRep,
+ PKIX_PL_Date **pDate,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Date_Create_UTCTime
+ * DESCRIPTION:
+ * Creates a new Date from PRTime data.
+ *
+ * PARAMETERS:
+ * "time"
+ * Represented time in PRTime type.
+ * "pDate"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Date Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Date_CreateFromPRTime(
+ PRTime time,
+ PKIX_PL_Date **pDate,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Date_Create_CurrentOffBySeconds
+ * DESCRIPTION:
+ * Creates a new Date of type UTCTime for current time with seconds off by
+ * "secondsOffset" and returns it at "pDate".
+ *
+ * PARAMETERS:
+ * "secondsOffset"
+ * A PKIX_Int32 indicates the time offset from current. If "secondsOffset"
+ * is negative, the time is in past.
+ * "pDate"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Date Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Date_Create_CurrentOffBySeconds(
+ PKIX_Int32 secondsOffset,
+ PKIX_PL_Date **pDate,
+ void *plContext);
+
+#ifdef BUILD_LIBPKIX_TESTS
+/*
+ * FUNCTION: PKIX_PL_GeneralName_Create
+ * DESCRIPTION:
+ *
+ * Creates a new GeneralName of type "nameType" using the string
+ * representation pointed to by "stringRep" and stores it at "pGName".
+ * All of the GeneralName type format values specified in pkixt.h are
+ * supported, with the exception of PKIX_OTHER_NAME, PKIX_EDIPARTY_NAME,
+ * PKIX_IP_NAME, and PKIX_X400_ADDRESS. A PKIX_ESCASCII string representation
+ * should be used for all supported nameTypes, with the exception of
+ * registeredID and directoryName. For registeredID, the string representation
+ * should be the same as that used by PKIX_PL_OID_Create. For directoryName,
+ * the string representation should be the same as that used by
+ * PKIX_PL_X500Name_Create. If an unsupported name type is used, an Error is
+ * returned. Once created, a GeneralName is immutable.
+ *
+ * GeneralName ::= CHOICE {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER }
+ *
+ *
+ * NOTE: This function is allowed to be called only by pkix tests programs.
+ *
+ * PARAMETERS:
+ * "nameType"
+ * Type of GeneralName to be created. This must be one of the GeneralName
+ * type format values specified in pkixt.h
+ * "stringRep"
+ * Address of String representation of GeneralName. Must be non-NULL.
+ * "pGName"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a GeneralName Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_GeneralName_Create (
+ PKIX_UInt32 nameType,
+ PKIX_PL_String *stringRep,
+ PKIX_PL_GeneralName **pGName,
+ void *plContext);
+#endif /* BUILD_LIBPKIX_TESTS */
+
+/*
+ * FUNCTION: PKIX_PL_CertNameConstraints_CheckNamesInNameSpace
+ * DESCRIPTION:
+ *
+ * This function checks whether names in "nameList" comply with
+ * "nameConstraints". It stores PKIX_TRUE at "pCheckPass" if the names meet the
+ * requirement of the NameConstraints, PKIX_FALSE otherwise.
+ *
+ * PARAMETERS
+ * "nameList"
+ * List of GeneralNames that are checked for compliance. May be empty
+ * or NULL.
+ * "nameConstraints"
+ * Address of CertNameConstraints that provides lists of permitted
+ * and excluded names. Must be non-NULL.
+ * "pCheckPass"
+ * Address where PKIX_TRUE is returned if the all names in "nameList" are
+ * valid. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CertNameConstraints_CheckNamesInNameSpace(
+ PKIX_List *nameList, /* List of PKIX_PL_GeneralName */
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean *pCheckPass,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_AIAMgr_Create
+ * DESCRIPTION:
+ *
+ * This function creates an AIAMgr to handle retrieval of Certs and CRLs
+ * from servers given by AIA Certificate extensions. It manages connections
+ * and caches. The manager created is stored at "pAIAMgr".
+ *
+ * PARAMETERS:
+ * "pAIAMgr"
+ * The address at which the result is stored. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an AIAMgr Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_AIAMgr_Create(
+ PKIX_PL_AIAMgr **pAIAMgr,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_AIAMgr_GetAIACerts
+ * DESCRIPTION:
+ *
+ * This function uses the AIAMgr pointed to by "aiaMgr" to retrieve the Certs
+ * specified by an AIA certificate extension, if any, in the Cert pointed to by
+ * "prevCert", storing the results at "pCerts". If the certificate has no such
+ * extension, this function stores NULL at "pCerts".
+ *
+ * If the request is suspended for non-blocking I/O, a platform-dependent
+ * context is stored at "pNBIOContext" and NULL is stored at "pCerts". This
+ * return is referred to as the WOULDBLOCK state. Note that the caller must
+ * check for a non-NULL value at "pNBIOContext", to distinguish this state from
+ * the "no such extension" return described in the first paragraph. (The
+ * alternative would be to return an empty List, but it seemed wrong to incur
+ * the overhead of creating and destroying an empty List for the most common
+ * situation.)
+ *
+ * After a WOULDBLOCK return, the user may continue the operation by calling
+ * pkix_AIAMgr_GetAIACerts (possibly more than once, if the function again
+ * returns in the WOULDBLOCK state) with the previously-returned non-NULL
+ * value of "pNBIOContext". When results are complete, NULL is stored at
+ * "pNBIOContext", and the results (which may be NULL) are stored at "pCerts".
+ *
+ * PARAMETERS:
+ * "aiaMgr"
+ * The AIAMgr which controls the retrieval of certificates. Must be
+ * non-NULL.
+ * "prevCert"
+ * Address of PKIX_PL_Cert which may provide an AIA or SIA extension. Must
+ * be non-NULL.
+ * "pNBIOContext"
+ * Address at which platform-dependent information is returned if request
+ * is suspended for non-blocking I/O. Must be non-NULL.
+ * "pCerts"
+ * Address at which the returned List is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an AIAMgr Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_AIAMgr_GetAIACerts(
+ PKIX_PL_AIAMgr *aiaMgr,
+ PKIX_PL_Cert *prevCert,
+ void **pNBIOContext,
+ PKIX_List **pCerts,
+ void *plContext);
+
+typedef PKIX_Error *
+(*PKIX_PL_VerifyCallback)(
+ PKIX_PL_Object *signedObject,
+ PKIX_PL_Cert *signerCert, /* can be unknown */
+ PKIX_PL_Date *producedAt,
+ PKIX_ProcessingParams *procParams,
+ void **pNBIOContext,
+ void **pState,
+ PKIX_BuildResult **pBuildResult,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_PKI_H */
diff --git a/security/nss/lib/libpkix/include/pkix_pl_system.h b/security/nss/lib/libpkix/include/pkix_pl_system.h
new file mode 100644
index 0000000000..57d5df7cc0
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkix_pl_system.h
@@ -0,0 +1,1545 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 file defines several platform independent functions to make system
+ * calls in a portable manner.
+ *
+ */
+
+#ifndef _PKIX_PL_SYSTEM_H
+#define _PKIX_PL_SYSTEM_H
+
+#include "pkixt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General
+ *
+ * Please refer to the libpkix Programmer's Guide for detailed information
+ * about how to use the libpkix library. Certain key warnings and notices from
+ * that document are repeated here for emphasis.
+ *
+ * All identifiers in this file (and all public identifiers defined in
+ * libpkix) begin with "PKIX_". Private identifiers only intended for use
+ * within the library begin with "pkix_".
+ *
+ * A function returns NULL upon success, and a PKIX_Error pointer upon failure.
+ *
+ * Unless otherwise noted, for all accessor (gettor) functions that return a
+ * PKIX_PL_Object pointer, callers should assume that this pointer refers to a
+ * shared object. Therefore, the caller should treat this shared object as
+ * read-only and should not modify this shared object. When done using the
+ * shared object, the caller should release the reference to the object by
+ * using the PKIX_PL_Object_DecRef function.
+ *
+ * While a function is executing, if its arguments (or anything referred to by
+ * its arguments) are modified, free'd, or destroyed, the function's behavior
+ * is undefined.
+ *
+ */
+
+/*
+ * FUNCTION: PKIX_PL_Initialize
+ * DESCRIPTION:
+ *
+ * XXX If this function is really only meant to be used by PKIX_Initialize,
+ * why don't we just put it in a private header file rather than the public
+ * API. I think it may confuse users.
+ *
+ * This function should NOT be called by applications. It is only meant to
+ * be used internally. The application needs only to call PKIX_Initialize,
+ * which in turn will call this function.
+ *
+ * This function initializes data structures critical to the operation of
+ * libpkix. If initialization is not successful, an Error pointer is
+ * returned. This function should only be called once. If it is called more
+ * than once, the behavior is undefined.
+ *
+ * No PKIX_* types and functions should be used before this function is
+ * called and returns successfully.
+ *
+ * PARAMETERS:
+ * "platformInitNeeded"
+ * Boolean indicating whether platform initialization is to be called
+ * "useArenas"
+ * Boolean indicating whether allocation is to be done using arenas or
+ * individual allocation (malloc).
+ * "pPlContext"
+ * Address at which platform-specific context pointer is stored. Must be
+ * non-NULL.
+ * THREAD SAFETY:
+ * Not Thread Safe
+ *
+ * This function assumes that no other thread is calling this function while
+ * it is executing.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Initialize(
+ PKIX_Boolean platformInitNeeded,
+ PKIX_Boolean useArenas,
+ void **pPlContext);
+
+/*
+ * FUNCTION: PKIX_PL_Shutdown
+ * DESCRIPTION:
+ *
+ * XXX If this function is really only meant to be used by PKIX_Shutdown,
+ * why don't we just put it in a private header file rather than the public
+ * API. I think it may confuse users.
+ *
+ * This function should NOT be called by applications. It is only meant to
+ * be used internally. The application needs only to call PKIX_Shutdown,
+ * which in turn will call this function.
+ *
+ * This function deallocates any memory used by the Portability Layer (PL)
+ * component of the libpkix library and shuts down any ongoing operations.
+ * This function should only be called once. If it is called more than once,
+ * the behavior is undefined.
+ *
+ * No PKIX_* types and functions should be used after this function is called
+ * and returns successfully.
+ *
+ * PARAMETERS:
+ * "platformInitNeeded"
+ * Boolean value of whether PKIX initialized NSS: PKIX_TRUE if we
+ * called nssInit, PKIX_FALSE otherwise
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe
+ *
+ * This function makes use of global variables and should only be called once.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Shutdown(void *plContext);
+
+/* standard memory management operations (not reference-counted) */
+
+/*
+ * FUNCTION: PKIX_PL_Malloc
+ * DESCRIPTION:
+ *
+ * Allocates a block of "size" bytes. The bytes are not initialized. A
+ * pointer to the newly allocated memory will be stored at "pMemory". The
+ * memory allocated by PKIX_PL_Malloc() may only be freed by PKIX_PL_Free().
+ * If "size" equals zero, this function stores NULL at "pMemory".
+ *
+ * PARAMETERS:
+ * "size"
+ * Number of bytes to allocate.
+ * "pMemory"
+ * Address where newly allocated pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread safety depends on underlying thread safety of platform used by PL.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Malloc(
+ PKIX_UInt32 size,
+ void **pMemory,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Calloc
+ * DESCRIPTION:
+ *
+ * Allocates memory for an array of "nElem" elements, with each element
+ * requiring "elSize" bytes, and with all the bits initialized to zero. A
+ * pointer to the newly allocated memory will be stored at "pMemory". The
+ * memory allocated by PKIX_PL_Calloc() may only be freed by PKIX_PL_Free().
+ * If "nElem" equals zero or "elSize" equals zero, this function stores NULL
+ * at "pMemory".
+ *
+ * PARAMETERS:
+ * "nElem"
+ * Number of elements needed.
+ * "elSize"
+ * Number of bytes needed per element.
+ * "pMemory"
+ * Address where newly allocated pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread safety depends on underlying thread safety of platform used by PL.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Calloc(
+ PKIX_UInt32 nElem,
+ PKIX_UInt32 elSize,
+ void **pMemory,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Realloc
+ * DESCRIPTION:
+ *
+ * Resizes an existing block of memory (pointed to by "ptr") to "size" bytes.
+ * Stores a pointer to the resized memory at "pNewPtr". The "ptr" must
+ * originate from either PKIX_PL_Malloc(), PKIX_PL_Realloc(), or
+ * PKIX_PL_Calloc(). If "ptr" is NULL, this function behaves as if
+ * PKIX_PL_Malloc were called. If "ptr" is not NULL and "size" equals zero,
+ * the memory pointed to by "ptr" is deallocated and this function stores
+ * NULL at "pPtr".
+ *
+ * PARAMETERS:
+ * "ptr"
+ * A pointer to an existing block of memory.
+ * "size"
+ * New size in bytes.
+ * "pPtr"
+ * Address where newly allocated pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread safety depends on underlying thread safety of platform used by PL.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Realloc(
+ void *ptr,
+ PKIX_UInt32 size,
+ void **pNewPtr,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Free
+ * DESCRIPTION:
+ *
+ * Frees a block of memory pointed to by "ptr". This value must originate with
+ * either PKIX_PL_Malloc(), PKIX_PL_Calloc, or PKIX_PL_Realloc(). If "ptr" is
+ * NULL, the function has no effect.
+ *
+ * PARAMETERS:
+ * "ptr"
+ * A pointer to an existing block of memory.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread safety depends on underlying thread safety of platform used by PL.
+ * RETURNS:
+ * Returns NULL always.
+ */
+PKIX_Error *
+PKIX_PL_Free(
+ void *ptr,
+ void *plContext);
+
+/* Callback Types
+ *
+ * The next few typedefs define function pointer types for the standard
+ * functions associated with every object type. See the Implementation
+ * Guidelines or the comments below for more information.
+ */
+
+/*
+ * TYPE: PKIX_PL_DestructorCallback
+ * DESCRIPTION:
+ *
+ * This callback function destroys (or DecRef's) any pointers contained in
+ * the user data for the Object pointed to by "object" before the Object is
+ * destroyed.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object to destroy. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts (as long as they're not operating on the same
+ * object and nobody else is performing an operation on the object at the
+ * same time). Both of these conditions should be guaranteed by the fact that
+ * the object's ref count was reduced to 0 in a lock that's still held when
+ * this callback is called.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_PL_DestructorCallback)(
+ PKIX_PL_Object *object,
+ void *plContext);
+
+/*
+ * TYPE: PKIX_PL_EqualsCallback
+ * DESCRIPTION:
+ *
+ * This callback function compares the Object pointed to by "firstObject" with
+ * the Object pointed to by "secondObject" for equality and stores the result
+ * at "pResult" (PKIX_TRUE if equal; PKIX_FALSE if not).
+ *
+ * PARAMETERS:
+ * "firstObject"
+ * Address of first object to compare. Must be non-NULL.
+ * "secondObject"
+ * Address of second object to compare. Must be non-NULL.
+ * "pResult"
+ * Address where Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same objects.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_PL_EqualsCallback)(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext);
+
+/*
+ * TYPE: PKIX_PL_HashcodeCallback
+ * DESCRIPTION:
+ *
+ * This callback function computes the hashcode of the Object pointed to by
+ * "object" and stores the result at "pValue".
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object whose hashcode is desired. Must be non-NULL.
+ * "pValue"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_PL_HashcodeCallback)(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pValue,
+ void *plContext);
+
+/*
+ * TYPE: PKIX_PL_ToStringCallback
+ * DESCRIPTION:
+ *
+ * This callback function converts the Object pointed to by "object" to a
+ * string representation and stores the result at "pString".
+ *
+ * PARAMETERS:
+ * "object"
+ * Object to get a string representation from. Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_PL_ToStringCallback)(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+/*
+ * TYPE: PKIX_PL_ComparatorCallback
+ * DESCRIPTION:
+ *
+ * This callback function determines how the Object pointed to by
+ * "firstObject" compares to the Object pointed to by "secondObject" and
+ * stores the result at "pResult".
+ *
+ * Result is less than 0 if firstObject < secondObject
+ * Result equals 0 if firstObject = secondObject
+ * Result is greater than 0 if firstObject > secondObject
+ *
+ * PARAMETERS:
+ * "firstObject"
+ * Address of the first Object to compare. Must be non-NULL.
+ * "secondObject"
+ * Address of the second Object to compare. Must be non-NULL.
+ * "pResult"
+ * Address where PKIX_Int32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same objects.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_PL_ComparatorCallback)(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext);
+
+/*
+ * TYPE: PKIX_PL_DuplicateCallback
+ * DESCRIPTION:
+ *
+ * This callback function creates a copy of the Object pointed to by "object"
+ * and stores it at "pNewObject". Changes to the copy will not affect the
+ * original and vice versa.
+ *
+ * Note that if "object" is immutable, the Duplicate callback function simply
+ * needs to increment the reference count on "object" and return a reference
+ * to "object".
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of the object to be copied. Must be non-NULL.
+ * "pNewObject"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_PL_DuplicateCallback)(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext);
+
+/* reference-counted objects */
+
+/*
+ * FUNCTION: PKIX_PL_Object_Alloc
+ * DESCRIPTION:
+ *
+ * Allocates a new Object of type "type" with "size" bytes and stores the
+ * resulting pointer at "pObject". The reference count of the newly
+ * allocated object will be initialized to 1. To improve performance, each
+ * object maintains a small cache for the results of Hashcode and ToString.
+ * Mutable objects should call InvalidateCache whenever changes are made to
+ * the object's state (after creation). If an error occurs during allocation,
+ * "pObject" will be set to NULL. If "size" equals zero, this function creates
+ * an Object with a reference count of 1, and places a pointer to unallocated
+ * memory at "pMemory".
+ *
+ * PARAMETERS:
+ * "type"
+ * The type code of this object. See pkixt.h for codes. The type code
+ * must be previously registered with PKIX_PL_Object_RegisterType().
+ * "size"
+ * The number of bytes needed for this object.
+ * "pMemory"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_Alloc(
+ PKIX_TYPENUM type,
+ PKIX_UInt32 size,
+ PKIX_PL_Object **pObject,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Object_IsTypeRegistered
+ * DESCRIPTION:
+ *
+ * Checks whether "type" has been registered by a previous call to
+ * PKIX_PL_Object_RegisterType() and stores the Boolean result at "pBool".
+ * This function will typically only be called by constructors for specific
+ * types.
+ *
+ * PARAMETERS:
+ * "type"
+ * The type code to check if valid.
+ * "pBool"
+ * Address where Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_IsTypeRegistered(
+ PKIX_UInt32 type,
+ PKIX_Boolean *pBool,
+ void *plContext);
+
+#ifdef PKIX_USER_OBJECT_TYPE
+/*
+ * FUNCTION: PKIX_PL_Object_RegisterType
+ * DESCRIPTION:
+ *
+ * Registers a new Object with type value "type" and associates it with a set
+ * of functions ("destructor", "equalsFunction", "hashcodeFunction",
+ * "toStringFunction", "comparator", "duplicateFunction"). The new type value
+ * is also associated with a string pointed to by "description", which is used
+ * by the default ToStringCallback. This function may only be called with a
+ * particular "type" value once. If "destructor", "equalsFunction",
+ * "hashcodeFunction", or "toStringFunction" are NULL, default functions will
+ * be registered. However, if "comparator" and "duplicateFunction" are NULL,
+ * no functions will be registered and calls to PKIX_PL_Object_Compare and
+ * PKIX_PL_Object_Duplicate will result in an error.
+ *
+ * PARAMETERS:
+ * "type"
+ * The type code.
+ * "description"
+ * The string used by the default ToStringCallback. Default used if NULL.
+ * "destructor"
+ * The DestructorCallback function to be set. Default used if NULL.
+ * "equalsFunction"
+ * The EqualsCallback function to be set. Default used if NULL.
+ * "hashcodeFunction"
+ * The HashcodeCallback function to be set. Default used if NULL.
+ * "toStringFunction"
+ * The ToStringCallback function to be set. Default used if NULL.
+ * "comparator"
+ * The ComparatorCallback function to be set. None set if NULL. If no
+ * callback function is set in this field, calls to
+ * PKIX_PL_Object_Compare() will result in an error.
+ * "duplicateFunction"
+ * The DuplicateCallback function to be set. None set if NULL. If no
+ * callback function is set in this field, calls to
+ * PKIX_PL_Object_Duplicate() will result in an error.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object Error if "type" is already registered.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_RegisterType(
+ PKIX_UInt32 type,
+ char *description,
+ PKIX_PL_DestructorCallback destructor,
+ PKIX_PL_EqualsCallback equalsFunction,
+ PKIX_PL_HashcodeCallback hashcodeFunction,
+ PKIX_PL_ToStringCallback toStringFunction,
+ PKIX_PL_ComparatorCallback comparator,
+ PKIX_PL_DuplicateCallback duplicateFunction,
+ void *plContext);
+
+#endif
+/*
+ * FUNCTION: PKIX_PL_Object_InvalidateCache
+ * DESCRIPTION:
+ *
+ * Invalidates the cache of the Object pointed to by "object". The cache
+ * contains results of Hashcode and ToString. This function should be used by
+ * mutable objects whenever changes are made to the Object's state (after
+ * creation).
+ *
+ * For example, if ToString is called on a mutable Object, the result will be
+ * computed, cached, and returned. If the Object's state does not change, a
+ * subsequent call to ToString will recognize that the relevant result is
+ * cached and will simply return the result (without calling the Object's
+ * ToStringCallback to recompute it). However, when the Object's state
+ * changes, the cache needs to be invalidated in order to force a subsequent
+ * call to ToString to recompute the result.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object whose cache is to be invalidated. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY
+ * Thread Safe - Object Type Table is locked during modification.
+ *
+ * Multiple threads can safely call this function without worrying about
+ * conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_InvalidateCache(
+ PKIX_PL_Object *object,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Object_IncRef
+ * DESCRIPTION:
+ *
+ * Increments the reference count of the Object pointed to by "object".
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object whose reference count is to be incremented.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_IncRef(
+ PKIX_PL_Object *object,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Object_DecRef
+ * DESCRIPTION:
+ *
+ * Decrements the reference count of the Object pointed to by "object". If the
+ * resulting reference count is zero, the destructor (if any) registered for
+ * the Object's type (by PKIX_PL_RegisterType) will be called and then the
+ * Object will be destroyed.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object whose reference count is to be decremented.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * If destructor is not called, multiple threads can safely call this function
+ * without worrying about conflicts, even if they're operating on the same
+ * object. If destructor is called, thread safety depends on the callback
+ * defined by PKIX_PL_RegisterType().
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_DecRef(
+ PKIX_PL_Object *object,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Object_Equals
+ * DESCRIPTION:
+ *
+ * Compares the Object pointed to by "firstObject" with the Object pointed to
+ * by "secondObject" for equality using the callback function registered for
+ * "firstObject"'s type, and stores the Boolean result at "pResult". While
+ * typical callbacks will return PKIX_FALSE if the objects are of different
+ * types, other callbacks may be capable of comparing objects of different
+ * types [which may correctly result in cases where Equals(first, second)
+ * differs from Equals(second, first)].
+ *
+ * PARAMETERS:
+ * "firstObject"
+ * Address of the first Object to compare. Must be non-NULL.
+ * The EqualsCallback for this Object will be called.
+ * "secondObject"
+ * Address of the second Object to compare. Must be non-NULL.
+ * "pResult"
+ * Address where Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread safety depends on the callback defined by PKIX_PL_RegisterType().
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Object_Hashcode
+ * DESCRIPTION:
+ *
+ * Computes a hashcode of the Object pointed to by "object" using the
+ * callback registered for "object"'s type and stores it at "pValue". Two
+ * objects which are equal should have the same hashcode. Once a call to
+ * Hashcode has been made, the results are cached and subsequent calls to
+ * Hashcode will return the cached value. For mutable objects, an
+ * InvalidateCache function is provided, which should be called whenever
+ * changes are made to the object's state (after creation).
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of the Object whose hashcode is desired. Must be non-NULL.
+ * The HashcodeCallback for this object will be called.
+ * "pValue"
+ * Address where PKIX_Int32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread safety depends on the callback defined by PKIX_PL_RegisterType().
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pValue,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Object_ToString
+ * DESCRIPTION:
+ *
+ * Creates a string representation of the Object pointed to by "object" using
+ * the callback registered for "object"'s type and stores it at "pString".
+ * Once a call to ToString has been made, the results are cached and
+ * subsequent calls to ToString will return the cached value. For mutable
+ * objects, an InvalidateCache function is provided, which should be called
+ * whenever changes are made to the object's state (after creation).
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object whose string representation is desired.
+ * Must be non-NULL. The ToStringCallback for this object will be called.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread safety depends on the callback defined by PKIX_PL_RegisterType().
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Object_Compare
+ * DESCRIPTION:
+ *
+ * Compares the Object pointed to by "firstObject" and the Object pointed to
+ * by "secondObject" using the comparator registered for "firstObject"'s type
+ * and stores the result at "pResult". Different types may be compared. This
+ * may correctly result in cases where Compare(first, second) is not the
+ * opposite of Compare(second, first). The PKIX_Int32 value stored at
+ * "pResult" will be:
+ * Less than 0 if "firstObject" < "secondObject"
+ * Equals to 0 if "firstObject" = "secondObject"
+ * Greater than 0 if "firstObject" > "secondObject"
+ *
+ * PARAMETERS:
+ * "firstObject"
+ * Address of first Object to compare. Must be non-NULL.
+ * The ComparatorCallback for this object will be called.
+ * "secondObject"
+ * Address of second object to compare. Must be non-NULL.
+ * "pResult
+ * Address where PKIX_Int32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread safety depends on the comparator defined by PKIX_PL_RegisterType().
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_Compare(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Object_Duplicate
+ * DESCRIPTION:
+ *
+ * Creates a duplicate copy of the Object pointed to by "object" using the
+ * callback registered for "object"'s type and stores the copy at
+ * "pNewObject". Changes to the new object will not affect the original and
+ * vice versa.
+ *
+ * Note that if "object" is immutable, the Duplicate callback function simply
+ * needs to increment the reference count on "object" and return a reference
+ * to "object".
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object to be duplicated. Must be non-NULL.
+ * The DuplicateCallback for this Object will be called.
+ * "pNewObject"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread safety depends on the callback defined by PKIX_PL_RegisterType().
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Object_GetType
+ * DESCRIPTION:
+ *
+ * Retrieves the type code of the Object pointed to by "object" and stores it
+ * at "pType". See pkixt.h for type codes.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object whose type is desired. Must be non-NULL.
+ * "pType"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_GetType(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pType,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Object_Lock
+ * DESCRIPTION:
+ *
+ * Locks the Mutex associated with the Object pointed to by "object". When an
+ * object is created, it is associated with an object-specific Mutex to allow
+ * for synchronization when the fields of the object are modified.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object whose Mutex is to be locked. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_Lock(
+ PKIX_PL_Object *object,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Object_Unlock
+ * DESCRIPTION:
+ *
+ * Unlocks the Mutex associated with the Object pointed to by "object". When
+ * an object is created, it is associated with an object-specific Mutex to
+ * allow for synchronization when the fields of the object are modified.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object whose Mutex is to be unlocked. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Object_Unlock(
+ PKIX_PL_Object *object,
+ void *plContext);
+
+/* mutexes (locks) */
+
+/*
+ * FUNCTION: PKIX_PL_Mutex_Create
+ * DESCRIPTION:
+ *
+ * Creates a new Mutex and stores it at "pNewLock".
+ *
+ * PARAMETERS:
+ * "pNewLock"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Mutex_Create(
+ PKIX_PL_Mutex **pNewLock,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Mutex_Lock
+ * DESCRIPTION:
+ *
+ * Locks the Mutex pointed to by "lock". If the Mutex is already locked, this
+ * function will block the current thread until the mutex can be locked by
+ * this thread.
+ *
+ * PARAMETERS:
+ * "lock"
+ * Address of Mutex to lock. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Mutex_Lock(
+ PKIX_PL_Mutex *lock,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Mutex_Unlock
+ * DESCRIPTION:
+ *
+ * Unlocks the Mutex pointed to by "lock" if the current thread holds the
+ * Mutex.
+ *
+ * PARAMETERS:
+ * "lock"
+ * Address of Mutex to unlock. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Mutex_Unlock(
+ PKIX_PL_Mutex *lock,
+ void *plContext);
+
+/* monitor (locks) */
+
+/*
+ * FUNCTION: PKIX_PL_MonitorLock_Create
+ * DESCRIPTION:
+ *
+ * Creates a new PKIX_PL_MonitorLock and stores it at "pNewLock".
+ *
+ * PARAMETERS:
+ * "pNewLock"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_MonitorLock_Create(
+ PKIX_PL_MonitorLock **pNewLock,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_MonitorLock_Enter
+ * DESCRIPTION:
+ *
+ * Locks the MonitorLock pointed to by "lock". If the MonitorLock is already
+ * locked by other thread, this function will block the current thread. If
+ * the "lock" had been locked by current thread, this function will NOT block.
+ *
+ * PARAMETERS:
+ * "lock"
+ * Address of MonitorLock to lock. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_MonitorLock_Enter(
+ PKIX_PL_MonitorLock *lock,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_MonitorLock_Exit
+ * DESCRIPTION:
+ *
+ * Unlocks the MonitorLock pointed to by "lock" if the lock counter of
+ * current thread holds the MonitorLock reach 0, the lock is released.
+ *
+ * PARAMETERS:
+ * "lock"
+ * Address of MonitorLock to unlock. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_MonitorLock_Exit(
+ PKIX_PL_MonitorLock *lock,
+ void *plContext);
+
+/* strings and formatted printing */
+
+/*
+ * FUNCTION: PKIX_PL_String_Create
+ * DESCRIPTION:
+ *
+ * Creates a new String using the data pointed to by "pString", the
+ * PKIX_UInt32 pointed to by "stringLen", and the PKIX_UInt32 pointed to by
+ * "fmtIndicator" and stores it at "pString". If the format is PKIX_ESCASCII
+ * the "stringLen" parameter is ignored and the string extends until a zero
+ * byte is found. Once created, a String object is immutable.
+ *
+ * Valid formats are:
+ * PKIX_ESCASCII
+ * PKIX_ESCASCII_DEBUG
+ * PKIX_UTF8
+ * PKIX_UTF8_NULL_TERM
+ * PKIX_UTF16
+ *
+ * PARAMETERS:
+ * "fmtIndicator"
+ * Format that "stringRep" is encoded with. Must be non-NULL.
+ * "stringRep"
+ * Address of encoded string representation. Must be non-NULL.
+ * "stringLen"
+ * Length of data stored at stringRep.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a String Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_String_Create(
+ PKIX_UInt32 fmtIndicator,
+ const void *stringRep,
+ PKIX_UInt32 stringLen,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_Sprintf
+ * DESCRIPTION:
+ *
+ * Creates a formatted string at "pOut" using the given format "fmt" and a
+ * variable length list of arguments. The format flags are identical to
+ * standard C with the exception that %s expects a PKIX_PL_String*, rather
+ * than a char *, and that {%d, %i, %o, %u, %x, %X} expect PKIX_UInt32 or
+ * PKIX_Int32 instead of int or unsigned int.
+ *
+ * PARAMETERS:
+ * "pOut"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * "fmt"
+ * Address of format string. Must be non-NULL.
+ * THREAD SAFETY:
+ * Not Thread Safe - Caller must have exclusive access to all arguments.
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a String Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Sprintf(
+ PKIX_PL_String **pOut,
+ void *plContext,
+ const PKIX_PL_String *fmt, ...);
+
+/*
+ * FUNCTION: PKIX_PL_GetString
+ * DESCRIPTION:
+ *
+ * Retrieves the String associated with the value of "stringID" (if any) and
+ * stores it at "pString". If no such string is associated with "stringID",
+ * this function uses "defaultString" to create a String and stores it at
+ * "pString".
+ *
+ * PARAMETERS:
+ * "stringID"
+ * PKIX_UInt32 valud of string identifier.
+ * "defaultString"
+ * Address of a PKIX_ESCASCII encoded string representation.
+ * Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a String Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_GetString(
+ PKIX_UInt32 stringID,
+ char *defaultString,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_String_GetEncoded
+ * DESCRIPTION:
+ *
+ * Retrieves the value of the String pointed to by "string" in the encoding
+ * specified by "fmtIndicator" and stores the result in "pStringRep" and
+ * "pLength", respectively. Note that "pStringRep" is not reference counted
+ * and will need to be freed with PKIX_PL_Free().
+ *
+ * PARAMETERS:
+ * "string"
+ * Address of String whose encoded value is desired. Must be non-NULL.
+ * "fmtIndicator"
+ * Format of encoding. Supported formats are:
+ * PKIX_ESCASCII, PKIX_ESCASII_DEBUG, PKIX_UTF8, PKIX_UTF8_NULL_TERM, and
+ * PKIX_UTF16. XXX Where are these documented?
+ * "pStringRep"
+ * Address where pointer to encoded value will be stored.
+ * Must be non-NULL.
+ * "pLength"
+ * Address where byte length of encoded value will be stored.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a String Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_String_GetEncoded(
+ PKIX_PL_String *string,
+ PKIX_UInt32 fmtIndicator,
+ void **pStringRep,
+ PKIX_UInt32 *pLength,
+ void *plContext);
+
+/*
+ * Hashtable
+ *
+ * A hashtable is a very efficient data structure used for mapping keys to
+ * values. Any non-null PKIX_PL_Object can be used as a key or as a value,
+ * provided that it correctly implements the PKIX_PL_EqualsCallback and the
+ * PKIX_PL_HashcodeCallback. A hashtable consists of several buckets, with
+ * each bucket capable of holding a linked list of key/value mappings. When
+ * adding, retrieving, or deleting a value, the hashcode of the key is used to
+ * determine which bucket's linked list is relevant. The corresponding
+ * key/value pair is then appended, retrieved, or deleted.
+ */
+
+/*
+ * FUNCTION: PKIX_PL_HashTable_Create
+ * DESCRIPTION:
+ *
+ * Creates a new Hashtable with an initial capacity of "numBuckets" buckets
+ * and "maxEntriesPerBucket" of entries limit for each bucket and stores it
+ * at "pResult".
+ *
+ * PARAMETERS:
+ * "numBuckets"
+ * The initial number of hash table buckets. Must be non-zero.
+ * "maxEntriesPerBucket"
+ * The limit of entries per bucket. Zero means no limit.
+ * "pResult"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_HashTable_Create(
+ PKIX_UInt32 numBuckets,
+ PKIX_UInt32 maxEntriesPerBucket,
+ PKIX_PL_HashTable **pResult,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_HashTable_Add
+ * DESCRIPTION:
+ *
+ * Adds a key/value mapping using the Objects pointed to by "key" and "value"
+ * to the Hashtable pointed to by "ht".
+ *
+ * Function increments key/value reference counts. Caller is responsible to
+ * to decrement(destroy) key/value ref counts(objects).
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of Hashtable to be added to. Must be non-NULL.
+ * "key"
+ * Address of Object to be associated with "value". Must be non-NULL.
+ * "value"
+ * Address of Object to be added to Hashtable. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "ht"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Hashtable Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_HashTable_Add(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_Object *key,
+ PKIX_PL_Object *value,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_HashTable_Remove
+ * DESCRIPTION:
+ *
+ * Removes the Object value whose key is equal to the Object pointed to by
+ * "key" from the Hashtable pointed to by "ht". If no such object exists,
+ * this function throws an Error.
+ *
+ * Function frees "value" object. Caller is responsible to free "key"
+ * object.
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of Hashtable to remove object from. Must be non-NULL.
+ * "key"
+ * Address of Object used for lookup. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "ht"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Hashtable Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_HashTable_Remove(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_Object *key,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_HashTable_Lookup
+ * DESCRIPTION:
+ *
+ * Retrieves the Object whose key equals the Object pointed to by "key" from
+ * the Hashtable associated with "ht" and stores it at "pResult". If no
+ * Object is found, this function stores NULL at "pResult".
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of Hashtable to lookup Object from. Must be non-NULL.
+ * "key"
+ * Address of key Object used for lookup. Must be non-NULL.
+ * "pResult"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Hashtable Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_HashTable_Lookup(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_Object *key,
+ PKIX_PL_Object **pResult,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_ByteArray_Create
+ * DESCRIPTION:
+ *
+ * Creates a new ByteArray using "length" bytes of data pointed to by "array"
+ * and stores it at "pByteArray". Once created, a ByteArray is immutable.
+ *
+ * PARAMETERS:
+ * "array"
+ * Address of source data.
+ * "length"
+ * Number of bytes to copy.
+ * "pByteArray"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_ByteArray_Create(
+ void *array,
+ PKIX_UInt32 length,
+ PKIX_PL_ByteArray **pByteArray,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_ByteArray_GetPointer
+ * DESCRIPTION:
+ *
+ * Allocates enough memory to hold the contents of the ByteArray pointed to
+ * by "byteArray", copies the data from the ByteArray pointed to by
+ * "byteArray" into the newly allocated memory, and stores a pointer to the
+ * memory at "pArray". Note that "pArray" is not reference counted. It will
+ * need to be freed with PKIX_PL_Free().
+ *
+ * PARAMETERS:
+ * "byteArray"
+ * Address of ByteArray whose data is desired. Must be non-NULL.
+ * "pArray"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_ByteArray_GetPointer(
+ PKIX_PL_ByteArray *byteArray,
+ void **pArray,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_ByteArray_GetLength
+ * DESCRIPTION:
+ *
+ * Retrieves the length of the ByteArray pointed to by "byteArray" and stores
+ * the length at "pLength".
+ *
+ * PARAMETERS:
+ * "byteArray"
+ * Address of ByteArray whose length is desired. Must be non-NULL.
+ * "pLength"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_ByteArray_GetLength(
+ PKIX_PL_ByteArray *byteArray,
+ PKIX_UInt32 *pLength,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_OID_Create
+ * DESCRIPTION:
+ *
+ * Creates a new OID using NSS oid tag.
+ *
+ * PARAMETERS:
+ * "idtag"
+ * nss oid id tag.
+ * "pOID"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OID Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_OID_Create(
+ SECOidTag idtag,
+ PKIX_PL_OID **pOID,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_OID_CreateBySECItem
+ * DESCRIPTION:
+ *
+ * Creates a new OID using a DER encoded OID stored as SECItem.
+ *
+ * PARAMETERS:
+ * "derOid"
+ * Address of SECItem that holds DER encoded OID.
+ * "pOID"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OID Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_OID_CreateBySECItem(
+ SECItem *derOid,
+ PKIX_PL_OID **pOID,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_BigInt_Create
+ * DESCRIPTION:
+ *
+ * Creates a new BigInt using the source String pointed to by "stringRep" and
+ * stores it at "pBigInt". Valid source Strings consist of an even number of
+ * hexadecimal digits, which are always interpreted as a positive number.
+ * Once created, a BigInt is immutable.
+ *
+ * The regexp format is:
+ * HexDigit ::= [0-9] | [A-F] | [a-f]
+ * DoubleHex ::= HexDigit HexDigit
+ * BigIntSrc ::= (DoubleHex)+
+ *
+ * Note that since we are using DoubleHex, the number of characters in the
+ * source MUST be even. Additionally, the first DoubleHex MUST NOT be "00"
+ * unless it is the only DoubleHex.
+ *
+ * Valid : "09"
+ * Valid : "00" (special case where first and only DoubleHex is "00")
+ * Invalid: "9" (not DoubleHex: odd number of characters)
+ * Invalid: "0009" (first DoubleHex is "00")
+ *
+ * XXX Why does this take a String object while OID_Create takes a char* ?
+ * Perhaps because OID_Create is often used with constant strings and
+ * this function isn't. That's a good reason, but we should explain it
+ * (if it's right)
+ * PARAMETERS:
+ * "stringRep"
+ * Address of String representing a BigInt. Must be non-NULL.
+ * "pBigInt"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a BigInt Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_BigInt_Create(
+ PKIX_PL_String *stringRep,
+ PKIX_PL_BigInt **pBigInt,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * FUNCTION: PKIX_PL_GetPLErrorCode
+ * DESCRIPTION:
+ *
+ * Returns error code from PL layer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * PL layer error code.
+ */
+int
+PKIX_PL_GetPLErrorCode();
+
+#endif /* _LIBPKIX_SYSTEM_H */
diff --git a/security/nss/lib/libpkix/include/pkix_results.h b/security/nss/lib/libpkix/include/pkix_results.h
new file mode 100644
index 0000000000..bf4a381faa
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkix_results.h
@@ -0,0 +1,425 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 file defines functions associated with the results used
+ * by the top-level functions.
+ *
+ */
+
+#ifndef _PKIX_RESULTS_H
+#define _PKIX_RESULTS_H
+
+#include "pkixt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General
+ *
+ * Please refer to the libpkix Programmer's Guide for detailed information
+ * about how to use the libpkix library. Certain key warnings and notices from
+ * that document are repeated here for emphasis.
+ *
+ * All identifiers in this file (and all public identifiers defined in
+ * libpkix) begin with "PKIX_". Private identifiers only intended for use
+ * within the library begin with "pkix_".
+ *
+ * A function returns NULL upon success, and a PKIX_Error pointer upon failure.
+ *
+ * Unless otherwise noted, for all accessor (gettor) functions that return a
+ * PKIX_PL_Object pointer, callers should assume that this pointer refers to a
+ * shared object. Therefore, the caller should treat this shared object as
+ * read-only and should not modify this shared object. When done using the
+ * shared object, the caller should release the reference to the object by
+ * using the PKIX_PL_Object_DecRef function.
+ *
+ * While a function is executing, if its arguments (or anything referred to by
+ * its arguments) are modified, free'd, or destroyed, the function's behavior
+ * is undefined.
+ *
+ */
+/* PKIX_ValidateResult
+ *
+ * PKIX_ValidateResult represents the result of a PKIX_ValidateChain call. It
+ * consists of the valid policy tree and public key resulting from validation,
+ * as well as the trust anchor used for this chain. Once created, a
+ * ValidateResult object is immutable.
+ */
+
+/*
+ * FUNCTION: PKIX_ValidateResult_GetPolicyTree
+ * DESCRIPTION:
+ *
+ * Retrieves the PolicyNode component (representing the valid_policy_tree)
+ * from the ValidateResult object pointed to by "result" and stores it at
+ * "pPolicyTree".
+ *
+ * PARAMETERS:
+ * "result"
+ * Address of ValidateResult whose policy tree is to be stored. Must be
+ * non-NULL.
+ * "pPolicyTree"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Result Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ValidateResult_GetPolicyTree(
+ PKIX_ValidateResult *result,
+ PKIX_PolicyNode **pPolicyTree,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ValidateResult_GetPublicKey
+ * DESCRIPTION:
+ *
+ * Retrieves the PublicKey component (representing the valid public_key) of
+ * the ValidateResult object pointed to by "result" and stores it at
+ * "pPublicKey".
+ *
+ * PARAMETERS:
+ * "result"
+ * Address of ValidateResult whose public key is to be stored.
+ * Must be non-NULL.
+ * "pPublicKey"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Result Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ValidateResult_GetPublicKey(
+ PKIX_ValidateResult *result,
+ PKIX_PL_PublicKey **pPublicKey,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_ValidateResult_GetTrustAnchor
+ * DESCRIPTION:
+ *
+ * Retrieves the TrustAnchor component (representing the trust anchor used
+ * during chain validation) of the ValidateResult object pointed to by
+ * "result" and stores it at "pTrustAnchor".
+ *
+ * PARAMETERS:
+ * "result"
+ * Address of ValidateResult whose trust anchor is to be stored.
+ * Must be non-NULL.
+ * "pTrustAnchor"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Result Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_ValidateResult_GetTrustAnchor(
+ PKIX_ValidateResult *result,
+ PKIX_TrustAnchor **pTrustAnchor,
+ void *plContext);
+
+/* PKIX_BuildResult
+ *
+ * PKIX_BuildResult represents the result of a PKIX_BuildChain call. It
+ * consists of a ValidateResult object, as well as the built and validated
+ * CertChain. Once created, a BuildResult object is immutable.
+ */
+
+/*
+ * FUNCTION: PKIX_BuildResult_GetValidateResult
+ * DESCRIPTION:
+ *
+ * Retrieves the ValidateResult component (representing the build's validate
+ * result) of the BuildResult object pointed to by "result" and stores it at
+ * "pResult".
+ *
+ * PARAMETERS:
+ * "result"
+ * Address of BuildResult whose ValidateResult component is to be stored.
+ * Must be non-NULL.
+ * "pResult"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Result Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_BuildResult_GetValidateResult(
+ PKIX_BuildResult *result,
+ PKIX_ValidateResult **pResult,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_BuildResult_GetCertChain
+ * DESCRIPTION:
+ *
+ * Retrieves the List of Certs (certChain) component (representing the built
+ * and validated CertChain) of the BuildResult object pointed to by "result"
+ * and stores it at "pChain".
+ *
+ * PARAMETERS:
+ * "result"
+ * Address of BuildResult whose CertChain component is to be stored.
+ * Must be non-NULL.
+ * "pChain"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Result Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_BuildResult_GetCertChain(
+ PKIX_BuildResult *result,
+ PKIX_List **pChain,
+ void *plContext);
+
+/* PKIX_PolicyNode
+ *
+ * PKIX_PolicyNode represents a node in the policy tree returned in
+ * ValidateResult. The policy tree is the same length as the validated
+ * certificate chain and the nodes are associated with a particular depth
+ * (corresponding to a particular certificate in the chain).
+ * PKIX_ValidateResult_GetPolicyTree returns the root node of the valid policy
+ * tree. Other nodes can be accessed using the getChildren and getParents
+ * functions, and individual elements of a node can be accessed with the
+ * appropriate gettors. Once created, a PolicyNode is immutable.
+ */
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetChildren
+ * DESCRIPTION:
+ *
+ * Retrieves the List of PolicyNodes representing the child nodes of the
+ * Policy Node pointed to by "node" and stores it at "pChildren". If "node"
+ * has no child nodes, this function stores an empty List at "pChildren".
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of PolicyNode whose child nodes are to be stored.
+ * Must be non-NULL.
+ * "pChildren"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Result Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetChildren(
+ PKIX_PolicyNode *node,
+ PKIX_List **pChildren, /* list of PKIX_PolicyNode */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetParent
+ * DESCRIPTION:
+ *
+ * Retrieves the PolicyNode representing the parent node of the PolicyNode
+ * pointed to by "node" and stores it at "pParent". If "node" has no parent
+ * node, this function stores NULL at "pParent".
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of PolicyNode whose parent node is to be stored.
+ * Must be non-NULL.
+ * "pParent"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Result Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetParent(
+ PKIX_PolicyNode *node,
+ PKIX_PolicyNode **pParent,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetValidPolicy
+ * DESCRIPTION:
+ *
+ * Retrieves the OID representing the valid policy of the PolicyNode pointed
+ * to by "node" and stores it at "pValidPolicy".
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of PolicyNode whose valid policy is to be stored.
+ * Must be non-NULL.
+ * "pValidPolicy"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Result Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetValidPolicy(
+ PKIX_PolicyNode *node,
+ PKIX_PL_OID **pValidPolicy,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetPolicyQualifiers
+ * DESCRIPTION:
+ *
+ * Retrieves the List of CertPolicyQualifiers representing the policy
+ * qualifiers associated with the PolicyNode pointed to by "node" and stores
+ * it at "pQualifiers". If "node" has no policy qualifiers, this function
+ * stores an empty List at "pQualifiers".
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of PolicyNode whose policy qualifiers are to be stored.
+ * Must be non-NULL.
+ * "pQualifiers"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Result Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetPolicyQualifiers(
+ PKIX_PolicyNode *node,
+ PKIX_List **pQualifiers, /* list of PKIX_PL_CertPolicyQualifier */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetExpectedPolicies
+ * DESCRIPTION:
+ *
+ * Retrieves the List of OIDs representing the expected policies associated
+ * with the PolicyNode pointed to by "node" and stores it at "pExpPolicies".
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of PolicyNode whose expected policies are to be stored.
+ * Must be non-NULL.
+ * "pExpPolicies"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Result Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetExpectedPolicies(
+ PKIX_PolicyNode *node,
+ PKIX_List **pExpPolicies, /* list of PKIX_PL_OID */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PolicyNode_IsCritical
+ * DESCRIPTION:
+ *
+ * Checks the criticality field of the PolicyNode pointed to by "node" and
+ * stores the Boolean result at "pCritical".
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of PolicyNode whose criticality field is examined.
+ * Must be non-NULL.
+ * "pCritical"
+ * Address where Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Result Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PolicyNode_IsCritical(
+ PKIX_PolicyNode *node,
+ PKIX_Boolean *pCritical,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetDepth
+ * DESCRIPTION:
+ *
+ * Retrieves the depth component of the PolicyNode pointed to by "node" and
+ * stores it at "pDepth".
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of PolicyNode whose depth component is to be stored.
+ * Must be non-NULL.
+ * "pDepth"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Result Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetDepth(
+ PKIX_PolicyNode *node,
+ PKIX_UInt32 *pDepth,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_RESULTS_H */
diff --git a/security/nss/lib/libpkix/include/pkix_revchecker.h b/security/nss/lib/libpkix/include/pkix_revchecker.h
new file mode 100644
index 0000000000..a16d23a933
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkix_revchecker.h
@@ -0,0 +1,215 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * This file defines functions associated with the PKIX_RevocationChecker
+ * type.
+ *
+ */
+
+#ifndef _PKIX_REVCHECKER_H
+#define _PKIX_REVCHECKER_H
+
+#include "pkixt.h"
+#include "pkix_pl_pki.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General
+ *
+ * Please refer to the libpkix Programmer's Guide for detailed information
+ * about how to use the libpkix library. Certain key warnings and notices from
+ * that document are repeated here for emphasis.
+ *
+ * All identifiers in this file (and all public identifiers defined in
+ * libpkix) begin with "PKIX_". Private identifiers only intended for use
+ * within the library begin with "pkix_".
+ *
+ * A function returns NULL upon success, and a PKIX_Error pointer upon failure.
+ *
+ * Unless otherwise noted, for all accessor (gettor) functions that return a
+ * PKIX_PL_Object pointer, callers should assume that this pointer refers to a
+ * shared object. Therefore, the caller should treat this shared object as
+ * read-only and should not modify this shared object. When done using the
+ * shared object, the caller should release the reference to the object by
+ * using the PKIX_PL_Object_DecRef function.
+ *
+ * While a function is executing, if its arguments (or anything referred to by
+ * its arguments) are modified, free'd, or destroyed, the function's behavior
+ * is undefined.
+ *
+ */
+
+/* PKIX_RevocationChecker
+ *
+ * PKIX_RevocationChecker provides a standard way of revocation checking.
+ * Caller should configure two set of tests(represented at lists of
+ * RevocationMethod objects) to be performed on the leaf and on the rest of
+ * the chain certificates.
+ *
+ * PKIX_RevocationMethods provide a standard way for the caller to insert
+ * their own custom revocation checks to verify the revocation status of
+ * certificates. This may be useful in many scenarios, including when the
+ * caller wishes to use their own revocation checking mechanism instead of (or
+ * in addition to) the default revocation checking mechanism provided by
+ * libpkix, which uses CRLs and OCSP.
+ *
+ * Once the caller has created the RevocationMethod object(s), the caller
+ * then specifies the RevocationMethod object(s) in a RevocationCheck object
+ * and sets it into a ProcessingParams.
+ */
+
+/*
+ * FUNCTION: PKIX_RevocationChecker_Create
+ * DESCRIPTION:
+ *
+ * Creates a revocation checker object with the given flags. Revocation will
+ * be checked at the current date.
+ *
+ * PARAMETERS:
+ * "leafMethodListFlags"
+ * Defines a set of method independent flags that will be used to check
+ * revocation of the leaf cert in the chain.
+ * "chainMethodListFlags"
+ * Defines a set of method independent flags that will be used to check
+ * revocation of the remaining certs in the chain.
+ * "pChecker"
+ * The return address of created checker.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same objects.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a RevocationChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_RevocationChecker_Create(
+ PKIX_UInt32 leafMethodListFlags,
+ PKIX_UInt32 chainMethodListFlags,
+ PKIX_RevocationChecker **pChecker,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_RevocationChecker_CreateAndAddMethod
+ * DESCRIPTION:
+ *
+ * Creates revocation method object with given parameters and adds it
+ * to revocation checker method list.
+ *
+ * PARAMETERS:
+ * "revChecker"
+ * Address of revocation checker structure.
+ * "procParams"
+ * Address of ProcessingParams used to initialize the checker.
+ * Must be non-NULL.
+ * "methodType"
+ * Type of the method. Currently only two types are
+ * supported: crl and ocsp. (See PKIX_RevocationMethodType enum).
+ * "methodFlags"
+ * Set of flags for the method.
+ * "methodPriority"
+ * Method priority. (0 corresponds to the highest priority)
+ * "verificationFn"
+ * User call back function that will perform validation of fetched
+ * revocation information(new crl or ocsp response)
+ * "isLeafMethod"
+ * Boolean flag that if set to true indicates that the method should
+ * should be used for leaf cert revocation test(false for chain set
+ * methods).
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same objects.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a RevocationChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_RevocationChecker_CreateAndAddMethod(
+ PKIX_RevocationChecker *revChecker,
+ PKIX_ProcessingParams *params,
+ PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 methodFlags,
+ PKIX_UInt32 methodPriority,
+ PKIX_PL_VerifyCallback verificationFn,
+ PKIX_Boolean isLeafMethod,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_RevocationChecker_Check
+ * DESCRIPTION:
+ *
+ * Verifies revocation status of the certificate. Issuer cert is given to
+ * be used in verification of revocation information. Performed verification
+ * check depends on configured revocation methods(ocsp, crl. See
+ * PKIX_RevocationChecker_CreateAndAddMethod function) and a point of chain
+ * building process at which PKIX_RevocationChecker_Check was invoked.
+ * For security reasons, the cert status is checked only against cached
+ * revocation information during chain building stage(no trust anchor yes has
+ * been found). The fresh revocation information fetching is done only at chain
+ * verification stage after trust anchor was identified.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert whose revocation status is to be determined.
+ * Must be non-NULL.
+ * "issuer"
+ * Issuer cert that potentially holds public key that will be used
+ * to verify revocation info.
+ * "revChecker"
+ * Address of revocation checker structure.
+ * "procParams"
+ * Address of ProcessingParams used to initialize the checker.
+ * Must be non-NULL.
+ * "chainVerificationState"
+ * Need to be set to true, if the check was called during chain verification
+ * as an opposite to chain building.
+ * "testingLeafCert"
+ * Set to true if verifying revocation status of a leaf cert.
+ * "revStatus"
+ * Address of the returned revocation status of the cert.
+ * "pResultCode"
+ * Address where revocation status will be stored. Must be non-NULL.
+ * "pNBIOContext"
+ * Address at which platform-dependent non-blocking I/O context is stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same objects.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a RevocationChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_RevocationChecker_Check(PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_RevocationChecker *revChecker,
+ PKIX_ProcessingParams *procParams,
+ PKIX_Boolean chainVerificationState,
+ PKIX_Boolean testingLeafCert,
+ PKIX_RevocationStatus *revStatus,
+ PKIX_UInt32 *pReasonCode,
+ void **pNbioContext,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_REVCHECKER_H */
diff --git a/security/nss/lib/libpkix/include/pkix_sample_modules.h b/security/nss/lib/libpkix/include/pkix_sample_modules.h
new file mode 100644
index 0000000000..75d9618c57
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkix_sample_modules.h
@@ -0,0 +1,420 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 file defines functions associated with CertStore types.
+ *
+ */
+
+
+#ifndef _PKIX_SAMPLEMODULES_H
+#define _PKIX_SAMPLEMODULES_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General
+ *
+ * Please refer to the libpkix Programmer's Guide for detailed information
+ * about how to use the libpkix library. Certain key warnings and notices from
+ * that document are repeated here for emphasis.
+ *
+ * All identifiers in this file (and all public identifiers defined in
+ * libpkix) begin with "PKIX_". Private identifiers only intended for use
+ * within the library begin with "pkix_".
+ *
+ * A function returns NULL upon success, and a PKIX_Error pointer upon failure.
+ *
+ * Unless otherwise noted, for all accessor (gettor) functions that return a
+ * PKIX_PL_Object pointer, callers should assume that this pointer refers to a
+ * shared object. Therefore, the caller should treat this shared object as
+ * read-only and should not modify this shared object. When done using the
+ * shared object, the caller should release the reference to the object by
+ * using the PKIX_PL_Object_DecRef function.
+ *
+ * While a function is executing, if its arguments (or anything referred to by
+ * its arguments) are modified, free'd, or destroyed, the function's behavior
+ * is undefined.
+ *
+ */
+
+/* PKIX_PL_CollectionCertStore
+ *
+ * A PKIX_CollectionCertStore provides an example for showing how to retrieve
+ * certificates and CRLs from a repository, such as a directory in the system.
+ * It is expected the directory is an absolute directory which contains CRL
+ * and Cert data files. CRL files are expected to have the suffix of .crl
+ * and Cert files are expected to have the suffix of .crt .
+ *
+ * Once the caller has created the CollectionCertStoreContext object, the caller
+ * then can call pkix_pl_CollectionCertStore_GetCert or
+ * pkix_pl_CollectionCertStore_GetCRL to obtain Lists of PKIX_PL_Cert or
+ * PKIX_PL_CRL objects, respectively.
+ */
+
+/*
+ * FUNCTION: PKIX_PL_CollectionCertStore_Create
+ * DESCRIPTION:
+ *
+ * Creates a new CollectionCertStore and returns it at
+ * "pColCertStore".
+ *
+ * PARAMETERS:
+ * "storeDir"
+ * The absolute path where *.crl files are located.
+ * "pColCertStoreContext"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CollectionCertStoreContext Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_CollectionCertStore_Create(
+ PKIX_PL_String *storeDir,
+ PKIX_CertStore **pCertStore,
+ void *plContext);
+
+/* PKIX_PL_PK11CertStore
+ *
+ * A PKIX_PL_PK11CertStore retrieves certificates and CRLs from a PKCS11
+ * database. The directory that contains the cert8.db, key3.db, and secmod.db
+ * files that comprise a PKCS11 database are specified in NSS initialization.
+ *
+ * Once the caller has created the Pk11CertStore object, the caller can call
+ * pkix_pl_Pk11CertStore_GetCert or pkix_pl_Pk11CertStore_GetCert to obtain
+ * a List of PKIX_PL_Certs or PKIX_PL_CRL objects, respectively.
+ */
+
+/*
+ * FUNCTION: PKIX_PL_Pk11CertStore_Create
+ * DESCRIPTION:
+ *
+ * Creates a new Pk11CertStore and returns it at "pPk11CertStore".
+ *
+ * PARAMETERS:
+ * "pPk11CertStore"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_Pk11CertStore_Create(
+ PKIX_CertStore **pPk11CertStore,
+ void *plContext);
+
+#ifndef NSS_PKIX_NO_LDAP
+/* PKIX_PL_LdapCertStore
+ *
+ * A PKIX_PL_LdapCertStore retrieves certificates and CRLs from an LDAP server
+ * over a socket connection. It used the LDAP protocol as described in RFC1777.
+ *
+ * Once the caller has created the LdapCertStore object, the caller can call
+ * pkix_pl_LdapCertStore_GetCert or pkix_pl_LdapCertStore_GetCert to obtain
+ * a List of PKIX_PL_Certs or PKIX_PL_CRL objects, respectively.
+ */
+
+/*
+ * FUNCTION: PKIX_PL_LdapDefaultClient_Create
+ * DESCRIPTION:
+ *
+ * Creates an LdapDefaultClient using the PRNetAddr poined to by "sockaddr",
+ * with a timeout value of "timeout", and a BindAPI pointed to by "bindAPI";
+ * and stores the address of the default LdapClient at "pClient".
+ *
+ * At the time of this version, there are unresolved questions about the LDAP
+ * protocol. Although RFC1777 describes a BIND and UNBIND message, it is not
+ * clear whether they are appropriate to this application. We have tested only
+ * using servers that do not expect authentication, and that reject BIND
+ * messages. It is not clear what values might be appropriate for the bindname
+ * and authentication fields, which are currently implemented as char strings
+ * supplied by the caller. (If this changes, the API and possibly the templates
+ * will have to change.) Therefore the Client_Create API contains a BindAPI
+ * structure, a union, which will have to be revised and extended when this
+ * area of the protocol is better understood.
+ *
+ * PARAMETERS:
+ * "sockaddr"
+ * Address of the PRNetAddr to be used for the socket connection. Must be
+ * non-NULL.
+ * "timeout"
+ * The PRIntervalTime value to be used as a timeout value in socket calls;
+ * a zero value indicates non-blocking I/O is to be used.
+ * "bindAPI"
+ * The address of a BindAPI to be used if a BIND message is required. If
+ * this argument is NULL, no Bind (or Unbind) will be sent.
+ * "pClient"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_LdapDefaultClient_Create(
+ PRNetAddr *sockaddr,
+ PRIntervalTime timeout,
+ LDAPBindAPI *bindAPI,
+ PKIX_PL_LdapDefaultClient **pClient,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_LdapDefaultClient_CreateByName
+ * DESCRIPTION:
+ *
+ * Creates an LdapDefaultClient using the hostname poined to by "hostname",
+ * with a timeout value of "timeout", and a BindAPI pointed to by "bindAPI";
+ * and stores the address of the default LdapClient at "pClient".
+ *
+ * At the time of this version, there are unresolved questions about the LDAP
+ * protocol. Although RFC1777 describes a BIND and UNBIND message, it is not
+ * clear whether they are appropriate to this application. We have tested only
+ * using servers that do not expect authentication, and that reject BIND
+ * messages. It is not clear what values might be appropriate for the bindname
+ * and authentication fields, which are currently implemented as char strings
+ * supplied by the caller. (If this changes, the API and possibly the templates
+ * will have to change.) Therefore the Client_Create API contains a BindAPI
+ * structure, a union, which will have to be revised and extended when this
+ * area of the protocol is better understood.
+ *
+ * PARAMETERS:
+ * "hostname"
+ * Address of the hostname to be used for the socket connection. Must be
+ * non-NULL.
+ * "timeout"
+ * The PRIntervalTime value to be used as a timeout value in socket calls;
+ * a zero value indicates non-blocking I/O is to be used.
+ * "bindAPI"
+ * The address of a BindAPI to be used if a BIND message is required. If
+ * this argument is NULL, no Bind (or Unbind) will be sent.
+ * "pClient"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_LdapDefaultClient_CreateByName(
+ char *hostname,
+ PRIntervalTime timeout,
+ LDAPBindAPI *bindAPI,
+ PKIX_PL_LdapDefaultClient **pClient,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_LdapCertStore_Create
+ * DESCRIPTION:
+ *
+ * Creates a new LdapCertStore using the LdapClient pointed to by "client",
+ * and stores the address of the CertStore at "pCertStore".
+ *
+ * PARAMETERS:
+ * "client"
+ * Address of the LdapClient to be used. Must be non-NULL.
+ * "pCertStore"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_LdapCertStore_Create(
+ PKIX_PL_LdapClient *client,
+ PKIX_CertStore **pCertStore,
+ void *plContext);
+#endif /* !NSS_PKIX_NO_LDAP */
+
+/* PKIX_PL_NssContext
+ *
+ * A PKIX_PL_NssContext provides an example showing how the "plContext"
+ * argument, that is part of every libpkix function call, can be used.
+ * The "plContext" is the Portability Layer Context, which can be used
+ * to communicate layer-specific information from the application to the
+ * underlying Portability Layer (while bypassing the Portable Code, which
+ * blindly passes the plContext on to every function call).
+ *
+ * In this case, NSS serves as both the application and the Portability Layer.
+ * We define an NSS-specific structure, which includes an arena and a number
+ * of SECCertificateUsage bit flags encoded as a PKIX_UInt32. A third argument,
+ * wincx, is used on Windows platforms for PKCS11 access, and should be set to
+ * NULL for other platforms.
+ * Before calling any of the libpkix functions, the caller should create the NSS
+ * context, by calling PKIX_PL_NssContext_Create, and provide that NSS context
+ * as the "plContext" argument in every libpkix function call the caller makes.
+ * When the caller is finished using the NSS context (usually just after he
+ * calls PKIX_Shutdown), the caller should call PKIX_PL_NssContext_Destroy to
+ * free the NSS context structure.
+ */
+
+/*
+ * FUNCTION: PKIX_PL_NssContext_Create
+ * DESCRIPTION:
+ *
+ * Creates a new NssContext using the certificate usage(s) specified by
+ * "certUsage" and stores it at "pNssContext". This function also internally
+ * creates an arena and stores it as part of the NssContext structure. Unlike
+ * most other libpkix API functions, this function does not take a "plContext"
+ * parameter.
+ *
+ * PARAMETERS:
+ * "certUsage"
+ * The desired SECCertificateUsage(s).
+ * "useNssArena"
+ * Boolean flag indicates NSS Arena is used for memory allocation.
+ * "wincx"
+ * A Windows-dependent pointer for PKCS11 token handling.
+ * "pNssContext"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Context Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_NssContext_Create(
+ PKIX_UInt32 certificateUsage,
+ PKIX_Boolean useNssArena,
+ void *wincx,
+ void **pNssContext);
+
+/*
+ * FUNCTION: PKIX_PL_NssContext_Destroy
+ * DESCRIPTION:
+ *
+ * Frees the structure pointed to by "nssContext" along with any of its
+ * associated memory. Unlike most other libpkix API functions, this function
+ * does not take a "plContext" parameter.
+ *
+ * PARAMETERS:
+ * "nssContext"
+ * Address of NssContext to be destroyed. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Context Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_NssContext_Destroy(
+ void *nssContext);
+
+/*
+ * FUNCTION: PKIX_PL_NssContext_SetTimeout
+ * DESCRIPTION:
+ *
+ * Sets IO timeout for network operations like OCSP response and cert
+ * fetching.
+ *
+ * PARAMETERS:
+ * "nssContext"
+ * Address of NssContext to be destroyed. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Context Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_NssContext_SetTimeout(PKIX_UInt32 timeout, PKIX_PL_NssContext *nssContext);
+
+/*
+ * FUNCTION: PKIX_PL_NssContext_SetMaxResponseLen
+ * DESCRIPTION:
+ *
+ * Sets maximum responce length allowed during network IO operations.
+ *
+ * PARAMETERS:
+ * "nssContext"
+ * Address of NssContext to be destroyed. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Context Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_NssContext_SetMaxResponseLen(PKIX_UInt32 len, PKIX_PL_NssContext *nssContext);
+
+/*
+ * FUNCTION: PKIX_PL_NssContext_SetCrlReloadDelay
+ * DESCRIPTION:
+ *
+ * Sets user defined timeout between attempts to load crl using
+ * CRLDP.
+ *
+ * PARAMETERS:
+ * "delaySeconds"
+ * Reload delay in seconds.
+ * "nssContext"
+ * Address of NssContext to be destroyed. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Context Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_NssContext_SetCrlReloadDelay(PKIX_UInt32 delaySeconds,
+ PKIX_PL_NssContext *nssContext);
+
+/*
+ * FUNCTION: PKIX_PL_NssContext_SetBadDerCrlReloadDelay
+ * DESCRIPTION:
+ *
+ * Sets user defined timeout between attempts to load crls
+ * that failed to decode.
+ *
+ * PARAMETERS:
+ * "delaySeconds"
+ * Reload delay in seconds.
+ * "nssContext"
+ * Address of NssContext to be destroyed. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Context Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_NssContext_SetBadDerCrlReloadDelay(PKIX_UInt32 delaySeconds,
+ PKIX_PL_NssContext *nssContext);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_SAMPLEMODULES_H */
diff --git a/security/nss/lib/libpkix/include/pkix_util.h b/security/nss/lib/libpkix/include/pkix_util.h
new file mode 100644
index 0000000000..e42f608c17
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkix_util.h
@@ -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/. */
+/*
+ * These functions provide support for a number of other functions
+ * by creating and manipulating data structures used by those functions.
+ *
+ */
+
+#ifndef _PKIX_UTIL_H
+#define _PKIX_UTIL_H
+
+#include "pkixt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General
+ *
+ * Please refer to the libpkix Programmer's Guide for detailed information
+ * about how to use the libpkix library. Certain key warnings and notices from
+ * that document are repeated here for emphasis.
+ *
+ * All identifiers in this file (and all public identifiers defined in
+ * libpkix) begin with "PKIX_". Private identifiers only intended for use
+ * within the library begin with "pkix_".
+ *
+ * A function returns NULL upon success, and a PKIX_Error pointer upon failure.
+ *
+ * Unless otherwise noted, for all accessor (gettor) functions that return a
+ * PKIX_PL_Object pointer, callers should assume that this pointer refers to a
+ * shared object. Therefore, the caller should treat this shared object as
+ * read-only and should not modify this shared object. When done using the
+ * shared object, the caller should release the reference to the object by
+ * using the PKIX_PL_Object_DecRef function.
+ *
+ * While a function is executing, if its arguments (or anything referred to by
+ * its arguments) are modified, free'd, or destroyed, the function's behavior
+ * is undefined.
+ *
+ */
+
+/* PKIX_Logger
+ *
+ * PKIX_Loggers provide a standard way for the caller to insert custom logging
+ * facilities. These are used by libpkix to log errors, debug information,
+ * status, etc. The LogCallback allows custom logging to take place.
+ * Additionally, a Logger can be initialized with a loggerContext, which is
+ * where the caller can specify configuration data such as the name of a
+ * logfile or database. Note that this loggerContext must be a PKIX_PL_Object,
+ * allowing it to be reference-counted and allowing it to provide the standard
+ * PKIX_PL_Object functions (Equals, Hashcode, ToString, Compare, Duplicate).
+ *
+ * Once the caller has created the Logger object(s) (and set the loggerContext
+ * (if any) and the Log callback), the caller then registers these Loggers
+ * with the system by calling PKIX_SetLoggers or PKIX_AddLogger. All log
+ * entries will then be logged using the specified Loggers. If multiple
+ * Loggers are specified, every log entry will be logged with each of them.
+ *
+ * XXX Maybe give some guidance somewhere on how much detail each logging
+ * level should have and where component boundaries should be. Maybe in
+ * Implementor's Guide or Programmer's Guide.
+ */
+
+#define PKIX_LOGGER_LEVEL_TRACE 5
+#define PKIX_LOGGER_LEVEL_DEBUG 4
+#define PKIX_LOGGER_LEVEL_WARNING 3
+#define PKIX_LOGGER_LEVEL_ERROR 2
+#define PKIX_LOGGER_LEVEL_FATALERROR 1
+
+#define PKIX_LOGGER_LEVEL_MAX 5
+
+/*
+ * FUNCTION: PKIX_Logger_LogCallback
+ * DESCRIPTION:
+ *
+ * This callback function logs a log entry containing the String pointed to
+ * by "message", the integer value of logLevel, and the String pointed to by
+ * "logComponent". A log entry can be associated with a particular log
+ * level (i.e. level 3) and a particular log component (i.e. "CertStore").
+ * For example, someone reading the log may only be interested in very general
+ * log entries so they look only for log level 1. Similarly, they may only be
+ * interested in log entries pertaining to the CertStore component so they
+ * look only for that log component. This function can be used before calling
+ * PKIX_Initialize.
+ *
+ * PARAMETERS:
+ * "logger"
+ * Address of logger whose LogCallback is to be used. Must be non-NULL.
+ * "message"
+ * Address of String that is to be logged used "logger". Must be non-NULL.
+ * "logLevel"
+ * Integer value representing the log level for this entry. The higher the
+ * level, the more detail. Must be non-NULL.
+ * "logComponent"
+ * PKIXERRORNUM value (defined in pkixt.h) designating the log component
+ * for this entry.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads must be able to safely call this function without
+ * worrying about conflicts, even if they're operating on the same objects.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Logger Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+typedef PKIX_Error *
+(*PKIX_Logger_LogCallback)(
+ PKIX_Logger *logger,
+ PKIX_PL_String *message,
+ PKIX_UInt32 logLevel,
+ PKIX_ERRORCLASS logComponent,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_Logger_Create
+ * DESCRIPTION:
+ *
+ * Creates a new Logger using the Object pointed to by "loggerContext"
+ * (if any) and stores it at "pLogger". The new Logger uses the LogCallback
+ * pointed to by "callback". The Logger's maximum logging level is initially
+ * set to a very high level and its logging component is set to NULL (all
+ * components).
+ *
+ * PARAMETERS:
+ * "callback"
+ * The LogCallback function to be used. Must be non-NULL.
+ * "loggerContext"
+ * Address of Object representing the Logger's context (if any).
+ * "pLogger"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Logger Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Logger_Create(
+ PKIX_Logger_LogCallback callback,
+ PKIX_PL_Object *loggerContext,
+ PKIX_Logger **pLogger,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_Logger_GetLogCallback
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to "logger's" Log callback function and puts it in
+ * "pCallback".
+ *
+ * PARAMETERS:
+ * "logger"
+ * Address of Logger whose Log callback is desired. Must be non-NULL.
+ * "pCallback"
+ * Address where Log callback function pointer will be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Logger Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Logger_GetLogCallback(
+ PKIX_Logger *logger,
+ PKIX_Logger_LogCallback *pCallback,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_Logger_GetLoggerContext
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a PKIX_PL_Object representing the context (if any)
+ * of the Logger pointed to by "logger" and stores it at "pLoggerContext".
+ *
+ * PARAMETERS:
+ * "logger"
+ * Address of Logger whose context is to be stored. Must be non-NULL.
+ * "pLoggerContext"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Logger Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Logger_GetLoggerContext(
+ PKIX_Logger *logger,
+ PKIX_PL_Object **pLoggerContext,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_Logger_GetMaxLoggingLevel
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a PKIX_UInt32 representing the maximum logging
+ * level of the Logger pointed to by "logger" and stores it at "pLevel". Only
+ * log entries whose log level is less than or equal to this maximum logging
+ * level will be logged.
+ *
+ * PARAMETERS:
+ * "logger"
+ * Address of Logger whose maximum logging level is to be stored.
+ * Must be non-NULL.
+ * "pLevel"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Logger Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Logger_GetMaxLoggingLevel(
+ PKIX_Logger *logger,
+ PKIX_UInt32 *pLevel,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_Logger_SetMaxLoggingLevel
+ * DESCRIPTION:
+ *
+ * Sets the maximum logging level of the Logger pointed to by "logger" with
+ * the integer value of "level".
+ *
+ * PARAMETERS:
+ * "logger"
+ * Address of Logger whose maximum logging level is to be set.
+ * Must be non-NULL.
+ * "level"
+ * Maximum logging level to be set
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "logger"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Logger Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Logger_SetMaxLoggingLevel(
+ PKIX_Logger *logger,
+ PKIX_UInt32 level,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_Logger_GetLoggingComponent
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to a String representing the logging component of the
+ * Logger pointed to by "logger" and stores it at "pComponent". Only log
+ * entries whose log component matches the specified logging component will
+ * be logged.
+ *
+ * PARAMETERS:
+ * "logger"
+ * Address of Logger whose logging component is to be stored.
+ * Must be non-NULL.
+ * "pComponent"
+ * Address where PKIXERRORNUM will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Logger Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Logger_GetLoggingComponent(
+ PKIX_Logger *logger,
+ PKIX_ERRORCLASS *pComponent,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_Logger_SetLoggingComponent
+ * DESCRIPTION:
+ *
+ * Sets the logging component of the Logger pointed to by "logger" with the
+ * PKIXERRORNUM pointed to by "component". To match a small set of components,
+ * create a Logger for each.
+ *
+ * PARAMETERS:
+ * "logger"
+ * Address of Logger whose logging component is to be set.
+ * Must be non-NULL.
+ * "component"
+ * PKIXERRORNUM value representing logging component to be set.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "logger"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Logger Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Logger_SetLoggingComponent(
+ PKIX_Logger *logger,
+ PKIX_ERRORCLASS component,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_GetLoggers
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of Loggers (if any) being used for logging
+ * by libpkix and stores it at "pLoggers". If no loggers are being used, this
+ * function stores an empty List at "pLoggers".
+ *
+ * Note that the List returned by this function is immutable.
+ *
+ * PARAMETERS:
+ * "pLoggers"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Logger Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_GetLoggers(
+ PKIX_List **pLoggers, /* list of PKIX_Logger */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_SetLoggers
+ * DESCRIPTION:
+ *
+ * Sets the Loggers to be used by libpkix to the List of Loggers pointed to
+ * by "loggers". If "loggers" is NULL, no Loggers will be used.
+ *
+ * PARAMETERS:
+ * "loggers"
+ * Address of List of Loggers to be set. NULL for no Loggers.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Logger Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_SetLoggers(
+ PKIX_List *loggers, /* list of PKIX_Logger */
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_AddLogger
+ * DESCRIPTION:
+ *
+ * Adds the Logger pointed to by "logger" to the List of Loggers used by
+ * libpkix.
+ *
+ * PARAMETERS:
+ * "logger"
+ * Address of Logger to be added. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Logger Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_AddLogger(
+ PKIX_Logger *logger,
+ void *plContext);
+
+/* Functions pertaining to the PKIX_Error type */
+
+/* Error
+ *
+ * An Error object is returned by a function upon encountering some error
+ * condition. Each Error is associated with an errorCode specified in pkixt.h.
+ * The remaining components of an Error are optional. An Error's description
+ * specifies a text message describing the Error. An Error's supplementary info
+ * specifies additional information that might be useful. Finally, an Error's
+ * cause specifies the underlying Error (if any) that resulted in this Error
+ * being returned, thereby allowing Errors to be chained so that an entire
+ * "error stack trace" can be represented. Once created, an Error is immutable.
+ *
+ * Note that the Error's supplementary info must be an Object (although any
+ * object type), allowing it to be reference-counted and allowing it to
+ * provide the standard Object functions (Equals, Hashcode, ToString, Compare,
+ * Duplicate).
+ *
+ * Errors are classified as either being fatal or non-fatal. If a function
+ * fails in an unrecoverable way, it returns an Error whose errorCode is
+ * PKIX_FATAL_ERROR. If such an error is encountered, the caller should
+ * not attempt to recover since something seriously wrong has happened
+ * (e.g. corrupted memory, memory finished, etc.). All other errorCodes
+ * are considered non-fatal errors and can be handled by the caller as they
+ * see fit.
+ */
+
+/*
+ * FUNCTION: PKIX_Error_Create
+ * DESCRIPTION:
+ *
+ * Creates a new Error using the value of "errorCode", the Error pointed to by
+ * "cause" (if any), the Object pointed to by "info" (if any), and the String
+ * pointed to by "desc" and stores it at "pError". If any error occurs during
+ * error allocation, it will be returned without chaining, since new errors
+ * cannot be created. Once created, an Error is immutable.
+ *
+ * PARAMETERS:
+ * "errorCode"
+ * Value of error code.
+ * "cause"
+ * Address of Error representing error's cause.
+ * NULL if none or unspecified.
+ * "info"
+ * Address of Object representing error's supplementary information.
+ * NULL if none.
+ * "desc"
+ * Address of String representing error's description. NULL if none.
+ * "pError"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Error_Create(
+ PKIX_ERRORCLASS errClass,
+ PKIX_Error *cause,
+ PKIX_PL_Object *info,
+ PKIX_ERRORCODE errCode,
+ PKIX_Error **pError,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_Error_GetErrorClass
+ * DESCRIPTION:
+ *
+ * Retrieves the error class of the Error pointed to by "error" and
+ * stores it at "pClass". Supported error codes are defined in pkixt.h.
+ *
+ * PARAMETERS:
+ * "error"
+ * Address of Error whose error code is desired. Must be non-NULL.
+ * "pClass"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Error_GetErrorClass(
+ PKIX_Error *error,
+ PKIX_ERRORCLASS *pClass,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_Error_GetErrorCode
+ * DESCRIPTION:
+ *
+ * Retrieves the error code of the Error pointed to by "error" and
+ * stores it at "pCode". Supported error codes are defined in pkixt.h.
+ *
+ * PARAMETERS:
+ * "error"
+ * Address of Error whose error code is desired. Must be non-NULL.
+ * "pCode"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Error_GetErrorCode(
+ PKIX_Error *error,
+ PKIX_ERRORCODE *pCode,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_Error_GetCause
+ * DESCRIPTION:
+ *
+ * Retrieves the cause of the Error pointed to by "error" and stores it at
+ * "pCause". If no cause was specified, NULL will be stored at "pCause".
+ *
+ * PARAMETERS:
+ * "error"
+ * Address of Error whose cause is desired. Must be non-NULL.
+ * "pCause"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Error_GetCause(
+ PKIX_Error *error,
+ PKIX_Error **pCause,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_Error_GetSupplementaryInfo
+ * DESCRIPTION:
+ *
+ * Retrieves the supplementary info of the Error pointed to by "error" and
+ * stores it at "pInfo".
+ *
+ * PARAMETERS:
+ * "error"
+ * Address of Error whose info is desired. Must be non-NULL.
+ * "pInfo"
+ * Address where info pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Error_GetSupplementaryInfo(
+ PKIX_Error *error,
+ PKIX_PL_Object **pInfo,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_Error_GetDescription
+ * DESCRIPTION:
+ *
+ * Retrieves the description of the Error pointed to by "error" and stores it
+ * at "pDesc". If no description was specified, NULL will be stored at
+ * "pDesc".
+ *
+ * PARAMETERS:
+ * "error"
+ * Address of Error whose description is desired. Must be non-NULL.
+ * "pDesc"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_Error_GetDescription(
+ PKIX_Error *error,
+ PKIX_PL_String **pDesc,
+ void *plContext);
+
+/* PKIX_List
+ *
+ * Represents a collection of items. NULL is considered a valid item.
+ */
+
+/*
+ * FUNCTION: PKIX_List_Create
+ * DESCRIPTION:
+ *
+ * Creates a new List and stores it at "pList". The List is initially empty
+ * and holds no items. To initially add items to the List, use
+ * PKIX_List_AppendItem
+ *
+ * PARAMETERS:
+ * "pList"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_List_Create(
+ PKIX_List **pList,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_List_SetImmutable
+ * DESCRIPTION:
+ *
+ * Sets the List pointed to by "list" to be immutable. If a caller tries to
+ * change a List after it has been marked immutable (i.e. by calling
+ * PKIX_List_AppendItem, PKIX_List_InsertItem, PKIX_List_SetItem, or
+ * PKIX_List_DeleteItem), an Error is returned.
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List to be marked immutable. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "list"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_List_SetImmutable(
+ PKIX_List *list,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_List_IsImmutable
+ * DESCRIPTION:
+ *
+ * Checks whether the List pointed to by "list" is immutable and stores
+ * the Boolean result at "pImmutable". If a caller tries to change a List
+ * after it has been marked immutable (i.e. by calling PKIX_List_AppendItem,
+ * PKIX_List_InsertItem, PKIX_List_SetItem, or PKIX_List_DeleteItem), an
+ * Error is returned.
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List whose immutability is to be determined.
+ * Must be non-NULL.
+ * "pImmutable"
+ * Address where PKIX_Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_List_IsImmutable(
+ PKIX_List *list,
+ PKIX_Boolean *pImmutable,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_List_GetLength
+ * DESCRIPTION:
+ *
+ * Retrieves the length of the List pointed to by "list" and stores it at
+ * "pLength".
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List whose length is desired. Must be non-NULL.
+ * "pLength"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_List_GetLength(
+ PKIX_List *list,
+ PKIX_UInt32 *pLength,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_List_IsEmpty
+ * DESCRIPTION:
+ *
+ * Checks whether the List pointed to by "list" is empty and stores
+ * the Boolean result at "pEmpty".
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List whose emptiness is to be determined. Must be non-NULL.
+ * "pEmpty"
+ * Address where PKIX_Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_List_IsEmpty(
+ PKIX_List *list,
+ PKIX_Boolean *pEmpty,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_List_AppendItem
+ * DESCRIPTION:
+ *
+ * Appends the Object pointed to by "item" after the last non-NULL item in
+ * List pointed to by "list", if any. Note that a List may validly contain
+ * NULL items. Appending "c" into the List ("a", NULL, "b", NULL) will result
+ * in ("a", NULL, "b", "c").
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List to append to. Must be non-NULL.
+ * "item"
+ * Address of new item to append.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "list"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_List_AppendItem(
+ PKIX_List *list,
+ PKIX_PL_Object *item,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_List_InsertItem
+ * DESCRIPTION:
+ *
+ * Inserts the Object pointed to by "item" into the List pointed to by "list"
+ * at the given "index". The index counts from zero and must be less than the
+ * List's length. Existing list entries at or after this index will be moved
+ * to the next highest index.
+ *
+ * XXX why not allow equal to length which would be equivalent to AppendItem?
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List to insert into. Must be non-NULL.
+ * "index"
+ * Position to insert into. Must be less than List's length.
+ * "item"
+ * Address of new item to append.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "list"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_List_InsertItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_PL_Object *item,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_List_GetItem
+ * DESCRIPTION:
+ *
+ * Copies the "list"'s item at "index" into "pItem". The index counts from
+ * zero and must be less than the list's length. Increments the reference
+ * count on the returned object, if non-NULL.
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List to get item from. Must be non-NULL.
+ * "index"
+ * Index of list to get item from. Must be less than List's length.
+ * "pItem"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_List_GetItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_PL_Object **pItem,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_List_SetItem
+ * DESCRIPTION:
+ *
+ * Sets the item at "index" of the List pointed to by "list" with the Object
+ * pointed to by "item". The index counts from zero and must be less than the
+ * List's length. The previous entry at this index will have its reference
+ * count decremented and the new entry will have its reference count
+ * incremented.
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List to modify. Must be non-NULL.
+ * "index"
+ * Position in List to set. Must be less than List's length.
+ * "item"
+ * Address of Object to set at "index".
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "list"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_List_SetItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_PL_Object *item,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_List_DeleteItem
+ *
+ * Deletes the item at "index" from the List pointed to by "list". The index
+ * counts from zero and must be less than the List's length. Note that this
+ * function does not destroy the List. It simply decrements the reference
+ * count of the item at "index" in the List, deletes that item from the list
+ * and moves all subsequent entries to a lower index in the list. If there is
+ * only a single element in the List and that element is deleted, then the
+ * List will be empty.
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List to delete from. Must be non-NULL.
+ * "index"
+ * Position in List to delete. Must be less than List's length.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "list"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_List_DeleteItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_List_ReverseList
+ * DESCRIPTION:
+ *
+ * Creates a new List whose elements are in the reverse order as the elements
+ * of the Object pointed to by "list" and stores the copy at "pReversedList".
+ * If "list" is empty, the new reversed List will be a copy of "list".
+ * Changes to the new object will not affect the original and vice versa.
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List whose elements are to be reversed. Must be non-NULL.
+ * "pReversedList"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_List_ReverseList(
+ PKIX_List *list,
+ PKIX_List **pReversedList,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_UTIL_H */
diff --git a/security/nss/lib/libpkix/include/pkixt.h b/security/nss/lib/libpkix/include/pkixt.h
new file mode 100644
index 0000000000..71997f700b
--- /dev/null
+++ b/security/nss/lib/libpkix/include/pkixt.h
@@ -0,0 +1,485 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 file defines the types in the libpkix API.
+ * XXX Maybe we should specify the API version number in all API header files
+ *
+ */
+
+#ifndef _PKIXT_H
+#define _PKIXT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "secerr.h"
+
+/* Types
+ *
+ * This header file provides typedefs for the abstract types used by libpkix.
+ * It also provides several useful macros.
+ *
+ * Note that all these abstract types are typedef'd as opaque structures. This
+ * is intended to discourage the caller from looking at the contents directly,
+ * since the format of the contents may change from one version of the library
+ * to the next. Instead, callers should only access these types using the
+ * functions defined in the public header files.
+ *
+ * An instance of an abstract type defined in this file is called an "object"
+ * here, although C does not have real support for objects.
+ *
+ * Because C does not typically have automatic garbage collection, the caller
+ * is expected to release the reference to any object that they create or that
+ * is returned to them by a libpkix function. The caller should do this by
+ * using the PKIX_PL_Object_DecRef function. Note that the caller should not
+ * release the reference to an object if the object has been passed to a
+ * libpkix function and that function has not returned.
+ *
+ * Please refer to libpkix Programmer's Guide for more details.
+ */
+
+/* Version
+ *
+ * These macros specify the major and minor version of the libpkix API defined
+ * by this header file.
+ */
+
+#define PKIX_MAJOR_VERSION ((PKIX_UInt32) 0)
+#define PKIX_MINOR_VERSION ((PKIX_UInt32) 3)
+
+/* Maximum minor version
+ *
+ * This macro is used to specify that the caller wants the largest minor
+ * version available.
+ */
+
+#define PKIX_MAX_MINOR_VERSION ((PKIX_UInt32) 4000000000)
+
+/* Define Cert Store type for database access */
+#define PKIX_STORE_TYPE_NONE 0
+#define PKIX_STORE_TYPE_PK11 1
+
+/* Portable Code (PC) data types
+ *
+ * These types are used to perform the primary operations of this library:
+ * building and validating chains of X.509 certificates.
+ */
+
+typedef struct PKIX_ErrorStruct PKIX_Error;
+typedef struct PKIX_ProcessingParamsStruct PKIX_ProcessingParams;
+typedef struct PKIX_ValidateParamsStruct PKIX_ValidateParams;
+typedef struct PKIX_ValidateResultStruct PKIX_ValidateResult;
+typedef struct PKIX_ResourceLimitsStruct PKIX_ResourceLimits;
+typedef struct PKIX_BuildResultStruct PKIX_BuildResult;
+typedef struct PKIX_CertStoreStruct PKIX_CertStore;
+typedef struct PKIX_CertChainCheckerStruct PKIX_CertChainChecker;
+typedef struct PKIX_RevocationCheckerStruct PKIX_RevocationChecker;
+typedef struct PKIX_CertSelectorStruct PKIX_CertSelector;
+typedef struct PKIX_CRLSelectorStruct PKIX_CRLSelector;
+typedef struct PKIX_ComCertSelParamsStruct PKIX_ComCertSelParams;
+typedef struct PKIX_ComCRLSelParamsStruct PKIX_ComCRLSelParams;
+typedef struct PKIX_TrustAnchorStruct PKIX_TrustAnchor;
+typedef struct PKIX_PolicyNodeStruct PKIX_PolicyNode;
+typedef struct PKIX_LoggerStruct PKIX_Logger;
+typedef struct PKIX_ListStruct PKIX_List;
+typedef struct PKIX_ForwardBuilderStateStruct PKIX_ForwardBuilderState;
+typedef struct PKIX_DefaultRevocationCheckerStruct
+ PKIX_DefaultRevocationChecker;
+typedef struct PKIX_VerifyNodeStruct PKIX_VerifyNode;
+
+/* Portability Layer (PL) data types
+ *
+ * These types are used are used as portable data types that are defined
+ * consistently across platforms
+ */
+
+typedef struct PKIX_PL_NssContextStruct PKIX_PL_NssContext;
+typedef struct PKIX_PL_ObjectStruct PKIX_PL_Object;
+typedef struct PKIX_PL_ByteArrayStruct PKIX_PL_ByteArray;
+typedef struct PKIX_PL_HashTableStruct PKIX_PL_HashTable;
+typedef struct PKIX_PL_MutexStruct PKIX_PL_Mutex;
+typedef struct PKIX_PL_RWLockStruct PKIX_PL_RWLock;
+typedef struct PKIX_PL_MonitorLockStruct PKIX_PL_MonitorLock;
+typedef struct PKIX_PL_BigIntStruct PKIX_PL_BigInt;
+typedef struct PKIX_PL_StringStruct PKIX_PL_String;
+typedef struct PKIX_PL_OIDStruct PKIX_PL_OID;
+typedef struct PKIX_PL_CertStruct PKIX_PL_Cert;
+typedef struct PKIX_PL_GeneralNameStruct PKIX_PL_GeneralName;
+typedef struct PKIX_PL_X500NameStruct PKIX_PL_X500Name;
+typedef struct PKIX_PL_PublicKeyStruct PKIX_PL_PublicKey;
+typedef struct PKIX_PL_DateStruct PKIX_PL_Date;
+typedef struct PKIX_PL_CertNameConstraintsStruct PKIX_PL_CertNameConstraints;
+typedef struct PKIX_PL_CertBasicConstraintsStruct PKIX_PL_CertBasicConstraints;
+typedef struct PKIX_PL_CertPoliciesStruct PKIX_PL_CertPolicies;
+typedef struct PKIX_PL_CertPolicyInfoStruct PKIX_PL_CertPolicyInfo;
+typedef struct PKIX_PL_CertPolicyQualifierStruct PKIX_PL_CertPolicyQualifier;
+typedef struct PKIX_PL_CertPolicyMapStruct PKIX_PL_CertPolicyMap;
+typedef struct PKIX_PL_CRLStruct PKIX_PL_CRL;
+typedef struct PKIX_PL_CRLEntryStruct PKIX_PL_CRLEntry;
+typedef struct PKIX_PL_CollectionCertStoreStruct PKIX_PL_CollectionCertStore;
+typedef struct PKIX_PL_CollectionCertStoreContext
+ PKIX_PL_CollectionCertStoreContext;
+typedef struct PKIX_PL_LdapCertStoreContext PKIX_PL_LdapCertStoreContext;
+typedef struct PKIX_PL_LdapRequestStruct PKIX_PL_LdapRequest;
+typedef struct PKIX_PL_LdapResponseStruct PKIX_PL_LdapResponse;
+typedef struct PKIX_PL_LdapDefaultClientStruct PKIX_PL_LdapDefaultClient;
+typedef struct PKIX_PL_SocketStruct PKIX_PL_Socket;
+typedef struct PKIX_PL_InfoAccessStruct PKIX_PL_InfoAccess;
+typedef struct PKIX_PL_AIAMgrStruct PKIX_PL_AIAMgr;
+typedef struct PKIX_PL_OcspCertIDStruct PKIX_PL_OcspCertID;
+typedef struct PKIX_PL_OcspRequestStruct PKIX_PL_OcspRequest;
+typedef struct PKIX_PL_OcspResponseStruct PKIX_PL_OcspResponse;
+typedef struct PKIX_PL_HttpClientStruct PKIX_PL_HttpClient;
+typedef struct PKIX_PL_HttpDefaultClientStruct PKIX_PL_HttpDefaultClient;
+typedef struct PKIX_PL_HttpCertStoreContextStruct PKIX_PL_HttpCertStoreContext;
+
+/* Primitive types
+ *
+ * In order to guarantee desired behavior as well as platform-independence, we
+ * typedef these types depending on the platform. XXX This needs more work!
+ */
+
+/* XXX Try compiling these files (and maybe the whole libpkix-nss) on Win32.
+ * We don't know what type is at least 32 bits long. ISO C probably requires
+ * at least 32 bits for long. we could default to that and only list platforms
+ * where that's not true.
+ *
+ * #elif
+ * #error
+ * #endif
+ */
+
+/* currently, int is 32 bits on all our supported platforms */
+
+typedef unsigned int PKIX_UInt32;
+typedef int PKIX_Int32;
+
+typedef int PKIX_Boolean;
+
+/* Object Types
+ *
+ * Every reference-counted PKIX_PL_Object is associated with an integer type.
+ */
+#define PKIX_TYPES \
+ TYPEMACRO(AIAMGR), \
+ TYPEMACRO(BASICCONSTRAINTSCHECKERSTATE), \
+ TYPEMACRO(BIGINT), \
+ TYPEMACRO(BUILDRESULT), \
+ TYPEMACRO(BYTEARRAY), \
+ TYPEMACRO(CERT), \
+ TYPEMACRO(CERTBASICCONSTRAINTS), \
+ TYPEMACRO(CERTCHAINCHECKER), \
+ TYPEMACRO(CERTNAMECONSTRAINTS), \
+ TYPEMACRO(CERTNAMECONSTRAINTSCHECKERSTATE), \
+ TYPEMACRO(CERTPOLICYCHECKERSTATE), \
+ TYPEMACRO(CERTPOLICYINFO), \
+ TYPEMACRO(CERTPOLICYMAP), \
+ TYPEMACRO(CERTPOLICYNODE), \
+ TYPEMACRO(CERTPOLICYQUALIFIER), \
+ TYPEMACRO(CERTSELECTOR), \
+ TYPEMACRO(CERTSTORE), \
+ TYPEMACRO(COLLECTIONCERTSTORECONTEXT), \
+ TYPEMACRO(COMCERTSELPARAMS), \
+ TYPEMACRO(COMCRLSELPARAMS), \
+ TYPEMACRO(CRL), \
+ TYPEMACRO(CRLDP), \
+ TYPEMACRO(CRLENTRY), \
+ TYPEMACRO(CRLSELECTOR), \
+ TYPEMACRO(DATE), \
+ TYPEMACRO(CRLCHECKER), \
+ TYPEMACRO(EKUCHECKER), \
+ TYPEMACRO(ERROR), \
+ TYPEMACRO(FORWARDBUILDERSTATE), \
+ TYPEMACRO(GENERALNAME), \
+ TYPEMACRO(HASHTABLE), \
+ TYPEMACRO(HTTPCERTSTORECONTEXT), \
+ TYPEMACRO(HTTPDEFAULTCLIENT), \
+ TYPEMACRO(INFOACCESS), \
+ TYPEMACRO(LDAPDEFAULTCLIENT), \
+ TYPEMACRO(LDAPREQUEST), \
+ TYPEMACRO(LDAPRESPONSE), \
+ TYPEMACRO(LIST), \
+ TYPEMACRO(LOGGER), \
+ TYPEMACRO(MONITORLOCK), \
+ TYPEMACRO(MUTEX), \
+ TYPEMACRO(OBJECT), \
+ TYPEMACRO(OCSPCERTID), \
+ TYPEMACRO(OCSPCHECKER), \
+ TYPEMACRO(OCSPREQUEST), \
+ TYPEMACRO(OCSPRESPONSE), \
+ TYPEMACRO(OID), \
+ TYPEMACRO(REVOCATIONCHECKER), \
+ TYPEMACRO(PROCESSINGPARAMS), \
+ TYPEMACRO(PUBLICKEY), \
+ TYPEMACRO(RESOURCELIMITS), \
+ TYPEMACRO(RWLOCK), \
+ TYPEMACRO(SIGNATURECHECKERSTATE), \
+ TYPEMACRO(SOCKET), \
+ TYPEMACRO(STRING), \
+ TYPEMACRO(TARGETCERTCHECKERSTATE), \
+ TYPEMACRO(TRUSTANCHOR), \
+ TYPEMACRO(VALIDATEPARAMS), \
+ TYPEMACRO(VALIDATERESULT), \
+ TYPEMACRO(VERIFYNODE), \
+ TYPEMACRO(X500NAME)
+
+#define TYPEMACRO(type) PKIX_ ## type ## _TYPE
+
+typedef enum { /* Now invoke all those TYPEMACROs to assign the numbers */
+ PKIX_TYPES,
+ PKIX_NUMTYPES /* This gets PKIX_NUMTYPES defined as the total number */
+} PKIX_TYPENUM;
+
+
+#ifdef PKIX_USER_OBJECT_TYPE
+
+/* User Define Object Types
+ *
+ * User may define their own object types offset from PKIX_USER_OBJECT_TYPE
+ */
+#define PKIX_USER_OBJECT_TYPEBASE 1000
+
+#endif /* PKIX_USER_OBJECT_TYPE */
+
+/* Error Codes
+ *
+ * This list is used to define a set of PKIX_Error exception class numbers.
+ * ERRMACRO is redefined to produce a corresponding set of
+ * strings in the table "const char *PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES]" in
+ * pkix_error.c. For example, since the fifth ERRMACRO entry is MUTEX, then
+ * PKIX_MUTEX_ERROR is defined in pkixt.h as 4, and PKIX_ERRORCLASSNAMES[4] is
+ * initialized in pkix_error.c with the value "MUTEX".
+ */
+#define PKIX_ERRORCLASSES \
+ ERRMACRO(AIAMGR), \
+ ERRMACRO(BASICCONSTRAINTSCHECKERSTATE), \
+ ERRMACRO(BIGINT), \
+ ERRMACRO(BUILD), \
+ ERRMACRO(BUILDRESULT), \
+ ERRMACRO(BYTEARRAY), \
+ ERRMACRO(CERT), \
+ ERRMACRO(CERTBASICCONSTRAINTS), \
+ ERRMACRO(CERTCHAINCHECKER), \
+ ERRMACRO(CERTNAMECONSTRAINTS), \
+ ERRMACRO(CERTNAMECONSTRAINTSCHECKERSTATE), \
+ ERRMACRO(CERTPOLICYCHECKERSTATE), \
+ ERRMACRO(CERTPOLICYINFO), \
+ ERRMACRO(CERTPOLICYMAP), \
+ ERRMACRO(CERTPOLICYNODE), \
+ ERRMACRO(CERTPOLICYQUALIFIER), \
+ ERRMACRO(CERTSELECTOR), \
+ ERRMACRO(CERTSTORE), \
+ ERRMACRO(CERTVFYPKIX), \
+ ERRMACRO(COLLECTIONCERTSTORECONTEXT), \
+ ERRMACRO(COMCERTSELPARAMS), \
+ ERRMACRO(COMCRLSELPARAMS), \
+ ERRMACRO(CONTEXT), \
+ ERRMACRO(CRL), \
+ ERRMACRO(CRLDP), \
+ ERRMACRO(CRLENTRY), \
+ ERRMACRO(CRLSELECTOR), \
+ ERRMACRO(CRLCHECKER), \
+ ERRMACRO(DATE), \
+ ERRMACRO(EKUCHECKER), \
+ ERRMACRO(ERROR), \
+ ERRMACRO(FATAL), \
+ ERRMACRO(FORWARDBUILDERSTATE), \
+ ERRMACRO(GENERALNAME), \
+ ERRMACRO(HASHTABLE), \
+ ERRMACRO(HTTPCERTSTORECONTEXT), \
+ ERRMACRO(HTTPDEFAULTCLIENT), \
+ ERRMACRO(INFOACCESS), \
+ ERRMACRO(LDAPCLIENT), \
+ ERRMACRO(LDAPDEFAULTCLIENT), \
+ ERRMACRO(LDAPREQUEST), \
+ ERRMACRO(LDAPRESPONSE), \
+ ERRMACRO(LIFECYCLE), \
+ ERRMACRO(LIST), \
+ ERRMACRO(LOGGER), \
+ ERRMACRO(MEM), \
+ ERRMACRO(MONITORLOCK), \
+ ERRMACRO(MUTEX), \
+ ERRMACRO(OBJECT), \
+ ERRMACRO(OCSPCERTID), \
+ ERRMACRO(OCSPCHECKER), \
+ ERRMACRO(OCSPREQUEST), \
+ ERRMACRO(OCSPRESPONSE), \
+ ERRMACRO(OID), \
+ ERRMACRO(PROCESSINGPARAMS), \
+ ERRMACRO(PUBLICKEY), \
+ ERRMACRO(RESOURCELIMITS), \
+ ERRMACRO(REVOCATIONMETHOD), \
+ ERRMACRO(REVOCATIONCHECKER), \
+ ERRMACRO(RWLOCK), \
+ ERRMACRO(SIGNATURECHECKERSTATE), \
+ ERRMACRO(SOCKET), \
+ ERRMACRO(STRING), \
+ ERRMACRO(TARGETCERTCHECKERSTATE), \
+ ERRMACRO(TRUSTANCHOR), \
+ ERRMACRO(USERDEFINEDMODULES), \
+ ERRMACRO(VALIDATE), \
+ ERRMACRO(VALIDATEPARAMS), \
+ ERRMACRO(VALIDATERESULT), \
+ ERRMACRO(VERIFYNODE), \
+ ERRMACRO(X500NAME)
+
+#define ERRMACRO(type) PKIX_ ## type ## _ERROR
+
+typedef enum { /* Now invoke all those ERRMACROs to assign the numbers */
+ PKIX_ERRORCLASSES,
+ PKIX_NUMERRORCLASSES /* This gets PKIX_NUMERRORCLASSES defined as the total number */
+} PKIX_ERRORCLASS;
+
+/* Now define error strings (for internationalization) */
+
+#define PKIX_ERRORENTRY(name,desc,plerr) PKIX_ ## name
+
+/* Define all the error numbers */
+typedef enum {
+#include "pkix_errorstrings.h"
+, PKIX_NUMERRORCODES
+} PKIX_ERRORCODE;
+
+extern const char * const PKIX_ErrorText[];
+
+/* String Formats
+ *
+ * These formats specify supported encoding formats for Strings.
+ */
+
+#define PKIX_ESCASCII 0
+#define PKIX_UTF8 1
+#define PKIX_UTF16 2
+#define PKIX_UTF8_NULL_TERM 3
+#define PKIX_ESCASCII_DEBUG 4
+
+/* Name Types
+ *
+ * These types specify supported formats for GeneralNames.
+ */
+
+#define PKIX_OTHER_NAME 1
+#define PKIX_RFC822_NAME 2
+#define PKIX_DNS_NAME 3
+#define PKIX_X400_ADDRESS 4
+#define PKIX_DIRECTORY_NAME 5
+#define PKIX_EDIPARTY_NAME 6
+#define PKIX_URI_NAME 7
+#define PKIX_IP_NAME 8
+#define PKIX_OID_NAME 9
+
+/* Key Usages
+ *
+ * These types specify supported Key Usages
+ */
+
+#define PKIX_DIGITAL_SIGNATURE 0x001
+#define PKIX_NON_REPUDIATION 0x002
+#define PKIX_KEY_ENCIPHERMENT 0x004
+#define PKIX_DATA_ENCIPHERMENT 0x008
+#define PKIX_KEY_AGREEMENT 0x010
+#define PKIX_KEY_CERT_SIGN 0x020
+#define PKIX_CRL_SIGN 0x040
+#define PKIX_ENCIPHER_ONLY 0x080
+#define PKIX_DECIPHER_ONLY 0x100
+
+/* Reason Flags
+ *
+ * These macros specify supported Reason Flags
+ */
+
+#define PKIX_UNUSED 0x001
+#define PKIX_KEY_COMPROMISE 0x002
+#define PKIX_CA_COMPROMISE 0x004
+#define PKIX_AFFILIATION_CHANGED 0x008
+#define PKIX_SUPERSEDED 0x010
+#define PKIX_CESSATION_OF_OPERATION 0x020
+#define PKIX_CERTIFICATE_HOLD 0x040
+#define PKIX_PRIVILEGE_WITHDRAWN 0x080
+#define PKIX_AA_COMPROMISE 0x100
+
+/* Boolean values
+ *
+ * These macros specify the Boolean values of TRUE and FALSE
+ * XXX Is it the case that any non-zero value is actually considered TRUE
+ * and this is just a convenient mnemonic macro?
+ */
+
+#define PKIX_TRUE ((PKIX_Boolean) 1)
+#define PKIX_FALSE ((PKIX_Boolean) 0)
+
+/*
+ * Define constants for basic constraints selector
+ * (see comments in pkix_certsel.h)
+ */
+
+#define PKIX_CERTSEL_ENDENTITY_MIN_PATHLENGTH (-2)
+#define PKIX_CERTSEL_ALL_MATCH_MIN_PATHLENGTH (-1)
+
+/*
+ * PKIX_ALLOC_ERROR is a special error object hard-coded into the pkix_error.o
+ * object file. It is thrown if system memory cannot be allocated or may be
+ * thrown for other unrecoverable errors. PKIX_ALLOC_ERROR is immutable.
+ * IncRef, DecRef and all Settor functions cannot be called.
+ * XXX Does anyone actually need to know about this?
+ * XXX Why no DecRef? Would be good to handle it the same.
+ */
+
+PKIX_Error* PKIX_ALLOC_ERROR(void);
+
+/*
+ * In a CertBasicConstraints extension, if the CA flag is set,
+ * indicating the certificate refers to a Certification
+ * Authority, then the pathLen field indicates how many intermediate
+ * certificates (not counting self-signed ones) can exist in a valid
+ * chain following this certificate. If the pathLen has the value
+ * of this constant, then the length of the chain is unlimited
+ */
+#define PKIX_UNLIMITED_PATH_CONSTRAINT ((PKIX_Int32) -1)
+
+/*
+ * Define Certificate Extension hard-coded OID's
+ */
+#define PKIX_UNKNOWN_OID SEC_OID_UNKNOWN
+#define PKIX_CERTKEYUSAGE_OID SEC_OID_X509_KEY_USAGE
+#define PKIX_CERTSUBJALTNAME_OID SEC_OID_X509_SUBJECT_ALT_NAME
+#define PKIX_BASICCONSTRAINTS_OID SEC_OID_X509_BASIC_CONSTRAINTS
+#define PKIX_CRLREASONCODE_OID SEC_OID_X509_REASON_CODE
+#define PKIX_NAMECONSTRAINTS_OID SEC_OID_X509_NAME_CONSTRAINTS
+#define PKIX_CERTIFICATEPOLICIES_OID SEC_OID_X509_CERTIFICATE_POLICIES
+#define PKIX_CERTIFICATEPOLICIES_ANYPOLICY_OID SEC_OID_X509_ANY_POLICY
+#define PKIX_POLICYMAPPINGS_OID SEC_OID_X509_POLICY_MAPPINGS
+#define PKIX_POLICYCONSTRAINTS_OID SEC_OID_X509_POLICY_CONSTRAINTS
+#define PKIX_EXTENDEDKEYUSAGE_OID SEC_OID_X509_EXT_KEY_USAGE
+#define PKIX_INHIBITANYPOLICY_OID SEC_OID_X509_INHIBIT_ANY_POLICY
+#define PKIX_NSCERTTYPE_OID SEC_OID_NS_CERT_EXT_CERT_TYPE
+#define PKIX_KEY_USAGE_SERVER_AUTH_OID SEC_OID_EXT_KEY_USAGE_SERVER_AUTH
+#define PKIX_KEY_USAGE_CLIENT_AUTH_OID SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH
+#define PKIX_KEY_USAGE_CODE_SIGN_OID SEC_OID_EXT_KEY_USAGE_CODE_SIGN
+#define PKIX_KEY_USAGE_EMAIL_PROTECT_OID SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT
+#define PKIX_KEY_USAGE_TIME_STAMP_OID SEC_OID_EXT_KEY_USAGE_TIME_STAMP
+#define PKIX_KEY_USAGE_OCSP_RESPONDER_OID SEC_OID_OCSP_RESPONDER
+
+
+/* Available revocation method types. */
+typedef enum PKIX_RevocationMethodTypeEnum {
+ PKIX_RevocationMethod_CRL = 0,
+ PKIX_RevocationMethod_OCSP,
+ PKIX_RevocationMethod_MAX
+} PKIX_RevocationMethodType;
+
+/* A set of statuses revocation checker operates on */
+typedef enum PKIX_RevocationStatusEnum {
+ PKIX_RevStatus_NoInfo = 0,
+ PKIX_RevStatus_Revoked,
+ PKIX_RevStatus_Success
+} PKIX_RevocationStatus;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIXT_H */
diff --git a/security/nss/lib/libpkix/libpkix.gyp b/security/nss/lib/libpkix/libpkix.gyp
new file mode 100644
index 0000000000..ec6e006179
--- /dev/null
+++ b/security/nss/lib/libpkix/libpkix.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'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'libpkix',
+ 'type': 'none',
+ 'conditions': [
+ [ 'disable_libpkix==0', {
+ 'dependencies': [
+ 'pkix/certsel/certsel.gyp:pkixcertsel',
+ 'pkix/checker/checker.gyp:pkixchecker',
+ 'pkix/crlsel/crlsel.gyp:pkixcrlsel',
+ 'pkix/params/params.gyp:pkixparams',
+ 'pkix/results/results.gyp:pkixresults',
+ 'pkix/store/store.gyp:pkixstore',
+ 'pkix/top/top.gyp:pkixtop',
+ 'pkix/util/util.gyp:pkixutil',
+ 'pkix_pl_nss/module/module.gyp:pkixmodule',
+ 'pkix_pl_nss/pki/pki.gyp:pkixpki',
+ 'pkix_pl_nss/system/system.gyp:pkixsystem',
+ ],
+ }],
+ ],
+ },
+ ],
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/manifest.mn b/security/nss/lib/libpkix/manifest.mn
new file mode 100644
index 0000000000..31990da63d
--- /dev/null
+++ b/security/nss/lib/libpkix/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 = ../..
+DEPTH = ../..
+
+#
+DIRS = include pkix pkix_pl_nss \
+ $(NULL)
+
+# This part of the code, including all sub-dirs, can be optimized for size
+export ALLOW_OPT_CODE_SIZE = 1
diff --git a/security/nss/lib/libpkix/pkix/Makefile b/security/nss/lib/libpkix/pkix/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/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). #
+#######################################################################
+
+
+#######################################################################
+# (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/lib/libpkix/pkix/certsel/Makefile b/security/nss/lib/libpkix/pkix/certsel/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/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). #
+#######################################################################
+
+
+#######################################################################
+# (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/lib/libpkix/pkix/certsel/certsel.gyp b/security/nss/lib/libpkix/pkix/certsel/certsel.gyp
new file mode 100644
index 0000000000..a7ff65ce76
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/certsel.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'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixcertsel',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_certselector.c',
+ 'pkix_comcertselparams.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/certsel/exports.gyp b/security/nss/lib/libpkix/pkix/certsel/exports.gyp
new file mode 100644
index 0000000000..9cbd847e7c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/exports.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'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_libpkix_pkix_certsel_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_certselector.h',
+ 'pkix_comcertselparams.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/certsel/manifest.mn b/security/nss/lib/libpkix/pkix/certsel/manifest.mn
new file mode 100644
index 0000000000..eb434bd531
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/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 = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_certselector.h \
+ pkix_comcertselparams.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_certselector.c \
+ pkix_comcertselparams.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixcertsel
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.c b/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.c
new file mode 100644
index 0000000000..89bddd98bc
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.c
@@ -0,0 +1,1637 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_certselector.c
+ *
+ * CertSelector Object Functions
+ *
+ */
+
+#include "pkix_certselector.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_CertSelector_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertSelector_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_CertSelector *selector = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a cert selector */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSELECTOR_TYPE, plContext),
+ PKIX_OBJECTNOTCERTSELECTOR);
+
+ selector = (PKIX_CertSelector *)object;
+ PKIX_DECREF(selector->params);
+ PKIX_DECREF(selector->context);
+
+cleanup:
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertSelector_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_CertSelector *certSelectorDuplicate = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSELECTOR_TYPE, plContext),
+ PKIX_OBJECTNOTCERTSELECTOR);
+
+ certSelector = (PKIX_CertSelector *)object;
+
+ PKIX_CHECK(PKIX_CertSelector_Create
+ (certSelector->matchCallback,
+ certSelector->context,
+ &certSelectorDuplicate,
+ plContext),
+ PKIX_CERTSELECTORCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)certSelector->params,
+ (PKIX_PL_Object **)&certSelectorDuplicate->params,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)certSelectorDuplicate;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(certSelectorDuplicate);
+ }
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_BasicConstraint
+ * DESCRIPTION:
+ *
+ * Determines whether the Cert pointed to by "cert" matches the basic
+ * constraints criterion using the basic constraints field of the
+ * ComCertSelParams pointed to by "params". If the basic constraints field is
+ * -1, no basic constraints check is done and the Cert is considered to match
+ * the basic constraints criterion. If the Cert does not match the basic
+ * constraints criterion, an Error pointer is returned.
+ *
+ * In order to match against this criterion, there are several possibilities.
+ *
+ * 1) If the criterion's minimum path length is greater than or equal to zero,
+ * a certificate must include a BasicConstraints extension with a pathLen of
+ * at least this value.
+ *
+ * 2) If the criterion's minimum path length is -2, a certificate must be an
+ * end-entity certificate.
+ *
+ * 3) If the criterion's minimum path length is -1, no basic constraints check
+ * is done and all certificates are considered to match this criterion.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose basic constraints field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * OUTPUT PARAMETERS ON FAILURE:
+ * If the function returns a failure,
+ * the output parameters of this function are undefined.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CertSelector_Match_BasicConstraint(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
+ PKIX_Boolean caFlag = PKIX_FALSE; /* EE Cert by default */
+ PKIX_Int32 pathLength = 0;
+ PKIX_Int32 minPathLength = 0;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_BasicConstraint");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+ *pResult = PKIX_TRUE;
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetBasicConstraints
+ (params, &minPathLength, plContext),
+ PKIX_COMCERTSELPARAMSGETBASICCONSTRAINTSFAILED);
+
+ /* If the minPathLength is unlimited (-1), no checking */
+ if (minPathLength == PKIX_CERTSEL_ALL_MATCH_MIN_PATHLENGTH) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
+ (cert, &basicConstraints, plContext),
+ PKIX_CERTGETBASICCONSTRAINTSFAILED);
+
+ if (basicConstraints != NULL) {
+ PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag
+ (basicConstraints, &caFlag, plContext),
+ PKIX_BASICCONSTRAINTSGETCAFLAGFAILED);
+
+ PKIX_CHECK(PKIX_PL_BasicConstraints_GetPathLenConstraint
+ (basicConstraints, &pathLength, plContext),
+ PKIX_BASICCONSTRAINTSGETPATHLENCONSTRAINTFAILED);
+ }
+
+ /*
+ * if minPathLength >= 0, the cert must have a BasicConstraints ext and
+ * the pathLength in this cert
+ * BasicConstraints needs to be >= minPathLength.
+ */
+ if (minPathLength >= 0){
+ if ((!basicConstraints) || (caFlag == PKIX_FALSE)){
+ PKIX_ERROR(PKIX_CERTNOTALLOWEDTOSIGNCERTIFICATES);
+ } else if ((pathLength != PKIX_UNLIMITED_PATH_CONSTRAINT) &&
+ (pathLength < minPathLength)){
+ PKIX_CERTSELECTOR_DEBUG
+ ("Basic Constraints path length match failed\n");
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_PATHLENCONSTRAINTINVALID);
+ }
+ }
+
+ /* if the minPathLength is -2, this cert must be an end-entity cert. */
+ if (minPathLength == PKIX_CERTSEL_ENDENTITY_MIN_PATHLENGTH) {
+ if (caFlag == PKIX_TRUE) {
+ PKIX_CERTSELECTOR_DEBUG
+ ("Basic Constraints end-entity match failed\n");
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_PATHLENCONSTRAINTINVALID);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(basicConstraints);
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_Policies
+ * DESCRIPTION:
+ *
+ * Determines whether the Cert pointed to by "cert" matches the policy
+ * constraints specified in the ComCertsSelParams given by "params".
+ * If "params" specifies a policy constraint of NULL, all certificates
+ * match. If "params" specifies an empty list, "cert" must have at least
+ * some policy. Otherwise "cert" must include at least one of the
+ * policies in the list. See the description of PKIX_CertSelector in
+ * pkix_certsel.h for more.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose policy criterion (if any) is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CertSelector_Match_Policies(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 numConstraintPolicies = 0;
+ PKIX_UInt32 numCertPolicies = 0;
+ PKIX_UInt32 certPolicyIndex = 0;
+ PKIX_Boolean result = PKIX_FALSE;
+ PKIX_List *constraintPolicies = NULL; /* List of PKIX_PL_OID */
+ PKIX_List *certPolicyInfos = NULL; /* List of PKIX_PL_CertPolicyInfo */
+ PKIX_PL_CertPolicyInfo *policyInfo = NULL;
+ PKIX_PL_OID *polOID = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_Policies");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetPolicy
+ (params, &constraintPolicies, plContext),
+ PKIX_COMCERTSELPARAMSGETPOLICYFAILED);
+
+ /* If constraintPolicies is NULL, all certificates "match" */
+ if (constraintPolicies) {
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation
+ (cert, &certPolicyInfos, plContext),
+ PKIX_CERTGETPOLICYINFORMATIONFAILED);
+
+ /* No hope of a match if cert has no policies */
+ if (!certPolicyInfos) {
+ PKIX_CERTSELECTOR_DEBUG("Certificate has no policies\n");
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHPOLICIESFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (constraintPolicies, &numConstraintPolicies, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numConstraintPolicies > 0) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (certPolicyInfos, &numCertPolicies, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (certPolicyIndex = 0;
+ ((!result) && (certPolicyIndex < numCertPolicies));
+ certPolicyIndex++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (certPolicyInfos,
+ certPolicyIndex,
+ (PKIX_PL_Object **)&policyInfo,
+ plContext),
+ PKIX_LISTGETELEMENTFAILED);
+ PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolicyId
+ (policyInfo, &polOID, plContext),
+ PKIX_CERTPOLICYINFOGETPOLICYIDFAILED);
+
+ PKIX_CHECK(pkix_List_Contains
+ (constraintPolicies,
+ (PKIX_PL_Object *)polOID,
+ &result,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ PKIX_DECREF(policyInfo);
+ PKIX_DECREF(polOID);
+ }
+ if (!result) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHPOLICIESFAILED);
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(constraintPolicies);
+ PKIX_DECREF(certPolicyInfos);
+ PKIX_DECREF(policyInfo);
+ PKIX_DECREF(polOID);
+
+ PKIX_RETURN(CERTSELECTOR);
+
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_CertificateValid
+ * DESCRIPTION:
+ *
+ * Determines whether the Cert pointed to by "cert" matches the certificate
+ * validity criterion using the CertificateValid field of the
+ * ComCertSelParams pointed to by "params". If the CertificateValid field is
+ * NULL, no validity check is done and the Cert is considered to match
+ * the CertificateValid criterion. If the CertificateValid field specifies a
+ * Date prior to the notBefore field in the Cert, or greater than the notAfter
+ * field in the Cert, an Error is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose certValid field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CertSelector_Match_CertificateValid(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_Date *validityTime = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_CertificateValid");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetCertificateValid
+ (params, &validityTime, plContext),
+ PKIX_COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED);
+
+ /* If the validityTime is not set, all certificates are acceptable */
+ if (validityTime) {
+ PKIX_CHECK(PKIX_PL_Cert_CheckValidity
+ (cert, validityTime, plContext),
+ PKIX_CERTCHECKVALIDITYFAILED);
+ }
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ *pResult = PKIX_FALSE;
+ }
+ PKIX_DECREF(validityTime);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_NameConstraints
+ * DESCRIPTION:
+ *
+ * Determines whether the Cert pointed to by "cert" matches the name
+ * constraints criterion specified in the ComCertSelParams pointed to by
+ * "params". If the name constraints field is NULL, no name constraints check
+ * is done and the Cert is considered to match the name constraints criterion.
+ * If the Cert does not match the name constraints criterion, an Error pointer
+ * is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose name constraints field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CertSelector_Match_NameConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_NameConstraints");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetNameConstraints
+ (params, &nameConstraints, plContext),
+ PKIX_COMCERTSELPARAMSGETNAMECONSTRAINTSFAILED);
+
+ if (nameConstraints != NULL) {
+ /* As only the end-entity certificate should have
+ * the common name constrained as if it was a dNSName,
+ * do not constrain the common name when building a
+ * forward path.
+ */
+ PKIX_CHECK(PKIX_PL_Cert_CheckNameConstraints
+ (cert, nameConstraints, PKIX_FALSE, plContext),
+ PKIX_CERTCHECKNAMECONSTRAINTSFAILED);
+ }
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ *pResult = PKIX_FALSE;
+ }
+
+ PKIX_DECREF(nameConstraints);
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_PathToNames
+ * DESCRIPTION:
+ *
+ * Determines whether the names at pathToNames in "params" complies with the
+ * NameConstraints pointed to by "cert". If the pathToNames field is NULL
+ * or there is no name constraints for this "cert", no checking is done
+ * and the Cert is considered to match the name constraints criterion.
+ * If the Cert does not match the name constraints criterion, an Error
+ * pointer is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose PathToNames field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CertSelector_Match_PathToNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_List *pathToNamesList = NULL;
+ PKIX_Boolean passed = PKIX_FALSE;
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_PathToNames");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetPathToNames
+ (params, &pathToNamesList, plContext),
+ PKIX_COMCERTSELPARAMSGETPATHTONAMESFAILED);
+
+ if (pathToNamesList != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
+ (cert, &nameConstraints, plContext),
+ PKIX_CERTGETNAMECONSTRAINTSFAILED);
+
+ if (nameConstraints != NULL) {
+
+ PKIX_CHECK(PKIX_PL_CertNameConstraints_CheckNamesInNameSpace
+ (pathToNamesList, nameConstraints, &passed, plContext),
+ PKIX_CERTNAMECONSTRAINTSCHECKNAMESINNAMESPACEFAILED);
+
+ if (passed != PKIX_TRUE) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHPATHTONAMESFAILED);
+ }
+ }
+
+ }
+
+cleanup:
+
+ PKIX_DECREF(nameConstraints);
+ PKIX_DECREF(pathToNamesList);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_SubjAltNames
+ * DESCRIPTION:
+ *
+ * Determines whether the names at subjAltNames in "params" match with the
+ * SubjAltNames pointed to by "cert". If the subjAltNames field is NULL,
+ * no name checking is done and the Cert is considered to match the
+ * criterion. If the Cert does not match the criterion, an Error pointer
+ * is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose SubjAltNames field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CertSelector_Match_SubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_List *subjAltNamesList = NULL;
+ PKIX_List *certSubjAltNames = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+ PKIX_Boolean checkPassed = PKIX_FALSE;
+ PKIX_Boolean matchAll = PKIX_TRUE;
+ PKIX_UInt32 i, numItems;
+ PKIX_UInt32 matchCount = 0;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjAltNames");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetMatchAllSubjAltNames
+ (params, &matchAll, plContext),
+ PKIX_COMCERTSELPARAMSGETMATCHALLSUBJALTNAMESFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubjAltNames
+ (params, &subjAltNamesList, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
+
+ if (subjAltNamesList != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
+ (cert, &certSubjAltNames, plContext),
+ PKIX_CERTGETSUBJALTNAMESFAILED);
+
+ if (certSubjAltNames == NULL) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJALTNAMESFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (subjAltNamesList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (subjAltNamesList,
+ i,
+ (PKIX_PL_Object **) &name,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_List_Contains
+ (certSubjAltNames,
+ (PKIX_PL_Object *) name,
+ &checkPassed,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ PKIX_DECREF(name);
+
+ if (checkPassed == PKIX_TRUE) {
+
+ if (matchAll == PKIX_FALSE) {
+ /* one match is good enough */
+ matchCount = numItems;
+ break;
+ } else {
+ /* else continue checking next */
+ matchCount++;
+ }
+
+ }
+
+ }
+
+ if (matchCount != numItems) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJALTNAMESFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(name);
+ PKIX_DECREF(certSubjAltNames);
+ PKIX_DECREF(subjAltNamesList);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_ExtendedKeyUsage
+ * DESCRIPTION:
+ *
+ * Determines whether the names at ExtKeyUsage in "params" matches with the
+ * ExtKeyUsage pointed to by "cert". If the ExtKeyUsage criterion or
+ * ExtKeyUsage in "cert" is NULL, no checking is done and the Cert is
+ * considered a match. If the Cert does not match, an Error pointer is
+ * returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose ExtKeyUsage field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CertSelector_Match_ExtendedKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_List *extKeyUsageList = NULL;
+ PKIX_List *certExtKeyUsageList = NULL;
+ PKIX_PL_OID *ekuOid = NULL;
+ PKIX_Boolean isContained = PKIX_FALSE;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_ExtendedKeyUsage");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
+ (params, &extKeyUsageList, plContext),
+ PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
+
+ if (extKeyUsageList == NULL) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
+ (cert, &certExtKeyUsageList, plContext),
+ PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
+
+ if (certExtKeyUsageList != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (extKeyUsageList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (extKeyUsageList, i, (PKIX_PL_Object **)&ekuOid, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_List_Contains
+ (certExtKeyUsageList,
+ (PKIX_PL_Object *)ekuOid,
+ &isContained,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ PKIX_DECREF(ekuOid);
+
+ if (isContained != PKIX_TRUE) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHEXTENDEDKEYUSAGEFAILED);
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(ekuOid);
+ PKIX_DECREF(extKeyUsageList);
+ PKIX_DECREF(certExtKeyUsageList);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_KeyUsage
+ * DESCRIPTION:
+ *
+ * Determines whether the bits at KeyUsage in "params" matches with the
+ * KeyUsage pointed to by "cert". If the KeyUsage in params is 0
+ * no checking is done and the Cert is considered a match. If the Cert does
+ * not match, an Error pointer is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose ExtKeyUsage field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CertSelector_Match_KeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 keyUsage = 0;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_KeyUsage");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetKeyUsage
+ (params, &keyUsage, plContext),
+ PKIX_COMCERTSELPARAMSGETKEYUSAGEFAILED);
+
+ if (keyUsage != 0) {
+
+ PKIX_CHECK(PKIX_PL_Cert_VerifyKeyUsage
+ (cert, keyUsage, plContext),
+ PKIX_CERTVERIFYKEYUSAGEFAILED);
+
+ }
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ *pResult = PKIX_FALSE;
+ }
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_SubjKeyId
+ * DESCRIPTION:
+ *
+ * Determines whether the bytes at subjKeyId in "params" matches with the
+ * Subject Key Identifier pointed to by "cert". If the subjKeyId in params is
+ * set to NULL or the Cert doesn't have a Subject Key Identifier, no checking
+ * is done and the Cert is considered a match. If the Cert does not match, an
+ * Error pointer is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose subjKeyId field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CertSelector_Match_SubjKeyId(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *selSubjKeyId = NULL;
+ PKIX_PL_ByteArray *certSubjKeyId = NULL;
+ PKIX_Boolean equals = PKIX_FALSE;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjKeyId");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubjKeyIdentifier
+ (params, &selSubjKeyId, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJKEYIDENTIFIERFAILED);
+
+ if (selSubjKeyId != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier
+ (cert, &certSubjKeyId, plContext),
+ PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED);
+
+ if (certSubjKeyId == NULL) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)selSubjKeyId,
+ (PKIX_PL_Object *)certSubjKeyId,
+ &equals,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (equals == PKIX_FALSE) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJKEYIDFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(selSubjKeyId);
+ PKIX_DECREF(certSubjKeyId);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_AuthKeyId
+ * DESCRIPTION:
+ *
+ * Determines whether the bytes at authKeyId in "params" matches with the
+ * Authority Key Identifier pointed to by "cert". If the authKeyId in params
+ * is set to NULL, no checking is done and the Cert is considered a match. If
+ * the Cert does not match, an Error pointer is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose authKeyId field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CertSelector_Match_AuthKeyId(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *selAuthKeyId = NULL;
+ PKIX_PL_ByteArray *certAuthKeyId = NULL;
+ PKIX_Boolean equals = PKIX_FALSE;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_AuthKeyId");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetAuthorityKeyIdentifier
+ (params, &selAuthKeyId, plContext),
+ PKIX_COMCERTSELPARAMSGETAUTHORITYKEYIDENTIFIERFAILED);
+
+ if (selAuthKeyId != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier
+ (cert, &certAuthKeyId, plContext),
+ PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED);
+
+ if (certAuthKeyId == NULL) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHAUTHKEYIDFAILED);
+ }
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)selAuthKeyId,
+ (PKIX_PL_Object *)certAuthKeyId,
+ &equals,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (equals != PKIX_TRUE) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHAUTHKEYIDFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(selAuthKeyId);
+ PKIX_DECREF(certAuthKeyId);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_SubjPKAlgId
+ * DESCRIPTION:
+ *
+ * Determines whether the OID at subjPKAlgId in "params" matches with the
+ * Subject Public Key Alg Id pointed to by "cert". If the subjPKAlgId in params
+ * is set to NULL, no checking is done and the Cert is considered a match. If
+ * the Cert does not match, an Error pointer is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose subjPKAlgId field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CertSelector_Match_SubjPKAlgId(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_OID *selPKAlgId = NULL;
+ PKIX_PL_OID *certPKAlgId = NULL;
+ PKIX_Boolean equals = PKIX_FALSE;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjPKAlgId");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubjPKAlgId
+ (params, &selPKAlgId, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJPKALGIDFAILED);
+
+ if (selPKAlgId != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKeyAlgId
+ (cert, &certPKAlgId, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYALGIDFAILED);
+
+ if (certPKAlgId != NULL) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPKALGIDFAILED);
+ }
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)selPKAlgId,
+ (PKIX_PL_Object *)certPKAlgId,
+ &equals,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (equals != PKIX_TRUE) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPKALGIDFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(selPKAlgId);
+ PKIX_DECREF(certPKAlgId);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Match_SubjPubKey
+ * DESCRIPTION:
+ *
+ * Determines whether the key at subjPubKey in "params" matches with the
+ * Subject Public Key pointed to by "cert". If the subjPubKey in params
+ * is set to NULL, no checking is done and the Cert is considered a match. If
+ * the Cert does not match, an Error pointer is returned.
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of ComCertSelParams whose subPubKey field is used.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched. Must be non-NULL.
+ * "pResult"
+ * Address of PKIX_Boolean that returns the match result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CertSelector_Match_SubjPubKey(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *selPK = NULL;
+ PKIX_PL_PublicKey *certPK = NULL;
+ PKIX_Boolean equals = PKIX_FALSE;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjPubKey");
+ PKIX_NULLCHECK_THREE(params, cert, pResult);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubjPubKey
+ (params, &selPK, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJPUBKEYFAILED);
+
+ if (selPK != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (cert, &certPK, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+
+ if (certPK == NULL) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPUBKEYFAILED);
+ }
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)selPK,
+ (PKIX_PL_Object *)certPK,
+ &equals,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (equals != PKIX_TRUE) {
+ *pResult = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPUBKEYFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(selPK);
+ PKIX_DECREF(certPK);
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_DefaultMatch
+ * DESCRIPTION:
+ *
+ * This default match function determines whether the specified Cert pointed
+ * to by "cert" matches the criteria of the CertSelector pointed to by
+ * "selector". If the Cert does not match the CertSelector's
+ * criteria, an error will be thrown.
+ *
+ * This default match function understands how to process the most common
+ * parameters. Any common parameter that is not set is assumed to be disabled,
+ * which means this function will select all certificates without regard to
+ * that particular disabled parameter. For example, if the SerialNumber
+ * parameter is not set, this function will not filter out any certificate
+ * based on its serial number. As such, if no parameters are set, all are
+ * disabled and any certificate will match. If a parameter is disabled, its
+ * associated PKIX_ComCertSelParams_Get* function returns a default value.
+ * That value is -1 for PKIX_ComCertSelParams_GetBasicConstraints and
+ * PKIX_ComCertSelParams_GetVersion, 0 for PKIX_ComCertSelParams_GetKeyUsage,
+ * and NULL for all other Get functions.
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CertSelector whose MatchCallback logic and parameters are
+ * to be used. Must be non-NULL.
+ * "cert"
+ * Address of Cert that is to be matched using "selector".
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CertSelector_DefaultMatch(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Cert *cert,
+ void *plContext)
+{
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_X500Name *certSubject = NULL;
+ PKIX_PL_X500Name *selSubject = NULL;
+ PKIX_PL_X500Name *certIssuer = NULL;
+ PKIX_PL_X500Name *selIssuer = NULL;
+ PKIX_PL_BigInt *certSerialNumber = NULL;
+ PKIX_PL_BigInt *selSerialNumber = NULL;
+ PKIX_PL_Cert *selCert = NULL;
+ PKIX_PL_Date *selDate = NULL;
+ PKIX_UInt32 selVersion = 0xFFFFFFFF;
+ PKIX_UInt32 certVersion = 0;
+ PKIX_Boolean result = PKIX_TRUE;
+ PKIX_Boolean isLeafCert = PKIX_TRUE;
+
+#ifdef PKIX_BUILDDEBUG
+ PKIX_PL_String *certString = NULL;
+ void *certAscii = NULL;
+ PKIX_UInt32 certAsciiLen;
+#endif
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_DefaultMatch");
+ PKIX_NULLCHECK_TWO(selector, cert);
+
+ PKIX_INCREF(selector->params);
+ params = selector->params;
+
+ /* Are we looking for CAs? */
+ PKIX_CHECK(PKIX_ComCertSelParams_GetLeafCertFlag
+ (params, &isLeafCert, plContext),
+ PKIX_COMCERTSELPARAMSGETLEAFCERTFLAGFAILED);
+
+ if (params == NULL){
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetVersion
+ (params, &selVersion, plContext),
+ PKIX_COMCERTSELPARAMSGETVERSIONFAILED);
+
+ if (selVersion != 0xFFFFFFFF){
+ PKIX_CHECK(PKIX_PL_Cert_GetVersion
+ (cert, &certVersion, plContext),
+ PKIX_CERTGETVERSIONFAILED);
+
+ if (selVersion != certVersion) {
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTVERSIONFAILED);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
+ (params, &selSubject, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
+
+ if (selSubject){
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject
+ (cert, &certSubject, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+
+ if (certSubject){
+ PKIX_CHECK(PKIX_PL_X500Name_Match
+ (selSubject, certSubject, &result, plContext),
+ PKIX_X500NAMEMATCHFAILED);
+
+ if (result == PKIX_FALSE){
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTSUBJECTFAILED);
+ }
+ } else { /* cert has no subject */
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTSUBJECTFAILED);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetIssuer
+ (params, &selIssuer, plContext),
+ PKIX_COMCERTSELPARAMSGETISSUERFAILED);
+
+ if (selIssuer){
+ PKIX_CHECK(PKIX_PL_Cert_GetIssuer
+ (cert, &certIssuer, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ PKIX_CHECK(PKIX_PL_X500Name_Match
+ (selIssuer, certIssuer, &result, plContext),
+ PKIX_X500NAMEMATCHFAILED);
+
+ if (result == PKIX_FALSE){
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTISSUERFAILED);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSerialNumber
+ (params, &selSerialNumber, plContext),
+ PKIX_COMCERTSELPARAMSGETSERIALNUMBERFAILED);
+
+ if (selSerialNumber){
+ PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber
+ (cert, &certSerialNumber, plContext),
+ PKIX_CERTGETSERIALNUMBERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)selSerialNumber,
+ (PKIX_PL_Object *)certSerialNumber,
+ &result,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (result == PKIX_FALSE){
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTSERIALNUMFAILED);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetCertificate
+ (params, &selCert, plContext),
+ PKIX_COMCERTSELPARAMSGETCERTIFICATEFAILED);
+
+ if (selCert){
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *) selCert,
+ (PKIX_PL_Object *) cert,
+ &result,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (result == PKIX_FALSE){
+ PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTOBJECTFAILED);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetCertificateValid
+ (params, &selDate, plContext),
+ PKIX_COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED);
+
+ if (selDate){
+ PKIX_CHECK(PKIX_PL_Cert_CheckValidity
+ (cert, selDate, plContext),
+ PKIX_CERTCHECKVALIDITYFAILED);
+ }
+
+ PKIX_CHECK(pkix_CertSelector_Match_BasicConstraint
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHBASICCONSTRAINTFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_Policies
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHPOLICIESFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_CertificateValid
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHCERTIFICATEVALIDFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_NameConstraints
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHNAMECONSTRAINTSFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_PathToNames
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHPATHTONAMESFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_SubjAltNames
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHSUBJALTNAMESFAILED);
+
+ /* Check key usage and cert type based on certificate usage. */
+ PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert, !isLeafCert,
+ plContext),
+ PKIX_CERTVERIFYCERTTYPEFAILED);
+
+ /* Next two check are for user supplied additional KU and EKU. */
+ PKIX_CHECK(pkix_CertSelector_Match_ExtendedKeyUsage
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHEXTENDEDKEYUSAGEFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_KeyUsage
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHKEYUSAGEFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_SubjKeyId
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHSUBJKEYIDFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_AuthKeyId
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHAUTHKEYIDFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_SubjPKAlgId
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHSUBJPKALGIDFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Match_SubjPubKey
+ (params, cert, &result, plContext),
+ PKIX_CERTSELECTORMATCHSUBJPUBKEYFAILED);
+
+ /* if we reach here, the cert has successfully matched criteria */
+
+
+#ifdef PKIX_BUILDDEBUG
+
+ PKIX_CHECK(pkix_pl_Cert_ToString_Helper
+ (cert, PKIX_TRUE, &certString, plContext),
+ PKIX_CERTTOSTRINGHELPERFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (certString,
+ PKIX_ESCASCII,
+ &certAscii,
+ &certAsciiLen,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_CERTSELECTOR_DEBUG_ARG("Cert Selected:\n%s\n", certAscii);
+
+#endif
+
+cleanup:
+
+#ifdef PKIX_BUILDDEBUG
+ PKIX_DECREF(certString);
+ PKIX_FREE(certAscii);
+#endif
+
+ PKIX_DECREF(certSubject);
+ PKIX_DECREF(selSubject);
+ PKIX_DECREF(certIssuer);
+ PKIX_DECREF(selIssuer);
+ PKIX_DECREF(certSerialNumber);
+ PKIX_DECREF(selSerialNumber);
+ PKIX_DECREF(selCert);
+ PKIX_DECREF(selDate);
+ PKIX_DECREF(params);
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTSELECTOR_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_CertSelector_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_RegisterSelf");
+
+ entry.description = "CertSelector";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_CertSelector);
+ entry.destructor = pkix_CertSelector_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_CertSelector_Duplicate;
+
+ systemClasses[PKIX_CERTSELECTOR_TYPE] = entry;
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+
+/*
+ * FUNCTION: PKIX_CertSelector_Create (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_CertSelector_Create(
+ PKIX_CertSelector_MatchCallback callback,
+ PKIX_PL_Object *certSelectorContext,
+ PKIX_CertSelector **pSelector,
+ void *plContext)
+{
+ PKIX_CertSelector *selector = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_Create");
+ PKIX_NULLCHECK_ONE(pSelector);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTSELECTOR_TYPE,
+ sizeof (PKIX_CertSelector),
+ (PKIX_PL_Object **)&selector,
+ plContext),
+ PKIX_COULDNOTCREATECERTSELECTOROBJECT);
+
+ /*
+ * if user specified a particular match callback, we use that one.
+ * otherwise, we use the default match implementation which
+ * understands how to process PKIX_ComCertSelParams
+ */
+
+ if (callback){
+ selector->matchCallback = callback;
+ } else {
+ selector->matchCallback = pkix_CertSelector_DefaultMatch;
+ }
+
+ /* initialize other fields */
+ selector->params = NULL;
+
+ PKIX_INCREF(certSelectorContext);
+ selector->context = certSelectorContext;
+
+ *pSelector = selector;
+
+cleanup:
+
+ PKIX_RETURN(CERTSELECTOR);
+
+}
+
+/*
+ * FUNCTION: PKIX_CertSelector_GetMatchCallback
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_CertSelector_GetMatchCallback(
+ PKIX_CertSelector *selector,
+ PKIX_CertSelector_MatchCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_GetMatchCallback");
+ PKIX_NULLCHECK_TWO(selector, pCallback);
+
+ *pCallback = selector->matchCallback;
+
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: PKIX_CertSelector_GetCertSelectorContext
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_CertSelector_GetCertSelectorContext(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Object **pCertSelectorContext,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_GetCertSelectorContext");
+ PKIX_NULLCHECK_TWO(selector, pCertSelectorContext);
+
+ PKIX_INCREF(selector->context);
+
+ *pCertSelectorContext = selector->context;
+
+cleanup:
+ PKIX_RETURN(CERTSELECTOR);
+}
+
+/*
+ * FUNCTION: PKIX_CertSelector_GetCommonCertSelectorParams
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_CertSelector_GetCommonCertSelectorParams(
+ PKIX_CertSelector *selector,
+ PKIX_ComCertSelParams **pParams,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSELECTOR,
+ "PKIX_CertSelector_GetCommonCertSelectorParams");
+
+ PKIX_NULLCHECK_TWO(selector, pParams);
+
+ PKIX_INCREF(selector->params);
+ *pParams = selector->params;
+
+cleanup:
+ PKIX_RETURN(CERTSELECTOR);
+
+}
+
+/*
+ * FUNCTION: PKIX_CertSelector_SetCommonCertSelectorParams
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_CertSelector_SetCommonCertSelectorParams(
+ PKIX_CertSelector *selector,
+ PKIX_ComCertSelParams *params,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSELECTOR,
+ "PKIX_CertSelector_SetCommonCertSelectorParams");
+
+ PKIX_NULLCHECK_ONE(selector);
+
+ PKIX_DECREF(selector->params);
+ PKIX_INCREF(params);
+ selector->params = params;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)selector, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CERTSELECTOR);
+
+}
+
+/*
+ * FUNCTION: pkix_CertSelector_Select
+ * DESCRIPTION:
+ *
+ * This function applies the selector pointed to by "selector" to each Cert,
+ * in turn, in the List pointed to by "before", and creates a List containing
+ * all the Certs that matched, or passed the selection process, storing that
+ * List at "pAfter". If no Certs match, an empty List is stored at "pAfter".
+ *
+ * The List returned in "pAfter" is immutable.
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CertSelelector to be applied to the List. Must be non-NULL.
+ * "before"
+ * Address of List that is to be filtered. Must be non-NULL.
+ * "pAfter"
+ * Address at which resulting List, possibly empty, is stored. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CertSelector_Select(
+ PKIX_CertSelector *selector,
+ PKIX_List *before,
+ PKIX_List **pAfter,
+ void *plContext)
+{
+ PKIX_UInt32 numBefore = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_List *filtered = NULL;
+ PKIX_PL_Cert *candidate = NULL;
+
+ PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_Select");
+ PKIX_NULLCHECK_THREE(selector, before, pAfter);
+
+ PKIX_CHECK(PKIX_List_Create(&filtered, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(before, &numBefore, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numBefore; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (before, i, (PKIX_PL_Object **)&candidate, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK_ONLY_FATAL(selector->matchCallback
+ (selector, candidate, plContext),
+ PKIX_CERTSELECTORMATCHCALLBACKFAILED);
+
+ if (!(PKIX_ERROR_RECEIVED)) {
+
+ PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem
+ (filtered,
+ (PKIX_PL_Object *)candidate,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ pkixTempErrorReceived = PKIX_FALSE;
+ PKIX_DECREF(candidate);
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(filtered, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ /* Don't throw away the list if one Cert was bad! */
+ pkixTempErrorReceived = PKIX_FALSE;
+
+ *pAfter = filtered;
+ filtered = NULL;
+
+cleanup:
+
+ PKIX_DECREF(filtered);
+ PKIX_DECREF(candidate);
+
+ PKIX_RETURN(CERTSELECTOR);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.h b/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.h
new file mode 100644
index 0000000000..33b648354c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/pkix_certselector.h
@@ -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_certselector.h
+ *
+ * CertSelector Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_CERTSELECTOR_H
+#define _PKIX_CERTSELECTOR_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_CertSelectorStruct {
+ PKIX_CertSelector_MatchCallback matchCallback;
+ PKIX_ComCertSelParams *params;
+ PKIX_PL_Object *context;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_CertSelector_Select(
+ PKIX_CertSelector *selector,
+ PKIX_List *before,
+ PKIX_List **pAfter,
+ void *plContext);
+
+PKIX_Error *pkix_CertSelector_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_CERTSELECTOR_H */
diff --git a/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.c b/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.c
new file mode 100644
index 0000000000..a62f78d231
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.c
@@ -0,0 +1,1188 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_comcertselparams.c
+ *
+ * ComCertSelParams Object Functions
+ *
+ */
+
+#include "pkix_comcertselparams.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_ComCertSelParams_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCertSelParams_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ComCertSelParams *params = NULL;
+
+ PKIX_ENTER(COMCERTSELPARAMS, "pkix_ComCertSelParams_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a comCertSelParams object */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_COMCERTSELPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTCOMCERTSELPARAMS);
+
+ params = (PKIX_ComCertSelParams *)object;
+
+ PKIX_DECREF(params->subject);
+ PKIX_DECREF(params->policies);
+ PKIX_DECREF(params->cert);
+ PKIX_DECREF(params->nameConstraints);
+ PKIX_DECREF(params->pathToNames);
+ PKIX_DECREF(params->subjAltNames);
+ PKIX_DECREF(params->date);
+ PKIX_DECREF(params->extKeyUsage);
+ PKIX_DECREF(params->certValid);
+ PKIX_DECREF(params->issuer);
+ PKIX_DECREF(params->serialNumber);
+ PKIX_DECREF(params->authKeyId);
+ PKIX_DECREF(params->subjKeyId);
+ PKIX_DECREF(params->subjPubKey);
+ PKIX_DECREF(params->subjPKAlgId);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCertSelParams_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCertSelParams_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_ComCertSelParams *paramsDuplicate = NULL;
+
+ PKIX_ENTER(COMCERTSELPARAMS, "pkix_ComCertSelParams_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_COMCERTSELPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTCOMCERTSELPARAMS);
+
+ params = (PKIX_ComCertSelParams *)object;
+
+ PKIX_CHECK(PKIX_ComCertSelParams_Create(&paramsDuplicate, plContext),
+ PKIX_COMCERTSELPARAMSCREATEFAILED);
+
+ paramsDuplicate->minPathLength = params->minPathLength;
+ paramsDuplicate->matchAllSubjAltNames = params->matchAllSubjAltNames;
+
+ PKIX_DUPLICATE(params->subject, &paramsDuplicate->subject, plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->policies, &paramsDuplicate->policies, plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ if (params->cert){
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)params->cert,
+ (PKIX_PL_Object **)&paramsDuplicate->cert,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+ }
+
+ PKIX_DUPLICATE
+ (params->nameConstraints,
+ &paramsDuplicate->nameConstraints,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->pathToNames,
+ &paramsDuplicate->pathToNames,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->subjAltNames,
+ &paramsDuplicate->subjAltNames,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ if (params->date){
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)params->date,
+ (PKIX_PL_Object **)&paramsDuplicate->date,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+ }
+
+ paramsDuplicate->keyUsage = params->keyUsage;
+
+ PKIX_DUPLICATE(params->certValid,
+ &paramsDuplicate->certValid,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->issuer,
+ &paramsDuplicate->issuer,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->serialNumber,
+ &paramsDuplicate->serialNumber,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->authKeyId,
+ &paramsDuplicate->authKeyId,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->subjKeyId,
+ &paramsDuplicate->subjKeyId,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->subjPubKey,
+ &paramsDuplicate->subjPubKey,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE(params->subjPKAlgId,
+ &paramsDuplicate->subjPKAlgId,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ paramsDuplicate->leafCertFlag = params->leafCertFlag;
+
+ *pNewObject = (PKIX_PL_Object *)paramsDuplicate;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(paramsDuplicate);
+ }
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCertSelParams_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_COMCERTSELPARAMS_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_ComCertSelParams_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry* entry = &systemClasses[PKIX_COMCERTSELPARAMS_TYPE];
+
+ PKIX_ENTER(COMCERTSELPARAMS, "pkix_ComCertSelParams_RegisterSelf");
+
+ entry->description = "ComCertSelParams";
+ entry->typeObjectSize = sizeof(PKIX_ComCertSelParams);
+ entry->destructor = pkix_ComCertSelParams_Destroy;
+ entry->duplicateFunction = pkix_ComCertSelParams_Duplicate;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_Create (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_Create(
+ PKIX_ComCertSelParams **pParams,
+ void *plContext)
+{
+ PKIX_ComCertSelParams *params = NULL;
+
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_Create");
+ PKIX_NULLCHECK_ONE(pParams);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_COMCERTSELPARAMS_TYPE,
+ sizeof (PKIX_ComCertSelParams),
+ (PKIX_PL_Object **)&params,
+ plContext),
+ PKIX_COULDNOTCREATECOMMONCERTSELPARAMSOBJECT);
+
+ /* initialize fields */
+ params->version = 0xFFFFFFFF;
+ params->minPathLength = -1;
+ params->matchAllSubjAltNames = PKIX_TRUE;
+ params->subject = NULL;
+ params->policies = NULL;
+ params->cert = NULL;
+ params->nameConstraints = NULL;
+ params->pathToNames = NULL;
+ params->subjAltNames = NULL;
+ params->extKeyUsage = NULL;
+ params->keyUsage = 0;
+ params->extKeyUsage = NULL;
+ params->keyUsage = 0;
+ params->date = NULL;
+ params->certValid = NULL;
+ params->issuer = NULL;
+ params->serialNumber = NULL;
+ params->authKeyId = NULL;
+ params->subjKeyId = NULL;
+ params->subjPubKey = NULL;
+ params->subjPKAlgId = NULL;
+ params->leafCertFlag = PKIX_FALSE;
+
+ *pParams = params;
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubject (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubject(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_X500Name **pSubject,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSubject");
+ PKIX_NULLCHECK_TWO(params, pSubject);
+
+ PKIX_INCREF(params->subject);
+
+ *pSubject = params->subject;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubject (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubject(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_X500Name *subject,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetSubject");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->subject);
+
+ PKIX_INCREF(subject);
+
+ params->subject = subject;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetBasicConstraints
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetBasicConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_Int32 *pMinPathLength,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetBasicConstraints");
+ PKIX_NULLCHECK_TWO(params, pMinPathLength);
+
+ *pMinPathLength = params->minPathLength;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetBasicConstraints
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetBasicConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_Int32 minPathLength,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetBasicConstraints");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->minPathLength = minPathLength;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetPolicy (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetPolicy(
+ PKIX_ComCertSelParams *params,
+ PKIX_List **pPolicy, /* List of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetPolicy");
+ PKIX_NULLCHECK_TWO(params, pPolicy);
+
+ PKIX_INCREF(params->policies);
+ *pPolicy = params->policies;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetPolicy (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetPolicy(
+ PKIX_ComCertSelParams *params,
+ PKIX_List *policy, /* List of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetPolicy");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->policies);
+ PKIX_INCREF(policy);
+ params->policies = policy;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetCertificate
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetCertificate(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert **pCert,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetCertificate");
+ PKIX_NULLCHECK_TWO(params, pCert);
+
+ PKIX_INCREF(params->cert);
+ *pCert = params->cert;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetCertificate
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetCertificate(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Cert *cert,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetCertificate");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->cert);
+ PKIX_INCREF(cert);
+ params->cert = cert;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetCertificateValid
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetCertificateValid(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetCertificateValid");
+
+ PKIX_NULLCHECK_TWO(params, pDate);
+
+ PKIX_INCREF(params->date);
+ *pDate = params->date;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetCertificateValid
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetCertificateValid(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_Date *date,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetCertificateValid");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->date);
+ PKIX_INCREF(date);
+ params->date = date;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetNameConstraints
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetNameConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetNameConstraints");
+ PKIX_NULLCHECK_TWO(params, pNameConstraints);
+
+ PKIX_INCREF(params->nameConstraints);
+
+ *pNameConstraints = params->nameConstraints;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetNameConstraints
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetNameConstraints(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetNameConstraints");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->nameConstraints);
+ PKIX_INCREF(nameConstraints);
+ params->nameConstraints = nameConstraints;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetPathToNames
+ * (see comments in pkix_certsel.h)
+ */PKIX_Error *
+PKIX_ComCertSelParams_GetPathToNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_List **pNames, /* list of PKIX_PL_GeneralName */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetPathToNames");
+ PKIX_NULLCHECK_TWO(params, pNames);
+
+ PKIX_INCREF(params->pathToNames);
+
+ *pNames = params->pathToNames;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetPathToNames
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetPathToNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_List *names, /* list of PKIX_PL_GeneralName */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->pathToNames);
+ PKIX_INCREF(names);
+
+ params->pathToNames = names;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_AddPathToName
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_AddPathToName(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_GeneralName *name,
+ void *plContext)
+{
+ PKIX_List *pathToNamesList = NULL;
+
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_AddPathToName");
+ PKIX_NULLCHECK_ONE(params);
+
+ if (name == NULL) {
+ goto cleanup;
+ }
+
+ if (params->pathToNames == NULL) {
+ /* Create a list for name item */
+ PKIX_CHECK(PKIX_List_Create(&pathToNamesList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ params->pathToNames = pathToNamesList;
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (params->pathToNames, (PKIX_PL_Object *)name, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubjAltNames
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_List **pNames, /* list of PKIX_PL_GeneralName */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSubjAltNames");
+ PKIX_NULLCHECK_TWO(params, pNames);
+
+ PKIX_INCREF(params->subjAltNames);
+
+ *pNames = params->subjAltNames;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubjAltNames
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_List *names, /* list of PKIX_PL_GeneralName */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetSubjAltNames");
+ PKIX_NULLCHECK_TWO(params, names);
+
+ PKIX_DECREF(params->subjAltNames);
+ PKIX_INCREF(names);
+
+ params->subjAltNames = names;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_AddSubjAltNames
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_AddSubjAltName(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_GeneralName *name,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_AddSubjAltName");
+ PKIX_NULLCHECK_TWO(params, name);
+
+ if (params->subjAltNames == NULL) {
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+ params->subjAltNames = list;
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (params->subjAltNames, (PKIX_PL_Object *)name, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS)
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetMatchAllSubjAltNames
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetMatchAllSubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_Boolean *pMatch,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetMatchAllSubjAltNames");
+ PKIX_NULLCHECK_TWO(params, pMatch);
+
+ *pMatch = params->matchAllSubjAltNames;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetMatchAllSubjAltNames
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetMatchAllSubjAltNames(
+ PKIX_ComCertSelParams *params,
+ PKIX_Boolean match,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetMatchAllSubjAltNames");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->matchAllSubjAltNames = match;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetExtendedKeyUsage
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetExtendedKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_List **pExtKeyUsage, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetExtendedKeyUsage");
+ PKIX_NULLCHECK_TWO(params, pExtKeyUsage);
+
+ PKIX_INCREF(params->extKeyUsage);
+ *pExtKeyUsage = params->extKeyUsage;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetExtendedKeyUsage
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetExtendedKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_List *extKeyUsage, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetExtendedKeyUsage");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->extKeyUsage);
+ PKIX_INCREF(extKeyUsage);
+
+ params->extKeyUsage = extKeyUsage;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetKeyUsage
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_UInt32 *pKeyUsage,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetKeyUsage");
+ PKIX_NULLCHECK_TWO(params, pKeyUsage);
+
+ *pKeyUsage = params->keyUsage;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetKeyUsage
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetKeyUsage(
+ PKIX_ComCertSelParams *params,
+ PKIX_UInt32 keyUsage,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetKeyUsage");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->keyUsage = keyUsage;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetIssuer
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetIssuer(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_X500Name **pIssuer,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetIssuer");
+ PKIX_NULLCHECK_TWO(params, pIssuer);
+
+ PKIX_INCREF(params->issuer);
+ *pIssuer = params->issuer;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetIssuer
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetIssuer(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_X500Name *issuer,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetIssuer");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->issuer);
+ PKIX_INCREF(issuer);
+ params->issuer = issuer;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSerialNumber
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSerialNumber(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_BigInt **pSerialNumber,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSerialNumber");
+ PKIX_NULLCHECK_TWO(params, pSerialNumber);
+
+ PKIX_INCREF(params->serialNumber);
+ *pSerialNumber = params->serialNumber;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSerialNumber
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSerialNumber(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_BigInt *serialNumber,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetSerialNumber");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->serialNumber);
+ PKIX_INCREF(serialNumber);
+ params->serialNumber = serialNumber;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetVersion
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetVersion(
+ PKIX_ComCertSelParams *params,
+ PKIX_UInt32 *pVersion,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetVersion");
+ PKIX_NULLCHECK_TWO(params, pVersion);
+
+ *pVersion = params->version;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetVersion
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetVersion(
+ PKIX_ComCertSelParams *params,
+ PKIX_Int32 version,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetVersion");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->version = version;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubjKeyIdentifier
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubjKeyIdentifier(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray **pSubjKeyId,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetSubjKeyIdentifier");
+ PKIX_NULLCHECK_TWO(params, pSubjKeyId);
+
+ PKIX_INCREF(params->subjKeyId);
+
+ *pSubjKeyId = params->subjKeyId;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubjKeyIdentifier
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubjKeyIdentifier(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray *subjKeyId,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetSubjKeyIdentifier");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->subjKeyId);
+ PKIX_INCREF(subjKeyId);
+
+ params->subjKeyId = subjKeyId;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetAuthorityKeyIdentifier
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetAuthorityKeyIdentifier(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray **pAuthKeyId,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_GetAuthorityKeyIdentifier");
+ PKIX_NULLCHECK_TWO(params, pAuthKeyId);
+
+ PKIX_INCREF(params->authKeyId);
+
+ *pAuthKeyId = params->authKeyId;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetAuthorityKeyIdentifier
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetAuthorityKeyIdentifier(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_ByteArray *authKeyId,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetAuthKeyIdentifier");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->authKeyId);
+ PKIX_INCREF(authKeyId);
+
+ params->authKeyId = authKeyId;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubjPubKey
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubjPubKey(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_PublicKey **pSubjPubKey,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSubjPubKey");
+ PKIX_NULLCHECK_TWO(params, pSubjPubKey);
+
+ PKIX_INCREF(params->subjPubKey);
+
+ *pSubjPubKey = params->subjPubKey;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubjPubKey
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubjPubKey(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_PublicKey *subjPubKey,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS,
+ "PKIX_ComCertSelParams_SetSubjPubKey");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->subjPubKey);
+ PKIX_INCREF(subjPubKey);
+
+ params->subjPubKey = subjPubKey;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetSubjPKAlgId
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_GetSubjPKAlgId(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_OID **pAlgId,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetSubjPKAlgId");
+ PKIX_NULLCHECK_TWO(params, pAlgId);
+
+ PKIX_INCREF(params->subjPKAlgId);
+
+ *pAlgId = params->subjPKAlgId;
+
+cleanup:
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetSubjPKAlgId
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetSubjPKAlgId(
+ PKIX_ComCertSelParams *params,
+ PKIX_PL_OID *algId,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetSubjPKAlgId");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->subjPKAlgId);
+ PKIX_INCREF(algId);
+
+ params->subjPKAlgId = algId;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_GetLeafCertFlag
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error*
+PKIX_ComCertSelParams_GetLeafCertFlag(
+ PKIX_ComCertSelParams *params,
+ PKIX_Boolean *pLeafFlag,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_GetLeafCertFlag");
+ PKIX_NULLCHECK_TWO(params, pLeafFlag);
+
+ *pLeafFlag = params->leafCertFlag;
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCertSelParams_SetLeafCertFlag
+ * (see comments in pkix_certsel.h)
+ */
+PKIX_Error *
+PKIX_ComCertSelParams_SetLeafCertFlag(
+ PKIX_ComCertSelParams *params,
+ PKIX_Boolean leafFlag,
+ void *plContext)
+{
+ PKIX_ENTER(COMCERTSELPARAMS, "PKIX_ComCertSelParams_SetLeafCertFlag");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->leafCertFlag = leafFlag;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCERTSELPARAMS);
+}
diff --git a/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.h b/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.h
new file mode 100644
index 0000000000..935c639f0a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/certsel/pkix_comcertselparams.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/. */
+/*
+ * pkix_comcertselparams.h
+ *
+ * ComCertSelParams Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_COMCERTSELPARAMS_H
+#define _PKIX_COMCERTSELPARAMS_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * pathToNamesConstraint is Name Constraints generated based on the
+ * pathToNames. We save a cached copy to save regeneration for each
+ * check. SubjAltNames also has its cache, since SubjAltNames are
+ * verified by checker, its cache copy is stored in checkerstate.
+ */
+struct PKIX_ComCertSelParamsStruct {
+ PKIX_Int32 version;
+ PKIX_Int32 minPathLength;
+ PKIX_Boolean matchAllSubjAltNames;
+ PKIX_PL_X500Name *subject;
+ PKIX_List *policies; /* List of PKIX_PL_OID */
+ PKIX_PL_Cert *cert;
+ PKIX_PL_CertNameConstraints *nameConstraints;
+ PKIX_List *pathToNames; /* List of PKIX_PL_GeneralNames */
+ PKIX_List *subjAltNames; /* List of PKIX_PL_GeneralNames */
+ PKIX_List *extKeyUsage; /* List of PKIX_PL_OID */
+ PKIX_UInt32 keyUsage;
+ PKIX_PL_Date *date;
+ PKIX_PL_Date *certValid;
+ PKIX_PL_X500Name *issuer;
+ PKIX_PL_BigInt *serialNumber;
+ PKIX_PL_ByteArray *authKeyId;
+ PKIX_PL_ByteArray *subjKeyId;
+ PKIX_PL_PublicKey *subjPubKey;
+ PKIX_PL_OID *subjPKAlgId;
+ PKIX_Boolean leafCertFlag;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_ComCertSelParams_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_COMCERTSELPARAMS_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/Makefile b/security/nss/lib/libpkix/pkix/checker/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/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). #
+#######################################################################
+
+
+#######################################################################
+# (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/lib/libpkix/pkix/checker/checker.gyp b/security/nss/lib/libpkix/pkix/checker/checker.gyp
new file mode 100644
index 0000000000..ac260fc24d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/checker.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'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixchecker',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_basicconstraintschecker.c',
+ 'pkix_certchainchecker.c',
+ 'pkix_crlchecker.c',
+ 'pkix_ekuchecker.c',
+ 'pkix_expirationchecker.c',
+ 'pkix_namechainingchecker.c',
+ 'pkix_nameconstraintschecker.c',
+ 'pkix_ocspchecker.c',
+ 'pkix_policychecker.c',
+ 'pkix_revocationchecker.c',
+ 'pkix_revocationmethod.c',
+ 'pkix_signaturechecker.c',
+ 'pkix_targetcertchecker.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/checker/exports.gyp b/security/nss/lib/libpkix/pkix/checker/exports.gyp
new file mode 100644
index 0000000000..4bd68b39c1
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/exports.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': 'lib_libpkix_pkix_checker_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_basicconstraintschecker.h',
+ 'pkix_certchainchecker.h',
+ 'pkix_crlchecker.h',
+ 'pkix_ekuchecker.h',
+ 'pkix_expirationchecker.h',
+ 'pkix_namechainingchecker.h',
+ 'pkix_nameconstraintschecker.h',
+ 'pkix_ocspchecker.h',
+ 'pkix_policychecker.h',
+ 'pkix_revocationchecker.h',
+ 'pkix_revocationmethod.h',
+ 'pkix_signaturechecker.h',
+ 'pkix_targetcertchecker.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/manifest.mn b/security/nss/lib/libpkix/pkix/checker/manifest.mn
new file mode 100644
index 0000000000..84a372cea9
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/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 = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_basicconstraintschecker.h \
+ pkix_certchainchecker.h \
+ pkix_crlchecker.h \
+ pkix_ekuchecker.h \
+ pkix_expirationchecker.h \
+ pkix_namechainingchecker.h \
+ pkix_nameconstraintschecker.h \
+ pkix_ocspchecker.h \
+ pkix_policychecker.h \
+ pkix_revocationmethod.h \
+ pkix_revocationchecker.h \
+ pkix_signaturechecker.h \
+ pkix_targetcertchecker.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_basicconstraintschecker.c \
+ pkix_certchainchecker.c \
+ pkix_crlchecker.c \
+ pkix_ekuchecker.c \
+ pkix_expirationchecker.c \
+ pkix_namechainingchecker.c \
+ pkix_nameconstraintschecker.c \
+ pkix_ocspchecker.c \
+ pkix_revocationmethod.c \
+ pkix_revocationchecker.c \
+ pkix_policychecker.c \
+ pkix_signaturechecker.c \
+ pkix_targetcertchecker.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixchecker
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.c
new file mode 100644
index 0000000000..0e7a87997d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.c
@@ -0,0 +1,306 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_basicconstraintschecker.c
+ *
+ * Functions for basic constraints validation
+ *
+ */
+
+#include "pkix_basicconstraintschecker.h"
+
+/* --Private-BasicConstraintsCheckerState-Functions------------------------- */
+
+/*
+ * FUNCTION: pkix_BasicConstraintsCheckerState_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_BasicConstraintsCheckerState_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_BasicConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
+ "pkix_BasicConstraintsCheckerState_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a basic constraints checker state */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTBASICCONSTRAINTSCHECKERSTATE);
+
+ state = (pkix_BasicConstraintsCheckerState *)object;
+
+ PKIX_DECREF(state->basicConstraintsOID);
+
+cleanup:
+
+ PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_BasicConstraintsCheckerState_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERT_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_BasicConstraintsCheckerState_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
+ "pkix_BasicConstraintsCheckerState_RegisterSelf");
+
+ entry.description = "BasicConstraintsCheckerState";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(pkix_BasicConstraintsCheckerState);
+ entry.destructor = pkix_BasicConstraintsCheckerState_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE] = entry;
+
+ PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_BasicConstraintsCheckerState_Create
+ * DESCRIPTION:
+ *
+ * Creates a new BasicConstraintsCheckerState using the number of certs in
+ * the chain represented by "certsRemaining" and stores it at "pState".
+ *
+ * PARAMETERS:
+ * "certsRemaining"
+ * Number of certificates in the chain.
+ * "pState"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a BasicConstraintsCheckerState Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_BasicConstraintsCheckerState_Create(
+ PKIX_UInt32 certsRemaining,
+ pkix_BasicConstraintsCheckerState **pState,
+ void *plContext)
+{
+ pkix_BasicConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(BASICCONSTRAINTSCHECKERSTATE,
+ "pkix_BasicConstraintsCheckerState_Create");
+
+ PKIX_NULLCHECK_ONE(pState);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_BASICCONSTRAINTSCHECKERSTATE_TYPE,
+ sizeof (pkix_BasicConstraintsCheckerState),
+ (PKIX_PL_Object **)&state,
+ plContext),
+ PKIX_COULDNOTCREATEBASICCONSTRAINTSSTATEOBJECT);
+
+ /* initialize fields */
+ state->certsRemaining = certsRemaining;
+ state->maxPathLength = PKIX_UNLIMITED_PATH_CONSTRAINT;
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_BASICCONSTRAINTS_OID,
+ &state->basicConstraintsOID,
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ *pState = state;
+ state = NULL;
+
+cleanup:
+
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(BASICCONSTRAINTSCHECKERSTATE);
+}
+
+/* --Private-BasicConstraintsChecker-Functions------------------------------ */
+
+/*
+ * FUNCTION: pkix_BasicConstraintsChecker_Check
+ * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
+ */
+PKIX_Error *
+pkix_BasicConstraintsChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions, /* list of PKIX_PL_OID */
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
+ pkix_BasicConstraintsCheckerState *state = NULL;
+ PKIX_Boolean caFlag = PKIX_FALSE;
+ PKIX_Int32 pathLength = 0;
+ PKIX_Int32 maxPathLength_now;
+ PKIX_Boolean isSelfIssued = PKIX_FALSE;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_Check");
+ PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
+
+ *pNBIOContext = NULL; /* we never block on pending I/O */
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
+ (checker, (PKIX_PL_Object **)&state, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ state->certsRemaining--;
+
+ if (state->certsRemaining != 0) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
+ (cert, &basicConstraints, plContext),
+ PKIX_CERTGETBASICCONSTRAINTSFAILED);
+
+ /* get CA Flag and path length */
+ if (basicConstraints != NULL) {
+ PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag
+ (basicConstraints,
+ &caFlag,
+ plContext),
+ PKIX_BASICCONSTRAINTSGETCAFLAGFAILED);
+
+ if (caFlag == PKIX_TRUE) {
+ PKIX_CHECK
+ (PKIX_PL_BasicConstraints_GetPathLenConstraint
+ (basicConstraints,
+ &pathLength,
+ plContext),
+ PKIX_BASICCONSTRAINTSGETPATHLENCONSTRAINTFAILED);
+ }
+
+ }else{
+ caFlag = PKIX_FALSE;
+ pathLength = PKIX_UNLIMITED_PATH_CONSTRAINT;
+ }
+
+ PKIX_CHECK(pkix_IsCertSelfIssued
+ (cert,
+ &isSelfIssued,
+ plContext),
+ PKIX_ISCERTSELFISSUEDFAILED);
+
+ maxPathLength_now = state->maxPathLength;
+
+ if (isSelfIssued != PKIX_TRUE) {
+
+ /* Not last CA Cert, but maxPathLength is down to zero */
+ if (maxPathLength_now == 0) {
+ PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDLN);
+ }
+
+ if (caFlag == PKIX_FALSE) {
+ PKIX_ERROR(PKIX_BASICCONSTRAINTSVALIDATIONFAILEDCA);
+ }
+
+ if (maxPathLength_now > 0) { /* can be unlimited (-1) */
+ maxPathLength_now--;
+ }
+
+ }
+
+ if (caFlag == PKIX_TRUE) {
+ if (maxPathLength_now == PKIX_UNLIMITED_PATH_CONSTRAINT){
+ maxPathLength_now = pathLength;
+ } else {
+ /* If pathLength is not specified, don't set */
+ if (pathLength != PKIX_UNLIMITED_PATH_CONSTRAINT) {
+ maxPathLength_now =
+ (maxPathLength_now > pathLength)?
+ pathLength:maxPathLength_now;
+ }
+ }
+ }
+
+ state->maxPathLength = maxPathLength_now;
+ }
+
+ /* Remove Basic Constraints Extension OID from list */
+ if (unresolvedCriticalExtensions != NULL) {
+
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticalExtensions,
+ (PKIX_PL_Object *) state->basicConstraintsOID,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+ }
+
+
+ PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
+ (checker, (PKIX_PL_Object *)state, plContext),
+ PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
+
+
+cleanup:
+ PKIX_DECREF(state);
+ PKIX_DECREF(basicConstraints);
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_BasicConstraintsChecker_Initialize
+ * DESCRIPTION:
+ * Registers PKIX_CERT_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_BasicConstraintsChecker_Initialize(
+ PKIX_UInt32 certsRemaining,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ pkix_BasicConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_BasicConstraintsChecker_Initialize");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ PKIX_CHECK(pkix_BasicConstraintsCheckerState_Create
+ (certsRemaining, &state, plContext),
+ PKIX_BASICCONSTRAINTSCHECKERSTATECREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_BasicConstraintsChecker_Check,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *)state,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCHECKFAILED);
+
+cleanup:
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.h
new file mode 100644
index 0000000000..7a8b09c379
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_basicconstraintschecker.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/. */
+/*
+ * pkix_basicconstraintschecker.h
+ *
+ * Header file for basic constraints checker.
+ *
+ */
+
+#ifndef _PKIX_BASICCONSTRAINTSCHECKER_H
+#define _PKIX_BASICCONSTRAINTSCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkix_BasicConstraintsCheckerStateStruct \
+ pkix_BasicConstraintsCheckerState;
+
+struct pkix_BasicConstraintsCheckerStateStruct{
+ PKIX_PL_OID *basicConstraintsOID;
+ PKIX_Int32 certsRemaining;
+ PKIX_Int32 maxPathLength;
+};
+
+PKIX_Error *
+pkix_BasicConstraintsChecker_Initialize(
+ PKIX_UInt32 numCerts,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+PKIX_Error *
+pkix_BasicConstraintsCheckerState_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_BASICCONSTRAINTSCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.c
new file mode 100644
index 0000000000..a6ea50d02d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.c
@@ -0,0 +1,322 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_certchainchecker.c
+ *
+ * CertChainChecker Object Functions
+ *
+ */
+
+#include "pkix_certchainchecker.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_CertChainChecker_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertChainChecker_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_CertChainChecker *checker = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_CertChainChecker_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a cert chain checker */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTCHAINCHECKER_TYPE, plContext),
+ PKIX_OBJECTNOTCERTCHAINCHECKER);
+
+ checker = (PKIX_CertChainChecker *)object;
+
+ PKIX_DECREF(checker->extensions);
+ PKIX_DECREF(checker->state);
+
+cleanup:
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_CertChainChecker_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertChainChecker_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_CertChainChecker *checker = NULL;
+ PKIX_CertChainChecker *checkerDuplicate = NULL;
+ PKIX_List *extensionsDuplicate = NULL;
+ PKIX_PL_Object *stateDuplicate = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_CertChainChecker_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTCHAINCHECKER_TYPE, plContext),
+ PKIX_OBJECTNOTCERTCHAINCHECKER);
+
+ checker = (PKIX_CertChainChecker *)object;
+
+ if (checker->extensions){
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)checker->extensions,
+ (PKIX_PL_Object **)&extensionsDuplicate,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+ }
+
+ if (checker->state){
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)checker->state,
+ (PKIX_PL_Object **)&stateDuplicate,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (checker->checkCallback,
+ checker->forwardChecking,
+ checker->isForwardDirectionExpected,
+ extensionsDuplicate,
+ stateDuplicate,
+ &checkerDuplicate,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)checkerDuplicate;
+
+cleanup:
+
+ PKIX_DECREF(extensionsDuplicate);
+ PKIX_DECREF(stateDuplicate);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_CertChainChecker_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTCHAINCHECKER_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_CertChainChecker_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_CertChainChecker_RegisterSelf");
+
+ entry.description = "CertChainChecker";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_CertChainChecker);
+ entry.destructor = pkix_CertChainChecker_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_CertChainChecker_Duplicate;
+
+ systemClasses[PKIX_CERTCHAINCHECKER_TYPE] = entry;
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_Create (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_Create(
+ PKIX_CertChainChecker_CheckCallback callback,
+ PKIX_Boolean forwardCheckingSupported,
+ PKIX_Boolean isForwardDirectionExpected,
+ PKIX_List *list, /* list of PKIX_PL_OID */
+ PKIX_PL_Object *initialState,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ PKIX_CertChainChecker *checker = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "PKIX_CertChainChecker_Create");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTCHAINCHECKER_TYPE,
+ sizeof (PKIX_CertChainChecker),
+ (PKIX_PL_Object **)&checker,
+ plContext),
+ PKIX_COULDNOTCREATECERTCHAINCHECKEROBJECT);
+
+ /* initialize fields */
+ checker->checkCallback = callback;
+ checker->forwardChecking = forwardCheckingSupported;
+ checker->isForwardDirectionExpected = isForwardDirectionExpected;
+
+ PKIX_INCREF(list);
+ checker->extensions = list;
+
+ PKIX_INCREF(initialState);
+ checker->state = initialState;
+
+ *pChecker = checker;
+ checker = NULL;
+cleanup:
+
+ PKIX_DECREF(checker);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_GetCheckCallback
+ * (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_GetCheckCallback(
+ PKIX_CertChainChecker *checker,
+ PKIX_CertChainChecker_CheckCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTCHAINCHECKER, "PKIX_CertChainChecker_GetCheckCallback");
+ PKIX_NULLCHECK_TWO(checker, pCallback);
+
+ *pCallback = checker->checkCallback;
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_IsForwardCheckingSupported
+ * (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_IsForwardCheckingSupported(
+ PKIX_CertChainChecker *checker,
+ PKIX_Boolean *pForwardCheckingSupported,
+ void *plContext)
+{
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "PKIX_CertChainChecker_IsForwardCheckingSupported");
+ PKIX_NULLCHECK_TWO(checker, pForwardCheckingSupported);
+
+ *pForwardCheckingSupported = checker->forwardChecking;
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_IsForwardDirectionExpected
+ * (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_IsForwardDirectionExpected(
+ PKIX_CertChainChecker *checker,
+ PKIX_Boolean *pForwardDirectionExpected,
+ void *plContext)
+{
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "PKIX_CertChainChecker_IsForwardDirectionExpected");
+ PKIX_NULLCHECK_TWO(checker, pForwardDirectionExpected);
+
+ *pForwardDirectionExpected = checker->isForwardDirectionExpected;
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_GetCertChainCheckerState
+ * (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_GetCertChainCheckerState(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Object **pCertChainCheckerState,
+ void *plContext)
+{
+ PKIX_ENTER(CERTCHAINCHECKER,
+ "PKIX_CertChainChecker_GetCertChainCheckerState");
+
+ PKIX_NULLCHECK_TWO(checker, pCertChainCheckerState);
+
+ PKIX_INCREF(checker->state);
+
+ *pCertChainCheckerState = checker->state;
+
+cleanup:
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_SetCertChainCheckerState
+ * (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_SetCertChainCheckerState(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Object *certChainCheckerState,
+ void *plContext)
+{
+ PKIX_ENTER(CERTCHAINCHECKER,
+ "PKIX_CertChainChecker_SetCertChainCheckerState");
+
+ PKIX_NULLCHECK_ONE(checker);
+
+ /* DecRef old contents */
+ PKIX_DECREF(checker->state);
+
+ PKIX_INCREF(certChainCheckerState);
+ checker->state = certChainCheckerState;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)checker, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_CertChainChecker_GetSupportedExtensions
+ * (see comments in pkix_checker.h)
+ */
+PKIX_Error *
+PKIX_CertChainChecker_GetSupportedExtensions(
+ PKIX_CertChainChecker *checker,
+ PKIX_List **pExtensions, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_ENTER(CERTCHAINCHECKER,
+ "PKIX_CertChainChecker_GetSupportedExtensions");
+
+ PKIX_NULLCHECK_TWO(checker, pExtensions);
+
+ PKIX_INCREF(checker->extensions);
+
+ *pExtensions = checker->extensions;
+
+cleanup:
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.h
new file mode 100644
index 0000000000..ff6454761e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_certchainchecker.h
@@ -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/. */
+/*
+ * pkix_certchainchecker.h
+ *
+ * CertChainChecker Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_CERTCHAINCHECKER_H
+#define _PKIX_CERTCHAINCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_CertChainCheckerStruct {
+ PKIX_CertChainChecker_CheckCallback checkCallback;
+ PKIX_List *extensions;
+ PKIX_PL_Object *state;
+ PKIX_Boolean forwardChecking;
+ PKIX_Boolean isForwardDirectionExpected;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_CertChainChecker_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_CERTCHAINCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c
new file mode 100644
index 0000000000..d6f5b6bcc8
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.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/. */
+/*
+ * pkix_defaultcrlchecker.c
+ *
+ * Functions for default CRL Checkers
+ *
+ */
+#include "pkix.h"
+#include "pkix_crlchecker.h"
+#include "pkix_tools.h"
+
+/* --Private-CRLChecker-Data-and-Types------------------------------- */
+
+typedef struct pkix_CrlCheckerStruct {
+ /* RevocationMethod is the super class of CrlChecker. */
+ pkix_RevocationMethod method;
+ PKIX_List *certStores; /* list of CertStore */
+ PKIX_PL_VerifyCallback crlVerifyFn;
+} pkix_CrlChecker;
+
+
+/* --Private-CRLChecker-Functions----------------------------------- */
+
+/*
+ * FUNCTION: pkix_CrlCheckerstate_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CrlChecker_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_CrlChecker *state = NULL;
+
+ PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a default CRL checker state */
+ PKIX_CHECK(
+ pkix_CheckType(object, PKIX_CRLCHECKER_TYPE, plContext),
+ PKIX_OBJECTNOTCRLCHECKER);
+
+ state = (pkix_CrlChecker *)object;
+
+ PKIX_DECREF(state->certStores);
+
+cleanup:
+
+ PKIX_RETURN(CRLCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_CrlChecker_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_CRLCHECKER_TYPE and its related functions
+ * with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_CrlChecker_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry* entry = &systemClasses[PKIX_CRLCHECKER_TYPE];
+
+ PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_RegisterSelf");
+
+ entry->description = "CRLChecker";
+ entry->typeObjectSize = sizeof(pkix_CrlChecker);
+ entry->destructor = pkix_CrlChecker_Destroy;
+
+ PKIX_RETURN(CRLCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_CrlChecker_Create
+ *
+ * DESCRIPTION:
+ * Allocate and initialize CRLChecker state data.
+ *
+ * PARAMETERS
+ * "certStores"
+ * Address of CertStore List to be stored in state. Must be non-NULL.
+ * "testDate"
+ * Address of PKIX_PL_Date to be checked. May be NULL.
+ * "trustedPubKey"
+ * Trusted Anchor Public Key for verifying first Cert in the chain.
+ * Must be non-NULL.
+ * "certsRemaining"
+ * Number of certificates remaining in the chain.
+ * "nistCRLPolicyEnabled"
+ * If enabled, enforce nist crl policy.
+ * "pChecker"
+ * Address of CRLChecker that is returned. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a DefaultCrlChecker Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error
+ */
+PKIX_Error *
+pkix_CrlChecker_Create(PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 flags,
+ PKIX_UInt32 priority,
+ pkix_LocalRevocationCheckFn localRevChecker,
+ pkix_ExternalRevocationCheckFn externalRevChecker,
+ PKIX_List *certStores,
+ PKIX_PL_VerifyCallback crlVerifyFn,
+ pkix_RevocationMethod **pChecker,
+ void *plContext)
+{
+ pkix_CrlChecker *crlChecker = NULL;
+
+ PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_Create");
+ PKIX_NULLCHECK_TWO(certStores, pChecker);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CRLCHECKER_TYPE,
+ sizeof (pkix_CrlChecker),
+ (PKIX_PL_Object **)&crlChecker,
+ plContext),
+ PKIX_COULDNOTCREATECRLCHECKEROBJECT);
+
+ pkixErrorResult = pkix_RevocationMethod_Init(
+ (pkix_RevocationMethod*)crlChecker, methodType, flags, priority,
+ localRevChecker, externalRevChecker, plContext);
+ if (pkixErrorResult) {
+ goto cleanup;
+ }
+
+ /* Initialize fields */
+ PKIX_INCREF(certStores);
+ crlChecker->certStores = certStores;
+
+ crlChecker->crlVerifyFn = crlVerifyFn;
+ *pChecker = (pkix_RevocationMethod*)crlChecker;
+ crlChecker = NULL;
+
+cleanup:
+ PKIX_DECREF(crlChecker);
+
+ PKIX_RETURN(CRLCHECKER);
+}
+
+/* --Private-CRLChecker-Functions------------------------------------ */
+
+/*
+ * FUNCTION: pkix_CrlChecker_CheckLocal
+ *
+ * DESCRIPTION:
+ * Check if the Cert has been revoked based the CRLs data. This function
+ * maintains the checker state to be current.
+ *
+ * PARAMETERS
+ * "checker"
+ * Address of CertChainChecker which has the state data.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Certificate that is to be validated. Must be non-NULL.
+ * "unreslvdCrtExts"
+ * A List OIDs. Not **yet** used in this checker function.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error
+ */
+PKIX_Error *
+pkix_CrlChecker_CheckLocal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean chainVerificationState,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *pReasonCode,
+ void *plContext)
+{
+ PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn;
+ PKIX_CertStore *certStore = NULL;
+ pkix_CrlChecker *state = NULL;
+ PKIX_UInt32 crlStoreIndex = 0;
+ PKIX_UInt32 numCrlStores = 0;
+ PKIX_Boolean storeIsLocal = PKIX_FALSE;
+ PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckLocal");
+ PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, checkerObject);
+
+ state = (pkix_CrlChecker*)checkerObject;
+
+ PKIX_CHECK(
+ PKIX_List_GetLength(state->certStores, &numCrlStores, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (;crlStoreIndex < numCrlStores;crlStoreIndex++) {
+ PKIX_CHECK(
+ PKIX_List_GetItem(state->certStores, crlStoreIndex,
+ (PKIX_PL_Object **)&certStore,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(
+ PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal,
+ plContext),
+ PKIX_CERTSTOREGETLOCALFLAGFAILED);
+ if (storeIsLocal) {
+ PKIX_CHECK(
+ PKIX_CertStore_GetCrlCheckerFn(certStore,
+ &storeCheckRevocationFn,
+ plContext),
+ PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);
+
+ if (storeCheckRevocationFn) {
+ PKIX_CHECK(
+ (*storeCheckRevocationFn)(certStore, cert, issuer,
+ /* delay sig check if building
+ * a chain by not specifying the time*/
+ chainVerificationState ? date : NULL,
+ /* crl downloading is not done. */
+ PKIX_FALSE,
+ pReasonCode, &revStatus, plContext),
+ PKIX_CERTSTORECRLCHECKFAILED);
+ if (revStatus == PKIX_RevStatus_Revoked) {
+ break;
+ }
+ }
+ }
+ PKIX_DECREF(certStore);
+ } /* while */
+
+cleanup:
+ *pRevStatus = revStatus;
+ PKIX_DECREF(certStore);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_CrlChecker_CheckRemote
+ *
+ * DESCRIPTION:
+ * Check if the Cert has been revoked based the CRLs data. This function
+ * maintains the checker state to be current.
+ *
+ * PARAMETERS
+ * "checker"
+ * Address of CertChainChecker which has the state data.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Certificate that is to be validated. Must be non-NULL.
+ * "unreslvdCrtExts"
+ * A List OIDs. Not **yet** used in this checker function.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error
+ */
+PKIX_Error *
+pkix_CrlChecker_CheckExternal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *pReasonCode,
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn = NULL;
+ PKIX_CertStore_ImportCrlCallback storeImportCrlFn = NULL;
+ PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertStore *localStore = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+ PKIX_PL_X500Name *issuerName = NULL;
+ pkix_CrlChecker *state = NULL;
+ PKIX_UInt32 crlStoreIndex = 0;
+ PKIX_UInt32 numCrlStores = 0;
+ PKIX_Boolean storeIsLocal = PKIX_FALSE;
+ PKIX_List *crlList = NULL;
+ PKIX_List *dpList = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckExternal");
+ PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, pNBIOContext);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL; /* prepare for Error exit */
+
+ state = (pkix_CrlChecker*)checkerObject;
+
+ PKIX_CHECK(
+ PKIX_List_GetLength(state->certStores, &numCrlStores, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ /* Find a cert store that is capable of storing crls */
+ for (;crlStoreIndex < numCrlStores;crlStoreIndex++) {
+ PKIX_CHECK(
+ PKIX_List_GetItem(state->certStores, crlStoreIndex,
+ (PKIX_PL_Object **)&certStore,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(
+ PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal,
+ plContext),
+ PKIX_CERTSTOREGETLOCALFLAGFAILED);
+ if (storeIsLocal) {
+ PKIX_CHECK(
+ PKIX_CertStore_GetImportCrlCallback(certStore,
+ &storeImportCrlFn,
+ plContext),
+ PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);
+
+ PKIX_CHECK(
+ PKIX_CertStore_GetCrlCheckerFn(certStore,
+ &storeCheckRevocationFn,
+ plContext),
+ PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);
+
+ if (storeImportCrlFn && storeCheckRevocationFn) {
+ localStore = certStore;
+ certStore = NULL;
+ break;
+ }
+ }
+ PKIX_DECREF(certStore);
+ } /* while */
+
+ /* Report unknown status if we can not check crl in one of the
+ * local stores. */
+ if (!localStore) {
+ PKIX_ERROR_FATAL(PKIX_CRLCHECKERNOLOCALCERTSTOREFOUND);
+ }
+ PKIX_CHECK(
+ PKIX_PL_Cert_VerifyKeyUsage(issuer, PKIX_CRL_SIGN, plContext),
+ PKIX_CERTCHECKKEYUSAGEFAILED);
+ PKIX_CHECK(
+ PKIX_PL_Cert_GetCrlDp(cert, &dpList, plContext),
+ PKIX_CERTGETCRLDPFAILED);
+ if (!(methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) &&
+ (!dpList || !dpList->length)) {
+ goto cleanup;
+ }
+ PKIX_CHECK(
+ PKIX_PL_Cert_GetIssuer(cert, &issuerName, plContext),
+ PKIX_CERTGETISSUERFAILED);
+ PKIX_CHECK(
+ PKIX_CRLSelector_Create(issuer, dpList, date, &crlSelector, plContext),
+ PKIX_CRLCHECKERSETSELECTORFAILED);
+ /* Fetch crl and store in a local cert store */
+ for (crlStoreIndex = 0;crlStoreIndex < numCrlStores;crlStoreIndex++) {
+ PKIX_CertStore_CRLCallback getCrlsFn;
+
+ PKIX_CHECK(
+ PKIX_List_GetItem(state->certStores, crlStoreIndex,
+ (PKIX_PL_Object **)&certStore,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(
+ PKIX_CertStore_GetCRLCallback(certStore, &getCrlsFn,
+ plContext),
+ PKIX_CERTSTOREGETCRLCALLBACKFAILED);
+
+ PKIX_CHECK(
+ (*getCrlsFn)(certStore, crlSelector, &nbioContext,
+ &crlList, plContext),
+ PKIX_GETCRLSFAILED);
+
+ PKIX_CHECK(
+ (*storeImportCrlFn)(localStore, issuerName, crlList, plContext),
+ PKIX_CERTSTOREFAILTOIMPORTCRLLIST);
+
+ PKIX_CHECK(
+ (*storeCheckRevocationFn)(certStore, cert, issuer, date,
+ /* done with crl downloading */
+ PKIX_TRUE,
+ pReasonCode, &revStatus, plContext),
+ PKIX_CERTSTORECRLCHECKFAILED);
+ if (revStatus != PKIX_RevStatus_NoInfo) {
+ break;
+ }
+ PKIX_DECREF(crlList);
+ PKIX_DECREF(certStore);
+ } /* while */
+
+cleanup:
+ /* Update return flags */
+ if (revStatus == PKIX_RevStatus_NoInfo &&
+ ((dpList && dpList->length > 0) ||
+ (methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE)) &&
+ methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
+ revStatus = PKIX_RevStatus_Revoked;
+ }
+ *pRevStatus = revStatus;
+
+ PKIX_DECREF(dpList);
+ PKIX_DECREF(crlList);
+ PKIX_DECREF(certStore);
+ PKIX_DECREF(issuerName);
+ PKIX_DECREF(localStore);
+ PKIX_DECREF(crlSelector);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.h
new file mode 100644
index 0000000000..35f1a47455
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.h
@@ -0,0 +1,68 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_defaultcrlchecker.h
+ *
+ * Header file for default CRL function
+ *
+ */
+
+#ifndef _PKIX_CRLCHECKER_H
+#define _PKIX_CRLCHECKER_H
+
+#include "pkixt.h"
+#include "pkix_revocationmethod.h"
+#include "pkix_crlsel.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: nbio logic removed. Will be replaced later. */
+
+PKIX_Error *
+pkix_CrlChecker_CheckLocal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean chainVerificationState,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *reasonCode,
+ void *plContext);
+
+PKIX_Error *
+pkix_CrlChecker_CheckExternal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *reasonCode,
+ void **pNBIOContext,
+ void *plContext);
+
+PKIX_Error *
+pkix_CrlChecker_Create(PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 flags,
+ PKIX_UInt32 priority,
+ pkix_LocalRevocationCheckFn localRevChecker,
+ pkix_ExternalRevocationCheckFn externalRevChecker,
+ PKIX_List *certStores,
+ PKIX_PL_VerifyCallback crlVerifyFn,
+ pkix_RevocationMethod **pChecker,
+ void *plContext);
+
+PKIX_Error *
+pkix_CrlChecker_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_CRLCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c
new file mode 100644
index 0000000000..a2b8437397
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.c
@@ -0,0 +1,328 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_ekuchecker.c
+ *
+ * User Defined ExtenedKeyUsage Function Definitions
+ *
+ */
+
+#include "pkix_ekuchecker.h"
+
+SECOidTag ekuOidStrings[] = {
+ PKIX_KEY_USAGE_SERVER_AUTH_OID,
+ PKIX_KEY_USAGE_CLIENT_AUTH_OID,
+ PKIX_KEY_USAGE_CODE_SIGN_OID,
+ PKIX_KEY_USAGE_EMAIL_PROTECT_OID,
+ PKIX_KEY_USAGE_TIME_STAMP_OID,
+ PKIX_KEY_USAGE_OCSP_RESPONDER_OID,
+ PKIX_UNKNOWN_OID
+};
+
+typedef struct pkix_EkuCheckerStruct {
+ PKIX_List *requiredExtKeyUsageOids;
+ PKIX_PL_OID *ekuOID;
+} pkix_EkuChecker;
+
+
+/*
+ * FUNCTION: pkix_EkuChecker_Destroy
+ * (see comments for PKIX_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_EkuChecker_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_EkuChecker *ekuCheckerState = NULL;
+
+ PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_EKUCHECKER_TYPE, plContext),
+ PKIX_OBJECTNOTANEKUCHECKERSTATE);
+
+ ekuCheckerState = (pkix_EkuChecker *)object;
+
+ PKIX_DECREF(ekuCheckerState->ekuOID);
+ PKIX_DECREF(ekuCheckerState->requiredExtKeyUsageOids);
+
+cleanup:
+
+ PKIX_RETURN(EKUCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_EkuChecker_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_PL_HTTPCERTSTORECONTEXT_TYPE and its related
+ * functions with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_EkuChecker_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry *entry = &systemClasses[PKIX_EKUCHECKER_TYPE];
+
+ PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_RegisterSelf");
+
+ entry->description = "EkuChecker";
+ entry->typeObjectSize = sizeof(pkix_EkuChecker);
+ entry->destructor = pkix_EkuChecker_Destroy;
+
+ PKIX_RETURN(EKUCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_EkuChecker_Create
+ * DESCRIPTION:
+ *
+ * Creates a new Extend Key Usage CheckerState using "params" to retrieve
+ * application specified EKU for verification and stores it at "pState".
+ *
+ * PARAMETERS:
+ * "params"
+ * a PKIX_ProcessingParams links to PKIX_ComCertSelParams where a list of
+ * Extended Key Usage OIDs specified by application can be retrieved for
+ * verification.
+ * "pState"
+ * Address where state pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a UserDefinedModules Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_EkuChecker_Create(
+ PKIX_ProcessingParams *params,
+ pkix_EkuChecker **pState,
+ void *plContext)
+{
+ pkix_EkuChecker *state = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_ComCertSelParams *comCertSelParams = NULL;
+ PKIX_List *requiredOids = NULL;
+
+ PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Create");
+ PKIX_NULLCHECK_TWO(params, pState);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_EKUCHECKER_TYPE,
+ sizeof (pkix_EkuChecker),
+ (PKIX_PL_Object **)&state,
+ plContext),
+ PKIX_COULDNOTCREATEEKUCHECKERSTATEOBJECT);
+
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
+ (params, &certSelector, plContext),
+ PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
+
+ if (certSelector != NULL) {
+
+ /* Get initial EKU OIDs from ComCertSelParams, if set */
+ PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
+ (certSelector, &comCertSelParams, plContext),
+ PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
+
+ if (comCertSelParams != NULL) {
+ PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
+ (comCertSelParams, &requiredOids, plContext),
+ PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
+
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_EXTENDEDKEYUSAGE_OID,
+ &state->ekuOID,
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ state->requiredExtKeyUsageOids = requiredOids;
+ requiredOids = NULL;
+ *pState = state;
+ state = NULL;
+
+cleanup:
+
+ PKIX_DECREF(certSelector);
+ PKIX_DECREF(comCertSelParams);
+ PKIX_DECREF(requiredOids);
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(EKUCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_EkuChecker_Check
+ * DESCRIPTION:
+ *
+ * This function determines the Extended Key Usage OIDs specified by the
+ * application is included in the Extended Key Usage OIDs of this "cert".
+ *
+ * PARAMETERS:
+ * "checker"
+ * Address of CertChainChecker which has the state data.
+ * Must be non-NULL.
+ * "cert"
+ * Address of Certificate that is to be validated. Must be non-NULL.
+ * "unresolvedCriticalExtensions"
+ * A List OIDs. The OID for Extended Key Usage is removed.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a UserDefinedModules Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_EkuChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ pkix_EkuChecker *state = NULL;
+ PKIX_List *requiredExtKeyUsageList = NULL;
+ PKIX_List *certExtKeyUsageList = NULL;
+ PKIX_PL_OID *ekuOid = NULL;
+ PKIX_Boolean isContained = PKIX_FALSE;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+ PKIX_Boolean checkResult = PKIX_TRUE;
+
+ PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Check");
+ PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
+
+ *pNBIOContext = NULL; /* no non-blocking IO */
+
+ PKIX_CHECK(
+ PKIX_CertChainChecker_GetCertChainCheckerState
+ (checker, (PKIX_PL_Object **)&state, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ requiredExtKeyUsageList = state->requiredExtKeyUsageOids;
+ if (requiredExtKeyUsageList == NULL) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(
+ PKIX_List_GetLength(requiredExtKeyUsageList, &numItems,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ if (numItems == 0) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(
+ PKIX_PL_Cert_GetExtendedKeyUsage(cert, &certExtKeyUsageList,
+ plContext),
+ PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
+
+ if (certExtKeyUsageList == NULL) {
+ goto cleanup;
+ }
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(
+ PKIX_List_GetItem(requiredExtKeyUsageList, i,
+ (PKIX_PL_Object **)&ekuOid, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(
+ pkix_List_Contains(certExtKeyUsageList,
+ (PKIX_PL_Object *)ekuOid,
+ &isContained,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ PKIX_DECREF(ekuOid);
+ if (isContained != PKIX_TRUE) {
+ checkResult = PKIX_FALSE;
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (!pkixErrorResult && checkResult == PKIX_FALSE) {
+ pkixErrorReceived = PKIX_TRUE;
+ pkixErrorCode = PKIX_EXTENDEDKEYUSAGECHECKINGFAILED;
+ }
+
+ PKIX_DECREF(ekuOid);
+ PKIX_DECREF(certExtKeyUsageList);
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(EKUCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_EkuChecker_Initialize
+ * (see comments in pkix_sample_modules.h)
+ */
+PKIX_Error *
+PKIX_EkuChecker_Create(
+ PKIX_ProcessingParams *params,
+ PKIX_CertChainChecker **pEkuChecker,
+ void *plContext)
+{
+ pkix_EkuChecker *state = NULL;
+ PKIX_List *critExtOIDsList = NULL;
+
+ PKIX_ENTER(EKUCHECKER, "PKIX_EkuChecker_Initialize");
+ PKIX_NULLCHECK_ONE(params);
+
+ /*
+ * This function and functions in this file provide an example of how
+ * an application defined checker can be hooked into libpkix.
+ */
+
+ PKIX_CHECK(pkix_EkuChecker_Create
+ (params, &state, plContext),
+ PKIX_EKUCHECKERSTATECREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&critExtOIDsList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (critExtOIDsList,
+ (PKIX_PL_Object *)state->ekuOID,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_EkuChecker_Check,
+ PKIX_TRUE, /* forwardCheckingSupported */
+ PKIX_FALSE, /* forwardDirectionExpected */
+ critExtOIDsList,
+ (PKIX_PL_Object *) state,
+ pEkuChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+cleanup:
+
+ PKIX_DECREF(critExtOIDsList);
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(EKUCHECKER);
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.h
new file mode 100644
index 0000000000..e542dda20b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_ekuchecker.h
@@ -0,0 +1,92 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_ekuchecker.h
+ *
+ * User Defined Object Type Extended Key Usage Definition
+ *
+ */
+
+#ifndef _PKIX_EKUCHECKER_H
+#define _PKIX_EKUCHECKER_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * FUNCTION: PKIX_PL_EkuChecker_Create
+ *
+ * DESCRIPTION:
+ * Create a CertChainChecker with EkuCheckerState and add it into
+ * PKIX_ProcessingParams object.
+ *
+ * PARAMETERS
+ * "params"
+ * a PKIX_ProcessingParams links to PKIX_ComCertSelParams where a list of
+ * Extended Key Usage OIDs specified by application can be retrieved for
+ * verification.
+ * "ekuChecker"
+ * Address of created ekuchecker.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a UserDefinedModules Error if the function fails in a non-fatal
+ * way.
+ * Returns a Fatal Error
+ */
+PKIX_Error *
+PKIX_EkuChecker_Create(
+ PKIX_ProcessingParams *params,
+ PKIX_CertChainChecker **ekuChecker,
+ void *plContext);
+
+/*
+ * FUNCTION: PKIX_PL_EkuChecker_GetRequiredEku
+ *
+ * DESCRIPTION:
+ * This function retrieves application specified ExtenedKeyUsage(s) from
+ * ComCertSetparams and converts its OID representations to SECCertUsageEnum.
+ * The result is stored and returned in bit mask at "pRequiredExtKeyUsage".
+ *
+ * PARAMETERS
+ * "certSelector"
+ * a PKIX_CertSelector links to PKIX_ComCertSelParams where a list of
+ * Extended Key Usage OIDs specified by application can be retrieved for
+ * verification. Must be non-NULL.
+ * "pRequiredExtKeyUsage"
+ * Address where the result is returned. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a UserDefinedModules Error if the function fails in a non-fatal
+ * way.
+ * Returns a Fatal Error
+ */
+PKIX_Error *
+pkix_EkuChecker_GetRequiredEku(
+ PKIX_CertSelector *certSelector,
+ PKIX_UInt32 *pRequiredExtKeyUsage,
+ void *plContext);
+
+/* see source file for function documentation */
+PKIX_Error *pkix_EkuChecker_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_EKUCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.c
new file mode 100644
index 0000000000..4f101ee29b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.c
@@ -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/. */
+/*
+ * pkix_expirationchecker.c
+ *
+ * Functions for expiration validation
+ *
+ */
+
+
+#include "pkix_expirationchecker.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_ExpirationChecker_Check
+ * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
+ */
+PKIX_Error *
+pkix_ExpirationChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_PL_Date *testDate = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_ExpirationChecker_Check");
+ PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
+
+ *pNBIOContext = NULL; /* we never block on pending I/O */
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
+ (checker, (PKIX_PL_Object **)&testDate, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_CheckValidity(cert, testDate, plContext),
+ PKIX_CERTCHECKVALIDITYFAILED);
+
+cleanup:
+
+ PKIX_DECREF(testDate);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_ExpirationChecker_Initialize
+ * DESCRIPTION:
+ *
+ * Creates a new CertChainChecker and stores it at "pChecker", where it will
+ * used by pkix_ExpirationChecker_Check to check that the certificate has not
+ * expired with respect to the Date pointed to by "testDate." If "testDate"
+ * is NULL, then the CertChainChecker will check that a certificate has not
+ * expired with respect to the current date and time.
+ *
+ * PARAMETERS:
+ * "testDate"
+ * Address of Date representing the point in time at which the cert is to
+ * be validated. If "testDate" is NULL, the current date and time is used.
+ * "pChecker"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_ExpirationChecker_Initialize(
+ PKIX_PL_Date *testDate,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ PKIX_PL_Date *myDate = NULL;
+ PKIX_PL_Date *nowDate = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_ExpirationChecker_Initialize");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ /* if testDate is NULL, we use the current time */
+ if (!testDate){
+ PKIX_CHECK(PKIX_PL_Date_Create_UTCTime
+ (NULL, &nowDate, plContext),
+ PKIX_DATECREATEUTCTIMEFAILED);
+ myDate = nowDate;
+ } else {
+ myDate = testDate;
+ }
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_ExpirationChecker_Check,
+ PKIX_TRUE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *)myDate,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(nowDate);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.h
new file mode 100644
index 0000000000..17b5c1bc10
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_expirationchecker.h
@@ -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/. */
+/*
+ * pkix_expirationchecker.h
+ *
+ * Header file for validate expiration function
+ *
+ */
+
+#ifndef _PKIX_EXPIRATIONCHECKER_H
+#define _PKIX_EXPIRATIONCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PKIX_Error *
+pkix_ExpirationChecker_Initialize(
+ PKIX_PL_Date *testDate,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_EXPIRATIONCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.c
new file mode 100644
index 0000000000..873d19cd05
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.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/. */
+/*
+ * pkix_namechainingchecker.c
+ *
+ * Functions for name chaining validation
+ *
+ */
+
+
+#include "pkix_namechainingchecker.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_NameChainingChecker_Check
+ * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
+ */
+PKIX_Error *
+pkix_NameChainingChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_PL_X500Name *prevSubject = NULL;
+ PKIX_PL_X500Name *currIssuer = NULL;
+ PKIX_PL_X500Name *currSubject = NULL;
+ PKIX_Boolean result;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameChainingChecker_Check");
+ PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
+
+ *pNBIOContext = NULL; /* we never block on pending I/O */
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
+ (checker, (PKIX_PL_Object **)&prevSubject, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetIssuer(cert, &currIssuer, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ if (prevSubject){
+ PKIX_CHECK(PKIX_PL_X500Name_Match
+ (prevSubject, currIssuer, &result, plContext),
+ PKIX_X500NAMEMATCHFAILED);
+ if (!result){
+ PKIX_ERROR(PKIX_NAMECHAININGCHECKFAILED);
+ }
+ } else {
+ PKIX_ERROR(PKIX_NAMECHAININGCHECKFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &currSubject, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
+ (checker, (PKIX_PL_Object *)currSubject, plContext),
+ PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(prevSubject);
+ PKIX_DECREF(currIssuer);
+ PKIX_DECREF(currSubject);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_NameChainingChecker_Initialize
+ * DESCRIPTION:
+ *
+ * Creates a new CertChainChecker and stores it at "pChecker", where it will
+ * be used by pkix_NameChainingChecker_Check to check that the issuer name
+ * of the certificate matches the subject name in the checker's state. The
+ * X500Name pointed to by "trustedCAName" is used to initialize the checker's
+ * state.
+ *
+ * PARAMETERS:
+ * "trustedCAName"
+ * Address of X500Name representing the trusted CA Name used to
+ * initialize the state of this checker. Must be non-NULL.
+ * "pChecker"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_NameChainingChecker_Initialize(
+ PKIX_PL_X500Name *trustedCAName,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ PKIX_ENTER(CERTCHAINCHECKER, "PKIX_NameChainingChecker_Initialize");
+ PKIX_NULLCHECK_TWO(pChecker, trustedCAName);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_NameChainingChecker_Check,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *)trustedCAName,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.h
new file mode 100644
index 0000000000..bc413f4561
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_namechainingchecker.h
@@ -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/. */
+/*
+ * pkix_namechainingchecker.h
+ *
+ * Header file for name chaining checker.
+ *
+ */
+
+#ifndef _PKIX_NAMECHAININGCHECKER_H
+#define _PKIX_NAMECHAININGCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PKIX_Error *
+pkix_NameChainingChecker_Initialize(
+ PKIX_PL_X500Name *trustedCAName,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_NAMECHAININGCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c
new file mode 100644
index 0000000000..28f21a6c2d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.c
@@ -0,0 +1,340 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_nameconstraintschecker.c
+ *
+ * Functions for Name Constraints Checkers
+ *
+ */
+
+#include "pkix_nameconstraintschecker.h"
+
+/* --Private-NameConstraintsCheckerState-Functions---------------------- */
+
+/*
+ * FUNCTION: pkix_NameConstraintsCheckerstate_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_NameConstraintsCheckerState_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_NameConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
+ "pkix_NameConstraintsCheckerState_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that object type */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTNAMECONSTRAINTSCHECKERSTATE);
+
+ state = (pkix_NameConstraintsCheckerState *)object;
+
+ PKIX_DECREF(state->nameConstraints);
+ PKIX_DECREF(state->nameConstraintsOID);
+
+cleanup:
+
+ PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_NameConstraintsCheckerState_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE and its related
+ * functions with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_NameConstraintsCheckerState_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
+ "pkix_NameConstraintsCheckerState_RegisterSelf");
+
+ entry.description = "NameConstraintsCheckerState";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(pkix_NameConstraintsCheckerState);
+ entry.destructor = pkix_NameConstraintsCheckerState_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE] = entry;
+
+ PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_NameConstraintsCheckerState_Create
+ *
+ * DESCRIPTION:
+ * Allocate and initialize NameConstraintsChecker state data.
+ *
+ * PARAMETERS
+ * "nameConstraints"
+ * Address of NameConstraints to be stored in state. May be NULL.
+ * "numCerts"
+ * Number of certificates in the validation chain. This data is used
+ * to identify end-entity.
+ * "pCheckerState"
+ * Address of NameConstraintsCheckerState that is returned. Must be
+ * non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CERTNAMECONSTRAINTSCHECKERSTATE Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error
+ */
+static PKIX_Error *
+pkix_NameConstraintsCheckerState_Create(
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_UInt32 numCerts,
+ pkix_NameConstraintsCheckerState **pCheckerState,
+ void *plContext)
+{
+ pkix_NameConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE,
+ "pkix_NameConstraintsCheckerState_Create");
+ PKIX_NULLCHECK_ONE(pCheckerState);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE,
+ sizeof (pkix_NameConstraintsCheckerState),
+ (PKIX_PL_Object **)&state,
+ plContext),
+ PKIX_COULDNOTCREATENAMECONSTRAINTSCHECKERSTATEOBJECT);
+
+ /* Initialize fields */
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_NAMECONSTRAINTS_OID,
+ &state->nameConstraintsOID,
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_INCREF(nameConstraints);
+
+ state->nameConstraints = nameConstraints;
+ state->certsRemaining = numCerts;
+
+ *pCheckerState = state;
+ state = NULL;
+
+cleanup:
+
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE);
+}
+
+/* --Private-NameConstraintsChecker-Functions------------------------- */
+
+/*
+ * FUNCTION: pkix_NameConstraintsChecker_Check
+ * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
+ */
+static PKIX_Error *
+pkix_NameConstraintsChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ pkix_NameConstraintsCheckerState *state = NULL;
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ PKIX_PL_CertNameConstraints *mergedNameConstraints = NULL;
+ PKIX_Boolean selfIssued = PKIX_FALSE;
+ PKIX_Boolean lastCert = PKIX_FALSE;
+ PKIX_Boolean treatCommonNameAsDNSName = PKIX_FALSE;
+ PKIX_List *extKeyUsageList = NULL;
+ PKIX_PL_OID *serverAuthOID = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_Check");
+ PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
+
+ *pNBIOContext = NULL; /* we never block on pending I/O */
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
+ (checker, (PKIX_PL_Object **)&state, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ state->certsRemaining--;
+ lastCert = state->certsRemaining == 0;
+
+ /* Get status of self issued */
+ PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext),
+ PKIX_ISCERTSELFISSUEDFAILED);
+
+ if (lastCert) {
+ /* For the last cert, treat the CN as a DNS name for name
+ * constraint check. But only if EKU has id-kp-serverAuth
+ * or EKU is absent. It does not make sense to treat CN
+ * as a DNS name for an OCSP signing certificate, for example.
+ */
+ PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
+ (cert, &extKeyUsageList, plContext),
+ PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
+ if (extKeyUsageList == NULL) {
+ treatCommonNameAsDNSName = PKIX_TRUE;
+ } else {
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_KEY_USAGE_SERVER_AUTH_OID,
+ &serverAuthOID,
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(pkix_List_Contains
+ (extKeyUsageList,
+ (PKIX_PL_Object *) serverAuthOID,
+ &treatCommonNameAsDNSName,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ }
+ }
+
+ /* Check on non self-issued and if so only for last cert */
+ if (selfIssued == PKIX_FALSE ||
+ (selfIssued == PKIX_TRUE && lastCert)) {
+ PKIX_CHECK(PKIX_PL_Cert_CheckNameConstraints
+ (cert, state->nameConstraints, treatCommonNameAsDNSName,
+ plContext),
+ PKIX_CERTCHECKNAMECONSTRAINTSFAILED);
+ }
+
+ if (!lastCert) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
+ (cert, &nameConstraints, plContext),
+ PKIX_CERTGETNAMECONSTRAINTSFAILED);
+
+ /* Merge with previous name constraints kept in state */
+
+ if (nameConstraints != NULL) {
+
+ if (state->nameConstraints == NULL) {
+
+ state->nameConstraints = nameConstraints;
+
+ } else {
+
+ PKIX_CHECK(PKIX_PL_Cert_MergeNameConstraints
+ (nameConstraints,
+ state->nameConstraints,
+ &mergedNameConstraints,
+ plContext),
+ PKIX_CERTMERGENAMECONSTRAINTSFAILED);
+
+ PKIX_DECREF(nameConstraints);
+ PKIX_DECREF(state->nameConstraints);
+
+ state->nameConstraints = mergedNameConstraints;
+ }
+
+ /* Remove Name Constraints Extension OID from list */
+ if (unresolvedCriticalExtensions != NULL) {
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticalExtensions,
+ (PKIX_PL_Object *)state->nameConstraintsOID,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+ }
+ }
+ }
+
+ PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
+ (checker, (PKIX_PL_Object *)state, plContext),
+ PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(state);
+ PKIX_DECREF(extKeyUsageList);
+ PKIX_DECREF(serverAuthOID);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_NameConstraintsChecker_Initialize
+ *
+ * DESCRIPTION:
+ * Create a CertChainChecker with a NameConstraintsCheckerState. The
+ * NameConstraintsCheckerState is created with "trustedNC" and "numCerts"
+ * as its initial state. The CertChainChecker for the NameConstraints is
+ * returned at address of "pChecker".
+ *
+ * PARAMETERS
+ * "trustedNC"
+ * The NameConstraints from trusted anchor Cert is stored at "trustedNC"
+ * for initialization. May be NULL.
+ * "numCerts"
+ * Number of certificates in the validation chain. This data is used
+ * to identify end-entity.
+ * "pChecker"
+ * Address of CertChainChecker to bo created and returned.
+ * Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CERTCHAINCHECKER Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error
+ */
+PKIX_Error *
+pkix_NameConstraintsChecker_Initialize(
+ PKIX_PL_CertNameConstraints *trustedNC,
+ PKIX_UInt32 numCerts,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ pkix_NameConstraintsCheckerState *state = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_Initialize");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ PKIX_CHECK(pkix_NameConstraintsCheckerState_Create
+ (trustedNC, numCerts, &state, plContext),
+ PKIX_NAMECONSTRAINTSCHECKERSTATECREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_NameConstraintsChecker_Check,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *) state,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.h
new file mode 100644
index 0000000000..ac3de346db
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_nameconstraintschecker.h
@@ -0,0 +1,43 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_nameconstraintschecker.h
+ *
+ * Header file for validate Name Constraints Checker function
+ *
+ */
+
+#ifndef _PKIX_NAMECONSTRAINTSCHECKER_H
+#define _PKIX_NAMECONSTRAINTSCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkix_NameConstraintsCheckerState \
+ pkix_NameConstraintsCheckerState;
+
+struct pkix_NameConstraintsCheckerState {
+ PKIX_PL_CertNameConstraints *nameConstraints;
+ PKIX_PL_OID *nameConstraintsOID;
+ PKIX_UInt32 certsRemaining;
+};
+
+PKIX_Error *
+pkix_NameConstraintsChecker_Initialize(
+ PKIX_PL_CertNameConstraints *trustedNC,
+ PKIX_UInt32 numCerts,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+PKIX_Error *
+pkix_NameConstraintsCheckerState_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_NAMECONSTRAINTSCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c
new file mode 100644
index 0000000000..b6fca9a354
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.c
@@ -0,0 +1,419 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_ocspchecker.c
+ *
+ * OcspChecker Object Functions
+ *
+ */
+
+#include "pkix_ocspchecker.h"
+#include "pkix_pl_ocspcertid.h"
+#include "pkix_error.h"
+
+
+/* --Private-Data-and-Types--------------------------------------- */
+
+typedef struct pkix_OcspCheckerStruct {
+ /* RevocationMethod is the super class of OcspChecker. */
+ pkix_RevocationMethod method;
+ PKIX_PL_VerifyCallback certVerifyFcn;
+} pkix_OcspChecker;
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_OcspChecker_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_OcspChecker_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ return NULL;
+}
+
+/*
+ * FUNCTION: pkix_OcspChecker_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_OCSPCHECKER_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_OcspChecker_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry* entry = &systemClasses[PKIX_OCSPCHECKER_TYPE];
+
+ PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_RegisterSelf");
+
+ entry->description = "OcspChecker";
+ entry->typeObjectSize = sizeof(pkix_OcspChecker);
+ entry->destructor = pkix_OcspChecker_Destroy;
+
+ PKIX_RETURN(OCSPCHECKER);
+}
+
+
+/*
+ * FUNCTION: pkix_OcspChecker_Create
+ */
+PKIX_Error *
+pkix_OcspChecker_Create(PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 flags,
+ PKIX_UInt32 priority,
+ pkix_LocalRevocationCheckFn localRevChecker,
+ pkix_ExternalRevocationCheckFn externalRevChecker,
+ PKIX_PL_VerifyCallback verifyFn,
+ pkix_RevocationMethod **pChecker,
+ void *plContext)
+{
+ pkix_OcspChecker *method = NULL;
+
+ PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_Create");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_OCSPCHECKER_TYPE,
+ sizeof (pkix_OcspChecker),
+ (PKIX_PL_Object **)&method,
+ plContext),
+ PKIX_COULDNOTCREATECERTCHAINCHECKEROBJECT);
+
+ pkixErrorResult = pkix_RevocationMethod_Init(
+ (pkix_RevocationMethod*)method, methodType, flags, priority,
+ localRevChecker, externalRevChecker, plContext);
+ if (pkixErrorResult) {
+ goto cleanup;
+ }
+ method->certVerifyFcn = (PKIX_PL_VerifyCallback)verifyFn;
+
+ *pChecker = (pkix_RevocationMethod*)method;
+ method = NULL;
+
+cleanup:
+ PKIX_DECREF(method);
+
+ PKIX_RETURN(OCSPCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_OcspChecker_MapResultCodeToRevStatus
+ */
+PKIX_RevocationStatus
+pkix_OcspChecker_MapResultCodeToRevStatus(SECErrorCodes resultCode)
+{
+ switch (resultCode) {
+ case SEC_ERROR_REVOKED_CERTIFICATE:
+ return PKIX_RevStatus_Revoked;
+ default:
+ return PKIX_RevStatus_NoInfo;
+ }
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_OcspChecker_Check (see comments in pkix_checker.h)
+ */
+
+/*
+ * The OCSPChecker is created in an idle state, and remains in this state until
+ * either (a) the default Responder has been set and enabled, and a Check
+ * request is received with no responder specified, or (b) a Check request is
+ * received with a specified responder. A request message is constructed and
+ * given to the HttpClient. If non-blocking I/O is used the client may return
+ * with WOULDBLOCK, in which case the OCSPChecker returns the WOULDBLOCK
+ * condition to its caller in turn. On a subsequent call the I/O is resumed.
+ * When a response is received it is decoded and the results provided to the
+ * caller.
+ *
+ */
+PKIX_Error *
+pkix_OcspChecker_CheckLocal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean chainVerificationState,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *pReasonCode,
+ void *plContext)
+{
+ PKIX_PL_OcspCertID *cid = NULL;
+ PKIX_Boolean hasFreshStatus = PKIX_FALSE;
+ PKIX_Boolean statusIsGood = PKIX_FALSE;
+ SECErrorCodes resultCode = SEC_ERROR_REVOKED_CERTIFICATE_OCSP;
+ PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
+
+ PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_CheckLocal");
+
+ PKIX_CHECK(
+ PKIX_PL_OcspCertID_Create(cert, NULL, &cid,
+ plContext),
+ PKIX_OCSPCERTIDCREATEFAILED);
+ if (!cid) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(
+ PKIX_PL_OcspCertID_GetFreshCacheStatus(cid, date,
+ &hasFreshStatus,
+ &statusIsGood,
+ &resultCode,
+ plContext),
+ PKIX_OCSPCERTIDGETFRESHCACHESTATUSFAILED);
+ if (hasFreshStatus) {
+ if (statusIsGood) {
+ revStatus = PKIX_RevStatus_Success;
+ resultCode = 0;
+ } else {
+ revStatus = pkix_OcspChecker_MapResultCodeToRevStatus(resultCode);
+ }
+ }
+
+cleanup:
+ *pRevStatus = revStatus;
+
+ /* ocsp carries only tree statuses: good, bad, and unknown.
+ * revStatus is used to pass them. reasonCode is always set
+ * to be unknown. */
+ *pReasonCode = crlEntryReasonUnspecified;
+ PKIX_DECREF(cid);
+
+ PKIX_RETURN(OCSPCHECKER);
+}
+
+
+/*
+ * The OCSPChecker is created in an idle state, and remains in this state until
+ * either (a) the default Responder has been set and enabled, and a Check
+ * request is received with no responder specified, or (b) a Check request is
+ * received with a specified responder. A request message is constructed and
+ * given to the HttpClient. When a response is received it is decoded and the
+ * results provided to the caller.
+ *
+ * During the most recent enhancement of this function, it has been found that
+ * it doesn't correctly implement non-blocking I/O.
+ *
+ * The nbioContext is used in two places, for "response-obtaining" and
+ * for "response-verification".
+ *
+ * However, if this function gets called to resume, it always
+ * repeats the "request creation" and "response fetching" steps!
+ * As a result, the earlier operation is never resumed.
+ */
+PKIX_Error *
+pkix_OcspChecker_CheckExternal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *pReasonCode,
+ void **pNBIOContext,
+ void *plContext)
+{
+ SECErrorCodes resultCode = SEC_ERROR_REVOKED_CERTIFICATE_OCSP;
+ PKIX_Boolean uriFound = PKIX_FALSE;
+ PKIX_Boolean passed = PKIX_TRUE;
+ pkix_OcspChecker *checker = NULL;
+ PKIX_PL_OcspCertID *cid = NULL;
+ PKIX_PL_OcspRequest *request = NULL;
+ PKIX_PL_OcspResponse *response = NULL;
+ PKIX_PL_Date *validity = NULL;
+ PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
+ void *nbioContext = NULL;
+ enum { stageGET, stagePOST } currentStage;
+ PRBool retry = PR_FALSE;
+
+ PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_CheckExternal");
+
+ PKIX_CHECK(
+ pkix_CheckType((PKIX_PL_Object*)checkerObject,
+ PKIX_OCSPCHECKER_TYPE, plContext),
+ PKIX_OBJECTNOTOCSPCHECKER);
+
+ checker = (pkix_OcspChecker *)checkerObject;
+
+ PKIX_CHECK(
+ PKIX_PL_OcspCertID_Create(cert, NULL, &cid,
+ plContext),
+ PKIX_OCSPCERTIDCREATEFAILED);
+
+ /* create request */
+ PKIX_CHECK(
+ pkix_pl_OcspRequest_Create(cert, cid, validity, NULL,
+ methodFlags, &uriFound, &request,
+ plContext),
+ PKIX_OCSPREQUESTCREATEFAILED);
+
+ if (uriFound == PKIX_FALSE) {
+ /* no caching for certs lacking URI */
+ resultCode = 0;
+ goto cleanup;
+ }
+
+ if (methodFlags & CERT_REV_M_FORCE_POST_METHOD_FOR_OCSP) {
+ /* Do not try HTTP GET, only HTTP POST */
+ currentStage = stagePOST;
+ } else {
+ /* Try HTTP GET first, falling back to POST */
+ currentStage = stageGET;
+ }
+
+ do {
+ const char *method;
+ passed = PKIX_TRUE;
+
+ retry = PR_FALSE;
+ if (currentStage == stageGET) {
+ method = "GET";
+ } else {
+ PORT_Assert(currentStage == stagePOST);
+ method = "POST";
+ }
+
+ /* send request and create a response object */
+ PKIX_CHECK_NO_GOTO(
+ pkix_pl_OcspResponse_Create(request, method, NULL,
+ checker->certVerifyFcn,
+ &nbioContext,
+ &response,
+ plContext),
+ PKIX_OCSPRESPONSECREATEFAILED);
+
+ if (pkixErrorResult) {
+ passed = PKIX_FALSE;
+ }
+
+ if (passed && nbioContext != 0) {
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ if (passed){
+ PKIX_CHECK_NO_GOTO(
+ pkix_pl_OcspResponse_Decode(response, &passed,
+ &resultCode, plContext),
+ PKIX_OCSPRESPONSEDECODEFAILED);
+ if (pkixErrorResult) {
+ passed = PKIX_FALSE;
+ }
+ }
+
+ if (passed){
+ PKIX_CHECK_NO_GOTO(
+ pkix_pl_OcspResponse_GetStatus(response, &passed,
+ &resultCode, plContext),
+ PKIX_OCSPRESPONSEGETSTATUSRETURNEDANERROR);
+ if (pkixErrorResult) {
+ passed = PKIX_FALSE;
+ }
+ }
+
+ if (passed){
+ PKIX_CHECK_NO_GOTO(
+ pkix_pl_OcspResponse_VerifySignature(response, cert,
+ procParams, &passed,
+ &nbioContext, plContext),
+ PKIX_OCSPRESPONSEVERIFYSIGNATUREFAILED);
+ if (pkixErrorResult) {
+ passed = PKIX_FALSE;
+ } else {
+ if (nbioContext != 0) {
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+ }
+ }
+
+ if (!passed && currentStage == stagePOST) {
+ /* We won't retry a POST failure, so it's final.
+ * Because the following block with its call to
+ * pkix_pl_OcspResponse_GetStatusForCert
+ * will take care of caching good or bad state,
+ * but we only execute that next block if there hasn't
+ * been a failure yet, we must cache the POST
+ * failure now.
+ */
+
+ if (cid && cid->certID) {
+ /* Caching MIGHT consume the cid. */
+ PKIX_Error *err;
+ err = PKIX_PL_OcspCertID_RememberOCSPProcessingFailure(
+ cid, plContext);
+ if (err) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)err, plContext);
+ }
+ }
+ }
+
+ if (passed){
+ PKIX_Boolean allowCachingOfFailures =
+ (currentStage == stagePOST) ? PKIX_TRUE : PKIX_FALSE;
+
+ PKIX_CHECK_NO_GOTO(
+ pkix_pl_OcspResponse_GetStatusForCert(cid, response,
+ allowCachingOfFailures,
+ date,
+ &passed, &resultCode,
+ plContext),
+ PKIX_OCSPRESPONSEGETSTATUSFORCERTFAILED);
+ if (pkixErrorResult) {
+ passed = PKIX_FALSE;
+ } else if (passed == PKIX_FALSE) {
+ revStatus = pkix_OcspChecker_MapResultCodeToRevStatus(resultCode);
+ } else {
+ revStatus = PKIX_RevStatus_Success;
+ }
+ }
+
+ if (currentStage == stageGET && revStatus != PKIX_RevStatus_Success &&
+ revStatus != PKIX_RevStatus_Revoked) {
+ /* we'll retry */
+ PKIX_DECREF(response);
+ retry = PR_TRUE;
+ currentStage = stagePOST;
+ revStatus = PKIX_RevStatus_NoInfo;
+ if (pkixErrorResult) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorResult,
+ plContext);
+ pkixErrorResult = NULL;
+ }
+ }
+ } while (retry);
+
+cleanup:
+ if (revStatus == PKIX_RevStatus_NoInfo && (uriFound ||
+ methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) &&
+ methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
+ revStatus = PKIX_RevStatus_Revoked;
+ }
+ *pRevStatus = revStatus;
+
+ /* ocsp carries only three statuses: good, bad, and unknown.
+ * revStatus is used to pass them. reasonCode is always set
+ * to be unknown. */
+ *pReasonCode = crlEntryReasonUnspecified;
+
+ PKIX_DECREF(cid);
+ PKIX_DECREF(request);
+ PKIX_DECREF(response);
+
+ PKIX_RETURN(OCSPCHECKER);
+}
+
+
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.h
new file mode 100644
index 0000000000..fbec315f96
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_ocspchecker.h
@@ -0,0 +1,67 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_ocspchecker.h
+ *
+ * OcspChecker Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_OCSPCHECKER_H
+#define _PKIX_OCSPCHECKER_H
+
+#include "pkix_tools.h"
+#include "pkix_revocationmethod.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: nbio logic removed. Will be replaced later. */
+
+PKIX_Error *
+pkix_OcspChecker_CheckLocal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean chainVerificationState,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *reasonCode,
+ void *plContext);
+
+PKIX_Error *
+pkix_OcspChecker_CheckExternal(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *reasonCode,
+ void **pNBIOContext,
+ void *plContext);
+
+PKIX_Error *
+pkix_OcspChecker_Create(PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 flags,
+ PKIX_UInt32 priority,
+ pkix_LocalRevocationCheckFn localRevChecker,
+ pkix_ExternalRevocationCheckFn externalRevChecker,
+ PKIX_PL_VerifyCallback certVerifyFn,
+ pkix_RevocationMethod **pChecker,
+ void *plContext);
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_OcspChecker_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_OCSPCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.c
new file mode 100644
index 0000000000..8e40596541
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.c
@@ -0,0 +1,2783 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_policychecker.c
+ *
+ * Functions for Policy Checker
+ *
+ */
+#include "pkix_policychecker.h"
+
+/* --Forward declarations----------------------------------------------- */
+
+static PKIX_Error *
+pkix_PolicyChecker_MakeSingleton(
+ PKIX_PL_Object *listItem,
+ PKIX_Boolean immutability,
+ PKIX_List **pList,
+ void *plContext);
+
+/* --Private-PolicyCheckerState-Functions---------------------------------- */
+
+/*
+ * FUNCTION:pkix_PolicyCheckerState_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyCheckerState_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PolicyCheckerState *checkerState = NULL;
+
+ PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYCHECKERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTPOLICYCHECKERSTATE);
+
+ checkerState = (PKIX_PolicyCheckerState *)object;
+
+ PKIX_DECREF(checkerState->certPoliciesExtension);
+ PKIX_DECREF(checkerState->policyMappingsExtension);
+ PKIX_DECREF(checkerState->policyConstraintsExtension);
+ PKIX_DECREF(checkerState->inhibitAnyPolicyExtension);
+ PKIX_DECREF(checkerState->anyPolicyOID);
+ PKIX_DECREF(checkerState->validPolicyTree);
+ PKIX_DECREF(checkerState->userInitialPolicySet);
+ PKIX_DECREF(checkerState->mappedUserInitialPolicySet);
+
+ checkerState->policyQualifiersRejected = PKIX_FALSE;
+ checkerState->explicitPolicy = 0;
+ checkerState->inhibitAnyPolicy = 0;
+ checkerState->policyMapping = 0;
+ checkerState->numCerts = 0;
+ checkerState->certsProcessed = 0;
+ checkerState->certPoliciesCritical = PKIX_FALSE;
+
+ PKIX_DECREF(checkerState->anyPolicyNodeAtBottom);
+ PKIX_DECREF(checkerState->newAnyPolicyNode);
+ PKIX_DECREF(checkerState->mappedPolicyOIDs);
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyCheckerState_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyCheckerState_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pCheckerStateString,
+ void *plContext)
+{
+ PKIX_PolicyCheckerState *state = NULL;
+ PKIX_PL_String *resultString = NULL;
+ PKIX_PL_String *policiesExtOIDString = NULL;
+ PKIX_PL_String *policyMapOIDString = NULL;
+ PKIX_PL_String *policyConstrOIDString = NULL;
+ PKIX_PL_String *inhAnyPolOIDString = NULL;
+ PKIX_PL_String *anyPolicyOIDString = NULL;
+ PKIX_PL_String *validPolicyTreeString = NULL;
+ PKIX_PL_String *userInitialPolicySetString = NULL;
+ PKIX_PL_String *mappedUserPolicySetString = NULL;
+ PKIX_PL_String *mappedPolicyOIDsString = NULL;
+ PKIX_PL_String *anyAtBottomString = NULL;
+ PKIX_PL_String *newAnyPolicyString = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *trueString = NULL;
+ PKIX_PL_String *falseString = NULL;
+ PKIX_PL_String *nullString = NULL;
+ PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
+ PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
+ PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
+ PKIX_Boolean initialIsAnyPolicy = PKIX_FALSE;
+ PKIX_Boolean policyQualifiersRejected = PKIX_FALSE;
+ PKIX_Boolean certPoliciesCritical = PKIX_FALSE;
+ char *asciiFormat =
+ "{\n"
+ "\tcertPoliciesExtension: \t%s\n"
+ "\tpolicyMappingsExtension: \t%s\n"
+ "\tpolicyConstraintsExtension:\t%s\n"
+ "\tinhibitAnyPolicyExtension:\t%s\n"
+ "\tanyPolicyOID: \t%s\n"
+ "\tinitialIsAnyPolicy: \t%s\n"
+ "\tvalidPolicyTree: \t%s\n"
+ "\tuserInitialPolicySet: \t%s\n"
+ "\tmappedUserPolicySet: \t%s\n"
+ "\tpolicyQualifiersRejected: \t%s\n"
+ "\tinitialPolMappingInhibit: \t%s\n"
+ "\tinitialExplicitPolicy: \t%s\n"
+ "\tinitialAnyPolicyInhibit: \t%s\n"
+ "\texplicitPolicy: \t%d\n"
+ "\tinhibitAnyPolicy: \t%d\n"
+ "\tpolicyMapping: \t%d\n"
+ "\tnumCerts: \t%d\n"
+ "\tcertsProcessed: \t%d\n"
+ "\tanyPolicyNodeAtBottom: \t%s\n"
+ "\tnewAnyPolicyNode: \t%s\n"
+ "\tcertPoliciesCritical: \t%s\n"
+ "\tmappedPolicyOIDs: \t%s\n"
+ "}";
+
+ PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_ToString");
+
+ PKIX_NULLCHECK_TWO(object, pCheckerStateString);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYCHECKERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTPOLICYCHECKERSTATE);
+
+ state = (PKIX_PolicyCheckerState *)object;
+ PKIX_NULLCHECK_THREE
+ (state->certPoliciesExtension,
+ state->policyMappingsExtension,
+ state->policyConstraintsExtension);
+ PKIX_NULLCHECK_THREE
+ (state->inhibitAnyPolicyExtension,
+ state->anyPolicyOID,
+ state->userInitialPolicySet);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
+ PKIX_STRINGCREATEFAILED);
+ /*
+ * Create TRUE, FALSE, and "NULL" PKIX_PL_Strings. But creating a
+ * PKIX_PL_String is complicated enough, it's worth checking, for
+ * each, to make sure the string is needed.
+ */
+ initialPolicyMappingInhibit = state->initialPolicyMappingInhibit;
+ initialExplicitPolicy = state->initialExplicitPolicy;
+ initialAnyPolicyInhibit = state->initialAnyPolicyInhibit;
+ initialIsAnyPolicy = state->initialIsAnyPolicy;
+ policyQualifiersRejected = state->policyQualifiersRejected;
+ certPoliciesCritical = state->certPoliciesCritical;
+
+ if (initialPolicyMappingInhibit || initialExplicitPolicy ||
+ initialAnyPolicyInhibit || initialIsAnyPolicy ||
+ policyQualifiersRejected || certPoliciesCritical) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "TRUE", 0, &trueString, plContext),
+ PKIX_STRINGCREATEFAILED);
+ }
+ if (!initialPolicyMappingInhibit || !initialExplicitPolicy ||
+ !initialAnyPolicyInhibit || !initialIsAnyPolicy ||
+ !policyQualifiersRejected || !certPoliciesCritical) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "FALSE", 0, &falseString, plContext),
+ PKIX_STRINGCREATEFAILED);
+ }
+ if (!(state->anyPolicyNodeAtBottom) || !(state->newAnyPolicyNode)) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "(null)", 0, &nullString, plContext),
+ PKIX_STRINGCREATEFAILED);
+ }
+
+ PKIX_TOSTRING
+ (state->certPoliciesExtension, &policiesExtOIDString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->policyMappingsExtension,
+ &policyMapOIDString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->policyConstraintsExtension,
+ &policyConstrOIDString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->inhibitAnyPolicyExtension,
+ &inhAnyPolOIDString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(state->anyPolicyOID, &anyPolicyOIDString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(state->validPolicyTree, &validPolicyTreeString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->userInitialPolicySet,
+ &userInitialPolicySetString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->mappedUserInitialPolicySet,
+ &mappedUserPolicySetString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ if (state->anyPolicyNodeAtBottom) {
+ PKIX_CHECK(pkix_SinglePolicyNode_ToString
+ (state->anyPolicyNodeAtBottom,
+ &anyAtBottomString,
+ plContext),
+ PKIX_SINGLEPOLICYNODETOSTRINGFAILED);
+ } else {
+ PKIX_INCREF(nullString);
+ anyAtBottomString = nullString;
+ }
+
+ if (state->newAnyPolicyNode) {
+ PKIX_CHECK(pkix_SinglePolicyNode_ToString
+ (state->newAnyPolicyNode,
+ &newAnyPolicyString,
+ plContext),
+ PKIX_SINGLEPOLICYNODETOSTRINGFAILED);
+ } else {
+ PKIX_INCREF(nullString);
+ newAnyPolicyString = nullString;
+ }
+
+ PKIX_TOSTRING
+ (state->mappedPolicyOIDs,
+ &mappedPolicyOIDsString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ formatString,
+ policiesExtOIDString,
+ policyMapOIDString,
+ policyConstrOIDString,
+ inhAnyPolOIDString,
+ anyPolicyOIDString,
+ initialIsAnyPolicy?trueString:falseString,
+ validPolicyTreeString,
+ userInitialPolicySetString,
+ mappedUserPolicySetString,
+ policyQualifiersRejected?trueString:falseString,
+ initialPolicyMappingInhibit?trueString:falseString,
+ initialExplicitPolicy?trueString:falseString,
+ initialAnyPolicyInhibit?trueString:falseString,
+ state->explicitPolicy,
+ state->inhibitAnyPolicy,
+ state->policyMapping,
+ state->numCerts,
+ state->certsProcessed,
+ anyAtBottomString,
+ newAnyPolicyString,
+ certPoliciesCritical?trueString:falseString,
+ mappedPolicyOIDsString),
+ PKIX_SPRINTFFAILED);
+
+ *pCheckerStateString = resultString;
+
+cleanup:
+ PKIX_DECREF(policiesExtOIDString);
+ PKIX_DECREF(policyMapOIDString);
+ PKIX_DECREF(policyConstrOIDString);
+ PKIX_DECREF(inhAnyPolOIDString);
+ PKIX_DECREF(anyPolicyOIDString);
+ PKIX_DECREF(validPolicyTreeString);
+ PKIX_DECREF(userInitialPolicySetString);
+ PKIX_DECREF(mappedUserPolicySetString);
+ PKIX_DECREF(anyAtBottomString);
+ PKIX_DECREF(newAnyPolicyString);
+ PKIX_DECREF(mappedPolicyOIDsString);
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(trueString);
+ PKIX_DECREF(falseString);
+ PKIX_DECREF(nullString);
+
+ PKIX_RETURN(CERTPOLICYCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyCheckerState_RegisterSelf
+ * DESCRIPTION:
+ *
+ * Registers PKIX_POLICYCHECKERSTATE_TYPE and its related functions
+ * with systemClasses[]
+ *
+ * PARAMETERS:
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_PolicyCheckerState_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER
+ (CERTPOLICYCHECKERSTATE,
+ "pkix_PolicyCheckerState_RegisterSelf");
+
+ entry.description = "PolicyCheckerState";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PolicyCheckerState);
+ entry.destructor = pkix_PolicyCheckerState_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = pkix_PolicyCheckerState_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_CERTPOLICYCHECKERSTATE_TYPE] = entry;
+
+ PKIX_RETURN(CERTPOLICYCHECKERSTATE);
+}
+
+/*
+ * FUNCTION:pkix_PolicyCheckerState_Create
+ * DESCRIPTION:
+ *
+ * Creates a PolicyCheckerState Object, using the List pointed to
+ * by "initialPolicies" for the user-initial-policy-set, the Boolean value
+ * of "policyQualifiersRejected" for the policyQualifiersRejected parameter,
+ * the Boolean value of "initialPolicyMappingInhibit" for the
+ * inhibitPolicyMappings parameter, the Boolean value of
+ * "initialExplicitPolicy" for the initialExplicitPolicy parameter, the
+ * Boolean value of "initialAnyPolicyInhibit" for the inhibitAnyPolicy
+ * parameter, and the UInt32 value of "numCerts" as the number of
+ * certificates in the chain; and stores the Object at "pCheckerState".
+ *
+ * PARAMETERS:
+ * "initialPolicies"
+ * Address of List of OIDs comprising the user-initial-policy-set; the List
+ * may be empty, but must be non-NULL
+ * "policyQualifiersRejected"
+ * Boolean value of the policyQualifiersRejected parameter
+ * "initialPolicyMappingInhibit"
+ * Boolean value of the inhibitPolicyMappings parameter
+ * "initialExplicitPolicy"
+ * Boolean value of the initialExplicitPolicy parameter
+ * "initialAnyPolicyInhibit"
+ * Boolean value of the inhibitAnyPolicy parameter
+ * "numCerts"
+ * Number of certificates in the chain to be validated
+ * "pCheckerState"
+ * Address where PolicyCheckerState will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertPolicyCheckerState Error if the functions fails in a
+ * non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyCheckerState_Create(
+ PKIX_List *initialPolicies,
+ PKIX_Boolean policyQualifiersRejected,
+ PKIX_Boolean initialPolicyMappingInhibit,
+ PKIX_Boolean initialExplicitPolicy,
+ PKIX_Boolean initialAnyPolicyInhibit,
+ PKIX_UInt32 numCerts,
+ PKIX_PolicyCheckerState **pCheckerState,
+ void *plContext)
+{
+ PKIX_PolicyCheckerState *checkerState = NULL;
+ PKIX_PolicyNode *policyNode = NULL;
+ PKIX_List *anyPolicyList = NULL;
+ PKIX_Boolean initialPoliciesIsEmpty = PKIX_FALSE;
+
+ PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_Create");
+ PKIX_NULLCHECK_TWO(initialPolicies, pCheckerState);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTPOLICYCHECKERSTATE_TYPE,
+ sizeof (PKIX_PolicyCheckerState),
+ (PKIX_PL_Object **)&checkerState,
+ plContext),
+ PKIX_COULDNOTCREATEPOLICYCHECKERSTATEOBJECT);
+
+ /* Create constant PKIX_PL_OIDs: */
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_CERTIFICATEPOLICIES_OID,
+ &(checkerState->certPoliciesExtension),
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_POLICYMAPPINGS_OID,
+ &(checkerState->policyMappingsExtension),
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_POLICYCONSTRAINTS_OID,
+ &(checkerState->policyConstraintsExtension),
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_INHIBITANYPOLICY_OID,
+ &(checkerState->inhibitAnyPolicyExtension),
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_CERTIFICATEPOLICIES_ANYPOLICY_OID,
+ &(checkerState->anyPolicyOID),
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* Create an initial policy set from argument supplied */
+ PKIX_INCREF(initialPolicies);
+ checkerState->userInitialPolicySet = initialPolicies;
+ PKIX_INCREF(initialPolicies);
+ checkerState->mappedUserInitialPolicySet = initialPolicies;
+
+ PKIX_CHECK(PKIX_List_IsEmpty
+ (initialPolicies,
+ &initialPoliciesIsEmpty,
+ plContext),
+ PKIX_LISTISEMPTYFAILED);
+ if (initialPoliciesIsEmpty) {
+ checkerState->initialIsAnyPolicy = PKIX_TRUE;
+ } else {
+ PKIX_CHECK(pkix_List_Contains
+ (initialPolicies,
+ (PKIX_PL_Object *)(checkerState->anyPolicyOID),
+ &(checkerState->initialIsAnyPolicy),
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ }
+
+ checkerState->policyQualifiersRejected =
+ policyQualifiersRejected;
+ checkerState->initialExplicitPolicy = initialExplicitPolicy;
+ checkerState->explicitPolicy =
+ (initialExplicitPolicy? 0: numCerts + 1);
+ checkerState->initialAnyPolicyInhibit = initialAnyPolicyInhibit;
+ checkerState->inhibitAnyPolicy =
+ (initialAnyPolicyInhibit? 0: numCerts + 1);
+ checkerState->initialPolicyMappingInhibit = initialPolicyMappingInhibit;
+ checkerState->policyMapping =
+ (initialPolicyMappingInhibit? 0: numCerts + 1);
+ ;
+ checkerState->numCerts = numCerts;
+ checkerState->certsProcessed = 0;
+ checkerState->certPoliciesCritical = PKIX_FALSE;
+
+ /* Create a valid_policy_tree as in RFC3280 6.1.2(a) */
+ PKIX_CHECK(pkix_PolicyChecker_MakeSingleton
+ ((PKIX_PL_Object *)(checkerState->anyPolicyOID),
+ PKIX_TRUE,
+ &anyPolicyList,
+ plContext),
+ PKIX_POLICYCHECKERMAKESINGLETONFAILED);
+
+ PKIX_CHECK(pkix_PolicyNode_Create
+ (checkerState->anyPolicyOID, /* validPolicy */
+ NULL, /* qualifier set */
+ PKIX_FALSE, /* criticality */
+ anyPolicyList, /* expectedPolicySet */
+ &policyNode,
+ plContext),
+ PKIX_POLICYNODECREATEFAILED);
+ checkerState->validPolicyTree = policyNode;
+
+ /*
+ * Since the initial validPolicyTree specifies
+ * ANY_POLICY, begin with a pointer to the root node.
+ */
+ PKIX_INCREF(policyNode);
+ checkerState->anyPolicyNodeAtBottom = policyNode;
+
+ checkerState->newAnyPolicyNode = NULL;
+
+ checkerState->mappedPolicyOIDs = NULL;
+
+ *pCheckerState = checkerState;
+ checkerState = NULL;
+
+cleanup:
+
+ PKIX_DECREF(checkerState);
+
+ PKIX_DECREF(anyPolicyList);
+
+ PKIX_RETURN(CERTPOLICYCHECKERSTATE);
+}
+
+/* --Private-PolicyChecker-Functions--------------------------------------- */
+
+/*
+ * FUNCTION: pkix_PolicyChecker_MapContains
+ * DESCRIPTION:
+ *
+ * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps", to
+ * determine whether the OID pointed to by "policy" is among the
+ * issuerDomainPolicies or subjectDomainPolicies of "certPolicyMaps", and
+ * stores the result in "pFound".
+ *
+ * This function is intended to allow an efficient check that the proscription
+ * against anyPolicy being mapped, described in RFC3280 Section 6.1.4(a), is
+ * not violated.
+ *
+ * PARAMETERS:
+ * "certPolicyMaps"
+ * Address of List of CertPolicyMaps to be searched. May be empty, but
+ * must be non-NULL
+ * "policy"
+ * Address of OID to be checked for. Must be non-NULL
+ * "pFound"
+ * Address where the result of the search will be stored. Must be non-NULL.
+ * "plContext"
+ * platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_PolicyChecker_MapContains(
+ PKIX_List *certPolicyMaps,
+ PKIX_PL_OID *policy,
+ PKIX_Boolean *pFound,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *map = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+ PKIX_Boolean match = PKIX_FALSE;
+ PKIX_PL_OID *issuerDomainPolicy = NULL;
+ PKIX_PL_OID *subjectDomainPolicy = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MapContains");
+ PKIX_NULLCHECK_THREE(certPolicyMaps, policy, pFound);
+
+ PKIX_CHECK(PKIX_List_GetLength(certPolicyMaps, &numEntries, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (index = 0; (!match) && (index < numEntries); index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_NULLCHECK_ONE(map);
+
+ PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy
+ (map, &issuerDomainPolicy, plContext),
+ PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED);
+
+ PKIX_EQUALS
+ (policy, issuerDomainPolicy, &match, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!match) {
+ PKIX_CHECK(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy
+ (map, &subjectDomainPolicy, plContext),
+ PKIX_CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED);
+
+ PKIX_EQUALS
+ (policy, subjectDomainPolicy, &match, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+ }
+
+ PKIX_DECREF(map);
+ PKIX_DECREF(issuerDomainPolicy);
+ PKIX_DECREF(subjectDomainPolicy);
+ }
+
+ *pFound = match;
+
+cleanup:
+
+ PKIX_DECREF(map);
+ PKIX_DECREF(issuerDomainPolicy);
+ PKIX_DECREF(subjectDomainPolicy);
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_MapGetSubjectDomainPolicies
+ * DESCRIPTION:
+ *
+ * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps", to create
+ * a list of all SubjectDomainPolicies for which the IssuerDomainPolicy is the
+ * policy pointed to by "policy", and stores the result in
+ * "pSubjectDomainPolicies".
+ *
+ * If the List of CertPolicyMaps provided in "certPolicyMaps" is NULL, the
+ * resulting List will be NULL. If there are CertPolicyMaps, but none that
+ * include "policy" as an IssuerDomainPolicy, the returned List pointer will
+ * be NULL. Otherwise, the returned List will contain the SubjectDomainPolicies
+ * of all CertPolicyMaps for which "policy" is the IssuerDomainPolicy. If a
+ * List is returned it will be immutable.
+ *
+ * PARAMETERS:
+ * "certPolicyMaps"
+ * Address of List of CertPolicyMaps to be searched. May be empty or NULL.
+ * "policy"
+ * Address of OID to be checked for. Must be non-NULL
+ * "pSubjectDomainPolicies"
+ * Address where the result of the search will be stored. Must be non-NULL.
+ * "plContext"
+ * platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_PolicyChecker_MapGetSubjectDomainPolicies(
+ PKIX_List *certPolicyMaps,
+ PKIX_PL_OID *policy,
+ PKIX_List **pSubjectDomainPolicies,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *map = NULL;
+ PKIX_List *subjectList = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+ PKIX_Boolean match = PKIX_FALSE;
+ PKIX_PL_OID *issuerDomainPolicy = NULL;
+ PKIX_PL_OID *subjectDomainPolicy = NULL;
+
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "pkix_PolicyChecker_MapGetSubjectDomainPolicies");
+ PKIX_NULLCHECK_TWO(policy, pSubjectDomainPolicies);
+
+ if (certPolicyMaps) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (certPolicyMaps,
+ &numEntries,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ for (index = 0; index < numEntries; index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_NULLCHECK_ONE(map);
+
+ PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy
+ (map, &issuerDomainPolicy, plContext),
+ PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED);
+
+ PKIX_EQUALS
+ (policy, issuerDomainPolicy, &match, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (match) {
+ if (!subjectList) {
+ PKIX_CHECK(PKIX_List_Create(&subjectList, plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy
+ (map, &subjectDomainPolicy, plContext),
+ PKIX_CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (subjectList,
+ (PKIX_PL_Object *)subjectDomainPolicy,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ PKIX_DECREF(map);
+ PKIX_DECREF(issuerDomainPolicy);
+ PKIX_DECREF(subjectDomainPolicy);
+ }
+
+ if (subjectList) {
+ PKIX_CHECK(PKIX_List_SetImmutable(subjectList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+ }
+
+ *pSubjectDomainPolicies = subjectList;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(subjectList);
+ }
+
+ PKIX_DECREF(map);
+ PKIX_DECREF(issuerDomainPolicy);
+ PKIX_DECREF(subjectDomainPolicy);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_MapGetMappedPolicies
+ * DESCRIPTION:
+ *
+ * Checks the List of CertPolicyMaps pointed to by "certPolicyMaps" to create a
+ * List of all IssuerDomainPolicies, and stores the result in
+ * "pMappedPolicies".
+ *
+ * The caller may not rely on the IssuerDomainPolicies to be in any particular
+ * order. IssuerDomainPolicies that appear in more than one CertPolicyMap will
+ * only appear once in "pMappedPolicies". If "certPolicyMaps" is empty the
+ * result will be an empty List. The created List is mutable.
+ *
+ * PARAMETERS:
+ * "certPolicyMaps"
+ * Address of List of CertPolicyMaps to be searched. May be empty, but
+ * must be non-NULL.
+ * "pMappedPolicies"
+ * Address where the result will be stored. Must be non-NULL.
+ * "plContext"
+ * platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_PolicyChecker_MapGetMappedPolicies(
+ PKIX_List *certPolicyMaps,
+ PKIX_List **pMappedPolicies,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *map = NULL;
+ PKIX_List *mappedList = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+ PKIX_Boolean isContained = PKIX_FALSE;
+ PKIX_PL_OID *issuerDomainPolicy = NULL;
+
+ PKIX_ENTER
+ (CERTCHAINCHECKER, "pkix_PolicyChecker_MapGetMappedPolicies");
+ PKIX_NULLCHECK_TWO(certPolicyMaps, pMappedPolicies);
+
+ PKIX_CHECK(PKIX_List_Create(&mappedList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(certPolicyMaps, &numEntries, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (index = 0; index < numEntries; index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_NULLCHECK_ONE(map);
+
+ PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy
+ (map, &issuerDomainPolicy, plContext),
+ PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED);
+
+ PKIX_CHECK(pkix_List_Contains
+ (mappedList,
+ (PKIX_PL_Object *)issuerDomainPolicy,
+ &isContained,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ if (isContained == PKIX_FALSE) {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (mappedList,
+ (PKIX_PL_Object *)issuerDomainPolicy,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ PKIX_DECREF(map);
+ PKIX_DECREF(issuerDomainPolicy);
+ }
+
+ *pMappedPolicies = mappedList;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(mappedList);
+ }
+
+ PKIX_DECREF(map);
+ PKIX_DECREF(issuerDomainPolicy);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_MakeMutableCopy
+ * DESCRIPTION:
+ *
+ * Creates a mutable copy of the List pointed to by "list", which may or may
+ * not be immutable, and stores the address at "pMutableCopy".
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List to be copied. Must be non-NULL.
+ * "pMutableCopy"
+ * Address where mutable copy will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_MakeMutableCopy(
+ PKIX_List *list,
+ PKIX_List **pMutableCopy,
+ void *plContext)
+{
+ PKIX_List *newList = NULL;
+ PKIX_UInt32 listLen = 0;
+ PKIX_UInt32 listIx = 0;
+ PKIX_PL_Object *object = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MakeMutableCopy");
+ PKIX_NULLCHECK_TWO(list, pMutableCopy);
+
+ PKIX_CHECK(PKIX_List_Create(&newList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(list, &listLen, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (listIx = 0; listIx < listLen; listIx++) {
+
+ PKIX_CHECK(PKIX_List_GetItem(list, listIx, &object, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem(newList, object, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(object);
+ }
+
+ *pMutableCopy = newList;
+ newList = NULL;
+
+cleanup:
+ PKIX_DECREF(newList);
+ PKIX_DECREF(object);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_MakeSingleton
+ * DESCRIPTION:
+ *
+ * Creates a new List containing the Object pointed to by "listItem", using
+ * the Boolean value of "immutability" to determine whether to set the List
+ * immutable, and stores the address at "pList".
+ *
+ * PARAMETERS:
+ * "listItem"
+ * Address of Object to be inserted into the new List. Must be non-NULL.
+ * "immutability"
+ * Boolean value indicating whether new List is to be immutable
+ * "pList"
+ * Address where List will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_MakeSingleton(
+ PKIX_PL_Object *listItem,
+ PKIX_Boolean immutability,
+ PKIX_List **pList,
+ void *plContext)
+{
+ PKIX_List *newList = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MakeSingleton");
+ PKIX_NULLCHECK_TWO(listItem, pList);
+
+ PKIX_CHECK(PKIX_List_Create(&newList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (newList, (PKIX_PL_Object *)listItem, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ if (immutability) {
+ PKIX_CHECK(PKIX_List_SetImmutable(newList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+ }
+
+ *pList = newList;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(newList);
+ }
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_Spawn
+ * DESCRIPTION:
+ *
+ * Creates a new childNode for the parent pointed to by "parent", using
+ * the OID pointed to by "policyOID", the List of CertPolicyQualifiers
+ * pointed to by "qualifiers", the List of OIDs pointed to by
+ * "subjectDomainPolicies", and the PolicyCheckerState pointed to by
+ * "state". The new node will be added to "parent".
+ *
+ * The validPolicy of the new node is set from the OID pointed to by
+ * "policyOID". The policy qualifiers for the new node is set from the
+ * List of qualifiers pointed to by "qualifiers", and may be NULL or
+ * empty if the argument provided was NULL or empty. The criticality is
+ * set according to the criticality obtained from the PolicyCheckerState.
+ * If "subjectDomainPolicies" is NULL, the expectedPolicySet of the
+ * child is set to contain the same policy as the validPolicy. If
+ * "subjectDomainPolicies" is not NULL, it is used as the value for
+ * the expectedPolicySet.
+ *
+ * The PolicyCheckerState also contains a constant, anyPolicy, which is
+ * compared to "policyOID". If they match, the address of the childNode
+ * is saved in the state's newAnyPolicyNode.
+ *
+ * PARAMETERS:
+ * "parent"
+ * Address of PolicyNode to which the child will be linked. Must be
+ * non-NULL.
+ * "policyOID"
+ * Address of OID of the new child's validPolicy and also, if
+ * subjectDomainPolicies is NULL, of the new child's expectedPolicySet.
+ * Must be non-NULL.
+ * "qualifiers"
+ * Address of List of CertPolicyQualifiers. May be NULL or empty.
+ * "subjectDomainPolicies"
+ * Address of List of OIDs indicating the policies to which "policy" is
+ * mapped. May be empty or NULL.
+ * "state"
+ * Address of the current PKIX_PolicyCheckerState. Must be non-NULL..
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_Spawn(
+ PKIX_PolicyNode *parent,
+ PKIX_PL_OID *policyOID,
+ PKIX_List *qualifiers, /* CertPolicyQualifiers */
+ PKIX_List *subjectDomainPolicies,
+ PKIX_PolicyCheckerState *state,
+ void *plContext)
+{
+ PKIX_List *expectedSet = NULL; /* OIDs */
+ PKIX_PolicyNode *childNode = NULL;
+ PKIX_Boolean match = PKIX_FALSE;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Spawn");
+ PKIX_NULLCHECK_THREE(policyOID, parent, state);
+
+ if (subjectDomainPolicies) {
+
+ PKIX_INCREF(subjectDomainPolicies);
+ expectedSet = subjectDomainPolicies;
+
+ } else {
+ /* Create the child's ExpectedPolicy Set */
+ PKIX_CHECK(pkix_PolicyChecker_MakeSingleton
+ ((PKIX_PL_Object *)policyOID,
+ PKIX_TRUE, /* make expectedPolicySet immutable */
+ &expectedSet,
+ plContext),
+ PKIX_POLICYCHECKERMAKESINGLETONFAILED);
+ }
+
+ PKIX_CHECK(pkix_PolicyNode_Create
+ (policyOID,
+ qualifiers,
+ state->certPoliciesCritical,
+ expectedSet,
+ &childNode,
+ plContext),
+ PKIX_POLICYNODECREATEFAILED);
+
+ /*
+ * If we had a non-empty mapping, we know the new node could not
+ * have been created with a validPolicy of anyPolicy. Otherwise,
+ * check whether we just created a new node with anyPolicy, because
+ * in that case we want to save the child pointer in newAnyPolicyNode.
+ */
+ if (!subjectDomainPolicies) {
+ PKIX_EQUALS(policyOID, state->anyPolicyOID, &match, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (match) {
+ PKIX_DECREF(state->newAnyPolicyNode);
+ PKIX_INCREF(childNode);
+ state->newAnyPolicyNode = childNode;
+ }
+ }
+
+ PKIX_CHECK(pkix_PolicyNode_AddToParent(parent, childNode, plContext),
+ PKIX_POLICYNODEADDTOPARENTFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+ PKIX_DECREF(childNode);
+ PKIX_DECREF(expectedSet);
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_CheckPolicyRecursive
+ * DESCRIPTION:
+ *
+ * Performs policy processing for the policy whose OID is pointed to by
+ * "policyOID" and whose List of CertPolicyQualifiers is pointed to by
+ * "policyQualifiers", using the List of policy OIDs pointed to by
+ * "subjectDomainPolicies" and the PolicyNode pointed to by "currentNode",
+ * in accordance with the current PolicyCheckerState pointed to by "state",
+ * and setting "pChildNodeCreated" to TRUE if a new childNode is created.
+ * Note: "pChildNodeCreated" is not set to FALSE if no childNode is created.
+ * The intent of the design is that the caller can set a variable to FALSE
+ * initially, prior to a recursive set of calls. At the end, the variable
+ * can be tested to see whether *any* of the calls created a child node.
+ *
+ * If the currentNode is not at the bottom of the tree, this function
+ * calls itself recursively for each child of currentNode. At the bottom of
+ * the tree, it creates new child nodes as appropriate. This function will
+ * never be called with policy = anyPolicy.
+ *
+ * This function implements the processing described in RFC3280
+ * Section 6.1.3(d)(1)(i).
+ *
+ * PARAMETERS:
+ * "policyOID"
+ * Address of OID of the policy to be checked for. Must be non-NULL.
+ * "policyQualifiers"
+ * Address of List of CertPolicyQualifiers of the policy to be checked for.
+ * May be empty or NULL.
+ * "subjectDomainPolicies"
+ * Address of List of OIDs indicating the policies to which "policy" is
+ * mapped. May be empty or NULL.
+ * "currentNode"
+ * Address of PolicyNode whose descendants will be checked, if not at the
+ * bottom of the tree; or whose expectedPolicySet will be compared to
+ * "policy", if at the bottom. Must be non-NULL.
+ * "state"
+ * Address of PolicyCheckerState of the current PolicyChecker. Must be
+ * non-NULL.
+ * "pChildNodeCreated"
+ * Address of the Boolean that will be set TRUE if this function
+ * creates a child node. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_CheckPolicyRecursive(
+ PKIX_PL_OID *policyOID,
+ PKIX_List *policyQualifiers,
+ PKIX_List *subjectDomainPolicies,
+ PKIX_PolicyNode *currentNode,
+ PKIX_PolicyCheckerState *state,
+ PKIX_Boolean *pChildNodeCreated,
+ void *plContext)
+{
+ PKIX_UInt32 depth = 0;
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 childIx = 0;
+ PKIX_Boolean isIncluded = PKIX_FALSE;
+ PKIX_List *children = NULL; /* PolicyNodes */
+ PKIX_PolicyNode *childNode = NULL;
+ PKIX_List *expectedPolicies = NULL; /* OIDs */
+
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "pkix_PolicyChecker_CheckPolicyRecursive");
+ PKIX_NULLCHECK_FOUR(policyOID, currentNode, state, pChildNodeCreated);
+
+ /* if not at the bottom of the tree */
+ PKIX_CHECK(PKIX_PolicyNode_GetDepth
+ (currentNode, &depth, plContext),
+ PKIX_POLICYNODEGETDEPTHFAILED);
+
+ if (depth < (state->certsProcessed)) {
+ PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable
+ (currentNode, &children, plContext),
+ PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED);
+
+ if (children) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ for (childIx = 0; childIx < numChildren; childIx++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (children,
+ childIx,
+ (PKIX_PL_Object **)&childNode,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_CheckPolicyRecursive
+ (policyOID,
+ policyQualifiers,
+ subjectDomainPolicies,
+ childNode,
+ state,
+ pChildNodeCreated,
+ plContext),
+ PKIX_POLICYCHECKERCHECKPOLICYRECURSIVEFAILED);
+
+ PKIX_DECREF(childNode);
+ }
+ } else { /* if at the bottom of the tree */
+
+ /* Check whether policy is in this node's expectedPolicySet */
+ PKIX_CHECK(PKIX_PolicyNode_GetExpectedPolicies
+ (currentNode, &expectedPolicies, plContext),
+ PKIX_POLICYNODEGETEXPECTEDPOLICIESFAILED);
+
+ PKIX_NULLCHECK_ONE(expectedPolicies);
+
+ PKIX_CHECK(pkix_List_Contains
+ (expectedPolicies,
+ (PKIX_PL_Object *)policyOID,
+ &isIncluded,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ if (isIncluded) {
+ PKIX_CHECK(pkix_PolicyChecker_Spawn
+ (currentNode,
+ policyOID,
+ policyQualifiers,
+ subjectDomainPolicies,
+ state,
+ plContext),
+ PKIX_POLICYCHECKERSPAWNFAILED);
+
+ *pChildNodeCreated = PKIX_TRUE;
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(children);
+ PKIX_DECREF(childNode);
+ PKIX_DECREF(expectedPolicies);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_CheckPolicy
+ * DESCRIPTION:
+ *
+ * Performs the non-recursive portion of the policy processing for the policy
+ * whose OID is pointed to by "policyOID" and whose List of
+ * CertPolicyQualifiers is pointed to by "policyQualifiers", for the
+ * Certificate pointed to by "cert" with the List of CertPolicyMaps pointed
+ * to by "maps", in accordance with the current PolicyCheckerState pointed
+ * to by "state".
+ *
+ * This function implements the processing described in RFC3280
+ * Section 6.1.3(d)(1)(i).
+ *
+ * PARAMETERS:
+ * "policyOID"
+ * Address of OID of the policy to be checked for. Must be non-NULL.
+ * "policyQualifiers"
+ * Address of List of CertPolicyQualifiers of the policy to be checked for.
+ * May be empty or NULL.
+ * "cert"
+ * Address of the current certificate. Must be non-NULL.
+ * "maps"
+ * Address of List of CertPolicyMaps for the current certificate
+ * "state"
+ * Address of PolicyCheckerState of the current PolicyChecker. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_CheckPolicy(
+ PKIX_PL_OID *policyOID,
+ PKIX_List *policyQualifiers,
+ PKIX_PL_Cert *cert,
+ PKIX_List *maps,
+ PKIX_PolicyCheckerState *state,
+ void *plContext)
+{
+ PKIX_Boolean childNodeCreated = PKIX_FALSE;
+ PKIX_Boolean okToSpawn = PKIX_FALSE;
+ PKIX_Boolean found = PKIX_FALSE;
+ PKIX_List *subjectDomainPolicies = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_CheckPolicy");
+ PKIX_NULLCHECK_THREE(policyOID, cert, state);
+
+ /*
+ * If this is not the last certificate, get the set of
+ * subjectDomainPolicies that "policy" maps to, according to the
+ * current cert's policy mapping extension. That set will be NULL
+ * if the current cert does not have a policy mapping extension,
+ * or if the current policy is not mapped.
+ */
+ if (state->certsProcessed != (state->numCerts - 1)) {
+ PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies
+ (maps, policyOID, &subjectDomainPolicies, plContext),
+ PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED);
+ }
+
+ /*
+ * Section 6.1.4(b)(2) tells us that if policyMapping is zero, we
+ * will have to delete any nodes created with validPolicies equal to
+ * policies that appear as issuerDomainPolicies in a policy mapping
+ * extension. Let's avoid creating any such nodes.
+ */
+ if ((state->policyMapping) == 0) {
+ if (subjectDomainPolicies) {
+ goto cleanup;
+ }
+ }
+
+ PKIX_CHECK(pkix_PolicyChecker_CheckPolicyRecursive
+ (policyOID,
+ policyQualifiers,
+ subjectDomainPolicies,
+ state->validPolicyTree,
+ state,
+ &childNodeCreated,
+ plContext),
+ PKIX_POLICYCHECKERCHECKPOLICYRECURSIVEFAILED);
+
+ if (!childNodeCreated) {
+ /*
+ * Section 6.1.3(d)(1)(ii)
+ * There was no match. If there was a node at
+ * depth i-1 with valid policy anyPolicy,
+ * generate a node subordinate to that.
+ *
+ * But that means this created node would be in
+ * the valid-policy-node-set, and will be
+ * pruned in 6.1.5(g)(iii)(2) unless it is in
+ * the user-initial-policy-set or the user-
+ * initial-policy-set is {anyPolicy}. So check,
+ * and don't create it if it will be pruned.
+ */
+ if (state->anyPolicyNodeAtBottom) {
+ if (state->initialIsAnyPolicy) {
+ okToSpawn = PKIX_TRUE;
+ } else {
+ PKIX_CHECK(pkix_List_Contains
+ (state->mappedUserInitialPolicySet,
+ (PKIX_PL_Object *)policyOID,
+ &okToSpawn,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ }
+ if (okToSpawn) {
+ PKIX_CHECK(pkix_PolicyChecker_Spawn
+ (state->anyPolicyNodeAtBottom,
+ policyOID,
+ policyQualifiers,
+ subjectDomainPolicies,
+ state,
+ plContext),
+ PKIX_POLICYCHECKERSPAWNFAILED);
+ childNodeCreated = PKIX_TRUE;
+ }
+ }
+ }
+
+ if (childNodeCreated) {
+ /*
+ * If this policy had qualifiers, and the certificate policies
+ * extension was marked critical, and the user cannot deal with
+ * policy qualifiers, throw an error.
+ */
+ if (policyQualifiers &&
+ state->certPoliciesCritical &&
+ state->policyQualifiersRejected) {
+ PKIX_ERROR
+ (PKIX_QUALIFIERSINCRITICALCERTIFICATEPOLICYEXTENSION);
+ }
+ /*
+ * If the policy we just propagated was in the list of mapped
+ * policies, remove it from the list. That list is used, at the
+ * end, to determine policies that have not been propagated.
+ */
+ if (state->mappedPolicyOIDs) {
+ PKIX_CHECK(pkix_List_Contains
+ (state->mappedPolicyOIDs,
+ (PKIX_PL_Object *)policyOID,
+ &found,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ if (found) {
+ PKIX_CHECK(pkix_List_Remove
+ (state->mappedPolicyOIDs,
+ (PKIX_PL_Object *)policyOID,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(subjectDomainPolicies);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_CheckAny
+ * DESCRIPTION:
+ * Performs the creation of PolicyNodes, for the PolicyNode pointed to by
+ * "currentNode" and PolicyNodes subordinate to it, using the List of
+ * qualifiers pointed to by "qualsOfAny", in accordance with the current
+ * certificate's PolicyMaps pointed to by "policyMaps" and the current
+ * PolicyCheckerState pointed to by "state".
+ *
+ * If the currentNode is not just above the bottom of the validPolicyTree, this
+ * function calls itself recursively for each child of currentNode. At the
+ * level just above the bottom, for each policy in the currentNode's
+ * expectedPolicySet not already present in a child node, it creates a new
+ * child node. The validPolicy of the child created, and its expectedPolicySet,
+ * will be the policy from the currentNode's expectedPolicySet. The policy
+ * qualifiers will be the qualifiers from the current certificate's anyPolicy,
+ * the "qualsOfAny" parameter. If the currentNode's expectedSet includes
+ * anyPolicy, a childNode will be created with a policy of anyPolicy. This is
+ * the only way such a node can be created.
+ *
+ * This function is called only when anyPolicy is one of the current
+ * certificate's policies. This function implements the processing described
+ * in RFC3280 Section 6.1.3(d)(2).
+ *
+ * PARAMETERS:
+ * "currentNode"
+ * Address of PolicyNode whose descendants will be checked, if not at the
+ * bottom of the tree; or whose expectedPolicySet will be compared to those
+ * in "alreadyPresent", if at the bottom. Must be non-NULL.
+ * "qualsOfAny"
+ * Address of List of qualifiers of the anyPolicy in the current
+ * certificate. May be empty or NULL.
+ * "policyMaps"
+ * Address of the List of PolicyMaps of the current certificate. May be
+ * empty or NULL.
+ * "state"
+ * Address of the current state of the PKIX_PolicyChecker.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_CheckAny(
+ PKIX_PolicyNode *currentNode,
+ PKIX_List *qualsOfAny, /* CertPolicyQualifiers */
+ PKIX_List *policyMaps, /* CertPolicyMaps */
+ PKIX_PolicyCheckerState *state,
+ void *plContext)
+{
+ PKIX_UInt32 depth = 0;
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 childIx = 0;
+ PKIX_UInt32 numPolicies = 0;
+ PKIX_UInt32 polx = 0;
+ PKIX_Boolean isIncluded = PKIX_FALSE;
+ PKIX_List *children = NULL; /* PolicyNodes */
+ PKIX_PolicyNode *childNode = NULL;
+ PKIX_List *expectedPolicies = NULL; /* OIDs */
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_PL_OID *childPolicy = NULL;
+ PKIX_List *subjectDomainPolicies = NULL; /* OIDs */
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_CheckAny");
+ PKIX_NULLCHECK_TWO(currentNode, state);
+
+ PKIX_CHECK(PKIX_PolicyNode_GetDepth
+ (currentNode, &depth, plContext),
+ PKIX_POLICYNODEGETDEPTHFAILED);
+
+ PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable
+ (currentNode, &children, plContext),
+ PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED);
+
+ if (children) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ if (depth < (state->certsProcessed)) {
+ for (childIx = 0; childIx < numChildren; childIx++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (children,
+ childIx,
+ (PKIX_PL_Object **)&childNode,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_NULLCHECK_ONE(childNode);
+ PKIX_CHECK(pkix_PolicyChecker_CheckAny
+ (childNode,
+ qualsOfAny,
+ policyMaps,
+ state,
+ plContext),
+ PKIX_POLICYCHECKERCHECKANYFAILED);
+
+ PKIX_DECREF(childNode);
+ }
+ } else { /* if at the bottom of the tree */
+
+ PKIX_CHECK(PKIX_PolicyNode_GetExpectedPolicies
+ (currentNode, &expectedPolicies, plContext),
+ PKIX_POLICYNODEGETEXPECTEDPOLICIESFAILED);
+
+ /* Expected Policy Set is not allowed to be NULL */
+ PKIX_NULLCHECK_ONE(expectedPolicies);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (expectedPolicies, &numPolicies, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (polx = 0; polx < numPolicies; polx++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (expectedPolicies,
+ polx,
+ (PKIX_PL_Object **)&policyOID,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_NULLCHECK_ONE(policyOID);
+
+ isIncluded = PKIX_FALSE;
+
+ for (childIx = 0;
+ (!isIncluded && (childIx < numChildren));
+ childIx++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (children,
+ childIx,
+ (PKIX_PL_Object **)&childNode,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_NULLCHECK_ONE(childNode);
+
+ PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy
+ (childNode, &childPolicy, plContext),
+ PKIX_POLICYNODEGETVALIDPOLICYFAILED);
+
+ PKIX_NULLCHECK_ONE(childPolicy);
+
+ PKIX_EQUALS(policyOID, childPolicy, &isIncluded, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(childNode);
+ PKIX_DECREF(childPolicy);
+ }
+
+ if (!isIncluded) {
+ if (policyMaps) {
+ PKIX_CHECK
+ (pkix_PolicyChecker_MapGetSubjectDomainPolicies
+ (policyMaps,
+ policyOID,
+ &subjectDomainPolicies,
+ plContext),
+ PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED);
+ }
+ PKIX_CHECK(pkix_PolicyChecker_Spawn
+ (currentNode,
+ policyOID,
+ qualsOfAny,
+ subjectDomainPolicies,
+ state,
+ plContext),
+ PKIX_POLICYCHECKERSPAWNFAILED);
+ PKIX_DECREF(subjectDomainPolicies);
+ }
+
+ PKIX_DECREF(policyOID);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(children);
+ PKIX_DECREF(childNode);
+ PKIX_DECREF(expectedPolicies);
+ PKIX_DECREF(policyOID);
+ PKIX_DECREF(childPolicy);
+ PKIX_DECREF(subjectDomainPolicies);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_CalculateIntersection
+ * DESCRIPTION:
+ *
+ * Processes the PolicyNode pointed to by "currentNode", and its descendants,
+ * using the PolicyCheckerState pointed to by "state", using the List at
+ * the address pointed to by "nominees" the OIDs of policies that are in the
+ * user-initial-policy-set but are not represented among the nodes at the
+ * bottom of the tree, and storing at "pShouldBePruned" the value TRUE if
+ * currentNode is childless at the end of this processing, FALSE if it has
+ * children or is at the bottom of the tree.
+ *
+ * When this function is called at the top level, "nominees" should be the List
+ * of all policies in the user-initial-policy-set. Policies that are
+ * represented in the valid-policy-node-set are removed from this List. As a
+ * result when nodes are created according to 6.1.5.(g)(iii)(3)(b), a node will
+ * be created for each policy remaining in this List.
+ *
+ * This function implements the calculation of the intersection of the
+ * validPolicyTree with the user-initial-policy-set, as described in
+ * RFC 3280 6.1.5(g)(iii).
+ *
+ * PARAMETERS:
+ * "currentNode"
+ * Address of PolicyNode whose descendants will be processed as described.
+ * Must be non-NULL.
+ * "state"
+ * Address of the current state of the PKIX_PolicyChecker. Must be non-NULL
+ * "nominees"
+ * Address of List of the OIDs for which nodes should be created to replace
+ * anyPolicy nodes. Must be non-NULL but may be empty.
+ * "pShouldBePruned"
+ * Address where Boolean return value, set to TRUE if this PolicyNode
+ * should be deleted, is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_CalculateIntersection(
+ PKIX_PolicyNode *currentNode,
+ PKIX_PolicyCheckerState *state,
+ PKIX_List *nominees, /* OIDs */
+ PKIX_Boolean *pShouldBePruned,
+ void *plContext)
+{
+ PKIX_Boolean currentPolicyIsAny = PKIX_FALSE;
+ PKIX_Boolean parentPolicyIsAny = PKIX_FALSE;
+ PKIX_Boolean currentPolicyIsValid = PKIX_FALSE;
+ PKIX_Boolean shouldBePruned = PKIX_FALSE;
+ PKIX_Boolean priorCriticality = PKIX_FALSE;
+ PKIX_UInt32 depth = 0;
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 childIndex = 0;
+ PKIX_UInt32 numNominees = 0;
+ PKIX_UInt32 polIx = 0;
+ PKIX_PL_OID *currentPolicy = NULL;
+ PKIX_PL_OID *parentPolicy = NULL;
+ PKIX_PL_OID *substPolicy = NULL;
+ PKIX_PolicyNode *parent = NULL;
+ PKIX_PolicyNode *child = NULL;
+ PKIX_List *children = NULL; /* PolicyNodes */
+ PKIX_List *policyQualifiers = NULL;
+
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "pkix_PolicyChecker_CalculateIntersection");
+
+ /*
+ * We call this function if the valid_policy_tree is not NULL and
+ * the user-initial-policy-set is not any-policy.
+ */
+ if (!state->validPolicyTree || state->initialIsAnyPolicy) {
+ PKIX_ERROR(PKIX_PRECONDITIONFAILED);
+ }
+
+ PKIX_NULLCHECK_FOUR(currentNode, state, nominees, pShouldBePruned);
+
+ PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy
+ (currentNode, &currentPolicy, plContext),
+ PKIX_POLICYNODEGETVALIDPOLICYFAILED);
+
+ PKIX_NULLCHECK_TWO(state->anyPolicyOID, currentPolicy);
+
+ PKIX_EQUALS
+ (state->anyPolicyOID,
+ currentPolicy,
+ &currentPolicyIsAny,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_CHECK(PKIX_PolicyNode_GetParent(currentNode, &parent, plContext),
+ PKIX_POLICYNODEGETPARENTFAILED);
+
+ if (currentPolicyIsAny == PKIX_FALSE) {
+
+ /*
+ * If we are at the top of the tree, or if our
+ * parent's validPolicy is anyPolicy, we are in
+ * the valid policy node set.
+ */
+ if (parent) {
+ PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy
+ (parent, &parentPolicy, plContext),
+ PKIX_POLICYNODEGETVALIDPOLICYFAILED);
+
+ PKIX_NULLCHECK_ONE(parentPolicy);
+
+ PKIX_EQUALS
+ (state->anyPolicyOID,
+ parentPolicy,
+ &parentPolicyIsAny,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+ }
+
+ /*
+ * Section 6.1.5(g)(iii)(2)
+ * If this node's policy is not in the user-initial-policy-set,
+ * it is not in the intersection. Prune it.
+ */
+ if (!parent || parentPolicyIsAny) {
+ PKIX_CHECK(pkix_List_Contains
+ (state->userInitialPolicySet,
+ (PKIX_PL_Object *)currentPolicy,
+ &currentPolicyIsValid,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ if (!currentPolicyIsValid) {
+ *pShouldBePruned = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If this node's policy is in the user-initial-policy-
+ * set, it will propagate that policy into the next
+ * level of the tree. Remove the policy from the list
+ * of policies that an anyPolicy will spawn.
+ */
+ PKIX_CHECK(pkix_List_Remove
+ (nominees,
+ (PKIX_PL_Object *)currentPolicy,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+ }
+ }
+
+
+ /* Are we at the bottom of the tree? */
+
+ PKIX_CHECK(PKIX_PolicyNode_GetDepth
+ (currentNode, &depth, plContext),
+ PKIX_POLICYNODEGETDEPTHFAILED);
+
+ if (depth == (state->numCerts)) {
+ /*
+ * Section 6.1.5(g)(iii)(3)
+ * Replace anyPolicy nodes...
+ */
+ if (currentPolicyIsAny == PKIX_TRUE) {
+
+ /* replace this node */
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (nominees, &numNominees, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numNominees) {
+
+ PKIX_CHECK(PKIX_PolicyNode_GetPolicyQualifiers
+ (currentNode,
+ &policyQualifiers,
+ plContext),
+ PKIX_POLICYNODEGETPOLICYQUALIFIERSFAILED);
+
+ PKIX_CHECK(PKIX_PolicyNode_IsCritical
+ (currentNode, &priorCriticality, plContext),
+ PKIX_POLICYNODEISCRITICALFAILED);
+ }
+
+ PKIX_NULLCHECK_ONE(parent);
+
+ for (polIx = 0; polIx < numNominees; polIx++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (nominees,
+ polIx,
+ (PKIX_PL_Object **)&substPolicy,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_Spawn
+ (parent,
+ substPolicy,
+ policyQualifiers,
+ NULL,
+ state,
+ plContext),
+ PKIX_POLICYCHECKERSPAWNFAILED);
+
+ PKIX_DECREF(substPolicy);
+
+ }
+ /* remove currentNode from parent */
+ *pShouldBePruned = PKIX_TRUE;
+ /*
+ * We can get away with augmenting the parent's List
+ * of children because we started at the end and went
+ * toward the beginning. New nodes are added at the end.
+ */
+ }
+ } else {
+ /*
+ * Section 6.1.5(g)(iii)(4)
+ * Prune any childless nodes above the bottom level
+ */
+ PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable
+ (currentNode, &children, plContext),
+ PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED);
+
+ /* CurrentNode should have been pruned if childless. */
+ PKIX_NULLCHECK_ONE(children);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (childIndex = numChildren; childIndex > 0; childIndex--) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (children,
+ childIndex - 1,
+ (PKIX_PL_Object **)&child,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_CalculateIntersection
+ (child, state, nominees, &shouldBePruned, plContext),
+ PKIX_POLICYCHECKERCALCULATEINTERSECTIONFAILED);
+
+ if (PKIX_TRUE == shouldBePruned) {
+
+ PKIX_CHECK(PKIX_List_DeleteItem
+ (children, childIndex - 1, plContext),
+ PKIX_LISTDELETEITEMFAILED);
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ }
+
+ PKIX_DECREF(child);
+ }
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numChildren == 0) {
+ *pShouldBePruned = PKIX_TRUE;
+ }
+ }
+cleanup:
+ PKIX_DECREF(currentPolicy);
+ PKIX_DECREF(parentPolicy);
+ PKIX_DECREF(substPolicy);
+ PKIX_DECREF(parent);
+ PKIX_DECREF(child);
+ PKIX_DECREF(children);
+ PKIX_DECREF(policyQualifiers);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_PolicyMapProcessing
+ * DESCRIPTION:
+ *
+ * Performs the processing of Policies in the List of CertPolicyMaps pointed
+ * to by "policyMaps", using and updating the PolicyCheckerState pointed to by
+ * "state".
+ *
+ * This function implements the policyMap processing described in RFC3280
+ * Section 6.1.4(b)(1), after certificate i has been processed, in preparation
+ * for certificate i+1. Section references are to that document.
+ *
+ * PARAMETERS:
+ * "policyMaps"
+ * Address of the List of CertPolicyMaps presented by certificate i.
+ * Must be non-NULL.
+ * "certPoliciesIncludeAny"
+ * Boolean value which is PKIX_TRUE if the current certificate asserts
+ * anyPolicy, PKIX_FALSE otherwise.
+ * "qualsOfAny"
+ * Address of List of qualifiers of the anyPolicy in the current
+ * certificate. May be empty or NULL.
+ * "state"
+ * Address of the current state of the PKIX_PolicyChecker.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_PolicyMapProcessing(
+ PKIX_List *policyMaps, /* CertPolicyMaps */
+ PKIX_Boolean certPoliciesIncludeAny,
+ PKIX_List *qualsOfAny,
+ PKIX_PolicyCheckerState *state,
+ void *plContext)
+{
+ PKIX_UInt32 numPolicies = 0;
+ PKIX_UInt32 polX = 0;
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_List *newMappedPolicies = NULL; /* OIDs */
+ PKIX_List *subjectDomainPolicies = NULL; /* OIDs */
+
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "pkix_PolicyChecker_PolicyMapProcessing");
+ PKIX_NULLCHECK_THREE
+ (policyMaps,
+ state,
+ state->mappedUserInitialPolicySet);
+
+ /*
+ * For each policy in mappedUserInitialPolicySet, if it is not mapped,
+ * append it to new policySet; if it is mapped, append its
+ * subjectDomainPolicies to new policySet. When done, this new
+ * policySet will replace mappedUserInitialPolicySet.
+ */
+ PKIX_CHECK(PKIX_List_Create
+ (&newMappedPolicies, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->mappedUserInitialPolicySet,
+ &numPolicies,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (polX = 0; polX < numPolicies; polX++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->mappedUserInitialPolicySet,
+ polX,
+ (PKIX_PL_Object **)&policyOID,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies
+ (policyMaps,
+ policyOID,
+ &subjectDomainPolicies,
+ plContext),
+ PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED);
+
+ if (subjectDomainPolicies) {
+
+ PKIX_CHECK(pkix_List_AppendUnique
+ (newMappedPolicies,
+ subjectDomainPolicies,
+ plContext),
+ PKIX_LISTAPPENDUNIQUEFAILED);
+
+ PKIX_DECREF(subjectDomainPolicies);
+
+ } else {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (newMappedPolicies,
+ (PKIX_PL_Object *)policyOID,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+ PKIX_DECREF(policyOID);
+ }
+
+ /*
+ * For each policy ID-P remaining in mappedPolicyOIDs, it has not been
+ * propagated to the bottom of the tree (depth i). If policyMapping
+ * is greater than zero and this cert contains anyPolicy and the tree
+ * contains an anyPolicy node at depth i-1, then we must create a node
+ * with validPolicy ID-P, the policy qualifiers of anyPolicy in
+ * this certificate, and expectedPolicySet the subjectDomainPolicies
+ * that ID-P maps to. We also then add those subjectDomainPolicies to
+ * the list of policies that will be accepted in the next certificate,
+ * the mappedUserInitialPolicySet.
+ */
+
+ if ((state->policyMapping > 0) && (certPoliciesIncludeAny) &&
+ (state->anyPolicyNodeAtBottom) && (state->mappedPolicyOIDs)) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->mappedPolicyOIDs,
+ &numPolicies,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (polX = 0; polX < numPolicies; polX++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->mappedPolicyOIDs,
+ polX,
+ (PKIX_PL_Object **)&policyOID,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies
+ (policyMaps,
+ policyOID,
+ &subjectDomainPolicies,
+ plContext),
+ PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_Spawn
+ (state->anyPolicyNodeAtBottom,
+ policyOID,
+ qualsOfAny,
+ subjectDomainPolicies,
+ state,
+ plContext),
+ PKIX_POLICYCHECKERSPAWNFAILED);
+
+ PKIX_CHECK(pkix_List_AppendUnique
+ (newMappedPolicies,
+ subjectDomainPolicies,
+ plContext),
+ PKIX_LISTAPPENDUNIQUEFAILED);
+
+ PKIX_DECREF(subjectDomainPolicies);
+ PKIX_DECREF(policyOID);
+ }
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(newMappedPolicies, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ PKIX_DECREF(state->mappedUserInitialPolicySet);
+ PKIX_INCREF(newMappedPolicies);
+
+ state->mappedUserInitialPolicySet = newMappedPolicies;
+
+cleanup:
+
+ PKIX_DECREF(policyOID);
+ PKIX_DECREF(newMappedPolicies);
+ PKIX_DECREF(subjectDomainPolicies);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_WrapUpProcessing
+ * DESCRIPTION:
+ *
+ * Performs the wrap-up processing for the Cert pointed to by "cert",
+ * using and updating the PolicyCheckerState pointed to by "state".
+ *
+ * This function implements the wrap-up processing described in RFC3280
+ * Section 6.1.5, after the final certificate has been processed. Section
+ * references in the comments are to that document.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of the current (presumably the end entity) certificate.
+ * Must be non-NULL.
+ * "state"
+ * Address of the current state of the PKIX_PolicyChecker.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+static PKIX_Error *
+pkix_PolicyChecker_WrapUpProcessing(
+ PKIX_PL_Cert *cert,
+ PKIX_PolicyCheckerState *state,
+ void *plContext)
+{
+ PKIX_Int32 explicitPolicySkipCerts = 0;
+ PKIX_Boolean isSelfIssued = PKIX_FALSE;
+ PKIX_Boolean shouldBePruned = PKIX_FALSE;
+ PKIX_List *nominees = NULL; /* OIDs */
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ PKIX_PL_String *stateString = NULL;
+ char *stateAscii = NULL;
+ PKIX_UInt32 length;
+#endif
+
+ PKIX_ENTER
+ (CERTCHAINCHECKER,
+ "pkix_PolicyChecker_WrapUpProcessing");
+ PKIX_NULLCHECK_THREE(cert, state, state->userInitialPolicySet);
+
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)state, &stateString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stateString,
+ PKIX_ESCASCII,
+ (void **)&stateAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_DEBUG_ARG("%s\n", stateAscii);
+
+ PKIX_FREE(stateAscii);
+ PKIX_DECREF(stateString);
+#endif
+
+ /* Section 6.1.5(a) ... */
+ PKIX_CHECK(pkix_IsCertSelfIssued
+ (cert, &isSelfIssued, plContext),
+ PKIX_ISCERTSELFISSUEDFAILED);
+
+ if (!isSelfIssued) {
+ if (state->explicitPolicy > 0) {
+
+ state->explicitPolicy--;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ }
+ }
+
+ /* Section 6.1.5(b) ... */
+ PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy
+ (cert, &explicitPolicySkipCerts, plContext),
+ PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED);
+
+ if (explicitPolicySkipCerts == 0) {
+ state->explicitPolicy = 0;
+ }
+
+ /* Section 6.1.5(g)(i) ... */
+
+ if (!(state->validPolicyTree)) {
+ goto cleanup;
+ }
+
+ /* Section 6.1.5(g)(ii) ... */
+
+ if (state->initialIsAnyPolicy) {
+ goto cleanup;
+ }
+
+ /*
+ * Section 6.1.5(g)(iii) ...
+ * Create a list of policies which could be substituted for anyPolicy.
+ * Start with a (mutable) copy of user-initial-policy-set.
+ */
+ PKIX_CHECK(pkix_PolicyChecker_MakeMutableCopy
+ (state->userInitialPolicySet, &nominees, plContext),
+ PKIX_POLICYCHECKERMAKEMUTABLECOPYFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_CalculateIntersection
+ (state->validPolicyTree, /* node at top of tree */
+ state,
+ nominees,
+ &shouldBePruned,
+ plContext),
+ PKIX_POLICYCHECKERCALCULATEINTERSECTIONFAILED);
+
+ if (PKIX_TRUE == shouldBePruned) {
+ PKIX_DECREF(state->validPolicyTree);
+ }
+
+ if (state->validPolicyTree) {
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state->validPolicyTree, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ if (state->validPolicyTree) {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)state, &stateString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stateString,
+ PKIX_ESCASCII,
+ (void **)&stateAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_DEBUG_ARG
+ ("After CalculateIntersection:\n%s\n", stateAscii);
+
+ PKIX_FREE(stateAscii);
+ PKIX_DECREF(stateString);
+ } else {
+ PKIX_DEBUG("validPolicyTree is NULL\n");
+ }
+#endif
+
+ /* Section 6.1.5(g)(iii)(4) ... */
+
+ if (state->validPolicyTree) {
+
+ PKIX_CHECK(pkix_PolicyNode_Prune
+ (state->validPolicyTree,
+ state->numCerts,
+ &shouldBePruned,
+ plContext),
+ PKIX_POLICYNODEPRUNEFAILED);
+
+ if (shouldBePruned) {
+ PKIX_DECREF(state->validPolicyTree);
+ }
+ }
+
+ if (state->validPolicyTree) {
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state->validPolicyTree, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)state, &stateString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stateString,
+ PKIX_ESCASCII,
+ (void **)&stateAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+ PKIX_DEBUG_ARG("%s\n", stateAscii);
+
+ PKIX_FREE(stateAscii);
+ PKIX_DECREF(stateString);
+#endif
+
+cleanup:
+
+ PKIX_DECREF(nominees);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+
+/*
+ * FUNCTION: pkix_PolicyChecker_Check
+ * (see comments in pkix_checker.h for PKIX_CertChainChecker_CheckCallback)
+ *
+ * Labels referring to sections, such as "Section 6.1.3(d)", refer to
+ * sections of RFC3280, Section 6.1.3 Basic Certificate Processing.
+ *
+ * If a non-fatal error occurs, it is unlikely that policy processing can
+ * continue. But it is still possible that chain validation could succeed if
+ * policy processing is non-critical. So if this function receives a non-fatal
+ * error from a lower level routine, it aborts policy processing by setting
+ * the validPolicyTree to NULL and tries to continue.
+ *
+ */
+static PKIX_Error *
+pkix_PolicyChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticals, /* OIDs */
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_UInt32 numPolicies = 0;
+ PKIX_UInt32 polX = 0;
+ PKIX_Boolean result = PKIX_FALSE;
+ PKIX_Int32 inhibitMappingSkipCerts = 0;
+ PKIX_Int32 explicitPolicySkipCerts = 0;
+ PKIX_Int32 inhibitAnyPolicySkipCerts = 0;
+ PKIX_Boolean shouldBePruned = PKIX_FALSE;
+ PKIX_Boolean isSelfIssued = PKIX_FALSE;
+ PKIX_Boolean certPoliciesIncludeAny = PKIX_FALSE;
+ PKIX_Boolean doAnyPolicyProcessing = PKIX_FALSE;
+
+ PKIX_PolicyCheckerState *state = NULL;
+ PKIX_List *certPolicyInfos = NULL; /* CertPolicyInfos */
+ PKIX_PL_CertPolicyInfo *policy = NULL;
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_List *qualsOfAny = NULL; /* CertPolicyQualifiers */
+ PKIX_List *policyQualifiers = NULL; /* CertPolicyQualifiers */
+ PKIX_List *policyMaps = NULL; /* CertPolicyMaps */
+ PKIX_List *mappedPolicies = NULL; /* OIDs */
+ PKIX_Error *subroutineErr = NULL;
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ PKIX_PL_String *stateString = NULL;
+ char *stateAscii = NULL;
+ PKIX_PL_String *certString = NULL;
+ char *certAscii = NULL;
+ PKIX_UInt32 length;
+#endif
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Check");
+ PKIX_NULLCHECK_FOUR(checker, cert, unresolvedCriticals, pNBIOContext);
+
+ *pNBIOContext = NULL; /* we never block on pending I/O */
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
+ (checker, (PKIX_PL_Object **)&state, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ PKIX_NULLCHECK_TWO(state, state->certPoliciesExtension);
+
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)state, &stateString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stateString,
+ PKIX_ESCASCII,
+ (void **)&stateAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+ PKIX_DEBUG_ARG("On entry %s\n", stateAscii);
+ PKIX_FREE(stateAscii);
+ PKIX_DECREF(stateString);
+#endif
+
+ /*
+ * Section 6.1.4(a)
+ * If this is not the last certificate, and if
+ * policyMapping extension is present, check that no
+ * issuerDomainPolicy or subjectDomainPolicy is equal to the
+ * special policy anyPolicy.
+ */
+ if (state->certsProcessed != (state->numCerts - 1)) {
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings
+ (cert, &policyMaps, plContext),
+ PKIX_CERTGETPOLICYMAPPINGSFAILED);
+ }
+
+ if (policyMaps) {
+
+ PKIX_CHECK(pkix_PolicyChecker_MapContains
+ (policyMaps, state->anyPolicyOID, &result, plContext),
+ PKIX_POLICYCHECKERMAPCONTAINSFAILED);
+
+ if (result) {
+ PKIX_ERROR(PKIX_INVALIDPOLICYMAPPINGINCLUDESANYPOLICY);
+ }
+
+ PKIX_CHECK(pkix_PolicyChecker_MapGetMappedPolicies
+ (policyMaps, &mappedPolicies, plContext),
+ PKIX_POLICYCHECKERMAPGETMAPPEDPOLICIESFAILED);
+
+ PKIX_DECREF(state->mappedPolicyOIDs);
+ PKIX_INCREF(mappedPolicies);
+ state->mappedPolicyOIDs = mappedPolicies;
+ }
+
+ /* Section 6.1.3(d) */
+ if (state->validPolicyTree) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation
+ (cert, &certPolicyInfos, plContext),
+ PKIX_CERTGETPOLICYINFORMATIONFAILED);
+
+ if (certPolicyInfos) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (certPolicyInfos, &numPolicies, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ if (numPolicies > 0) {
+
+ PKIX_CHECK(PKIX_PL_Cert_AreCertPoliciesCritical
+ (cert, &(state->certPoliciesCritical), plContext),
+ PKIX_CERTARECERTPOLICIESCRITICALFAILED);
+
+ /* Section 6.1.3(d)(1) For each policy not equal to anyPolicy */
+ for (polX = 0; polX < numPolicies; polX++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (certPolicyInfos,
+ polX,
+ (PKIX_PL_Object **)&policy,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolicyId
+ (policy, &policyOID, plContext),
+ PKIX_CERTPOLICYINFOGETPOLICYIDFAILED);
+
+ PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolQualifiers
+ (policy, &policyQualifiers, plContext),
+ PKIX_CERTPOLICYINFOGETPOLQUALIFIERSFAILED);
+
+ PKIX_EQUALS
+ (state->anyPolicyOID,
+ policyOID,
+ &result,
+ plContext,
+ PKIX_OIDEQUALFAILED);
+
+ if (result == PKIX_FALSE) {
+
+ /* Section 6.1.3(d)(1)(i) */
+ subroutineErr = pkix_PolicyChecker_CheckPolicy
+ (policyOID,
+ policyQualifiers,
+ cert,
+ policyMaps,
+ state,
+ plContext);
+ if (subroutineErr) {
+ goto subrErrorCleanup;
+ }
+
+ } else {
+ /*
+ * No descent (yet) for anyPolicy, but we will need
+ * the policyQualifiers for anyPolicy in 6.1.3(d)(2)
+ */
+ PKIX_DECREF(qualsOfAny);
+ PKIX_INCREF(policyQualifiers);
+ qualsOfAny = policyQualifiers;
+ certPoliciesIncludeAny = PKIX_TRUE;
+ }
+ PKIX_DECREF(policy);
+ PKIX_DECREF(policyOID);
+ PKIX_DECREF(policyQualifiers);
+ }
+
+ /* Section 6.1.3(d)(2) */
+ if (certPoliciesIncludeAny == PKIX_TRUE) {
+ if (state->inhibitAnyPolicy > 0) {
+ doAnyPolicyProcessing = PKIX_TRUE;
+ } else {
+ /* We haven't yet counted the current cert */
+ if (((state->certsProcessed) + 1) <
+ (state->numCerts)) {
+
+ PKIX_CHECK(pkix_IsCertSelfIssued
+ (cert,
+ &doAnyPolicyProcessing,
+ plContext),
+ PKIX_ISCERTSELFISSUEDFAILED);
+ }
+ }
+ if (doAnyPolicyProcessing) {
+ subroutineErr = pkix_PolicyChecker_CheckAny
+ (state->validPolicyTree,
+ qualsOfAny,
+ policyMaps,
+ state,
+ plContext);
+ if (subroutineErr) {
+ goto subrErrorCleanup;
+ }
+ }
+ }
+
+ /* Section 6.1.3(d)(3) */
+ if (state->validPolicyTree) {
+ subroutineErr = pkix_PolicyNode_Prune
+ (state->validPolicyTree,
+ state->certsProcessed + 1,
+ &shouldBePruned,
+ plContext);
+ if (subroutineErr) {
+ goto subrErrorCleanup;
+ }
+ if (shouldBePruned) {
+ PKIX_DECREF(state->validPolicyTree);
+ PKIX_DECREF(state->anyPolicyNodeAtBottom);
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ } else {
+ /* Section 6.1.3(e) */
+ PKIX_DECREF(state->validPolicyTree);
+ PKIX_DECREF(state->anyPolicyNodeAtBottom);
+ PKIX_DECREF(state->newAnyPolicyNode);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ }
+ }
+
+ /* Section 6.1.3(f) */
+ if ((0 == state->explicitPolicy) && (!state->validPolicyTree)) {
+ PKIX_ERROR(PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION);
+ }
+
+ /*
+ * Remove Policy OIDs from list of unresolved critical
+ * extensions, if present.
+ */
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticals,
+ (PKIX_PL_Object *)state->certPoliciesExtension,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticals,
+ (PKIX_PL_Object *)state->policyMappingsExtension,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticals,
+ (PKIX_PL_Object *)state->policyConstraintsExtension,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticals,
+ (PKIX_PL_Object *)state->inhibitAnyPolicyExtension,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+
+ state->certsProcessed++;
+
+ /* If this was not the last certificate, do next-cert preparation */
+ if (state->certsProcessed != state->numCerts) {
+
+ if (policyMaps) {
+ subroutineErr = pkix_PolicyChecker_PolicyMapProcessing
+ (policyMaps,
+ certPoliciesIncludeAny,
+ qualsOfAny,
+ state,
+ plContext);
+ if (subroutineErr) {
+ goto subrErrorCleanup;
+ }
+ }
+
+ /* update anyPolicyNodeAtBottom pointer */
+ PKIX_DECREF(state->anyPolicyNodeAtBottom);
+ state->anyPolicyNodeAtBottom = state->newAnyPolicyNode;
+ state->newAnyPolicyNode = NULL;
+
+ /* Section 6.1.4(h) */
+ PKIX_CHECK(pkix_IsCertSelfIssued
+ (cert, &isSelfIssued, plContext),
+ PKIX_ISCERTSELFISSUEDFAILED);
+
+ if (!isSelfIssued) {
+ if (state->explicitPolicy > 0) {
+ state->explicitPolicy--;
+ }
+ if (state->policyMapping > 0) {
+ state->policyMapping--;
+ }
+ if (state->inhibitAnyPolicy > 0) {
+ state->inhibitAnyPolicy--;
+ }
+ }
+
+ /* Section 6.1.4(i) */
+ PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy
+ (cert, &explicitPolicySkipCerts, plContext),
+ PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED);
+
+ if (explicitPolicySkipCerts != -1) {
+ if (((PKIX_UInt32)explicitPolicySkipCerts) <
+ (state->explicitPolicy)) {
+ state->explicitPolicy =
+ ((PKIX_UInt32) explicitPolicySkipCerts);
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited
+ (cert, &inhibitMappingSkipCerts, plContext),
+ PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED);
+
+ if (inhibitMappingSkipCerts != -1) {
+ if (((PKIX_UInt32)inhibitMappingSkipCerts) <
+ (state->policyMapping)) {
+ state->policyMapping =
+ ((PKIX_UInt32)inhibitMappingSkipCerts);
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy
+ (cert, &inhibitAnyPolicySkipCerts, plContext),
+ PKIX_CERTGETINHIBITANYPOLICYFAILED);
+
+ if (inhibitAnyPolicySkipCerts != -1) {
+ if (((PKIX_UInt32)inhibitAnyPolicySkipCerts) <
+ (state->inhibitAnyPolicy)) {
+ state->inhibitAnyPolicy =
+ ((PKIX_UInt32)inhibitAnyPolicySkipCerts);
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ } else { /* If this was the last certificate, do wrap-up processing */
+
+ /* Section 6.1.5 */
+ subroutineErr = pkix_PolicyChecker_WrapUpProcessing
+ (cert, state, plContext);
+ if (subroutineErr) {
+ goto subrErrorCleanup;
+ }
+
+ if ((0 == state->explicitPolicy) && (!state->validPolicyTree)) {
+ PKIX_ERROR(PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION);
+ }
+
+ PKIX_DECREF(state->anyPolicyNodeAtBottom);
+ PKIX_DECREF(state->newAnyPolicyNode);
+ }
+
+
+ if (subroutineErr) {
+
+subrErrorCleanup:
+ /* We had an error. Was it a fatal error? */
+ pkixErrorClass = subroutineErr->errClass;
+ if (pkixErrorClass == PKIX_FATAL_ERROR) {
+ pkixErrorResult = subroutineErr;
+ subroutineErr = NULL;
+ goto cleanup;
+ }
+ /*
+ * Abort policy processing, and then determine whether
+ * we can continue without policy processing.
+ */
+ PKIX_DECREF(state->validPolicyTree);
+ PKIX_DECREF(state->anyPolicyNodeAtBottom);
+ PKIX_DECREF(state->newAnyPolicyNode);
+ if (state->explicitPolicy == 0) {
+ PKIX_ERROR
+ (PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION);
+ }
+ }
+
+ /* Checking is complete. Save state for the next certificate. */
+ PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
+ (checker, (PKIX_PL_Object *)state, plContext),
+ PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
+
+cleanup:
+
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+ if (cert) {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)cert, &certString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (certString,
+ PKIX_ESCASCII,
+ (void **)&certAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+ PKIX_DEBUG_ARG("Cert was %s\n", certAscii);
+ PKIX_FREE(certAscii);
+ PKIX_DECREF(certString);
+ }
+ if (state) {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)state, &stateString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stateString,
+ PKIX_ESCASCII,
+ (void **)&stateAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+ PKIX_DEBUG_ARG("On exit %s\n", stateAscii);
+ PKIX_FREE(stateAscii);
+ PKIX_DECREF(stateString);
+ }
+#endif
+
+ PKIX_DECREF(state);
+ PKIX_DECREF(certPolicyInfos);
+ PKIX_DECREF(policy);
+ PKIX_DECREF(qualsOfAny);
+ PKIX_DECREF(policyQualifiers);
+ PKIX_DECREF(policyOID);
+ PKIX_DECREF(subroutineErr);
+ PKIX_DECREF(policyMaps);
+ PKIX_DECREF(mappedPolicies);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_PolicyChecker_Initialize
+ * DESCRIPTION:
+ *
+ * Creates and initializes a PolicyChecker, using the List pointed to
+ * by "initialPolicies" for the user-initial-policy-set, the Boolean value
+ * of "policyQualifiersRejected" for the policyQualifiersRejected parameter,
+ * the Boolean value of "initialPolicyMappingInhibit" for the
+ * inhibitPolicyMappings parameter, the Boolean value of
+ * "initialExplicitPolicy" for the initialExplicitPolicy parameter, the
+ * Boolean value of "initialAnyPolicyInhibit" for the inhibitAnyPolicy
+ * parameter, and the UInt32 value of "numCerts" as the number of
+ * certificates in the chain; and stores the Checker at "pChecker".
+ *
+ * PARAMETERS:
+ * "initialPolicies"
+ * Address of List of OIDs comprising the user-initial-policy-set; the List
+ * may be empty or NULL
+ * "policyQualifiersRejected"
+ * Boolean value of the policyQualifiersRejected parameter
+ * "initialPolicyMappingInhibit"
+ * Boolean value of the inhibitPolicyMappings parameter
+ * "initialExplicitPolicy"
+ * Boolean value of the initialExplicitPolicy parameter
+ * "initialAnyPolicyInhibit"
+ * Boolean value of the inhibitAnyPolicy parameter
+ * "numCerts"
+ * Number of certificates in the chain to be validated
+ * "pChecker"
+ * Address to store the created PolicyChecker. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a CertChainChecker Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_PolicyChecker_Initialize(
+ PKIX_List *initialPolicies,
+ PKIX_Boolean policyQualifiersRejected,
+ PKIX_Boolean initialPolicyMappingInhibit,
+ PKIX_Boolean initialExplicitPolicy,
+ PKIX_Boolean initialAnyPolicyInhibit,
+ PKIX_UInt32 numCerts,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ PKIX_PolicyCheckerState *polCheckerState = NULL;
+ PKIX_List *policyExtensions = NULL; /* OIDs */
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Initialize");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ PKIX_CHECK(pkix_PolicyCheckerState_Create
+ (initialPolicies,
+ policyQualifiersRejected,
+ initialPolicyMappingInhibit,
+ initialExplicitPolicy,
+ initialAnyPolicyInhibit,
+ numCerts,
+ &polCheckerState,
+ plContext),
+ PKIX_POLICYCHECKERSTATECREATEFAILED);
+
+ /* Create the list of extensions that we handle */
+ PKIX_CHECK(pkix_PolicyChecker_MakeSingleton
+ ((PKIX_PL_Object *)(polCheckerState->certPoliciesExtension),
+ PKIX_TRUE,
+ &policyExtensions,
+ plContext),
+ PKIX_POLICYCHECKERMAKESINGLETONFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_PolicyChecker_Check,
+ PKIX_FALSE, /* forwardCheckingSupported */
+ PKIX_FALSE,
+ policyExtensions,
+ (PKIX_PL_Object *)polCheckerState,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+cleanup:
+ PKIX_DECREF(polCheckerState);
+ PKIX_DECREF(policyExtensions);
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.h
new file mode 100644
index 0000000000..8b87ac1224
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_policychecker.h
@@ -0,0 +1,73 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_policychecker.h
+ *
+ * Header file for policy checker.
+ *
+ */
+
+#ifndef _PKIX_POLICYCHECKER_H
+#define _PKIX_POLICYCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct PKIX_PolicyCheckerStateStruct PKIX_PolicyCheckerState;
+
+struct PKIX_PolicyCheckerStateStruct{
+ PKIX_PL_OID *certPoliciesExtension; /* const */
+ PKIX_PL_OID *policyMappingsExtension; /* const */
+ PKIX_PL_OID *policyConstraintsExtension; /* const */
+ PKIX_PL_OID *inhibitAnyPolicyExtension; /* const */
+ PKIX_PL_OID *anyPolicyOID; /* const */
+ PKIX_Boolean initialIsAnyPolicy; /* const */
+ PKIX_PolicyNode *validPolicyTree;
+ PKIX_List *userInitialPolicySet; /* immutable */
+ PKIX_List *mappedUserInitialPolicySet;
+ PKIX_Boolean policyQualifiersRejected;
+ PKIX_Boolean initialPolicyMappingInhibit;
+ PKIX_Boolean initialExplicitPolicy;
+ PKIX_Boolean initialAnyPolicyInhibit;
+ PKIX_UInt32 explicitPolicy;
+ PKIX_UInt32 inhibitAnyPolicy;
+ PKIX_UInt32 policyMapping;
+ PKIX_UInt32 numCerts;
+ PKIX_UInt32 certsProcessed;
+ PKIX_PolicyNode *anyPolicyNodeAtBottom;
+ PKIX_PolicyNode *newAnyPolicyNode;
+ /*
+ * The following variables do not survive from one
+ * certificate to the next. They are needed at each
+ * level of recursive routines, any by placing them
+ * in the state object we can pass fewer arguments.
+ */
+ PKIX_Boolean certPoliciesCritical;
+ PKIX_List *mappedPolicyOIDs;
+};
+
+PKIX_Error *
+pkix_PolicyChecker_Initialize(
+ PKIX_List *initialPolicies,
+ PKIX_Boolean policyQualifiersRejected,
+ PKIX_Boolean initialPolicyMappingInhibit,
+ PKIX_Boolean initialExplicitPolicy,
+ PKIX_Boolean initialAnyPolicyInhibit,
+ PKIX_UInt32 numCerts,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+/* --Private-Functions-------------------------------------------- */
+
+PKIX_Error *
+pkix_PolicyCheckerState_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_POLICYCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c
new file mode 100644
index 0000000000..7bed9b8860
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.c
@@ -0,0 +1,475 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_revocationchecker.c
+ *
+ * RevocationChecker Object Functions
+ *
+ */
+
+#include "pkix_revocationchecker.h"
+#include "pkix_tools.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_RevocationChecker_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_RevocationChecker_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_RevocationChecker *checker = NULL;
+
+ PKIX_ENTER(REVOCATIONCHECKER, "pkix_RevocationChecker_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a revocation checker */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_REVOCATIONCHECKER_TYPE, plContext),
+ PKIX_OBJECTNOTREVOCATIONCHECKER);
+
+ checker = (PKIX_RevocationChecker *)object;
+
+ PKIX_DECREF(checker->leafMethodList);
+ PKIX_DECREF(checker->chainMethodList);
+
+cleanup:
+
+ PKIX_RETURN(REVOCATIONCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_RevocationChecker_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_RevocationChecker_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_RevocationChecker *checker = NULL;
+ PKIX_RevocationChecker *checkerDuplicate = NULL;
+ PKIX_List *dupLeafList = NULL;
+ PKIX_List *dupChainList = NULL;
+
+ PKIX_ENTER(REVOCATIONCHECKER, "pkix_RevocationChecker_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_REVOCATIONCHECKER_TYPE, plContext),
+ PKIX_OBJECTNOTCERTCHAINCHECKER);
+
+ checker = (PKIX_RevocationChecker *)object;
+
+ if (checker->leafMethodList){
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)checker->leafMethodList,
+ (PKIX_PL_Object **)&dupLeafList,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+ }
+ if (checker->chainMethodList){
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)checker->chainMethodList,
+ (PKIX_PL_Object **)&dupChainList,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+ }
+
+ PKIX_CHECK(
+ PKIX_RevocationChecker_Create(checker->leafMethodListFlags,
+ checker->chainMethodListFlags,
+ &checkerDuplicate,
+ plContext),
+ PKIX_REVOCATIONCHECKERCREATEFAILED);
+
+ checkerDuplicate->leafMethodList = dupLeafList;
+ checkerDuplicate->chainMethodList = dupChainList;
+ dupLeafList = NULL;
+ dupChainList = NULL;
+
+ *pNewObject = (PKIX_PL_Object *)checkerDuplicate;
+
+cleanup:
+ PKIX_DECREF(dupLeafList);
+ PKIX_DECREF(dupChainList);
+
+ PKIX_RETURN(REVOCATIONCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_RevocationChecker_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_REVOCATIONCHECKER_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_RevocationChecker_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(REVOCATIONCHECKER, "pkix_RevocationChecker_RegisterSelf");
+
+ entry.description = "RevocationChecker";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_RevocationChecker);
+ entry.destructor = pkix_RevocationChecker_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_RevocationChecker_Duplicate;
+
+ systemClasses[PKIX_REVOCATIONCHECKER_TYPE] = entry;
+
+ PKIX_RETURN(REVOCATIONCHECKER);
+}
+
+/* Sort methods by their priorities (lower priority = higher preference) */
+static PKIX_Error *
+pkix_RevocationChecker_SortComparator(
+ PKIX_PL_Object *obj1,
+ PKIX_PL_Object *obj2,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ pkix_RevocationMethod *method1 = NULL, *method2 = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_RevocationChecker_SortComparator");
+
+ method1 = (pkix_RevocationMethod *)obj1;
+ method2 = (pkix_RevocationMethod *)obj2;
+
+ if (method1->priority < method2->priority) {
+ *pResult = -1;
+ } else if (method1->priority > method2->priority) {
+ *pResult = 1;
+ } else {
+ *pResult = 0;
+ }
+
+ PKIX_RETURN(BUILD);
+}
+
+
+/* --Public-Functions--------------------------------------------- */
+
+
+/*
+ * FUNCTION: PKIX_RevocationChecker_Create (see comments in pkix_revchecker.h)
+ */
+PKIX_Error *
+PKIX_RevocationChecker_Create(
+ PKIX_UInt32 leafMethodListFlags,
+ PKIX_UInt32 chainMethodListFlags,
+ PKIX_RevocationChecker **pChecker,
+ void *plContext)
+{
+ PKIX_RevocationChecker *checker = NULL;
+
+ PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_Create");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ PKIX_CHECK(
+ PKIX_PL_Object_Alloc(PKIX_REVOCATIONCHECKER_TYPE,
+ sizeof (PKIX_RevocationChecker),
+ (PKIX_PL_Object **)&checker,
+ plContext),
+ PKIX_COULDNOTCREATECERTCHAINCHECKEROBJECT);
+
+ checker->leafMethodListFlags = leafMethodListFlags;
+ checker->chainMethodListFlags = chainMethodListFlags;
+ checker->leafMethodList = NULL;
+ checker->chainMethodList = NULL;
+
+ *pChecker = checker;
+ checker = NULL;
+
+cleanup:
+ PKIX_DECREF(checker);
+
+ PKIX_RETURN(REVOCATIONCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_RevocationChecker_CreateAndAddMethod
+ */
+PKIX_Error *
+PKIX_RevocationChecker_CreateAndAddMethod(
+ PKIX_RevocationChecker *revChecker,
+ PKIX_ProcessingParams *params,
+ PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 flags,
+ PKIX_UInt32 priority,
+ PKIX_PL_VerifyCallback verificationFn,
+ PKIX_Boolean isLeafMethod,
+ void *plContext)
+{
+ PKIX_List **methodList = NULL;
+ PKIX_List *unsortedList = NULL;
+ PKIX_List *certStores = NULL;
+ pkix_RevocationMethod *method = NULL;
+ pkix_LocalRevocationCheckFn *localRevChecker = NULL;
+ pkix_ExternalRevocationCheckFn *externRevChecker = NULL;
+ PKIX_UInt32 miFlags;
+
+ PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_CreateAndAddMethod");
+ PKIX_NULLCHECK_ONE(revChecker);
+
+ /* If the caller has said "Either one is sufficient, then don't let the
+ * absence of any one method's info lead to an overall failure.
+ */
+ miFlags = isLeafMethod ? revChecker->leafMethodListFlags
+ : revChecker->chainMethodListFlags;
+ if (miFlags & PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE)
+ flags &= ~PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO;
+
+ switch (methodType) {
+ case PKIX_RevocationMethod_CRL:
+ localRevChecker = pkix_CrlChecker_CheckLocal;
+ externRevChecker = pkix_CrlChecker_CheckExternal;
+ PKIX_CHECK(
+ PKIX_ProcessingParams_GetCertStores(params, &certStores,
+ plContext),
+ PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
+ PKIX_CHECK(
+ pkix_CrlChecker_Create(methodType, flags, priority,
+ localRevChecker, externRevChecker,
+ certStores, verificationFn,
+ &method,
+ plContext),
+ PKIX_COULDNOTCREATECRLCHECKEROBJECT);
+ break;
+ case PKIX_RevocationMethod_OCSP:
+ localRevChecker = pkix_OcspChecker_CheckLocal;
+ externRevChecker = pkix_OcspChecker_CheckExternal;
+ PKIX_CHECK(
+ pkix_OcspChecker_Create(methodType, flags, priority,
+ localRevChecker, externRevChecker,
+ verificationFn,
+ &method,
+ plContext),
+ PKIX_COULDNOTCREATEOCSPCHECKEROBJECT);
+ break;
+ default:
+ PKIX_ERROR(PKIX_INVALIDREVOCATIONMETHOD);
+ }
+
+ if (isLeafMethod) {
+ methodList = &revChecker->leafMethodList;
+ } else {
+ methodList = &revChecker->chainMethodList;
+ }
+
+ if (*methodList == NULL) {
+ PKIX_CHECK(
+ PKIX_List_Create(methodList, plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+ unsortedList = *methodList;
+ PKIX_CHECK(
+ PKIX_List_AppendItem(unsortedList, (PKIX_PL_Object*)method, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_CHECK(
+ pkix_List_BubbleSort(unsortedList,
+ pkix_RevocationChecker_SortComparator,
+ methodList, plContext),
+ PKIX_LISTBUBBLESORTFAILED);
+
+cleanup:
+ PKIX_DECREF(method);
+ PKIX_DECREF(unsortedList);
+ PKIX_DECREF(certStores);
+
+ PKIX_RETURN(REVOCATIONCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_RevocationChecker_Check
+ */
+PKIX_Error *
+PKIX_RevocationChecker_Check(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Cert *issuer,
+ PKIX_RevocationChecker *revChecker,
+ PKIX_ProcessingParams *procParams,
+ PKIX_Boolean chainVerificationState,
+ PKIX_Boolean testingLeafCert,
+ PKIX_RevocationStatus *pRevStatus,
+ PKIX_UInt32 *pReasonCode,
+ void **pNbioContext,
+ void *plContext)
+{
+ PKIX_RevocationStatus overallStatus = PKIX_RevStatus_NoInfo;
+ PKIX_RevocationStatus methodStatus[PKIX_RevocationMethod_MAX];
+ PKIX_Boolean onlyUseRemoteMethods = PKIX_FALSE;
+ PKIX_UInt32 revFlags = 0;
+ PKIX_List *revList = NULL;
+ PKIX_PL_Date *date = NULL;
+ pkix_RevocationMethod *method = NULL;
+ void *nbioContext;
+ int tries;
+
+ PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_Check");
+ PKIX_NULLCHECK_TWO(revChecker, procParams);
+
+ nbioContext = *pNbioContext;
+ *pNbioContext = NULL;
+
+ if (testingLeafCert) {
+ revList = revChecker->leafMethodList;
+ revFlags = revChecker->leafMethodListFlags;
+ } else {
+ revList = revChecker->chainMethodList;
+ revFlags = revChecker->chainMethodListFlags;
+ }
+ if (!revList) {
+ /* Return NoInfo status */
+ goto cleanup;
+ }
+
+ PORT_Memset(methodStatus, PKIX_RevStatus_NoInfo,
+ sizeof(PKIX_RevocationStatus) * PKIX_RevocationMethod_MAX);
+
+ date = procParams->date;
+
+ /* Need to have two loops if we testing all local info first:
+ * first we are going to test all local(cached) info
+ * second, all remote info(fetching) */
+ for (tries = 0;tries < 2;tries++) {
+ unsigned int methodNum = 0;
+ for (;methodNum < revList->length;methodNum++) {
+ PKIX_UInt32 methodFlags = 0;
+
+ PKIX_DECREF(method);
+ PKIX_CHECK(
+ PKIX_List_GetItem(revList, methodNum,
+ (PKIX_PL_Object**)&method, plContext),
+ PKIX_LISTGETITEMFAILED);
+ methodFlags = method->flags;
+ if (!(methodFlags & PKIX_REV_M_TEST_USING_THIS_METHOD)) {
+ /* Will not check with this method. Skipping... */
+ continue;
+ }
+ if (!onlyUseRemoteMethods &&
+ methodStatus[methodNum] == PKIX_RevStatus_NoInfo) {
+ PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
+ PKIX_CHECK_NO_GOTO(
+ (*method->localRevChecker)(cert, issuer, date,
+ method, procParams,
+ methodFlags,
+ chainVerificationState,
+ &revStatus,
+ (CERTCRLEntryReasonCode *)pReasonCode,
+ plContext),
+ PKIX_REVCHECKERCHECKFAILED);
+ methodStatus[methodNum] = revStatus;
+ if (revStatus == PKIX_RevStatus_Revoked) {
+ /* if error was generated use it as final error. */
+ overallStatus = PKIX_RevStatus_Revoked;
+ goto cleanup;
+ }
+ if (pkixErrorResult) {
+ /* Disregard errors. Only returned revStatus matters. */
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorResult,
+ plContext);
+ pkixErrorResult = NULL;
+ }
+ }
+ if ((!(revFlags & PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST) ||
+ onlyUseRemoteMethods) &&
+ chainVerificationState &&
+ methodStatus[methodNum] == PKIX_RevStatus_NoInfo) {
+ if (!(methodFlags & PKIX_REV_M_FORBID_NETWORK_FETCHING)) {
+ PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
+ PKIX_CHECK_NO_GOTO(
+ (*method->externalRevChecker)(cert, issuer, date,
+ method,
+ procParams, methodFlags,
+ &revStatus,
+ (CERTCRLEntryReasonCode *)pReasonCode,
+ &nbioContext, plContext),
+ PKIX_REVCHECKERCHECKFAILED);
+ methodStatus[methodNum] = revStatus;
+ if (revStatus == PKIX_RevStatus_Revoked) {
+ /* if error was generated use it as final error. */
+ overallStatus = PKIX_RevStatus_Revoked;
+ goto cleanup;
+ }
+ if (pkixErrorResult) {
+ /* Disregard errors. Only returned revStatus matters. */
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorResult,
+ plContext);
+ pkixErrorResult = NULL;
+ }
+ } else if (methodFlags &
+ PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
+ /* Info is not in the local cache. Network fetching is not
+ * allowed. If need to fail on missing fresh info for the
+ * the method, then we should fail right here.*/
+ overallStatus = PKIX_RevStatus_Revoked;
+ goto cleanup;
+ }
+ }
+ /* If success and we should not check the next method, then
+ * return a success. */
+ if (methodStatus[methodNum] == PKIX_RevStatus_Success &&
+ !(methodFlags & PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO)) {
+ overallStatus = PKIX_RevStatus_Success;
+ goto cleanup;
+ }
+ } /* inner loop */
+ if (!onlyUseRemoteMethods &&
+ revFlags & PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST &&
+ chainVerificationState) {
+ onlyUseRemoteMethods = PKIX_TRUE;
+ continue;
+ }
+ break;
+ } /* outer loop */
+
+ if (overallStatus == PKIX_RevStatus_NoInfo &&
+ chainVerificationState) {
+ /* The following check makes sence only for chain
+ * validation step, sinse we do not fetch info while
+ * in the process of finding trusted anchor.
+ * For chain building step it is enough to know, that
+ * the cert was not directly revoked by any of the
+ * methods. */
+
+ /* Still have no info. But one of the method could
+ * have returned success status(possible if CONTINUE
+ * TESTING ON FRESH INFO flag was used).
+ * If any of the methods have returned Success status,
+ * the overallStatus should be success. */
+ int methodNum = 0;
+ for (;methodNum < PKIX_RevocationMethod_MAX;methodNum++) {
+ if (methodStatus[methodNum] == PKIX_RevStatus_Success) {
+ overallStatus = PKIX_RevStatus_Success;
+ goto cleanup;
+ }
+ }
+ if (revFlags & PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE) {
+ overallStatus = PKIX_RevStatus_Revoked;
+ }
+ }
+
+cleanup:
+ *pRevStatus = overallStatus;
+ PKIX_DECREF(method);
+
+ PKIX_RETURN(REVOCATIONCHECKER);
+}
+
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.h
new file mode 100644
index 0000000000..20dfe37787
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_revocationchecker.h
@@ -0,0 +1,151 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_revocationchecker.h
+ *
+ * RevocationChecker Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_REVOCATIONCHECKER_H
+#define _PKIX_REVOCATIONCHECKER_H
+
+#include "pkixt.h"
+#include "certt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: nbio logistic removed. Will be replaced later. */
+
+/*
+ * All Flags are prefixed by CERT_REV_M_, where _M_ indicates
+ * this is a method dependent flag.
+ */
+
+/*
+ * Whether or not to use a method for revocation testing.
+ * If set to "do not test", then all other flags are ignored.
+ */
+#define PKIX_REV_M_DO_NOT_TEST_USING_THIS_METHOD 0x00L
+#define PKIX_REV_M_TEST_USING_THIS_METHOD 0x01L
+
+/*
+ * Whether or not NSS is allowed to attempt to fetch fresh information
+ * from the network.
+ * (Although fetching will never happen if fresh information for the
+ * method is already locally available.)
+ */
+#define PKIX_REV_M_ALLOW_NETWORK_FETCHING 0x00L
+#define PKIX_REV_M_FORBID_NETWORK_FETCHING 0x02L
+
+/*
+ * Example for an implicit default source:
+ * The globally configured default OCSP responder.
+ * IGNORE means:
+ * ignore the implicit default source, whether it's configured or not.
+ * ALLOW means:
+ * if an implicit default source is configured,
+ * then it overrides any available or missing source in the cert.
+ * if no implicit default source is configured,
+ * then we continue to use what's available (or not available)
+ * in the certs.
+ */
+#define PKIX_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE 0x00L
+#define PKIX_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE 0x04L /* OCSP only */
+
+/*
+ * Defines the behavior if no fresh information is available,
+ * fetching from the network is allowed, but the source of revocation
+ * information is unknown (even after considering implicit sources,
+ * if allowed by other flags).
+ * SKIPT_TEST means:
+ * We ignore that no fresh information is available and
+ * skip this test.
+ * REQUIRE_INFO means:
+ * We still require that fresh information is available.
+ * Other flags define what happens on missing fresh info.
+ */
+
+#define PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE 0x00L
+#define PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE 0x08L
+
+/*
+ * Defines the behavior if we are unable to obtain fresh information.
+ * INGORE means:
+ * Return "cert status unknown"
+ * FAIL means:
+ * Return "cert revoked".
+ */
+
+#define PKIX_REV_M_IGNORE_MISSING_FRESH_INFO 0x00L
+#define PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO 0x10L
+
+/*
+ * What should happen if we were able to find fresh information using
+ * this method, and the data indicated the cert is good?
+ * STOP_TESTING means:
+ * Our success is sufficient, do not continue testing
+ * other methods.
+ * CONTINUE_TESTING means:
+ * We will continue and test the next allowed
+ * specified method.
+ */
+
+#define PKIX_REV_M_STOP_TESTING_ON_FRESH_INFO 0x00L
+#define PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO 0x20L
+
+/*
+ * All Flags are prefixed by PKIX_REV_MI_, where _MI_ indicates
+ * this is a method independent flag.
+ */
+
+/*
+ * This defines the order to checking.
+ * EACH_METHOD_SEPARATELY means:
+ * Do all tests related to a particular allowed method
+ * (both local information and network fetching) in a single step.
+ * Only after testing for a particular method is done,
+ * then switching to the next method will happen.
+ * ALL_LOCAL_INFORMATION_FIRST means:
+ * Start by testing the information for all allowed methods
+ * which are already locally available. Only after that is done
+ * consider to fetch from the network (as allowed by other flags).
+ */
+#define PKIX_REV_MI_TEST_EACH_METHOD_SEPARATELY 0x00L
+#define PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST 0x01L
+
+/*
+ * Use this flag to specify that it's necessary that fresh information
+ * is available for at least one of the allowed methods, but it's
+ * irrelevant which of the mechanisms succeeded.
+ * NO_OVERALL_INFO_REQUIREMENT means:
+ * We strictly follow the requirements for each individual method.
+ * REQUIRE_SOME_FRESH_INFO_AVAILABLE means:
+ * After the individual tests have been executed, we must have
+ * been able to find fresh information using at least one method.
+ * If we were unable to find fresh info, it's a failure.
+ */
+#define PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT 0x00L
+#define PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE 0x02L
+
+/* Defines check time for the cert, revocation methods lists and
+ * flags for leaf and chain certs revocation tests. */
+struct PKIX_RevocationCheckerStruct {
+ PKIX_List *leafMethodList;
+ PKIX_List *chainMethodList;
+ PKIX_UInt32 leafMethodListFlags;
+ PKIX_UInt32 chainMethodListFlags;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_RevocationChecker_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_REVOCATIONCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.c b/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.c
new file mode 100644
index 0000000000..ee18ddef95
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.c
@@ -0,0 +1,66 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_revocationmethod.c
+ *
+ * RevocationMethod Object Functions
+ *
+ */
+
+#include "pkix_revocationmethod.h"
+#include "pkix_tools.h"
+
+/* Constructor of revocation method object. Does not create an object,
+ * but just initializez PKIX_RevocationMethodStruct fields. Object
+ * suppose to be already created. */
+PKIX_Error *
+pkix_RevocationMethod_Init(
+ pkix_RevocationMethod *method,
+ PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 flags,
+ PKIX_UInt32 priority,
+ pkix_LocalRevocationCheckFn localRevChecker,
+ pkix_ExternalRevocationCheckFn externalRevChecker,
+ void *plContext)
+{
+ PKIX_ENTER(REVOCATIONMETHOD, "PKIX_RevocationMethod_Init");
+
+ method->methodType = methodType;
+ method->flags = flags;
+ method->priority = priority;
+ method->localRevChecker = localRevChecker;
+ method->externalRevChecker = externalRevChecker;
+
+ PKIX_RETURN(REVOCATIONMETHOD);
+}
+
+/* Data duplication data. Not create an object. Only initializes fields
+ * in the new object by data from "object". */
+PKIX_Error *
+pkix_RevocationMethod_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object *newObject,
+ void *plContext)
+{
+ pkix_RevocationMethod *method = NULL;
+
+ PKIX_ENTER(REVOCATIONMETHOD, "pkix_RevocationMethod_Duplicate");
+ PKIX_NULLCHECK_TWO(object, newObject);
+
+ method = (pkix_RevocationMethod *)object;
+
+ PKIX_CHECK(
+ pkix_RevocationMethod_Init((pkix_RevocationMethod*)newObject,
+ method->methodType,
+ method->flags,
+ method->priority,
+ method->localRevChecker,
+ method->externalRevChecker,
+ plContext),
+ PKIX_COULDNOTCREATEREVOCATIONMETHODOBJECT);
+
+cleanup:
+
+ PKIX_RETURN(REVOCATIONMETHOD);
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.h b/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.h
new file mode 100644
index 0000000000..a97c7620ae
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_revocationmethod.h
@@ -0,0 +1,81 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_revocationmethod.h
+ *
+ * RevocationMethod Object
+ *
+ */
+
+#ifndef _PKIX_REVOCATIONMETHOD_H
+#define _PKIX_REVOCATIONMETHOD_H
+
+#include "pkixt.h"
+#include "pkix_revocationchecker.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkix_RevocationMethodStruct pkix_RevocationMethod;
+
+/* Local revocation check function prototype definition.
+ * Revocation methods capable of checking revocation though local
+ * means(cache) should implement this prototype. */
+typedef PKIX_Error *
+pkix_LocalRevocationCheckFn(PKIX_PL_Cert *cert, PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean chainVerificationState,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *reasonCode,
+ void *plContext);
+
+/* External revocation check function prototype definition.
+ * Revocation methods that required external communications(crldp
+ * ocsp) shoult implement this prototype. */
+typedef PKIX_Error *
+pkix_ExternalRevocationCheckFn(PKIX_PL_Cert *cert, PKIX_PL_Cert *issuer,
+ PKIX_PL_Date *date,
+ pkix_RevocationMethod *checkerObject,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 methodFlags,
+ PKIX_RevocationStatus *pRevStatus,
+ CERTCRLEntryReasonCode *reasonCode,
+ void **pNBIOContext, void *plContext);
+
+/* Revocation method structure assosiates revocation types with
+ * a set of flags on the method, a priority of the method (0
+ * corresponds to the highest priority), and method local/external
+ * checker functions. */
+struct pkix_RevocationMethodStruct {
+ PKIX_RevocationMethodType methodType;
+ PKIX_UInt32 flags;
+ PKIX_UInt32 priority;
+ pkix_LocalRevocationCheckFn (*localRevChecker);
+ pkix_ExternalRevocationCheckFn (*externalRevChecker);
+};
+
+PKIX_Error *
+pkix_RevocationMethod_Duplicate(PKIX_PL_Object *object,
+ PKIX_PL_Object *newObject,
+ void *plContext);
+
+PKIX_Error *
+pkix_RevocationMethod_Init(pkix_RevocationMethod *method,
+ PKIX_RevocationMethodType methodType,
+ PKIX_UInt32 flags,
+ PKIX_UInt32 priority,
+ pkix_LocalRevocationCheckFn localRevChecker,
+ pkix_ExternalRevocationCheckFn externalRevChecker,
+ void *plContext);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_REVOCATIONMETHOD_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c
new file mode 100644
index 0000000000..0ed9ffaecc
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.c
@@ -0,0 +1,443 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_signaturechecker.c
+ *
+ * Functions for signature validation
+ *
+ */
+
+#include "pkix_signaturechecker.h"
+
+/*
+ * FUNCTION: pkix_SignatureCheckerstate_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_SignatureCheckerState_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_SignatureCheckerState *state = NULL;
+
+ PKIX_ENTER(SIGNATURECHECKERSTATE,
+ "pkix_SignatureCheckerState_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a signature checker state */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_SIGNATURECHECKERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTSIGNATURECHECKERSTATE);
+
+ state = (pkix_SignatureCheckerState *) object;
+
+ state->prevCertCertSign = PKIX_FALSE;
+
+ PKIX_DECREF(state->prevPublicKey);
+ PKIX_DECREF(state->prevPublicKeyList);
+ PKIX_DECREF(state->keyUsageOID);
+
+cleanup:
+
+ PKIX_RETURN(SIGNATURECHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_SignatureCheckerState_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_SIGNATURECHECKERSTATE_TYPE and its related functions
+ * with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_SignatureCheckerState_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(SIGNATURECHECKERSTATE,
+ "pkix_SignatureCheckerState_RegisterSelf");
+
+ entry.description = "SignatureCheckerState";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(pkix_SignatureCheckerState);
+ entry.destructor = pkix_SignatureCheckerState_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_SIGNATURECHECKERSTATE_TYPE] = entry;
+
+ PKIX_RETURN(SIGNATURECHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_SignatureCheckerState_Create
+ *
+ * DESCRIPTION:
+ * Allocate and initialize SignatureChecker state data.
+ *
+ * PARAMETERS
+ * "trustedPubKey"
+ * Address of trusted Anchor Public Key for verifying first Cert in the
+ * chain. Must be non-NULL.
+ * "certsRemaining"
+ * Number of certificates remaining in the chain.
+ * "pCheckerState"
+ * Address where SignatureCheckerState will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a SignatureCheckerState Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_SignatureCheckerState_Create(
+ PKIX_PL_PublicKey *trustedPubKey,
+ PKIX_UInt32 certsRemaining,
+ pkix_SignatureCheckerState **pCheckerState,
+ void *plContext)
+{
+ pkix_SignatureCheckerState *state = NULL;
+ PKIX_PL_OID *keyUsageOID = NULL;
+
+ PKIX_ENTER(SIGNATURECHECKERSTATE, "pkix_SignatureCheckerState_Create");
+ PKIX_NULLCHECK_TWO(trustedPubKey, pCheckerState);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_SIGNATURECHECKERSTATE_TYPE,
+ sizeof (pkix_SignatureCheckerState),
+ (PKIX_PL_Object **)&state,
+ plContext),
+ PKIX_COULDNOTCREATESIGNATURECHECKERSTATEOBJECT);
+
+ /* Initialize fields */
+
+ state->prevCertCertSign = PKIX_TRUE;
+ state->prevPublicKeyList = NULL;
+ state->certsRemaining = certsRemaining;
+
+ PKIX_INCREF(trustedPubKey);
+ state->prevPublicKey = trustedPubKey;
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_CERTKEYUSAGE_OID,
+ &keyUsageOID,
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ state->keyUsageOID = keyUsageOID;
+ keyUsageOID = NULL;
+
+ *pCheckerState = state;
+ state = NULL;
+
+cleanup:
+
+ PKIX_DECREF(keyUsageOID);
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(SIGNATURECHECKERSTATE);
+}
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_SignatureChecker_Check
+ * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
+ */
+PKIX_Error *
+pkix_SignatureChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ pkix_SignatureCheckerState *state = NULL;
+ PKIX_PL_PublicKey *prevPubKey = NULL;
+ PKIX_PL_PublicKey *currPubKey = NULL;
+ PKIX_PL_PublicKey *newPubKey = NULL;
+ PKIX_PL_PublicKey *pKey = NULL;
+ PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
+ PKIX_Error *checkKeyUsageFail = NULL;
+ PKIX_Error *verifyFail = NULL;
+ PKIX_Boolean certVerified = PKIX_FALSE;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_SignatureChecker_Check");
+ PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
+
+ *pNBIOContext = NULL; /* we never block on pending I/O */
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
+ (checker, (PKIX_PL_Object **)&state, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ (state->certsRemaining)--;
+
+ PKIX_INCREF(state->prevPublicKey);
+ prevPubKey = state->prevPublicKey;
+
+ /*
+ * Previous Cert doesn't have CertSign bit on for signature
+ * verification and it is not a self-issued Cert so there is no
+ * old key saved. This is considered error.
+ */
+ if (state->prevCertCertSign == PKIX_FALSE &&
+ state->prevPublicKeyList == NULL) {
+ PKIX_ERROR(PKIX_KEYUSAGEKEYCERTSIGNBITNOTON);
+ }
+
+ /* Previous Cert is valid for signature verification, try it first */
+ if (state->prevCertCertSign == PKIX_TRUE) {
+ verifyFail = PKIX_PL_Cert_VerifySignature
+ (cert, prevPubKey, plContext);
+ if (verifyFail == NULL) {
+ certVerified = PKIX_TRUE;
+ } else {
+ certVerified = PKIX_FALSE;
+ }
+ }
+
+#ifdef NIST_TEST_4_5_4_AND_4_5_6
+
+ /*
+ * Following codes under this compiler flag is implemented for
+ * special cases of NIST tests 4.5.4 and 4.5.6. We are not sure
+ * we should handle these two tests as what is implemented so the
+ * codes are commented out, and the tests fails (for now).
+ * For Cert chain validation, our assumption is all the Certs on
+ * the chain are using its previous Cert's public key to decode
+ * its current key. But for thses two tests, keys are used not
+ * in this precedent order, we can either
+ * 1) Use what is implemented here: take in what Cert order NIST
+ * specified and for continuous self-issued Certs, stacking up
+ * their keys and tries all of them in FILO order.
+ * But this method breaks the idea of chain key presdency.
+ * 2) Use Build Chain facility: we will specify the valid Certs
+ * order (means key precedency is kept) and count on Build Chain
+ * to get the Certs that can fill for the needed keys. This may have
+ * performance impact.
+ * 3) Fetch Certs from CertStore: we will specifiy the valid Certs
+ * order and use CertSelector on SubjectName to get a list of
+ * candidates Certs to fill in for the needed keys.
+ * Anyhow, the codes are kept around just in case we want to use
+ * solution one...
+ */
+
+ /* If failed and previous key is self-issued, try its old key(s) */
+ if (certVerified == PKIX_FALSE && state->prevPublicKeyList != NULL) {
+
+ /* Verify from keys on the list */
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->prevPublicKeyList, &numKeys, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = numKeys - 1; i >= 0; i--) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->prevPublicKeyList,
+ i,
+ (PKIX_PL_Object **) &pKey,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_DECREF(verifyFail);
+ verifyFail = PKIX_PL_Cert_VerifySignature
+ (cert, pKey, plContext);
+
+ if (verifyFail == NULL) {
+ certVerified = PKIX_TRUE;
+ break;
+ } else {
+ certVerified = PKIX_FALSE;
+ }
+
+ PKIX_DECREF(pKey);
+ }
+ }
+#endif
+
+ if (certVerified == PKIX_FALSE) {
+ pkixErrorResult = verifyFail;
+ verifyFail = NULL;
+ PKIX_ERROR(PKIX_VALIDATIONFAILEDCERTSIGNATURECHECKING);
+ }
+
+#ifdef NIST_TEST_4_5_4_AND_4_5_6
+ /*
+ * Check if Cert is self-issued. If so, the old key(s) is saved, in
+ * conjunction to the new key, for verifying CERT validity later.
+ */
+ PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext),
+ PKIX_ISCERTSELFISSUEFAILED);
+
+ /*
+ * Check if Cert is self-issued. If so, the public key of the Cert
+ * that issues this Cert (old key) can be used together with this
+ * current key (new key) for key verification. If there are multiple
+ * self-issued certs, keys of those Certs (old keys) can also be used
+ * for key verification. Old key(s) is saved in a list (PrevPublickKey-
+ * List) and cleared when a Cert is no longer self-issued. PrevPublic-
+ * Key keep key of the previous Cert.
+ */
+ if (selfIssued == PKIX_TRUE) {
+
+ /* Make sure previous Cert is valid for signature verification */
+ if (state->prevCertCertSign == PKIX_TRUE) {
+
+ if (state->prevPublicKeyList == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&state->prevPublicKeyList, plContext),
+ PKIX_LISTCREATEFALIED);
+
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (state->prevPublicKeyList,
+ (PKIX_PL_Object *) state->prevPublicKey,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ } else {
+ /* Not self-issued Cert any more, clear old key(s) saved */
+ PKIX_DECREF(state->prevPublicKeyList);
+ }
+#endif
+
+ /* Save current key as prevPublicKey */
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (cert, &currPubKey, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+
+ PKIX_CHECK(PKIX_PL_PublicKey_MakeInheritedDSAPublicKey
+ (currPubKey, prevPubKey, &newPubKey, plContext),
+ PKIX_PUBLICKEYMAKEINHERITEDDSAPUBLICKEYFAILED);
+
+ if (newPubKey == NULL){
+ PKIX_INCREF(currPubKey);
+ newPubKey = currPubKey;
+ }
+
+ PKIX_INCREF(newPubKey);
+ PKIX_DECREF(state->prevPublicKey);
+
+ state->prevPublicKey = newPubKey;
+
+ /* Save this Cert key usage CertSign bit */
+ if (state->certsRemaining != 0) {
+ checkKeyUsageFail = PKIX_PL_Cert_VerifyKeyUsage
+ (cert, PKIX_KEY_CERT_SIGN, plContext);
+
+ state->prevCertCertSign = (checkKeyUsageFail == NULL)?
+ PKIX_TRUE:PKIX_FALSE;
+
+ PKIX_DECREF(checkKeyUsageFail);
+ }
+
+ /* Remove Key Usage Extension OID from list */
+ if (unresolvedCriticalExtensions != NULL) {
+
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticalExtensions,
+ (PKIX_PL_Object *) state->keyUsageOID,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
+ (checker, (PKIX_PL_Object *)state, plContext),
+ PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(state);
+ PKIX_DECREF(pKey);
+ PKIX_DECREF(prevPubKey);
+ PKIX_DECREF(currPubKey);
+ PKIX_DECREF(newPubKey);
+ PKIX_DECREF(basicConstraints);
+ PKIX_DECREF(verifyFail);
+ PKIX_DECREF(checkKeyUsageFail);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_SignatureChecker_Initialize
+ * DESCRIPTION:
+ *
+ * Creates a new CertChainChecker and stores it at "pChecker", where it will
+ * be used by pkix_SignatureChecker_Check to check that the public key in
+ * the checker's state is able to successfully validate the certificate's
+ * signature. The PublicKey pointed to by "trustedPubKey" is used to
+ * initialize the checker's state.
+ *
+ * PARAMETERS:
+ * "trustedPubKey"
+ * Address of PublicKey representing the trusted public key used to
+ * initialize the state of this checker. Must be non-NULL.
+ * "certsRemaining"
+ * Number of certificates remaining in the chain.
+ * "pChecker"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_SignatureChecker_Initialize(
+ PKIX_PL_PublicKey *trustedPubKey,
+ PKIX_UInt32 certsRemaining,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ pkix_SignatureCheckerState* state = NULL;
+ PKIX_ENTER(CERTCHAINCHECKER, "PKIX_SignatureChecker_Initialize");
+ PKIX_NULLCHECK_TWO(pChecker, trustedPubKey);
+
+ PKIX_CHECK(pkix_SignatureCheckerState_Create
+ (trustedPubKey, certsRemaining, &state, plContext),
+ PKIX_SIGNATURECHECKERSTATECREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_SignatureChecker_Check,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *) state,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.h
new file mode 100644
index 0000000000..ccfb578579
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_signaturechecker.h
@@ -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/. */
+/*
+ * pkix_signaturechecker.h
+ *
+ * Header file for validate signature function
+ *
+ */
+
+#ifndef _PKIX_SIGNATURECHECKER_H
+#define _PKIX_SIGNATURECHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkix_SignatureCheckerState pkix_SignatureCheckerState;
+
+struct pkix_SignatureCheckerState {
+ PKIX_Boolean prevCertCertSign;
+ PKIX_UInt32 certsRemaining;
+ PKIX_PL_PublicKey *prevPublicKey; /* Subject PubKey of last cert */
+ PKIX_List *prevPublicKeyList; /* of PKIX_PL_PublicKey */
+ PKIX_PL_OID *keyUsageOID;
+};
+
+PKIX_Error *
+pkix_SignatureChecker_Initialize(
+ PKIX_PL_PublicKey *trustedPubKey,
+ PKIX_UInt32 certsRemaining,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+PKIX_Error *
+pkix_SignatureCheckerState_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_SIGNATURECHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c
new file mode 100644
index 0000000000..46fe07112b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.c
@@ -0,0 +1,516 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_targetcertchecker.c
+ *
+ * Functions for target cert validation
+ *
+ */
+
+
+#include "pkix_targetcertchecker.h"
+
+/* --Private-TargetCertCheckerState-Functions------------------------------- */
+
+/*
+ * FUNCTION: pkix_TargetCertCheckerState_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_TargetCertCheckerState_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_TargetCertCheckerState *state = NULL;
+
+ PKIX_ENTER(TARGETCERTCHECKERSTATE,
+ "pkix_TargetCertCheckerState_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a target cert checker state */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_TARGETCERTCHECKERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTTARGETCERTCHECKERSTATE);
+
+ state = (pkix_TargetCertCheckerState *)object;
+
+ PKIX_DECREF(state->certSelector);
+ PKIX_DECREF(state->extKeyUsageOID);
+ PKIX_DECREF(state->subjAltNameOID);
+ PKIX_DECREF(state->pathToNameList);
+ PKIX_DECREF(state->extKeyUsageList);
+ PKIX_DECREF(state->subjAltNameList);
+
+cleanup:
+
+ PKIX_RETURN(TARGETCERTCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_TargetCertCheckerState_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_TARGETCERTCHECKERSTATE_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_TargetCertCheckerState_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(TARGETCERTCHECKERSTATE,
+ "pkix_TargetCertCheckerState_RegisterSelf");
+
+ entry.description = "TargetCertCheckerState";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(pkix_TargetCertCheckerState);
+ entry.destructor = pkix_TargetCertCheckerState_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_TARGETCERTCHECKERSTATE_TYPE] = entry;
+
+ PKIX_RETURN(TARGETCERTCHECKERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_TargetCertCheckerState_Create
+ * DESCRIPTION:
+ *
+ * Creates a new TargetCertCheckerState using the CertSelector pointed to
+ * by "certSelector" and the number of certs represented by "certsRemaining"
+ * and stores it at "pState".
+ *
+ * PARAMETERS:
+ * "certSelector"
+ * Address of CertSelector representing the criteria against which the
+ * final certificate in a chain is to be matched. Must be non-NULL.
+ * "certsRemaining"
+ * Number of certificates remaining in the chain.
+ * "pState"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a TargetCertCheckerState Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_TargetCertCheckerState_Create(
+ PKIX_CertSelector *certSelector,
+ PKIX_UInt32 certsRemaining,
+ pkix_TargetCertCheckerState **pState,
+ void *plContext)
+{
+ pkix_TargetCertCheckerState *state = NULL;
+ PKIX_ComCertSelParams *certSelectorParams = NULL;
+ PKIX_List *pathToNameList = NULL;
+ PKIX_List *extKeyUsageList = NULL;
+ PKIX_List *subjAltNameList = NULL;
+ PKIX_PL_OID *extKeyUsageOID = NULL;
+ PKIX_PL_OID *subjAltNameOID = NULL;
+ PKIX_Boolean subjAltNameMatchAll = PKIX_TRUE;
+
+ PKIX_ENTER(TARGETCERTCHECKERSTATE,
+ "pkix_TargetCertCheckerState_Create");
+ PKIX_NULLCHECK_ONE(pState);
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_EXTENDEDKEYUSAGE_OID,
+ &extKeyUsageOID,
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (PKIX_CERTSUBJALTNAME_OID,
+ &subjAltNameOID,
+ plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_TARGETCERTCHECKERSTATE_TYPE,
+ sizeof (pkix_TargetCertCheckerState),
+ (PKIX_PL_Object **)&state,
+ plContext),
+ PKIX_COULDNOTCREATETARGETCERTCHECKERSTATEOBJECT);
+
+ /* initialize fields */
+
+ if (certSelector != NULL) {
+
+ PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
+ (certSelector, &certSelectorParams, plContext),
+ PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMFAILED);
+
+ if (certSelectorParams != NULL) {
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetPathToNames
+ (certSelectorParams,
+ &pathToNameList,
+ plContext),
+ PKIX_COMCERTSELPARAMSGETPATHTONAMESFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
+ (certSelectorParams,
+ &extKeyUsageList,
+ plContext),
+ PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubjAltNames
+ (certSelectorParams,
+ &subjAltNameList,
+ plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetMatchAllSubjAltNames
+ (certSelectorParams,
+ &subjAltNameMatchAll,
+ plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED);
+ }
+ }
+
+ state->certsRemaining = certsRemaining;
+ state->subjAltNameMatchAll = subjAltNameMatchAll;
+
+ PKIX_INCREF(certSelector);
+ state->certSelector = certSelector;
+
+ state->pathToNameList = pathToNameList;
+ pathToNameList = NULL;
+
+ state->extKeyUsageList = extKeyUsageList;
+ extKeyUsageList = NULL;
+
+ state->subjAltNameList = subjAltNameList;
+ subjAltNameList = NULL;
+
+ state->extKeyUsageOID = extKeyUsageOID;
+ extKeyUsageOID = NULL;
+
+ state->subjAltNameOID = subjAltNameOID;
+ subjAltNameOID = NULL;
+
+ *pState = state;
+ state = NULL;
+
+cleanup:
+
+ PKIX_DECREF(extKeyUsageOID);
+ PKIX_DECREF(subjAltNameOID);
+ PKIX_DECREF(pathToNameList);
+ PKIX_DECREF(extKeyUsageList);
+ PKIX_DECREF(subjAltNameList);
+ PKIX_DECREF(state);
+
+ PKIX_DECREF(certSelectorParams);
+
+ PKIX_RETURN(TARGETCERTCHECKERSTATE);
+
+}
+
+/* --Private-TargetCertChecker-Functions------------------------------- */
+
+/*
+ * FUNCTION: pkix_TargetCertChecker_Check
+ * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h)
+ */
+PKIX_Error *
+pkix_TargetCertChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ pkix_TargetCertCheckerState *state = NULL;
+ PKIX_CertSelector_MatchCallback certSelectorMatch = NULL;
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ PKIX_List *certSubjAltNames = NULL;
+ PKIX_List *certExtKeyUsageList = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+ PKIX_PL_X500Name *certSubjectName = NULL;
+ PKIX_Boolean checkPassed = PKIX_FALSE;
+ PKIX_UInt32 numItems, i;
+ PKIX_UInt32 matchCount = 0;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Check");
+ PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);
+
+ *pNBIOContext = NULL; /* we never block on pending I/O */
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
+ (checker, (PKIX_PL_Object **)&state, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ (state->certsRemaining)--;
+
+ if (state->pathToNameList != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
+ (cert, &nameConstraints, plContext),
+ PKIX_CERTGETNAMECONSTRAINTSFAILED);
+
+ /*
+ * XXX We should either make the following call a public one
+ * so it is legal to call from the portability layer or we
+ * should try to create pathToNameList as CertNameConstraints
+ * then call the existing check function.
+ */
+ PKIX_CHECK(PKIX_PL_CertNameConstraints_CheckNamesInNameSpace
+ (state->pathToNameList,
+ nameConstraints,
+ &checkPassed,
+ plContext),
+ PKIX_CERTNAMECONSTRAINTSCHECKNAMEINNAMESPACEFAILED);
+
+ if (checkPassed != PKIX_TRUE) {
+ PKIX_ERROR(PKIX_VALIDATIONFAILEDPATHTONAMECHECKFAILED);
+ }
+
+ }
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
+ (cert, &certSubjAltNames, plContext),
+ PKIX_CERTGETSUBJALTNAMESFAILED);
+
+ if (state->subjAltNameList != NULL && certSubjAltNames != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->subjAltNameList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->subjAltNameList,
+ i,
+ (PKIX_PL_Object **) &name,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_List_Contains
+ (certSubjAltNames,
+ (PKIX_PL_Object *) name,
+ &checkPassed,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ PKIX_DECREF(name);
+
+ if (checkPassed == PKIX_TRUE) {
+
+ if (state->subjAltNameMatchAll == PKIX_FALSE) {
+ matchCount = numItems;
+ break;
+ } else {
+ /* else continue checking next */
+ matchCount++;
+ }
+
+ }
+ }
+
+ if (matchCount != numItems) {
+ PKIX_ERROR(PKIX_SUBJALTNAMECHECKFAILED);
+
+ }
+ }
+
+ if (state->certsRemaining == 0) {
+
+ if (state->certSelector != NULL) {
+ PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
+ (state->certSelector,
+ &certSelectorMatch,
+ plContext),
+ PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
+
+ PKIX_CHECK(certSelectorMatch
+ (state->certSelector,
+ cert,
+ plContext),
+ PKIX_CERTSELECTORMATCHFAILED);
+ } else {
+ /* Check at least cert/key usages if target cert selector
+ * is not set. */
+ PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert,
+ PKIX_FALSE /* is chain cert*/,
+ plContext),
+ PKIX_CERTVERIFYCERTTYPEFAILED);
+ }
+ /*
+ * There are two Extended Key Usage Checkings
+ * available :
+ * 1) here at the targetcertchecker where we
+ * verify the Extended Key Usage OIDs application
+ * specifies via ComCertSelParams are included
+ * in Cert's Extended Key Usage OID's. Note,
+ * this is an OID to OID comparison and only last
+ * Cert is checked.
+ * 2) at user defined ekuchecker where checking
+ * is applied to all Certs on the chain and
+ * the NSS Extended Key Usage algorithm is
+ * used. In order to invoke this checking, not
+ * only does the ComCertSelparams needs to be
+ * set, the EKU initialize call is required to
+ * activate the checking.
+ *
+ * XXX We use the same ComCertSelParams Set/Get
+ * functions to set the parameters for both cases.
+ * We may want to separate them in the future.
+ */
+
+ PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
+ (cert, &certExtKeyUsageList, plContext),
+ PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
+
+
+ if (state->extKeyUsageList != NULL &&
+ certExtKeyUsageList != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->extKeyUsageList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->extKeyUsageList,
+ i,
+ (PKIX_PL_Object **) &name,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_List_Contains
+ (certExtKeyUsageList,
+ (PKIX_PL_Object *) name,
+ &checkPassed,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ PKIX_DECREF(name);
+
+ if (checkPassed != PKIX_TRUE) {
+ PKIX_ERROR
+ (PKIX_EXTENDEDKEYUSAGECHECKINGFAILED);
+
+ }
+ }
+ }
+ } else {
+ /* Check key usage and cert type based on certificate usage. */
+ PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert, PKIX_TRUE,
+ plContext),
+ PKIX_CERTVERIFYCERTTYPEFAILED);
+ }
+
+ /* Remove Critical Extension OID from list */
+ if (unresolvedCriticalExtensions != NULL) {
+
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticalExtensions,
+ (PKIX_PL_Object *) state->extKeyUsageOID,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject
+ (cert, &certSubjectName, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+
+ if (certSubjAltNames != NULL) {
+ PKIX_CHECK(pkix_List_Remove
+ (unresolvedCriticalExtensions,
+ (PKIX_PL_Object *) state->subjAltNameOID,
+ plContext),
+ PKIX_LISTREMOVEFAILED);
+ }
+
+ }
+
+cleanup:
+
+ PKIX_DECREF(name);
+ PKIX_DECREF(nameConstraints);
+ PKIX_DECREF(certSubjAltNames);
+ PKIX_DECREF(certExtKeyUsageList);
+ PKIX_DECREF(certSubjectName);
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+
+}
+
+/*
+ * FUNCTION: pkix_TargetCertChecker_Initialize
+ * DESCRIPTION:
+ *
+ * Creates a new CertChainChecker and stores it at "pChecker", where it will
+ * used by pkix_TargetCertChecker_Check to check that the final certificate
+ * of a chain meets the criteria of the CertSelector pointed to by
+ * "certSelector". The number of certs remaining in the chain, represented by
+ * "certsRemaining" is used to initialize the checker's state.
+ *
+ * PARAMETERS:
+ * "certSelector"
+ * Address of CertSelector representing the criteria against which the
+ * final certificate in a chain is to be matched. May be NULL.
+ * "certsRemaining"
+ * Number of certificates remaining in the chain.
+ * "pChecker"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertChainChecker Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_TargetCertChecker_Initialize(
+ PKIX_CertSelector *certSelector,
+ PKIX_UInt32 certsRemaining,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext)
+{
+ pkix_TargetCertCheckerState *state = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Initialize");
+ PKIX_NULLCHECK_ONE(pChecker);
+
+ PKIX_CHECK(pkix_TargetCertCheckerState_Create
+ (certSelector, certsRemaining, &state, plContext),
+ PKIX_TARGETCERTCHECKERSTATECREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_Create
+ (pkix_TargetCertChecker_Check,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *)state,
+ pChecker,
+ plContext),
+ PKIX_CERTCHAINCHECKERCREATEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.h b/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.h
new file mode 100644
index 0000000000..4592d10a94
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/checker/pkix_targetcertchecker.h
@@ -0,0 +1,47 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_targetcertchecker.h
+ *
+ * Header file for validate target cert function
+ *
+ */
+
+#ifndef _PKIX_TARGETCERTCHECKER_H
+#define _PKIX_TARGETCERTCHECKER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkix_TargetCertCheckerState pkix_TargetCertCheckerState;
+
+struct pkix_TargetCertCheckerState {
+ PKIX_CertSelector *certSelector;
+ PKIX_List *pathToNameList;
+ PKIX_List *extKeyUsageList; /* List of PKIX_PL_OID */
+ PKIX_List *subjAltNameList;
+ PKIX_Boolean subjAltNameMatchAll;
+ PKIX_UInt32 certsRemaining;
+ PKIX_PL_OID *extKeyUsageOID;
+ PKIX_PL_OID *subjAltNameOID;
+};
+
+PKIX_Error *
+pkix_TargetCertChecker_Initialize(
+ PKIX_CertSelector *certSelector,
+ PKIX_UInt32 certsRemaining,
+ PKIX_CertChainChecker **pChecker,
+ void *plContext);
+
+PKIX_Error *
+pkix_TargetCertCheckerState_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_TARGETCERTCHECKER_H */
diff --git a/security/nss/lib/libpkix/pkix/crlsel/Makefile b/security/nss/lib/libpkix/pkix/crlsel/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/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). #
+#######################################################################
+
+
+#######################################################################
+# (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/lib/libpkix/pkix/crlsel/crlsel.gyp b/security/nss/lib/libpkix/pkix/crlsel/crlsel.gyp
new file mode 100644
index 0000000000..894569ef6c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/crlsel.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'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixcrlsel',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_comcrlselparams.c',
+ 'pkix_crlselector.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/crlsel/exports.gyp b/security/nss/lib/libpkix/pkix/crlsel/exports.gyp
new file mode 100644
index 0000000000..a7001ffed7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/exports.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'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_libpkix_pkix_crlsel_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_comcrlselparams.h',
+ 'pkix_crlselector.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/crlsel/manifest.mn b/security/nss/lib/libpkix/pkix/crlsel/manifest.mn
new file mode 100644
index 0000000000..fe84a2d62f
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/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 = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_comcrlselparams.h \
+ pkix_crlselector.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_crlselector.c \
+ pkix_comcrlselparams.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixcrlsel
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.c b/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.c
new file mode 100644
index 0000000000..90380c5b2b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.c
@@ -0,0 +1,826 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_comcrlselparams.c
+ *
+ * ComCRLSelParams Function Definitions
+ *
+ */
+
+#include "pkix_comcrlselparams.h"
+
+/* --ComCRLSelParams-Private-Functions------------------------------------ */
+
+/*
+ * FUNCTION: pkix_ComCrlSelParams_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCRLSelParams_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *params = NULL;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_COMCRLSELPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTCOMCRLSELPARAMS);
+
+ params = (PKIX_ComCRLSelParams *)object;
+
+ PKIX_DECREF(params->issuerNames);
+ PKIX_DECREF(params->cert);
+ PKIX_DECREF(params->date);
+ PKIX_DECREF(params->maxCRLNumber);
+ PKIX_DECREF(params->minCRLNumber);
+ PKIX_DECREF(params->crldpList);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCRLSelParams_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of ComCRLSelParams
+ * pointed to by "crlParams" and stores the result at "pString".
+ *
+ * PARAMETERS
+ * "crlParams"
+ * Address of ComCRLSelParams whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address of object pointer's destination. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLEntry Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_ComCRLSelParams_ToString_Helper(
+ PKIX_ComCRLSelParams *crlParams,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *crlIssuerNamesString = NULL;
+ PKIX_PL_String *crlDateString = NULL;
+ PKIX_PL_String *crlMaxCRLNumberString = NULL;
+ PKIX_PL_String *crlMinCRLNumberString = NULL;
+ PKIX_PL_String *crlCertString = NULL;
+ PKIX_PL_String *crlParamsString = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_ToString_Helper");
+ PKIX_NULLCHECK_TWO(crlParams, pString);
+
+ asciiFormat =
+ "\n\t[\n"
+ "\tIssuerNames: %s\n"
+ "\tDate: %s\n"
+ "\tmaxCRLNumber: %s\n"
+ "\tminCRLNumber: %s\n"
+ "\tCertificate: %s\n"
+ "\t]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_TOSTRING
+ (crlParams->issuerNames, &crlIssuerNamesString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(crlParams->date, &crlDateString, plContext,
+ PKIX_DATETOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (crlParams->maxCRLNumber, &crlMaxCRLNumberString, plContext,
+ PKIX_BIGINTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (crlParams->minCRLNumber, &crlMinCRLNumberString, plContext,
+ PKIX_BIGINTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(crlParams->cert, &crlCertString, plContext,
+ PKIX_CERTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&crlParamsString,
+ plContext,
+ formatString,
+ crlIssuerNamesString,
+ crlDateString,
+ crlMaxCRLNumberString,
+ crlMinCRLNumberString,
+ crlCertString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = crlParamsString;
+
+cleanup:
+
+ PKIX_DECREF(crlIssuerNamesString);
+ PKIX_DECREF(crlDateString);
+ PKIX_DECREF(crlMaxCRLNumberString);
+ PKIX_DECREF(crlMinCRLNumberString);
+ PKIX_DECREF(crlCertString);
+ PKIX_DECREF(formatString);
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCRLSelParams_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCRLSelParams_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *crlParamsString = NULL;
+ PKIX_ComCRLSelParams *crlParams = NULL;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_COMCRLSELPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTCOMCRLSELPARAMS);
+
+ crlParams = (PKIX_ComCRLSelParams *) object;
+
+ PKIX_CHECK(pkix_ComCRLSelParams_ToString_Helper
+ (crlParams, &crlParamsString, plContext),
+ PKIX_COMCRLSELPARAMSTOSTRINGHELPERFAILED);
+
+ *pString = crlParamsString;
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCRLSelParams_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCRLSelParams_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *crlParams = NULL;
+ PKIX_UInt32 namesHash = 0;
+ PKIX_UInt32 certHash = 0;
+ PKIX_UInt32 dateHash = 0;
+ PKIX_UInt32 maxCRLNumberHash = 0;
+ PKIX_UInt32 minCRLNumberHash = 0;
+ PKIX_UInt32 hash = 0;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_COMCRLSELPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTCOMCRLSELPARAMS);
+
+ crlParams = (PKIX_ComCRLSelParams *)object;
+
+ PKIX_HASHCODE(crlParams->issuerNames, &namesHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(crlParams->cert, &certHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(crlParams->date, &dateHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(crlParams->maxCRLNumber, &maxCRLNumberHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(crlParams->minCRLNumber, &minCRLNumberHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+
+ hash = (((namesHash << 3) + certHash) << 3) + dateHash;
+ hash = (hash << 3) + maxCRLNumberHash + minCRLNumberHash;
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCRLSelParams_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCRLSelParams_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *firstCrlParams = NULL;
+ PKIX_ComCRLSelParams *secondCrlParams = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a ComCRLSelParams */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_COMCRLSELPARAMS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCOMCRLSELPARAMS);
+
+ firstCrlParams = (PKIX_ComCRLSelParams *)firstObject;
+ secondCrlParams = (PKIX_ComCRLSelParams *)secondObject;
+
+ /*
+ * Since we know firstObject is a ComCRLSelParams, if both references
+ * are identical, they must be equal
+ */
+ if (firstCrlParams == secondCrlParams){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondComCRLSelParams isn't a ComCRLSelParams, we don't
+ * throw an error. We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ ((PKIX_PL_Object *)secondCrlParams, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ if (secondType != PKIX_COMCRLSELPARAMS_TYPE) {
+ goto cleanup;
+ }
+
+ /* Compare Issuer Names */
+ PKIX_EQUALS
+ (firstCrlParams->issuerNames,
+ secondCrlParams->issuerNames,
+ &cmpResult,
+ plContext,
+ PKIX_LISTEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE) {
+ goto cleanup;
+ }
+
+ /* Compare Date */
+ PKIX_EQUALS
+ (firstCrlParams->date,
+ secondCrlParams->date,
+ &cmpResult,
+ plContext,
+ PKIX_DATEEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE) {
+ goto cleanup;
+ }
+
+ /* Compare Max CRL Number */
+ PKIX_EQUALS
+ (firstCrlParams->maxCRLNumber,
+ secondCrlParams->maxCRLNumber,
+ &cmpResult,
+ plContext,
+ PKIX_BIGINTEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE) {
+ goto cleanup;
+ }
+
+ /* Compare Min CRL Number */
+ PKIX_EQUALS
+ (firstCrlParams->minCRLNumber,
+ secondCrlParams->minCRLNumber,
+ &cmpResult,
+ plContext,
+ PKIX_BIGINTEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE) {
+ goto cleanup;
+ }
+
+ /* Compare Cert */
+ PKIX_EQUALS
+ (firstCrlParams->cert,
+ secondCrlParams->cert,
+ &cmpResult,
+ plContext,
+ PKIX_CERTEQUALSFAILED);
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCRLSelParams_Duplicate
+ * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ComCRLSelParams_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *old;
+ PKIX_ComCRLSelParams *new = NULL;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_COMCRLSELPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTCOMCRLSELPARAMS);
+
+ old = (PKIX_ComCRLSelParams *)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_COMCRLSELPARAMS_TYPE,
+ (PKIX_UInt32)(sizeof (PKIX_ComCRLSelParams)),
+ (PKIX_PL_Object **)&new,
+ plContext),
+ PKIX_OBJECTALLOCFAILED);
+
+ PKIX_DUPLICATE(old->cert, &new->cert, plContext,
+ PKIX_OBJECTDUPLICATECERTFAILED);
+
+ PKIX_DUPLICATE(old->crldpList, &new->crldpList, plContext,
+ PKIX_OBJECTDUPLICATECERTFAILED);
+
+ PKIX_DUPLICATE(old->issuerNames, &new->issuerNames, plContext,
+ PKIX_OBJECTDUPLICATEISSUERNAMESFAILED);
+
+ PKIX_DUPLICATE(old->date, &new->date, plContext,
+ PKIX_OBJECTDUPLICATEDATEFAILED);
+
+ PKIX_DUPLICATE(old->maxCRLNumber, &new->maxCRLNumber, plContext,
+ PKIX_OBJECTDUPLICATEMAXCRLNUMBERFAILED);
+
+ PKIX_DUPLICATE(old->minCRLNumber, &new->minCRLNumber, plContext,
+ PKIX_OBJECTDUPLICATEMINCRLNUMBERFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)new;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(new);
+ }
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ComCrlSelParams_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_COMCRLSELPARAMS_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_ComCRLSelParams_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "pkix_ComCRLSelParams_RegisterSelf");
+
+ entry.description = "ComCRLSelParams";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_ComCRLSelParams);
+ entry.destructor = pkix_ComCRLSelParams_Destroy;
+ entry.equalsFunction = pkix_ComCRLSelParams_Equals;
+ entry.hashcodeFunction = pkix_ComCRLSelParams_Hashcode;
+ entry.toStringFunction = pkix_ComCRLSelParams_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_ComCRLSelParams_Duplicate;
+
+ systemClasses[PKIX_COMCRLSELPARAMS_TYPE] = entry;
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/* --ComCRLSelParams-Public-Functions------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_Create (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_Create(
+ PKIX_ComCRLSelParams **pParams,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *params = NULL;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_Create");
+ PKIX_NULLCHECK_ONE(pParams);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_COMCRLSELPARAMS_TYPE,
+ sizeof (PKIX_ComCRLSelParams),
+ (PKIX_PL_Object **)&params,
+ plContext),
+ PKIX_COULDNOTCREATECOMMONCRLSELECTORPARAMSOBJECT);
+
+ /* initialize fields */
+ params->issuerNames = NULL;
+ params->cert = NULL;
+ params->crldpList = NULL;
+ params->date = NULL;
+ params->nistPolicyEnabled = PKIX_TRUE;
+ params->maxCRLNumber = NULL;
+ params->minCRLNumber = NULL;
+
+ *pParams = params;
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetIssuerNames (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetIssuerNames(
+ PKIX_ComCRLSelParams *params,
+ PKIX_List **pIssuerNames,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_GetIssuerNames");
+ PKIX_NULLCHECK_TWO(params, pIssuerNames);
+
+ PKIX_INCREF(params->issuerNames);
+
+ *pIssuerNames = params->issuerNames;
+
+cleanup:
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetIssuerNames (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetIssuerNames(
+ PKIX_ComCRLSelParams *params,
+ PKIX_List *names,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_SetIssuerNames");
+ PKIX_NULLCHECK_ONE(params); /* allows null for names from spec */
+
+ PKIX_DECREF(params->issuerNames);
+
+ PKIX_INCREF(names); /* if NULL, allows to reset for no action */
+
+ params->issuerNames = names;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_AddIssuerName (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_AddIssuerName(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_X500Name *name,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+
+ PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_AddIssuerName");
+ PKIX_NULLCHECK_ONE(params);
+
+ if (name != NULL) {
+
+ if (params->issuerNames == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+ params->issuerNames = list;
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (params->issuerNames, (PKIX_PL_Object *)name, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ }
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetCertificateChecking
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetCertificateChecking(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_Cert **pCert,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_GetCertificateChecking");
+ PKIX_NULLCHECK_TWO(params, pCert);
+
+ PKIX_INCREF(params->cert);
+
+ *pCert = params->cert;
+
+cleanup:
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetCertificateChecking
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetCertificateChecking(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_Cert *cert,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_SetCertificateChecking");
+ PKIX_NULLCHECK_ONE(params); /* allows cert to be NULL from spec */
+
+ PKIX_DECREF(params->cert);
+
+ PKIX_INCREF(cert);
+
+ params->cert = cert;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetDateAndTime (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetDateAndTime(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_GetDateAndTime");
+ PKIX_NULLCHECK_TWO(params, pDate);
+
+ PKIX_INCREF(params->date);
+
+ *pDate = params->date;
+
+cleanup:
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetDateAndTime (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetDateAndTime(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_Date *date,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_SetDateAndTime");
+ PKIX_NULLCHECK_ONE(params); /* allows date to be NULL from spec */
+
+ PKIX_DECREF (params->date);
+
+ PKIX_INCREF(date);
+
+ params->date = date;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetDateAndTime (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetNISTPolicyEnabled(
+ PKIX_ComCRLSelParams *params,
+ PKIX_Boolean *pEnabled,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_GetNISTPolicyEnabled");
+ PKIX_NULLCHECK_TWO(params, pEnabled);
+
+ *pEnabled = params->nistPolicyEnabled;
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetDateAndTime (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetNISTPolicyEnabled(
+ PKIX_ComCRLSelParams *params,
+ PKIX_Boolean enabled,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_SetNISTPolicyEnabled");
+ PKIX_NULLCHECK_ONE(params); /* allows date to be NULL from spec */
+
+ params->nistPolicyEnabled = enabled;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetMaxCRLNumber
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetMaxCRLNumber(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_BigInt **pMaxCRLNumber,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_GetMaxCRLNumber");
+ PKIX_NULLCHECK_TWO(params, pMaxCRLNumber);
+
+ PKIX_INCREF(params->maxCRLNumber);
+
+ *pMaxCRLNumber = params->maxCRLNumber;
+
+cleanup:
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetMaxCRLNumber
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetMaxCRLNumber(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_BigInt *maxCRLNumber,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_SetMaxCRLNumber");
+ PKIX_NULLCHECK_ONE(params); /* maxCRLNumber can be NULL - from spec */
+
+ PKIX_DECREF(params->maxCRLNumber);
+
+ PKIX_INCREF(maxCRLNumber);
+
+ params->maxCRLNumber = maxCRLNumber;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_GetMinCRLNumber
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_GetMinCRLNumber(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_BigInt **pMinCRLNumber,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_GetMinCRLNumber");
+ PKIX_NULLCHECK_TWO(params, pMinCRLNumber);
+
+ PKIX_INCREF(params->minCRLNumber);
+
+ *pMinCRLNumber = params->minCRLNumber;
+
+cleanup:
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ComCRLSelParams_SetMinCRLNumber
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_ComCRLSelParams_SetMinCRLNumber(
+ PKIX_ComCRLSelParams *params,
+ PKIX_PL_BigInt *minCRLNumber,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS,
+ "PKIX_ComCRLSelParams_SetMinCRLNumber");
+ PKIX_NULLCHECK_ONE(params); /* minCRLNumber can be NULL - from spec */
+
+ PKIX_DECREF(params->minCRLNumber);
+
+ PKIX_INCREF(minCRLNumber);
+
+ params->minCRLNumber = minCRLNumber;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
+
+
+PKIX_Error*
+PKIX_ComCRLSelParams_SetCrlDp(
+ PKIX_ComCRLSelParams *params,
+ PKIX_List *crldpList,
+ void *plContext)
+{
+ PKIX_ENTER(COMCRLSELPARAMS, "PKIX_ComCRLSelParams_SetCrlDp");
+ PKIX_NULLCHECK_ONE(params); /* minCRLNumber can be NULL - from spec */
+
+ PKIX_INCREF(crldpList);
+ params->crldpList = crldpList;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+cleanup:
+
+ PKIX_RETURN(COMCRLSELPARAMS);
+}
diff --git a/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.h b/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.h
new file mode 100644
index 0000000000..08351375d9
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/pkix_comcrlselparams.h
@@ -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_comcrlselparams.h
+ *
+ * ComCrlSelParams Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_COMCRLSELPARAMS_H
+#define _PKIX_COMCRLSELPARAMS_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_ComCRLSelParamsStruct {
+ PKIX_List *issuerNames; /* list of PKIX_PL_X500Name */
+ PKIX_PL_Cert *cert; /* certificate being checked */
+ PKIX_List *crldpList;
+ PKIX_PL_Date *date;
+ PKIX_Boolean nistPolicyEnabled;
+ PKIX_PL_BigInt *maxCRLNumber;
+ PKIX_PL_BigInt *minCRLNumber;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_ComCRLSelParams_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_COMCRLSELPARAMS_H */
diff --git a/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.c b/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.c
new file mode 100644
index 0000000000..e9a9c03dfd
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.c
@@ -0,0 +1,870 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_crlselector.c
+ *
+ * CRLSelector Function Definitions
+ *
+ */
+
+#include "pkix_crlselector.h"
+
+/* --CRLSelector Private-Functions-------------------------------------- */
+
+/*
+ * FUNCTION: pkix_CRLSelector_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CRLSelector_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_CRLSelector *selector = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRLSELECTOR_TYPE, plContext),
+ PKIX_OBJECTNOTCRLSELECTOR);
+
+ selector = (PKIX_CRLSelector *)object;
+
+ selector->matchCallback = NULL;
+
+ PKIX_DECREF(selector->params);
+ PKIX_DECREF(selector->context);
+
+cleanup:
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_ToString_Helper
+ *
+ * DESCRIPTION:
+ * Helper function that creates a string representation of CRLSelector
+ * pointed to by "crlParams" and stores its address in the object pointed to
+ * by "pString".
+ *
+ * PARAMETERS
+ * "list"
+ * Address of CRLSelector whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address of object pointer's destination. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CRLSelector_ToString_Helper(
+ PKIX_CRLSelector *crlSelector,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *crlSelectorString = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *crlParamsString = NULL;
+ PKIX_PL_String *crlContextString = NULL;
+ char *asciiFormat = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_ToString_Helper");
+ PKIX_NULLCHECK_TWO(crlSelector, pString);
+ PKIX_NULLCHECK_ONE(crlSelector->params);
+
+ asciiFormat =
+ "\n\t[\n"
+ "\tMatchCallback: 0x%x\n"
+ "\tParams: %s\n"
+ "\tContext: %s\n"
+ "\t]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Params */
+ PKIX_TOSTRING
+ ((PKIX_PL_Object *)crlSelector->params,
+ &crlParamsString,
+ plContext,
+ PKIX_COMCRLSELPARAMSTOSTRINGFAILED);
+
+ /* Context */
+ PKIX_TOSTRING(crlSelector->context, &crlContextString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&crlSelectorString,
+ plContext,
+ formatString,
+ crlSelector->matchCallback,
+ crlParamsString,
+ crlContextString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = crlSelectorString;
+
+cleanup:
+
+ PKIX_DECREF(crlParamsString);
+ PKIX_DECREF(crlContextString);
+ PKIX_DECREF(formatString);
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CRLSelector_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *crlSelectorString = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRLSELECTOR_TYPE, plContext),
+ PKIX_OBJECTNOTCRLSELECTOR);
+
+ crlSelector = (PKIX_CRLSelector *) object;
+
+ PKIX_CHECK(pkix_CRLSelector_ToString_Helper
+ (crlSelector, &crlSelectorString, plContext),
+ PKIX_CRLSELECTORTOSTRINGHELPERFAILED);
+
+ *pString = crlSelectorString;
+
+cleanup:
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CRLSelector_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_UInt32 paramsHash = 0;
+ PKIX_UInt32 contextHash = 0;
+ PKIX_UInt32 hash = 0;
+
+ PKIX_CRLSelector *crlSelector = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRLSELECTOR_TYPE, plContext),
+ PKIX_OBJECTNOTCRLSELECTOR);
+
+ crlSelector = (PKIX_CRLSelector *)object;
+
+ PKIX_HASHCODE(crlSelector->params, &paramsHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(crlSelector->context, &contextHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = 31 * ((PKIX_UInt32)((char *)crlSelector->matchCallback - (char *)NULL) +
+ (contextHash << 3)) + paramsHash;
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CRLSelector_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_CRLSelector *firstCrlSelector = NULL;
+ PKIX_CRLSelector *secondCrlSelector = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CRLSelector */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CRLSELECTOR_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCRLSELECTOR);
+
+ firstCrlSelector = (PKIX_CRLSelector *)firstObject;
+ secondCrlSelector = (PKIX_CRLSelector *)secondObject;
+
+ /*
+ * Since we know firstObject is a CRLSelector, if both references are
+ * identical, they must be equal
+ */
+ if (firstCrlSelector == secondCrlSelector){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondCRLSelector isn't a CRLSelector, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ ((PKIX_PL_Object *)secondCrlSelector,
+ &secondType,
+ plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ if (secondType != PKIX_CRLSELECTOR_TYPE) {
+ goto cleanup;
+ }
+
+ /* Compare MatchCallback address */
+ cmpResult = (firstCrlSelector->matchCallback ==
+ secondCrlSelector->matchCallback);
+
+ if (cmpResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ /* Compare Common CRL Selector Params */
+ PKIX_EQUALS
+ (firstCrlSelector->params,
+ secondCrlSelector->params,
+ &cmpResult,
+ plContext,
+ PKIX_COMCRLSELPARAMSEQUALSFAILED);
+
+
+ if (cmpResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ /* Compare Context */
+ PKIX_EQUALS
+ (firstCrlSelector->context,
+ secondCrlSelector->context,
+ &cmpResult,
+ plContext,
+ PKIX_COMCRLSELPARAMSEQUALSFAILED);
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_Duplicate
+ * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CRLSelector_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_CRLSelector *old;
+ PKIX_CRLSelector *new = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CRLSELECTOR_TYPE, plContext),
+ PKIX_OBJECTNOTCRLSELECTOR);
+
+ old = (PKIX_CRLSelector *)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CRLSELECTOR_TYPE,
+ (PKIX_UInt32)(sizeof (PKIX_CRLSelector)),
+ (PKIX_PL_Object **)&new,
+ plContext),
+ PKIX_CREATECRLSELECTORDUPLICATEOBJECTFAILED);
+
+ new->matchCallback = old->matchCallback;
+
+ PKIX_DUPLICATE(old->params, &new->params, plContext,
+ PKIX_OBJECTDUPLICATEPARAMSFAILED);
+
+ PKIX_DUPLICATE(old->context, &new->context, plContext,
+ PKIX_OBJECTDUPLICATECONTEXTFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)new;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(new);
+ }
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_DefaultMatch
+ *
+ * DESCRIPTION:
+ * This function compares the parameter values (Issuer, date, and CRL number)
+ * set in the ComCRLSelParams of the CRLSelector pointed to by "selector" with
+ * the corresponding values in the CRL pointed to by "crl". When all the
+ * criteria set in the parameter values match the values in "crl", PKIX_TRUE is
+ * stored at "pMatch". If the CRL does not match the CRLSelector's criteria,
+ * PKIX_FALSE is stored at "pMatch".
+ *
+ * PARAMETERS
+ * "selector"
+ * Address of CRLSelector which is verified for a match
+ * Must be non-NULL.
+ * "crl"
+ * Address of the CRL object to be verified. Must be non-NULL.
+ * "pMatch"
+ * Address at which Boolean result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CRLSelector_DefaultMatch(
+ PKIX_CRLSelector *selector,
+ PKIX_PL_CRL *crl,
+ PKIX_Boolean *pMatch,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *params = NULL;
+ PKIX_PL_X500Name *crlIssuerName = NULL;
+ PKIX_PL_X500Name *issuerName = NULL;
+ PKIX_List *selIssuerNames = NULL;
+ PKIX_PL_Date *selDate = NULL;
+ PKIX_Boolean result = PKIX_TRUE;
+ PKIX_UInt32 numIssuers = 0;
+ PKIX_UInt32 i;
+ PKIX_PL_BigInt *minCRLNumber = NULL;
+ PKIX_PL_BigInt *maxCRLNumber = NULL;
+ PKIX_PL_BigInt *crlNumber = NULL;
+ PKIX_Boolean nistPolicyEnabled = PKIX_FALSE;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_DefaultMatch");
+ PKIX_NULLCHECK_TWO(selector, crl);
+
+ *pMatch = PKIX_TRUE;
+ params = selector->params;
+
+ /* No matching parameter provided, just a match */
+ if (params == NULL) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_ComCRLSelParams_GetIssuerNames
+ (params, &selIssuerNames, plContext),
+ PKIX_COMCRLSELPARAMSGETISSUERNAMESFAILED);
+
+ /* Check for Issuers */
+ if (selIssuerNames != NULL){
+
+ result = PKIX_FALSE;
+
+ PKIX_CHECK(PKIX_PL_CRL_GetIssuer
+ (crl, &crlIssuerName, plContext),
+ PKIX_CRLGETISSUERFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (selIssuerNames, &numIssuers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numIssuers; i++){
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (selIssuerNames,
+ i,
+ (PKIX_PL_Object **)&issuerName,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_X500Name_Match
+ (crlIssuerName,
+ issuerName,
+ &result,
+ plContext),
+ PKIX_X500NAMEMATCHFAILED);
+
+ PKIX_DECREF(issuerName);
+
+ if (result == PKIX_TRUE) {
+ break;
+ }
+ }
+
+ if (result == PKIX_FALSE) {
+ PKIX_CRLSELECTOR_DEBUG("Issuer Match Failed\N");
+ *pMatch = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ }
+
+ PKIX_CHECK(PKIX_ComCRLSelParams_GetDateAndTime
+ (params, &selDate, plContext),
+ PKIX_COMCRLSELPARAMSGETDATEANDTIMEFAILED);
+
+ /* Check for Date */
+ if (selDate != NULL){
+
+ PKIX_CHECK(PKIX_ComCRLSelParams_GetNISTPolicyEnabled
+ (params, &nistPolicyEnabled, plContext),
+ PKIX_COMCRLSELPARAMSGETNISTPOLICYENABLEDFAILED);
+
+ /* check crl dates only for if NIST policies enforced */
+ if (nistPolicyEnabled) {
+ result = PKIX_FALSE;
+
+ PKIX_CHECK(PKIX_PL_CRL_VerifyUpdateTime
+ (crl, selDate, &result, plContext),
+ PKIX_CRLVERIFYUPDATETIMEFAILED);
+
+ if (result == PKIX_FALSE) {
+ *pMatch = PKIX_FALSE;
+ goto cleanup;
+ }
+ }
+
+ }
+
+ /* Check for CRL number in range */
+ PKIX_CHECK(PKIX_PL_CRL_GetCRLNumber(crl, &crlNumber, plContext),
+ PKIX_CRLGETCRLNUMBERFAILED);
+
+ if (crlNumber != NULL) {
+ result = PKIX_FALSE;
+
+ PKIX_CHECK(PKIX_ComCRLSelParams_GetMinCRLNumber
+ (params, &minCRLNumber, plContext),
+ PKIX_COMCRLSELPARAMSGETMINCRLNUMBERFAILED);
+
+ if (minCRLNumber != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)minCRLNumber,
+ (PKIX_PL_Object *)crlNumber,
+ &result,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+
+ if (result == 1) {
+ PKIX_CRLSELECTOR_DEBUG
+ ("CRL MinNumber Range Match Failed\n");
+ *pMatch = PKIX_FALSE;
+ goto cleanup;
+ }
+ }
+
+ PKIX_CHECK(PKIX_ComCRLSelParams_GetMaxCRLNumber
+ (params, &maxCRLNumber, plContext),
+ PKIX_COMCRLSELPARAMSGETMAXCRLNUMBERFAILED);
+
+ if (maxCRLNumber != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)crlNumber,
+ (PKIX_PL_Object *)maxCRLNumber,
+ &result,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+
+ if (result == 1) {
+ PKIX_CRLSELECTOR_DEBUG
+ (PKIX_CRLMAXNUMBERRANGEMATCHFAILED);
+ *pMatch = PKIX_FALSE;
+ goto cleanup;
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(selIssuerNames);
+ PKIX_DECREF(selDate);
+ PKIX_DECREF(crlIssuerName);
+ PKIX_DECREF(issuerName);
+ PKIX_DECREF(crlNumber);
+ PKIX_DECREF(minCRLNumber);
+ PKIX_DECREF(maxCRLNumber);
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CRLSELECTOR_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_CRLSelector_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CRLSELECTOR, "pkix_CRLSelector_RegisterSelf");
+
+ entry.description = "CRLSelector";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_CRLSelector);
+ entry.destructor = pkix_CRLSelector_Destroy;
+ entry.equalsFunction = pkix_CRLSelector_Equals;
+ entry.hashcodeFunction = pkix_CRLSelector_Hashcode;
+ entry.toStringFunction = pkix_CRLSelector_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_CRLSelector_Duplicate;
+
+ systemClasses[PKIX_CRLSELECTOR_TYPE] = entry;
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/* --CRLSelector-Public-Functions---------------------------------------- */
+PKIX_Error *
+pkix_CRLSelector_Create(
+ PKIX_CRLSelector_MatchCallback callback,
+ PKIX_PL_Object *crlSelectorContext,
+ PKIX_CRLSelector **pSelector,
+ void *plContext)
+{
+ PKIX_CRLSelector *selector = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_Create");
+ PKIX_NULLCHECK_ONE(pSelector);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CRLSELECTOR_TYPE,
+ sizeof (PKIX_CRLSelector),
+ (PKIX_PL_Object **)&selector,
+ plContext),
+ PKIX_COULDNOTCREATECRLSELECTOROBJECT);
+
+ /*
+ * if user specified a particular match callback, we use that one.
+ * otherwise, we use the default match provided.
+ */
+
+ if (callback != NULL){
+ selector->matchCallback = callback;
+ } else {
+ selector->matchCallback = pkix_CRLSelector_DefaultMatch;
+ }
+
+ /* initialize other fields */
+ selector->params = NULL;
+
+ PKIX_INCREF(crlSelectorContext);
+ selector->context = crlSelectorContext;
+
+ *pSelector = selector;
+ selector = NULL;
+
+cleanup:
+
+ PKIX_DECREF(selector);
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: PKIX_CRLSelector_Create (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_CRLSelector_Create(
+ PKIX_PL_Cert *issuer,
+ PKIX_List *crldpList,
+ PKIX_PL_Date *date,
+ PKIX_CRLSelector **pCrlSelector,
+ void *plContext)
+{
+ PKIX_PL_X500Name *issuerName = NULL;
+ PKIX_PL_Date *nowDate = NULL;
+ PKIX_ComCRLSelParams *comCrlSelParams = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+
+ PKIX_ENTER(CERTCHAINCHECKER, "PKIX_CrlSelector_Create");
+ PKIX_NULLCHECK_ONE(issuer);
+
+ PKIX_CHECK(
+ PKIX_PL_Cert_GetSubject(issuer, &issuerName, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ if (date != NULL) {
+ PKIX_INCREF(date);
+ nowDate = date;
+ } else {
+ PKIX_CHECK(
+ PKIX_PL_Date_Create_UTCTime(NULL, &nowDate, plContext),
+ PKIX_DATECREATEUTCTIMEFAILED);
+ }
+
+ PKIX_CHECK(
+ PKIX_ComCRLSelParams_Create(&comCrlSelParams, plContext),
+ PKIX_COMCRLSELPARAMSCREATEFAILED);
+
+ PKIX_CHECK(
+ PKIX_ComCRLSelParams_AddIssuerName(comCrlSelParams, issuerName,
+ plContext),
+ PKIX_COMCRLSELPARAMSADDISSUERNAMEFAILED);
+
+ PKIX_CHECK(
+ PKIX_ComCRLSelParams_SetCrlDp(comCrlSelParams, crldpList,
+ plContext),
+ PKIX_COMCRLSELPARAMSSETCERTFAILED);
+
+ PKIX_CHECK(
+ PKIX_ComCRLSelParams_SetDateAndTime(comCrlSelParams, nowDate,
+ plContext),
+ PKIX_COMCRLSELPARAMSSETDATEANDTIMEFAILED);
+
+ PKIX_CHECK(
+ pkix_CRLSelector_Create(NULL, NULL, &crlSelector, plContext),
+ PKIX_CRLSELECTORCREATEFAILED);
+
+ PKIX_CHECK(
+ PKIX_CRLSelector_SetCommonCRLSelectorParams(crlSelector,
+ comCrlSelParams,
+ plContext),
+ PKIX_CRLSELECTORSETCOMMONCRLSELECTORPARAMSFAILED);
+
+ *pCrlSelector = crlSelector;
+ crlSelector = NULL;
+
+cleanup:
+
+ PKIX_DECREF(issuerName);
+ PKIX_DECREF(nowDate);
+ PKIX_DECREF(comCrlSelParams);
+ PKIX_DECREF(crlSelector);
+
+ PKIX_RETURN(CERTCHAINCHECKER);
+}
+
+/*
+ * FUNCTION: PKIX_CRLSelector_GetMatchCallback (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_CRLSelector_GetMatchCallback(
+ PKIX_CRLSelector *selector,
+ PKIX_CRLSelector_MatchCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_GetMatchCallback");
+ PKIX_NULLCHECK_TWO(selector, pCallback);
+
+ *pCallback = selector->matchCallback;
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+
+/*
+ * FUNCTION: PKIX_CRLSelector_GetCRLSelectorContext
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_CRLSelector_GetCRLSelectorContext(
+ PKIX_CRLSelector *selector,
+ void **pCrlSelectorContext,
+ void *plContext)
+{
+ PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_GetCRLSelectorContext");
+ PKIX_NULLCHECK_TWO(selector, pCrlSelectorContext);
+
+ PKIX_INCREF(selector->context);
+
+ *pCrlSelectorContext = selector->context;
+
+cleanup:
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: PKIX_CRLSelector_GetCommonCRLSelectorParams
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_CRLSelector_GetCommonCRLSelectorParams(
+ PKIX_CRLSelector *selector,
+ PKIX_ComCRLSelParams **pParams,
+ void *plContext)
+{
+ PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_GetCommonCRLSelectorParams");
+ PKIX_NULLCHECK_TWO(selector, pParams);
+
+ PKIX_INCREF(selector->params);
+
+ *pParams = selector->params;
+
+cleanup:
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: PKIX_CRLSelector_SetCommonCRLSelectorParams
+ * (see comments in pkix_crlsel.h)
+ */
+PKIX_Error *
+PKIX_CRLSelector_SetCommonCRLSelectorParams(
+ PKIX_CRLSelector *selector,
+ PKIX_ComCRLSelParams *params,
+ void *plContext)
+{
+ PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_SetCommonCRLSelectorParams");
+ PKIX_NULLCHECK_TWO(selector, params);
+
+ PKIX_DECREF(selector->params);
+
+ PKIX_INCREF(params);
+ selector->params = params;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)selector, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CRLSELECTOR);
+}
+
+/*
+ * FUNCTION: pkix_CRLSelector_Select
+ * DESCRIPTION:
+ *
+ * This function applies the selector pointed to by "selector" to each CRL,
+ * in turn, in the List pointed to by "before", and creates a List containing
+ * all the CRLs that matched, or passed the selection process, storing that
+ * List at "pAfter". If no CRLs match, an empty List is stored at "pAfter".
+ *
+ * The List returned in "pAfter" is immutable.
+ *
+ * PARAMETERS:
+ * "selector"
+ * Address of CRLSelelector to be applied to the List. Must be non-NULL.
+ * "before"
+ * Address of List that is to be filtered. Must be non-NULL.
+ * "pAfter"
+ * Address at which resulting List, possibly empty, is stored. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLSelector Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CRLSelector_Select(
+ PKIX_CRLSelector *selector,
+ PKIX_List *before,
+ PKIX_List **pAfter,
+ void *plContext)
+{
+ PKIX_Boolean match = PKIX_FALSE;
+ PKIX_UInt32 numBefore = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_List *filtered = NULL;
+ PKIX_PL_CRL *candidate = NULL;
+
+ PKIX_ENTER(CRLSELECTOR, "PKIX_CRLSelector_Select");
+ PKIX_NULLCHECK_THREE(selector, before, pAfter);
+
+ PKIX_CHECK(PKIX_List_Create(&filtered, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(before, &numBefore, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numBefore; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (before, i, (PKIX_PL_Object **)&candidate, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK_ONLY_FATAL(selector->matchCallback
+ (selector, candidate, &match, plContext),
+ PKIX_CRLSELECTORMATCHCALLBACKFAILED);
+
+ if (!(PKIX_ERROR_RECEIVED) && match == PKIX_TRUE) {
+
+ PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem
+ (filtered,
+ (PKIX_PL_Object *)candidate,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ pkixTempErrorReceived = PKIX_FALSE;
+ PKIX_DECREF(candidate);
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(filtered, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ /* Don't throw away the list if one CRL was bad! */
+ pkixTempErrorReceived = PKIX_FALSE;
+
+ *pAfter = filtered;
+ filtered = NULL;
+
+cleanup:
+
+ PKIX_DECREF(filtered);
+ PKIX_DECREF(candidate);
+
+ PKIX_RETURN(CRLSELECTOR);
+
+}
diff --git a/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.h b/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.h
new file mode 100644
index 0000000000..4f44cc7683
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/crlsel/pkix_crlselector.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/. */
+/*
+ * pkix_crlselector.h
+ *
+ * CrlSelector Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_CRLSELECTOR_H
+#define _PKIX_CRLSELECTOR_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_CRLSelectorStruct {
+ PKIX_CRLSelector_MatchCallback matchCallback;
+ PKIX_ComCRLSelParams *params;
+ PKIX_PL_Object *context;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_CRLSelector_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_CRLSelector_Select(
+ PKIX_CRLSelector *selector,
+ PKIX_List *before,
+ PKIX_List **pAfter,
+ void *plContext);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_CRLSELECTOR_H */
diff --git a/security/nss/lib/libpkix/pkix/manifest.mn b/security/nss/lib/libpkix/pkix/manifest.mn
new file mode 100644
index 0000000000..dcb6f0ce61
--- /dev/null
+++ b/security/nss/lib/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/.
+CORE_DEPTH = ../../..
+DEPTH = ../../..
+
+#
+DIRS = certsel crlsel checker params results store top util \
+ $(NULL)
+
diff --git a/security/nss/lib/libpkix/pkix/params/Makefile b/security/nss/lib/libpkix/pkix/params/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/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). #
+#######################################################################
+
+
+#######################################################################
+# (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/lib/libpkix/pkix/params/exports.gyp b/security/nss/lib/libpkix/pkix/params/exports.gyp
new file mode 100644
index 0000000000..921f2ceae3
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/exports.gyp
@@ -0,0 +1,28 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_libpkix_pkix_params_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_procparams.h',
+ 'pkix_resourcelimits.h',
+ 'pkix_trustanchor.h',
+ 'pkix_valparams.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/params/manifest.mn b/security/nss/lib/libpkix/pkix/params/manifest.mn
new file mode 100644
index 0000000000..2a77bf0eea
--- /dev/null
+++ b/security/nss/lib/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/.
+CORE_DEPTH = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_procparams.h \
+ pkix_trustanchor.h \
+ pkix_valparams.h \
+ pkix_resourcelimits.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_trustanchor.c \
+ pkix_procparams.c \
+ pkix_valparams.c \
+ pkix_resourcelimits.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixparams
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/params/params.gyp b/security/nss/lib/libpkix/pkix/params/params.gyp
new file mode 100644
index 0000000000..a1463c4c7c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/params.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'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixparams',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_procparams.c',
+ 'pkix_resourcelimits.c',
+ 'pkix_trustanchor.c',
+ 'pkix_valparams.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_procparams.c b/security/nss/lib/libpkix/pkix/params/pkix_procparams.c
new file mode 100644
index 0000000000..260b0074c7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_procparams.c
@@ -0,0 +1,1417 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_procparams.c
+ *
+ * ProcessingParams Object Functions
+ *
+ */
+
+#include "pkix_procparams.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_ProcessingParams_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ProcessingParams_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ProcessingParams *params = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a processing params object */
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_PROCESSINGPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTPROCESSINGPARAMS);
+
+ params = (PKIX_ProcessingParams *)object;
+
+ PKIX_DECREF(params->trustAnchors);
+ PKIX_DECREF(params->hintCerts);
+ PKIX_DECREF(params->constraints);
+ PKIX_DECREF(params->date);
+ PKIX_DECREF(params->initialPolicies);
+ PKIX_DECREF(params->certChainCheckers);
+ PKIX_DECREF(params->revChecker);
+ PKIX_DECREF(params->certStores);
+ PKIX_DECREF(params->resourceLimits);
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ProcessingParams_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ProcessingParams_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_ProcessingParams *firstProcParams = NULL;
+ PKIX_ProcessingParams *secondProcParams = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_PROCESSINGPARAMS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTPROCESSINGPARAMS);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_PROCESSINGPARAMS_TYPE) goto cleanup;
+
+ firstProcParams = (PKIX_ProcessingParams *)first;
+ secondProcParams = (PKIX_ProcessingParams *)second;
+
+ /* Do the simplest tests first */
+ if ((firstProcParams->qualifiersRejected) !=
+ (secondProcParams->qualifiersRejected)) {
+ goto cleanup;
+ }
+
+ if (firstProcParams->isCrlRevocationCheckingEnabled !=
+ secondProcParams->isCrlRevocationCheckingEnabled) {
+ goto cleanup;
+ }
+ if (firstProcParams->isCrlRevocationCheckingEnabledWithNISTPolicy !=
+ secondProcParams->isCrlRevocationCheckingEnabledWithNISTPolicy) {
+ goto cleanup;
+ }
+
+ /* trustAnchors can never be NULL */
+
+ PKIX_EQUALS
+ (firstProcParams->trustAnchors,
+ secondProcParams->trustAnchors,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_EQUALS
+ (firstProcParams->hintCerts,
+ secondProcParams->hintCerts,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_EQUALS
+ (firstProcParams->date,
+ secondProcParams->date,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_EQUALS
+ (firstProcParams->constraints,
+ secondProcParams->constraints,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_EQUALS
+ (firstProcParams->initialPolicies,
+ secondProcParams->initialPolicies,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ /* There is no Equals function for CertChainCheckers */
+
+ PKIX_EQUALS
+ ((PKIX_PL_Object *)firstProcParams->certStores,
+ (PKIX_PL_Object *)secondProcParams->certStores,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_EQUALS
+ (firstProcParams->resourceLimits,
+ secondProcParams->resourceLimits,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (cmpResult == PKIX_FALSE) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ProcessingParams_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ProcessingParams_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 anchorsHash = 0;
+ PKIX_UInt32 hintCertsHash = 0;
+ PKIX_UInt32 dateHash = 0;
+ PKIX_UInt32 constraintsHash = 0;
+ PKIX_UInt32 initialHash = 0;
+ PKIX_UInt32 rejectedHash = 0;
+ PKIX_UInt32 certChainCheckersHash = 0;
+ PKIX_UInt32 revCheckerHash = 0;
+ PKIX_UInt32 certStoresHash = 0;
+ PKIX_UInt32 resourceLimitsHash = 0;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_PROCESSINGPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTPROCESSINGPARAMS);
+
+ procParams = (PKIX_ProcessingParams*)object;
+
+ PKIX_HASHCODE(procParams->trustAnchors, &anchorsHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(procParams->hintCerts, &hintCertsHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(procParams->date, &dateHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(procParams->constraints, &constraintsHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(procParams->initialPolicies, &initialHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ rejectedHash = procParams->qualifiersRejected;
+
+ /* There is no Hash function for CertChainCheckers */
+
+ PKIX_HASHCODE(procParams->certStores, &certStoresHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(procParams->resourceLimits,
+ &resourceLimitsHash,
+ plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = (31 * ((31 * anchorsHash) + hintCertsHash + dateHash)) +
+ constraintsHash + initialHash + rejectedHash;
+
+ hash += ((((certStoresHash + resourceLimitsHash) << 7) +
+ certChainCheckersHash + revCheckerHash +
+ procParams->isCrlRevocationCheckingEnabled +
+ procParams->isCrlRevocationCheckingEnabledWithNISTPolicy) << 7);
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ProcessingParams_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ProcessingParams_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_ProcessingParams *procParams = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *procParamsString = NULL;
+ PKIX_PL_String *anchorsString = NULL;
+ PKIX_PL_String *dateString = NULL;
+ PKIX_PL_String *constraintsString = NULL;
+ PKIX_PL_String *InitialPoliciesString = NULL;
+ PKIX_PL_String *qualsRejectedString = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_PL_String *certStoresString = NULL;
+ PKIX_PL_String *resourceLimitsString = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_PROCESSINGPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTPROCESSINGPARAMS);
+
+ asciiFormat =
+ "[\n"
+ "\tTrust Anchors: \n"
+ "\t********BEGIN LIST OF TRUST ANCHORS********\n"
+ "\t\t%s\n"
+ "\t********END LIST OF TRUST ANCHORS********\n"
+ "\tDate: \t\t%s\n"
+ "\tTarget Constraints: %s\n"
+ "\tInitial Policies: %s\n"
+ "\tQualifiers Rejected: %s\n"
+ "\tCert Stores: %s\n"
+ "\tResource Limits: %s\n"
+ "\tCRL Checking Enabled: %d\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ procParams = (PKIX_ProcessingParams*)object;
+
+ PKIX_TOSTRING(procParams->trustAnchors, &anchorsString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(procParams->date, &dateString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(procParams->constraints, &constraintsString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (procParams->initialPolicies, &InitialPoliciesString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (procParams->qualifiersRejected)?"TRUE":"FALSE",
+ 0,
+ &qualsRejectedString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* There is no ToString function for CertChainCheckers */
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
+ (procParams, &certStores, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
+
+ PKIX_TOSTRING(certStores, &certStoresString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_TOSTRING(procParams->resourceLimits,
+ &resourceLimitsString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&procParamsString,
+ plContext,
+ formatString,
+ anchorsString,
+ dateString,
+ constraintsString,
+ InitialPoliciesString,
+ qualsRejectedString,
+ certStoresString,
+ resourceLimitsString,
+ procParams->isCrlRevocationCheckingEnabled,
+ procParams->isCrlRevocationCheckingEnabledWithNISTPolicy),
+ PKIX_SPRINTFFAILED);
+
+ *pString = procParamsString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(anchorsString);
+ PKIX_DECREF(dateString);
+ PKIX_DECREF(constraintsString);
+ PKIX_DECREF(InitialPoliciesString);
+ PKIX_DECREF(qualsRejectedString);
+ PKIX_DECREF(certStores);
+ PKIX_DECREF(certStoresString);
+ PKIX_DECREF(resourceLimitsString);
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ProcessingParams_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ProcessingParams_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_ProcessingParams *params = NULL;
+ PKIX_ProcessingParams *paramsDuplicate = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_PROCESSINGPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTPROCESSINGPARAMS);
+
+ params = (PKIX_ProcessingParams *)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_PROCESSINGPARAMS_TYPE,
+ sizeof (PKIX_ProcessingParams),
+ (PKIX_PL_Object **)&paramsDuplicate,
+ plContext),
+ PKIX_PROCESSINGPARAMSCREATEFAILED);
+
+ /* initialize fields */
+ PKIX_DUPLICATE
+ (params->trustAnchors,
+ &(paramsDuplicate->trustAnchors),
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->hintCerts, &(paramsDuplicate->hintCerts), plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->constraints,
+ &(paramsDuplicate->constraints),
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->date, &(paramsDuplicate->date), plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->initialPolicies,
+ &(paramsDuplicate->initialPolicies),
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ paramsDuplicate->initialPolicyMappingInhibit =
+ params->initialPolicyMappingInhibit;
+ paramsDuplicate->initialAnyPolicyInhibit =
+ params->initialAnyPolicyInhibit;
+ paramsDuplicate->initialExplicitPolicy = params->initialExplicitPolicy;
+ paramsDuplicate->qualifiersRejected = params->qualifiersRejected;
+
+ PKIX_DUPLICATE
+ (params->certChainCheckers,
+ &(paramsDuplicate->certChainCheckers),
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->revChecker,
+ &(paramsDuplicate->revChecker),
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->certStores, &(paramsDuplicate->certStores), plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_DUPLICATE
+ (params->resourceLimits,
+ &(paramsDuplicate->resourceLimits),
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ paramsDuplicate->isCrlRevocationCheckingEnabled =
+ params->isCrlRevocationCheckingEnabled;
+
+ paramsDuplicate->isCrlRevocationCheckingEnabledWithNISTPolicy =
+ params->isCrlRevocationCheckingEnabledWithNISTPolicy;
+
+ *pNewObject = (PKIX_PL_Object *)paramsDuplicate;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(paramsDuplicate);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+
+}
+
+/*
+ * FUNCTION: pkix_ProcessingParams_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_PROCESSINGPARAMS_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_ProcessingParams_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_RegisterSelf");
+
+ entry.description = "ProcessingParams";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_ProcessingParams);
+ entry.destructor = pkix_ProcessingParams_Destroy;
+ entry.equalsFunction = pkix_ProcessingParams_Equals;
+ entry.hashcodeFunction = pkix_ProcessingParams_Hashcode;
+ entry.toStringFunction = pkix_ProcessingParams_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_ProcessingParams_Duplicate;
+
+ systemClasses[PKIX_PROCESSINGPARAMS_TYPE] = entry;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_Create (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_Create(
+ PKIX_ProcessingParams **pParams,
+ void *plContext)
+{
+ PKIX_ProcessingParams *params = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_Create");
+ PKIX_NULLCHECK_ONE(pParams);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_PROCESSINGPARAMS_TYPE,
+ sizeof (PKIX_ProcessingParams),
+ (PKIX_PL_Object **)&params,
+ plContext),
+ PKIX_COULDNOTCREATEPROCESSINGPARAMSOBJECT);
+
+ /* initialize fields */
+ PKIX_CHECK(PKIX_List_Create(&params->trustAnchors, plContext),
+ PKIX_LISTCREATEFAILED);
+ PKIX_CHECK(PKIX_List_SetImmutable(params->trustAnchors, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Date_Create_UTCTime
+ (NULL, &params->date, plContext),
+ PKIX_DATECREATEUTCTIMEFAILED);
+
+ params->hintCerts = NULL;
+ params->constraints = NULL;
+ params->initialPolicies = NULL;
+ params->initialPolicyMappingInhibit = PKIX_FALSE;
+ params->initialAnyPolicyInhibit = PKIX_FALSE;
+ params->initialExplicitPolicy = PKIX_FALSE;
+ params->qualifiersRejected = PKIX_FALSE;
+ params->certChainCheckers = NULL;
+ params->revChecker = NULL;
+ params->certStores = NULL;
+ params->resourceLimits = NULL;
+
+ params->isCrlRevocationCheckingEnabled = PKIX_TRUE;
+
+ params->isCrlRevocationCheckingEnabledWithNISTPolicy = PKIX_TRUE;
+
+ params->useAIAForCertFetching = PKIX_FALSE;
+ params->qualifyTargetCert = PKIX_TRUE;
+ params->useOnlyTrustAnchors = PKIX_TRUE;
+
+ *pParams = params;
+ params = NULL;
+
+cleanup:
+
+ PKIX_DECREF(params);
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetUseAIAForCertFetching
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetUseAIAForCertFetching(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pUseAIA, /* list of TrustAnchor */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetUseAIAForCertFetching");
+ PKIX_NULLCHECK_TWO(params, pUseAIA);
+
+ *pUseAIA = params->useAIAForCertFetching;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetUseAIAForCertFetching
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetUseAIAForCertFetching(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean useAIA,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetUseAIAForCertFetching");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->useAIAForCertFetching = useAIA;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetQualifyTargetCert
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetValidateTargetCert(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pQualifyTargetCert,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_GetValidateTargetCert");
+ PKIX_NULLCHECK_TWO(params, pQualifyTargetCert);
+
+ *pQualifyTargetCert = params->qualifyTargetCert;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetQualifyTargetCert
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetQualifyTargetCert(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean qualifyTargetCert,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetQualifyTargetCert");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->qualifyTargetCert = qualifyTargetCert;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetTrustAnchors
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetTrustAnchors(
+ PKIX_ProcessingParams *params,
+ PKIX_List *anchors, /* list of TrustAnchor */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetTrustAnchors");
+ PKIX_NULLCHECK_TWO(params, anchors);
+
+ PKIX_DECREF(params->trustAnchors);
+
+ PKIX_INCREF(anchors);
+ params->trustAnchors = anchors;
+ PKIX_CHECK(PKIX_List_SetImmutable(params->trustAnchors, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetTrustAnchors
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetTrustAnchors(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pAnchors, /* list of TrustAnchor */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetTrustAnchors");
+ PKIX_NULLCHECK_TWO(params, pAnchors);
+
+ PKIX_INCREF(params->trustAnchors);
+
+ *pAnchors = params->trustAnchors;
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/**
+ * FUNCTION: PKIX_ProcessingParams_SetUseOnlyTrustAnchors
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetUseOnlyTrustAnchors(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pUseOnlyTrustAnchors,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetUseTrustAnchorsOnly");
+ PKIX_NULLCHECK_TWO(params, pUseOnlyTrustAnchors);
+
+ *pUseOnlyTrustAnchors = params->useOnlyTrustAnchors;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/**
+ * FUNCTION: PKIX_ProcessingParams_SetUseOnlyTrustAnchors
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetUseOnlyTrustAnchors(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean useOnlyTrustAnchors,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetUseTrustAnchorsOnly");
+ PKIX_NULLCHECK_ONE(params);
+
+ params->useOnlyTrustAnchors = useOnlyTrustAnchors;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetDate (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetDate(
+ PKIX_ProcessingParams *params,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetDate");
+ PKIX_NULLCHECK_TWO(params, pDate);
+
+ PKIX_INCREF(params->date);
+ *pDate = params->date;
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetDate (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetDate(
+ PKIX_ProcessingParams *params,
+ PKIX_PL_Date *date,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetDate");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->date);
+
+ PKIX_INCREF(date);
+ params->date = date;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->date);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetTargetCertConstraints
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetTargetCertConstraints(
+ PKIX_ProcessingParams *params,
+ PKIX_CertSelector **pConstraints,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_GetTargetCertConstraints");
+
+ PKIX_NULLCHECK_TWO(params, pConstraints);
+
+ PKIX_INCREF(params->constraints);
+ *pConstraints = params->constraints;
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetTargetCertConstraints
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetTargetCertConstraints(
+ PKIX_ProcessingParams *params,
+ PKIX_CertSelector *constraints,
+ void *plContext)
+{
+
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetTargetCertConstraints");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->constraints);
+
+ PKIX_INCREF(constraints);
+ params->constraints = constraints;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->constraints);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetInitialPolicies
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetInitialPolicies(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pInitPolicies, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_GetInitialPolicies");
+
+ PKIX_NULLCHECK_TWO(params, pInitPolicies);
+
+ if (params->initialPolicies == NULL) {
+ PKIX_CHECK(PKIX_List_Create
+ (&params->initialPolicies, plContext),
+ PKIX_UNABLETOCREATELIST);
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (params->initialPolicies, plContext),
+ PKIX_UNABLETOMAKELISTIMMUTABLE);
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ }
+
+ PKIX_INCREF(params->initialPolicies);
+ *pInitPolicies = params->initialPolicies;
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetInitialPolicies
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetInitialPolicies(
+ PKIX_ProcessingParams *params,
+ PKIX_List *initPolicies, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetInitialPolicies");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->initialPolicies);
+
+ PKIX_INCREF(initPolicies);
+ params->initialPolicies = initPolicies;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->initialPolicies);
+ }
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetPolicyQualifiersRejected
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetPolicyQualifiersRejected(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pRejected,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_GetPolicyQualifiersRejected");
+
+ PKIX_NULLCHECK_TWO(params, pRejected);
+
+ *pRejected = params->qualifiersRejected;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetPolicyQualifiersRejected
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetPolicyQualifiersRejected(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean rejected,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetPolicyQualifiersRejected");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ params->qualifiersRejected = rejected;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetCertChainCheckers
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetCertChainCheckers(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pCheckers, /* list of PKIX_CertChainChecker */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_GetCertChainCheckers");
+ PKIX_NULLCHECK_TWO(params, pCheckers);
+
+ PKIX_INCREF(params->certChainCheckers);
+ *pCheckers = params->certChainCheckers;
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetCertChainCheckers
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetCertChainCheckers(
+ PKIX_ProcessingParams *params,
+ PKIX_List *checkers, /* list of PKIX_CertChainChecker */
+ void *plContext)
+{
+
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetCertChainCheckers");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->certChainCheckers);
+
+ PKIX_INCREF(checkers);
+ params->certChainCheckers = checkers;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->certChainCheckers);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_AddCertChainCheckers
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_AddCertChainChecker(
+ PKIX_ProcessingParams *params,
+ PKIX_CertChainChecker *checker,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_AddCertChainChecker");
+ PKIX_NULLCHECK_TWO(params, checker);
+
+ if (params->certChainCheckers == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ params->certChainCheckers = list;
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (params->certChainCheckers, (PKIX_PL_Object *)checker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ list = NULL;
+
+cleanup:
+
+ if (list && params) {
+ PKIX_DECREF(params->certChainCheckers);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetRevocationChecker
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetRevocationChecker(
+ PKIX_ProcessingParams *params,
+ PKIX_RevocationChecker **pChecker,
+ void *plContext)
+{
+
+ PKIX_ENTER
+ (PROCESSINGPARAMS, "PKIX_ProcessingParams_GetRevocationCheckers");
+ PKIX_NULLCHECK_TWO(params, pChecker);
+
+ PKIX_INCREF(params->revChecker);
+ *pChecker = params->revChecker;
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetRevocationChecker
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetRevocationChecker(
+ PKIX_ProcessingParams *params,
+ PKIX_RevocationChecker *checker,
+ void *plContext)
+{
+
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_InitRevocationChecker");
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->revChecker);
+ PKIX_INCREF(checker);
+ params->revChecker = checker;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetCertStores
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetCertStores(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pStores, /* list of PKIX_CertStore */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetCertStores");
+
+ PKIX_NULLCHECK_TWO(params, pStores);
+
+ if (!params->certStores){
+ PKIX_CHECK(PKIX_List_Create(&params->certStores, plContext),
+ PKIX_UNABLETOCREATELIST);
+ }
+
+ PKIX_INCREF(params->certStores);
+ *pStores = params->certStores;
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetCertStores
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetCertStores(
+ PKIX_ProcessingParams *params,
+ PKIX_List *stores, /* list of PKIX_CertStore */
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetCertStores");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->certStores);
+
+ PKIX_INCREF(stores);
+ params->certStores = stores;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->certStores);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_AddCertStore
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_AddCertStore(
+ PKIX_ProcessingParams *params,
+ PKIX_CertStore *store,
+ void *plContext)
+{
+ PKIX_List *certStores = NULL;
+
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_AddCertStore");
+ PKIX_NULLCHECK_TWO(params, store);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
+ (params, &certStores, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (certStores, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(certStores);
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetResourceLimits
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetResourceLimits(
+ PKIX_ProcessingParams *params,
+ PKIX_ResourceLimits *resourceLimits,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetResourceLimits");
+
+ PKIX_NULLCHECK_TWO(params, resourceLimits);
+
+ PKIX_DECREF(params->resourceLimits);
+ PKIX_INCREF(resourceLimits);
+ params->resourceLimits = resourceLimits;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->resourceLimits);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetResourceLimits
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetResourceLimits(
+ PKIX_ProcessingParams *params,
+ PKIX_ResourceLimits **pResourceLimits,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_GetResourceLimits");
+
+ PKIX_NULLCHECK_TWO(params, pResourceLimits);
+
+ PKIX_INCREF(params->resourceLimits);
+ *pResourceLimits = params->resourceLimits;
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_IsAnyPolicyInhibited
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_IsAnyPolicyInhibited(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pInhibited,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_IsAnyPolicyInhibited");
+
+ PKIX_NULLCHECK_TWO(params, pInhibited);
+
+ *pInhibited = params->initialAnyPolicyInhibit;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetAnyPolicyInhibited
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetAnyPolicyInhibited(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean inhibited,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetAnyPolicyInhibited");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ params->initialAnyPolicyInhibit = inhibited;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_IsExplicitPolicyRequired
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_IsExplicitPolicyRequired(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pRequired,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_IsExplicitPolicyRequired");
+
+ PKIX_NULLCHECK_TWO(params, pRequired);
+
+ *pRequired = params->initialExplicitPolicy;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetExplicitPolicyRequired
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetExplicitPolicyRequired(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean required,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetExplicitPolicyRequired");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ params->initialExplicitPolicy = required;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_IsPolicyMappingInhibited
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_IsPolicyMappingInhibited(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean *pInhibited,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_IsPolicyMappingInhibited");
+
+ PKIX_NULLCHECK_TWO(params, pInhibited);
+
+ *pInhibited = params->initialPolicyMappingInhibit;
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetPolicyMappingInhibited
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetPolicyMappingInhibited(
+ PKIX_ProcessingParams *params,
+ PKIX_Boolean inhibited,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS,
+ "PKIX_ProcessingParams_SetPolicyMappingInhibited");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ params->initialPolicyMappingInhibit = inhibited;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)params, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_SetHintCerts
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_SetHintCerts(
+ PKIX_ProcessingParams *params,
+ PKIX_List *hintCerts,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_SetHintCerts");
+
+ PKIX_NULLCHECK_ONE(params);
+
+ PKIX_DECREF(params->hintCerts);
+ PKIX_INCREF(hintCerts);
+ params->hintCerts = hintCerts;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED && params) {
+ PKIX_DECREF(params->hintCerts);
+ }
+
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ProcessingParams_GetHintCerts
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ProcessingParams_GetHintCerts(
+ PKIX_ProcessingParams *params,
+ PKIX_List **pHintCerts,
+ void *plContext)
+{
+ PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_GetHintCerts");
+
+ PKIX_NULLCHECK_TWO(params, pHintCerts);
+
+ PKIX_INCREF(params->hintCerts);
+ *pHintCerts = params->hintCerts;
+
+cleanup:
+ PKIX_RETURN(PROCESSINGPARAMS);
+}
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_procparams.h b/security/nss/lib/libpkix/pkix/params/pkix_procparams.h
new file mode 100644
index 0000000000..599f5d4988
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_procparams.h
@@ -0,0 +1,50 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_procparams.h
+ *
+ * ProcessingParams Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_PROCESSINGPARAMS_H
+#define _PKIX_PROCESSINGPARAMS_H
+
+#include "pkix_tools.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_ProcessingParamsStruct {
+ PKIX_List *trustAnchors; /* Never NULL */
+ PKIX_List *hintCerts; /* user-supplied partial chain, may be NULL */
+ PKIX_CertSelector *constraints;
+ PKIX_PL_Date *date;
+ PKIX_List *initialPolicies; /* list of PKIX_PL_OID */
+ PKIX_Boolean initialPolicyMappingInhibit;
+ PKIX_Boolean initialAnyPolicyInhibit;
+ PKIX_Boolean initialExplicitPolicy;
+ PKIX_Boolean qualifiersRejected;
+ PKIX_List *certChainCheckers;
+ PKIX_List *certStores;
+ PKIX_Boolean isCrlRevocationCheckingEnabled;
+ PKIX_Boolean isCrlRevocationCheckingEnabledWithNISTPolicy;
+ PKIX_RevocationChecker *revChecker;
+ PKIX_ResourceLimits *resourceLimits;
+ PKIX_Boolean useAIAForCertFetching;
+ PKIX_Boolean qualifyTargetCert;
+ PKIX_Boolean useOnlyTrustAnchors;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_ProcessingParams_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PROCESSINGPARAMS_H */
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.c b/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.c
new file mode 100644
index 0000000000..de93e9d771
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.c
@@ -0,0 +1,433 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_resourcelimits.c
+ *
+ * Resourcelimits Params Object Functions
+ *
+ */
+
+#include "pkix_resourcelimits.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_ResourceLimits_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ResourceLimits_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ResourceLimits *rLimits = NULL;
+
+ PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a ResourceLimits object */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_RESOURCELIMITS_TYPE, plContext),
+ PKIX_OBJECTNOTRESOURCELIMITS);
+
+ rLimits = (PKIX_ResourceLimits *)object;
+
+ rLimits->maxTime = 0;
+ rLimits->maxFanout = 0;
+ rLimits->maxDepth = 0;
+ rLimits->maxCertsNumber = 0;
+ rLimits->maxCrlsNumber = 0;
+
+cleanup:
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: pkix_ResourceLimits_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ResourceLimits_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_ResourceLimits *firstRLimits = NULL;
+ PKIX_ResourceLimits *secondRLimits = NULL;
+
+ PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_RESOURCELIMITS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTRESOURCELIMITS);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_RESOURCELIMITS_TYPE) goto cleanup;
+
+ firstRLimits = (PKIX_ResourceLimits *)first;
+ secondRLimits = (PKIX_ResourceLimits *)second;
+
+ cmpResult = (firstRLimits->maxTime == secondRLimits->maxTime) &&
+ (firstRLimits->maxFanout == secondRLimits->maxFanout) &&
+ (firstRLimits->maxDepth == secondRLimits->maxDepth) &&
+ (firstRLimits->maxCertsNumber ==
+ secondRLimits->maxCertsNumber) &&
+ (firstRLimits->maxCrlsNumber ==
+ secondRLimits->maxCrlsNumber);
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: pkix_ResourceLimits_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ResourceLimits_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_ResourceLimits *rLimits = NULL;
+ PKIX_UInt32 hash = 0;
+
+ PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_RESOURCELIMITS_TYPE, plContext),
+ PKIX_OBJECTNOTRESOURCELIMITS);
+
+ rLimits = (PKIX_ResourceLimits*)object;
+
+ hash = 31 * rLimits->maxTime + (rLimits->maxFanout << 1) +
+ (rLimits->maxDepth << 2) + (rLimits->maxCertsNumber << 3) +
+ rLimits->maxCrlsNumber;
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: pkix_ResourceLimits_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ResourceLimits_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_ResourceLimits *rLimits = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *rLimitsString = NULL;
+
+ PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_RESOURCELIMITS_TYPE, plContext),
+ PKIX_OBJECTNOTRESOURCELIMITS);
+
+ /* maxCertsNumber and maxCrlsNumber are not supported */
+ asciiFormat =
+ "[\n"
+ "\tMaxTime: \t\t%d\n"
+ "\tMaxFanout: \t\t%d\n"
+ "\tMaxDepth: \t\t%d\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ rLimits = (PKIX_ResourceLimits*)object;
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&rLimitsString,
+ plContext,
+ formatString,
+ rLimits->maxTime,
+ rLimits->maxFanout,
+ rLimits->maxDepth),
+ PKIX_SPRINTFFAILED);
+
+ *pString = rLimitsString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: pkix_ResourceLimits_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_RESOURCELIMITS_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_ResourceLimits_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(RESOURCELIMITS, "pkix_ResourceLimits_RegisterSelf");
+
+ entry.description = "ResourceLimits";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_ResourceLimits);
+ entry.destructor = pkix_ResourceLimits_Destroy;
+ entry.equalsFunction = pkix_ResourceLimits_Equals;
+ entry.hashcodeFunction = pkix_ResourceLimits_Hashcode;
+ entry.toStringFunction = pkix_ResourceLimits_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_RESOURCELIMITS_TYPE] = entry;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_Create (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_Create(
+ PKIX_ResourceLimits **pResourceLimits,
+ void *plContext)
+{
+ PKIX_ResourceLimits *rLimits = NULL;
+
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_Create");
+ PKIX_NULLCHECK_ONE(pResourceLimits);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_RESOURCELIMITS_TYPE,
+ sizeof (PKIX_ResourceLimits),
+ (PKIX_PL_Object **)&rLimits,
+ plContext),
+ PKIX_COULDNOTCREATERESOURCELIMITOBJECT);
+
+ /* initialize fields */
+ rLimits->maxTime = 0;
+ rLimits->maxFanout = 0;
+ rLimits->maxDepth = 0;
+ rLimits->maxCertsNumber = 0;
+ rLimits->maxCrlsNumber = 0;
+
+ *pResourceLimits = rLimits;
+
+cleanup:
+
+ PKIX_RETURN(RESOURCELIMITS);
+
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxTime
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxTime(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 *pMaxTime,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxTime");
+ PKIX_NULLCHECK_TWO(rLimits, pMaxTime);
+
+ *pMaxTime = rLimits->maxTime;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxTime
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxTime(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 maxTime,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxTime");
+ PKIX_NULLCHECK_ONE(rLimits);
+
+ rLimits->maxTime = maxTime;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxFanout
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxFanout(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 *pMaxFanout,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxFanout");
+ PKIX_NULLCHECK_TWO(rLimits, pMaxFanout);
+
+ *pMaxFanout = rLimits->maxFanout;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxFanout
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxFanout(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 maxFanout,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxFanout");
+ PKIX_NULLCHECK_ONE(rLimits);
+
+ rLimits->maxFanout = maxFanout;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxDepth
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxDepth(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 *pMaxDepth,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxDepth");
+ PKIX_NULLCHECK_TWO(rLimits, pMaxDepth);
+
+ *pMaxDepth = rLimits->maxDepth;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxDepth
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxDepth(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 maxDepth,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxDepth");
+ PKIX_NULLCHECK_ONE(rLimits);
+
+ rLimits->maxDepth = maxDepth;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxNumberOfCerts
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxNumberOfCerts(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 *pMaxNumber,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxNumberOfCerts");
+ PKIX_NULLCHECK_TWO(rLimits, pMaxNumber);
+
+ *pMaxNumber = rLimits->maxCertsNumber;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxNumberOfCerts
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxNumberOfCerts(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 maxNumber,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxNumberOfCerts");
+ PKIX_NULLCHECK_ONE(rLimits);
+
+ rLimits->maxCertsNumber = maxNumber;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_GetMaxNumberOfCRLs
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_GetMaxNumberOfCRLs(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 *pMaxNumber,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_GetMaxNumberOfCRLs");
+ PKIX_NULLCHECK_TWO(rLimits, pMaxNumber);
+
+ *pMaxNumber = rLimits->maxCrlsNumber;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
+
+/*
+ * FUNCTION: PKIX_ResourceLimits_SetMaxNumberOfCRLs
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ResourceLimits_SetMaxNumberOfCRLs(
+ PKIX_ResourceLimits *rLimits,
+ PKIX_UInt32 maxNumber,
+ void *plContext)
+{
+ PKIX_ENTER(RESOURCELIMITS, "PKIX_ResourceLimits_SetMaxNumberOfCRLs");
+ PKIX_NULLCHECK_ONE(rLimits);
+
+ rLimits->maxCrlsNumber = maxNumber;
+
+ PKIX_RETURN(RESOURCELIMITS);
+}
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.h b/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.h
new file mode 100644
index 0000000000..c4f582ce6f
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_resourcelimits.h
@@ -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/. */
+/*
+ * pkix_resourcelimits.h
+ *
+ * ResourceLimits Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_RESOURCELIMITS_H
+#define _PKIX_RESOURCELIMITS_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_ResourceLimitsStruct {
+ PKIX_UInt32 maxTime;
+ PKIX_UInt32 maxFanout;
+ PKIX_UInt32 maxDepth;
+ PKIX_UInt32 maxCertsNumber;
+ PKIX_UInt32 maxCrlsNumber;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_ResourceLimits_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_RESOURCELIMITS_H */
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.c b/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.c
new file mode 100644
index 0000000000..ced16d2902
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.c
@@ -0,0 +1,525 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_trustanchor.c
+ *
+ * TrustAnchor Object Functions
+ *
+ */
+
+#include "pkix_trustanchor.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_TrustAnchor_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_TrustAnchor_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_TrustAnchor *anchor = NULL;
+
+ PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a trust anchor */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext),
+ PKIX_OBJECTNOTTRUSTANCHOR);
+
+ anchor = (PKIX_TrustAnchor *)object;
+
+ PKIX_DECREF(anchor->trustedCert);
+ PKIX_DECREF(anchor->caName);
+ PKIX_DECREF(anchor->caPubKey);
+ PKIX_DECREF(anchor->nameConstraints);
+
+cleanup:
+
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/*
+ * FUNCTION: pkix_TrustAnchor_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_TrustAnchor_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_TrustAnchor *firstAnchor = NULL;
+ PKIX_TrustAnchor *secondAnchor = NULL;
+ PKIX_PL_Cert *firstCert = NULL;
+ PKIX_PL_Cert *secondCert = NULL;
+
+ PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_TRUSTANCHOR_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTTRUSTANCHOR);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_TRUSTANCHOR_TYPE) goto cleanup;
+
+ firstAnchor = (PKIX_TrustAnchor *)first;
+ secondAnchor = (PKIX_TrustAnchor *)second;
+
+ firstCert = firstAnchor->trustedCert;
+ secondCert = secondAnchor->trustedCert;
+
+ if ((firstCert && !secondCert) || (!firstCert && secondCert)){
+ goto cleanup;
+ }
+
+ if (firstCert && secondCert){
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstCert,
+ (PKIX_PL_Object *)secondCert,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstAnchor->caName,
+ (PKIX_PL_Object *)secondAnchor->caName,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstAnchor->caPubKey,
+ (PKIX_PL_Object *)secondAnchor->caPubKey,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_EQUALS
+ (firstAnchor->nameConstraints,
+ secondAnchor->nameConstraints,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/*
+ * FUNCTION: pkix_TrustAnchor_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_TrustAnchor_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 certHash = 0;
+ PKIX_UInt32 nameHash = 0;
+ PKIX_UInt32 pubKeyHash = 0;
+ PKIX_UInt32 ncHash = 0;
+
+ PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext),
+ PKIX_OBJECTNOTTRUSTANCHOR);
+
+ anchor = (PKIX_TrustAnchor*)object;
+ cert = anchor->trustedCert;
+
+ if (cert){
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)cert,
+ &certHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = certHash;
+
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)anchor->caName,
+ &nameHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)anchor->caPubKey,
+ &pubKeyHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE(anchor->nameConstraints, &ncHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = 31 * nameHash + pubKeyHash + ncHash;
+
+ }
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/*
+ * FUNCTION: pkix_TrustAnchor_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_TrustAnchor_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_TrustAnchor *anchor = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *anchorString = NULL;
+ PKIX_PL_String *certString = NULL;
+ PKIX_PL_String *nameString = NULL;
+ PKIX_PL_String *pubKeyString = NULL;
+ PKIX_PL_String *nameConstraintsString = NULL;
+
+ PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext),
+ PKIX_OBJECTNOTTRUSTANCHOR);
+
+ anchor = (PKIX_TrustAnchor*)object;
+
+ if (anchor->trustedCert){
+ asciiFormat =
+ "[\n"
+ "\tTrusted Cert: %s\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)anchor->trustedCert,
+ &certString,
+ plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&anchorString,
+ plContext,
+ formatString,
+ certString),
+ PKIX_SPRINTFFAILED);
+ } else {
+ asciiFormat =
+ "[\n"
+ "\tTrusted CA Name: %s\n"
+ "\tTrusted CA PublicKey: %s\n"
+ "\tInitial Name Constraints:%s\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)anchor->caName,
+ &nameString,
+ plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)anchor->caPubKey,
+ &pubKeyString,
+ plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (anchor->nameConstraints,
+ &nameConstraintsString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&anchorString,
+ plContext,
+ formatString,
+ nameString,
+ pubKeyString,
+ nameConstraintsString),
+ PKIX_SPRINTFFAILED);
+ }
+
+ *pString = anchorString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(certString);
+ PKIX_DECREF(nameString);
+ PKIX_DECREF(pubKeyString);
+ PKIX_DECREF(nameConstraintsString);
+
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/*
+ * FUNCTION: pkix_TrustAnchor_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_TRUSTANCHOR_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_TrustAnchor_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_RegisterSelf");
+
+ entry.description = "TrustAnchor";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_TrustAnchor);
+ entry.destructor = pkix_TrustAnchor_Destroy;
+ entry.equalsFunction = pkix_TrustAnchor_Equals;
+ entry.hashcodeFunction = pkix_TrustAnchor_Hashcode;
+ entry.toStringFunction = pkix_TrustAnchor_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_TRUSTANCHOR_TYPE] = entry;
+
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_CreateWithCert (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_TrustAnchor_CreateWithCert(
+ PKIX_PL_Cert *cert,
+ PKIX_TrustAnchor **pAnchor,
+ void *plContext)
+{
+ PKIX_TrustAnchor *anchor = NULL;
+
+ PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_CreateWithCert");
+ PKIX_NULLCHECK_TWO(cert, pAnchor);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_TRUSTANCHOR_TYPE,
+ sizeof (PKIX_TrustAnchor),
+ (PKIX_PL_Object **)&anchor,
+ plContext),
+ PKIX_COULDNOTCREATETRUSTANCHOROBJECT);
+
+ /* initialize fields */
+ PKIX_CHECK(
+ PKIX_PL_Cert_SetAsTrustAnchor(cert, plContext),
+ PKIX_CERTSETASTRUSTANCHORFAILED);
+
+ PKIX_INCREF(cert);
+ anchor->trustedCert = cert;
+
+ anchor->caName = NULL;
+ anchor->caPubKey = NULL;
+
+ PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
+ (anchor->trustedCert, &anchor->nameConstraints, plContext),
+ PKIX_CERTGETNAMECONSTRAINTSFAILED);
+
+
+ *pAnchor = anchor;
+ anchor = NULL;
+
+cleanup:
+
+ PKIX_DECREF(anchor);
+
+ PKIX_RETURN(TRUSTANCHOR);
+
+}
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_CreateWithNameKeyPair
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_TrustAnchor_CreateWithNameKeyPair(
+ PKIX_PL_X500Name *name,
+ PKIX_PL_PublicKey *pubKey,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_TrustAnchor **pAnchor,
+ void *plContext)
+{
+ PKIX_TrustAnchor *anchor = NULL;
+
+ PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_CreateWithNameKeyPair");
+
+#ifndef BUILD_LIBPKIX_TESTS
+ /* Nss creates trust anchors by using PKIX_TrustAnchor_CreateWithCert
+ * function as the complete trusted cert structure, and not only cert
+ * public key, is required for chain building and validation processes.
+ * Restricting this function for been used only in libpkix unit
+ * tests. */
+ PKIX_ERROR(PKIX_FUNCTIONMUSTNOTBEUSED);
+#endif
+
+ PKIX_NULLCHECK_THREE(name, pubKey, pAnchor);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_TRUSTANCHOR_TYPE,
+ sizeof (PKIX_TrustAnchor),
+ (PKIX_PL_Object **)&anchor,
+ plContext),
+ PKIX_COULDNOTCREATETRUSTANCHOROBJECT);
+
+ /* initialize fields */
+ anchor->trustedCert = NULL;
+
+ PKIX_INCREF(name);
+ anchor->caName = name;
+
+ PKIX_INCREF(pubKey);
+ anchor->caPubKey = pubKey;
+
+ PKIX_INCREF(nameConstraints);
+ anchor->nameConstraints = nameConstraints;
+
+ *pAnchor = anchor;
+ anchor = NULL;
+cleanup:
+
+ PKIX_DECREF(anchor);
+
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_GetTrustedCert (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_TrustAnchor_GetTrustedCert(
+ PKIX_TrustAnchor *anchor,
+ PKIX_PL_Cert **pCert,
+ void *plContext)
+{
+ PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetTrustedCert");
+ PKIX_NULLCHECK_TWO(anchor, pCert);
+
+ PKIX_INCREF(anchor->trustedCert);
+
+ *pCert = anchor->trustedCert;
+
+cleanup:
+ PKIX_RETURN(TRUSTANCHOR);
+
+}
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_GetCAName (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_TrustAnchor_GetCAName(
+ PKIX_TrustAnchor *anchor,
+ PKIX_PL_X500Name **pCAName,
+ void *plContext)
+{
+ PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetCAName");
+ PKIX_NULLCHECK_TWO(anchor, pCAName);
+
+ PKIX_INCREF(anchor->caName);
+
+ *pCAName = anchor->caName;
+
+cleanup:
+ PKIX_RETURN(TRUSTANCHOR);
+
+}
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_GetCAPublicKey (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_TrustAnchor_GetCAPublicKey(
+ PKIX_TrustAnchor *anchor,
+ PKIX_PL_PublicKey **pPubKey,
+ void *plContext)
+{
+ PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetCAPublicKey");
+ PKIX_NULLCHECK_TWO(anchor, pPubKey);
+
+ PKIX_INCREF(anchor->caPubKey);
+
+ *pPubKey = anchor->caPubKey;
+
+cleanup:
+ PKIX_RETURN(TRUSTANCHOR);
+}
+
+/*
+ * FUNCTION: PKIX_TrustAnchor_GetNameConstraints
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_TrustAnchor_GetNameConstraints(
+ PKIX_TrustAnchor *anchor,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext)
+{
+ PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetNameConstraints");
+ PKIX_NULLCHECK_TWO(anchor, pNameConstraints);
+
+ PKIX_INCREF(anchor->nameConstraints);
+
+ *pNameConstraints = anchor->nameConstraints;
+
+cleanup:
+ PKIX_RETURN(TRUSTANCHOR);
+}
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.h b/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.h
new file mode 100644
index 0000000000..e3ceb7fd33
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_trustanchor.h
@@ -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/. */
+/*
+ * pkix_trustanchor.h
+ *
+ * TrustAnchor Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_TRUSTANCHOR_H
+#define _PKIX_TRUSTANCHOR_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_TrustAnchorStruct {
+ PKIX_PL_Cert *trustedCert;
+ PKIX_PL_X500Name *caName;
+ PKIX_PL_PublicKey *caPubKey;
+ PKIX_PL_CertNameConstraints *nameConstraints;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_TrustAnchor_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_TRUSTANCHOR_H */
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_valparams.c b/security/nss/lib/libpkix/pkix/params/pkix_valparams.c
new file mode 100644
index 0000000000..83c3d2b08f
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_valparams.c
@@ -0,0 +1,335 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_valparams.c
+ *
+ * Validate Params Object Functions
+ *
+ */
+
+#include "pkix_valparams.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_ValidateParams_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateParams_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ValidateParams *params = NULL;
+
+ PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a validate params object */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATEPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTVALIDATEPARAMS);
+
+ params = (PKIX_ValidateParams *)object;
+
+ PKIX_DECREF(params->procParams);
+ PKIX_DECREF(params->chain);
+
+cleanup:
+
+ PKIX_RETURN(VALIDATEPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ValidateParams_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateParams_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_ValidateParams *firstValParams = NULL;
+ PKIX_ValidateParams *secondValParams = NULL;
+
+ PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_VALIDATEPARAMS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTVALIDATEPARAMS);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_VALIDATEPARAMS_TYPE) goto cleanup;
+
+ firstValParams = (PKIX_ValidateParams *)first;
+ secondValParams = (PKIX_ValidateParams *)second;
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstValParams->procParams,
+ (PKIX_PL_Object *)secondValParams->procParams,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstValParams->chain,
+ (PKIX_PL_Object *)secondValParams->chain,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(VALIDATEPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ValidateParams_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateParams_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 procParamsHash = 0;
+ PKIX_UInt32 chainHash = 0;
+
+ PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATEPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTVALIDATEPARAMS);
+
+ valParams = (PKIX_ValidateParams*)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)valParams->procParams,
+ &procParamsHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)valParams->chain,
+ &chainHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = 31 * procParamsHash + chainHash;
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(VALIDATEPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ValidateParams_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateParams_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_ValidateParams *valParams = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *valParamsString = NULL;
+
+ PKIX_PL_String *procParamsString = NULL;
+ PKIX_PL_String *chainString = NULL;
+
+ PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATEPARAMS_TYPE, plContext),
+ PKIX_OBJECTNOTVALIDATEPARAMS);
+
+ asciiFormat =
+ "[\n"
+ "\tProcessing Params: \n"
+ "\t********BEGIN PROCESSING PARAMS********\n"
+ "\t\t%s\n"
+ "\t********END PROCESSING PARAMS********\n"
+ "\tChain: \t\t%s\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ valParams = (PKIX_ValidateParams*)object;
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)valParams->procParams,
+ &procParamsString,
+ plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)valParams->chain,
+ &chainString,
+ plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&valParamsString,
+ plContext,
+ formatString,
+ procParamsString,
+ chainString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = valParamsString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(procParamsString);
+ PKIX_DECREF(chainString);
+
+ PKIX_RETURN(VALIDATEPARAMS);
+}
+
+/*
+ * FUNCTION: pkix_ValidateParams_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_VALIDATEPARAMS_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_ValidateParams_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(VALIDATEPARAMS, "pkix_ValidateParams_RegisterSelf");
+
+ entry.description = "ValidateParams";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_ValidateParams);
+ entry.destructor = pkix_ValidateParams_Destroy;
+ entry.equalsFunction = pkix_ValidateParams_Equals;
+ entry.hashcodeFunction = pkix_ValidateParams_Hashcode;
+ entry.toStringFunction = pkix_ValidateParams_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_VALIDATEPARAMS_TYPE] = entry;
+
+ PKIX_RETURN(VALIDATEPARAMS);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_ValidateParams_Create (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ValidateParams_Create(
+ PKIX_ProcessingParams *procParams,
+ PKIX_List *chain,
+ PKIX_ValidateParams **pParams,
+ void *plContext)
+{
+ PKIX_ValidateParams *params = NULL;
+
+ PKIX_ENTER(VALIDATEPARAMS, "PKIX_ValidateParams_Create");
+ PKIX_NULLCHECK_THREE(procParams, chain, pParams);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_VALIDATEPARAMS_TYPE,
+ sizeof (PKIX_ValidateParams),
+ (PKIX_PL_Object **)&params,
+ plContext),
+ PKIX_COULDNOTCREATEVALIDATEPARAMSOBJECT);
+
+ /* initialize fields */
+ PKIX_INCREF(procParams);
+ params->procParams = procParams;
+
+ PKIX_INCREF(chain);
+ params->chain = chain;
+
+ *pParams = params;
+ params = NULL;
+
+cleanup:
+
+ PKIX_DECREF(params);
+
+ PKIX_RETURN(VALIDATEPARAMS);
+
+}
+
+/*
+ * FUNCTION: PKIX_ValidateParams_GetProcessingParams
+ * (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ValidateParams_GetProcessingParams(
+ PKIX_ValidateParams *valParams,
+ PKIX_ProcessingParams **pProcParams,
+ void *plContext)
+{
+ PKIX_ENTER(VALIDATEPARAMS, "PKIX_ValidateParams_GetProcessingParams");
+ PKIX_NULLCHECK_TWO(valParams, pProcParams);
+
+ PKIX_INCREF(valParams->procParams);
+
+ *pProcParams = valParams->procParams;
+
+cleanup:
+ PKIX_RETURN(VALIDATEPARAMS);
+}
+
+/*
+ * FUNCTION: PKIX_ValidateParams_GetCertChain (see comments in pkix_params.h)
+ */
+PKIX_Error *
+PKIX_ValidateParams_GetCertChain(
+ PKIX_ValidateParams *valParams,
+ PKIX_List **pChain,
+ void *plContext)
+{
+ PKIX_ENTER(VALIDATEPARAMS, "PKIX_ValidateParams_GetCertChain");
+ PKIX_NULLCHECK_TWO(valParams, pChain);
+
+ PKIX_INCREF(valParams->chain);
+
+ *pChain = valParams->chain;
+
+cleanup:
+ PKIX_RETURN(VALIDATEPARAMS);
+}
diff --git a/security/nss/lib/libpkix/pkix/params/pkix_valparams.h b/security/nss/lib/libpkix/pkix/params/pkix_valparams.h
new file mode 100644
index 0000000000..93b754f712
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/params/pkix_valparams.h
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_valparams.h
+ *
+ * ValidateParams Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_VALIDATEPARAMS_H
+#define _PKIX_VALIDATEPARAMS_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_ValidateParamsStruct {
+ PKIX_ProcessingParams *procParams; /* Never NULL */
+ PKIX_List *chain; /* Never NULL */
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_ValidateParams_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_VALIDATEPARAMS_H */
diff --git a/security/nss/lib/libpkix/pkix/results/Makefile b/security/nss/lib/libpkix/pkix/results/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/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). #
+#######################################################################
+
+
+#######################################################################
+# (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/lib/libpkix/pkix/results/exports.gyp b/security/nss/lib/libpkix/pkix/results/exports.gyp
new file mode 100644
index 0000000000..dfff689033
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/exports.gyp
@@ -0,0 +1,28 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_libpkix_pkix_results_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_buildresult.h',
+ 'pkix_policynode.h',
+ 'pkix_valresult.h',
+ 'pkix_verifynode.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/results/manifest.mn b/security/nss/lib/libpkix/pkix/results/manifest.mn
new file mode 100644
index 0000000000..bec0270fb6
--- /dev/null
+++ b/security/nss/lib/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/.
+CORE_DEPTH = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_buildresult.h \
+ pkix_policynode.h \
+ pkix_valresult.h \
+ pkix_verifynode.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_buildresult.c \
+ pkix_policynode.c \
+ pkix_valresult.c \
+ pkix_verifynode.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixresults
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_buildresult.c b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.c
new file mode 100644
index 0000000000..7d35119bcb
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.c
@@ -0,0 +1,362 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_buildresult.c
+ *
+ * BuildResult Object Functions
+ *
+ */
+
+#include "pkix_buildresult.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_BuildResult_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_BuildResult_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_BuildResult *result = NULL;
+
+ PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a build result object */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BUILDRESULT_TYPE, plContext),
+ PKIX_OBJECTNOTBUILDRESULT);
+
+ result = (PKIX_BuildResult *)object;
+
+ PKIX_DECREF(result->valResult);
+ PKIX_DECREF(result->certChain);
+
+cleanup:
+
+ PKIX_RETURN(BUILDRESULT);
+}
+
+/*
+ * FUNCTION: pkix_BuildResult_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_BuildResult_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_BuildResult *firstBuildResult = NULL;
+ PKIX_BuildResult *secondBuildResult = NULL;
+
+ PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_BUILDRESULT_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTBUILDRESULT);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_BUILDRESULT_TYPE) goto cleanup;
+
+ firstBuildResult = (PKIX_BuildResult *)first;
+ secondBuildResult = (PKIX_BuildResult *)second;
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstBuildResult->valResult,
+ (PKIX_PL_Object *)secondBuildResult->valResult,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstBuildResult->certChain,
+ (PKIX_PL_Object *)secondBuildResult->certChain,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ /*
+ * The remaining case is that both are null,
+ * which we consider equality.
+ * cmpResult = PKIX_TRUE;
+ */
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(BUILDRESULT);
+}
+
+/*
+ * FUNCTION: pkix_BuildResult_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_BuildResult_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 valResultHash = 0;
+ PKIX_UInt32 certChainHash = 0;
+
+ PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BUILDRESULT_TYPE, plContext),
+ PKIX_OBJECTNOTBUILDRESULT);
+
+ buildResult = (PKIX_BuildResult*)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)buildResult->valResult,
+ &valResultHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)buildResult->certChain,
+ &certChainHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = 31*(31 * valResultHash + certChainHash);
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(BUILDRESULT);
+}
+
+/*
+ * FUNCTION: pkix_BuildResult_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_BuildResult_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *buildResultString = NULL;
+
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_List *certChain = NULL;
+
+ PKIX_PL_String *valResultString = NULL;
+ PKIX_PL_String *certChainString = NULL;
+
+ char *asciiFormat =
+ "[\n"
+ "\tValidateResult: \t\t%s"
+ "\tCertChain: \t\t%s\n"
+ "]\n";
+
+ PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BUILDRESULT_TYPE, plContext),
+ PKIX_OBJECTNOTBUILDRESULT);
+
+ buildResult = (PKIX_BuildResult*)object;
+
+ valResult = buildResult->valResult;
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)valResult, &valResultString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ certChain = buildResult->certChain;
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)certChain, &certChainString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&buildResultString,
+ plContext,
+ formatString,
+ valResultString,
+ certChainString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = buildResultString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(valResultString);
+ PKIX_DECREF(certChainString);
+
+ PKIX_RETURN(BUILDRESULT);
+}
+
+/*
+ * FUNCTION: pkix_BuildResult_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_BUILDRESULT_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_BuildResult_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_RegisterSelf");
+
+ entry.description = "BuildResult";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_BuildResult);
+ entry.destructor = pkix_BuildResult_Destroy;
+ entry.equalsFunction = pkix_BuildResult_Equals;
+ entry.hashcodeFunction = pkix_BuildResult_Hashcode;
+ entry.toStringFunction = pkix_BuildResult_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_BUILDRESULT_TYPE] = entry;
+
+ PKIX_RETURN(BUILDRESULT);
+}
+
+/*
+ * FUNCTION: pkix_BuildResult_Create
+ * DESCRIPTION:
+ *
+ * Creates a new BuildResult Object using the ValidateResult pointed to by
+ * "valResult" and the List pointed to by "certChain", and stores it at
+ * "pResult".
+ *
+ * PARAMETERS
+ * "valResult"
+ * Address of ValidateResult component. Must be non-NULL.
+ * "certChain
+ * Address of List component. Must be non-NULL.
+ * "pResult"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_BuildResult_Create(
+ PKIX_ValidateResult *valResult,
+ PKIX_List *certChain,
+ PKIX_BuildResult **pResult,
+ void *plContext)
+{
+ PKIX_BuildResult *result = NULL;
+
+ PKIX_ENTER(BUILDRESULT, "pkix_BuildResult_Create");
+ PKIX_NULLCHECK_THREE(valResult, certChain, pResult);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_BUILDRESULT_TYPE,
+ sizeof (PKIX_BuildResult),
+ (PKIX_PL_Object **)&result,
+ plContext),
+ PKIX_COULDNOTCREATEBUILDRESULTOBJECT);
+
+ /* initialize fields */
+
+ PKIX_INCREF(valResult);
+ result->valResult = valResult;
+
+ PKIX_INCREF(certChain);
+ result->certChain = certChain;
+
+ PKIX_CHECK(PKIX_List_SetImmutable(result->certChain, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pResult = result;
+ result = NULL;
+
+cleanup:
+
+ PKIX_DECREF(result);
+
+ PKIX_RETURN(BUILDRESULT);
+
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+
+/*
+ * FUNCTION: PKIX_BuildResult_GetValidateResult
+ * (see comments in pkix_result.h)
+ */
+PKIX_Error *
+PKIX_BuildResult_GetValidateResult(
+ PKIX_BuildResult *result,
+ PKIX_ValidateResult **pResult,
+ void *plContext)
+{
+ PKIX_ENTER(BUILDRESULT, "PKIX_BuildResult_GetValidateResult");
+ PKIX_NULLCHECK_TWO(result, pResult);
+
+ PKIX_INCREF(result->valResult);
+ *pResult = result->valResult;
+
+cleanup:
+ PKIX_RETURN(BUILDRESULT);
+}
+
+
+
+/*
+ * FUNCTION: PKIX_BuildResult_GetCertChain
+ * (see comments in pkix_result.h)
+ */
+PKIX_Error *
+PKIX_BuildResult_GetCertChain(
+ PKIX_BuildResult *result,
+ PKIX_List **pChain,
+ void *plContext)
+{
+ PKIX_ENTER(BUILDRESULT, "PKIX_BuildResult_GetCertChain");
+ PKIX_NULLCHECK_TWO(result, pChain);
+
+ PKIX_INCREF(result->certChain);
+ *pChain = result->certChain;
+
+cleanup:
+ PKIX_RETURN(BUILDRESULT);
+}
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_buildresult.h b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.h
new file mode 100644
index 0000000000..b43f12ba14
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_buildresult.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/. */
+/*
+ * pkix_buildresult.h
+ *
+ * BuildResult Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_BUILDRESULT_H
+#define _PKIX_BUILDRESULT_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_BuildResultStruct {
+ PKIX_ValidateResult *valResult;
+ PKIX_List *certChain;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_BuildResult_Create(
+ PKIX_ValidateResult *valResult,
+ PKIX_List *certChain,
+ PKIX_BuildResult **pResult,
+ void *plContext);
+
+PKIX_Error *pkix_BuildResult_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_BUILDRESULT_H */
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_policynode.c b/security/nss/lib/libpkix/pkix/results/pkix_policynode.c
new file mode 100644
index 0000000000..fd8cee982b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_policynode.c
@@ -0,0 +1,1377 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_policynode.c
+ *
+ * Policy Node Object Type Definition
+ *
+ */
+
+#include "pkix_policynode.h"
+
+/* --Private-PolicyNode-Functions---------------------------------- */
+
+/*
+ * FUNCTION: pkix_PolicyNode_GetChildrenMutable
+ * DESCRIPTION:
+ *
+ * Retrieves the List of PolicyNodes representing the child nodes of the
+ * Policy Node pointed to by "node" and stores it at "pChildren". If "node"
+ * has no List of child nodes, this function stores NULL at "pChildren".
+ *
+ * Note that the List returned by this function may be mutable. This function
+ * differs from the public function PKIX_PolicyNode_GetChildren in that
+ * respect. (It also differs in that the public function creates an empty
+ * List, if necessary, rather than storing NULL.)
+ *
+ * During certificate processing, children Lists are created and modified.
+ * Once the list is accessed using the public call, the List is set immutable.
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of PolicyNode whose child nodes are to be stored.
+ * Must be non-NULL.
+ * "pChildren"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a PolicyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_PolicyNode_GetChildrenMutable(
+ PKIX_PolicyNode *node,
+ PKIX_List **pChildren, /* list of PKIX_PolicyNode */
+ void *plContext)
+{
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_GetChildrenMutable");
+
+ PKIX_NULLCHECK_TWO(node, pChildren);
+
+ PKIX_INCREF(node->children);
+
+ *pChildren = node->children;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_Create
+ * DESCRIPTION:
+ *
+ * Creates a new PolicyNode using the OID pointed to by "validPolicy", the List
+ * of CertPolicyQualifiers pointed to by "qualifierSet", the criticality
+ * indicated by the Boolean value of "criticality", and the List of OIDs
+ * pointed to by "expectedPolicySet", and stores the result at "pObject". The
+ * criticality should be derived from whether the certificate policy extension
+ * was marked as critical in the certificate that led to creation of this
+ * PolicyNode. The "qualifierSet" and "expectedPolicySet" Lists are made
+ * immutable. The PolicyNode pointers to parent and to children are initialized
+ * to NULL, and the depth is set to zero; those values should be set by using
+ * the pkix_PolicyNode_AddToParent function.
+ *
+ * PARAMETERS
+ * "validPolicy"
+ * Address of OID of the valid policy for the path. Must be non-NULL
+ * "qualifierSet"
+ * Address of List of CertPolicyQualifiers associated with the validpolicy.
+ * May be NULL
+ * "criticality"
+ * Boolean indicator of whether the criticality should be set in this
+ * PolicyNode
+ * "expectedPolicySet"
+ * Address of List of OIDs that would satisfy this policy in the next
+ * certificate. Must be non-NULL
+ * "pObject"
+ * Address where the PolicyNode pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a PolicyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_PolicyNode_Create(
+ PKIX_PL_OID *validPolicy,
+ PKIX_List *qualifierSet,
+ PKIX_Boolean criticality,
+ PKIX_List *expectedPolicySet,
+ PKIX_PolicyNode **pObject,
+ void *plContext)
+{
+ PKIX_PolicyNode *node = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Create");
+
+ PKIX_NULLCHECK_THREE(validPolicy, expectedPolicySet, pObject);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTPOLICYNODE_TYPE,
+ sizeof (PKIX_PolicyNode),
+ (PKIX_PL_Object **)&node,
+ plContext),
+ PKIX_COULDNOTCREATEPOLICYNODEOBJECT);
+
+ PKIX_INCREF(validPolicy);
+ node->validPolicy = validPolicy;
+
+ PKIX_INCREF(qualifierSet);
+ node->qualifierSet = qualifierSet;
+ if (qualifierSet) {
+ PKIX_CHECK(PKIX_List_SetImmutable(qualifierSet, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+ }
+
+ node->criticality = criticality;
+
+ PKIX_INCREF(expectedPolicySet);
+ node->expectedPolicySet = expectedPolicySet;
+ PKIX_CHECK(PKIX_List_SetImmutable(expectedPolicySet, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ node->parent = NULL;
+ node->children = NULL;
+ node->depth = 0;
+
+ *pObject = node;
+ node = NULL;
+
+cleanup:
+
+ PKIX_DECREF(node);
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_AddToParent
+ * DESCRIPTION:
+ *
+ * Adds the PolicyNode pointed to by "child" to the List of children of
+ * the PolicyNode pointed to by "parentNode". If "parentNode" had a
+ * NULL pointer for the List of children, a new List is created containing
+ * "child". Otherwise "child" is appended to the existing List. The
+ * parent field in "child" is set to "parent", and the depth field is
+ * set to one more than the corresponding value in "parent".
+ *
+ * Depth, in this context, means distance from the root node, which
+ * is at depth zero.
+ *
+ * PARAMETERS:
+ * "parentNode"
+ * Address of PolicyNode whose List of child PolicyNodes is to be
+ * created or appended to. Must be non-NULL.
+ * "child"
+ * Address of PolicyNode to be added to parentNode's List. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a PolicyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_PolicyNode_AddToParent(
+ PKIX_PolicyNode *parentNode,
+ PKIX_PolicyNode *child,
+ void *plContext)
+{
+ PKIX_List *listOfChildren = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_AddToParent");
+
+ PKIX_NULLCHECK_TWO(parentNode, child);
+
+ listOfChildren = parentNode->children;
+ if (listOfChildren == NULL) {
+ PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext),
+ PKIX_LISTCREATEFAILED);
+ parentNode->children = listOfChildren;
+ }
+
+ /*
+ * Note: this link is not reference-counted. The link from parent
+ * to child is counted (actually, the parent "owns" a List which
+ * "owns" children), but the children do not "own" the parent.
+ * Otherwise, there would be loops.
+ */
+ child->parent = parentNode;
+
+ child->depth = 1 + (parentNode->depth);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (listOfChildren, (PKIX_PL_Object *)child, plContext),
+ PKIX_COULDNOTAPPENDCHILDTOPARENTSPOLICYNODELIST);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)parentNode, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)child, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_Prune
+ * DESCRIPTION:
+ *
+ * Prunes a tree below the PolicyNode whose address is pointed to by "node",
+ * using the UInt32 value of "height" as the distance from the leaf level,
+ * and storing at "pDelete" the Boolean value of whether this PolicyNode is,
+ * after pruning, childless and should be pruned.
+ *
+ * Any PolicyNode at height 0 is allowed to survive. If the height is greater
+ * than zero, pkix_PolicyNode_Prune is called recursively for each child of
+ * the current PolicyNode. After this process, a node with no children
+ * stores PKIX_TRUE in "pDelete" to indicate that it should be deleted.
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of the PolicyNode to be pruned. Must be non-NULL.
+ * "height"
+ * UInt32 value for the distance from the leaf level
+ * "pDelete"
+ * Address to store the Boolean return value of PKIX_TRUE if this node
+ * should be pruned, or PKIX_FALSE if there remains at least one
+ * branch of the required height. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a PolicyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_PolicyNode_Prune(
+ PKIX_PolicyNode *node,
+ PKIX_UInt32 height,
+ PKIX_Boolean *pDelete,
+ void *plContext)
+{
+ PKIX_Boolean childless = PKIX_FALSE;
+ PKIX_Boolean shouldBePruned = PKIX_FALSE;
+ PKIX_UInt32 listSize = 0;
+ PKIX_UInt32 listIndex = 0;
+ PKIX_PolicyNode *candidate = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Prune");
+
+ PKIX_NULLCHECK_TWO(node, pDelete);
+
+ /* Don't prune at the leaf */
+ if (height == 0) {
+ goto cleanup;
+ }
+
+ /* Above the bottom level, childless nodes get pruned */
+ if (!(node->children)) {
+ childless = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * This node has children. If they are leaf nodes,
+ * we know they will live. Otherwise, check them out.
+ */
+ if (height > 1) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (node->children, &listSize, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ /*
+ * By working backwards from the end of the list,
+ * we avoid having to worry about possible
+ * decreases in the size of the list, as we
+ * delete items. The only nuisance is that since the
+ * index is UInt32, we can't check for it to reach -1;
+ * we have to use the 1-based index, rather than the
+ * 0-based index that PKIX_List functions require.
+ */
+ for (listIndex = listSize; listIndex > 0; listIndex--) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (node->children,
+ (listIndex - 1),
+ (PKIX_PL_Object **)&candidate,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyNode_Prune
+ (candidate,
+ height - 1,
+ &shouldBePruned,
+ plContext),
+ PKIX_POLICYNODEPRUNEFAILED);
+
+ if (shouldBePruned == PKIX_TRUE) {
+ PKIX_CHECK(PKIX_List_DeleteItem
+ (node->children,
+ (listIndex - 1),
+ plContext),
+ PKIX_LISTDELETEITEMFAILED);
+ }
+
+ PKIX_DECREF(candidate);
+ }
+ }
+
+ /* Prune if this node has *become* childless */
+ PKIX_CHECK(PKIX_List_GetLength
+ (node->children, &listSize, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ if (listSize == 0) {
+ childless = PKIX_TRUE;
+ }
+
+ /*
+ * Even if we did not change this node, or any of its children,
+ * maybe a [great-]*grandchild was pruned.
+ */
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)node, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+ *pDelete = childless;
+
+ PKIX_DECREF(candidate);
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_SinglePolicyNode_ToString
+ * DESCRIPTION:
+ *
+ * Creates a String representation of the attributes of the PolicyNode
+ * pointed to by "node", other than its parents or children, and
+ * stores the result at "pString".
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of PolicyNode to be described by the string. Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a PolicyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+PKIX_Error *
+pkix_SinglePolicyNode_ToString(
+ PKIX_PolicyNode *node,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *fmtString = NULL;
+ PKIX_PL_String *validString = NULL;
+ PKIX_PL_String *qualifierString = NULL;
+ PKIX_PL_String *criticalityString = NULL;
+ PKIX_PL_String *expectedString = NULL;
+ PKIX_PL_String *outString = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_ToString");
+ PKIX_NULLCHECK_TWO(node, pString);
+ PKIX_NULLCHECK_TWO(node->validPolicy, node->expectedPolicySet);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "{%s,%s,%s,%s,%d}",
+ 0,
+ &fmtString,
+ plContext),
+ PKIX_CANTCREATESTRING);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)(node->validPolicy),
+ &validString,
+ plContext),
+ PKIX_OIDTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)(node->expectedPolicySet),
+ &expectedString,
+ plContext),
+ PKIX_LISTTOSTRINGFAILED);
+
+ if (node->qualifierSet) {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)(node->qualifierSet),
+ &qualifierString,
+ plContext),
+ PKIX_LISTTOSTRINGFAILED);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "{}",
+ 0,
+ &qualifierString,
+ plContext),
+ PKIX_CANTCREATESTRING);
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (node->criticality)?"Critical":"Not Critical",
+ 0,
+ &criticalityString,
+ plContext),
+ PKIX_CANTCREATESTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString,
+ plContext,
+ fmtString,
+ validString,
+ qualifierString,
+ criticalityString,
+ expectedString,
+ node->depth),
+ PKIX_SPRINTFFAILED);
+
+ *pString = outString;
+
+cleanup:
+
+ PKIX_DECREF(fmtString);
+ PKIX_DECREF(validString);
+ PKIX_DECREF(qualifierString);
+ PKIX_DECREF(criticalityString);
+ PKIX_DECREF(expectedString);
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Produces a String representation of a PolicyNode tree below the PolicyNode
+ * pointed to by "rootNode", with each line of output prefixed by the String
+ * pointed to by "indent", and stores the result at "pTreeString". It is
+ * called recursively, with ever-increasing indentation, for successively
+ * lower nodes on the tree.
+ *
+ * PARAMETERS:
+ * "rootNode"
+ * Address of PolicyNode subtree. Must be non-NULL.
+ * "indent"
+ * Address of String to be prefixed to each line of output. May be NULL
+ * if no indentation is desired
+ * "pTreeString"
+ * Address where the resulting String will be stored; must be non-NULL
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a PolicyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_PolicyNode_ToString_Helper(
+ PKIX_PolicyNode *rootNode,
+ PKIX_PL_String *indent,
+ PKIX_PL_String **pTreeString,
+ void *plContext)
+{
+ PKIX_PL_String *nextIndentFormat = NULL;
+ PKIX_PL_String *thisNodeFormat = NULL;
+ PKIX_PL_String *childrenFormat = NULL;
+ PKIX_PL_String *nextIndentString = NULL;
+ PKIX_PL_String *resultString = NULL;
+ PKIX_PL_String *thisItemString = NULL;
+ PKIX_PL_String *childString = NULL;
+ PKIX_PolicyNode *childNode = NULL;
+ PKIX_UInt32 numberOfChildren = 0;
+ PKIX_UInt32 childIndex = 0;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_ToString_Helper");
+
+ PKIX_NULLCHECK_TWO(rootNode, pTreeString);
+
+ /* Create a string for this node */
+ PKIX_CHECK(pkix_SinglePolicyNode_ToString
+ (rootNode, &thisItemString, plContext),
+ PKIX_ERRORINSINGLEPOLICYNODETOSTRING);
+
+ if (indent) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s%s",
+ 0,
+ &thisNodeFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ thisNodeFormat,
+ indent,
+ thisItemString),
+ PKIX_ERRORINSPRINTF);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s",
+ 0,
+ &thisNodeFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ thisNodeFormat,
+ thisItemString),
+ PKIX_ERRORINSPRINTF);
+ }
+
+ PKIX_DECREF(thisItemString);
+ thisItemString = resultString;
+
+ /* if no children, we are done */
+ if (rootNode->children) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (rootNode->children, &numberOfChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ if (numberOfChildren != 0) {
+ /*
+ * We create a string for each child in turn,
+ * concatenating them to thisItemString.
+ */
+
+ /* Prepare an indent string for each child */
+ if (indent) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s. ",
+ 0,
+ &nextIndentFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&nextIndentString,
+ plContext,
+ nextIndentFormat,
+ indent),
+ PKIX_ERRORINSPRINTF);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ ". ",
+ 0,
+ &nextIndentString,
+ plContext),
+ PKIX_ERRORCREATINGINDENTSTRING);
+ }
+
+ /* Prepare the format for concatenation. */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s\n%s",
+ 0,
+ &childrenFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ for (childIndex = 0;
+ childIndex < numberOfChildren;
+ childIndex++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (rootNode->children,
+ childIndex,
+ (PKIX_PL_Object **)&childNode,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyNode_ToString_Helper
+ (childNode,
+ nextIndentString,
+ &childString,
+ plContext),
+ PKIX_ERRORCREATINGCHILDSTRING);
+
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ childrenFormat,
+ thisItemString,
+ childString),
+ PKIX_ERRORINSPRINTF);
+
+ PKIX_DECREF(childNode);
+ PKIX_DECREF(childString);
+ PKIX_DECREF(thisItemString);
+
+ thisItemString = resultString;
+ }
+ }
+
+ *pTreeString = thisItemString;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(thisItemString);
+ }
+
+ PKIX_DECREF(nextIndentFormat);
+ PKIX_DECREF(thisNodeFormat);
+ PKIX_DECREF(childrenFormat);
+ PKIX_DECREF(nextIndentString);
+ PKIX_DECREF(childString);
+ PKIX_DECREF(childNode);
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyNode_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pTreeString,
+ void *plContext)
+{
+ PKIX_PolicyNode *rootNode = NULL;
+ PKIX_PL_String *resultString = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_ToString");
+
+ PKIX_NULLCHECK_TWO(object, pTreeString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTPOLICYNODE);
+
+ rootNode = (PKIX_PolicyNode *)object;
+
+ PKIX_CHECK(pkix_PolicyNode_ToString_Helper
+ (rootNode, NULL, &resultString, plContext),
+ PKIX_ERRORCREATINGSUBTREESTRING);
+
+ *pTreeString = resultString;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyNode_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PolicyNode *node = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTPOLICYNODE);
+
+ node = (PKIX_PolicyNode*)object;
+
+ node->criticality = PKIX_FALSE;
+ PKIX_DECREF(node->validPolicy);
+ PKIX_DECREF(node->qualifierSet);
+ PKIX_DECREF(node->expectedPolicySet);
+ PKIX_DECREF(node->children);
+
+ /*
+ * Note: the link to parent is not reference-counted. See comment
+ * in pkix_PolicyNode_AddToParent for more details.
+ */
+ node->parent = NULL;
+ node->depth = 0;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_SinglePolicyNode_Hashcode
+ * DESCRIPTION:
+ *
+ * Computes the hashcode of the attributes of the PolicyNode pointed to by
+ * "node", other than its parents and children, and stores the result at
+ * "pHashcode".
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of PolicyNode to be hashcoded; must be non-NULL
+ * "pHashcode"
+ * Address where UInt32 result will be stored; must be non-NULL
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a PolicyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+static PKIX_Error *
+pkix_SinglePolicyNode_Hashcode(
+ PKIX_PolicyNode *node,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_UInt32 componentHash = 0;
+ PKIX_UInt32 nodeHash = 0;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_Hashcode");
+ PKIX_NULLCHECK_TWO(node, pHashcode);
+ PKIX_NULLCHECK_TWO(node->validPolicy, node->expectedPolicySet);
+
+ PKIX_HASHCODE
+ (node->qualifierSet,
+ &nodeHash,
+ plContext,
+ PKIX_FAILUREHASHINGLISTQUALIFIERSET);
+
+ if (PKIX_TRUE == (node->criticality)) {
+ nodeHash = 31*nodeHash + 0xff;
+ } else {
+ nodeHash = 31*nodeHash + 0x00;
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)node->validPolicy,
+ &componentHash,
+ plContext),
+ PKIX_FAILUREHASHINGOIDVALIDPOLICY);
+
+ nodeHash = 31*nodeHash + componentHash;
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)node->expectedPolicySet,
+ &componentHash,
+ plContext),
+ PKIX_FAILUREHASHINGLISTEXPECTEDPOLICYSET);
+
+ nodeHash = 31*nodeHash + componentHash;
+
+ *pHashcode = nodeHash;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyNode_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PolicyNode *node = NULL;
+ PKIX_UInt32 childrenHash = 0;
+ PKIX_UInt32 nodeHash = 0;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTPOLICYNODE);
+
+ node = (PKIX_PolicyNode *)object;
+
+ PKIX_CHECK(pkix_SinglePolicyNode_Hashcode
+ (node, &nodeHash, plContext),
+ PKIX_SINGLEPOLICYNODEHASHCODEFAILED);
+
+ nodeHash = 31*nodeHash + (PKIX_UInt32)((char *)node->parent - (char *)NULL);
+
+ PKIX_HASHCODE
+ (node->children,
+ &childrenHash,
+ plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ nodeHash = 31*nodeHash + childrenHash;
+
+ *pHashcode = nodeHash;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_SinglePolicyNode_Equals
+ * DESCRIPTION:
+ *
+ * Compares for equality the components of the PolicyNode pointed to by
+ * "firstPN", other than its parents and children, with those of the
+ * PolicyNode pointed to by "secondPN" and stores the result at "pResult"
+ * (PKIX_TRUE if equal; PKIX_FALSE if not).
+ *
+ * PARAMETERS:
+ * "firstPN"
+ * Address of first of the PolicyNodes to be compared; must be non-NULL
+ * "secondPN"
+ * Address of second of the PolicyNodes to be compared; must be non-NULL
+ * "pResult"
+ * Address where Boolean will be stored; must be non-NULL
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a PolicyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+static PKIX_Error *
+pkix_SinglePolicyNode_Equals(
+ PKIX_PolicyNode *firstPN,
+ PKIX_PolicyNode *secondPN,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_Boolean compResult = PKIX_FALSE;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_SinglePolicyNode_Equals");
+ PKIX_NULLCHECK_THREE(firstPN, secondPN, pResult);
+
+ /* If both references are identical, they must be equal */
+ if (firstPN == secondPN) {
+ compResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * It seems we have to do the comparisons. Do
+ * the easiest ones first.
+ */
+ if ((firstPN->criticality) != (secondPN->criticality)) {
+ goto cleanup;
+ }
+ if ((firstPN->depth) != (secondPN->depth)) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS
+ (firstPN->qualifierSet,
+ secondPN->qualifierSet,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (compResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ /* These fields must be non-NULL */
+ PKIX_NULLCHECK_TWO(firstPN->validPolicy, secondPN->validPolicy);
+
+ PKIX_EQUALS
+ (firstPN->validPolicy,
+ secondPN->validPolicy,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (compResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ /* These fields must be non-NULL */
+ PKIX_NULLCHECK_TWO
+ (firstPN->expectedPolicySet, secondPN->expectedPolicySet);
+
+ PKIX_EQUALS
+ (firstPN->expectedPolicySet,
+ secondPN->expectedPolicySet,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILEDONEXPECTEDPOLICYSETS);
+
+cleanup:
+
+ *pResult = compResult;
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyNode_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PolicyNode *firstPN = NULL;
+ PKIX_PolicyNode *secondPN = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean compResult = PKIX_FALSE;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a PolicyNode */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CERTPOLICYNODE_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTPOLICYNODE);
+
+ /*
+ * Since we know firstObject is a PolicyNode,
+ * if both references are identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ compResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a PolicyNode, we
+ * don't throw an error. We simply return FALSE.
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ if (secondType != PKIX_CERTPOLICYNODE_TYPE) {
+ goto cleanup;
+ }
+
+ /*
+ * Oh, well, we have to do the comparisons. Do
+ * the easiest ones first.
+ */
+ firstPN = (PKIX_PolicyNode *)firstObject;
+ secondPN = (PKIX_PolicyNode *)secondObject;
+
+ /*
+ * We don't require the parents to be identical. In the
+ * course of traversing the tree, we will have checked the
+ * attributes of the parent nodes, and checking the lists
+ * of children will determine whether they match.
+ */
+
+ PKIX_EQUALS
+ (firstPN->children,
+ secondPN->children,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILEDONCHILDREN);
+
+ if (compResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_SinglePolicyNode_Equals
+ (firstPN, secondPN, &compResult, plContext),
+ PKIX_SINGLEPOLICYNODEEQUALSFAILED);
+
+cleanup:
+
+ *pResult = compResult;
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_DuplicateHelper
+ * DESCRIPTION:
+ *
+ * Duplicates the PolicyNode whose address is pointed to by "original",
+ * and stores the result at "pNewNode", if a non-NULL pointer is provided
+ * for "pNewNode". In addition, the created PolicyNode is added as a child
+ * to "parent", if a non-NULL pointer is provided for "parent". Then this
+ * function is called recursively to duplicate each of the children of
+ * "original". At the top level this function is called with a null
+ * "parent" and a non-NULL "pNewNode". Below the top level "parent" will
+ * be non-NULL and "pNewNode" will be NULL.
+ *
+ * PARAMETERS:
+ * "original"
+ * Address of PolicyNode to be copied; must be non-NULL
+ * "parent"
+ * Address of PolicyNode to which the created node is to be added as a
+ * child; NULL for the top-level call and non-NULL below the top level
+ * "pNewNode"
+ * Address to store the node created; should be NULL if "parent" is
+ * non-NULL and vice versa
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a PolicyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+static PKIX_Error *
+pkix_PolicyNode_DuplicateHelper(
+ PKIX_PolicyNode *original,
+ PKIX_PolicyNode *parent,
+ PKIX_PolicyNode **pNewNode,
+ void *plContext)
+{
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 childIndex = 0;
+ PKIX_List *children = NULL; /* List of PKIX_PolicyNode */
+ PKIX_PolicyNode *copy = NULL;
+ PKIX_PolicyNode *child = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_DuplicateHelper");
+
+ PKIX_NULLCHECK_THREE
+ (original, original->validPolicy, original->expectedPolicySet);
+
+ /*
+ * These components are immutable, so copying the pointers
+ * is sufficient. The create function increments the reference
+ * counts as it stores the pointers into the new object.
+ */
+ PKIX_CHECK(pkix_PolicyNode_Create
+ (original->validPolicy,
+ original->qualifierSet,
+ original->criticality,
+ original->expectedPolicySet,
+ &copy,
+ plContext),
+ PKIX_POLICYNODECREATEFAILED);
+
+ if (parent) {
+ PKIX_CHECK(pkix_PolicyNode_AddToParent(parent, copy, plContext),
+ PKIX_POLICYNODEADDTOPARENTFAILED);
+ }
+
+ /* Are there any children to duplicate? */
+ children = original->children;
+
+ if (children) {
+ PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ for (childIndex = 0; childIndex < numChildren; childIndex++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (children,
+ childIndex,
+ (PKIX_PL_Object **)&child,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_PolicyNode_DuplicateHelper
+ (child, copy, NULL, plContext),
+ PKIX_POLICYNODEDUPLICATEHELPERFAILED);
+
+ PKIX_DECREF(child);
+ }
+
+ if (pNewNode) {
+ *pNewNode = copy;
+ copy = NULL; /* no DecRef if we give our handle away */
+ }
+
+cleanup:
+ PKIX_DECREF(copy);
+ PKIX_DECREF(child);
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_Duplicate
+ * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_PolicyNode_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_PolicyNode *original = NULL;
+ PKIX_PolicyNode *copy = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_Duplicate");
+
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTPOLICYNODE);
+
+ original = (PKIX_PolicyNode *)object;
+
+ PKIX_CHECK(pkix_PolicyNode_DuplicateHelper
+ (original, NULL, &copy, plContext),
+ PKIX_POLICYNODEDUPLICATEHELPERFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)copy;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: pkix_PolicyNode_RegisterSelf
+ * DESCRIPTION:
+ *
+ * Registers PKIX_CERTPOLICYNODE_TYPE and its related
+ * functions with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize,
+ * which should only be called once, it is acceptable that
+ * this function is not thread-safe.
+ */
+PKIX_Error *
+pkix_PolicyNode_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTPOLICYNODE, "pkix_PolicyNode_RegisterSelf");
+
+ entry.description = "PolicyNode";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PolicyNode);
+ entry.destructor = pkix_PolicyNode_Destroy;
+ entry.equalsFunction = pkix_PolicyNode_Equals;
+ entry.hashcodeFunction = pkix_PolicyNode_Hashcode;
+ entry.toStringFunction = pkix_PolicyNode_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_PolicyNode_Duplicate;
+
+ systemClasses[PKIX_CERTPOLICYNODE_TYPE] = entry;
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+
+/* --Public-PolicyNode-Functions----------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetChildren
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetChildren(
+ PKIX_PolicyNode *node,
+ PKIX_List **pChildren, /* list of PKIX_PolicyNode */
+ void *plContext)
+{
+ PKIX_List *children = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetChildren");
+
+ PKIX_NULLCHECK_TWO(node, pChildren);
+
+ PKIX_INCREF(node->children);
+ children = node->children;
+
+ if (!children) {
+ PKIX_CHECK(PKIX_List_Create(&children, plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(children, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pChildren = children;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(children);
+ }
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetParent
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetParent(
+ PKIX_PolicyNode *node,
+ PKIX_PolicyNode **pParent,
+ void *plContext)
+{
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetParent");
+
+ PKIX_NULLCHECK_TWO(node, pParent);
+
+ PKIX_INCREF(node->parent);
+ *pParent = node->parent;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetValidPolicy
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetValidPolicy(
+ PKIX_PolicyNode *node,
+ PKIX_PL_OID **pValidPolicy,
+ void *plContext)
+{
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetValidPolicy");
+
+ PKIX_NULLCHECK_TWO(node, pValidPolicy);
+
+ PKIX_INCREF(node->validPolicy);
+ *pValidPolicy = node->validPolicy;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetPolicyQualifiers
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetPolicyQualifiers(
+ PKIX_PolicyNode *node,
+ PKIX_List **pQualifiers, /* list of PKIX_PL_CertPolicyQualifier */
+ void *plContext)
+{
+ PKIX_List *qualifiers = NULL;
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetPolicyQualifiers");
+
+ PKIX_NULLCHECK_TWO(node, pQualifiers);
+
+ PKIX_INCREF(node->qualifierSet);
+ qualifiers = node->qualifierSet;
+
+ if (!qualifiers) {
+ PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(qualifiers, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pQualifiers = qualifiers;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetExpectedPolicies
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetExpectedPolicies(
+ PKIX_PolicyNode *node,
+ PKIX_List **pExpPolicies, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetExpectedPolicies");
+
+ PKIX_NULLCHECK_TWO(node, pExpPolicies);
+
+ PKIX_INCREF(node->expectedPolicySet);
+ *pExpPolicies = node->expectedPolicySet;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_PolicyNode_IsCritical
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_IsCritical(
+ PKIX_PolicyNode *node,
+ PKIX_Boolean *pCritical,
+ void *plContext)
+{
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_IsCritical");
+
+ PKIX_NULLCHECK_TWO(node, pCritical);
+
+ *pCritical = node->criticality;
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_PolicyNode_GetDepth
+ * (see description of this function in pkix_results.h)
+ */
+PKIX_Error *
+PKIX_PolicyNode_GetDepth(
+ PKIX_PolicyNode *node,
+ PKIX_UInt32 *pDepth,
+ void *plContext)
+{
+
+ PKIX_ENTER(CERTPOLICYNODE, "PKIX_PolicyNode_GetDepth");
+
+ PKIX_NULLCHECK_TWO(node, pDepth);
+
+ *pDepth = node->depth;
+
+ PKIX_RETURN(CERTPOLICYNODE);
+}
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_policynode.h b/security/nss/lib/libpkix/pkix/results/pkix_policynode.h
new file mode 100644
index 0000000000..799b7a60aa
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_policynode.h
@@ -0,0 +1,74 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_policynode.h
+ *
+ * PolicyNode Type Definitions
+ *
+ */
+
+#ifndef _PKIX_POLICYNODE_H
+#define _PKIX_POLICYNODE_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This structure reflects the contents of a policy node...
+ */
+struct PKIX_PolicyNodeStruct {
+ PKIX_PL_OID *validPolicy;
+ PKIX_List *qualifierSet; /* CertPolicyQualifiers */
+ PKIX_Boolean criticality;
+ PKIX_List *expectedPolicySet; /* OIDs */
+ PKIX_PolicyNode *parent;
+ PKIX_List *children; /* PolicyNodes */
+ PKIX_UInt32 depth;
+};
+
+PKIX_Error *
+pkix_SinglePolicyNode_ToString(
+ PKIX_PolicyNode *node,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+PKIX_Error *
+pkix_PolicyNode_GetChildrenMutable(
+ PKIX_PolicyNode *node,
+ PKIX_List **pChildren, /* PolicyNodes */
+ void *plContext);
+
+PKIX_Error *
+pkix_PolicyNode_Create(
+ PKIX_PL_OID *validPolicy,
+ PKIX_List *qualifierSet, /* CertPolicyQualifiers */
+ PKIX_Boolean criticality,
+ PKIX_List *expectedPolicySet, /* OIDs */
+ PKIX_PolicyNode **pObject,
+ void *plContext);
+
+PKIX_Error *
+pkix_PolicyNode_AddToParent(
+ PKIX_PolicyNode *parentNode,
+ PKIX_PolicyNode *child,
+ void *plContext);
+
+PKIX_Error *
+pkix_PolicyNode_Prune(
+ PKIX_PolicyNode *node,
+ PKIX_UInt32 depth,
+ PKIX_Boolean *pDelete,
+ void *plContext);
+
+PKIX_Error *
+pkix_PolicyNode_RegisterSelf(
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_POLICYNODE_H */
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_valresult.c b/security/nss/lib/libpkix/pkix/results/pkix_valresult.c
new file mode 100644
index 0000000000..25b69e59c3
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_valresult.c
@@ -0,0 +1,442 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_valresult.c
+ *
+ * ValidateResult Object Functions
+ *
+ */
+
+#include "pkix_valresult.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_ValidateResult_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateResult_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ValidateResult *result = NULL;
+
+ PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a validate result object */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATERESULT_TYPE, plContext),
+ PKIX_OBJECTNOTVALIDATERESULT);
+
+ result = (PKIX_ValidateResult *)object;
+
+ PKIX_DECREF(result->anchor);
+ PKIX_DECREF(result->pubKey);
+ PKIX_DECREF(result->policyTree);
+
+cleanup:
+
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: pkix_ValidateResult_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateResult_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_ValidateResult *firstValResult = NULL;
+ PKIX_ValidateResult *secondValResult = NULL;
+ PKIX_TrustAnchor *firstAnchor = NULL;
+ PKIX_TrustAnchor *secondAnchor = NULL;
+ PKIX_PolicyNode *firstTree = NULL;
+ PKIX_PolicyNode *secondTree = NULL;
+
+ PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_VALIDATERESULT_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTVALIDATERESULT);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_VALIDATERESULT_TYPE) goto cleanup;
+
+ firstValResult = (PKIX_ValidateResult *)first;
+ secondValResult = (PKIX_ValidateResult *)second;
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstValResult->pubKey,
+ (PKIX_PL_Object *)secondValResult->pubKey,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (!cmpResult) goto cleanup;
+
+ firstAnchor = firstValResult->anchor;
+ secondAnchor = secondValResult->anchor;
+
+ if ((firstAnchor != NULL) && (secondAnchor != NULL)) {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstAnchor,
+ (PKIX_PL_Object *)secondAnchor,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+ } else {
+ cmpResult = (firstAnchor == secondAnchor);
+ }
+
+ if (!cmpResult) goto cleanup;
+
+ firstTree = firstValResult->policyTree;
+ secondTree = secondValResult->policyTree;
+
+ if ((firstTree != NULL) && (secondTree != NULL)) {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstTree,
+ (PKIX_PL_Object *)secondTree,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+ } else {
+ cmpResult = (firstTree == secondTree);
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: pkix_ValidateResult_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateResult_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 pubKeyHash = 0;
+ PKIX_UInt32 anchorHash = 0;
+ PKIX_UInt32 policyTreeHash = 0;
+
+ PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATERESULT_TYPE, plContext),
+ PKIX_OBJECTNOTVALIDATERESULT);
+
+ valResult = (PKIX_ValidateResult*)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)valResult->pubKey, &pubKeyHash, plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ if (valResult->anchor) {
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)valResult->anchor,
+ &anchorHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+ }
+
+ if (valResult->policyTree) {
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)valResult->policyTree,
+ &policyTreeHash,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+ }
+
+ hash = 31*(31 * pubKeyHash + anchorHash) + policyTreeHash;
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: pkix_ValidateResult_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ValidateResult_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *valResultString = NULL;
+
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_PL_PublicKey *pubKey = NULL;
+ PKIX_PolicyNode *policyTree = NULL;
+
+ PKIX_PL_String *anchorString = NULL;
+ PKIX_PL_String *pubKeyString = NULL;
+ PKIX_PL_String *treeString = NULL;
+ char *asciiNullString = "(null)";
+ char *asciiFormat =
+ "[\n"
+ "\tTrustAnchor: \t\t%s"
+ "\tPubKey: \t\t%s\n"
+ "\tPolicyTree: \t\t%s\n"
+ "]\n";
+
+ PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VALIDATERESULT_TYPE, plContext),
+ PKIX_OBJECTNOTVALIDATERESULT);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ valResult = (PKIX_ValidateResult*)object;
+
+ anchor = valResult->anchor;
+
+ if (anchor) {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)anchor, &anchorString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiNullString,
+ 0,
+ &anchorString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ }
+
+ pubKey = valResult->pubKey;
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)pubKey, &pubKeyString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ policyTree = valResult->policyTree;
+
+ if (policyTree) {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)policyTree, &treeString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiNullString,
+ 0,
+ &treeString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&valResultString,
+ plContext,
+ formatString,
+ anchorString,
+ pubKeyString,
+ treeString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = valResultString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(anchorString);
+ PKIX_DECREF(pubKeyString);
+ PKIX_DECREF(treeString);
+
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: pkix_ValidateResult_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_VALIDATERESULT_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_ValidateResult_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_RegisterSelf");
+
+ entry.description = "ValidateResult";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_ValidateResult);
+ entry.destructor = pkix_ValidateResult_Destroy;
+ entry.equalsFunction = pkix_ValidateResult_Equals;
+ entry.hashcodeFunction = pkix_ValidateResult_Hashcode;
+ entry.toStringFunction = pkix_ValidateResult_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_VALIDATERESULT_TYPE] = entry;
+
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: pkix_ValidateResult_Create
+ * DESCRIPTION:
+ *
+ * Creates a new ValidateResult Object using the PublicKey pointed to by
+ * "pubKey", the TrustAnchor pointed to by "anchor", and the PolicyNode
+ * pointed to by "policyTree", and stores it at "pResult".
+ *
+ * PARAMETERS
+ * "pubKey"
+ * PublicKey of the desired ValidateResult. Must be non-NULL.
+ * "anchor"
+ * TrustAnchor of the desired Validateresult. May be NULL.
+ * "policyTree"
+ * PolicyNode of the desired ValidateResult; may be NULL
+ * "pResult"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_ValidateResult_Create(
+ PKIX_PL_PublicKey *pubKey,
+ PKIX_TrustAnchor *anchor,
+ PKIX_PolicyNode *policyTree,
+ PKIX_ValidateResult **pResult,
+ void *plContext)
+{
+ PKIX_ValidateResult *result = NULL;
+
+ PKIX_ENTER(VALIDATERESULT, "pkix_ValidateResult_Create");
+ PKIX_NULLCHECK_TWO(pubKey, pResult);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_VALIDATERESULT_TYPE,
+ sizeof (PKIX_ValidateResult),
+ (PKIX_PL_Object **)&result,
+ plContext),
+ PKIX_COULDNOTCREATEVALIDATERESULTOBJECT);
+
+ /* initialize fields */
+
+ PKIX_INCREF(pubKey);
+ result->pubKey = pubKey;
+
+ PKIX_INCREF(anchor);
+ result->anchor = anchor;
+
+ PKIX_INCREF(policyTree);
+ result->policyTree = policyTree;
+
+ *pResult = result;
+ result = NULL;
+
+cleanup:
+
+ PKIX_DECREF(result);
+
+ PKIX_RETURN(VALIDATERESULT);
+
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_ValidateResult_GetPublicKey
+ * (see comments in pkix_result.h)
+ */
+PKIX_Error *
+PKIX_ValidateResult_GetPublicKey(
+ PKIX_ValidateResult *result,
+ PKIX_PL_PublicKey **pPublicKey,
+ void *plContext)
+{
+ PKIX_ENTER(VALIDATERESULT, "PKIX_ValidateResult_GetPublicKey");
+ PKIX_NULLCHECK_TWO(result, pPublicKey);
+
+ PKIX_INCREF(result->pubKey);
+ *pPublicKey = result->pubKey;
+
+cleanup:
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: PKIX_ValidateResult_GetTrustAnchor
+ * (see comments in pkix_result.h)
+ */
+PKIX_Error *
+PKIX_ValidateResult_GetTrustAnchor(
+ PKIX_ValidateResult *result,
+ PKIX_TrustAnchor **pTrustAnchor,
+ void *plContext)
+{
+ PKIX_ENTER(VALIDATERESULT, "PKIX_ValidateResult_GetTrustAnchor");
+ PKIX_NULLCHECK_TWO(result, pTrustAnchor);
+
+ PKIX_INCREF(result->anchor);
+ *pTrustAnchor = result->anchor;
+
+cleanup:
+ PKIX_RETURN(VALIDATERESULT);
+}
+
+/*
+ * FUNCTION: PKIX_ValidateResult_GetPolicyTree
+ * (see comments in pkix_result.h)
+ */
+PKIX_Error *
+PKIX_ValidateResult_GetPolicyTree(
+ PKIX_ValidateResult *result,
+ PKIX_PolicyNode **pPolicyTree,
+ void *plContext)
+{
+ PKIX_ENTER(VALIDATERESULT, "PKIX_ValidateResult_GetPolicyTree");
+ PKIX_NULLCHECK_TWO(result, pPolicyTree);
+
+ PKIX_INCREF(result->policyTree);
+ (*pPolicyTree) = result->policyTree;
+
+cleanup:
+ PKIX_RETURN(VALIDATERESULT);
+}
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_valresult.h b/security/nss/lib/libpkix/pkix/results/pkix_valresult.h
new file mode 100644
index 0000000000..8011ae8c8f
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_valresult.h
@@ -0,0 +1,43 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_valresult.h
+ *
+ * ValidateResult Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_VALIDATERESULT_H
+#define _PKIX_VALIDATERESULT_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_ValidateResultStruct {
+ PKIX_PL_PublicKey *pubKey;
+ PKIX_TrustAnchor *anchor;
+ PKIX_PolicyNode *policyTree;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_ValidateResult_Create(
+ PKIX_PL_PublicKey *pubKey,
+ PKIX_TrustAnchor *anchor,
+ PKIX_PolicyNode *policyTree,
+ PKIX_ValidateResult **pResult,
+ void *plContext);
+
+PKIX_Error *pkix_ValidateResult_RegisterSelf(void *plContext);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_VALIDATERESULT_H */
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_verifynode.c b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.c
new file mode 100644
index 0000000000..b52f83fcab
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.c
@@ -0,0 +1,1182 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_verifynode.c
+ *
+ * Verify Node Object Type Definition
+ *
+ */
+
+#include "pkix_verifynode.h"
+
+/* --Private-VerifyNode-Functions---------------------------------- */
+
+/*
+ * FUNCTION: pkix_VerifyNode_Create
+ * DESCRIPTION:
+ *
+ * This function creates a VerifyNode using the Cert pointed to by "cert",
+ * the depth given by "depth", and the Error pointed to by "error", storing
+ * the result at "pObject".
+ *
+ * PARAMETERS
+ * "cert"
+ * Address of Cert for the node. Must be non-NULL
+ * "depth"
+ * UInt32 value of the depth for this node.
+ * "error"
+ * Address of Error for the node.
+ * "pObject"
+ * Address where the VerifyNode pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_VerifyNode_Create(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 depth,
+ PKIX_Error *error,
+ PKIX_VerifyNode **pObject,
+ void *plContext)
+{
+ PKIX_VerifyNode *node = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Create");
+ PKIX_NULLCHECK_TWO(cert, pObject);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_VERIFYNODE_TYPE,
+ sizeof (PKIX_VerifyNode),
+ (PKIX_PL_Object **)&node,
+ plContext),
+ PKIX_COULDNOTCREATEVERIFYNODEOBJECT);
+
+ PKIX_INCREF(cert);
+ node->verifyCert = cert;
+
+ PKIX_INCREF(error);
+ node->error = error;
+
+ node->depth = depth;
+
+ node->children = NULL;
+
+ *pObject = node;
+ node = NULL;
+
+cleanup:
+
+ PKIX_DECREF(node);
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_AddToChain
+ * DESCRIPTION:
+ *
+ * Adds the VerifyNode pointed to by "child", at the appropriate depth, to the
+ * List of children of the VerifyNode pointed to by "parentNode". The chain of
+ * VerifyNodes is traversed until a VerifyNode is found at a depth one less
+ * than that specified in "child". An Error is returned if there is no parent
+ * at a suitable depth.
+ *
+ * If "parentNode" has a NULL pointer for the List of children, a new List is
+ * created containing "child". Otherwise "child" is appended to the existing
+ * List.
+ *
+ * Depth, in this context, means distance from the root node, which
+ * is at depth zero.
+ *
+ * PARAMETERS:
+ * "parentNode"
+ * Address of VerifyNode whose List of child VerifyNodes is to be
+ * created or appended to. Must be non-NULL.
+ * "child"
+ * Address of VerifyNode to be added to parentNode's List. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a VerifyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_VerifyNode_AddToChain(
+ PKIX_VerifyNode *parentNode,
+ PKIX_VerifyNode *child,
+ void *plContext)
+{
+ PKIX_VerifyNode *successor = NULL;
+ PKIX_List *listOfChildren = NULL;
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 parentDepth = 0;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToChain");
+ PKIX_NULLCHECK_TWO(parentNode, child);
+
+ parentDepth = parentNode->depth;
+ listOfChildren = parentNode->children;
+ if (listOfChildren == NULL) {
+
+ if (parentDepth != (child->depth - 1)) {
+ PKIX_ERROR(PKIX_NODESMISSINGFROMCHAIN);
+ }
+
+ PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (listOfChildren, (PKIX_PL_Object *)child, plContext),
+ PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST);
+
+ parentNode->children = listOfChildren;
+ } else {
+ /* get number of children */
+ PKIX_CHECK(PKIX_List_GetLength
+ (listOfChildren, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numChildren != 1) {
+ PKIX_ERROR(PKIX_AMBIGUOUSPARENTAGEOFVERIFYNODE);
+ }
+
+ /* successor = listOfChildren[0] */
+ PKIX_CHECK(PKIX_List_GetItem
+ (listOfChildren,
+ 0,
+ (PKIX_PL_Object **)&successor,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_VerifyNode_AddToChain
+ (successor, child, plContext),
+ PKIX_VERIFYNODEADDTOCHAINFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)parentNode, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+ PKIX_DECREF(successor);
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_SetDepth
+ * DESCRIPTION:
+ *
+ * The function sets the depth field of each VerifyNode in the List "children"
+ * to the value given by "depth", and recursively sets the depth of any
+ * successive generations to the successive values.
+ *
+ * PARAMETERS:
+ * "children"
+ * The List of VerifyNodes. Must be non-NULL.
+ * "depth"
+ * The value of the depth field to be set in members of the List.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_VerifyNode_SetDepth(PKIX_List *children,
+ PKIX_UInt32 depth,
+ void *plContext)
+{
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 chIx = 0;
+ PKIX_VerifyNode *child = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_SetDepth");
+ PKIX_NULLCHECK_ONE(children);
+
+ PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (chIx = 0; chIx < numChildren; chIx++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (children, chIx, (PKIX_PL_Object **)&child, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ child->depth = depth;
+
+ if (child->children != NULL) {
+ PKIX_CHECK(pkix_VerifyNode_SetDepth
+ (child->children, depth + 1, plContext),
+ PKIX_VERIFYNODESETDEPTHFAILED);
+ }
+
+ PKIX_DECREF(child);
+ }
+
+cleanup:
+
+ PKIX_DECREF(child);
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_AddToTree
+ * DESCRIPTION:
+ *
+ * Adds the VerifyNode pointed to by "child" to the List of children of the
+ * VerifyNode pointed to by "parentNode". If "parentNode" has a NULL pointer
+ * for the List of children, a new List is created containing "child".
+ * Otherwise "child" is appended to the existing List. The depth field of
+ * "child" is set to one more than the corresponding value in "parent", and
+ * if the "child" itself has child nodes, their depth fields are updated
+ * accordingly.
+ *
+ * Depth, in this context, means distance from the root node, which
+ * is at depth zero.
+ *
+ * PARAMETERS:
+ * "parentNode"
+ * Address of VerifyNode whose List of child VerifyNodes is to be
+ * created or appended to. Must be non-NULL.
+ * "child"
+ * Address of VerifyNode to be added to parentNode's List. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_VerifyNode_AddToTree(
+ PKIX_VerifyNode *parentNode,
+ PKIX_VerifyNode *child,
+ void *plContext)
+{
+ PKIX_List *listOfChildren = NULL;
+ PKIX_UInt32 parentDepth = 0;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToTree");
+ PKIX_NULLCHECK_TWO(parentNode, child);
+
+ parentDepth = parentNode->depth;
+ listOfChildren = parentNode->children;
+ if (listOfChildren == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ parentNode->children = listOfChildren;
+ }
+
+ child->depth = parentDepth + 1;
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (parentNode->children, (PKIX_PL_Object *)child, plContext),
+ PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST);
+
+ if (child->children != NULL) {
+ PKIX_CHECK(pkix_VerifyNode_SetDepth
+ (child->children, child->depth + 1, plContext),
+ PKIX_VERIFYNODESETDEPTHFAILED);
+ }
+
+
+cleanup:
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_SingleVerifyNode_ToString
+ * DESCRIPTION:
+ *
+ * Creates a String representation of the attributes of the VerifyNode pointed
+ * to by "node", other than its children, and stores the result at "pString".
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of VerifyNode to be described by the string. Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a VerifyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+PKIX_Error *
+pkix_SingleVerifyNode_ToString(
+ PKIX_VerifyNode *node,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *fmtString = NULL;
+ PKIX_PL_String *errorString = NULL;
+ PKIX_PL_String *outString = NULL;
+
+ PKIX_PL_X500Name *issuerName = NULL;
+ PKIX_PL_X500Name *subjectName = NULL;
+ PKIX_PL_String *issuerString = NULL;
+ PKIX_PL_String *subjectString = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_ToString");
+ PKIX_NULLCHECK_THREE(node, pString, node->verifyCert);
+
+ PKIX_TOSTRING(node->error, &errorString, plContext,
+ PKIX_ERRORTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetIssuer
+ (node->verifyCert, &issuerName, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ PKIX_TOSTRING(issuerName, &issuerString, plContext,
+ PKIX_X500NAMETOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject
+ (node->verifyCert, &subjectName, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+
+ PKIX_TOSTRING(subjectName, &subjectString, plContext,
+ PKIX_X500NAMETOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "CERT[Issuer:%s, Subject:%s], depth=%d, error=%s",
+ 0,
+ &fmtString,
+ plContext),
+ PKIX_CANTCREATESTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString,
+ plContext,
+ fmtString,
+ issuerString,
+ subjectString,
+ node->depth,
+ errorString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = outString;
+
+cleanup:
+
+ PKIX_DECREF(fmtString);
+ PKIX_DECREF(errorString);
+ PKIX_DECREF(issuerName);
+ PKIX_DECREF(subjectName);
+ PKIX_DECREF(issuerString);
+ PKIX_DECREF(subjectString);
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Produces a String representation of a VerifyNode tree below the VerifyNode
+ * pointed to by "rootNode", with each line of output prefixed by the String
+ * pointed to by "indent", and stores the result at "pTreeString". It is
+ * called recursively, with ever-increasing indentation, for successively
+ * lower nodes on the tree.
+ *
+ * PARAMETERS:
+ * "rootNode"
+ * Address of VerifyNode subtree. Must be non-NULL.
+ * "indent"
+ * Address of String to be prefixed to each line of output. May be NULL
+ * if no indentation is desired
+ * "pTreeString"
+ * Address where the resulting String will be stored; must be non-NULL
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a VerifyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_VerifyNode_ToString_Helper(
+ PKIX_VerifyNode *rootNode,
+ PKIX_PL_String *indent,
+ PKIX_PL_String **pTreeString,
+ void *plContext)
+{
+ PKIX_PL_String *nextIndentFormat = NULL;
+ PKIX_PL_String *thisNodeFormat = NULL;
+ PKIX_PL_String *childrenFormat = NULL;
+ PKIX_PL_String *nextIndentString = NULL;
+ PKIX_PL_String *resultString = NULL;
+ PKIX_PL_String *thisItemString = NULL;
+ PKIX_PL_String *childString = NULL;
+ PKIX_VerifyNode *childNode = NULL;
+ PKIX_UInt32 numberOfChildren = 0;
+ PKIX_UInt32 childIndex = 0;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString_Helper");
+
+ PKIX_NULLCHECK_TWO(rootNode, pTreeString);
+
+ /* Create a string for this node */
+ PKIX_CHECK(pkix_SingleVerifyNode_ToString
+ (rootNode, &thisItemString, plContext),
+ PKIX_ERRORINSINGLEVERIFYNODETOSTRING);
+
+ if (indent) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s%s",
+ 0,
+ &thisNodeFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ thisNodeFormat,
+ indent,
+ thisItemString),
+ PKIX_ERRORINSPRINTF);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s",
+ 0,
+ &thisNodeFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ thisNodeFormat,
+ thisItemString),
+ PKIX_ERRORINSPRINTF);
+ }
+
+ PKIX_DECREF(thisItemString);
+ thisItemString = resultString;
+
+ /* if no children, we are done */
+ if (rootNode->children) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (rootNode->children, &numberOfChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ if (numberOfChildren != 0) {
+ /*
+ * We create a string for each child in turn,
+ * concatenating them to thisItemString.
+ */
+
+ /* Prepare an indent string for each child */
+ if (indent) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s. ",
+ 0,
+ &nextIndentFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&nextIndentString,
+ plContext,
+ nextIndentFormat,
+ indent),
+ PKIX_ERRORINSPRINTF);
+ } else {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ ". ",
+ 0,
+ &nextIndentString,
+ plContext),
+ PKIX_ERRORCREATINGINDENTSTRING);
+ }
+
+ /* Prepare the format for concatenation. */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s\n%s",
+ 0,
+ &childrenFormat,
+ plContext),
+ PKIX_ERRORCREATINGFORMATSTRING);
+
+ for (childIndex = 0;
+ childIndex < numberOfChildren;
+ childIndex++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (rootNode->children,
+ childIndex,
+ (PKIX_PL_Object **)&childNode,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_VerifyNode_ToString_Helper
+ (childNode,
+ nextIndentString,
+ &childString,
+ plContext),
+ PKIX_ERRORCREATINGCHILDSTRING);
+
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ childrenFormat,
+ thisItemString,
+ childString),
+ PKIX_ERRORINSPRINTF);
+
+ PKIX_DECREF(childNode);
+ PKIX_DECREF(childString);
+ PKIX_DECREF(thisItemString);
+
+ thisItemString = resultString;
+ }
+ }
+
+ *pTreeString = thisItemString;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(thisItemString);
+ }
+
+ PKIX_DECREF(nextIndentFormat);
+ PKIX_DECREF(thisNodeFormat);
+ PKIX_DECREF(childrenFormat);
+ PKIX_DECREF(nextIndentString);
+ PKIX_DECREF(childString);
+ PKIX_DECREF(childNode);
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_VerifyNode_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pTreeString,
+ void *plContext)
+{
+ PKIX_VerifyNode *rootNode = NULL;
+ PKIX_PL_String *resultString = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString");
+
+ PKIX_NULLCHECK_TWO(object, pTreeString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTVERIFYNODE);
+
+ rootNode = (PKIX_VerifyNode *)object;
+
+ PKIX_CHECK(pkix_VerifyNode_ToString_Helper
+ (rootNode, NULL, &resultString, plContext),
+ PKIX_ERRORCREATINGSUBTREESTRING);
+
+ *pTreeString = resultString;
+
+cleanup:
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_VerifyNode_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_VerifyNode *node = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTVERIFYNODE);
+
+ node = (PKIX_VerifyNode*)object;
+
+ PKIX_DECREF(node->verifyCert);
+ PKIX_DECREF(node->children);
+ PKIX_DECREF(node->error);
+
+ node->depth = 0;
+
+cleanup:
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_SingleVerifyNode_Hashcode
+ * DESCRIPTION:
+ *
+ * Computes the hashcode of the attributes of the VerifyNode pointed to by
+ * "node", other than its parents and children, and stores the result at
+ * "pHashcode".
+ *
+ * PARAMETERS:
+ * "node"
+ * Address of VerifyNode to be hashcoded; must be non-NULL
+ * "pHashcode"
+ * Address where UInt32 result will be stored; must be non-NULL
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a VerifyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+static PKIX_Error *
+pkix_SingleVerifyNode_Hashcode(
+ PKIX_VerifyNode *node,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_UInt32 errorHash = 0;
+ PKIX_UInt32 nodeHash = 0;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Hashcode");
+ PKIX_NULLCHECK_TWO(node, pHashcode);
+
+ PKIX_HASHCODE
+ (node->verifyCert,
+ &nodeHash,
+ plContext,
+ PKIX_FAILUREHASHINGCERT);
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)node->error,
+ &errorHash,
+ plContext),
+ PKIX_FAILUREHASHINGERROR);
+
+ nodeHash = 31*nodeHash + errorHash;
+ *pHashcode = nodeHash;
+
+cleanup:
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_VerifyNode_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_VerifyNode *node = NULL;
+ PKIX_UInt32 childrenHash = 0;
+ PKIX_UInt32 nodeHash = 0;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_VERIFYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTVERIFYNODE);
+
+ node = (PKIX_VerifyNode *)object;
+
+ PKIX_CHECK(pkix_SingleVerifyNode_Hashcode
+ (node, &nodeHash, plContext),
+ PKIX_SINGLEVERIFYNODEHASHCODEFAILED);
+
+ PKIX_HASHCODE
+ (node->children,
+ &childrenHash,
+ plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ nodeHash = 31*nodeHash + childrenHash;
+
+ *pHashcode = nodeHash;
+
+cleanup:
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_SingleVerifyNode_Equals
+ * DESCRIPTION:
+ *
+ * Compares for equality the components of the VerifyNode pointed to by
+ * "firstPN", other than its parents and children, with those of the
+ * VerifyNode pointed to by "secondPN" and stores the result at "pResult"
+ * (PKIX_TRUE if equal; PKIX_FALSE if not).
+ *
+ * PARAMETERS:
+ * "firstPN"
+ * Address of first of the VerifyNodes to be compared; must be non-NULL
+ * "secondPN"
+ * Address of second of the VerifyNodes to be compared; must be non-NULL
+ * "pResult"
+ * Address where Boolean will be stored; must be non-NULL
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a VerifyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+static PKIX_Error *
+pkix_SingleVerifyNode_Equals(
+ PKIX_VerifyNode *firstVN,
+ PKIX_VerifyNode *secondVN,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_Boolean compResult = PKIX_FALSE;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Equals");
+ PKIX_NULLCHECK_THREE(firstVN, secondVN, pResult);
+
+ /* If both references are identical, they must be equal */
+ if (firstVN == secondVN) {
+ compResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * It seems we have to do the comparisons. Do
+ * the easiest ones first.
+ */
+ if ((firstVN->depth) != (secondVN->depth)) {
+ goto cleanup;
+ }
+
+ /* These fields must be non-NULL */
+ PKIX_NULLCHECK_TWO(firstVN->verifyCert, secondVN->verifyCert);
+
+ PKIX_EQUALS
+ (firstVN->verifyCert,
+ secondVN->verifyCert,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (compResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS
+ (firstVN->error,
+ secondVN->error,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+cleanup:
+
+ *pResult = compResult;
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_VerifyNode_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_VerifyNode *firstVN = NULL;
+ PKIX_VerifyNode *secondVN = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean compResult = PKIX_FALSE;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a VerifyNode */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_VERIFYNODE_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTVERIFYNODE);
+
+ /*
+ * Since we know firstObject is a VerifyNode,
+ * if both references are identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ compResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a VerifyNode, we
+ * don't throw an error. We simply return FALSE.
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ if (secondType != PKIX_VERIFYNODE_TYPE) {
+ goto cleanup;
+ }
+
+ /*
+ * Oh, well, we have to do the comparisons. Do
+ * the easiest ones first.
+ */
+ firstVN = (PKIX_VerifyNode *)firstObject;
+ secondVN = (PKIX_VerifyNode *)secondObject;
+
+ PKIX_CHECK(pkix_SingleVerifyNode_Equals
+ (firstVN, secondVN, &compResult, plContext),
+ PKIX_SINGLEVERIFYNODEEQUALSFAILED);
+
+ if (compResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS
+ (firstVN->children,
+ secondVN->children,
+ &compResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILEDONCHILDREN);
+
+cleanup:
+
+ *pResult = compResult;
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_DuplicateHelper
+ * DESCRIPTION:
+ *
+ * Duplicates the VerifyNode whose address is pointed to by "original",
+ * and stores the result at "pNewNode", if a non-NULL pointer is provided
+ * for "pNewNode". In addition, the created VerifyNode is added as a child
+ * to "parent", if a non-NULL pointer is provided for "parent". Then this
+ * function is called recursively to duplicate each of the children of
+ * "original". At the top level this function is called with a null
+ * "parent" and a non-NULL "pNewNode". Below the top level "parent" will
+ * be non-NULL and "pNewNode" will be NULL.
+ *
+ * PARAMETERS:
+ * "original"
+ * Address of VerifyNode to be copied; must be non-NULL
+ * "parent"
+ * Address of VerifyNode to which the created node is to be added as a
+ * child; NULL for the top-level call and non-NULL below the top level
+ * "pNewNode"
+ * Address to store the node created; should be NULL if "parent" is
+ * non-NULL and vice versa
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if function succeeds
+ * Returns a VerifyNode Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in a fatal way
+ */
+static PKIX_Error *
+pkix_VerifyNode_DuplicateHelper(
+ PKIX_VerifyNode *original,
+ PKIX_VerifyNode *parent,
+ PKIX_VerifyNode **pNewNode,
+ void *plContext)
+{
+ PKIX_UInt32 numChildren = 0;
+ PKIX_UInt32 childIndex = 0;
+ PKIX_List *children = NULL; /* List of PKIX_VerifyNode */
+ PKIX_VerifyNode *copy = NULL;
+ PKIX_VerifyNode *child = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_DuplicateHelper");
+
+ PKIX_NULLCHECK_TWO
+ (original, original->verifyCert);
+
+ /*
+ * These components are immutable, so copying the pointers
+ * is sufficient. The create function increments the reference
+ * counts as it stores the pointers into the new object.
+ */
+ PKIX_CHECK(pkix_VerifyNode_Create
+ (original->verifyCert,
+ original->depth,
+ original->error,
+ &copy,
+ plContext),
+ PKIX_VERIFYNODECREATEFAILED);
+
+ /* Are there any children to duplicate? */
+ children = original->children;
+
+ if (children) {
+ PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ for (childIndex = 0; childIndex < numChildren; childIndex++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (children,
+ childIndex,
+ (PKIX_PL_Object **)&child,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_VerifyNode_DuplicateHelper
+ (child, copy, NULL, plContext),
+ PKIX_VERIFYNODEDUPLICATEHELPERFAILED);
+
+ PKIX_DECREF(child);
+ }
+
+ if (pNewNode) {
+ *pNewNode = copy;
+ copy = NULL; /* no DecRef if we give our handle away */
+ }
+
+cleanup:
+ PKIX_DECREF(copy);
+ PKIX_DECREF(child);
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_Duplicate
+ * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_VerifyNode_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_VerifyNode *original = NULL;
+ PKIX_VerifyNode *copy = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Duplicate");
+
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_VERIFYNODE_TYPE, plContext),
+ PKIX_OBJECTNOTVERIFYNODE);
+
+ original = (PKIX_VerifyNode *)object;
+
+ PKIX_CHECK(pkix_VerifyNode_DuplicateHelper
+ (original, NULL, &copy, plContext),
+ PKIX_VERIFYNODEDUPLICATEHELPERFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)copy;
+
+cleanup:
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: pkix_VerifyNode_RegisterSelf
+ * DESCRIPTION:
+ *
+ * Registers PKIX_VERIFYNODE_TYPE and its related
+ * functions with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize,
+ * which should only be called once, it is acceptable that
+ * this function is not thread-safe.
+ */
+PKIX_Error *
+pkix_VerifyNode_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_RegisterSelf");
+
+ entry.description = "VerifyNode";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_VerifyNode);
+ entry.destructor = pkix_VerifyNode_Destroy;
+ entry.equalsFunction = pkix_VerifyNode_Equals;
+ entry.hashcodeFunction = pkix_VerifyNode_Hashcode;
+ entry.toStringFunction = pkix_VerifyNode_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_VerifyNode_Duplicate;
+
+ systemClasses[PKIX_VERIFYNODE_TYPE] = entry;
+
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/* --Public-VerifyNode-Functions----------------------------------- */
+
+/*
+ * FUNCTION: PKIX_VerifyNode_SetError
+ * DESCRIPTION:
+ *
+ * This function sets the Error field of the VerifyNode pointed to by "node"
+ * to contain the Error pointed to by "error".
+ *
+ * PARAMETERS:
+ * "node"
+ * The address of the VerifyNode to be modified. Must be non-NULL.
+ * "error"
+ * The address of the Error to be stored.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_VerifyNode_SetError(
+ PKIX_VerifyNode *node,
+ PKIX_Error *error,
+ void *plContext)
+{
+
+ PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_SetError");
+
+ PKIX_NULLCHECK_TWO(node, error);
+
+ PKIX_DECREF(node->error); /* should have been NULL */
+ PKIX_INCREF(error);
+ node->error = error;
+
+cleanup:
+ PKIX_RETURN(VERIFYNODE);
+}
+
+/*
+ * FUNCTION: PKIX_VerifyNode_FindError
+ * DESCRIPTION:
+ *
+ * Finds meaningful error in the log. For now, just returns the first
+ * error it finds in. In the future the function should be changed to
+ * return a top priority error.
+ *
+ * PARAMETERS:
+ * "node"
+ * The address of the VerifyNode to be modified. Must be non-NULL.
+ * "error"
+ * The address of a pointer the error will be returned to.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_VerifyNode_FindError(
+ PKIX_VerifyNode *node,
+ PKIX_Error **error,
+ void *plContext)
+{
+ PKIX_VerifyNode *childNode = NULL;
+
+ PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_FindError");
+
+ /* Make sure the return address is initialized with NULL */
+ PKIX_DECREF(*error);
+
+ if (!node)
+ goto cleanup;
+
+ /* First, try to get error from lowest level. */
+ if (node->children) {
+ PKIX_UInt32 length = 0;
+ PKIX_UInt32 index = 0;
+
+ PKIX_CHECK(
+ PKIX_List_GetLength(node->children, &length,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ for (index = 0;index < length;index++) {
+ PKIX_CHECK(
+ PKIX_List_GetItem(node->children, index,
+ (PKIX_PL_Object**)&childNode, plContext),
+ PKIX_LISTGETITEMFAILED);
+ if (!childNode)
+ continue;
+ PKIX_CHECK(
+ pkix_VerifyNode_FindError(childNode, error,
+ plContext),
+ PKIX_VERIFYNODEFINDERRORFAILED);
+ PKIX_DECREF(childNode);
+ if (*error) {
+ goto cleanup;
+ }
+ }
+ }
+
+ if (node->error && node->error->plErr) {
+ PKIX_INCREF(node->error);
+ *error = node->error;
+ }
+
+cleanup:
+ PKIX_DECREF(childNode);
+
+ PKIX_RETURN(VERIFYNODE);
+}
diff --git a/security/nss/lib/libpkix/pkix/results/pkix_verifynode.h b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.h
new file mode 100644
index 0000000000..c943ae4ddc
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/pkix_verifynode.h
@@ -0,0 +1,75 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_verifynode.h
+ *
+ * VerifyNode Type Definitions
+ *
+ */
+
+#ifndef _PKIX_VERIFYNODE_H
+#define _PKIX_VERIFYNODE_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This structure reflects the contents of a verify node...
+ */
+struct PKIX_VerifyNodeStruct {
+ PKIX_PL_Cert *verifyCert;
+ PKIX_List *children; /* VerifyNodes */
+ PKIX_UInt32 depth;
+ PKIX_Error *error;
+};
+
+PKIX_Error *
+pkix_SingleVerifyNode_ToString(
+ PKIX_VerifyNode *node,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+PKIX_Error *
+pkix_VerifyNode_Create(
+ PKIX_PL_Cert *verifyCert,
+ PKIX_UInt32 depth,
+ PKIX_Error *error,
+ PKIX_VerifyNode **pObject,
+ void *plContext);
+
+PKIX_Error *
+pkix_VerifyNode_AddToChain(
+ PKIX_VerifyNode *parentNode,
+ PKIX_VerifyNode *child,
+ void *plContext);
+
+PKIX_Error *
+pkix_VerifyNode_AddToTree(
+ PKIX_VerifyNode *parentNode,
+ PKIX_VerifyNode *child,
+ void *plContext);
+
+PKIX_Error *
+pkix_VerifyNode_SetError(
+ PKIX_VerifyNode *node,
+ PKIX_Error *error,
+ void *plContext);
+
+PKIX_Error *
+pkix_VerifyNode_RegisterSelf(
+ void *plContext);
+
+PKIX_Error *
+pkix_VerifyNode_FindError(
+ PKIX_VerifyNode *node,
+ PKIX_Error **error,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_VERIFYNODE_H */
diff --git a/security/nss/lib/libpkix/pkix/results/results.gyp b/security/nss/lib/libpkix/pkix/results/results.gyp
new file mode 100644
index 0000000000..962fdb9481
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/results/results.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'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixresults',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_buildresult.c',
+ 'pkix_policynode.c',
+ 'pkix_valresult.c',
+ 'pkix_verifynode.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/store/Makefile b/security/nss/lib/libpkix/pkix/store/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/store/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). #
+#######################################################################
+
+
+#######################################################################
+# (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/lib/libpkix/pkix/store/exports.gyp b/security/nss/lib/libpkix/pkix/store/exports.gyp
new file mode 100644
index 0000000000..52f13f5ae7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/store/exports.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'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_libpkix_pkix_store_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_store.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/store/manifest.mn b/security/nss/lib/libpkix/pkix/store/manifest.mn
new file mode 100644
index 0000000000..53a54d6cc6
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/store/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 = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_store.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_store.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixstore
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/store/pkix_store.c b/security/nss/lib/libpkix/pkix/store/pkix_store.c
new file mode 100644
index 0000000000..af8be2bb2c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/store/pkix_store.c
@@ -0,0 +1,415 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_store.c
+ *
+ * CertStore Function Definitions
+ *
+ */
+
+#include "pkix_store.h"
+
+/* --CertStore-Private-Functions----------------------------------------- */
+
+/*
+ * FUNCTION: pkix_CertStore_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertStore_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_CertStore *certStore = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_CertStore_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a CertStore object */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSTORE_TYPE, plContext),
+ PKIX_OBJECTNOTCERTSTORE);
+
+ certStore = (PKIX_CertStore *)object;
+
+ certStore->certCallback = NULL;
+ certStore->crlCallback = NULL;
+ certStore->certContinue = NULL;
+ certStore->crlContinue = NULL;
+ certStore->trustCallback = NULL;
+
+ PKIX_DECREF(certStore->certStoreContext);
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_CertStore_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertStore_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_CertStore *certStore = NULL;
+ PKIX_UInt32 tempHash = 0;
+
+ PKIX_ENTER(CERTSTORE, "pkix_CertStore_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSTORE_TYPE, plContext),
+ PKIX_OBJECTNOTCERTSTORE);
+
+ certStore = (PKIX_CertStore *)object;
+
+ if (certStore->certStoreContext) {
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *) certStore->certStoreContext,
+ &tempHash,
+ plContext),
+ PKIX_CERTSTOREHASHCODEFAILED);
+ }
+
+ *pHashcode = (PKIX_UInt32)((char *)certStore->certCallback - (char *)NULL) +
+ (PKIX_UInt32)((char *)certStore->crlCallback - (char *)NULL) +
+ (PKIX_UInt32)((char *)certStore->certContinue - (char *)NULL) +
+ (PKIX_UInt32)((char *)certStore->crlContinue - (char *)NULL) +
+ (PKIX_UInt32)((char *)certStore->trustCallback - (char *)NULL) +
+ (tempHash << 7);
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_CertStore_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_CertStore_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_CertStore *firstCS = NULL;
+ PKIX_CertStore *secondCS = NULL;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+
+ PKIX_ENTER(CERTSTORE, "pkix_CertStore_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ PKIX_CHECK(pkix_CheckTypes
+ (firstObject, secondObject, PKIX_CERTSTORE_TYPE, plContext),
+ PKIX_ARGUMENTSNOTDATES);
+
+ firstCS = (PKIX_CertStore *)firstObject;
+ secondCS = (PKIX_CertStore *)secondObject;
+
+ cmpResult = (firstCS->certCallback == secondCS->certCallback) &&
+ (firstCS->crlCallback == secondCS->crlCallback) &&
+ (firstCS->certContinue == secondCS->certContinue) &&
+ (firstCS->crlContinue == secondCS->crlContinue) &&
+ (firstCS->trustCallback == secondCS->trustCallback);
+
+ if (cmpResult &&
+ (firstCS->certStoreContext != secondCS->certStoreContext)) {
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *) firstCS->certStoreContext,
+ (PKIX_PL_Object *) secondCS->certStoreContext,
+ &cmpResult,
+ plContext),
+ PKIX_CERTSTOREEQUALSFAILED);
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_CertStore_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTSTORE_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_CertStore_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTSTORE, "pkix_CertStore_RegisterSelf");
+
+ entry.description = "CertStore";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_CertStore);
+ entry.destructor = pkix_CertStore_Destroy;
+ entry.equalsFunction = pkix_CertStore_Equals;
+ entry.hashcodeFunction = pkix_CertStore_Hashcode;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CERTSTORE_TYPE] = entry;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/* --CertStore-Public-Functions------------------------------------------ */
+
+/*
+ * FUNCTION: PKIX_CertStore_Create (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_Create(
+ PKIX_CertStore_CertCallback certCallback,
+ PKIX_CertStore_CRLCallback crlCallback,
+ PKIX_CertStore_CertContinueFunction certContinue,
+ PKIX_CertStore_CrlContinueFunction crlContinue,
+ PKIX_CertStore_CheckTrustCallback trustCallback,
+ PKIX_CertStore_ImportCrlCallback importCrlCallback,
+ PKIX_CertStore_CheckRevokationByCrlCallback checkRevByCrlCallback,
+ PKIX_PL_Object *certStoreContext,
+ PKIX_Boolean cacheFlag,
+ PKIX_Boolean localFlag,
+ PKIX_CertStore **pStore,
+ void *plContext)
+{
+ PKIX_CertStore *certStore = NULL;
+
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_Create");
+ PKIX_NULLCHECK_THREE(certCallback, crlCallback, pStore);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTSTORE_TYPE,
+ sizeof (PKIX_CertStore),
+ (PKIX_PL_Object **)&certStore,
+ plContext),
+ PKIX_COULDNOTCREATECERTSTOREOBJECT);
+
+ certStore->certCallback = certCallback;
+ certStore->crlCallback = crlCallback;
+ certStore->certContinue = certContinue;
+ certStore->crlContinue = crlContinue;
+ certStore->trustCallback = trustCallback;
+ certStore->importCrlCallback = importCrlCallback;
+ certStore->checkRevByCrlCallback = checkRevByCrlCallback;
+ certStore->cacheFlag = cacheFlag;
+ certStore->localFlag = localFlag;
+
+ PKIX_INCREF(certStoreContext);
+ certStore->certStoreContext = certStoreContext;
+
+ *pStore = certStore;
+ certStore = NULL;
+
+cleanup:
+
+ PKIX_DECREF(certStore);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCertCallback (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetCertCallback(
+ PKIX_CertStore *store,
+ PKIX_CertStore_CertCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetCertCallback");
+ PKIX_NULLCHECK_TWO(store, pCallback);
+
+ *pCallback = store->certCallback;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCRLCallback (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetCRLCallback(
+ PKIX_CertStore *store,
+ PKIX_CertStore_CRLCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetCRLCallback");
+ PKIX_NULLCHECK_TWO(store, pCallback);
+
+ *pCallback = store->crlCallback;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_CertContinue (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_CertContinue(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ PKIX_VerifyNode *verifyNode,
+ void **pNBIOContext,
+ PKIX_List **pCertList,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_CertContinue");
+ PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCertList);
+
+ PKIX_CHECK(store->certContinue
+ (store, selector, verifyNode,
+ pNBIOContext, pCertList, plContext),
+ PKIX_CERTSTORECERTCONTINUEFUNCTIONFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_CrlContinue (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_CrlContinue(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrlList,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_CrlContinue");
+ PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCrlList);
+
+ PKIX_CHECK(store->crlContinue
+ (store, selector, pNBIOContext, pCrlList, plContext),
+ PKIX_CERTSTORECRLCONTINUEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetTrustCallback (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetTrustCallback(
+ PKIX_CertStore *store,
+ PKIX_CertStore_CheckTrustCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetTrustCallback");
+ PKIX_NULLCHECK_TWO(store, pCallback);
+
+ *pCallback = store->trustCallback;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetImportCrlCallback (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetImportCrlCallback(
+ PKIX_CertStore *store,
+ PKIX_CertStore_ImportCrlCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetTrustCallback");
+ PKIX_NULLCHECK_TWO(store, pCallback);
+
+ *pCallback = store->importCrlCallback;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCheckRevByCrl (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetCrlCheckerFn(
+ PKIX_CertStore *store,
+ PKIX_CertStore_CheckRevokationByCrlCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetTrustCallback");
+ PKIX_NULLCHECK_TWO(store, pCallback);
+
+ *pCallback = store->checkRevByCrlCallback;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCertStoreContext
+ * (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetCertStoreContext(
+ PKIX_CertStore *store,
+ PKIX_PL_Object **pCertStoreContext,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetCertStoreContext");
+ PKIX_NULLCHECK_TWO(store, pCertStoreContext);
+
+ PKIX_INCREF(store->certStoreContext);
+ *pCertStoreContext = store->certStoreContext;
+
+cleanup:
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetCertStoreCacheFlag
+ * (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetCertStoreCacheFlag(
+ PKIX_CertStore *store,
+ PKIX_Boolean *pCacheFlag,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetCertStoreCacheFlag");
+ PKIX_NULLCHECK_TWO(store, pCacheFlag);
+
+ *pCacheFlag = store->cacheFlag;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_CertStore_GetLocalFlag
+ * (see comments in pkix_certstore.h)
+ */
+PKIX_Error *
+PKIX_CertStore_GetLocalFlag(
+ PKIX_CertStore *store,
+ PKIX_Boolean *pLocalFlag,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "PKIX_CertStore_GetLocalFlag");
+ PKIX_NULLCHECK_TWO(store, pLocalFlag);
+
+ *pLocalFlag = store->localFlag;
+
+ PKIX_RETURN(CERTSTORE);
+}
diff --git a/security/nss/lib/libpkix/pkix/store/pkix_store.h b/security/nss/lib/libpkix/pkix/store/pkix_store.h
new file mode 100644
index 0000000000..9d116ffbda
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/store/pkix_store.h
@@ -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_store.h
+ *
+ * CertStore Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_STORE_H
+#define _PKIX_STORE_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_CertStoreStruct {
+ PKIX_CertStore_CertCallback certCallback;
+ PKIX_CertStore_CRLCallback crlCallback;
+ PKIX_CertStore_CertContinueFunction certContinue;
+ PKIX_CertStore_CrlContinueFunction crlContinue;
+ PKIX_CertStore_CheckTrustCallback trustCallback;
+ PKIX_CertStore_ImportCrlCallback importCrlCallback;
+ PKIX_CertStore_CheckRevokationByCrlCallback checkRevByCrlCallback;
+ PKIX_PL_Object *certStoreContext;
+ PKIX_Boolean cacheFlag;
+ PKIX_Boolean localFlag; /* TRUE if CertStore is local */
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_CertStore_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_STORE_H */
diff --git a/security/nss/lib/libpkix/pkix/store/store.gyp b/security/nss/lib/libpkix/pkix/store/store.gyp
new file mode 100644
index 0000000000..43aa177688
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/store/store.gyp
@@ -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/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixstore',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_store.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/top/Makefile b/security/nss/lib/libpkix/pkix/top/Makefile
new file mode 100644
index 0000000000..d714361be7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/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). #
+#######################################################################
+
+
+#######################################################################
+# (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/lib/libpkix/pkix/top/exports.gyp b/security/nss/lib/libpkix/pkix/top/exports.gyp
new file mode 100644
index 0000000000..d41f2b5ec4
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/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': 'lib_libpkix_pkix_top_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_build.h',
+ 'pkix_lifecycle.h',
+ 'pkix_validate.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/top/manifest.mn b/security/nss/lib/libpkix/pkix/top/manifest.mn
new file mode 100644
index 0000000000..5bdd3f300d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/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 = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_build.h \
+ pkix_lifecycle.h \
+ pkix_validate.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_validate.c \
+ pkix_lifecycle.c \
+ pkix_build.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixtop
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_build.c b/security/nss/lib/libpkix/pkix/top/pkix_build.c
new file mode 100644
index 0000000000..aebfeebade
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/pkix_build.c
@@ -0,0 +1,3763 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_build.c
+ *
+ * Top level buildChain function
+ *
+ */
+
+/* #define PKIX_BUILDDEBUG 1 */
+/* #define PKIX_FORWARDBUILDERSTATEDEBUG 1 */
+
+#include "pkix_build.h"
+
+extern PRLogModuleInfo *pkixLog;
+
+/*
+ * List of critical extension OIDs associate with what build chain has
+ * checked. Those OIDs need to be removed from the unresolved critical
+ * extension OIDs list manually (instead of by checker automatically).
+ */
+static SECOidTag buildCheckedCritExtOIDs[] = {
+ PKIX_CERTKEYUSAGE_OID,
+ PKIX_CERTSUBJALTNAME_OID,
+ PKIX_BASICCONSTRAINTS_OID,
+ PKIX_NAMECONSTRAINTS_OID,
+ PKIX_EXTENDEDKEYUSAGE_OID,
+ PKIX_NSCERTTYPE_OID,
+ PKIX_UNKNOWN_OID
+};
+
+/* --Private-ForwardBuilderState-Functions---------------------------------- */
+
+/*
+ * FUNCTION: pkix_ForwardBuilderState_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ForwardBuilderState_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ForwardBuilderState *state = NULL;
+
+ PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTFORWARDBUILDERSTATE);
+
+ state = (PKIX_ForwardBuilderState *)object;
+
+ state->status = BUILD_INITIAL;
+ state->traversedCACerts = 0;
+ state->certStoreIndex = 0;
+ state->numCerts = 0;
+ state->numAias = 0;
+ state->certIndex = 0;
+ state->aiaIndex = 0;
+ state->certCheckedIndex = 0;
+ state->checkerIndex = 0;
+ state->hintCertIndex = 0;
+ state->numFanout = 0;
+ state->numDepth = 0;
+ state->reasonCode = 0;
+ state->canBeCached = PKIX_FALSE;
+ state->useOnlyLocal = PKIX_FALSE;
+ state->revChecking = PKIX_FALSE;
+ state->usingHintCerts = PKIX_FALSE;
+ state->certLoopingDetected = PKIX_FALSE;
+ PKIX_DECREF(state->validityDate);
+ PKIX_DECREF(state->prevCert);
+ PKIX_DECREF(state->candidateCert);
+ PKIX_DECREF(state->traversedSubjNames);
+ PKIX_DECREF(state->trustChain);
+ PKIX_DECREF(state->aia);
+ PKIX_DECREF(state->candidateCerts);
+ PKIX_DECREF(state->reversedCertChain);
+ PKIX_DECREF(state->checkedCritExtOIDs);
+ PKIX_DECREF(state->checkerChain);
+ PKIX_DECREF(state->certSel);
+ PKIX_DECREF(state->verifyNode);
+ PKIX_DECREF(state->client);
+
+ /*
+ * If we ever add a child link we have to be careful not to have loops
+ * in the Destroy process. But with one-way links we should be okay.
+ */
+ if (state->parentState == NULL) {
+ state->buildConstants.numAnchors = 0;
+ state->buildConstants.numCertStores = 0;
+ state->buildConstants.numHintCerts = 0;
+ state->buildConstants.procParams = 0;
+ PKIX_DECREF(state->buildConstants.testDate);
+ PKIX_DECREF(state->buildConstants.timeLimit);
+ PKIX_DECREF(state->buildConstants.targetCert);
+ PKIX_DECREF(state->buildConstants.targetPubKey);
+ PKIX_DECREF(state->buildConstants.certStores);
+ PKIX_DECREF(state->buildConstants.anchors);
+ PKIX_DECREF(state->buildConstants.userCheckers);
+ PKIX_DECREF(state->buildConstants.hintCerts);
+ PKIX_DECREF(state->buildConstants.revChecker);
+ PKIX_DECREF(state->buildConstants.aiaMgr);
+ } else {
+ PKIX_DECREF(state->parentState);
+ }
+
+cleanup:
+
+ PKIX_RETURN(FORWARDBUILDERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_ForwardBuilderState_Create
+ *
+ * DESCRIPTION:
+ * Allocate and initialize a ForwardBuilderState.
+ *
+ * PARAMETERS
+ * "traversedCACerts"
+ * Number of CA certificates traversed.
+ * "numFanout"
+ * Number of Certs that can be considered at this level (0 = no limit)
+ * "numDepth"
+ * Number of additional levels that can be searched (0 = no limit)
+ * "canBeCached"
+ * Boolean value indicating whether all certs on the chain can be cached.
+ * "validityDate"
+ * Address of Date at which build chain Certs' most restricted validity
+ * time is kept. May be NULL.
+ * "prevCert"
+ * Address of Cert just traversed. Must be non-NULL.
+ * "traversedSubjNames"
+ * Address of List of GeneralNames that have been traversed.
+ * Must be non-NULL.
+ * "trustChain"
+ * Address of List of certificates traversed. Must be non-NULL.
+ * "parentState"
+ * Address of previous ForwardBuilderState
+ * "pState"
+ * Address where ForwardBuilderState will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_ForwardBuilderState_Create(
+ PKIX_Int32 traversedCACerts,
+ PKIX_UInt32 numFanout,
+ PKIX_UInt32 numDepth,
+ PKIX_Boolean canBeCached,
+ PKIX_PL_Date *validityDate,
+ PKIX_PL_Cert *prevCert,
+ PKIX_List *traversedSubjNames,
+ PKIX_List *trustChain,
+ PKIX_ForwardBuilderState *parentState,
+ PKIX_ForwardBuilderState **pState,
+ void *plContext)
+{
+ PKIX_ForwardBuilderState *state = NULL;
+
+ PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Create");
+ PKIX_NULLCHECK_FOUR(prevCert, traversedSubjNames, pState, trustChain);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_FORWARDBUILDERSTATE_TYPE,
+ sizeof (PKIX_ForwardBuilderState),
+ (PKIX_PL_Object **)&state,
+ plContext),
+ PKIX_COULDNOTCREATEFORWARDBUILDERSTATEOBJECT);
+
+ state->status = BUILD_INITIAL;
+ state->traversedCACerts = traversedCACerts;
+ state->certStoreIndex = 0;
+ state->numCerts = 0;
+ state->numAias = 0;
+ state->certIndex = 0;
+ state->aiaIndex = 0;
+ state->certCheckedIndex = 0;
+ state->checkerIndex = 0;
+ state->hintCertIndex = 0;
+ state->numFanout = numFanout;
+ state->numDepth = numDepth;
+ state->reasonCode = 0;
+ state->revChecking = numDepth;
+ state->canBeCached = canBeCached;
+ state->useOnlyLocal = PKIX_TRUE;
+ state->revChecking = PKIX_FALSE;
+ state->usingHintCerts = PKIX_FALSE;
+ state->certLoopingDetected = PKIX_FALSE;
+
+ PKIX_INCREF(validityDate);
+ state->validityDate = validityDate;
+
+ PKIX_INCREF(prevCert);
+ state->prevCert = prevCert;
+
+ state->candidateCert = NULL;
+
+ PKIX_INCREF(traversedSubjNames);
+ state->traversedSubjNames = traversedSubjNames;
+
+ PKIX_INCREF(trustChain);
+ state->trustChain = trustChain;
+
+ state->aia = NULL;
+ state->candidateCerts = NULL;
+ state->reversedCertChain = NULL;
+ state->checkedCritExtOIDs = NULL;
+ state->checkerChain = NULL;
+ state->certSel = NULL;
+ state->verifyNode = NULL;
+ state->client = NULL;
+
+ PKIX_INCREF(parentState);
+ state->parentState = parentState;
+
+ if (parentState != NULL) {
+ state->buildConstants.numAnchors =
+ parentState->buildConstants.numAnchors;
+ state->buildConstants.numCertStores =
+ parentState->buildConstants.numCertStores;
+ state->buildConstants.numHintCerts =
+ parentState->buildConstants.numHintCerts;
+ state->buildConstants.maxFanout =
+ parentState->buildConstants.maxFanout;
+ state->buildConstants.maxDepth =
+ parentState->buildConstants.maxDepth;
+ state->buildConstants.maxTime =
+ parentState->buildConstants.maxTime;
+ state->buildConstants.procParams =
+ parentState->buildConstants.procParams;
+ state->buildConstants.testDate =
+ parentState->buildConstants.testDate;
+ state->buildConstants.timeLimit =
+ parentState->buildConstants.timeLimit;
+ state->buildConstants.targetCert =
+ parentState->buildConstants.targetCert;
+ state->buildConstants.targetPubKey =
+ parentState->buildConstants.targetPubKey;
+ state->buildConstants.certStores =
+ parentState->buildConstants.certStores;
+ state->buildConstants.anchors =
+ parentState->buildConstants.anchors;
+ state->buildConstants.userCheckers =
+ parentState->buildConstants.userCheckers;
+ state->buildConstants.hintCerts =
+ parentState->buildConstants.hintCerts;
+ state->buildConstants.revChecker =
+ parentState->buildConstants.revChecker;
+ state->buildConstants.aiaMgr =
+ parentState->buildConstants.aiaMgr;
+ state->buildConstants.trustOnlyUserAnchors =
+ parentState->buildConstants.trustOnlyUserAnchors;
+ }
+
+ *pState = state;
+ state = NULL;
+cleanup:
+
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(FORWARDBUILDERSTATE);
+}
+
+/*
+ * FUNCTION: pkix_Build_GetResourceLimits
+ *
+ * DESCRIPTION:
+ * Retrieve Resource Limits from ProcessingParams and initialize them in
+ * BuildConstants.
+ *
+ * PARAMETERS
+ * "buildConstants"
+ * Address of a BuildConstants structure containing objects and values
+ * that remain constant throughout the building of a chain. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_Build_GetResourceLimits(
+ BuildConstants *buildConstants,
+ void *plContext)
+{
+ PKIX_ResourceLimits *resourceLimits = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_GetResourceLimits");
+ PKIX_NULLCHECK_ONE(buildConstants);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetResourceLimits
+ (buildConstants->procParams, &resourceLimits, plContext),
+ PKIX_PROCESSINGPARAMSGETRESOURCELIMITSFAILED);
+
+ buildConstants->maxFanout = 0;
+ buildConstants->maxDepth = 0;
+ buildConstants->maxTime = 0;
+
+ if (resourceLimits) {
+
+ PKIX_CHECK(PKIX_ResourceLimits_GetMaxFanout
+ (resourceLimits, &buildConstants->maxFanout, plContext),
+ PKIX_RESOURCELIMITSGETMAXFANOUTFAILED);
+
+ PKIX_CHECK(PKIX_ResourceLimits_GetMaxDepth
+ (resourceLimits, &buildConstants->maxDepth, plContext),
+ PKIX_RESOURCELIMITSGETMAXDEPTHFAILED);
+
+ PKIX_CHECK(PKIX_ResourceLimits_GetMaxTime
+ (resourceLimits, &buildConstants->maxTime, plContext),
+ PKIX_RESOURCELIMITSGETMAXTIMEFAILED);
+ }
+
+cleanup:
+
+ PKIX_DECREF(resourceLimits);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_ForwardBuilderState_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_ForwardBuilderState_ToString
+ (PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_ForwardBuilderState *state = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *resultString = NULL;
+ PKIX_PL_String *buildStatusString = NULL;
+ PKIX_PL_String *validityDateString = NULL;
+ PKIX_PL_String *prevCertString = NULL;
+ PKIX_PL_String *candidateCertString = NULL;
+ PKIX_PL_String *traversedSubjNamesString = NULL;
+ PKIX_PL_String *trustChainString = NULL;
+ PKIX_PL_String *candidateCertsString = NULL;
+ PKIX_PL_String *certSelString = NULL;
+ PKIX_PL_String *verifyNodeString = NULL;
+ PKIX_PL_String *parentStateString = NULL;
+ char *asciiFormat = "\n"
+ "\t{buildStatus: \t%s\n"
+ "\ttraversedCACerts: \t%d\n"
+ "\tcertStoreIndex: \t%d\n"
+ "\tnumCerts: \t%d\n"
+ "\tnumAias: \t%d\n"
+ "\tcertIndex: \t%d\n"
+ "\taiaIndex: \t%d\n"
+ "\tnumFanout: \t%d\n"
+ "\tnumDepth: \t%d\n"
+ "\treasonCode: \t%d\n"
+ "\tcanBeCached: \t%d\n"
+ "\tuseOnlyLocal: \t%d\n"
+ "\trevChecking: \t%d\n"
+ "\tvalidityDate: \t%s\n"
+ "\tprevCert: \t%s\n"
+ "\tcandidateCert: \t%s\n"
+ "\ttraversedSubjNames: \t%s\n"
+ "\ttrustChain: \t%s\n"
+ "\tcandidateCerts: \t%s\n"
+ "\tcertSel: \t%s\n"
+ "\tverifyNode: \t%s\n"
+ "\tparentState: \t%s}\n";
+ char *asciiStatus = NULL;
+
+ PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext),
+ PKIX_OBJECTNOTFORWARDBUILDERSTATE);
+
+ state = (PKIX_ForwardBuilderState *)object;
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ switch (state->status) {
+ case BUILD_SHORTCUTPENDING: asciiStatus = "BUILD_SHORTCUTPENDING";
+ break;
+ case BUILD_INITIAL: asciiStatus = "BUILD_INITIAL";
+ break;
+ case BUILD_TRYAIA: asciiStatus = "BUILD_TRYAIA";
+ break;
+ case BUILD_AIAPENDING: asciiStatus = "BUILD_AIAPENDING";
+ break;
+ case BUILD_COLLECTINGCERTS: asciiStatus = "BUILD_COLLECTINGCERTS";
+ break;
+ case BUILD_GATHERPENDING: asciiStatus = "BUILD_GATHERPENDING";
+ break;
+ case BUILD_CERTVALIDATING: asciiStatus = "BUILD_CERTVALIDATING";
+ break;
+ case BUILD_ABANDONNODE: asciiStatus = "BUILD_ABANDONNODE";
+ break;
+ case BUILD_DATEPREP: asciiStatus = "BUILD_DATEPREP";
+ break;
+ case BUILD_CHECKTRUSTED: asciiStatus = "BUILD_CHECKTRUSTED";
+ break;
+ case BUILD_CHECKTRUSTED2: asciiStatus = "BUILD_CHECKTRUSTED2";
+ break;
+ case BUILD_ADDTOCHAIN: asciiStatus = "BUILD_ADDTOCHAIN";
+ break;
+ case BUILD_VALCHAIN: asciiStatus = "BUILD_VALCHAIN";
+ break;
+ case BUILD_VALCHAIN2: asciiStatus = "BUILD_VALCHAIN2";
+ break;
+ case BUILD_EXTENDCHAIN: asciiStatus = "BUILD_EXTENDCHAIN";
+ break;
+ case BUILD_GETNEXTCERT: asciiStatus = "BUILD_GETNEXTCERT";
+ break;
+ default: asciiStatus = "INVALID STATUS";
+ break;
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiStatus, 0, &buildStatusString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_TOSTRING
+ (state->validityDate, &validityDateString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->prevCert, &prevCertString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->candidateCert, &candidateCertString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->traversedSubjNames,
+ &traversedSubjNamesString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->trustChain, &trustChainString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->candidateCerts, &candidateCertsString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->certSel, &certSelString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->verifyNode, &verifyNodeString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (state->parentState, &parentStateString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&resultString,
+ plContext,
+ formatString,
+ buildStatusString,
+ (PKIX_Int32)state->traversedCACerts,
+ (PKIX_UInt32)state->certStoreIndex,
+ (PKIX_UInt32)state->numCerts,
+ (PKIX_UInt32)state->numAias,
+ (PKIX_UInt32)state->certIndex,
+ (PKIX_UInt32)state->aiaIndex,
+ (PKIX_UInt32)state->numFanout,
+ (PKIX_UInt32)state->numDepth,
+ (PKIX_UInt32)state->reasonCode,
+ state->canBeCached,
+ state->useOnlyLocal,
+ state->revChecking,
+ validityDateString,
+ prevCertString,
+ candidateCertString,
+ traversedSubjNamesString,
+ trustChainString,
+ candidateCertsString,
+ certSelString,
+ verifyNodeString,
+ parentStateString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = resultString;
+
+cleanup:
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(buildStatusString);
+ PKIX_DECREF(validityDateString);
+ PKIX_DECREF(prevCertString);
+ PKIX_DECREF(candidateCertString);
+ PKIX_DECREF(traversedSubjNamesString);
+ PKIX_DECREF(trustChainString);
+ PKIX_DECREF(candidateCertsString);
+ PKIX_DECREF(certSelString);
+ PKIX_DECREF(verifyNodeString);
+ PKIX_DECREF(parentStateString);
+
+ PKIX_RETURN(FORWARDBUILDERSTATE);
+
+}
+
+/*
+ * FUNCTION: pkix_ForwardBuilderState_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_FORWARDBUILDERSTATE_TYPE and its related functions
+ * with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_ForwardBuilderState_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(FORWARDBUILDERSTATE,
+ "pkix_ForwardBuilderState_RegisterSelf");
+
+ entry.description = "ForwardBuilderState";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_ForwardBuilderState);
+ entry.destructor = pkix_ForwardBuilderState_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = pkix_ForwardBuilderState_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_FORWARDBUILDERSTATE_TYPE] = entry;
+
+ PKIX_RETURN(FORWARDBUILDERSTATE);
+}
+
+#if PKIX_FORWARDBUILDERSTATEDEBUG
+/*
+ * FUNCTION: pkix_ForwardBuilderState_DumpState
+ *
+ * DESCRIPTION:
+ * This function invokes the ToString function on the argument pointed to
+ * by "state".
+ * PARAMETERS:
+ * "state"
+ * The address of the ForwardBuilderState object. Must be non-NULL.
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ */
+PKIX_Error *
+pkix_ForwardBuilderState_DumpState(
+ PKIX_ForwardBuilderState *state,
+ void *plContext)
+{
+ PKIX_PL_String *stateString = NULL;
+ char *stateAscii = NULL;
+ PKIX_UInt32 length;
+
+ PKIX_ENTER(FORWARDBUILDERSTATE,"pkix_ForwardBuilderState_DumpState");
+ PKIX_NULLCHECK_ONE(state);
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)state, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)state, &stateString, plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stateString,
+ PKIX_ESCASCII,
+ (void **)&stateAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_DEBUG_ARG("In Phase 1: state = %s\n", stateAscii);
+
+ PKIX_FREE(stateAscii);
+ PKIX_DECREF(stateString);
+
+cleanup:
+ PKIX_RETURN(FORWARDBUILDERSTATE);
+}
+#endif
+
+/*
+ * FUNCTION: pkix_ForwardBuilderState_IsIOPending
+ * DESCRIPTION:
+ *
+ * This function determines whether the state of the ForwardBuilderState
+ * pointed to by "state" indicates I/O is in progress, and stores the Boolean
+ * result at "pPending".
+ *
+ * PARAMETERS:
+ * "state"
+ * The address of the ForwardBuilderState object. Must be non-NULL.
+ * "pPending"
+ * The address at which the result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a ForwardBuilderState Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error*
+pkix_ForwardBuilderState_IsIOPending(
+ PKIX_ForwardBuilderState *state,
+ PKIX_Boolean *pPending,
+ void *plContext)
+{
+ PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_IsIOPending");
+ PKIX_NULLCHECK_TWO(state, pPending);
+
+ if ((state->status == BUILD_GATHERPENDING) ||
+ (state->status == BUILD_CHECKTRUSTED2) ||
+ (state->status == BUILD_VALCHAIN2) ||
+ (state->status == BUILD_AIAPENDING)) {
+ *pPending = PKIX_TRUE;
+ } else {
+ *pPending = PKIX_FALSE;
+ }
+
+ PKIX_RETURN(FORWARDBUILDERSTATE);
+}
+
+/* --Private-BuildChain-Functions------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_Build_SortCertComparator
+ * DESCRIPTION:
+ *
+ * This Function takes two Certificates cast in "obj1" and "obj2",
+ * compares them to determine which is a more preferable certificate
+ * for chain building. This Function is suitable for use as a
+ * comparator callback for pkix_List_BubbleSort, setting "*pResult" to
+ * > 0 if "obj1" is less desirable than "obj2" and < 0 if "obj1"
+ * is more desirable than "obj2".
+ *
+ * PARAMETERS:
+ * "obj1"
+ * Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert.
+ * Must be non-NULL.
+ * "obj2"
+ * Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert.
+ * Must be non-NULL.
+ * "pResult"
+ * Address where the comparison result is returned. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_Build_SortCertComparator(
+ PKIX_PL_Object *obj1,
+ PKIX_PL_Object *obj2,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_PL_Date *date1 = NULL;
+ PKIX_PL_Date *date2 = NULL;
+ PKIX_Int32 result = 0;
+
+ PKIX_ENTER(BUILD, "pkix_Build_SortCertComparator");
+ PKIX_NULLCHECK_THREE(obj1, obj2, pResult);
+
+ /*
+ * For sorting candidate certificates, we use NotAfter date as the
+ * comparison key for now (can be expanded if desired in the future).
+ *
+ * In PKIX_BuildChain, the List of CertStores was reordered so that
+ * trusted CertStores are ahead of untrusted CertStores. That sort, or
+ * this one, could be taken out if it is determined that it doesn't help
+ * performance, or in some way hinders the solution of choosing desired
+ * candidates.
+ */
+
+ PKIX_CHECK(pkix_CheckType(obj1, PKIX_CERT_TYPE, plContext),
+ PKIX_OBJECTNOTCERT);
+ PKIX_CHECK(pkix_CheckType(obj2, PKIX_CERT_TYPE, plContext),
+ PKIX_OBJECTNOTCERT);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
+ ((PKIX_PL_Cert *)obj1, &date1, plContext),
+ PKIX_CERTGETVALIDITYNOTAFTERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
+ ((PKIX_PL_Cert *)obj2, &date2, plContext),
+ PKIX_CERTGETVALIDITYNOTAFTERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)date1,
+ (PKIX_PL_Object *)date2,
+ &result,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+
+ /*
+ * Invert the result, so that if date1 is greater than date2,
+ * obj1 is sorted before obj2. This is because pkix_List_BubbleSort
+ * sorts in ascending order.
+ */
+ *pResult = -result;
+
+cleanup:
+
+ PKIX_DECREF(date1);
+ PKIX_DECREF(date2);
+
+ PKIX_RETURN(BUILD);
+}
+
+/* This local error check macro */
+#define ERROR_CHECK(errCode) \
+ if (pkixErrorResult) { \
+ if (pkixLog) { \
+ PR_LOG(pkixLog, PR_LOG_DEBUG, ("====> ERROR_CHECK code %s\n", #errCode)); \
+ } \
+ pkixTempErrorReceived = PKIX_TRUE; \
+ pkixErrorClass = pkixErrorResult->errClass; \
+ if (pkixErrorClass == PKIX_FATAL_ERROR) { \
+ goto cleanup; \
+ } \
+ if (verifyNode) { \
+ PKIX_DECREF(verifyNode->error); \
+ PKIX_INCREF(pkixErrorResult); \
+ verifyNode->error = pkixErrorResult; \
+ } \
+ pkixErrorCode = errCode; \
+ goto cleanup; \
+ }
+
+/*
+ * FUNCTION: pkix_Build_VerifyCertificate
+ * DESCRIPTION:
+ *
+ * Checks whether the previous Cert stored in the ForwardBuilderState pointed
+ * to by "state" successfully chains, including signature verification, to the
+ * candidate Cert also stored in "state", using the Boolean value in "trusted"
+ * to determine whether "candidateCert" is trusted.
+ *
+ * First it checks whether "candidateCert" has already been traversed by
+ * determining whether it is contained in the List of traversed Certs. It then
+ * checks the candidate Cert with user checkers, if any, in the List pointed to
+ * by "userCheckers". Finally, it runs the signature validation.
+ *
+ * If this Certificate fails verification, and state->verifyNode is non-NULL,
+ * this function sets the Error code into the verifyNode.
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. Must be non-NULL.
+ * "userCheckers"
+ * Address of a List of CertChainCheckers to be used, if present, to
+ * validate the candidateCert.
+ * "trusted"
+ * Boolean value of trust for the candidate Cert
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_Build_VerifyCertificate(
+ PKIX_ForwardBuilderState *state,
+ PKIX_List *userCheckers,
+ PKIX_Boolean *pTrusted,
+ PKIX_VerifyNode *verifyNode,
+ void *plContext)
+{
+ PKIX_UInt32 numUserCheckers = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_Boolean loopFound = PKIX_FALSE;
+ PKIX_Boolean supportForwardChecking = PKIX_FALSE;
+ PKIX_Boolean trusted = PKIX_FALSE;
+ PKIX_PL_Cert *candidateCert = NULL;
+ PKIX_PL_PublicKey *candidatePubKey = NULL;
+ PKIX_CertChainChecker *userChecker = NULL;
+ PKIX_CertChainChecker_CheckCallback checkerCheck = NULL;
+ PKIX_PL_TrustAnchorMode trustAnchorMode =
+ PKIX_PL_TrustAnchorMode_Ignore;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_VerifyCertificate");
+ PKIX_NULLCHECK_TWO(state, pTrusted);
+ PKIX_NULLCHECK_THREE
+ (state->candidateCerts, state->prevCert, state->trustChain);
+
+ PKIX_INCREF(state->candidateCert);
+ candidateCert = state->candidateCert;
+
+ if (state->buildConstants.numAnchors) {
+ if (state->buildConstants.trustOnlyUserAnchors) {
+ trustAnchorMode = PKIX_PL_TrustAnchorMode_Exclusive;
+ } else {
+ trustAnchorMode = PKIX_PL_TrustAnchorMode_Additive;
+ }
+ } else {
+ trustAnchorMode = PKIX_PL_TrustAnchorMode_Ignore;
+ }
+
+ PKIX_CHECK(
+ PKIX_PL_Cert_IsCertTrusted(candidateCert, trustAnchorMode,
+ &trusted, plContext),
+ PKIX_CERTISCERTTRUSTEDFAILED);
+
+ *pTrusted = trusted;
+
+ /* check for loops */
+ PKIX_CHECK(pkix_List_Contains
+ (state->trustChain,
+ (PKIX_PL_Object *)candidateCert,
+ &loopFound,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ if (loopFound) {
+ if (verifyNode != NULL) {
+ PKIX_Error *verifyError = NULL;
+ PKIX_ERROR_CREATE
+ (BUILD,
+ PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED,
+ verifyError);
+ PKIX_DECREF(verifyNode->error);
+ verifyNode->error = verifyError;
+ }
+ /* Even if error logged, still need to abort
+ * if cert is not trusted. */
+ if (!trusted) {
+ PKIX_ERROR(PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED);
+ }
+ state->certLoopingDetected = PKIX_TRUE;
+ }
+
+ if (userCheckers != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (userCheckers, &numUserCheckers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numUserCheckers; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (userCheckers,
+ i,
+ (PKIX_PL_Object **) &userChecker,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK
+ (PKIX_CertChainChecker_IsForwardCheckingSupported
+ (userChecker, &supportForwardChecking, plContext),
+ PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
+
+ if (supportForwardChecking == PKIX_TRUE) {
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback
+ (userChecker, &checkerCheck, plContext),
+ PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED);
+
+ pkixErrorResult =
+ checkerCheck(userChecker, candidateCert, NULL,
+ &nbioContext, plContext);
+
+ ERROR_CHECK(PKIX_USERCHECKERCHECKFAILED);
+ }
+
+ PKIX_DECREF(userChecker);
+ }
+ }
+
+ /* Check that public key of the trusted dsa cert has
+ * dsa parameters */
+ if (trusted) {
+ PKIX_Boolean paramsNeeded = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (candidateCert, &candidatePubKey, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+ PKIX_CHECK(PKIX_PL_PublicKey_NeedsDSAParameters
+ (candidatePubKey, &paramsNeeded, plContext),
+ PKIX_PUBLICKEYNEEDSDSAPARAMETERSFAILED);
+ if (paramsNeeded) {
+ PKIX_ERROR(PKIX_MISSINGDSAPARAMETERS);
+ }
+ }
+
+cleanup:
+ PKIX_DECREF(candidateCert);
+ PKIX_DECREF(candidatePubKey);
+ PKIX_DECREF(userChecker);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_ValidationCheckers
+ * DESCRIPTION:
+ *
+ * Creates a List of Objects to be used in determining whether the List of
+ * Certs pointed to by "certChain" successfully validates using the
+ * ForwardBuilderState pointed to by "state", and the TrustAnchor pointed to by
+ * "anchor". These objects are a reversed Cert Chain, consisting of the certs
+ * in "certChain" in reversed order, suitable for presenting to the
+ * CertChainCheckers; a List of critical extension OIDS that have already been
+ * processed in forward building; a List of CertChainCheckers to be called, and
+ * a List of RevocationCheckers to be called. These results are stored in
+ * fields of "state".
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. Must be non-NULL.
+ * "certChain"
+ * Address of List of Certs to be validated. Must be non-NULL.
+ * "anchor"
+ * Address of TrustAnchor to be used. Must be non-NULL.
+ * "addEkuChecker"
+ * Boolean flags that tells to add eku checker to the list
+ * of checkers. Only needs to be done for existing chain revalidation.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_Build_ValidationCheckers(
+ PKIX_ForwardBuilderState *state,
+ PKIX_List *certChain,
+ PKIX_TrustAnchor *anchor,
+ PKIX_Boolean chainRevalidationStage,
+ void *plContext)
+{
+ PKIX_List *checkers = NULL;
+ PKIX_List *initialPolicies = NULL;
+ PKIX_List *reversedCertChain = NULL;
+ PKIX_List *buildCheckedCritExtOIDsList = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_PublicKey *trustedPubKey = NULL;
+ PKIX_PL_CertNameConstraints *trustedNC = NULL;
+ PKIX_CertChainChecker *sigChecker = NULL;
+ PKIX_CertChainChecker *policyChecker = NULL;
+ PKIX_CertChainChecker *userChecker = NULL;
+ PKIX_CertChainChecker *nameConstraintsChecker = NULL;
+ PKIX_CertChainChecker *checker = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *userCheckerExtOIDs = NULL;
+ PKIX_PL_OID *oid = NULL;
+ PKIX_Boolean supportForwardChecking = PKIX_FALSE;
+ PKIX_Boolean policyQualifiersRejected = PKIX_FALSE;
+ PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
+ PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
+ PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
+ PKIX_UInt32 numChainCerts;
+ PKIX_UInt32 numCertCheckers;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(BUILD, "pkix_Build_ValidationCheckers");
+ PKIX_NULLCHECK_THREE(state, certChain, anchor);
+
+ PKIX_CHECK(PKIX_List_Create(&checkers, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_ReverseList
+ (certChain, &reversedCertChain, plContext),
+ PKIX_LISTREVERSELISTFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (reversedCertChain, &numChainCerts, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ procParams = state->buildConstants.procParams;
+
+ /* Do need to add a number of checker to revalidate
+ * a built chain. KU, EKU, CertType and Validity Date
+ * get checked by certificate selector during chain
+ * construction, but needed to be checked for chain from
+ * the cache.*/
+ if (chainRevalidationStage) {
+ PKIX_CHECK(pkix_ExpirationChecker_Initialize
+ (state->buildConstants.testDate, &checker, plContext),
+ PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)checker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(checker);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
+ (procParams, &certSelector, plContext),
+ PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
+
+ PKIX_CHECK(pkix_TargetCertChecker_Initialize
+ (certSelector, numChainCerts, &checker, plContext),
+ PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)checker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(checker);
+ }
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies
+ (procParams, &initialPolicies, plContext),
+ PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected
+ (procParams, &policyQualifiersRejected, plContext),
+ PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited
+ (procParams, &initialPolicyMappingInhibit, plContext),
+ PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited
+ (procParams, &initialAnyPolicyInhibit, plContext),
+ PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired
+ (procParams, &initialExplicitPolicy, plContext),
+ PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_Initialize
+ (initialPolicies,
+ policyQualifiersRejected,
+ initialPolicyMappingInhibit,
+ initialExplicitPolicy,
+ initialAnyPolicyInhibit,
+ numChainCerts,
+ &policyChecker,
+ plContext),
+ PKIX_POLICYCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)policyChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ /*
+ * Create an OID list that contains critical extensions processed
+ * by BuildChain. These are specified in a static const array.
+ */
+ PKIX_CHECK(PKIX_List_Create(&buildCheckedCritExtOIDsList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ for (i = 0; buildCheckedCritExtOIDs[i] != PKIX_UNKNOWN_OID; i++) {
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (buildCheckedCritExtOIDs[i], &oid, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (buildCheckedCritExtOIDsList,
+ (PKIX_PL_Object *) oid,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(oid);
+ }
+
+ if (state->buildConstants.userCheckers != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->buildConstants.userCheckers,
+ &numCertCheckers,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numCertCheckers; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->buildConstants.userCheckers,
+ i,
+ (PKIX_PL_Object **) &userChecker,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK
+ (PKIX_CertChainChecker_IsForwardCheckingSupported
+ (userChecker, &supportForwardChecking, plContext),
+ PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
+
+ /*
+ * If this userChecker supports forwardChecking then it
+ * should have been checked during build chain. Skip
+ * checking but need to add checker's extension OIDs
+ * to buildCheckedCritExtOIDsList.
+ */
+ if (supportForwardChecking == PKIX_TRUE) {
+
+ PKIX_CHECK
+ (PKIX_CertChainChecker_GetSupportedExtensions
+ (userChecker, &userCheckerExtOIDs, plContext),
+ PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
+
+ if (userCheckerExtOIDs != NULL) {
+ PKIX_CHECK(pkix_List_AppendList
+ (buildCheckedCritExtOIDsList,
+ userCheckerExtOIDs,
+ plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ }
+
+ } else {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers,
+ (PKIX_PL_Object *)userChecker,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ PKIX_DECREF(userCheckerExtOIDs);
+ PKIX_DECREF(userChecker);
+ }
+ }
+
+ /* Enabling post chain building signature check on the certs. */
+ PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
+ (anchor, &trustedCert, plContext),
+ PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (trustedCert, &trustedPubKey, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+
+ PKIX_CHECK(pkix_SignatureChecker_Initialize
+ (trustedPubKey,
+ numChainCerts,
+ &sigChecker,
+ plContext),
+ PKIX_SIGNATURECHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers,
+ (PKIX_PL_Object *)sigChecker,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ /* Enabling post chain building name constraints check on the certs. */
+ PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints
+ (anchor, &trustedNC, plContext),
+ PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED);
+
+ PKIX_CHECK(pkix_NameConstraintsChecker_Initialize
+ (trustedNC, numChainCerts, &nameConstraintsChecker,
+ plContext),
+ PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers,
+ (PKIX_PL_Object *)nameConstraintsChecker,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+
+ PKIX_DECREF(state->reversedCertChain);
+ PKIX_INCREF(reversedCertChain);
+ state->reversedCertChain = reversedCertChain;
+ PKIX_DECREF(state->checkedCritExtOIDs);
+ PKIX_INCREF(buildCheckedCritExtOIDsList);
+ state->checkedCritExtOIDs = buildCheckedCritExtOIDsList;
+ PKIX_DECREF(state->checkerChain);
+ state->checkerChain = checkers;
+ checkers = NULL;
+ state->certCheckedIndex = 0;
+ state->checkerIndex = 0;
+ state->revChecking = PKIX_FALSE;
+
+
+cleanup:
+
+ PKIX_DECREF(oid);
+ PKIX_DECREF(reversedCertChain);
+ PKIX_DECREF(buildCheckedCritExtOIDsList);
+ PKIX_DECREF(checker);
+ PKIX_DECREF(checkers);
+ PKIX_DECREF(initialPolicies);
+ PKIX_DECREF(trustedCert);
+ PKIX_DECREF(trustedPubKey);
+ PKIX_DECREF(certSelector);
+ PKIX_DECREF(sigChecker);
+ PKIX_DECREF(trustedNC);
+ PKIX_DECREF(nameConstraintsChecker);
+ PKIX_DECREF(policyChecker);
+ PKIX_DECREF(userChecker);
+ PKIX_DECREF(userCheckerExtOIDs);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_ValidateEntireChain
+ * DESCRIPTION:
+ *
+ * Checks whether the current List of Certs successfully validates using the
+ * TrustAnchor pointed to by "anchor" and other parameters contained, as was
+ * the Cert List, in "state".
+ *
+ * If a checker using non-blocking I/O returns with a non-NULL non-blocking I/O
+ * context (NBIOContext), an indication that I/O is in progress and the
+ * checking has not been completed, this function stores that context at
+ * "pNBIOContext". Otherwise, it stores NULL at "pNBIOContext".
+ *
+ * If not awaiting I/O and if successful, a ValidateResult is created
+ * containing the Public Key of the target certificate (including DSA parameter
+ * inheritance, if any) and the PolicyNode representing the policy tree output
+ * by the validation algorithm. If not successful, an Error pointer is
+ * returned.
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. Must be non-NULL.
+ * "anchor"
+ * Address of TrustAnchor to be used. Must be non-NULL.
+ * "pNBIOContext"
+ * Address at which the NBIOContext is stored indicating whether the
+ * validation is complete. Must be non-NULL.
+ * "pValResult"
+ * Address at which the ValidateResult is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_Build_ValidateEntireChain(
+ PKIX_ForwardBuilderState *state,
+ PKIX_TrustAnchor *anchor,
+ void **pNBIOContext,
+ PKIX_ValidateResult **pValResult,
+ PKIX_VerifyNode *verifyNode,
+ void *plContext)
+{
+ PKIX_UInt32 numChainCerts = 0;
+ PKIX_PL_PublicKey *subjPubKey = NULL;
+ PKIX_PolicyNode *policyTree = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_ValidateEntireChain");
+ PKIX_NULLCHECK_FOUR(state, anchor, pNBIOContext, pValResult);
+
+ *pNBIOContext = NULL; /* prepare for case of error exit */
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->reversedCertChain, &numChainCerts, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ pkixErrorResult =
+ pkix_CheckChain(state->reversedCertChain, numChainCerts, anchor,
+ state->checkerChain,
+ state->buildConstants.revChecker,
+ state->checkedCritExtOIDs,
+ state->buildConstants.procParams,
+ &state->certCheckedIndex, &state->checkerIndex,
+ &state->revChecking, &state->reasonCode,
+ &nbioContext, &subjPubKey, &policyTree, NULL,
+ plContext);
+
+ if (nbioContext != NULL) {
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ ERROR_CHECK(PKIX_CHECKCHAINFAILED);
+
+ /* XXX Remove this assertion after 2014-12-31. See bug 946984. */
+ PORT_Assert(state->reasonCode == 0);
+
+ PKIX_CHECK(pkix_ValidateResult_Create
+ (subjPubKey, anchor, policyTree, &valResult, plContext),
+ PKIX_VALIDATERESULTCREATEFAILED);
+
+ *pValResult = valResult;
+ valResult = NULL;
+
+cleanup:
+ PKIX_DECREF(subjPubKey);
+ PKIX_DECREF(policyTree);
+ PKIX_DECREF(valResult);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_SortCandidateCerts
+ * DESCRIPTION:
+ *
+ * This function sorts a List of candidate Certs pointed to by "candidates"
+ * using an algorithm that places Certs most likely to produce a successful
+ * chain at the front of the list, storing the resulting sorted List at
+ * "pSortedCandidates".
+ *
+ * At present the only sort criterion is that trusted Certs go ahead of
+ * untrusted Certs.
+ *
+ * PARAMETERS:
+ * "candidates"
+ * Address of List of Candidate Certs to be sorted. Must be non-NULL.
+ * "pSortedCandidates"
+ * Address at which sorted List is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_Build_SortCandidateCerts(
+ PKIX_List *candidates,
+ PKIX_List **pSortedCandidates,
+ void *plContext)
+{
+ PKIX_List *sortedList = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_SortCandidateCerts");
+ PKIX_NULLCHECK_TWO(candidates, pSortedCandidates);
+
+ /*
+ * Both bubble and quick sort algorithms are available.
+ * For a list of fewer than around 100 items, the bubble sort is more
+ * efficient. (This number was determined by experimenting with both
+ * algorithms on a Java List.)
+ * If the candidate list is very small, using the sort can drag down
+ * the performance a little bit.
+ */
+
+ PKIX_CHECK(pkix_List_BubbleSort
+ (candidates,
+ pkix_Build_SortCertComparator,
+ &sortedList,
+ plContext),
+ PKIX_LISTBUBBLESORTFAILED);
+
+ *pSortedCandidates = sortedList;
+
+cleanup:
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_BuildSelectorAndParams
+ * DESCRIPTION:
+ *
+ * This function creates a CertSelector, initialized with an appropriate
+ * ComCertSelParams, using the variables provided in the ForwardBuilderState
+ * pointed to by "state". The CertSelector created is stored in the certsel
+ * element of "state".
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_Build_BuildSelectorAndParams(
+ PKIX_ForwardBuilderState *state,
+ void *plContext)
+{
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSel = NULL;
+ PKIX_PL_X500Name *currentIssuer = NULL;
+ PKIX_PL_ByteArray *authKeyId = NULL;
+ PKIX_PL_Date *testDate = NULL;
+ PKIX_CertSelector *callerCertSelector = NULL;
+ PKIX_ComCertSelParams *callerComCertSelParams = NULL;
+ PKIX_UInt32 reqKu = 0;
+ PKIX_List *reqEkuOids = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_BuildSelectorAndParams");
+ PKIX_NULLCHECK_THREE(state, state->prevCert, state->traversedSubjNames);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetIssuer
+ (state->prevCert, &currentIssuer, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier
+ (state->prevCert, &authKeyId, plContext),
+ PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_Create(&certSelParams, plContext),
+ PKIX_COMCERTSELPARAMSCREATEFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_SetSubject
+ (certSelParams, currentIssuer, plContext),
+ PKIX_COMCERTSELPARAMSSETSUBJECTFAILED);
+
+ if (authKeyId != NULL) {
+ PKIX_CHECK(PKIX_ComCertSelParams_SetSubjKeyIdentifier
+ (certSelParams, authKeyId, plContext),
+ PKIX_COMCERTSELPARAMSSETSUBJKEYIDENTIFIERFAILED);
+ }
+
+ PKIX_INCREF(state->buildConstants.testDate);
+ testDate = state->buildConstants.testDate;
+
+ PKIX_CHECK(PKIX_ComCertSelParams_SetCertificateValid
+ (certSelParams, testDate, plContext),
+ PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_SetBasicConstraints
+ (certSelParams, state->traversedCACerts, plContext),
+ PKIX_COMCERTSELPARAMSSETBASICCONSTRAINTSFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_SetPathToNames
+ (certSelParams, state->traversedSubjNames, plContext),
+ PKIX_COMCERTSELPARAMSSETPATHTONAMESFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
+ (state->buildConstants.procParams,
+ &callerCertSelector, plContext),
+ PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
+
+ if (callerCertSelector != NULL) {
+
+ /* Get initial EKU OIDs from ComCertSelParams, if set */
+ PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
+ (callerCertSelector, &callerComCertSelParams, plContext),
+ PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
+
+ if (callerComCertSelParams != NULL) {
+ PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
+ (callerComCertSelParams, &reqEkuOids, plContext),
+ PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetKeyUsage
+ (callerComCertSelParams, &reqKu, plContext),
+ PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
+ }
+ }
+
+ PKIX_CHECK(
+ PKIX_ComCertSelParams_SetKeyUsage(certSelParams, reqKu,
+ plContext),
+ PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED);
+
+ PKIX_CHECK(
+ PKIX_ComCertSelParams_SetExtendedKeyUsage(certSelParams,
+ reqEkuOids,
+ plContext),
+ PKIX_COMCERTSELPARAMSSETEXTKEYUSAGEFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_Create
+ (NULL, NULL, &state->certSel, plContext),
+ PKIX_CERTSELECTORCREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
+ (state->certSel, certSelParams, plContext),
+ PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&state->candidateCerts, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ state->certStoreIndex = 0;
+
+cleanup:
+ PKIX_DECREF(certSelParams);
+ PKIX_DECREF(certSel);
+ PKIX_DECREF(currentIssuer);
+ PKIX_DECREF(authKeyId);
+ PKIX_DECREF(testDate);
+ PKIX_DECREF(reqEkuOids);
+ PKIX_DECREF(callerComCertSelParams);
+ PKIX_DECREF(callerCertSelector);
+
+ PKIX_RETURN(BUILD);
+}
+
+/* Match trust anchor to select params in order to find next cert. */
+static PKIX_Error*
+pkix_Build_SelectCertsFromTrustAnchors(
+ PKIX_List *trustAnchorsList,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_List **pMatchList,
+ void *plContext)
+{
+ unsigned int anchorIndex = 0;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_List *matchList = NULL;
+ PKIX_CertSelector *certSel = NULL;
+ PKIX_CertSelector_MatchCallback selectorMatchCB = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_SelectCertsFromTrustAnchors");
+
+ PKIX_CHECK(PKIX_CertSelector_Create
+ (NULL, NULL, &certSel, plContext),
+ PKIX_CERTSELECTORCREATEFAILED);
+ PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSel, certSelParams, plContext),
+ PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
+ PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
+ (certSel, &selectorMatchCB, plContext),
+ PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
+
+ for (anchorIndex = 0;anchorIndex < trustAnchorsList->length; anchorIndex++) {
+ PKIX_CHECK(
+ PKIX_List_GetItem(trustAnchorsList,
+ anchorIndex,
+ (PKIX_PL_Object **)&anchor,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+ PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
+ (anchor, &trustedCert, plContext),
+ PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
+ pkixErrorResult =
+ (*selectorMatchCB)(certSel, trustedCert, plContext);
+ if (!pkixErrorResult) {
+ if (!matchList) {
+ PKIX_CHECK(PKIX_List_Create(&matchList,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+ PKIX_CHECK(
+ PKIX_List_AppendItem(matchList,
+ (PKIX_PL_Object*)trustedCert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ } else {
+ PKIX_DECREF(pkixErrorResult);
+ }
+ PKIX_DECREF(trustedCert);
+ PKIX_DECREF(anchor);
+ }
+
+ *pMatchList = matchList;
+ matchList = NULL;
+
+cleanup:
+ PKIX_DECREF(matchList);
+ PKIX_DECREF(trustedCert);
+ PKIX_DECREF(anchor);
+ PKIX_DECREF(certSel);
+
+ PKIX_RETURN(BUILD);
+}
+
+
+static PKIX_Error*
+pkix_Build_RemoveDupUntrustedCerts(
+ PKIX_List *trustedCertList,
+ PKIX_List *certsFound,
+ void *plContext)
+{
+ PKIX_UInt32 trustIndex;
+ PKIX_PL_Cert *trustCert = NULL, *cert = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_RemoveDupUntrustedCerts");
+ if (trustedCertList == NULL || certsFound == NULL) {
+ goto cleanup;
+ }
+ for (trustIndex = 0;trustIndex < trustedCertList->length;
+ trustIndex++) {
+ PKIX_UInt32 certIndex = 0;
+ PKIX_CHECK(
+ PKIX_List_GetItem(trustedCertList,
+ trustIndex,
+ (PKIX_PL_Object **)&trustCert,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ while (certIndex < certsFound->length) {
+ PKIX_Boolean result = PKIX_FALSE;
+ PKIX_DECREF(cert);
+ PKIX_CHECK(
+ PKIX_List_GetItem(certsFound, certIndex,
+ (PKIX_PL_Object **)&cert,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+ PKIX_CHECK(
+ PKIX_PL_Object_Equals((PKIX_PL_Object *)trustCert,
+ (PKIX_PL_Object *)cert,
+ &result,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+ if (!result) {
+ certIndex += 1;
+ continue;
+ }
+ PKIX_CHECK(
+ PKIX_List_DeleteItem(certsFound, certIndex,
+ plContext),
+ PKIX_LISTDELETEITEMFAILED);
+ }
+ PKIX_DECREF(trustCert);
+ }
+cleanup:
+ PKIX_DECREF(cert);
+ PKIX_DECREF(trustCert);
+
+ PKIX_RETURN(BUILD);
+}
+
+
+/*
+ * FUNCTION: pkix_Build_GatherCerts
+ * DESCRIPTION:
+ *
+ * This function traverses the CertStores in the List of CertStores contained
+ * in "state", using the certSelector and other parameters contained in
+ * "state", to obtain a List of all available Certs that satisfy the criteria.
+ * If a CertStore has a cache, "certSelParams" is used both to query the cache
+ * and, if an actual CertStore search occurred, to update the cache. (Behavior
+ * is undefined if "certSelParams" is different from the parameters that were
+ * used to initialize the certSelector in "state".)
+ *
+ * If a CertStore using non-blocking I/O returns with an indication that I/O is
+ * in progress and the checking has not been completed, this function stores
+ * platform-dependent information at "pNBIOContext". Otherwise it stores NULL
+ * at "pNBIOContext", and state is updated with the results of the search.
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. Must be non-NULL.
+ * "certSelParams"
+ * Address of ComCertSelParams which were used in creating the current
+ * CertSelector, and to be used in querying and updating any caches that
+ * may be associated with with the CertStores.
+ * "pNBIOContext"
+ * Address at which platform-dependent information is returned if request
+ * is suspended for non-blocking I/O. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+/* return NULL if wouldblock, empty list if none found, else list of found */
+static PKIX_Error *
+pkix_Build_GatherCerts(
+ PKIX_ForwardBuilderState *state,
+ PKIX_ComCertSelParams *certSelParams,
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_Boolean certStoreIsCached = PKIX_FALSE;
+ PKIX_Boolean certStoreIsLocal = PKIX_FALSE;
+ PKIX_Boolean foundInCache = PKIX_FALSE;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertStore_CertCallback getCerts = NULL;
+ PKIX_List *certsFound = NULL;
+ PKIX_List *trustedCertList = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_GatherCerts");
+ PKIX_NULLCHECK_THREE(state, certSelParams, pNBIOContext);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ PKIX_DECREF(state->candidateCerts);
+
+ while (state->certStoreIndex < state->buildConstants.numCertStores) {
+
+ /* Get the current CertStore */
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->buildConstants.certStores,
+ state->certStoreIndex,
+ (PKIX_PL_Object **)&certStore,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_CertStore_GetLocalFlag
+ (certStore, &certStoreIsLocal, plContext),
+ PKIX_CERTSTOREGETLOCALFLAGFAILED);
+
+ if (state->useOnlyLocal == certStoreIsLocal) {
+ /* If GATHERPENDING, we've already checked the cache */
+ if (state->status == BUILD_GATHERPENDING) {
+ certStoreIsCached = PKIX_FALSE;
+ foundInCache = PKIX_FALSE;
+ } else {
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag
+ (certStore, &certStoreIsCached, plContext),
+ PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED);
+
+ if (certStoreIsCached) {
+ /*
+ * Look for Certs in the cache, using the SubjectName as
+ * the key. Then the ComCertSelParams are used to filter
+ * for qualified certs. If none are found, then the
+ * certStores are queried. When we eventually add items
+ * to the cache, we will only add items that passed the
+ * ComCertSelParams filter, rather than all Certs which
+ * matched the SubjectName.
+ */
+
+ PKIX_CHECK(pkix_CacheCert_Lookup
+ (certStore,
+ certSelParams,
+ state->buildConstants.testDate,
+ &foundInCache,
+ &certsFound,
+ plContext),
+ PKIX_CACHECERTCHAINLOOKUPFAILED);
+
+ }
+ }
+
+ /*
+ * XXX need to verify if Cert is trusted, hence may not
+ * be worth it to have the Cert Cached or
+ * If it is trusted, don't cache, but once there is cached
+ * certs, we won't get certs from database any more.
+ * can use flag to force not getting certs from cache
+ */
+ if (!foundInCache) {
+
+ if (nbioContext == NULL) {
+ PKIX_CHECK(PKIX_CertStore_GetCertCallback
+ (certStore, &getCerts, plContext),
+ PKIX_CERTSTOREGETCERTCALLBACKFAILED);
+
+ PKIX_CHECK(getCerts
+ (certStore,
+ state->certSel,
+ state->verifyNode,
+ &nbioContext,
+ &certsFound,
+ plContext),
+ PKIX_GETCERTSFAILED);
+ } else {
+ PKIX_CHECK(PKIX_CertStore_CertContinue
+ (certStore,
+ state->certSel,
+ state->verifyNode,
+ &nbioContext,
+ &certsFound,
+ plContext),
+ PKIX_CERTSTORECERTCONTINUEFAILED);
+ }
+
+ if (certStoreIsCached && certsFound) {
+
+ PKIX_CHECK(pkix_CacheCert_Add
+ (certStore,
+ certSelParams,
+ certsFound,
+ plContext),
+ PKIX_CACHECERTADDFAILED);
+ }
+ }
+
+ /*
+ * getCerts returns an empty list for "NONE FOUND",
+ * a NULL list for "would block"
+ */
+ if (certsFound == NULL) {
+ state->status = BUILD_GATHERPENDING;
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+ }
+
+ /* Are there any more certStores to query? */
+ PKIX_DECREF(certStore);
+ ++(state->certStoreIndex);
+ }
+
+ if (certsFound && certsFound->length > 1) {
+ PKIX_List *sorted = NULL;
+
+ /* sort Certs to try to optimize search */
+ PKIX_CHECK(pkix_Build_SortCandidateCerts
+ (certsFound, &sorted, plContext),
+ PKIX_BUILDSORTCANDIDATECERTSFAILED);
+ PKIX_DECREF(certsFound);
+ certsFound = sorted;
+ }
+
+ PKIX_CHECK(
+ pkix_Build_SelectCertsFromTrustAnchors(
+ state->buildConstants.anchors,
+ certSelParams, &trustedCertList,
+ plContext),
+ PKIX_FAILTOSELECTCERTSFROMANCHORS);
+ PKIX_CHECK(
+ pkix_Build_RemoveDupUntrustedCerts(trustedCertList,
+ certsFound,
+ plContext),
+ PKIX_REMOVEDUPUNTRUSTEDCERTSFAILED);
+
+ PKIX_CHECK(
+ pkix_List_MergeLists(trustedCertList,
+ certsFound,
+ &state->candidateCerts,
+ plContext),
+ PKIX_LISTMERGEFAILED);
+
+ /* No, return the list we have gathered */
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->candidateCerts, &state->numCerts, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ state->certIndex = 0;
+
+cleanup:
+ PKIX_DECREF(trustedCertList);
+ PKIX_DECREF(certStore);
+ PKIX_DECREF(certsFound);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_UpdateDate
+ * DESCRIPTION:
+ *
+ * This function updates the validityDate contained in "state", for the current
+ * CertChain contained in "state", to include the validityDate of the
+ * candidateCert contained in "state". The validityDate of a chain is the
+ * earliest of all the notAfter dates contained in the respective Certificates.
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_Build_UpdateDate(
+ PKIX_ForwardBuilderState *state,
+ void *plContext)
+{
+ PKIX_Boolean canBeCached = PKIX_FALSE;
+ PKIX_Int32 comparison = 0;
+ PKIX_PL_Date *notAfter = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_UpdateDate");
+ PKIX_NULLCHECK_ONE(state);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetCacheFlag
+ (state->candidateCert, &canBeCached, plContext),
+ PKIX_CERTGETCACHEFLAGFAILED);
+
+ state->canBeCached = state->canBeCached && canBeCached;
+ if (state->canBeCached == PKIX_TRUE) {
+
+ /*
+ * So far, all certs can be cached. Update cert
+ * chain validity time, which is the earliest of
+ * all certs' notAfter times.
+ */
+ PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
+ (state->candidateCert, &notAfter, plContext),
+ PKIX_CERTGETVALIDITYNOTAFTERFAILED);
+
+ if (state->validityDate == NULL) {
+ state->validityDate = notAfter;
+ notAfter = NULL;
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)state->validityDate,
+ (PKIX_PL_Object *)notAfter,
+ &comparison,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+ if (comparison > 0) {
+ PKIX_DECREF(state->validityDate);
+ state->validityDate = notAfter;
+ notAfter = NULL;
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(notAfter);
+
+ PKIX_RETURN(BUILD);
+}
+
+/* Prepare 'state' for the AIA round. */
+static void
+pkix_PrepareForwardBuilderStateForAIA(
+ PKIX_ForwardBuilderState *state)
+{
+ PORT_Assert(state->useOnlyLocal == PKIX_TRUE);
+ state->useOnlyLocal = PKIX_FALSE;
+ state->certStoreIndex = 0;
+ state->numFanout = state->buildConstants.maxFanout;
+ state->status = BUILD_TRYAIA;
+}
+
+extern SECStatus
+isIssuerCertAllowedAtCertIssuanceTime(CERTCertificate *issuerCert,
+ CERTCertificate *referenceCert);
+
+/*
+ * FUNCTION: pkix_BuildForwardDepthFirstSearch
+ * DESCRIPTION:
+ *
+ * This function performs a depth first search in the "forward" direction (from
+ * the target Cert to the trust anchor). A non-NULL targetCert must be stored
+ * in the ForwardBuilderState before this function is called. It is not written
+ * recursively since execution may be suspended in in any of several places
+ * pending completion of non-blocking I/O. This iterative structure makes it
+ * much easier to resume where it left off.
+ *
+ * Since the nature of the search is recursive, the recursion is handled by
+ * chaining states. That is, each new step involves creating a new
+ * ForwardBuilderState linked to its predecessor. If a step turns out to be
+ * fruitless, the state of the predecessor is restored and the next alternative
+ * is tried. When a search is successful, values needed from the last state
+ * (canBeCached and validityDate) are copied to the state provided by the
+ * caller, so that the caller can retrieve those values.
+ *
+ * There are three return arguments, the NBIOContext, the ValidateResult and
+ * the ForwardBuilderState. If NBIOContext is non-NULL, it means the search is
+ * suspended until the results of a non-blocking IO become available. The
+ * caller may wait for the completion using platform-dependent methods and then
+ * call this function again, allowing it to resume the search. If NBIOContext
+ * is NULL and the ValidateResult is non-NULL, it means the search has
+ * concluded successfully. If the NBIOContext is NULL but the ValidateResult is
+ * NULL, it means the search was unsuccessful.
+ *
+ * This function performs several steps at each node in the constructed chain:
+ *
+ * 1) It retrieves Certs from the registered CertStores that match the
+ * criteria established by the ForwardBuilderState pointed to by "state", such
+ * as a subject name matching the issuer name of the previous Cert. If there
+ * are no matching Certs, the function returns to the previous, or "parent",
+ * state and tries to continue the chain building with another of the Certs
+ * obtained from the CertStores as possible issuers for that parent Cert.
+ *
+ * 2) For each candidate Cert returned by the CertStores, this function checks
+ * whether the Cert is valid. If it is trusted, this function checks whether
+ * this Cert might serve as a TrustAnchor for a complete chain.
+ *
+ * 3) It determines whether this Cert, in conjunction with any of the
+ * TrustAnchors, might complete a chain. A complete chain, from this or the
+ * preceding step, is checked to see whether it is valid as a complete
+ * chain, including the checks that cannot be done in the forward direction.
+ *
+ * 4) If this Cert chains successfully, but is not a complete chain, that is,
+ * we have not reached a trusted Cert, a new ForwardBuilderState is created
+ * with this Cert as the immediate predecessor, and we continue in step (1),
+ * attempting to get Certs from the CertStores with this Certs "issuer" as
+ * their subject.
+ *
+ * 5) If an entire chain validates successfully, then we are done. A
+ * ValidateResult is created containing the Public Key of the target
+ * certificate (including DSA parameter inheritance, if any) and the
+ * PolicyNode representing the policy tree output by the validation algorithm,
+ * and stored at pValResult, and the function exits returning NULL.
+ *
+ * 5) If the entire chain does not validate successfully, the algorithm
+ * discards the latest Cert and continues in step 2 with the next candidate
+ * Cert, backing up to a parent state when no more possibilities exist at a
+ * given level, and returning failure when we try to back up but discover we
+ * are at the top level.
+ *
+ * PARAMETERS:
+ * "pNBIOContext"
+ * Address at which platform-dependent information is returned if building
+ * is suspended for non-blocking I/O. Must be non-NULL.
+ * "pState"
+ * Address at which input ForwardBuilderState is found, and at which output
+ * ForwardBuilderState is stored. Must be non-NULL.
+ * "pValResult"
+ * Address at which the ValidateResult is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_BuildForwardDepthFirstSearch(
+ void **pNBIOContext,
+ PKIX_ForwardBuilderState *state,
+ PKIX_ValidateResult **pValResult,
+ void *plContext)
+{
+ PKIX_Boolean outOfOptions = PKIX_FALSE;
+ PKIX_Boolean trusted = PKIX_FALSE;
+ PKIX_Boolean isSelfIssued = PKIX_FALSE;
+ PKIX_Boolean canBeCached = PKIX_FALSE;
+ PKIX_Boolean ioPending = PKIX_FALSE;
+ PKIX_PL_Date *validityDate = NULL;
+ PKIX_PL_Date *currTime = NULL;
+ PKIX_Int32 childTraversedCACerts = 0;
+ PKIX_UInt32 numSubjectNames = 0;
+ PKIX_UInt32 numChained = 0;
+ PKIX_Int32 cmpTimeResult = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 certsSoFar = 0;
+ PKIX_List *childTraversedSubjNames = NULL;
+ PKIX_List *subjectNames = NULL;
+ PKIX_List *unfilteredCerts = NULL;
+ PKIX_List *filteredCerts = NULL;
+ PKIX_PL_Object *subjectName = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_ForwardBuilderState *childState = NULL;
+ PKIX_ForwardBuilderState *parentState = NULL;
+ PKIX_PL_Object *revCheckerState = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_TrustAnchor *trustAnchor = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_VerifyNode *verifyNode = NULL;
+ PKIX_Error *verifyError = NULL;
+ PKIX_Error *finalError = NULL;
+ void *nbio = NULL;
+ PKIX_UInt32 numIterations = 0;
+
+ PKIX_ENTER(BUILD, "pkix_BuildForwardDepthFirstSearch");
+ PKIX_NULLCHECK_THREE(pNBIOContext, state, pValResult);
+
+ nbio = *pNBIOContext;
+ *pNBIOContext = NULL;
+ PKIX_INCREF(state->validityDate);
+ validityDate = state->validityDate;
+ canBeCached = state->canBeCached;
+ PKIX_DECREF(*pValResult);
+ targetCert = state->buildConstants.targetCert;
+
+ /*
+ * We return if successful; if we fall off the end
+ * of this "while" clause our search has failed.
+ */
+ while (outOfOptions == PKIX_FALSE) {
+ /*
+ * The maximum number of iterations works around a bug that
+ * causes this while loop to never exit when AIA and cross
+ * certificates are involved. See bug xxxxx.
+ */
+ if (numIterations++ > 250)
+ PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS);
+
+ if (state->buildConstants.maxTime != 0) {
+ PKIX_DECREF(currTime);
+ PKIX_CHECK(PKIX_PL_Date_Create_UTCTime
+ (NULL, &currTime, plContext),
+ PKIX_DATECREATEUTCTIMEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)state->buildConstants.timeLimit,
+ (PKIX_PL_Object *)currTime,
+ &cmpTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+
+ if (cmpTimeResult < 0) {
+ if (state->verifyNode != NULL) {
+ PKIX_ERROR_CREATE
+ (BUILD,
+ PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS,
+ verifyError);
+ PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
+ (state->verifyNode,
+ verifyError,
+ plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_DECREF(finalError);
+ finalError = verifyError;
+ verifyError = NULL;
+ }
+ /* Even if we logged error, we still have to abort */
+ PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS);
+ }
+ }
+
+ if (state->status == BUILD_INITIAL) {
+
+ PKIX_CHECK(pkix_Build_BuildSelectorAndParams(state, plContext),
+ PKIX_BUILDBUILDSELECTORANDPARAMSFAILED);
+
+ /*
+ * If the caller supplied a partial certChain (hintCerts) try
+ * the next one from that List before we go to the certStores.
+ */
+ if (state->buildConstants.numHintCerts > 0) {
+ /* How many Certs does our trust chain have already? */
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->trustChain, &certsSoFar, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ /* That includes the target Cert. Don't count it. */
+ certsSoFar--;
+
+ /* Are we still within range of the partial chain? */
+ if (certsSoFar >= state->buildConstants.numHintCerts) {
+ state->status = BUILD_TRYAIA;
+ } else {
+ /*
+ * If we already have n certs, we want the n+1th
+ * (i.e., index = n) from the list of hints.
+ */
+ PKIX_DECREF(state->candidateCert);
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->buildConstants.hintCerts,
+ certsSoFar,
+ (PKIX_PL_Object **)&state->candidateCert,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (state->candidateCerts,
+ (PKIX_PL_Object *)state->candidateCert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ state->numCerts = 1;
+ state->usingHintCerts = PKIX_TRUE;
+ state->status = BUILD_CERTVALIDATING;
+ }
+ } else {
+ state->status = BUILD_TRYAIA;
+ }
+
+ }
+
+ if (state->status == BUILD_TRYAIA) {
+ if (state->useOnlyLocal == PKIX_TRUE) {
+ state->status = BUILD_COLLECTINGCERTS;
+ } else {
+ state->status = BUILD_AIAPENDING;
+ }
+ }
+
+ if (state->status == BUILD_AIAPENDING &&
+ state->buildConstants.aiaMgr) {
+ pkixErrorResult = PKIX_PL_AIAMgr_GetAIACerts
+ (state->buildConstants.aiaMgr,
+ state->prevCert,
+ &nbio,
+ &unfilteredCerts,
+ plContext);
+
+ if (nbio != NULL) {
+ /* IO still pending, resume later */
+ *pNBIOContext = nbio;
+ goto cleanup;
+ }
+ state->numCerts = 0;
+ if (pkixErrorResult) {
+ pkixErrorClass = pkixErrorResult->errClass;
+ if (pkixErrorClass == PKIX_FATAL_ERROR) {
+ goto fatal;
+ }
+ PKIX_DECREF(finalError);
+ finalError = pkixErrorResult;
+ pkixErrorResult = NULL;
+ if (state->verifyNode != NULL) {
+ /* state->verifyNode is the object that contains a list
+ * of verifyNodes. verifyNodes contains cert chain
+ * build failures that occurred on this level of chain
+ * building. Here, creating new verify node
+ * to log the failure and adding it to the list. */
+ PKIX_CHECK_FATAL(pkix_VerifyNode_Create
+ (state->prevCert,
+ 0, NULL,
+ &verifyNode,
+ plContext),
+ PKIX_VERIFYNODECREATEFAILED);
+ PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
+ (verifyNode, finalError, plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
+ (state->verifyNode,
+ verifyNode,
+ plContext),
+ PKIX_VERIFYNODEADDTOTREEFAILED);
+ PKIX_DECREF(verifyNode);
+ }
+ }
+#ifdef PKIX_BUILDDEBUG
+ /* Turn this on to trace the List of Certs, before CertSelect */
+ {
+ PKIX_PL_String *unString;
+ char *unAscii;
+ PKIX_UInt32 length;
+ PKIX_TOSTRING
+ ((PKIX_PL_Object*)unfilteredCerts,
+ &unString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (unString,
+ PKIX_ESCASCII,
+ (void **)&unAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_DEBUG_ARG
+ ("unfilteredCerts = %s\n", unAscii);
+ PKIX_DECREF(unString);
+ PKIX_FREE(unAscii);
+ }
+#endif
+
+ /* Note: Certs winnowed here don't get into VerifyTree. */
+ if (unfilteredCerts) {
+ PKIX_CHECK(pkix_CertSelector_Select
+ (state->certSel,
+ unfilteredCerts,
+ &filteredCerts,
+ plContext),
+ PKIX_CERTSELECTORSELECTFAILED);
+
+ PKIX_DECREF(unfilteredCerts);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (filteredCerts, &(state->numCerts), plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+#ifdef PKIX_BUILDDEBUG
+ /* Turn this on to trace the List of Certs, after CertSelect */
+ {
+ PKIX_PL_String *unString;
+ char *unAscii;
+ PKIX_UInt32 length;
+ PKIX_TOSTRING
+ ((PKIX_PL_Object*)filteredCerts,
+ &unString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (unString,
+ PKIX_ESCASCII,
+ (void **)&unAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_DEBUG_ARG("filteredCerts = %s\n", unAscii);
+ PKIX_DECREF(unString);
+ PKIX_FREE(unAscii);
+ }
+#endif
+
+ PKIX_DECREF(state->candidateCerts);
+ state->candidateCerts = filteredCerts;
+ state->certIndex = 0;
+ filteredCerts = NULL;
+ }
+
+ /* Are there any Certs to try? */
+ if (state->numCerts > 0) {
+ state->status = BUILD_CERTVALIDATING;
+ } else {
+ state->status = BUILD_COLLECTINGCERTS;
+ }
+ }
+
+ PKIX_DECREF(certSelParams);
+ PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
+ (state->certSel, &certSelParams, plContext),
+ PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
+
+ /* **** Querying the CertStores ***** */
+ if ((state->status == BUILD_COLLECTINGCERTS) ||
+ (state->status == BUILD_GATHERPENDING)) {
+
+#if PKIX_FORWARDBUILDERSTATEDEBUG
+ PKIX_CHECK(pkix_ForwardBuilderState_DumpState
+ (state, plContext),
+ PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED);
+#endif
+
+ PKIX_CHECK(pkix_Build_GatherCerts
+ (state, certSelParams, &nbio, plContext),
+ PKIX_BUILDGATHERCERTSFAILED);
+
+ if (nbio != NULL) {
+ /* IO still pending, resume later */
+ *pNBIOContext = nbio;
+ goto cleanup;
+ }
+
+ /* Are there any Certs to try? */
+ if (state->numCerts > 0) {
+ state->status = BUILD_CERTVALIDATING;
+ } else {
+ state->status = BUILD_ABANDONNODE;
+ }
+ }
+
+ /* ****Phase 2 - Chain building***** */
+
+#if PKIX_FORWARDBUILDERSTATEDEBUG
+ PKIX_CHECK(pkix_ForwardBuilderState_DumpState(state, plContext),
+ PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED);
+#endif
+
+ if (state->status == BUILD_CERTVALIDATING) {
+ PKIX_DECREF(state->candidateCert);
+ PKIX_CHECK(PKIX_List_GetItem
+ (state->candidateCerts,
+ state->certIndex,
+ (PKIX_PL_Object **)&(state->candidateCert),
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (isIssuerCertAllowedAtCertIssuanceTime(
+ state->candidateCert->nssCert, targetCert->nssCert)
+ != SECSuccess) {
+ PKIX_ERROR(PKIX_CERTISBLOCKLISTEDATISSUANCETIME);
+ }
+
+ if ((state->verifyNode) != NULL) {
+ PKIX_CHECK_FATAL(pkix_VerifyNode_Create
+ (state->candidateCert,
+ 0,
+ NULL,
+ &verifyNode,
+ plContext),
+ PKIX_VERIFYNODECREATEFAILED);
+ }
+
+ /* If failure, this function sets Error in verifyNode */
+ verifyError = pkix_Build_VerifyCertificate
+ (state,
+ state->buildConstants.userCheckers,
+ &trusted,
+ verifyNode,
+ plContext);
+
+ if (verifyError) {
+ pkixTempErrorReceived = PKIX_TRUE;
+ pkixErrorClass = verifyError->errClass;
+ if (pkixErrorClass == PKIX_FATAL_ERROR) {
+ pkixErrorResult = verifyError;
+ verifyError = NULL;
+ goto fatal;
+ }
+ }
+
+ if (PKIX_ERROR_RECEIVED) {
+ if (state->verifyNode != NULL) {
+ PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
+ (verifyNode, verifyError, plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
+ (state->verifyNode,
+ verifyNode,
+ plContext),
+ PKIX_VERIFYNODEADDTOTREEFAILED);
+ PKIX_DECREF(verifyNode);
+ }
+ pkixTempErrorReceived = PKIX_FALSE;
+ PKIX_DECREF(finalError);
+ finalError = verifyError;
+ verifyError = NULL;
+ if (state->certLoopingDetected) {
+ PKIX_ERROR
+ (PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED);
+ }
+ state->status = BUILD_GETNEXTCERT;
+ } else {
+ state->status = BUILD_DATEPREP;
+ }
+ }
+
+ if (state->status == BUILD_DATEPREP) {
+ /* Keep track of whether this chain can be cached */
+ PKIX_CHECK(pkix_Build_UpdateDate(state, plContext),
+ PKIX_BUILDUPDATEDATEFAILED);
+
+ canBeCached = state->canBeCached;
+ PKIX_DECREF(validityDate);
+ PKIX_INCREF(state->validityDate);
+ validityDate = state->validityDate;
+ if (trusted == PKIX_TRUE) {
+ state->status = BUILD_CHECKTRUSTED;
+ } else {
+ state->status = BUILD_ADDTOCHAIN;
+ }
+ }
+
+ if (state->status == BUILD_CHECKTRUSTED) {
+
+ /*
+ * If this cert is trusted, try to validate the entire
+ * chain using this certificate as trust anchor.
+ */
+ PKIX_CHECK(PKIX_TrustAnchor_CreateWithCert
+ (state->candidateCert,
+ &trustAnchor,
+ plContext),
+ PKIX_TRUSTANCHORCREATEWITHCERTFAILED);
+
+ PKIX_CHECK(pkix_Build_ValidationCheckers
+ (state,
+ state->trustChain,
+ trustAnchor,
+ PKIX_FALSE, /* do not add eku checker
+ * since eku was already
+ * checked */
+ plContext),
+ PKIX_BUILDVALIDATIONCHECKERSFAILED);
+
+ state->status = BUILD_CHECKTRUSTED2;
+ }
+
+ if (state->status == BUILD_CHECKTRUSTED2) {
+ verifyError =
+ pkix_Build_ValidateEntireChain(state,
+ trustAnchor,
+ &nbio, &valResult,
+ verifyNode,
+ plContext);
+ if (nbio != NULL) {
+ /* IO still pending, resume later */
+ goto cleanup;
+ } else {
+ /* checking the error for fatal status */
+ if (verifyError) {
+ pkixTempErrorReceived = PKIX_TRUE;
+ pkixErrorClass = verifyError->errClass;
+ if (pkixErrorClass == PKIX_FATAL_ERROR) {
+ pkixErrorResult = verifyError;
+ verifyError = NULL;
+ goto fatal;
+ }
+ }
+ if (state->verifyNode != NULL) {
+ PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
+ (state->verifyNode,
+ verifyNode,
+ plContext),
+ PKIX_VERIFYNODEADDTOTREEFAILED);
+ PKIX_DECREF(verifyNode);
+ }
+ if (!PKIX_ERROR_RECEIVED) {
+ *pValResult = valResult;
+ valResult = NULL;
+ /* Change state so IsIOPending is FALSE */
+ state->status = BUILD_CHECKTRUSTED;
+ goto cleanup;
+ }
+ PKIX_DECREF(finalError);
+ finalError = verifyError;
+ verifyError = NULL;
+ /* Reset temp error that was set by
+ * PKIX_CHECK_ONLY_FATAL and continue */
+ pkixTempErrorReceived = PKIX_FALSE;
+ PKIX_DECREF(trustAnchor);
+ }
+
+ /*
+ * If chain doesn't validate with a trusted Cert,
+ * adding more Certs to it can't help.
+ */
+ if (state->certLoopingDetected) {
+ PKIX_DECREF(verifyError);
+ PKIX_ERROR_CREATE(BUILD,
+ PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED,
+ verifyError);
+ PKIX_CHECK_FATAL(
+ pkix_VerifyNode_SetError(state->verifyNode,
+ verifyError,
+ plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_DECREF(verifyError);
+ }
+ state->status = BUILD_GETNEXTCERT;
+ }
+
+ /*
+ * This Cert was not trusted. Add it to our chain, and
+ * continue building. If we don't reach a trust anchor,
+ * we'll take it off later and continue without it.
+ */
+ if (state->status == BUILD_ADDTOCHAIN) {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (state->trustChain,
+ (PKIX_PL_Object *)state->candidateCert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ state->status = BUILD_EXTENDCHAIN;
+ }
+
+ if (state->status == BUILD_EXTENDCHAIN) {
+
+ /* Check whether we are allowed to extend the chain */
+ if ((state->buildConstants.maxDepth != 0) &&
+ (state->numDepth <= 1)) {
+
+ if (state->verifyNode != NULL) {
+ PKIX_ERROR_CREATE
+ (BUILD,
+ PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS,
+ verifyError);
+ PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
+ (verifyNode, verifyError, plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
+ (state->verifyNode, verifyNode, plContext),
+ PKIX_VERIFYNODEADDTOTREEFAILED);
+ PKIX_DECREF(verifyNode);
+ PKIX_DECREF(finalError);
+ finalError = verifyError;
+ verifyError = NULL;
+ }
+ /* Even if error logged, still need to abort */
+ PKIX_ERROR(PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS);
+ }
+
+ PKIX_CHECK(pkix_IsCertSelfIssued
+ (state->candidateCert, &isSelfIssued, plContext),
+ PKIX_ISCERTSELFISSUEDFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)state->traversedSubjNames,
+ (PKIX_PL_Object **)&childTraversedSubjNames,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ if (isSelfIssued) {
+ childTraversedCACerts = state->traversedCACerts;
+ } else {
+ childTraversedCACerts = state->traversedCACerts + 1;
+
+ PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames
+ (state->candidateCert,
+ &subjectNames,
+ plContext),
+ PKIX_CERTGETALLSUBJECTNAMESFAILED);
+
+ if (subjectNames) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (subjectNames,
+ &numSubjectNames,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ } else {
+ numSubjectNames = 0;
+ }
+
+ for (i = 0; i < numSubjectNames; i++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (subjectNames,
+ i,
+ &subjectName,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+ PKIX_NULLCHECK_ONE
+ (state->traversedSubjNames);
+ PKIX_CHECK(PKIX_List_AppendItem
+ (state->traversedSubjNames,
+ subjectName,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(subjectName);
+ }
+ PKIX_DECREF(subjectNames);
+ }
+
+ PKIX_CHECK(pkix_ForwardBuilderState_Create
+ (childTraversedCACerts,
+ state->buildConstants.maxFanout,
+ state->numDepth - 1,
+ canBeCached,
+ validityDate,
+ state->candidateCert,
+ childTraversedSubjNames,
+ state->trustChain,
+ state,
+ &childState,
+ plContext),
+ PKIX_FORWARDBUILDSTATECREATEFAILED);
+
+ PKIX_DECREF(childTraversedSubjNames);
+ PKIX_DECREF(certSelParams);
+ childState->verifyNode = verifyNode;
+ verifyNode = NULL;
+ PKIX_DECREF(state);
+ state = childState; /* state->status == BUILD_INITIAL */
+ childState = NULL;
+ continue; /* with while (!outOfOptions) */
+ }
+
+ if (state->status == BUILD_GETNEXTCERT) {
+ pkixTempErrorReceived = PKIX_FALSE;
+ PKIX_DECREF(state->candidateCert);
+
+ /*
+ * If we were using a Cert from the callier-supplied partial
+ * chain, delete it and go to the certStores.
+ */
+ if (state->usingHintCerts == PKIX_TRUE) {
+ PKIX_DECREF(state->candidateCerts);
+ PKIX_CHECK(PKIX_List_Create
+ (&state->candidateCerts, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ state->numCerts = 0;
+ state->usingHintCerts = PKIX_FALSE;
+ state->status = BUILD_TRYAIA;
+ continue;
+ } else if (++(state->certIndex) < (state->numCerts)) {
+ if ((state->buildConstants.maxFanout != 0) &&
+ (--(state->numFanout) == 0)) {
+
+ if (state->verifyNode != NULL) {
+ PKIX_ERROR_CREATE
+ (BUILD,
+ PKIX_FANOUTEXCEEDSRESOURCELIMITS,
+ verifyError);
+ PKIX_CHECK_FATAL
+ (pkix_VerifyNode_SetError
+ (state->verifyNode,
+ verifyError,
+ plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_DECREF(finalError);
+ finalError = verifyError;
+ verifyError = NULL;
+ }
+ /* Even if error logged, still need to abort */
+ PKIX_ERROR
+ (PKIX_FANOUTEXCEEDSRESOURCELIMITS);
+ }
+ state->status = BUILD_CERTVALIDATING;
+ continue;
+ }
+ }
+
+ /*
+ * Adding the current cert to the chain didn't help. If our search
+ * has been restricted to local certStores, try opening up the
+ * search and see whether that helps. Otherwise, back up to the
+ * parent cert, and see if there are any more to try.
+ */
+ if (state->useOnlyLocal == PKIX_TRUE) {
+ pkix_PrepareForwardBuilderStateForAIA(state);
+ } else do {
+ if (state->parentState == NULL) {
+ /* We are at the top level, and can't back up! */
+ outOfOptions = PKIX_TRUE;
+ } else {
+ /*
+ * Try the next cert, if any, for this parent.
+ * Otherwise keep backing up until we reach a
+ * parent with more certs to try.
+ */
+ PKIX_CHECK(PKIX_List_GetLength
+ (state->trustChain, &numChained, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ PKIX_CHECK(PKIX_List_DeleteItem
+ (state->trustChain, numChained - 1, plContext),
+ PKIX_LISTDELETEITEMFAILED);
+
+ /* local and aia fetching returned no good certs.
+ * Creating a verify node in the parent that tells
+ * us this. */
+ if (!state->verifyNode) {
+ PKIX_CHECK_FATAL(
+ pkix_VerifyNode_Create(state->prevCert,
+ 0, NULL,
+ &state->verifyNode,
+ plContext),
+ PKIX_VERIFYNODECREATEFAILED);
+ }
+ /* Updating the log with the error. */
+ PKIX_DECREF(verifyError);
+ PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER,
+ verifyError);
+ PKIX_CHECK_FATAL(
+ pkix_VerifyNode_SetError(state->verifyNode,
+ verifyError,
+ plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ PKIX_DECREF(verifyError);
+
+ PKIX_INCREF(state->parentState);
+ parentState = state->parentState;
+ PKIX_DECREF(verifyNode);
+ verifyNode = state->verifyNode;
+ state->verifyNode = NULL;
+ PKIX_DECREF(state);
+ state = parentState;
+ parentState = NULL;
+ if (state->verifyNode != NULL && verifyNode) {
+ PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
+ (state->verifyNode,
+ verifyNode,
+ plContext),
+ PKIX_VERIFYNODEADDTOTREEFAILED);
+ PKIX_DECREF(verifyNode);
+ }
+ PKIX_DECREF(validityDate);
+ PKIX_INCREF(state->validityDate);
+ validityDate = state->validityDate;
+ canBeCached = state->canBeCached;
+
+ /* Are there any more Certs to try? */
+ if (++(state->certIndex) < (state->numCerts)) {
+ state->status = BUILD_CERTVALIDATING;
+ PKIX_DECREF(state->candidateCert);
+ break;
+ }
+ if (state->useOnlyLocal == PKIX_TRUE) {
+ /* Clean up and go for AIA round. */
+ pkix_PrepareForwardBuilderStateForAIA(state);
+ break;
+ }
+ }
+ PKIX_DECREF(state->candidateCert);
+ } while (outOfOptions == PKIX_FALSE);
+
+ } /* while (outOfOptions == PKIX_FALSE) */
+
+cleanup:
+
+ if (pkixErrorClass == PKIX_FATAL_ERROR) {
+ goto fatal;
+ }
+
+ /* verifyNode should be equal to NULL at this point. Assert it.
+ * Temporarelly use verifyError to store an error ref to which we
+ * have in pkixErrorResult. This is done to prevent error cloberring
+ * while using macros below. */
+ PORT_Assert(verifyError == NULL);
+ verifyError = pkixErrorResult;
+
+ /*
+ * We were called with an initialState that had no parent. If we are
+ * returning with an error or with a result, we must destroy any state
+ * that we created (any state with a parent).
+ */
+
+ PKIX_CHECK_FATAL(pkix_ForwardBuilderState_IsIOPending
+ (state, &ioPending, plContext),
+ PKIX_FORWARDBUILDERSTATEISIOPENDINGFAILED);
+
+ if (ioPending == PKIX_FALSE) {
+ while (state->parentState) {
+ PKIX_INCREF(state->parentState);
+ parentState = state->parentState;
+ PKIX_DECREF(verifyNode);
+ verifyNode = state->verifyNode;
+ state->verifyNode = NULL;
+ PKIX_DECREF(state);
+ state = parentState;
+ parentState = NULL;
+ if (state->verifyNode != NULL && verifyNode) {
+ PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
+ (state->verifyNode,
+ verifyNode,
+ plContext),
+ PKIX_VERIFYNODEADDTOTREEFAILED);
+ PKIX_DECREF(verifyNode);
+ }
+ }
+ state->canBeCached = canBeCached;
+ PKIX_DECREF(state->validityDate);
+ state->validityDate = validityDate;
+ validityDate = NULL;
+ }
+ if (!*pValResult && !verifyError) {
+ if (!finalError) {
+ PKIX_CHECK_FATAL(
+ pkix_VerifyNode_FindError(state->verifyNode,
+ &finalError,
+ plContext),
+ PKIX_VERIFYNODEFINDERRORFAILED);
+ }
+ if (finalError) {
+ pkixErrorResult = finalError;
+ pkixErrorCode = PKIX_BUILDFORWARDDEPTHFIRSTSEARCHFAILED;
+ finalError = NULL;
+ goto fatal;
+ }
+ pkixErrorCode = PKIX_SECERRORUNKNOWNISSUER;
+ pkixErrorReceived = PKIX_TRUE;
+ PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER,
+ verifyError);
+ PKIX_CHECK_FATAL(
+ pkix_VerifyNode_SetError(state->verifyNode, verifyError,
+ plContext),
+ PKIX_VERIFYNODESETERRORFAILED);
+ } else {
+ pkixErrorResult = verifyError;
+ verifyError = NULL;
+ }
+
+fatal:
+ if (state->parentState) {
+ /* parentState in "state" object should be NULL at this point.
+ * If itn't, that means that we got fatal error(we have jumped to
+ * "fatal" label) and we should destroy all state except the top one. */
+ while (state->parentState) {
+ PKIX_Error *error = NULL;
+ PKIX_ForwardBuilderState *prntState = state->parentState;
+ /* Dumb: need to increment parentState to avoid destruction
+ * of "build constants"(they get destroyed when parentState is
+ * set to NULL. */
+ PKIX_INCREF(prntState);
+ error = PKIX_PL_Object_DecRef((PKIX_PL_Object*)state, plContext);
+ if (error) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)error, plContext);
+ }
+ /* No need to decref the parent state. It was already done by
+ * pkix_ForwardBuilderState_Destroy function. */
+ state = prntState;
+ }
+ }
+ PKIX_DECREF(parentState);
+ PKIX_DECREF(childState);
+ PKIX_DECREF(valResult);
+ PKIX_DECREF(verifyError);
+ PKIX_DECREF(finalError);
+ PKIX_DECREF(verifyNode);
+ PKIX_DECREF(childTraversedSubjNames);
+ PKIX_DECREF(certSelParams);
+ PKIX_DECREF(subjectNames);
+ PKIX_DECREF(subjectName);
+ PKIX_DECREF(trustAnchor);
+ PKIX_DECREF(validityDate);
+ PKIX_DECREF(revCheckerState);
+ PKIX_DECREF(currTime);
+ PKIX_DECREF(filteredCerts);
+ PKIX_DECREF(unfilteredCerts);
+ PKIX_DECREF(trustedCert);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_CheckInCache
+ * DESCRIPTION:
+ *
+ * The function tries to locate a chain for a cert in the cert chain cache.
+ * If found, the chain goes through revocation chacking and returned back to
+ * caller. Chains that fail revocation check get removed from cache.
+ *
+ * PARAMETERS:
+ * "state"
+ * Address of ForwardBuilderState to be used. Must be non-NULL.
+ * "pBuildResult"
+ * Address at which the BuildResult is stored, after a successful build.
+ * Must be non-NULL.
+ * "pNBIOContext"
+ * Address at which the NBIOContext is stored indicating whether the
+ * validation is complete. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error*
+pkix_Build_CheckInCache(
+ PKIX_ForwardBuilderState *state,
+ PKIX_BuildResult **pBuildResult,
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_PL_Date *testDate = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_Error *buildError = NULL;
+ PKIX_TrustAnchor *matchingAnchor = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_Boolean cacheHit = PKIX_FALSE;
+ PKIX_Boolean trusted = PKIX_FALSE;
+ PKIX_Boolean stillValid = PKIX_FALSE;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_CheckInCache");
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ targetCert = state->buildConstants.targetCert;
+ anchors = state->buildConstants.anchors;
+ testDate = state->buildConstants.testDate;
+
+ /* Check whether this cert verification has been cached. */
+ PKIX_CHECK(pkix_CacheCertChain_Lookup
+ (targetCert,
+ anchors,
+ testDate,
+ &cacheHit,
+ &buildResult,
+ plContext),
+ PKIX_CACHECERTCHAINLOOKUPFAILED);
+
+ if (!cacheHit) {
+ goto cleanup;
+ }
+
+ /*
+ * We found something in cache. Verify that the anchor
+ * cert is still trusted,
+ */
+ PKIX_CHECK(PKIX_BuildResult_GetValidateResult
+ (buildResult, &valResult, plContext),
+ PKIX_BUILDRESULTGETVALIDATERESULTFAILED);
+
+ PKIX_CHECK(PKIX_ValidateResult_GetTrustAnchor
+ (valResult, &matchingAnchor, plContext),
+ PKIX_VALIDATERESULTGETTRUSTANCHORFAILED);
+
+ PKIX_DECREF(valResult);
+
+ PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
+ (matchingAnchor, &trustedCert, plContext),
+ PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
+
+ if (anchors && state->buildConstants.numAnchors) {
+ /* Check if it is one of the trust anchors */
+ PKIX_CHECK(
+ pkix_List_Contains(anchors,
+ (PKIX_PL_Object *)matchingAnchor,
+ &trusted,
+ plContext),
+ PKIX_LISTCONTAINSFAILED);
+ }
+
+ if ((!trusted && !state->buildConstants.trustOnlyUserAnchors) ||
+ !state->buildConstants.numAnchors) {
+ /* If it is not one of the trust anchors and the trust anchors
+ * are supplemental, or if there are no trust anchors, then check
+ * if the cert is trusted directly.
+ */
+ PKIX_CHECK(
+ PKIX_PL_Cert_IsCertTrusted(trustedCert,
+ PKIX_PL_TrustAnchorMode_Ignore,
+ &trusted, plContext),
+ PKIX_CERTISCERTTRUSTEDFAILED);
+ }
+
+ if (!trusted) {
+ goto cleanup;
+ }
+ /*
+ * Since the key usage may vary for different
+ * applications, we need to verify the chain again.
+ * Reverification will be improved with a fix for 397805.
+ */
+ PKIX_CHECK(PKIX_BuildResult_GetCertChain
+ (buildResult, &certList, plContext),
+ PKIX_BUILDRESULTGETCERTCHAINFAILED);
+
+ PKIX_CHECK(pkix_Build_ValidationCheckers
+ (state,
+ certList,
+ matchingAnchor,
+ PKIX_TRUE, /* Chain revalidation stage. */
+ plContext),
+ PKIX_BUILDVALIDATIONCHECKERSFAILED);
+
+ PKIX_CHECK_ONLY_FATAL(
+ pkix_Build_ValidateEntireChain(state, matchingAnchor,
+ &nbioContext, &valResult,
+ state->verifyNode, plContext),
+ PKIX_BUILDVALIDATEENTIRECHAINFAILED);
+
+ if (nbioContext != NULL) {
+ /* IO still pending, resume later */
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+ if (!PKIX_ERROR_RECEIVED) {
+ /* The result from cache is still valid. But we replace an old*/
+ *pBuildResult = buildResult;
+ buildResult = NULL;
+ stillValid = PKIX_TRUE;
+ }
+
+cleanup:
+
+ if (!nbioContext && cacheHit && !(trusted && stillValid)) {
+ /* The anchor of this chain is no longer trusted or
+ * chain cert(s) has been revoked.
+ * Invalidate this result in the cache */
+ buildError = pkixErrorResult;
+ PKIX_CHECK_FATAL(pkix_CacheCertChain_Remove
+ (targetCert,
+ anchors,
+ plContext),
+ PKIX_CACHECERTCHAINREMOVEFAILED);
+ pkixErrorResult = buildError;
+ buildError = NULL;
+ }
+
+fatal:
+ PKIX_DECREF(buildResult);
+ PKIX_DECREF(valResult);
+ PKIX_DECREF(buildError);
+ PKIX_DECREF(certList);
+ PKIX_DECREF(matchingAnchor);
+ PKIX_DECREF(trustedCert);
+
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_InitiateBuildChain
+ * DESCRIPTION:
+ *
+ * This function initiates the search for a BuildChain, using the parameters
+ * provided in "procParams" and, if continuing a search that was suspended
+ * for I/O, using the ForwardBuilderState pointed to by "pState".
+ *
+ * If a successful chain is built, this function stores the BuildResult at
+ * "pBuildResult". Alternatively, if an operation using non-blocking I/O
+ * is in progress and the operation has not been completed, this function
+ * stores the platform-dependent non-blocking I/O context (nbioContext) at
+ * "pNBIOContext", the FowardBuilderState at "pState", and NULL at
+ * "pBuildResult". Finally, if chain building was unsuccessful, this function
+ * stores NULL at both "pState" and at "pBuildResult".
+ *
+ * Note: This function is re-entered only for the case of non-blocking I/O
+ * in the "short-cut" attempt to build a chain using the target Certificate
+ * directly with one of the trustAnchors. For all other cases, resumption
+ * after non-blocking I/O is via pkix_Build_ResumeBuildChain.
+ *
+ * PARAMETERS:
+ * "procParams"
+ * Address of the ProcessingParams for the search. Must be non-NULL.
+ * "pNBIOContext"
+ * Address at which the NBIOContext is stored indicating whether the
+ * validation is complete. Must be non-NULL.
+ * "pState"
+ * Address at which the ForwardBuilderState is stored, if the chain
+ * building is suspended for waiting I/O; also, the address at which the
+ * ForwardBuilderState is provided for resumption of the chain building
+ * attempt. Must be non-NULL.
+ * "pBuildResult"
+ * Address at which the BuildResult is stored, after a successful build.
+ * Must be non-NULL.
+ * "pVerifyNode"
+ * Address at which a VerifyNode chain is returned, if non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_Build_InitiateBuildChain(
+ PKIX_ProcessingParams *procParams,
+ void **pNBIOContext,
+ PKIX_ForwardBuilderState **pState,
+ PKIX_BuildResult **pBuildResult,
+ PKIX_VerifyNode **pVerifyNode,
+ void *plContext)
+{
+ PKIX_UInt32 numAnchors = 0;
+ PKIX_UInt32 numCertStores = 0;
+ PKIX_UInt32 numHintCerts = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_Boolean isDuplicate = PKIX_FALSE;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_CertSelector *targetConstraints = NULL;
+ PKIX_ComCertSelParams *targetParams = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *targetSubjNames = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_PL_Object *firstHintCert = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_List *userCheckers = NULL;
+ PKIX_List *hintCerts = NULL;
+ PKIX_PL_Date *testDate = NULL;
+ PKIX_PL_PublicKey *targetPubKey = NULL;
+ void *nbioContext = NULL;
+ BuildConstants buildConstants;
+
+ PKIX_List *tentativeChain = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_ForwardBuilderState *state = NULL;
+ PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
+ PKIX_CertSelector_MatchCallback selectorCallback = NULL;
+ PKIX_Boolean trusted = PKIX_FALSE;
+ PKIX_PL_AIAMgr *aiaMgr = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_InitiateBuildChain");
+ PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ state = *pState;
+ *pState = NULL; /* no net change in reference count */
+
+ if (state == NULL) {
+ PKIX_CHECK(PKIX_ProcessingParams_GetDate
+ (procParams, &testDate, plContext),
+ PKIX_PROCESSINGPARAMSGETDATEFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors
+ (procParams, &anchors, plContext),
+ PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(anchors, &numAnchors, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ /* retrieve stuff from targetCertConstraints */
+ PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
+ (procParams, &targetConstraints, plContext),
+ PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
+ (targetConstraints, &targetParams, plContext),
+ PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetCertificate
+ (targetParams, &targetCert, plContext),
+ PKIX_COMCERTSELPARAMSGETCERTIFICATEFAILED);
+
+ PKIX_CHECK(
+ PKIX_ComCertSelParams_SetLeafCertFlag(targetParams,
+ PKIX_TRUE, plContext),
+ PKIX_COMCERTSELPARAMSSETLEAFCERTFLAGFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetHintCerts
+ (procParams, &hintCerts, plContext),
+ PKIX_PROCESSINGPARAMSGETHINTCERTSFAILED);
+
+ if (hintCerts != NULL) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (hintCerts, &numHintCerts, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ /*
+ * Caller must provide either a target Cert
+ * (in ComCertSelParams->Certificate) or a partial Cert
+ * chain (in ProcParams->HintCerts).
+ */
+
+ if (targetCert == NULL) {
+
+ /* Use first cert of hintCerts as the targetCert */
+ if (numHintCerts == 0) {
+ PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED);
+ }
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (hintCerts,
+ 0,
+ (PKIX_PL_Object **)&targetCert,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_DeleteItem(hintCerts, 0, plContext),
+ PKIX_LISTGETITEMFAILED);
+ } else {
+
+ /*
+ * If the first hintCert is the same as the targetCert,
+ * delete it from hintCerts.
+ */
+ if (numHintCerts != 0) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (hintCerts, 0, &firstHintCert, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)targetCert,
+ firstHintCert,
+ &isDuplicate,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (isDuplicate) {
+ PKIX_CHECK(PKIX_List_DeleteItem
+ (hintCerts, 0, plContext),
+ PKIX_LISTGETITEMFAILED);
+ }
+ PKIX_DECREF(firstHintCert);
+ }
+
+ }
+
+ if (targetCert == NULL) {
+ PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Cert_IsLeafCertTrusted
+ (targetCert,
+ &trusted,
+ plContext),
+ PKIX_CERTISCERTTRUSTEDFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames
+ (targetCert,
+ &targetSubjNames,
+ plContext),
+ PKIX_CERTGETALLSUBJECTNAMESFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (targetCert, &targetPubKey, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&tentativeChain, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (tentativeChain, (PKIX_PL_Object *)targetCert, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ if (procParams->qualifyTargetCert) {
+ /* EE cert validation */
+ /* Sync up the time on the target selector parameter struct. */
+ PKIX_CHECK(
+ PKIX_ComCertSelParams_SetCertificateValid(targetParams,
+ testDate,
+ plContext),
+ PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
+ (targetConstraints, &selectorCallback, plContext),
+ PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
+
+ pkixErrorResult =
+ (*selectorCallback)(targetConstraints, targetCert,
+ plContext);
+ if (pkixErrorResult) {
+ pkixErrorClass = pkixErrorResult->errClass;
+ if (pkixErrorClass == PKIX_FATAL_ERROR) {
+ goto cleanup;
+ }
+ if (pVerifyNode != NULL) {
+ PKIX_Error *tempResult =
+ pkix_VerifyNode_Create(targetCert, 0,
+ pkixErrorResult,
+ pVerifyNode,
+ plContext);
+ if (tempResult) {
+ PKIX_DECREF(pkixErrorResult);
+ pkixErrorResult = tempResult;
+ pkixErrorCode = PKIX_VERIFYNODECREATEFAILED;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+ }
+ }
+ pkixErrorCode = PKIX_CERTCHECKVALIDITYFAILED;
+ goto cleanup;
+ }
+ }
+
+ /* If the EE cert is trusted, force success. We only want to do
+ * this if we aren't validating against a policy (like EV). */
+ if (trusted && procParams->initialPolicies == NULL) {
+ if (pVerifyNode != NULL) {
+ PKIX_Error *tempResult =
+ pkix_VerifyNode_Create(targetCert, 0, NULL,
+ pVerifyNode,
+ plContext);
+ if (tempResult) {
+ pkixErrorResult = tempResult;
+ pkixErrorCode = PKIX_VERIFYNODECREATEFAILED;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+ }
+ }
+ PKIX_CHECK(pkix_ValidateResult_Create
+ (targetPubKey, NULL /* anchor */,
+ NULL /* policyTree */, &valResult, plContext),
+ PKIX_VALIDATERESULTCREATEFAILED);
+ PKIX_CHECK(
+ pkix_BuildResult_Create(valResult, tentativeChain,
+ &buildResult, plContext),
+ PKIX_BUILDRESULTCREATEFAILED);
+ *pBuildResult = buildResult;
+ /* Note that *pState is NULL. The only side effect is that
+ * the cert chain won't be cached in PKIX_BuildChain, which
+ * is fine. */
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
+ (procParams, &certStores, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (certStores, &numCertStores, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ /* Reorder CertStores so trusted are at front of the List */
+ if (numCertStores > 1) {
+ for (i = numCertStores - 1; i > 0; i--) {
+ PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem
+ (certStores,
+ i,
+ (PKIX_PL_Object **)&certStore,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+ PKIX_CHECK_ONLY_FATAL(PKIX_CertStore_GetTrustCallback
+ (certStore, &trustCallback, plContext),
+ PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
+
+ if (trustCallback != NULL) {
+ /* Is a trusted Cert, move CertStore to front */
+ PKIX_CHECK(PKIX_List_DeleteItem
+ (certStores, i, plContext),
+ PKIX_LISTDELETEITEMFAILED);
+ PKIX_CHECK(PKIX_List_InsertItem
+ (certStores,
+ 0,
+ (PKIX_PL_Object *)certStore,
+ plContext),
+ PKIX_LISTINSERTITEMFAILED);
+
+ }
+
+ PKIX_DECREF(certStore);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
+ (procParams, &userCheckers, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
+ (procParams, &revChecker, plContext),
+ PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
+ /* Do not initialize AIA manager if we are not going to fetch
+ * cert using aia url. */
+ if (procParams->useAIAForCertFetching) {
+ PKIX_CHECK(PKIX_PL_AIAMgr_Create(&aiaMgr, plContext),
+ PKIX_AIAMGRCREATEFAILED);
+ }
+
+ /*
+ * We initialize all the fields of buildConstants here, in one place,
+ * just to help keep track and ensure that we got everything.
+ */
+
+ buildConstants.numAnchors = numAnchors;
+ buildConstants.numCertStores = numCertStores;
+ buildConstants.numHintCerts = numHintCerts;
+ buildConstants.procParams = procParams;
+ buildConstants.testDate = testDate;
+ buildConstants.timeLimit = NULL;
+ buildConstants.targetCert = targetCert;
+ buildConstants.targetPubKey = targetPubKey;
+ buildConstants.certStores = certStores;
+ buildConstants.anchors = anchors;
+ buildConstants.userCheckers = userCheckers;
+ buildConstants.hintCerts = hintCerts;
+ buildConstants.revChecker = revChecker;
+ buildConstants.aiaMgr = aiaMgr;
+ buildConstants.trustOnlyUserAnchors =
+ procParams->useOnlyTrustAnchors;
+
+ PKIX_CHECK(pkix_Build_GetResourceLimits(&buildConstants, plContext),
+ PKIX_BUILDGETRESOURCELIMITSFAILED);
+
+ PKIX_CHECK(pkix_ForwardBuilderState_Create
+ (0, /* PKIX_UInt32 traversedCACerts */
+ buildConstants.maxFanout,
+ buildConstants.maxDepth,
+ PKIX_TRUE, /* PKIX_Boolean canBeCached */
+ NULL, /* PKIX_Date *validityDate */
+ targetCert, /* PKIX_PL_Cert *prevCert */
+ targetSubjNames, /* PKIX_List *traversedSubjNames */
+ tentativeChain, /* PKIX_List *trustChain */
+ NULL, /* PKIX_ForwardBuilderState *parent */
+ &state, /* PKIX_ForwardBuilderState **pState */
+ plContext),
+ PKIX_BUILDSTATECREATEFAILED);
+
+ state->buildConstants.numAnchors = buildConstants.numAnchors;
+ state->buildConstants.numCertStores = buildConstants.numCertStores;
+ state->buildConstants.numHintCerts = buildConstants.numHintCerts;
+ state->buildConstants.maxFanout = buildConstants.maxFanout;
+ state->buildConstants.maxDepth = buildConstants.maxDepth;
+ state->buildConstants.maxTime = buildConstants.maxTime;
+ state->buildConstants.procParams = buildConstants.procParams;
+ PKIX_INCREF(buildConstants.testDate);
+ state->buildConstants.testDate = buildConstants.testDate;
+ state->buildConstants.timeLimit = buildConstants.timeLimit;
+ PKIX_INCREF(buildConstants.targetCert);
+ state->buildConstants.targetCert = buildConstants.targetCert;
+ PKIX_INCREF(buildConstants.targetPubKey);
+ state->buildConstants.targetPubKey =
+ buildConstants.targetPubKey;
+ PKIX_INCREF(buildConstants.certStores);
+ state->buildConstants.certStores = buildConstants.certStores;
+ PKIX_INCREF(buildConstants.anchors);
+ state->buildConstants.anchors = buildConstants.anchors;
+ PKIX_INCREF(buildConstants.userCheckers);
+ state->buildConstants.userCheckers =
+ buildConstants.userCheckers;
+ PKIX_INCREF(buildConstants.hintCerts);
+ state->buildConstants.hintCerts = buildConstants.hintCerts;
+ PKIX_INCREF(buildConstants.revChecker);
+ state->buildConstants.revChecker = buildConstants.revChecker;
+ state->buildConstants.aiaMgr = buildConstants.aiaMgr;
+ aiaMgr = NULL;
+ state->buildConstants.trustOnlyUserAnchors =
+ buildConstants.trustOnlyUserAnchors;
+
+ if (buildConstants.maxTime != 0) {
+ PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
+ (buildConstants.maxTime,
+ &state->buildConstants.timeLimit,
+ plContext),
+ PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
+ }
+
+ if (pVerifyNode != NULL) {
+ PKIX_Error *tempResult =
+ pkix_VerifyNode_Create(targetCert, 0, NULL,
+ &(state->verifyNode),
+ plContext);
+ if (tempResult) {
+ pkixErrorResult = tempResult;
+ pkixErrorCode = PKIX_VERIFYNODECREATEFAILED;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+ }
+ }
+
+ PKIX_CHECK_ONLY_FATAL(
+ pkix_Build_CheckInCache(state, &buildResult,
+ &nbioContext, plContext),
+ PKIX_UNABLETOBUILDCHAIN);
+ if (nbioContext) {
+ *pNBIOContext = nbioContext;
+ *pState = state;
+ state = NULL;
+ goto cleanup;
+ }
+ if (buildResult) {
+ *pBuildResult = buildResult;
+ if (pVerifyNode != NULL) {
+ *pVerifyNode = state->verifyNode;
+ state->verifyNode = NULL;
+ }
+ goto cleanup;
+ }
+ }
+
+ /* If we're resuming after non-blocking I/O we need to get SubjNames */
+ if (targetSubjNames == NULL) {
+ PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames
+ (state->buildConstants.targetCert,
+ &targetSubjNames,
+ plContext),
+ PKIX_CERTGETALLSUBJECTNAMESFAILED);
+ }
+
+ state->status = BUILD_INITIAL;
+
+ pkixErrorResult =
+ pkix_BuildForwardDepthFirstSearch(&nbioContext, state,
+ &valResult, plContext);
+
+ /* non-null nbioContext means the build would block */
+ if (pkixErrorResult == NULL && nbioContext != NULL) {
+
+ *pNBIOContext = nbioContext;
+ *pBuildResult = NULL;
+
+ /* no valResult means the build has failed */
+ } else {
+ if (pVerifyNode != NULL) {
+ PKIX_INCREF(state->verifyNode);
+ *pVerifyNode = state->verifyNode;
+ }
+
+ if (valResult == NULL || pkixErrorResult)
+ PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN);
+ PKIX_CHECK(
+ pkix_BuildResult_Create(valResult, state->trustChain,
+ &buildResult, plContext),
+ PKIX_BUILDRESULTCREATEFAILED);
+ *pBuildResult = buildResult;
+ }
+
+ *pState = state;
+ state = NULL;
+
+cleanup:
+
+ PKIX_DECREF(targetConstraints);
+ PKIX_DECREF(targetParams);
+ PKIX_DECREF(anchors);
+ PKIX_DECREF(targetSubjNames);
+ PKIX_DECREF(targetCert);
+ PKIX_DECREF(revChecker);
+ PKIX_DECREF(certStores);
+ PKIX_DECREF(certStore);
+ PKIX_DECREF(userCheckers);
+ PKIX_DECREF(hintCerts);
+ PKIX_DECREF(firstHintCert);
+ PKIX_DECREF(testDate);
+ PKIX_DECREF(targetPubKey);
+ PKIX_DECREF(tentativeChain);
+ PKIX_DECREF(valResult);
+ PKIX_DECREF(certList);
+ PKIX_DECREF(trustedCert);
+ PKIX_DECREF(state);
+ PKIX_DECREF(aiaMgr);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_Build_ResumeBuildChain
+ * DESCRIPTION:
+ *
+ * This function continues the search for a BuildChain, using the parameters
+ * provided in "procParams" and the ForwardBuilderState pointed to by "state".
+ *
+ * If a successful chain is built, this function stores the BuildResult at
+ * "pBuildResult". Alternatively, if an operation using non-blocking I/O
+ * is in progress and the operation has not been completed, this function
+ * stores the FowardBuilderState at "pState" and NULL at "pBuildResult".
+ * Finally, if chain building was unsuccessful, this function stores NULL
+ * at both "pState" and at "pBuildResult".
+ *
+ * PARAMETERS:
+ * "pNBIOContext"
+ * Address at which the NBIOContext is stored indicating whether the
+ * validation is complete. Must be non-NULL.
+ * "pState"
+ * Address at which the ForwardBuilderState is provided for resumption of
+ * the chain building attempt; also, the address at which the
+ * ForwardBuilderStateis stored, if the chain building is suspended for
+ * waiting I/O. Must be non-NULL.
+ * "pBuildResult"
+ * Address at which the BuildResult is stored, after a successful build.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Build Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_Build_ResumeBuildChain(
+ void **pNBIOContext,
+ PKIX_ForwardBuilderState *state,
+ PKIX_BuildResult **pBuildResult,
+ PKIX_VerifyNode **pVerifyNode,
+ void *plContext)
+{
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_Build_ResumeBuildChain");
+ PKIX_NULLCHECK_TWO(state, pBuildResult);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ pkixErrorResult =
+ pkix_BuildForwardDepthFirstSearch(&nbioContext, state,
+ &valResult, plContext);
+
+ /* non-null nbioContext means the build would block */
+ if (pkixErrorResult == NULL && nbioContext != NULL) {
+
+ *pNBIOContext = nbioContext;
+ *pBuildResult = NULL;
+
+ /* no valResult means the build has failed */
+ } else {
+ if (pVerifyNode != NULL) {
+ PKIX_INCREF(state->verifyNode);
+ *pVerifyNode = state->verifyNode;
+ }
+
+ if (valResult == NULL || pkixErrorResult)
+ PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN);
+
+ PKIX_CHECK(
+ pkix_BuildResult_Create(valResult, state->trustChain,
+ &buildResult, plContext),
+ PKIX_BUILDRESULTCREATEFAILED);
+ *pBuildResult = buildResult;
+ }
+
+cleanup:
+
+ PKIX_DECREF(valResult);
+
+ PKIX_RETURN(BUILD);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_BuildChain (see comments in pkix.h)
+ */
+PKIX_Error *
+PKIX_BuildChain(
+ PKIX_ProcessingParams *procParams,
+ void **pNBIOContext,
+ void **pState,
+ PKIX_BuildResult **pBuildResult,
+ PKIX_VerifyNode **pVerifyNode,
+ void *plContext)
+{
+ PKIX_ForwardBuilderState *state = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(BUILD, "PKIX_BuildChain");
+ PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ if (*pState == NULL) {
+ PKIX_CHECK(pkix_Build_InitiateBuildChain
+ (procParams,
+ &nbioContext,
+ &state,
+ &buildResult,
+ pVerifyNode,
+ plContext),
+ PKIX_BUILDINITIATEBUILDCHAINFAILED);
+ } else {
+ state = (PKIX_ForwardBuilderState *)(*pState);
+ *pState = NULL; /* no net change in reference count */
+ if (state->status == BUILD_SHORTCUTPENDING) {
+ PKIX_CHECK(pkix_Build_InitiateBuildChain
+ (procParams,
+ &nbioContext,
+ &state,
+ &buildResult,
+ pVerifyNode,
+ plContext),
+ PKIX_BUILDINITIATEBUILDCHAINFAILED);
+ } else {
+ PKIX_CHECK(pkix_Build_ResumeBuildChain
+ (&nbioContext,
+ state,
+ &buildResult,
+ pVerifyNode,
+ plContext),
+ PKIX_BUILDINITIATEBUILDCHAINFAILED);
+ }
+ }
+
+ /* non-null nbioContext means the build would block */
+ if (nbioContext != NULL) {
+
+ *pNBIOContext = nbioContext;
+ *pState = state;
+ state = NULL;
+ *pBuildResult = NULL;
+
+ /* no buildResult means the build has failed */
+ } else if (buildResult == NULL) {
+ PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN);
+ } else {
+ /*
+ * If we made a successful chain by combining the target Cert
+ * with one of the Trust Anchors, we may have never created a
+ * validityDate. We treat this situation as
+ * canBeCached = PKIX_FALSE.
+ */
+ if ((state != NULL) &&
+ ((state->validityDate) != NULL) &&
+ (state->canBeCached)) {
+ PKIX_CHECK(pkix_CacheCertChain_Add
+ (state->buildConstants.targetCert,
+ state->buildConstants.anchors,
+ state->validityDate,
+ buildResult,
+ plContext),
+ PKIX_CACHECERTCHAINADDFAILED);
+ }
+
+ *pState = NULL;
+ *pBuildResult = buildResult;
+ buildResult = NULL;
+ }
+
+cleanup:
+ PKIX_DECREF(buildResult);
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(BUILD);
+}
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_build.h b/security/nss/lib/libpkix/pkix/top/pkix_build.h
new file mode 100644
index 0000000000..eeba9239d8
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/pkix_build.h
@@ -0,0 +1,120 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_build.h
+ *
+ * Header file for buildChain function
+ *
+ */
+
+#ifndef _PKIX_BUILD_H
+#define _PKIX_BUILD_H
+#include "pkix_tools.h"
+#ifndef NSS_PKIX_NO_LDAP
+#include "pkix_pl_ldapt.h"
+#endif
+#include "pkix_ekuchecker.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ BUILD_SHORTCUTPENDING,
+ BUILD_INITIAL,
+ BUILD_TRYAIA,
+ BUILD_AIAPENDING,
+ BUILD_COLLECTINGCERTS,
+ BUILD_GATHERPENDING,
+ BUILD_CERTVALIDATING,
+ BUILD_ABANDONNODE,
+ BUILD_DATEPREP,
+ BUILD_CHECKTRUSTED,
+ BUILD_CHECKTRUSTED2,
+ BUILD_ADDTOCHAIN,
+ BUILD_VALCHAIN,
+ BUILD_VALCHAIN2,
+ BUILD_EXTENDCHAIN,
+ BUILD_GETNEXTCERT
+} BuildStatus;
+
+typedef struct BuildConstantsStruct BuildConstants;
+
+/*
+ * These fields (the ones that are objects) are not reference-counted
+ * in *each* state, but only in the root, the state that has no parent.
+ * That saves time in creation and destruction of child states, but is
+ * safe enough since they are constants.
+ */
+struct BuildConstantsStruct {
+ PKIX_UInt32 numAnchors;
+ PKIX_UInt32 numCertStores;
+ PKIX_UInt32 numHintCerts;
+ PKIX_UInt32 maxDepth;
+ PKIX_UInt32 maxFanout;
+ PKIX_UInt32 maxTime;
+ PKIX_ProcessingParams *procParams;
+ PKIX_PL_Date *testDate;
+ PKIX_PL_Date *timeLimit;
+ PKIX_PL_Cert *targetCert;
+ PKIX_PL_PublicKey *targetPubKey;
+ PKIX_List *certStores;
+ PKIX_List *anchors;
+ PKIX_List *userCheckers;
+ PKIX_List *hintCerts;
+ PKIX_RevocationChecker *revChecker;
+ PKIX_PL_AIAMgr *aiaMgr;
+ PKIX_Boolean useAIAForCertFetching;
+ PKIX_Boolean trustOnlyUserAnchors;
+};
+
+struct PKIX_ForwardBuilderStateStruct{
+ BuildStatus status;
+ PKIX_Int32 traversedCACerts;
+ PKIX_UInt32 certStoreIndex;
+ PKIX_UInt32 numCerts;
+ PKIX_UInt32 numAias;
+ PKIX_UInt32 certIndex;
+ PKIX_UInt32 aiaIndex;
+ PKIX_UInt32 certCheckedIndex;
+ PKIX_UInt32 checkerIndex;
+ PKIX_UInt32 hintCertIndex;
+ PKIX_UInt32 numFanout;
+ PKIX_UInt32 numDepth;
+ PKIX_UInt32 reasonCode;
+ PKIX_Boolean canBeCached;
+ PKIX_Boolean useOnlyLocal;
+ PKIX_Boolean revChecking;
+ PKIX_Boolean usingHintCerts;
+ PKIX_Boolean certLoopingDetected;
+ PKIX_PL_Date *validityDate;
+ PKIX_PL_Cert *prevCert;
+ PKIX_PL_Cert *candidateCert;
+ PKIX_List *traversedSubjNames;
+ PKIX_List *trustChain;
+ PKIX_List *aia;
+ PKIX_List *candidateCerts;
+ PKIX_List *reversedCertChain;
+ PKIX_List *checkedCritExtOIDs;
+ PKIX_List *checkerChain;
+ PKIX_CertSelector *certSel;
+ PKIX_VerifyNode *verifyNode;
+ void *client; /* messageHandler, such as LDAPClient */
+ PKIX_ForwardBuilderState *parentState;
+ BuildConstants buildConstants;
+};
+
+/* --Private-Functions-------------------------------------------- */
+
+PKIX_Error *
+pkix_ForwardBuilderState_RegisterSelf(void *plContext);
+
+PKIX_Error *
+PKIX_Build_GetNBIOContext(void *state, void **pNBIOContext, void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_BUILD_H */
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c
new file mode 100644
index 0000000000..aad0e1aaf3
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.c
@@ -0,0 +1,210 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_lifecycle.c
+ *
+ * Top level initialize and shutdown functions
+ *
+ */
+
+#include "pkix_lifecycle.h"
+
+static PKIX_Boolean pkixIsInitialized;
+
+/* Lock used by Logger - is reentrant by the same thread */
+extern PKIX_PL_MonitorLock *pkixLoggerLock;
+
+/*
+ * Following pkix_* variables are for debugging purpose. They should be taken
+ * out eventually. The purpose is to verify cache tables usage (via debugger).
+ */
+int pkix_ccAddCount = 0;
+int pkix_ccLookupCount = 0;
+int pkix_ccRemoveCount = 0;
+int pkix_cAddCount = 0;
+int pkix_cLookupCount = 0;
+int pkix_cRemoveCount = 0;
+int pkix_ceAddCount = 0;
+int pkix_ceLookupCount = 0;
+
+PKIX_PL_HashTable *cachedCrlSigTable = NULL;
+PKIX_PL_HashTable *cachedCertSigTable = NULL;
+PKIX_PL_HashTable *cachedCertChainTable = NULL;
+PKIX_PL_HashTable *cachedCertTable = NULL;
+PKIX_PL_HashTable *cachedCrlEntryTable = NULL;
+PKIX_PL_HashTable *aiaConnectionCache = NULL;
+PKIX_PL_HashTable *httpSocketCache = NULL;
+
+extern PKIX_List *pkixLoggers;
+extern PKIX_List *pkixLoggersErrors;
+extern PKIX_List *pkixLoggersDebugTrace;
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_Initialize (see comments in pkix.h)
+ */
+PKIX_Error *
+PKIX_Initialize(
+ PKIX_Boolean platformInitNeeded,
+ PKIX_UInt32 desiredMajorVersion,
+ PKIX_UInt32 minDesiredMinorVersion,
+ PKIX_UInt32 maxDesiredMinorVersion,
+ PKIX_UInt32 *pActualMinorVersion,
+ void **pPlContext)
+{
+ void *plContext = NULL;
+
+ PKIX_ENTER(LIFECYCLE, "PKIX_Initialize");
+ PKIX_NULLCHECK_ONE(pPlContext);
+
+ /*
+ * If we are called a second time other than in the situation handled
+ * above, we return a positive status.
+ */
+ if (pkixIsInitialized){
+ /* Already initialized */
+ PKIX_RETURN(LIFECYCLE);
+ }
+
+ PKIX_CHECK(PKIX_PL_Initialize
+ (platformInitNeeded, PKIX_FALSE, &plContext),
+ PKIX_INITIALIZEFAILED);
+
+ *pPlContext = plContext;
+
+ if (desiredMajorVersion != PKIX_MAJOR_VERSION){
+ PKIX_ERROR(PKIX_MAJORVERSIONSDONTMATCH);
+ }
+
+ if ((minDesiredMinorVersion > PKIX_MINOR_VERSION) ||
+ (maxDesiredMinorVersion < PKIX_MINOR_VERSION)){
+ PKIX_ERROR(PKIX_MINORVERSIONNOTBETWEENDESIREDMINANDMAX);
+ }
+
+ *pActualMinorVersion = PKIX_MINOR_VERSION;
+
+ /* Create Cache Tables
+ * Do not initialize hash tables for object leak test */
+#if !defined(PKIX_OBJECT_LEAK_TEST)
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (32, 0, &cachedCertSigTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (32, 0, &cachedCrlSigTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (32, 10, &cachedCertChainTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (32, 10, &cachedCertTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (32, 10, &cachedCrlEntryTable, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (5, 5, &aiaConnectionCache, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
+#ifdef PKIX_SOCKETCACHE
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (5, 5, &httpSocketCache, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+#endif
+ if (pkixLoggerLock == NULL) {
+ PKIX_CHECK(PKIX_PL_MonitorLock_Create
+ (&pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKCREATEFAILED);
+ }
+#else
+ fnInvTable = PL_NewHashTable(0, pkix_ErrorGen_Hash,
+ PL_CompareValues,
+ PL_CompareValues, NULL, NULL);
+ if (!fnInvTable) {
+ PKIX_ERROR(PKIX_HASHTABLECREATEFAILED);
+ }
+
+ fnStackNameArr = PORT_ZNewArray(char*, MAX_STACK_DEPTH);
+ if (!fnStackNameArr) {
+ PKIX_ERROR(PKIX_HASHTABLECREATEFAILED);
+ }
+
+ fnStackInvCountArr = PORT_ZNewArray(PKIX_UInt32, MAX_STACK_DEPTH);
+ if (!fnStackInvCountArr) {
+ PKIX_ERROR(PKIX_HASHTABLECREATEFAILED);
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+ pkixIsInitialized = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(LIFECYCLE);
+}
+
+/*
+ * FUNCTION: PKIX_Shutdown (see comments in pkix.h)
+ */
+PKIX_Error *
+PKIX_Shutdown(void *plContext)
+{
+ PKIX_List *savedPkixLoggers = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+
+ PKIX_ENTER(LIFECYCLE, "PKIX_Shutdown");
+
+ if (!pkixIsInitialized){
+ /* The library was not initialized */
+ PKIX_RETURN(LIFECYCLE);
+ }
+
+ pkixIsInitialized = PKIX_FALSE;
+
+ if (pkixLoggers) {
+ savedPkixLoggers = pkixLoggers;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggers = NULL;
+ pkixLoggersErrors = NULL;
+ pkixLoggersDebugTrace = NULL;
+ PKIX_DECREF(savedPkixLoggers);
+ PKIX_DECREF(savedPkixLoggersErrors);
+ PKIX_DECREF(savedPkixLoggersDebugTrace);
+ }
+ PKIX_DECREF(pkixLoggerLock);
+
+ /* Destroy Cache Tables */
+ PKIX_DECREF(cachedCertSigTable);
+ PKIX_DECREF(cachedCrlSigTable);
+ PKIX_DECREF(cachedCertChainTable);
+ PKIX_DECREF(cachedCertTable);
+ PKIX_DECREF(cachedCrlEntryTable);
+ PKIX_DECREF(aiaConnectionCache);
+ PKIX_DECREF(httpSocketCache);
+
+ /* Clean up any temporary errors that happened during shutdown */
+ if (pkixErrorList) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorList, plContext);
+ pkixErrorList = NULL;
+ }
+
+ PKIX_CHECK(PKIX_PL_Shutdown(plContext),
+ PKIX_SHUTDOWNFAILED);
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+ PORT_Free(fnStackInvCountArr);
+ PORT_Free(fnStackNameArr);
+ PL_HashTableDestroy(fnInvTable);
+#endif
+
+cleanup:
+
+ PKIX_RETURN(LIFECYCLE);
+}
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.h b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.h
new file mode 100644
index 0000000000..02631229cb
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/pkix_lifecycle.h
@@ -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_lifecycle.h
+ *
+ * Header file for initialize and shutdown functions.
+ *
+ */
+
+#ifndef _PKIX_LIFECYCLE_H
+#define _PKIX_LIFECYCLE_H
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_LIFECYCLE_H */
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_validate.c b/security/nss/lib/libpkix/pkix/top/pkix_validate.c
new file mode 100644
index 0000000000..1e5dec795a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/pkix_validate.c
@@ -0,0 +1,1451 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_validate.c
+ *
+ * Top level validateChain function
+ *
+ */
+
+#include "pkix_validate.h"
+#include "pkix_pl_common.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_AddToVerifyLog
+ * DESCRIPTION:
+ *
+ * This function returns immediately if the address for the VerifyNode tree
+ * pointed to by "pVerifyTree" is NULL. Otherwise it creates a new VerifyNode
+ * from the Cert pointed to by "cert" and the Error pointed to by "error",
+ * and inserts it at the depth in the VerifyNode tree determined by "depth". A
+ * depth of zero means that this function creates the root node of a new tree.
+ *
+ * Note: this function does not include the means of choosing among branches
+ * of a tree. It is intended for non-branching trees, that is, where each
+ * parent node has only a single child node.
+ *
+ * PARAMETERS:
+ * "cert"
+ * The address of the Cert to be included in the new VerifyNode. Must be
+ * non-NULL.
+ * "depth"
+ * The UInt32 value of the depth.
+ * "error"
+ * The address of the Error to be included in the new VerifyNode.
+ * "pVerifyTree"
+ * The address of the VerifyNode tree into which the created VerifyNode
+ * is to be inserted. The node is not created if VerifyTree is NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Validate Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_AddToVerifyLog(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 depth,
+ PKIX_Error *error,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext)
+{
+
+ PKIX_VerifyNode *verifyNode = NULL;
+
+ PKIX_ENTER(VALIDATE, "pkix_AddToVerifyLog");
+ PKIX_NULLCHECK_ONE(cert);
+
+ if (pVerifyTree) { /* nothing to do if no address given for log */
+
+ PKIX_CHECK(pkix_VerifyNode_Create
+ (cert, depth, error, &verifyNode, plContext),
+ PKIX_VERIFYNODECREATEFAILED);
+
+ if (depth == 0) {
+ /* We just created the root node */
+ *pVerifyTree = verifyNode;
+ } else {
+ PKIX_CHECK(pkix_VerifyNode_AddToChain
+ (*pVerifyTree, verifyNode, plContext),
+ PKIX_VERIFYNODEADDTOCHAINFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(VALIDATE);
+
+}
+
+/*
+ * FUNCTION: pkix_CheckCert
+ * DESCRIPTION:
+ *
+ * Checks whether the Cert pointed to by "cert" successfully validates
+ * using the List of CertChainCheckers pointed to by "checkers". If the
+ * certificate does not validate, an Error pointer is returned.
+ *
+ * This function should be called initially with the UInt32 pointed to by
+ * "pCheckerIndex" containing zero, and the pointer at "pNBIOContext"
+ * containing NULL. If a checker does non-blocking I/O, this function will
+ * return with the index of that checker stored at "pCheckerIndex" and a
+ * platform-dependent non-blocking I/O context stored at "pNBIOContext".
+ * A subsequent call to this function with those values intact will allow the
+ * checking to resume where it left off. This should be repeated until the
+ * function returns with NULL stored at "pNBIOContext".
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert to validate. Must be non-NULL.
+ * "checkers"
+ * List of CertChainCheckers which must each validate the certificate.
+ * Must be non-NULL.
+ * "checkedExtOIDs"
+ * List of PKIX_PL_OID that has been processed. If called from building
+ * chain, it is the list of critical extension OIDs that has been
+ * processed prior to validation. May be NULL.
+ * "pCheckerIndex"
+ * Address at which is stored the the index, within the List "checkers",
+ * of a checker whose processing was interrupted by non-blocking I/O.
+ * Must be non-NULL.
+ * "pNBIOContext"
+ * Address at which is stored platform-specific non-blocking I/O context.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Validate Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_CheckCert(
+ PKIX_PL_Cert *cert,
+ PKIX_List *checkers,
+ PKIX_List *checkedExtOIDsList,
+ PKIX_UInt32 *pCheckerIndex,
+ void **pNBIOContext,
+ void *plContext)
+{
+ PKIX_CertChainChecker_CheckCallback checkerCheck = NULL;
+ PKIX_CertChainChecker *checker = NULL;
+ PKIX_List *unresCritExtOIDs = NULL;
+ PKIX_UInt32 numCheckers;
+ PKIX_UInt32 numUnresCritExtOIDs = 0;
+ PKIX_UInt32 checkerIndex = 0;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(VALIDATE, "pkix_CheckCert");
+ PKIX_NULLCHECK_FOUR(cert, checkers, pCheckerIndex, pNBIOContext);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL; /* prepare for case of error exit */
+
+ PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs
+ (cert, &unresCritExtOIDs, plContext),
+ PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (checkerIndex = *pCheckerIndex;
+ checkerIndex < numCheckers;
+ checkerIndex++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (checkers,
+ checkerIndex,
+ (PKIX_PL_Object **)&checker,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback
+ (checker, &checkerCheck, plContext),
+ PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED);
+
+ PKIX_CHECK(checkerCheck(checker, cert, unresCritExtOIDs,
+ &nbioContext, plContext),
+ PKIX_CERTCHAINCHECKERCHECKFAILED);
+
+ if (nbioContext != NULL) {
+ *pCheckerIndex = checkerIndex;
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ PKIX_DECREF(checker);
+ }
+
+ if (unresCritExtOIDs){
+
+#ifdef PKIX_VALIDATEDEBUG
+ {
+ PKIX_PL_String *oidString = NULL;
+ PKIX_UInt32 length;
+ char *oidAscii = NULL;
+ PKIX_TOSTRING(unresCritExtOIDs, &oidString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (oidString,
+ PKIX_ESCASCII,
+ (void **) &oidAscii,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+ PKIX_VALIDATE_DEBUG_ARG
+ ("unrecognized critical extension OIDs:"
+ " %s\n", oidAscii);
+ PKIX_DECREF(oidString);
+ PKIX_PL_Free(oidAscii, plContext);
+ }
+#endif
+
+ if (checkedExtOIDsList != NULL) {
+ /* Take out OID's that had been processed, if any */
+ PKIX_CHECK(pkix_List_RemoveItems
+ (unresCritExtOIDs,
+ checkedExtOIDsList,
+ plContext),
+ PKIX_LISTREMOVEITEMSFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (unresCritExtOIDs, &numUnresCritExtOIDs, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numUnresCritExtOIDs != 0){
+ PKIX_ERROR(PKIX_UNRECOGNIZEDCRITICALEXTENSION);
+ }
+
+ }
+
+cleanup:
+
+ PKIX_DECREF(checker);
+ PKIX_DECREF(unresCritExtOIDs);
+
+ PKIX_RETURN(VALIDATE);
+
+}
+
+/*
+ * FUNCTION: pkix_InitializeCheckers
+ * DESCRIPTION:
+ *
+ * Creates several checkers and initializes them with values derived from the
+ * TrustAnchor pointed to by "anchor", the ProcessingParams pointed to by
+ * "procParams", and the number of Certs in the Chain, represented by
+ * "numCerts". The List of checkers is stored at "pCheckers".
+ *
+ * PARAMETERS:
+ * "anchor"
+ * Address of TrustAnchor used to initialize the SignatureChecker and
+ * NameChainingChecker. Must be non-NULL.
+ * "procParams"
+ * Address of ProcessingParams used to initialize the ExpirationChecker
+ * and TargetCertChecker. Must be non-NULL.
+ * "numCerts"
+ * Number of certificates in the CertChain.
+ * "pCheckers"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Validate Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_InitializeCheckers(
+ PKIX_TrustAnchor *anchor,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 numCerts,
+ PKIX_List **pCheckers,
+ void *plContext)
+{
+ PKIX_CertChainChecker *targetCertChecker = NULL;
+ PKIX_CertChainChecker *expirationChecker = NULL;
+ PKIX_CertChainChecker *nameChainingChecker = NULL;
+ PKIX_CertChainChecker *nameConstraintsChecker = NULL;
+ PKIX_CertChainChecker *basicConstraintsChecker = NULL;
+ PKIX_CertChainChecker *policyChecker = NULL;
+ PKIX_CertChainChecker *sigChecker = NULL;
+ PKIX_CertChainChecker *defaultCrlChecker = NULL;
+ PKIX_CertChainChecker *userChecker = NULL;
+ PKIX_PL_X500Name *trustedCAName = NULL;
+ PKIX_PL_PublicKey *trustedPubKey = NULL;
+ PKIX_List *checkers = NULL;
+ PKIX_PL_Date *testDate = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_CertNameConstraints *trustedNC = NULL;
+ PKIX_List *initialPolicies = NULL;
+ PKIX_Boolean policyQualifiersRejected = PKIX_FALSE;
+ PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
+ PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
+ PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
+ PKIX_List *userCheckersList = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_UInt32 numCertCheckers = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(VALIDATE, "pkix_InitializeCheckers");
+ PKIX_NULLCHECK_THREE(anchor, procParams, pCheckers);
+ PKIX_CHECK(PKIX_List_Create(&checkers, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ /*
+ * The TrustAnchor may have been created using CreateWithCert
+ * (in which case GetCAPublicKey and GetCAName will return NULL)
+ * or may have been created using CreateWithNameKeyPair (in which
+ * case GetTrustedCert will return NULL. So we call GetTrustedCert
+ * and populate trustedPubKey and trustedCAName accordingly.
+ */
+
+ PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
+ (anchor, &trustedCert, plContext),
+ PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
+
+ if (trustedCert){
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (trustedCert, &trustedPubKey, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject
+ (trustedCert, &trustedCAName, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+ } else {
+ PKIX_CHECK(PKIX_TrustAnchor_GetCAPublicKey
+ (anchor, &trustedPubKey, plContext),
+ PKIX_TRUSTANCHORGETCAPUBLICKEYFAILED);
+
+ PKIX_CHECK(PKIX_TrustAnchor_GetCAName
+ (anchor, &trustedCAName, plContext),
+ PKIX_TRUSTANCHORGETCANAMEFAILED);
+ }
+
+ PKIX_NULLCHECK_TWO(trustedPubKey, trustedCAName);
+
+ PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints
+ (anchor, &trustedNC, plContext),
+ PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
+ (procParams, &certSelector, plContext),
+ PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetDate
+ (procParams, &testDate, plContext),
+ PKIX_PROCESSINGPARAMSGETDATEFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies
+ (procParams, &initialPolicies, plContext),
+ PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected
+ (procParams, &policyQualifiersRejected, plContext),
+ PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited
+ (procParams, &initialPolicyMappingInhibit, plContext),
+ PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited
+ (procParams, &initialAnyPolicyInhibit, plContext),
+ PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired
+ (procParams, &initialExplicitPolicy, plContext),
+ PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
+ (procParams, &certStores, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
+ (procParams, &userCheckersList, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
+
+ /* now, initialize all the checkers */
+ PKIX_CHECK(pkix_TargetCertChecker_Initialize
+ (certSelector, numCerts, &targetCertChecker, plContext),
+ PKIX_TARGETCERTCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(pkix_ExpirationChecker_Initialize
+ (testDate, &expirationChecker, plContext),
+ PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(pkix_NameChainingChecker_Initialize
+ (trustedCAName, &nameChainingChecker, plContext),
+ PKIX_NAMECHAININGCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(pkix_NameConstraintsChecker_Initialize
+ (trustedNC, numCerts, &nameConstraintsChecker, plContext),
+ PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(pkix_BasicConstraintsChecker_Initialize
+ (numCerts, &basicConstraintsChecker, plContext),
+ PKIX_BASICCONSTRAINTSCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(pkix_PolicyChecker_Initialize
+ (initialPolicies,
+ policyQualifiersRejected,
+ initialPolicyMappingInhibit,
+ initialExplicitPolicy,
+ initialAnyPolicyInhibit,
+ numCerts,
+ &policyChecker,
+ plContext),
+ PKIX_POLICYCHECKERINITIALIZEFAILED);
+
+ PKIX_CHECK(pkix_SignatureChecker_Initialize
+ (trustedPubKey, numCerts, &sigChecker, plContext),
+ PKIX_SIGNATURECHECKERINITIALIZEFAILED);
+
+ if (userCheckersList != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (userCheckersList, &numCertCheckers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numCertCheckers; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (userCheckersList,
+ i,
+ (PKIX_PL_Object **) &userChecker,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers,
+ (PKIX_PL_Object *)userChecker,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(userChecker);
+ }
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)targetCertChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)expirationChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)nameChainingChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)nameConstraintsChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)basicConstraintsChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)policyChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (checkers, (PKIX_PL_Object *)sigChecker, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ *pCheckers = checkers;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(checkers);
+ }
+
+ PKIX_DECREF(certSelector);
+ PKIX_DECREF(testDate);
+ PKIX_DECREF(initialPolicies);
+ PKIX_DECREF(targetCertChecker);
+ PKIX_DECREF(expirationChecker);
+ PKIX_DECREF(nameChainingChecker);
+ PKIX_DECREF(nameConstraintsChecker);
+ PKIX_DECREF(basicConstraintsChecker);
+ PKIX_DECREF(policyChecker);
+ PKIX_DECREF(sigChecker);
+ PKIX_DECREF(trustedCAName);
+ PKIX_DECREF(trustedPubKey);
+ PKIX_DECREF(trustedNC);
+ PKIX_DECREF(trustedCert);
+ PKIX_DECREF(defaultCrlChecker);
+ PKIX_DECREF(userCheckersList);
+ PKIX_DECREF(certStores);
+ PKIX_DECREF(userChecker);
+
+ PKIX_RETURN(VALIDATE);
+}
+
+/*
+ * FUNCTION: pkix_RetrieveOutputs
+ * DESCRIPTION:
+ *
+ * This function queries the respective states of the List of checkers in
+ * "checkers" to to obtain the final public key from the SignatureChecker
+ * and the policy tree from the PolicyChecker, storing those values at
+ * "pFinalSubjPubKey" and "pPolicyTree", respectively.
+ *
+ * PARAMETERS:
+ * "checkers"
+ * Address of List of checkers to be queried. Must be non-NULL.
+ * "pFinalSubjPubKey"
+ * Address where final public key will be stored. Must be non-NULL.
+ * "pPolicyTree"
+ * Address where policy tree will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Validate Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_RetrieveOutputs(
+ PKIX_List *checkers,
+ PKIX_PL_PublicKey **pFinalSubjPubKey,
+ PKIX_PolicyNode **pPolicyTree,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *finalSubjPubKey = NULL;
+ PKIX_PolicyNode *validPolicyTree = NULL;
+ PKIX_CertChainChecker *checker = NULL;
+ PKIX_PL_Object *state = NULL;
+ PKIX_UInt32 numCheckers = 0;
+ PKIX_UInt32 type;
+ PKIX_Int32 j;
+
+ PKIX_ENTER(VALIDATE, "pkix_RetrieveOutputs");
+
+ PKIX_NULLCHECK_TWO(checkers, pPolicyTree);
+
+ /*
+ * To optimize the search, we guess that the sigChecker is
+ * last in the tree and is preceded by the policyChecker. We
+ * search toward the front of the chain. Remember that List
+ * items are indexed 0..(numItems - 1).
+ */
+
+ PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (j = numCheckers - 1; j >= 0; j--){
+ PKIX_CHECK(PKIX_List_GetItem
+ (checkers, j, (PKIX_PL_Object **)&checker, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
+ (checker, &state, plContext),
+ PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
+
+ /* user defined checker may have no state */
+ if (state != NULL) {
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(state, &type, plContext),
+ PKIX_OBJECTGETTYPEFAILED);
+
+ if (type == PKIX_SIGNATURECHECKERSTATE_TYPE){
+ /* final pubKey will include any inherited DSA params */
+ finalSubjPubKey =
+ ((pkix_SignatureCheckerState *)state)->
+ prevPublicKey;
+ PKIX_INCREF(finalSubjPubKey);
+ *pFinalSubjPubKey = finalSubjPubKey;
+ }
+
+ if (type == PKIX_CERTPOLICYCHECKERSTATE_TYPE) {
+ validPolicyTree =
+ ((PKIX_PolicyCheckerState *)state)->validPolicyTree;
+ break;
+ }
+ }
+
+ PKIX_DECREF(checker);
+ PKIX_DECREF(state);
+ }
+
+ PKIX_INCREF(validPolicyTree);
+ *pPolicyTree = validPolicyTree;
+
+cleanup:
+
+ PKIX_DECREF(checker);
+ PKIX_DECREF(state);
+
+ PKIX_RETURN(VALIDATE);
+
+}
+
+/*
+ * FUNCTION: pkix_CheckChain
+ * DESCRIPTION:
+ *
+ * Checks whether the List of Certs pointed to by "certs", containing
+ * "numCerts" entries, successfully validates using each CertChainChecker in
+ * the List pointed to by "checkers" and has not been revoked, according to any
+ * of the Revocation Checkers in the List pointed to by "revChecker". Checkers
+ * are expected to remove from "removeCheckedExtOIDs" and extensions that they
+ * process. Indices to the certChain and the checkerChain are obtained and
+ * returned in "pCertCheckedIndex" and "pCheckerIndex", respectively. These
+ * should be set to zero prior to the initial call, but may be changed (and
+ * must be supplied on subsequent calls) if processing is suspended for non-
+ * blocking I/O. Each time a Cert passes from being validated by one of the
+ * CertChainCheckers to being checked by a Revocation Checker, the Boolean
+ * stored at "pRevChecking" is changed from FALSE to TRUE. If the Cert is
+ * rejected by a Revocation Checker, its reason code is returned at
+ * "pReasonCode. If the List of Certs successfully validates, the public key i
+ * the final certificate is obtained and stored at "pFinalSubjPubKey" and the
+ * validPolicyTree, which could be NULL, is stored at pPolicyTree. If the List
+ * of Certs fails to validate, an Error pointer is returned.
+ *
+ * If "pVerifyTree" is non-NULL, a chain of VerifyNodes is created which
+ * tracks the results of the validation. That is, either each node in the
+ * chain has a NULL Error component, or the last node contains an Error
+ * which indicates why the validation failed.
+ *
+ * The number of Certs in the List, represented by "numCerts", is used to
+ * determine which Cert is the final Cert.
+ *
+ * PARAMETERS:
+ * "certs"
+ * Address of List of Certs to validate. Must be non-NULL.
+ * "numCerts"
+ * Number of certificates in the List of certificates.
+ * "checkers"
+ * List of CertChainCheckers which must each validate the List of
+ * certificates. Must be non-NULL.
+ * "revChecker"
+ * List of RevocationCheckers which must each not reject the List of
+ * certificates. May be empty, but must be non-NULL.
+ * "removeCheckedExtOIDs"
+ * List of PKIX_PL_OID that has been processed. If called from building
+ * chain, it is the list of critical extension OIDs that has been
+ * processed prior to validation. Extension OIDs that may be processed by
+ * user defined checker processes are also in the list. May be NULL.
+ * "procParams"
+ * Address of ProcessingParams used to initialize various checkers. Must
+ * be non-NULL.
+ * "pCertCheckedIndex"
+ * Address where Int32 index to the Cert chain is obtained and
+ * returned. Must be non-NULL.
+ * "pCheckerIndex"
+ * Address where Int32 index to the CheckerChain is obtained and
+ * returned. Must be non-NULL.
+ * "pRevChecking"
+ * Address where Boolean is obtained and returned, indicating, if FALSE,
+ * that CertChainCheckers are being called; or, if TRUE, that RevChecker
+ * are being called. Must be non-NULL.
+ * "pReasonCode"
+ * Address where UInt32 results of revocation checking are stored. Must be
+ * non-NULL.
+ * "pNBIOContext"
+ * Address where platform-dependent context is stored if checking is
+ * suspended for non-blocking I/O. Must be non-NULL.
+ * "pFinalSubjPubKey"
+ * Address where the final public key will be stored. Must be non-NULL.
+ * "pPolicyTree"
+ * Address where the final validPolicyTree is stored. Must be non-NULL.
+ * "pVerifyTree"
+ * Address where a VerifyTree is stored, if non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Validate Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CheckChain(
+ PKIX_List *certs,
+ PKIX_UInt32 numCerts,
+ PKIX_TrustAnchor *anchor,
+ PKIX_List *checkers,
+ PKIX_RevocationChecker *revChecker,
+ PKIX_List *removeCheckedExtOIDs,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 *pCertCheckedIndex,
+ PKIX_UInt32 *pCheckerIndex,
+ PKIX_Boolean *pRevChecking,
+ PKIX_UInt32 *pReasonCode,
+ void **pNBIOContext,
+ PKIX_PL_PublicKey **pFinalSubjPubKey,
+ PKIX_PolicyNode **pPolicyTree,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext)
+{
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean revChecking = PKIX_FALSE;
+ PKIX_Error *checkCertError = NULL;
+ void *nbioContext = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_Cert *issuer = NULL;
+ PKIX_PL_NssContext *nssContext = NULL;
+ CERTCertList *certList = NULL;
+ const CERTChainVerifyCallback *chainVerifyCallback = NULL;
+ CERTCertificate *nssCert = NULL;
+
+ PKIX_ENTER(VALIDATE, "pkix_CheckChain");
+ PKIX_NULLCHECK_FOUR(certs, checkers, revChecker, pCertCheckedIndex);
+ PKIX_NULLCHECK_FOUR(pCheckerIndex, pRevChecking, pReasonCode, anchor);
+ PKIX_NULLCHECK_THREE(pNBIOContext, pFinalSubjPubKey, pPolicyTree);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+ revChecking = *pRevChecking;
+ nssContext = (PKIX_PL_NssContext *)plContext;
+ chainVerifyCallback = &nssContext->chainVerifyCallback;
+
+ if (chainVerifyCallback->isChainValid != NULL) {
+ PRBool chainOK = PR_FALSE; /*assume failure*/
+ SECStatus rv;
+
+ certList = CERT_NewCertList();
+ if (certList == NULL) {
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+
+ /* Add the trust anchor to the list */
+ PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
+ (anchor, &cert, plContext),
+ PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
+
+ PKIX_CHECK(
+ PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext),
+ PKIX_CERTGETCERTCERTIFICATEFAILED);
+
+ rv = CERT_AddCertToListHead(certList, nssCert);
+ if (rv != SECSuccess) {
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+ /* the certList takes ownership of nssCert on success */
+ nssCert = NULL;
+ PKIX_DECREF(cert);
+
+ /* Add the rest of the chain to the list */
+ for (j = *pCertCheckedIndex; j < numCerts; j++) {
+ PKIX_CHECK(PKIX_List_GetItem(
+ certs, j, (PKIX_PL_Object **)&cert, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(
+ PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext),
+ PKIX_CERTGETCERTCERTIFICATEFAILED);
+
+ rv = CERT_AddCertToListHead(certList, nssCert);
+ if (rv != SECSuccess) {
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+ /* the certList takes ownership of nssCert on success */
+ nssCert = NULL;
+ PKIX_DECREF(cert);
+ }
+
+ rv = (*chainVerifyCallback->isChainValid)
+ (chainVerifyCallback->isChainValidArg, certList, &chainOK);
+ if (rv != SECSuccess) {
+ PKIX_ERROR_FATAL(PKIX_CHAINVERIFYCALLBACKFAILED);
+ }
+
+ if (!chainOK) {
+ PKIX_ERROR(PKIX_CHAINVERIFYCALLBACKFAILED);
+ }
+
+ }
+
+ PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
+ (anchor, &cert, plContext),
+ PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
+
+ for (j = *pCertCheckedIndex; j < numCerts; j++) {
+
+ PORT_Assert(cert);
+ PKIX_DECREF(issuer);
+ issuer = cert;
+ cert = NULL;
+
+ PKIX_CHECK(PKIX_List_GetItem(
+ certs, j, (PKIX_PL_Object **)&cert, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /* check if cert pointer is valid */
+ PORT_Assert(cert);
+ if (cert == NULL) {
+ continue;
+ }
+
+ if (revChecking == PKIX_FALSE) {
+
+ PKIX_CHECK(pkix_CheckCert
+ (cert,
+ checkers,
+ removeCheckedExtOIDs,
+ pCheckerIndex,
+ &nbioContext,
+ plContext),
+ PKIX_CHECKCERTFAILED);
+
+ if (nbioContext != NULL) {
+ *pCertCheckedIndex = j;
+ *pRevChecking = revChecking;
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ revChecking = PKIX_TRUE;
+ *pCheckerIndex = 0;
+ }
+
+ if (revChecking == PKIX_TRUE) {
+ PKIX_RevocationStatus revStatus;
+ pkixErrorResult =
+ PKIX_RevocationChecker_Check(
+ cert, issuer, revChecker,
+ procParams, PKIX_TRUE,
+ (j == numCerts - 1) ? PKIX_TRUE : PKIX_FALSE,
+ &revStatus, pReasonCode,
+ &nbioContext, plContext);
+ if (nbioContext != NULL) {
+ *pCertCheckedIndex = j;
+ *pRevChecking = revChecking;
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+ if (revStatus == PKIX_RevStatus_Revoked ||
+ pkixErrorResult) {
+ if (!pkixErrorResult) {
+ /* if pkixErrorResult is returned then
+ * use it as it has a detailed revocation
+ * error code. Otherwise create a new error */
+ PKIX_ERROR_CREATE(VALIDATE,
+ PKIX_CERTIFICATEREVOKED,
+ pkixErrorResult);
+ }
+ goto cleanup;
+ }
+ revChecking = PKIX_FALSE;
+ *pCheckerIndex = 0;
+ }
+
+ PKIX_CHECK(pkix_AddToVerifyLog
+ (cert, j, NULL, pVerifyTree, plContext),
+ PKIX_ADDTOVERIFYLOGFAILED);
+ }
+
+ PKIX_CHECK(pkix_RetrieveOutputs
+ (checkers, pFinalSubjPubKey, pPolicyTree, plContext),
+ PKIX_RETRIEVEOUTPUTSFAILED);
+
+ *pNBIOContext = NULL;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED && cert) {
+ checkCertError = pkixErrorResult;
+
+ PKIX_CHECK_FATAL(
+ pkix_AddToVerifyLog(cert, j, checkCertError, pVerifyTree,
+ plContext),
+ PKIX_ADDTOVERIFYLOGFAILED);
+ pkixErrorResult = checkCertError;
+ pkixErrorCode = pkixErrorResult->errCode;
+ checkCertError = NULL;
+ }
+
+fatal:
+ if (nssCert) {
+ CERT_DestroyCertificate(nssCert);
+ }
+
+ if (certList) {
+ CERT_DestroyCertList(certList);
+ }
+
+ PKIX_DECREF(checkCertError);
+ PKIX_DECREF(cert);
+ PKIX_DECREF(issuer);
+
+ PKIX_RETURN(VALIDATE);
+}
+
+/*
+ * FUNCTION: pkix_ExtractParameters
+ * DESCRIPTION:
+ *
+ * Extracts several parameters from the ValidateParams object pointed to by
+ * "valParams" and stores the CertChain at "pChain", the List of Certs at
+ * "pCerts", the number of Certs in the chain at "pNumCerts", the
+ * ProcessingParams object at "pProcParams", the List of TrustAnchors at
+ * "pAnchors", and the number of TrustAnchors at "pNumAnchors".
+ *
+ * PARAMETERS:
+ * "valParams"
+ * Address of ValidateParams from which the parameters are extracted.
+ * Must be non-NULL.
+ * "pCerts"
+ * Address where object pointer for List of Certs will be stored.
+ * Must be non-NULL.
+ * "pNumCerts"
+ * Address where number of Certs will be stored. Must be non-NULL.
+ * "pProcParams"
+ * Address where object pointer for ProcessingParams will be stored.
+ * Must be non-NULL.
+ * "pAnchors"
+ * Address where object pointer for List of Anchors will be stored.
+ * Must be non-NULL.
+ * "pNumAnchors"
+ * Address where number of Anchors will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Validate Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_ExtractParameters(
+ PKIX_ValidateParams *valParams,
+ PKIX_List **pCerts,
+ PKIX_UInt32 *pNumCerts,
+ PKIX_ProcessingParams **pProcParams,
+ PKIX_List **pAnchors,
+ PKIX_UInt32 *pNumAnchors,
+ void *plContext)
+{
+ PKIX_ENTER(VALIDATE, "pkix_ExtractParameters");
+ PKIX_NULLCHECK_THREE(valParams, pCerts, pNumCerts);
+ PKIX_NULLCHECK_THREE(pProcParams, pAnchors, pNumAnchors);
+
+ /* extract relevant parameters from chain */
+ PKIX_CHECK(PKIX_ValidateParams_GetCertChain
+ (valParams, pCerts, plContext),
+ PKIX_VALIDATEPARAMSGETCERTCHAINFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(*pCerts, pNumCerts, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ /* extract relevant parameters from procParams */
+ PKIX_CHECK(PKIX_ValidateParams_GetProcessingParams
+ (valParams, pProcParams, plContext),
+ PKIX_VALIDATEPARAMSGETPROCESSINGPARAMSFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors
+ (*pProcParams, pAnchors, plContext),
+ PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(*pAnchors, pNumAnchors, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+cleanup:
+
+ PKIX_RETURN(VALIDATE);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_ValidateChain (see comments in pkix.h)
+ */
+PKIX_Error *
+PKIX_ValidateChain(
+ PKIX_ValidateParams *valParams,
+ PKIX_ValidateResult **pResult,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext)
+{
+ PKIX_Error *chainFailed = NULL;
+
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_CertChainChecker *userChecker = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_List *checkers = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *userCheckers = NULL;
+ PKIX_List *userCheckerExtOIDs = NULL;
+ PKIX_List *validateCheckedCritExtOIDsList = NULL;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_PL_PublicKey *finalPubKey = NULL;
+ PKIX_PolicyNode *validPolicyTree = NULL;
+ PKIX_Boolean supportForwarding = PKIX_FALSE;
+ PKIX_Boolean revChecking = PKIX_FALSE;
+ PKIX_UInt32 i, numCerts, numAnchors;
+ PKIX_UInt32 numUserCheckers = 0;
+ PKIX_UInt32 certCheckedIndex = 0;
+ PKIX_UInt32 checkerIndex = 0;
+ PKIX_UInt32 reasonCode = 0;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(VALIDATE, "PKIX_ValidateChain");
+ PKIX_NULLCHECK_TWO(valParams, pResult);
+
+ /* extract various parameters from valParams */
+ PKIX_CHECK(pkix_ExtractParameters
+ (valParams,
+ &certs,
+ &numCerts,
+ &procParams,
+ &anchors,
+ &numAnchors,
+ plContext),
+ PKIX_EXTRACTPARAMETERSFAILED);
+
+ /*
+ * setup an extension OID list that user had defined for his checker
+ * processing. User checker is not responsible for taking out OIDs
+ * from unresolved critical extension list as the libpkix checker
+ * is doing. Here we add those user checkers' OIDs to the removal
+ * list to be taken out by CheckChain
+ */
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
+ (procParams, &userCheckers, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
+
+ if (userCheckers != NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&validateCheckedCritExtOIDsList,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (userCheckers, &numUserCheckers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numUserCheckers; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (userCheckers,
+ i,
+ (PKIX_PL_Object **) &userChecker,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK
+ (PKIX_CertChainChecker_IsForwardCheckingSupported
+ (userChecker, &supportForwarding, plContext),
+ PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
+
+ if (supportForwarding == PKIX_FALSE) {
+
+ PKIX_CHECK
+ (PKIX_CertChainChecker_GetSupportedExtensions
+ (userChecker, &userCheckerExtOIDs, plContext),
+ PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
+
+ if (userCheckerExtOIDs != NULL) {
+ PKIX_CHECK(pkix_List_AppendList
+ (validateCheckedCritExtOIDsList,
+ userCheckerExtOIDs,
+ plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ }
+ }
+
+ PKIX_DECREF(userCheckerExtOIDs);
+ PKIX_DECREF(userChecker);
+ }
+ }
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
+ (procParams, &revChecker, plContext),
+ PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
+
+ /* try to validate the chain with each anchor */
+ for (i = 0; i < numAnchors; i++){
+
+ /* get trust anchor */
+ PKIX_CHECK(PKIX_List_GetItem
+ (anchors, i, (PKIX_PL_Object **)&anchor, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /* initialize checkers using information from trust anchor */
+ PKIX_CHECK(pkix_InitializeCheckers
+ (anchor, procParams, numCerts, &checkers, plContext),
+ PKIX_INITIALIZECHECKERSFAILED);
+
+ /*
+ * Validate the chain using this trust anchor and these
+ * checkers. (WARNING: checkers that use non-blocking I/O
+ * are not currently supported.)
+ */
+ certCheckedIndex = 0;
+ checkerIndex = 0;
+ revChecking = PKIX_FALSE;
+ chainFailed = pkix_CheckChain
+ (certs,
+ numCerts,
+ anchor,
+ checkers,
+ revChecker,
+ validateCheckedCritExtOIDsList,
+ procParams,
+ &certCheckedIndex,
+ &checkerIndex,
+ &revChecking,
+ &reasonCode,
+ &nbioContext,
+ &finalPubKey,
+ &validPolicyTree,
+ pVerifyTree,
+ plContext);
+
+ if (chainFailed) {
+
+ /* cert chain failed to validate */
+
+ PKIX_DECREF(chainFailed);
+ PKIX_DECREF(anchor);
+ PKIX_DECREF(checkers);
+ PKIX_DECREF(validPolicyTree);
+
+ /* if last anchor, we fail; else, we try next anchor */
+ if (i == (numAnchors - 1)) { /* last anchor */
+ PKIX_ERROR(PKIX_VALIDATECHAINFAILED);
+ }
+
+ } else {
+
+ /* XXX Remove this assertion after 2014-12-31.
+ * See bug 946984. */
+ PORT_Assert(reasonCode == 0);
+
+ /* cert chain successfully validated! */
+ PKIX_CHECK(pkix_ValidateResult_Create
+ (finalPubKey,
+ anchor,
+ validPolicyTree,
+ &valResult,
+ plContext),
+ PKIX_VALIDATERESULTCREATEFAILED);
+
+ *pResult = valResult;
+
+ /* no need to try any more anchors in the loop */
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(finalPubKey);
+ PKIX_DECREF(certs);
+ PKIX_DECREF(anchors);
+ PKIX_DECREF(anchor);
+ PKIX_DECREF(checkers);
+ PKIX_DECREF(revChecker);
+ PKIX_DECREF(validPolicyTree);
+ PKIX_DECREF(chainFailed);
+ PKIX_DECREF(procParams);
+ PKIX_DECREF(userCheckers);
+ PKIX_DECREF(validateCheckedCritExtOIDsList);
+
+ PKIX_RETURN(VALIDATE);
+}
+
+/*
+ * FUNCTION: pkix_Validate_BuildUserOIDs
+ * DESCRIPTION:
+ *
+ * This function creates a List of the OIDs that are processed by the user
+ * checkers in the List pointed to by "userCheckers", storing the resulting
+ * List at "pUserCritOIDs". If the List of userCheckers is NULL, the output
+ * List will be NULL. Otherwise the output List will be non-NULL, but may be
+ * empty.
+ *
+ * PARAMETERS:
+ * "userCheckers"
+ * The address of the List of userCheckers.
+ * "pUserCritOIDs"
+ * The address at which the List is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a VALIDATE Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_Validate_BuildUserOIDs(
+ PKIX_List *userCheckers,
+ PKIX_List **pUserCritOIDs,
+ void *plContext)
+{
+ PKIX_UInt32 numUserCheckers = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_List *userCritOIDs = NULL;
+ PKIX_List *userCheckerExtOIDs = NULL;
+ PKIX_Boolean supportForwarding = PKIX_FALSE;
+ PKIX_CertChainChecker *userChecker = NULL;
+
+ PKIX_ENTER(VALIDATE, "pkix_Validate_BuildUserOIDs");
+ PKIX_NULLCHECK_ONE(pUserCritOIDs);
+
+ if (userCheckers != NULL) {
+ PKIX_CHECK(PKIX_List_Create(&userCritOIDs, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (userCheckers, &numUserCheckers, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numUserCheckers; i++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (userCheckers,
+ i,
+ (PKIX_PL_Object **) &userChecker,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_CertChainChecker_IsForwardCheckingSupported
+ (userChecker, &supportForwarding, plContext),
+ PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
+
+ if (supportForwarding == PKIX_FALSE) {
+
+ PKIX_CHECK(PKIX_CertChainChecker_GetSupportedExtensions
+ (userChecker, &userCheckerExtOIDs, plContext),
+ PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
+
+ if (userCheckerExtOIDs != NULL) {
+ PKIX_CHECK(pkix_List_AppendList
+ (userCritOIDs, userCheckerExtOIDs, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ }
+ }
+
+ PKIX_DECREF(userCheckerExtOIDs);
+ PKIX_DECREF(userChecker);
+ }
+ }
+
+ *pUserCritOIDs = userCritOIDs;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(userCritOIDs);
+ }
+
+ PKIX_DECREF(userCheckerExtOIDs);
+ PKIX_DECREF(userChecker);
+
+ PKIX_RETURN(VALIDATE);
+}
+
+/*
+ * FUNCTION: PKIX_ValidateChain_nb (see comments in pkix.h)
+ */
+PKIX_Error *
+PKIX_ValidateChain_NB(
+ PKIX_ValidateParams *valParams,
+ PKIX_UInt32 *pCertIndex,
+ PKIX_UInt32 *pAnchorIndex,
+ PKIX_UInt32 *pCheckerIndex,
+ PKIX_Boolean *pRevChecking,
+ PKIX_List **pCheckers,
+ void **pNBIOContext,
+ PKIX_ValidateResult **pResult,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext)
+{
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 numAnchors = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 certIndex = 0;
+ PKIX_UInt32 anchorIndex = 0;
+ PKIX_UInt32 checkerIndex = 0;
+ PKIX_UInt32 reasonCode = 0;
+ PKIX_Boolean revChecking = PKIX_FALSE;
+ PKIX_List *certs = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *checkers = NULL;
+ PKIX_List *userCheckers = NULL;
+ PKIX_List *validateCheckedCritExtOIDsList = NULL;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_PL_PublicKey *finalPubKey = NULL;
+ PKIX_PolicyNode *validPolicyTree = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_Error *chainFailed = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_ENTER(VALIDATE, "PKIX_ValidateChain_NB");
+ PKIX_NULLCHECK_FOUR
+ (valParams, pCertIndex, pAnchorIndex, pCheckerIndex);
+ PKIX_NULLCHECK_FOUR(pRevChecking, pCheckers, pNBIOContext, pResult);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ /* extract various parameters from valParams */
+ PKIX_CHECK(pkix_ExtractParameters
+ (valParams,
+ &certs,
+ &numCerts,
+ &procParams,
+ &anchors,
+ &numAnchors,
+ plContext),
+ PKIX_EXTRACTPARAMETERSFAILED);
+
+ /*
+ * Create a List of the OIDs that will be processed by the user
+ * checkers. User checkers are not responsible for removing OIDs from
+ * the List of unresolved critical extensions, as libpkix checkers are.
+ * So we add those user checkers' OIDs to the removal list to be taken
+ * out by CheckChain.
+ */
+ PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
+ (procParams, &userCheckers, plContext),
+ PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
+
+ PKIX_CHECK(pkix_Validate_BuildUserOIDs
+ (userCheckers, &validateCheckedCritExtOIDsList, plContext),
+ PKIX_VALIDATEBUILDUSEROIDSFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
+ (procParams, &revChecker, plContext),
+ PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
+
+ /* Are we resuming after a WOULDBLOCK return, or starting anew ? */
+ if (nbioContext != NULL) {
+ /* Resuming */
+ certIndex = *pCertIndex;
+ anchorIndex = *pAnchorIndex;
+ checkerIndex = *pCheckerIndex;
+ revChecking = *pRevChecking;
+ checkers = *pCheckers;
+ *pCheckers = NULL;
+ }
+
+ /* try to validate the chain with each anchor */
+ for (i = anchorIndex; i < numAnchors; i++) {
+
+ /* get trust anchor */
+ PKIX_CHECK(PKIX_List_GetItem
+ (anchors, i, (PKIX_PL_Object **)&anchor, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /* initialize checkers using information from trust anchor */
+ if (nbioContext == NULL) {
+ PKIX_CHECK(pkix_InitializeCheckers
+ (anchor,
+ procParams,
+ numCerts,
+ &checkers,
+ plContext),
+ PKIX_INITIALIZECHECKERSFAILED);
+ }
+
+ /*
+ * Validate the chain using this trust anchor and these
+ * checkers.
+ */
+ chainFailed = pkix_CheckChain
+ (certs,
+ numCerts,
+ anchor,
+ checkers,
+ revChecker,
+ validateCheckedCritExtOIDsList,
+ procParams,
+ &certIndex,
+ &checkerIndex,
+ &revChecking,
+ &reasonCode,
+ &nbioContext,
+ &finalPubKey,
+ &validPolicyTree,
+ pVerifyTree,
+ plContext);
+
+ if (nbioContext != NULL) {
+ *pCertIndex = certIndex;
+ *pAnchorIndex = anchorIndex;
+ *pCheckerIndex = checkerIndex;
+ *pRevChecking = revChecking;
+ PKIX_INCREF(checkers);
+ *pCheckers = checkers;
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ if (chainFailed) {
+
+ /* cert chain failed to validate */
+
+ PKIX_DECREF(chainFailed);
+ PKIX_DECREF(anchor);
+ PKIX_DECREF(checkers);
+ PKIX_DECREF(validPolicyTree);
+
+ /* if last anchor, we fail; else, we try next anchor */
+ if (i == (numAnchors - 1)) { /* last anchor */
+ PKIX_ERROR(PKIX_VALIDATECHAINFAILED);
+ }
+
+ } else {
+
+ /* XXX Remove this assertion after 2014-12-31.
+ * See bug 946984. */
+ PORT_Assert(reasonCode == 0);
+
+ /* cert chain successfully validated! */
+ PKIX_CHECK(pkix_ValidateResult_Create
+ (finalPubKey,
+ anchor,
+ validPolicyTree,
+ &valResult,
+ plContext),
+ PKIX_VALIDATERESULTCREATEFAILED);
+
+ *pResult = valResult;
+
+ /* no need to try any more anchors in the loop */
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(finalPubKey);
+ PKIX_DECREF(certs);
+ PKIX_DECREF(anchors);
+ PKIX_DECREF(anchor);
+ PKIX_DECREF(checkers);
+ PKIX_DECREF(revChecker);
+ PKIX_DECREF(validPolicyTree);
+ PKIX_DECREF(chainFailed);
+ PKIX_DECREF(procParams);
+ PKIX_DECREF(userCheckers);
+ PKIX_DECREF(validateCheckedCritExtOIDsList);
+
+ PKIX_RETURN(VALIDATE);
+}
diff --git a/security/nss/lib/libpkix/pkix/top/pkix_validate.h b/security/nss/lib/libpkix/pkix/top/pkix_validate.h
new file mode 100644
index 0000000000..7692e3babf
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/pkix_validate.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/. */
+/*
+ * pkix_validate.h
+ *
+ * Header file for validateChain function
+ *
+ */
+
+#ifndef _PKIX_VALIDATE_H
+#define _PKIX_VALIDATE_H
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PKIX_Error *
+pkix_CheckChain(
+ PKIX_List *certs,
+ PKIX_UInt32 numCerts,
+ PKIX_TrustAnchor *anchor,
+ PKIX_List *checkers,
+ PKIX_RevocationChecker *revChecker,
+ PKIX_List *buildCheckedExtOIDs,
+ PKIX_ProcessingParams *procParams,
+ PKIX_UInt32 *pCertCheckedIndex,
+ PKIX_UInt32 *pCheckerIndex,
+ PKIX_Boolean *pRevChecking,
+ PKIX_UInt32 *pReasonCode,
+ void **pNBIOContext,
+ PKIX_PL_PublicKey **pFinalSubjPubKey,
+ PKIX_PolicyNode **pPolicyTree,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_VALIDATE_H */
diff --git a/security/nss/lib/libpkix/pkix/top/top.gyp b/security/nss/lib/libpkix/pkix/top/top.gyp
new file mode 100644
index 0000000000..fb1b08ecbd
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/top/top.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'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixtop',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_build.c',
+ 'pkix_lifecycle.c',
+ 'pkix_validate.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix/util/Makefile b/security/nss/lib/libpkix/pkix/util/Makefile
new file mode 100644
index 0000000000..2b5492506c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/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). #
+#######################################################################
+
+
+#######################################################################
+# (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/lib/libpkix/pkix/util/exports.gyp b/security/nss/lib/libpkix/pkix/util/exports.gyp
new file mode 100644
index 0000000000..8318c6c347
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/exports.gyp
@@ -0,0 +1,28 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_libpkix_pkix_util_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_error.h',
+ 'pkix_list.h',
+ 'pkix_logger.h',
+ 'pkix_tools.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix/util/manifest.mn b/security/nss/lib/libpkix/pkix/util/manifest.mn
new file mode 100644
index 0000000000..e7d9f973c7
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/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 = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_tools.h \
+ pkix_error.h \
+ pkix_logger.h \
+ pkix_list.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_tools.c \
+ pkix_error.c \
+ pkix_logger.c \
+ pkix_list.c \
+ pkix_errpaths.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixutil
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_error.c b/security/nss/lib/libpkix/pkix/util/pkix_error.c
new file mode 100644
index 0000000000..9d730ca161
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_error.c
@@ -0,0 +1,565 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_error.c
+ *
+ * Error Object Functions
+ *
+ */
+
+#include "pkix_error.h"
+
+#undef PKIX_ERRORENTRY
+
+#define PKIX_ERRORENTRY(name,desc,nsserr) #desc
+
+#if defined PKIX_ERROR_DESCRIPTION
+
+const char * const PKIX_ErrorText[] =
+{
+#include "pkix_errorstrings.h"
+};
+
+#else
+
+#include "prprf.h"
+
+#endif /* PKIX_ERROR_DESCRIPTION */
+
+extern const PKIX_Int32 PKIX_PLErrorIndex[];
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_Error_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Error_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_Error *firstError = NULL;
+ PKIX_Error *secondError = NULL;
+ PKIX_Error *firstCause = NULL;
+ PKIX_Error *secondCause = NULL;
+ PKIX_PL_Object *firstInfo = NULL;
+ PKIX_PL_Object *secondInfo = NULL;
+ PKIX_ERRORCLASS firstClass, secondClass;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean boolResult, unequalFlag;
+
+ PKIX_ENTER(ERROR, "pkix_Error_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ unequalFlag = PKIX_FALSE;
+
+ /* First just compare pointer values to save time */
+ if (firstObject == secondObject) {
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ } else {
+ /* Result will only be set to true if all tests pass */
+ *pResult = PKIX_FALSE;
+ }
+
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_ERROR_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTANERROROBJECT);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_ERRORGETTINGSECONDOBJECTTYPE);
+
+ /* If types differ, then return false. Result is already set */
+ if (secondType != PKIX_ERROR_TYPE) goto cleanup;
+
+ /* It is safe to cast to PKIX_Error */
+ firstError = (PKIX_Error *) firstObject;
+ secondError = (PKIX_Error *) secondObject;
+
+ /* Compare error codes */
+ firstClass = firstError->errClass;
+ secondClass = secondError->errClass;
+
+ /* If codes differ, return false. Result is already set */
+ if (firstClass != secondClass) goto cleanup;
+
+ /* Compare causes */
+ firstCause = firstError->cause;
+ secondCause = secondError->cause;
+
+ /* Ensure that either both or none of the causes are NULL */
+ if (((firstCause != NULL) && (secondCause == NULL))||
+ ((firstCause == NULL) && (secondCause != NULL)))
+ unequalFlag = PKIX_TRUE;
+
+ if ((firstCause != NULL) && (secondCause != NULL)) {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object*)firstCause,
+ (PKIX_PL_Object*)secondCause,
+ &boolResult,
+ plContext),
+ PKIX_ERRORINRECURSIVEEQUALSCALL);
+
+ /* Set the unequalFlag so that we return after dec refing */
+ if (boolResult == 0) unequalFlag = PKIX_TRUE;
+ }
+
+ /* If the cause errors are not equal, return null */
+ if (unequalFlag) goto cleanup;
+
+ /* Compare info fields */
+ firstInfo = firstError->info;
+ secondInfo = secondError->info;
+
+ if (firstInfo != secondInfo) goto cleanup;
+
+ /* Ensure that either both or none of the infos are NULL */
+ if (((firstInfo != NULL) && (secondInfo == NULL))||
+ ((firstInfo == NULL) && (secondInfo != NULL)))
+ unequalFlag = PKIX_TRUE;
+
+ if ((firstInfo != NULL) && (secondInfo != NULL)) {
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object*)firstInfo,
+ (PKIX_PL_Object*)secondInfo,
+ &boolResult,
+ plContext),
+ PKIX_ERRORINRECURSIVEEQUALSCALL);
+
+ /* Set the unequalFlag so that we return after dec refing */
+ if (boolResult == 0) unequalFlag = PKIX_TRUE;
+ }
+
+ /* If the infos are not equal, return null */
+ if (unequalFlag) goto cleanup;
+
+
+ /* Compare descs */
+ if (firstError->errCode != secondError->errCode) {
+ unequalFlag = PKIX_TRUE;
+ }
+
+ if (firstError->plErr != secondError->plErr) {
+ unequalFlag = PKIX_TRUE;
+ }
+
+ /* If the unequalFlag was set, return false */
+ if (unequalFlag) goto cleanup;
+
+ /* Errors are equal in all fields at this point */
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: pkix_Error_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Error_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_Error *error = NULL;
+
+ PKIX_ENTER(ERROR, "pkix_Error_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext),
+ PKIX_OBJECTNOTANERROR);
+
+ error = (PKIX_Error *)object;
+
+ PKIX_DECREF(error->cause);
+
+ PKIX_DECREF(error->info);
+
+cleanup:
+
+ PKIX_RETURN(ERROR);
+}
+
+
+/* XXX This is not thread safe */
+static PKIX_UInt32 pkix_error_cause_depth = 1;
+
+/*
+ * FUNCTION: pkix_Error_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Error_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_Error *error = NULL;
+ PKIX_Error *cause = NULL;
+ PKIX_PL_String *desc = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *causeString = NULL;
+ PKIX_PL_String *optCauseString = NULL;
+ PKIX_PL_String *errorNameString = NULL;
+ char *format = NULL;
+ PKIX_ERRORCLASS errClass;
+
+ PKIX_ENTER(ERROR, "pkix_Error_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext),
+ PKIX_OBJECTNOTANERROR);
+
+ error = (PKIX_Error *)object;
+
+ /* Get this error's errClass, description and the string of its cause */
+ errClass = error->errClass;
+
+ /* Get the description string */
+ PKIX_Error_GetDescription(error, &desc, plContext);
+
+ /* Get the cause */
+ cause = error->cause;
+
+ /* Get the causes's description string */
+ if (cause != NULL) {
+ pkix_error_cause_depth++;
+
+ /* Get the cause string */
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)cause, &causeString, plContext),
+ PKIX_ERRORGETTINGCAUSESTRING);
+
+ format = "\n*** Cause (%d): %s";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ format,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Create the optional Cause String */
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&optCauseString,
+ plContext,
+ formatString,
+ pkix_error_cause_depth,
+ causeString),
+ PKIX_SPRINTFFAILED);
+
+ PKIX_DECREF(formatString);
+
+ pkix_error_cause_depth--;
+ }
+
+ /* Create the Format String */
+ if (optCauseString != NULL) {
+ format = "*** %s Error- %s%s";
+ } else {
+ format = "*** %s Error- %s";
+ }
+
+ /* Ensure that error errClass is known, otherwise default to Object */
+ if (errClass >= PKIX_NUMERRORCLASSES) {
+ errClass = 0;
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (void *)PKIX_ERRORCLASSNAMES[errClass],
+ 0,
+ &errorNameString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ format,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Create the output String */
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (pString,
+ plContext,
+ formatString,
+ errorNameString,
+ desc,
+ optCauseString),
+ PKIX_SPRINTFFAILED);
+
+cleanup:
+
+ PKIX_DECREF(desc);
+ PKIX_DECREF(causeString);
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(optCauseString);
+ PKIX_DECREF(errorNameString);
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: pkix_Error_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Error_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pResult,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "pkix_Error_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pResult);
+
+ /* XXX Unimplemented */
+ /* XXX Need to make hashcodes equal when two errors are equal */
+ *pResult = (PKIX_UInt32)((char *)object - (char *)NULL);
+
+ PKIX_RETURN(ERROR);
+}
+
+/* --Initializers------------------------------------------------- */
+
+/*
+ * PKIX_ERRORCLASSNAMES is an array of strings, with each string holding a
+ * descriptive name for an error errClass. This is used by the default
+ * PKIX_PL_Error_ToString function.
+ *
+ * Note: PKIX_ERRORCLASSES is defined in pkixt.h as a list of error types.
+ * (More precisely, as a list of invocations of ERRMACRO(type).) The
+ * macro is expanded in pkixt.h to define error numbers, and here to
+ * provide corresponding strings. For example, since the fifth ERRMACRO
+ * entry is MUTEX, then PKIX_MUTEX_ERROR is defined in pkixt.h as 4, and
+ * PKIX_ERRORCLASSNAMES[4] is initialized here with the value "MUTEX".
+ */
+#undef ERRMACRO
+#define ERRMACRO(type) #type
+
+const char *
+PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES] =
+{
+ PKIX_ERRORCLASSES
+};
+
+/*
+ * FUNCTION: pkix_Error_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_ERROR_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_Error_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(ERROR, "pkix_Error_RegisterSelf");
+
+ entry.description = "Error";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_Error);
+ entry.destructor = pkix_Error_Destroy;
+ entry.equalsFunction = pkix_Error_Equals;
+ entry.hashcodeFunction = pkix_Error_Hashcode;
+ entry.toStringFunction = pkix_Error_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_ERROR_TYPE] = entry;
+
+ PKIX_RETURN(ERROR);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_Error_Create (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_Create(
+ PKIX_ERRORCLASS errClass,
+ PKIX_Error *cause,
+ PKIX_PL_Object *info,
+ PKIX_ERRORCODE errCode,
+ PKIX_Error **pError,
+ void *plContext)
+{
+ PKIX_Error *tempCause = NULL;
+ PKIX_Error *error = NULL;
+
+ PKIX_ENTER(ERROR, "PKIX_Error_Create");
+
+ PKIX_NULLCHECK_ONE(pError);
+
+ /*
+ * when called here, if PKIX_PL_Object_Alloc returns an error,
+ * it must be a PKIX_ALLOC_ERROR
+ */
+ pkixErrorResult = PKIX_PL_Object_Alloc
+ (PKIX_ERROR_TYPE,
+ ((PKIX_UInt32)(sizeof (PKIX_Error))),
+ (PKIX_PL_Object **)&error,
+ plContext);
+
+ if (pkixErrorResult) return (pkixErrorResult);
+
+ error->errClass = errClass;
+
+ /* Ensure we don't have a loop. Follow causes until NULL */
+ for (tempCause = cause;
+ tempCause != NULL;
+ tempCause = tempCause->cause) {
+ /* If we detect a loop, throw a new error */
+ if (tempCause == error) {
+ PKIX_ERROR(PKIX_LOOPOFERRORCAUSEDETECTED);
+ }
+ }
+
+ PKIX_INCREF(cause);
+ error->cause = cause;
+
+ PKIX_INCREF(info);
+ error->info = info;
+
+ error->errCode = errCode;
+
+ error->plErr = PKIX_PLErrorIndex[error->errCode];
+
+ *pError = error;
+ error = NULL;
+
+cleanup:
+ /* PKIX-XXX Fix for leak during error creation */
+ PKIX_DECREF(error);
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetErrorClass (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetErrorClass(
+ PKIX_Error *error,
+ PKIX_ERRORCLASS *pClass,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "PKIX_Error_GetErrorClass");
+ PKIX_NULLCHECK_TWO(error, pClass);
+
+ *pClass = error->errClass;
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetErrorCode (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetErrorCode(
+ PKIX_Error *error,
+ PKIX_ERRORCODE *pCode,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "PKIX_Error_GetErrorCode");
+ PKIX_NULLCHECK_TWO(error, pCode);
+
+ *pCode = error->errCode;
+
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetCause (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetCause(
+ PKIX_Error *error,
+ PKIX_Error **pCause,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "PKIX_Error_GetCause");
+ PKIX_NULLCHECK_TWO(error, pCause);
+
+ if (error->cause != PKIX_ALLOC_ERROR()){
+ PKIX_INCREF(error->cause);
+ }
+
+ *pCause = error->cause;
+
+cleanup:
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetSupplementaryInfo (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetSupplementaryInfo(
+ PKIX_Error *error,
+ PKIX_PL_Object **pInfo,
+ void *plContext)
+{
+ PKIX_ENTER(ERROR, "PKIX_Error_GetSupplementaryInfo");
+ PKIX_NULLCHECK_TWO(error, pInfo);
+
+ PKIX_INCREF(error->info);
+
+ *pInfo = error->info;
+
+cleanup:
+ PKIX_RETURN(ERROR);
+}
+
+/*
+ * FUNCTION: PKIX_Error_GetDescription (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Error_GetDescription(
+ PKIX_Error *error,
+ PKIX_PL_String **pDesc,
+ void *plContext)
+{
+ PKIX_PL_String *descString = NULL;
+#ifndef PKIX_ERROR_DESCRIPTION
+ char errorStr[32];
+#endif
+
+ PKIX_ENTER(ERROR, "PKIX_Error_GetDescription");
+ PKIX_NULLCHECK_TWO(error, pDesc);
+
+#ifndef PKIX_ERROR_DESCRIPTION
+ PR_snprintf(errorStr, 32, "Error code: %d", error->errCode);
+#endif
+
+ PKIX_PL_String_Create(PKIX_ESCASCII,
+#if defined PKIX_ERROR_DESCRIPTION
+ (void *)PKIX_ErrorText[error->errCode],
+#else
+ errorStr,
+#endif
+ 0,
+ &descString,
+ plContext);
+
+ *pDesc = descString;
+
+ PKIX_RETURN(ERROR);
+}
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_error.h b/security/nss/lib/libpkix/pkix/util/pkix_error.h
new file mode 100644
index 0000000000..ca4171ab17
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_error.h
@@ -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/. */
+/*
+ * pkix_error.h
+ *
+ * Error Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_ERROR_H
+#define _PKIX_ERROR_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_ErrorStruct {
+ PKIX_ERRORCODE errCode;
+ PKIX_ERRORCLASS errClass; /* was formerly "code" */
+ PKIX_Int32 plErr;
+ PKIX_Error *cause;
+ PKIX_PL_Object *info;
+};
+
+/* see source file for function documentation */
+
+extern PKIX_Error * pkix_Error_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_ERROR_H */
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c b/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c
new file mode 100644
index 0000000000..a33ccf7ddb
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c
@@ -0,0 +1,103 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_errpaths.c
+ *
+ * Error Handling Helper Functions
+ *
+ */
+
+#define PKIX_STDVARS_POINTER
+#include "pkix_error.h"
+
+const PKIX_StdVars zeroStdVars;
+
+PKIX_Error*
+PKIX_DoThrow(PKIX_StdVars * stdVars, PKIX_ERRORCLASS errClass,
+ PKIX_ERRORCODE errCode, PKIX_ERRORCLASS overrideClass,
+ void *plContext)
+{
+ if (!pkixErrorReceived && !pkixErrorResult && pkixErrorList) {
+ pkixTempResult = PKIX_List_GetItem(pkixErrorList, 0,
+ (PKIX_PL_Object**)&pkixReturnResult,
+ plContext);
+ } else {
+ pkixTempResult = (PKIX_Error*)pkix_Throw(errClass, myFuncName, errCode,
+ overrideClass, pkixErrorResult,
+ &pkixReturnResult, plContext);
+ }
+ if (pkixReturnResult) {
+ if (pkixErrorResult != PKIX_ALLOC_ERROR()) {
+ PKIX_DECREF(pkixErrorResult);
+ }
+ pkixTempResult = pkixReturnResult;
+ } else if (pkixErrorResult) {
+ if (pkixTempResult != PKIX_ALLOC_ERROR()) {
+ PKIX_DECREF(pkixTempResult);
+ }
+ pkixTempResult = pkixErrorResult;
+ }
+ if (pkixErrorList) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorList, plContext);
+ pkixErrorList = NULL;
+ }
+ return pkixTempResult;
+}
+
+PKIX_Error *
+PKIX_DoReturn(PKIX_StdVars * stdVars, PKIX_ERRORCLASS errClass,
+ PKIX_Boolean doLogger, void *plContext)
+{
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ if (pkixErrorReceived || pkixErrorResult || pkixErrorList)
+ return PKIX_DoThrow(stdVars, errClass, pkixErrorCode, pkixErrorClass,
+ plContext);
+ /* PKIX_DEBUG_EXIT(type); */
+ if (doLogger)
+ _PKIX_DEBUG_TRACE(pkixLoggersDebugTrace, "<<<", PKIX_LOGGER_LEVEL_TRACE);
+ return NULL;
+}
+
+/* PKIX_DoAddError - creates the list of received error if it does not exist
+ * yet and adds newly received error into the list. */
+void
+PKIX_DoAddError(PKIX_StdVars *stdVars, PKIX_Error *error, void * plContext)
+{
+ PKIX_List *localList = NULL;
+ PKIX_Error *localError = NULL;
+ PKIX_Boolean listCreated = PKIX_FALSE;
+
+ if (!pkixErrorList) {
+ localError = PKIX_List_Create(&localList, plContext);
+ if (localError)
+ goto cleanup;
+ listCreated = PKIX_TRUE;
+ } else {
+ localList = pkixErrorList;
+ }
+
+ localError = PKIX_List_AppendItem(localList, (PKIX_PL_Object*)error,
+ plContext);
+ PORT_Assert (localError == NULL);
+ if (localError != NULL) {
+ if (listCreated) {
+ /* ignore the error code of DecRef function */
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)localList, plContext);
+ localList = NULL;
+ }
+ } else {
+ pkixErrorList = localList;
+ }
+
+cleanup:
+
+ if (localError && localError != PKIX_ALLOC_ERROR()) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)localError, plContext);
+ }
+
+ if (error && error != PKIX_ALLOC_ERROR()) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)error, plContext);
+ }
+}
+
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_list.c b/security/nss/lib/libpkix/pkix/util/pkix_list.c
new file mode 100644
index 0000000000..d02b66e6d6
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_list.c
@@ -0,0 +1,1701 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_list.c
+ *
+ * List Object Functions
+ *
+ */
+
+#include "pkix_list.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_List_Create_Internal
+ * DESCRIPTION:
+ *
+ * Creates a new List, using the Boolean value of "isHeader" to determine
+ * whether the new List should be a header, and stores it at "pList". The
+ * List is initially empty and holds no items. To initially add items to
+ * the List, use PKIX_List_AppendItem.
+ *
+ * PARAMETERS:
+ * "isHeader"
+ * Boolean value indicating whether new List should be a header.
+ * "pList"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_List_Create_Internal(
+ PKIX_Boolean isHeader,
+ PKIX_List **pList,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+
+ PKIX_ENTER(LIST, "pkix_List_Create_Internal");
+ PKIX_NULLCHECK_ONE(pList);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_LIST_TYPE,
+ ((PKIX_UInt32)(sizeof (PKIX_List))),
+ (PKIX_PL_Object **)&list, plContext),
+ PKIX_ERRORCREATINGLISTITEM);
+
+ list->item = NULL;
+ list->next = NULL;
+ list->immutable = PKIX_FALSE;
+ list->length = 0;
+ list->isHeader = isHeader;
+
+ *pList = list;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_List *nextItem = NULL;
+
+ PKIX_ENTER(LIST, "pkix_List_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a list */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
+ PKIX_OBJECTNOTLIST);
+
+ list = (PKIX_List *)object;
+
+ /* We have a valid list. DecRef its item and recurse on next */
+ PKIX_DECREF(list->item);
+ while ((nextItem = list->next) != NULL) {
+ list->next = nextItem->next;
+ nextItem->next = NULL;
+ PKIX_DECREF(nextItem);
+ }
+ list->immutable = PKIX_FALSE;
+ list->length = 0;
+ list->isHeader = PKIX_FALSE;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the List pointed
+ * to by "list" and stores its address in the object pointed to by "pString".
+ *
+ * PARAMETERS
+ * "list"
+ * Address of List whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address of object pointer's destination. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a List Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_List_ToString_Helper(
+ PKIX_List *list,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *itemString = NULL;
+ PKIX_PL_String *nextString = NULL;
+ PKIX_PL_String *format = NULL;
+ PKIX_Boolean empty;
+
+ PKIX_ENTER(LIST, "pkix_List_ToString_Helper");
+ PKIX_NULLCHECK_TWO(list, pString);
+
+ /* special case when list is the header */
+ if (list->isHeader){
+
+ PKIX_CHECK(PKIX_List_IsEmpty(list, &empty, plContext),
+ PKIX_LISTISEMPTYFAILED);
+
+ if (empty){
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "EMPTY",
+ 0,
+ &itemString,
+ plContext),
+ PKIX_ERRORCREATINGITEMSTRING);
+ (*pString) = itemString;
+ PKIX_DEBUG_EXIT(LIST);
+ return (NULL);
+ } else {
+ PKIX_CHECK(pkix_List_ToString_Helper
+ (list->next, &itemString, plContext),
+ PKIX_LISTTOSTRINGHELPERFAILED);
+ }
+
+ /* Create a string object from the format */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s", 0, &format, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (pString, plContext, format, itemString),
+ PKIX_SPRINTFFAILED);
+ } else {
+ /* Get a string for this list's item */
+ if (list->item == NULL) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "(null)",
+ 0,
+ &itemString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)list->item,
+ &itemString,
+ plContext),
+ PKIX_OBJECTTOSTRINGFAILED);
+ }
+ if (list->next == NULL) {
+ /* Just return the itemstring */
+ (*pString) = itemString;
+ PKIX_DEBUG_EXIT(LIST);
+ return (NULL);
+ }
+
+ /* Recursive call to get string for this list's next pointer */
+ PKIX_CHECK(pkix_List_ToString_Helper
+ (list->next, &nextString, plContext),
+ PKIX_LISTTOSTRINGHELPERFAILED);
+
+ /* Create a string object from the format */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ "%s, %s",
+ 0,
+ &format,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (pString,
+ plContext,
+ format,
+ itemString,
+ nextString),
+ PKIX_SPRINTFFAILED);
+ }
+
+cleanup:
+
+ PKIX_DECREF(itemString);
+ PKIX_DECREF(nextString);
+ PKIX_DECREF(format);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_PL_String *listString = NULL;
+ PKIX_PL_String *format = NULL;
+
+ PKIX_ENTER(LIST, "pkix_List_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
+ PKIX_OBJECTNOTLIST);
+
+ list = (PKIX_List *)object;
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ PKIX_CHECK(pkix_List_ToString_Helper(list, &listString, plContext),
+ PKIX_LISTTOSTRINGHELPERFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "(%s)", 0, &format, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf(pString, plContext, format, listString),
+ PKIX_SPRINTFFAILED);
+
+cleanup:
+
+ PKIX_DECREF(listString);
+ PKIX_DECREF(format);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_List *firstList = NULL;
+ PKIX_List *secondList = NULL;
+ PKIX_UInt32 firstLength = 0;
+ PKIX_UInt32 secondLength = 0;
+ PKIX_PL_Object *firstItem = NULL;
+ PKIX_PL_Object *secondItem = NULL;
+ PKIX_UInt32 i = 0;
+
+ PKIX_ENTER(LIST, "pkix_List_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ /* test that first is a List */
+ PKIX_CHECK(pkix_CheckType(first, PKIX_LIST_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTLIST);
+
+ /*
+ * Since we know first is a List, if both references are
+ * identical, they must be equal
+ */
+ if (first == second){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If second isn't a List, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_LIST_TYPE) goto cleanup;
+
+ firstList = (PKIX_List *)first;
+ secondList = (PKIX_List *)second;
+
+ if ((!firstList->isHeader) && (!secondList->isHeader)){
+ PKIX_ERROR(PKIX_INPUTLISTSMUSTBELISTHEADERS);
+ }
+
+ firstLength = firstList->length;
+ secondLength = secondList->length;
+
+ cmpResult = PKIX_FALSE;
+ if (firstLength == secondLength){
+ for (i = 0, cmpResult = PKIX_TRUE;
+ ((i < firstLength) && cmpResult);
+ i++){
+ PKIX_CHECK(PKIX_List_GetItem
+ (firstList, i, &firstItem, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (secondList, i, &secondItem, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if ((!firstItem && secondItem) ||
+ (firstItem && !secondItem)){
+ cmpResult = PKIX_FALSE;
+ } else if (!firstItem && !secondItem){
+ continue;
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ (firstItem,
+ secondItem,
+ &cmpResult,
+ plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(firstItem);
+ PKIX_DECREF(secondItem);
+ }
+ }
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_DECREF(firstItem);
+ PKIX_DECREF(secondItem);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_PL_Object *element = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 tempHash = 0;
+ PKIX_UInt32 length, i;
+
+ PKIX_ENTER(LIST, "pkix_List_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
+ PKIX_OBJECTNOTLIST);
+
+ list = (PKIX_List *)object;
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ for (i = 0; i < length; i++){
+ PKIX_CHECK(PKIX_List_GetItem(list, i, &element, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (!element){
+ tempHash = 100;
+ } else {
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ (element, &tempHash, plContext),
+ PKIX_LISTHASHCODEFAILED);
+ }
+
+ hash = 31 * hash + tempHash;
+
+ PKIX_DECREF(element);
+ }
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_DECREF(element);
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_List_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_List *listDuplicate = NULL;
+
+ PKIX_ENTER(LIST, "pkix_List_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext),
+ PKIX_OBJECTNOTLIST);
+
+ list = (PKIX_List *)object;
+
+ if (list->immutable){
+ PKIX_CHECK(pkix_duplicateImmutable
+ (object, pNewObject, plContext),
+ PKIX_DUPLICATEIMMUTABLEFAILED);
+ } else {
+
+ PKIX_CHECK(pkix_List_Create_Internal
+ (list->isHeader, &listDuplicate, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ listDuplicate->length = list->length;
+
+ PKIX_INCREF(list->item);
+ listDuplicate->item = list->item;
+
+ if (list->next == NULL){
+ listDuplicate->next = NULL;
+ } else {
+ /* Recursively Duplicate list */
+ PKIX_CHECK(pkix_List_Duplicate
+ ((PKIX_PL_Object *)list->next,
+ (PKIX_PL_Object **)&listDuplicate->next,
+ plContext),
+ PKIX_LISTDUPLICATEFAILED);
+ }
+
+ *pNewObject = (PKIX_PL_Object *)listDuplicate;
+ }
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(listDuplicate);
+ }
+
+ PKIX_RETURN(LIST);
+}
+
+
+/*
+ * FUNCTION: pkix_List_GetElement
+ * DESCRIPTION:
+ *
+ * Copies the "list"'s element at "index" into "element". The input List must
+ * be the header of the List (as opposed to being an element of the List). The
+ * index counts from zero and must be less than the List's length. This
+ * function does NOT increment the reference count of the List element since
+ * the returned element's reference will not be stored by the calling
+ * function.
+ *
+ * PARAMETERS:
+ * "list"
+ * Address of List (must be header) to get element from. Must be non-NULL.
+ * "index"
+ * Index of list to get element from. Must be less than List's length.
+ * "pElement"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_List_GetElement(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_List **pElement,
+ void *plContext)
+{
+ PKIX_List *iterator = NULL;
+ PKIX_UInt32 length;
+ PKIX_UInt32 position = 0;
+
+ PKIX_ENTER(LIST, "pkix_List_GetElement");
+ PKIX_NULLCHECK_TWO(list, pElement);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ if (index >= length) {
+ PKIX_ERROR(PKIX_INDEXOUTOFBOUNDS);
+ }
+
+ for (iterator = list; position++ <= index; iterator = iterator->next)
+ ;
+
+ (*pElement) = iterator;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+
+/*
+ * FUNCTION: pkix_List_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_LIST_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_List_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(LIST, "pkix_List_RegisterSelf");
+
+ entry.description = "List";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_List);
+ entry.destructor = pkix_List_Destroy;
+ entry.equalsFunction = pkix_List_Equals;
+ entry.hashcodeFunction = pkix_List_Hashcode;
+ entry.toStringFunction = pkix_List_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_List_Duplicate;
+
+ systemClasses[PKIX_LIST_TYPE] = entry;
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Contains
+ * DESCRIPTION:
+ *
+ * Checks a List pointed to by "list", to determine whether it includes
+ * an entry that is equal to the Object pointed to by "object", and stores
+ * the result in "pFound".
+ *
+ * PARAMETERS:
+ * "list"
+ * List to be searched; may be empty; must be non-NULL
+ * "object"
+ * Object to be checked for; must be non-NULL
+ * "pFound"
+ * Address where the result of the search will be stored. Must
+ * be non-NULL
+ * "plContext"
+ * platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_Contains(
+ PKIX_List *list,
+ PKIX_PL_Object *object,
+ PKIX_Boolean *pFound,
+ void *plContext)
+{
+ PKIX_PL_Object *current = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+ PKIX_Boolean match = PKIX_FALSE;
+
+ PKIX_ENTER(LIST, "pkix_List_Contains");
+ PKIX_NULLCHECK_THREE(list, object, pFound);
+
+ PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (index = 0; index < numEntries; index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (list, index, &current, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (current) {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ (object, current, &match, plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(current);
+ }
+
+ if (match) {
+ break;
+ }
+ }
+
+ *pFound = match;
+
+cleanup:
+
+ PKIX_DECREF(current);
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_Remove
+ * DESCRIPTION:
+ *
+ * Traverses the List pointed to by "list", to find and delete an entry
+ * that is equal to the Object pointed to by "object". If no such entry
+ * is found the function does not return an error.
+ *
+ * PARAMETERS:
+ * "list"
+ * List to be searched; may be empty; must be non-NULL
+ * "object"
+ * Object to be checked for and deleted, if found; must be non-NULL
+ * "plContext"
+ * platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Validate Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_Remove(
+ PKIX_List *list,
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Object *current = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+ PKIX_Boolean match = PKIX_FALSE;
+
+ PKIX_ENTER(LIST, "pkix_List_Remove");
+ PKIX_NULLCHECK_TWO(list, object);
+
+ PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (index = 0; index < numEntries; index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (list, index, &current, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (current) {
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ (object, current, &match, plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(current);
+ }
+
+ if (match) {
+ PKIX_CHECK(PKIX_List_DeleteItem
+ (list, index, plContext),
+ PKIX_LISTDELETEITEMFAILED);
+ break;
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(current);
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_RemoveItems
+ * DESCRIPTION:
+ *
+ * Traverses the List pointed to by "list", to find and delete an entry
+ * that is equal to the Object in the "deleteList". If no such entry
+ * is found the function does not return an error.
+ *
+ * PARAMETERS:
+ * "list"
+ * Object in "list" is checked for object in "deleteList" and deleted if
+ * found; may be empty; must be non-NULL
+ * "deleteList"
+ * List of objects to be searched ; may be empty; must be non-NULL
+ * "plContext"
+ * platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Validate Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_RemoveItems(
+ PKIX_List *list,
+ PKIX_List *deleteList,
+ void *plContext)
+{
+ PKIX_PL_Object *current = NULL;
+ PKIX_UInt32 numEntries = 0;
+ PKIX_UInt32 index = 0;
+
+ PKIX_ENTER(LIST, "pkix_List_RemoveItems");
+ PKIX_NULLCHECK_TWO(list, deleteList);
+
+ PKIX_CHECK(PKIX_List_GetLength(deleteList, &numEntries, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (index = 0; index < numEntries; index++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (deleteList, index, &current, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (current) {
+ PKIX_CHECK(pkix_List_Remove
+ (list, current, plContext),
+ PKIX_OBJECTEQUALSFAILED);
+
+ PKIX_DECREF(current);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(current);
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_MergeLists
+ * DESCRIPTION:
+ *
+ * Creates a new list consisting of the items from "firstList", followed by
+ * the items on "secondList", returns the new list at "pMergedList". If
+ * both input lists are NULL or empty, the result is an empty list. If an error
+ * occurs, the result is NULL.
+ *
+ * PARAMETERS:
+ * "firstList"
+ * Address of list to be merged from. May be NULL or empty.
+ * "secondList"
+ * Address of list to be merged from. May be NULL or empty.
+ * "pMergedList"
+ * Address where returned object is stored.
+ * "plContext"
+ * platform-specific context pointer * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a List Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_MergeLists(
+ PKIX_List *firstList,
+ PKIX_List *secondList,
+ PKIX_List **pMergedList,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_PL_Object *item = NULL;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(LIST, "pkix_List_MergeLists");
+ PKIX_NULLCHECK_ONE(pMergedList);
+
+ *pMergedList = NULL;
+
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ if (firstList != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength(firstList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem(firstList, i, &item, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem(list, item, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(item);
+ }
+
+ numItems = 0;
+ if (secondList != NULL) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (secondList,
+ &numItems,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ }
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (secondList, i, &item, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (list, item, plContext), PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(item);
+ }
+
+ *pMergedList = list;
+ list = NULL;
+
+cleanup:
+ PKIX_DECREF(list);
+ PKIX_DECREF(item);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_AppendList
+ * DESCRIPTION:
+ *
+ * Append items on "fromList" to the "toList". Item reference count on
+ * "toList" is not incremented, but items appended from "fromList" are
+ * incremented.
+ *
+ * PARAMETERS:
+ * "toList"
+ * Address of list to be appended to. Must be non-NULL.
+ * "fromList"
+ * Address of list to be appended from. May be NULL or empty.
+ * "plContext"
+ * platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a List Error if the functions fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_AppendList(
+ PKIX_List *toList,
+ PKIX_List *fromList,
+ void *plContext)
+{
+ PKIX_PL_Object *item = NULL;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(LIST, "pkix_List_AppendList");
+ PKIX_NULLCHECK_ONE(toList);
+
+ /* if fromList is NULL or is an empty list, no action */
+
+ if (fromList == NULL) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_List_GetLength(fromList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numItems == 0) {
+ goto cleanup;
+ }
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (fromList, i, &item, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem(toList, item, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(item);
+ }
+
+cleanup:
+
+ PKIX_DECREF(item);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_AppendUnique
+ * DESCRIPTION:
+ *
+ * Adds each Object in the List pointed to by "fromList" to the List pointed
+ * to by "toList", if it is not already a member of that List. In other words,
+ * "toList" becomes the union of the two sets.
+ *
+ * PARAMETERS:
+ * "toList"
+ * Address of a List of Objects to be augmented by "fromList". Must be
+ * non-NULL, but may be empty.
+ * "fromList"
+ * Address of a List of Objects to be added, if not already present, to
+ * "toList". Must be non-NULL, but may be empty.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "toList"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_AppendUnique(
+ PKIX_List *toList,
+ PKIX_List *fromList,
+ void *plContext)
+{
+ PKIX_Boolean isContained = PKIX_FALSE;
+ PKIX_UInt32 listLen = 0;
+ PKIX_UInt32 listIx = 0;
+ PKIX_PL_Object *object = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_List_AppendUnique");
+ PKIX_NULLCHECK_TWO(fromList, toList);
+
+ PKIX_CHECK(PKIX_List_GetLength(fromList, &listLen, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (listIx = 0; listIx < listLen; listIx++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (fromList, listIx, &object, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_List_Contains
+ (toList, object, &isContained, plContext),
+ PKIX_LISTCONTAINSFAILED);
+
+ if (isContained == PKIX_FALSE) {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (toList, object, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ PKIX_DECREF(object);
+ }
+
+cleanup:
+
+ PKIX_DECREF(object);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_QuickSort
+ * DESCRIPTION:
+ *
+ * Sorts List of Objects "fromList" using "comparatorCallback"'s result as
+ * comasrison key and returns the sorted List at "pSortedList". The sorting
+ * algorithm used is quick sort (n*logn).
+ *
+ * PARAMETERS:
+ * "fromList"
+ * Address of a List of Objects to be sorted. Must be non-NULL, but may be
+ * empty.
+ * "comparatorCallback"
+ * Address of callback function that will compare two Objects on the List.
+ * It should return -1 for less, 0 for equal and 1 for greater. The
+ * callback implementation chooses what in Objects to be compared. Must be
+ * non-NULL.
+ * "pSortedList"
+ * Address of a List of Objects that shall be sorted and returned. Must be
+ * non-NULL, but may be empty.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "toList"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_QuickSort(
+ PKIX_List *fromList,
+ PKIX_List_SortComparatorCallback comparator,
+ PKIX_List **pSortedList,
+ void *plContext)
+{
+ PKIX_List *sortedList = NULL;
+ PKIX_List *lessList = NULL;
+ PKIX_List *greaterList = NULL;
+ PKIX_List *sortedLessList = NULL;
+ PKIX_List *sortedGreaterList = NULL;
+ PKIX_PL_Object *object = NULL;
+ PKIX_PL_Object *cmpObj = NULL;
+ PKIX_Int32 cmpResult = 0;
+ PKIX_UInt32 size = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(BUILD, "pkix_List_QuickSort");
+ PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList);
+
+ PKIX_CHECK(PKIX_List_GetLength(fromList, &size, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&lessList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&greaterList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (fromList, 0, &object, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /*
+ * Pick the first item on the list as the one to be compared.
+ * Separate rest of the itmes into two lists: less-than or greater-
+ * than lists. Sort those two lists recursively. Insert sorted
+ * less-than list before the picked item and append the greater-
+ * than list after the picked item.
+ */
+ for (i = 1; i < size; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (fromList, i, &cmpObj, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(comparator(object, cmpObj, &cmpResult, plContext),
+ PKIX_COMPARATORCALLBACKFAILED);
+
+ if (cmpResult >= 0) {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (lessList, cmpObj, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ } else {
+ PKIX_CHECK(PKIX_List_AppendItem
+ (greaterList, cmpObj, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+ PKIX_DECREF(cmpObj);
+ }
+
+ PKIX_CHECK(PKIX_List_Create(&sortedList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(lessList, &size, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (size > 1) {
+
+ PKIX_CHECK(pkix_List_QuickSort
+ (lessList, comparator, &sortedLessList, plContext),
+ PKIX_LISTQUICKSORTFAILED);
+
+ PKIX_CHECK(pkix_List_AppendList
+ (sortedList, sortedLessList, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ } else {
+ PKIX_CHECK(pkix_List_AppendList
+ (sortedList, lessList, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem(sortedList, object, plContext),
+ PKIX_LISTAPPENDFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(greaterList, &size, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (size > 1) {
+
+ PKIX_CHECK(pkix_List_QuickSort
+ (greaterList, comparator, &sortedGreaterList, plContext),
+ PKIX_LISTQUICKSORTFAILED);
+
+ PKIX_CHECK(pkix_List_AppendList
+ (sortedList, sortedGreaterList, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ } else {
+ PKIX_CHECK(pkix_List_AppendList
+ (sortedList, greaterList, plContext),
+ PKIX_LISTAPPENDLISTFAILED);
+ }
+
+ *pSortedList = sortedList;
+
+cleanup:
+
+ PKIX_DECREF(cmpObj);
+ PKIX_DECREF(object);
+ PKIX_DECREF(sortedGreaterList);
+ PKIX_DECREF(sortedLessList);
+ PKIX_DECREF(greaterList);
+ PKIX_DECREF(lessList);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: pkix_List_BubbleSort
+ * DESCRIPTION:
+ *
+ * Sorts List of Objects "fromList" using "comparatorCallback"'s result as
+ * comasrison key and returns the sorted List at "pSortedList". The sorting
+ * algorithm used is bubble sort (n*n).
+ *
+ * PARAMETERS:
+ * "fromList"
+ * Address of a List of Objects to be sorted. Must be non-NULL, but may be
+ * empty.
+ * "comparatorCallback"
+ * Address of callback function that will compare two Objects on the List.
+ * It should return -1 for less, 0 for equal and 1 for greater. The
+ * callback implementation chooses what in Objects to be compared. Must be
+ * non-NULL.
+ * "pSortedList"
+ * Address of a List of Objects that shall be sorted and returned. Must be
+ * non-NULL, but may be empty.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "toList"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_List_BubbleSort(
+ PKIX_List *fromList,
+ PKIX_List_SortComparatorCallback comparator,
+ PKIX_List **pSortedList,
+ void *plContext)
+{
+ PKIX_List *sortedList = NULL;
+ PKIX_PL_Object *cmpObj = NULL;
+ PKIX_PL_Object *leastObj = NULL;
+ PKIX_Int32 cmpResult = 0;
+ PKIX_UInt32 size = 0;
+ PKIX_UInt32 i, j;
+
+ PKIX_ENTER(BUILD, "pkix_List_BubbleSort");
+ PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList);
+
+ if (fromList->immutable) {
+ PKIX_ERROR(PKIX_CANNOTSORTIMMUTABLELIST);
+ }
+ PKIX_CHECK(pkix_List_Duplicate
+ ((PKIX_PL_Object *) fromList,
+ (PKIX_PL_Object **) &sortedList,
+ plContext),
+ PKIX_LISTDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(sortedList, &size, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (size > 1) {
+
+ /*
+ * Move from the first of the item on the list, For each iteration,
+ * compare and swap the least value to the head of the comparisoning
+ * sub-list.
+ */
+ for (i = 0; i < size - 1; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (sortedList, i, &leastObj, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ for (j = i + 1; j < size; j++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (sortedList, j, &cmpObj, plContext),
+ PKIX_LISTGETITEMFAILED);
+ PKIX_CHECK(comparator
+ (leastObj, cmpObj, &cmpResult, plContext),
+ PKIX_COMPARATORCALLBACKFAILED);
+ if (cmpResult > 0) {
+ PKIX_CHECK(PKIX_List_SetItem
+ (sortedList, j, leastObj, plContext),
+ PKIX_LISTSETITEMFAILED);
+
+ PKIX_DECREF(leastObj);
+ leastObj = cmpObj;
+ cmpObj = NULL;
+ } else {
+ PKIX_DECREF(cmpObj);
+ }
+ }
+ PKIX_CHECK(PKIX_List_SetItem
+ (sortedList, i, leastObj, plContext),
+ PKIX_LISTSETITEMFAILED);
+
+ PKIX_DECREF(leastObj);
+ }
+
+ }
+
+ *pSortedList = sortedList;
+ sortedList = NULL;
+cleanup:
+
+ PKIX_DECREF(sortedList);
+ PKIX_DECREF(leastObj);
+ PKIX_DECREF(cmpObj);
+
+ PKIX_RETURN(LIST);
+}
+
+/* --Public-List-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_List_Create (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_Create(
+ PKIX_List **pList,
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+
+ PKIX_ENTER(LIST, "PKIX_List_Create");
+ PKIX_NULLCHECK_ONE(pList);
+
+ PKIX_CHECK(pkix_List_Create_Internal(PKIX_TRUE, &list, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ *pList = list;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_SetImmutable (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_SetImmutable(
+ PKIX_List *list,
+ void *plContext)
+{
+ PKIX_ENTER(LIST, "PKIX_List_SetImmutable");
+ PKIX_NULLCHECK_ONE(list);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ list->immutable = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_IsImmutable (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_IsImmutable(
+ PKIX_List *list,
+ PKIX_Boolean *pImmutable,
+ void *plContext)
+{
+ PKIX_ENTER(LIST, "PKIX_List_IsImmutable");
+ PKIX_NULLCHECK_TWO(list, pImmutable);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ *pImmutable = list->immutable;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_GetLength (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_GetLength(
+ PKIX_List *list,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ PKIX_ENTER(LIST, "PKIX_List_GetLength");
+ PKIX_NULLCHECK_TWO(list, pLength);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ *pLength = list->length;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_IsEmpty (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_IsEmpty(
+ PKIX_List *list,
+ PKIX_Boolean *pEmpty,
+ void *plContext)
+{
+ PKIX_UInt32 length;
+
+ PKIX_ENTER(LIST, "PKIX_List_IsEmpty");
+ PKIX_NULLCHECK_TWO(list, pEmpty);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ if (length == 0){
+ *pEmpty = PKIX_TRUE;
+ } else {
+ *pEmpty = PKIX_FALSE;
+ }
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_AppendItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_AppendItem(
+ PKIX_List *list,
+ PKIX_PL_Object *item,
+ void *plContext)
+{
+ PKIX_List *lastElement = NULL;
+ PKIX_List *newElement = NULL;
+ PKIX_UInt32 length, i;
+
+ PKIX_ENTER(LIST, "PKIX_List_AppendItem");
+ PKIX_NULLCHECK_ONE(list);
+
+ if (list->immutable){
+ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
+ }
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ /* find last element of list and create new element there */
+
+ lastElement = list;
+ for (i = 0; i < length; i++){
+ lastElement = lastElement->next;
+ }
+
+ PKIX_CHECK(pkix_List_Create_Internal
+ (PKIX_FALSE, &newElement, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ PKIX_INCREF(item);
+ newElement->item = item;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)list, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ lastElement->next = newElement;
+ newElement = NULL;
+ list->length += 1;
+
+cleanup:
+
+ PKIX_DECREF(newElement);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_InsertItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_InsertItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_PL_Object *item,
+ void *plContext)
+{
+ PKIX_List *element = NULL;
+ PKIX_List *newElem = NULL;
+
+ PKIX_ENTER(LIST, "PKIX_List_InsertItem");
+ PKIX_NULLCHECK_ONE(list);
+
+
+ if (list->immutable){
+ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
+ }
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ /* Create a new list object */
+ PKIX_CHECK(pkix_List_Create_Internal(PKIX_FALSE, &newElem, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ if (list->length) {
+ PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+ /* Copy the old element's contents into the new element */
+ newElem->item = element->item;
+ /* Add new item to the list */
+ PKIX_INCREF(item);
+ element->item = item;
+ /* Set the new element's next pointer to the old element's next */
+ newElem->next = element->next;
+ /* Set the old element's next pointer to the new element */
+ element->next = newElem;
+ newElem = NULL;
+ } else {
+ PKIX_INCREF(item);
+ newElem->item = item;
+ newElem->next = NULL;
+ list->next = newElem;
+ newElem = NULL;
+ }
+ list->length++;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)list, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+cleanup:
+ PKIX_DECREF(newElem);
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_GetItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_GetItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_PL_Object **pItem,
+ void *plContext)
+{
+ PKIX_List *element = NULL;
+
+ PKIX_ENTER(LIST, "PKIX_List_GetItem");
+ PKIX_NULLCHECK_TWO(list, pItem);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+
+ PKIX_INCREF(element->item);
+ *pItem = element->item;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_SetItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_SetItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ PKIX_PL_Object *item,
+ void *plContext)
+{
+ PKIX_List *element;
+
+ PKIX_ENTER(LIST, "PKIX_List_SetItem");
+ PKIX_NULLCHECK_ONE(list);
+
+ if (list->immutable){
+ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
+ }
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+
+ /* DecRef old contents */
+ PKIX_DECREF(element->item);
+
+ /* Set New Contents */
+ PKIX_INCREF(item);
+ element->item = item;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)list, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_DeleteItem (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_DeleteItem(
+ PKIX_List *list,
+ PKIX_UInt32 index,
+ void *plContext)
+{
+ PKIX_List *element = NULL;
+ PKIX_List *prevElement = NULL;
+ PKIX_List *nextElement = NULL;
+
+ PKIX_ENTER(LIST, "PKIX_List_DeleteItem");
+ PKIX_NULLCHECK_ONE(list);
+
+ if (list->immutable){
+ PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST);
+ }
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+
+ /* DecRef old contents */
+ PKIX_DECREF(element->item);
+
+ nextElement = element->next;
+
+ if (nextElement != NULL) {
+ /* If the next element exists, splice it out. */
+
+ /* Don't need to change ref counts for targets of next */
+ element->item = nextElement->item;
+ nextElement->item = NULL;
+
+ /* Don't need to change ref counts for targets of next */
+ element->next = nextElement->next;
+ nextElement->next = NULL;
+
+ PKIX_DECREF(nextElement);
+
+ } else { /* The element is at the tail of the list */
+ if (index != 0) {
+ PKIX_CHECK(pkix_List_GetElement
+ (list, index-1, &prevElement, plContext),
+ PKIX_LISTGETELEMENTFAILED);
+ } else if (index == 0){ /* prevElement must be header */
+ prevElement = list;
+ }
+ prevElement->next = NULL;
+
+ /* Delete the element */
+ PKIX_DECREF(element);
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)list, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ list->length = list->length - 1;
+
+cleanup:
+
+ PKIX_RETURN(LIST);
+}
+
+/*
+ * FUNCTION: PKIX_List_ReverseList (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_List_ReverseList(
+ PKIX_List *list,
+ PKIX_List **pReversedList,
+ void *plContext)
+{
+ PKIX_List *reversedList = NULL;
+ PKIX_PL_Object *item = NULL;
+ PKIX_PL_Object *duplicateItem = NULL;
+ PKIX_UInt32 length, i;
+
+ PKIX_ENTER(LIST, "pkix_List_ReverseList");
+ PKIX_NULLCHECK_TWO(list, pReversedList);
+
+ if (!list->isHeader){
+ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER);
+ }
+
+ length = list->length;
+
+ /* Create a new list object */
+ PKIX_CHECK(PKIX_List_Create(&reversedList, plContext),
+ PKIX_LISTCREATEINTERNALFAILED);
+
+ /*
+ * Starting with the last item and traversing backwards (from
+ * the original list), append each item to the reversed list
+ */
+
+ for (i = 1; i <= length; i++){
+ PKIX_CHECK(PKIX_List_GetItem
+ (list, (length - i), &item, plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ (item, &duplicateItem, plContext),
+ PKIX_LISTDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (reversedList, duplicateItem, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(item);
+ PKIX_DECREF(duplicateItem);
+ }
+
+ *pReversedList = reversedList;
+
+cleanup:
+
+ PKIX_DECREF(item);
+ PKIX_DECREF(duplicateItem);
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(reversedList);
+ }
+
+ PKIX_RETURN(LIST);
+}
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_list.h b/security/nss/lib/libpkix/pkix/util/pkix_list.h
new file mode 100644
index 0000000000..13e104f21a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_list.h
@@ -0,0 +1,95 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_list.h
+ *
+ * List Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_LIST_H
+#define _PKIX_LIST_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef PKIX_Error *
+(*PKIX_List_SortComparatorCallback)(
+ PKIX_PL_Object *obj1,
+ PKIX_PL_Object *obj2,
+ PKIX_Int32 *pResult,
+ void *plContext);
+
+struct PKIX_ListStruct {
+ PKIX_PL_Object *item;
+ PKIX_List *next;
+ PKIX_Boolean immutable;
+ PKIX_UInt32 length;
+ PKIX_Boolean isHeader;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_List_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_List_Contains(
+ PKIX_List *list,
+ PKIX_PL_Object *object,
+ PKIX_Boolean *pFound,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_Remove(
+ PKIX_List *list,
+ PKIX_PL_Object *target,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_MergeLists(
+ PKIX_List *firstList,
+ PKIX_List *secondList,
+ PKIX_List **pMergedList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_AppendList(
+ PKIX_List *toList,
+ PKIX_List *fromList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_AppendUnique(
+ PKIX_List *toList,
+ PKIX_List *fromList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_RemoveItems(
+ PKIX_List *list,
+ PKIX_List *deleteList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_QuickSort(
+ PKIX_List *fromList,
+ PKIX_List_SortComparatorCallback comparator,
+ PKIX_List **pSortedList,
+ void *plContext);
+
+PKIX_Error *
+pkix_List_BubbleSort(
+ PKIX_List *fromList,
+ PKIX_List_SortComparatorCallback comparator,
+ PKIX_List **pSortedList,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_LIST_H */
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_logger.c b/security/nss/lib/libpkix/pkix/util/pkix_logger.c
new file mode 100644
index 0000000000..10f537a319
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_logger.c
@@ -0,0 +1,1088 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_logger.c
+ *
+ * Logger Object Functions
+ *
+ */
+
+#include "pkix_logger.h"
+#ifndef PKIX_ERROR_DESCRIPTION
+#include "prprf.h"
+#endif
+
+/* Global variable to keep PKIX_Logger List */
+PKIX_List *pkixLoggers = NULL;
+
+/*
+ * Once the Logger has been set, for any logging related operations, we have
+ * to go through the List to find a match, and if found, issue the
+ * corresponding callback. The overhead to check for DEBUG and TRACE in each
+ * PKIX function entering and exiting is very expensive (400X), and redundant
+ * if they are not the interest of the Logger. Therefore, the PKIX_Logger List
+ * pkixLoggers is separated into two lists based on its Loggers' trace level.
+ *
+ * Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or
+ * PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors
+ * and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and
+ * WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to
+ * pkixLoggersDebugTrace.
+ *
+ * Currently we provide five logging levels and the default setting are by:
+ *
+ * PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level
+ * PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level
+ * WARNING is not invoked as default
+ * PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs
+ * compilation -DPKIX_<component>DEBUG flag to turn on
+ * PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE
+ * level. TRACE provides duplicate information of DEBUG, but needs no
+ * recompilation and cannot choose component. To allow application
+ * to use DEBUG level, TRACE is put as last.
+ *
+ */
+PKIX_List *pkixLoggersErrors = NULL;
+PKIX_List *pkixLoggersDebugTrace = NULL;
+
+/* To ensure atomic update on pkixLoggers lists */
+PKIX_PL_MonitorLock *pkixLoggerLock = NULL;
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_Logger_CheckErrors
+ * DESCRIPTION:
+ *
+ * This function goes through each PKIX_Logger at "pkixLoggersList" and
+ * checks if "maxLevel" and "logComponent" satisfies what is specified in the
+ * PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and
+ * passes a PKIX_PL_String that is the concatenation of "message" and
+ * "message2" to the application for processing.
+ * Since this call is inserted into a handful of PKIX macros, no macros are
+ * applied in this function, to avoid infinite recursion.
+ * If an error occurs, this call is aborted.
+ *
+ * PARAMETERS:
+ * "pkixLoggersList"
+ * A list of PKIX_Loggers to be examined for invoking callback. Must be
+ * non-NULL.
+ * "message"
+ * Address of "message" to be logged. Must be non-NULL.
+ * "message2"
+ * Address of "message2" to be concatenated and logged. May be NULL.
+ * "logComponent"
+ * A PKIX_UInt32 that indicates the component the message is from.
+ * "maxLevel"
+ * A PKIX_UInt32 that represents the level of severity of the message.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way
+ */
+PKIX_Error *
+pkix_Logger_Check(
+ PKIX_List *pkixLoggersList,
+ const char *message,
+ const char *message2,
+ PKIX_ERRORCLASS logComponent,
+ PKIX_UInt32 currentLevel,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *messageString = NULL;
+ PKIX_PL_String *message2String = NULL;
+ PKIX_PL_String *msgString = NULL;
+ PKIX_Error *error = NULL;
+ PKIX_Boolean needLogging = PKIX_FALSE;
+ PKIX_UInt32 i, length;
+
+ /*
+ * We cannot use any the PKIX_ macros here, since this function is
+ * called from some of these macros. It can create infinite recursion.
+ */
+
+ if ((pkixLoggersList == NULL) || (message == NULL)) {
+ return(NULL);
+ }
+
+ /*
+ * Disable all subsequent loggings to avoid recursion. The result is
+ * if other thread is calling this function at the same time, there
+ * won't be any logging because the pkixLoggersErrors and
+ * pkixLoggersDebugTrace are set to null.
+ * It would be nice if we provide control per thread (e.g. make
+ * plContext threadable) then we can avoid the recursion by setting
+ * flag at plContext. Then other thread's logging won't be affected.
+ *
+ * Also we need to use a reentrant Lock. Although we avoid recursion
+ * for TRACE. When there is an ERROR occurs in subsequent call, this
+ * function will be called.
+ */
+
+ error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext);
+ if (error) { return(NULL); }
+
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggersDebugTrace = NULL;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ pkixLoggersErrors = NULL;
+
+ /* Convert message and message2 to String */
+ error = PKIX_PL_String_Create
+ (PKIX_ESCASCII, message, 0, &messageString, plContext);
+ if (error) { goto cleanup; }
+
+ if (message2) {
+ error = PKIX_PL_String_Create
+ (PKIX_ESCASCII, message2, 0, &message2String, plContext);
+ if (error) { goto cleanup; }
+ error = PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s %s", 0, &formatString, plContext);
+ if (error) { goto cleanup; }
+
+ } else {
+ error = PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s", 0, &formatString, plContext);
+ if (error) { goto cleanup; }
+
+ }
+
+ error = PKIX_PL_Sprintf
+ (&msgString,
+ plContext,
+ formatString,
+ messageString,
+ message2String);
+ if (error) { goto cleanup; }
+
+ /* Go through the Logger list */
+
+ error = PKIX_List_GetLength(pkixLoggersList, &length, plContext);
+ if (error) { goto cleanup; }
+
+ for (i = 0; i < length; i++) {
+
+ error = PKIX_List_GetItem
+ (pkixLoggersList,
+ i,
+ (PKIX_PL_Object **) &logger,
+ plContext);
+ if (error) { goto cleanup; }
+
+ /* Intended logging level less or equal than the max */
+ needLogging = (currentLevel <= logger->maxLevel);
+
+ if (needLogging && (logger->callback)) {
+
+ /*
+ * We separate Logger into two lists based on log level
+ * but log level is not modified. We need to check here to
+ * avoid logging the higher log level (lower value) twice.
+ */
+ if (pkixLoggersList == pkixLoggersErrors) {
+ needLogging = needLogging &&
+ (currentLevel <= PKIX_LOGGER_LEVEL_WARNING);
+ } else if (pkixLoggersList == pkixLoggersDebugTrace) {
+ needLogging = needLogging &&
+ (currentLevel > PKIX_LOGGER_LEVEL_WARNING);
+ }
+
+ if (needLogging) {
+ if (logComponent == logger->logComponent) {
+ needLogging = PKIX_TRUE;
+ } else {
+ needLogging = PKIX_FALSE;
+ }
+ }
+
+ if (needLogging) {
+ error = logger->callback
+ (logger,
+ msgString,
+ currentLevel,
+ logComponent,
+ plContext);
+ if (error) { goto cleanup; }
+ }
+ }
+
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)logger, plContext);
+ logger = NULL;
+ if (error) { goto cleanup; }
+
+ }
+
+cleanup:
+
+ if (formatString) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)formatString, plContext);
+ }
+
+ if (messageString) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)messageString, plContext);
+ }
+
+ if (message2String) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)message2String, plContext);
+ }
+
+ if (msgString) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)msgString, plContext);
+ }
+
+ if (logger) {
+ error = PKIX_PL_Object_DecRef
+ ((PKIX_PL_Object *)logger, plContext);
+ }
+
+ if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) {
+ pkixLoggersErrors = savedPkixLoggersErrors;
+ }
+
+ if (pkixLoggersDebugTrace == NULL &&
+ savedPkixLoggersDebugTrace != NULL) {
+ pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
+ }
+
+ error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext);
+ if (error) { return(NULL); }
+
+ return(NULL);
+}
+
+PKIX_Error *
+pkix_Logger_CheckWithCode(
+ PKIX_List *pkixLoggersList,
+ PKIX_UInt32 errorCode,
+ const char *message2,
+ PKIX_ERRORCLASS logComponent,
+ PKIX_UInt32 currentLevel,
+ void *plContext)
+{
+ char error[32];
+ char *errorString = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_CheckWithCode");
+#if defined PKIX_ERROR_DESCRIPTION
+ errorString = PKIX_ErrorText[errorCode];
+#else
+ PR_snprintf(error, 32, "Error code: %d", errorCode);
+ errorString = error;
+#endif /* PKIX_ERROR_DESCRIPTION */
+
+ pkixErrorResult = pkix_Logger_Check(pkixLoggersList, errorString,
+ message2, logComponent,
+ currentLevel, plContext);
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a logger */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
+ PKIX_OBJECTNOTLOGGER);
+
+ logger = (PKIX_Logger *)object;
+
+ /* We have a valid logger. DecRef its item and recurse on next */
+
+ logger->callback = NULL;
+ PKIX_DECREF(logger->context);
+ logger->logComponent = (PKIX_ERRORCLASS)0;
+
+cleanup:
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *contextString = NULL;
+ PKIX_PL_String *componentString = NULL;
+ PKIX_PL_String *loggerString = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ /* Check that this object is a logger */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
+ PKIX_OBJECTNOTLOGGER);
+
+ logger = (PKIX_Logger *)object;
+
+ asciiFormat =
+ "[\n"
+ "\tLogger: \n"
+ "\tContext: %s\n"
+ "\tMaximum Level: %d\n"
+ "\tComponent Name: %s\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_TOSTRING(logger->context, &contextString, plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (void *)PKIX_ERRORCLASSNAMES[logger->logComponent],
+ 0,
+ &componentString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&loggerString,
+ plContext,
+ formatString,
+ contextString,
+ logger->maxLevel,
+ componentString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = loggerString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(contextString);
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+ PKIX_Logger *firstLogger = NULL;
+ PKIX_Logger *secondLogger = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ /* test that first is a Logger */
+ PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTLOGGER);
+
+ /*
+ * Since we know first is a Logger, if both references are
+ * identical, they must be equal
+ */
+ if (first == second){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If second isn't a Logger, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_LOGGER_TYPE) goto cleanup;
+
+ firstLogger = (PKIX_Logger *)first;
+ secondLogger = (PKIX_Logger *)second;
+
+ cmpResult = PKIX_FALSE;
+
+ if (firstLogger->callback != secondLogger->callback) {
+ goto cleanup;
+ }
+
+ if (firstLogger->logComponent != secondLogger->logComponent) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS
+ (firstLogger->context,
+ secondLogger->context,
+ &cmpResult,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (cmpResult == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ if (firstLogger->maxLevel != secondLogger->maxLevel) {
+ goto cleanup;
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ PKIX_UInt32 hash = 0;
+ PKIX_UInt32 tempHash = 0;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
+ PKIX_OBJECTNOTLOGGER);
+
+ logger = (PKIX_Logger *)object;
+
+ PKIX_HASHCODE(logger->context, &tempHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ hash = (((((PKIX_UInt32)((char *)logger->callback - (char *)NULL) + tempHash) << 7) +
+ logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent;
+
+ *pHashcode = hash;
+
+cleanup:
+
+ PKIX_RETURN(LOGGER);
+}
+
+
+/*
+ * FUNCTION: pkix_Logger_Duplicate
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_Logger_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ PKIX_Logger *dupLogger = NULL;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ ((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext),
+ PKIX_OBJECTNOTLOGGER);
+
+ logger = (PKIX_Logger *) object;
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_LOGGER_TYPE,
+ sizeof (PKIX_Logger),
+ (PKIX_PL_Object **)&dupLogger,
+ plContext),
+ PKIX_COULDNOTCREATELOGGEROBJECT);
+
+ dupLogger->callback = logger->callback;
+ dupLogger->maxLevel = logger->maxLevel;
+
+ PKIX_DUPLICATE
+ (logger->context,
+ &dupLogger->context,
+ plContext,
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ dupLogger->logComponent = logger->logComponent;
+
+ *pNewObject = (PKIX_PL_Object *) dupLogger;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(dupLogger);
+ }
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: pkix_Logger_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_LOGGER_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_Logger_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf");
+
+ entry.description = "Logger";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_Logger);
+ entry.destructor = pkix_Logger_Destroy;
+ entry.equalsFunction = pkix_Logger_Equals;
+ entry.hashcodeFunction = pkix_Logger_Hashcode;
+ entry.toStringFunction = pkix_Logger_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_Logger_Duplicate;
+
+ systemClasses[PKIX_LOGGER_TYPE] = entry;
+
+ PKIX_RETURN(LOGGER);
+}
+
+/* --Public-Logger-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_Create(
+ PKIX_Logger_LogCallback callback,
+ PKIX_PL_Object *loggerContext,
+ PKIX_Logger **pLogger,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+
+ PKIX_ENTER(LOGGER, "PKIX_Logger_Create");
+ PKIX_NULLCHECK_ONE(pLogger);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_LOGGER_TYPE,
+ sizeof (PKIX_Logger),
+ (PKIX_PL_Object **)&logger,
+ plContext),
+ PKIX_COULDNOTCREATELOGGEROBJECT);
+
+ logger->callback = callback;
+ logger->maxLevel = 0;
+ logger->logComponent = (PKIX_ERRORCLASS)0;
+
+ PKIX_INCREF(loggerContext);
+ logger->context = loggerContext;
+
+ *pLogger = logger;
+ logger = NULL;
+
+cleanup:
+
+ PKIX_DECREF(logger);
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_GetLogCallback(
+ PKIX_Logger *logger,
+ PKIX_Logger_LogCallback *pCallback,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetLogCallback");
+ PKIX_NULLCHECK_TWO(logger, pCallback);
+
+ *pCallback = logger->callback;
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_GetLoggerContext(
+ PKIX_Logger *logger,
+ PKIX_PL_Object **pLoggerContext,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggerContex");
+ PKIX_NULLCHECK_TWO(logger, pLoggerContext);
+
+ PKIX_INCREF(logger->context);
+ *pLoggerContext = logger->context;
+
+cleanup:
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_GetMaxLoggingLevel(
+ PKIX_Logger *logger,
+ PKIX_UInt32 *pLevel,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetMaxLoggingLevel");
+ PKIX_NULLCHECK_TWO(logger, pLevel);
+
+ *pLevel = logger->maxLevel;
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_SetMaxLoggingLevel(
+ PKIX_Logger *logger,
+ PKIX_UInt32 level,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_SetMaxLoggingLevel");
+ PKIX_NULLCHECK_ONE(logger);
+
+ if (level > PKIX_LOGGER_LEVEL_MAX) {
+ PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM);
+ } else {
+ logger->maxLevel = level;
+ }
+
+cleanup:
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_GetLoggingComponent(
+ PKIX_Logger *logger,
+ PKIX_ERRORCLASS *pComponent,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggingComponent");
+ PKIX_NULLCHECK_TWO(logger, pComponent);
+
+ *pComponent = logger->logComponent;
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_Logger_SetLoggingComponent(
+ PKIX_Logger *logger,
+ PKIX_ERRORCLASS component,
+ void *plContext)
+{
+ PKIX_ENTER(LOGGER, "PKIX_Logger_SetLoggingComponent");
+ PKIX_NULLCHECK_ONE(logger);
+
+ logger->logComponent = component;
+
+ PKIX_RETURN(LOGGER);
+}
+
+
+/*
+ * Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are
+ * documented as not thread-safe. However they are thread-safe now. We need
+ * the lock when accessing the logger lists.
+ */
+
+/*
+ * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_GetLoggers(
+ PKIX_List **pLoggers, /* list of PKIX_Logger */
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_Logger *logger = NULL;
+ PKIX_Logger *dupLogger = NULL;
+ PKIX_UInt32 i, length;
+ PKIX_Boolean locked = PKIX_FALSE;
+
+ PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers");
+ PKIX_NULLCHECK_ONE(pLoggers);
+
+ PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKENTERFAILED);
+ locked = PKIX_TRUE;
+
+ /*
+ * Temporarily disable DEBUG/TRACE Logging to avoid possible
+ * deadlock:
+ * When the Logger List is being accessed, e.g. by PKIX_ENTER or
+ * PKIX_DECREF, pkix_Logger_Check may check whether logging
+ * is requested, creating a deadlock situation.
+ */
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggersDebugTrace = NULL;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ pkixLoggersErrors = NULL;
+
+ if (pkixLoggers == NULL) {
+ length = 0;
+ } else {
+ PKIX_CHECK(PKIX_List_GetLength
+ (pkixLoggers, &length, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ /* Create a list and copy the pkixLoggers item to the list */
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ for (i = 0; i < length; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (pkixLoggers,
+ i,
+ (PKIX_PL_Object **) &logger,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_Logger_Duplicate
+ ((PKIX_PL_Object *)logger,
+ (PKIX_PL_Object **)&dupLogger,
+ plContext),
+ PKIX_LOGGERDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (list,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(logger);
+ PKIX_DECREF(dupLogger);
+ }
+
+ /* Set the list to be immutable */
+ PKIX_CHECK(PKIX_List_SetImmutable(list, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pLoggers = list;
+
+cleanup:
+
+ PKIX_DECREF(logger);
+
+ /* Restore logging capability */
+ pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
+ pkixLoggersErrors = savedPkixLoggersErrors;
+
+ if (locked) {
+ PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKEXITFAILED);
+ }
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_SetLoggers(
+ PKIX_List *loggers, /* list of PKIX_Logger */
+ void *plContext)
+{
+ PKIX_List *list = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+ PKIX_Logger *logger = NULL;
+ PKIX_Logger *dupLogger = NULL;
+ PKIX_Boolean locked = PKIX_FALSE;
+ PKIX_UInt32 i, length;
+
+ PKIX_ENTER(LOGGER, "PKIX_SetLoggers");
+
+ PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKENTERFAILED);
+ locked = PKIX_TRUE;
+
+ /* Disable tracing, etc. to avoid recursion and deadlock */
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggersDebugTrace = NULL;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ pkixLoggersErrors = NULL;
+
+ /* discard any prior loggers */
+ PKIX_DECREF(pkixLoggers);
+ PKIX_DECREF(savedPkixLoggersErrors);
+ PKIX_DECREF(savedPkixLoggersDebugTrace);
+
+ if (loggers != NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&list, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < length; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (loggers,
+ i,
+ (PKIX_PL_Object **) &logger,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_Logger_Duplicate
+ ((PKIX_PL_Object *)logger,
+ (PKIX_PL_Object **)&dupLogger,
+ plContext),
+ PKIX_LOGGERDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (list,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ /* Make two lists */
+
+ /* Put in pkixLoggersErrors in any case*/
+
+ if (savedPkixLoggersErrors == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&savedPkixLoggersErrors,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (savedPkixLoggersErrors,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
+
+ /* Put in pkixLoggersDebugTrace */
+
+ if (savedPkixLoggersDebugTrace == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&savedPkixLoggersDebugTrace,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (savedPkixLoggersDebugTrace,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+ PKIX_DECREF(logger);
+ PKIX_DECREF(dupLogger);
+
+ }
+
+ pkixLoggers = list;
+ }
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(list);
+ PKIX_DECREF(savedPkixLoggersErrors);
+ PKIX_DECREF(savedPkixLoggersDebugTrace);
+ pkixLoggers = NULL;
+ }
+
+ PKIX_DECREF(logger);
+
+ /* Reenable logging capability with new lists */
+ pkixLoggersErrors = savedPkixLoggersErrors;
+ pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
+
+ if (locked) {
+ PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKEXITFAILED);
+ }
+
+ PKIX_RETURN(LOGGER);
+}
+
+/*
+ * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h)
+ */
+PKIX_Error *
+PKIX_AddLogger(
+ PKIX_Logger *logger,
+ void *plContext)
+{
+ PKIX_Logger *dupLogger = NULL;
+ PKIX_Logger *addLogger = NULL;
+ PKIX_List *savedPkixLoggersErrors = NULL;
+ PKIX_List *savedPkixLoggersDebugTrace = NULL;
+ PKIX_Boolean locked = PKIX_FALSE;
+ PKIX_UInt32 i, length;
+
+ PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger");
+ PKIX_NULLCHECK_ONE(logger);
+
+ PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKENTERFAILED);
+ locked = PKIX_TRUE;
+
+ savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
+ pkixLoggersDebugTrace = NULL;
+ savedPkixLoggersErrors = pkixLoggersErrors;
+ pkixLoggersErrors = NULL;
+
+ PKIX_DECREF(savedPkixLoggersErrors);
+ PKIX_DECREF(savedPkixLoggersDebugTrace);
+
+ if (pkixLoggers == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(pkix_Logger_Duplicate
+ ((PKIX_PL_Object *)logger,
+ (PKIX_PL_Object **)&dupLogger,
+ plContext),
+ PKIX_LOGGERDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (pkixLoggers,
+ (PKIX_PL_Object *) dupLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */
+ for (i = 0; i < length; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (pkixLoggers,
+ i,
+ (PKIX_PL_Object **) &addLogger,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+
+ /* Put in pkixLoggersErrors */
+
+ if (savedPkixLoggersErrors == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&savedPkixLoggersErrors,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (savedPkixLoggersErrors,
+ (PKIX_PL_Object *) addLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
+
+ /* Put in pkixLoggersDebugTrace */
+
+ if (savedPkixLoggersDebugTrace == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create
+ (&savedPkixLoggersDebugTrace,
+ plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (savedPkixLoggersDebugTrace,
+ (PKIX_PL_Object *) addLogger,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+
+ PKIX_DECREF(addLogger);
+
+ }
+
+cleanup:
+
+ PKIX_DECREF(dupLogger);
+ PKIX_DECREF(addLogger);
+
+ /* Restore logging capability */
+ pkixLoggersErrors = savedPkixLoggersErrors;
+ pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
+
+ if (locked) {
+ PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
+ PKIX_MONITORLOCKEXITFAILED);
+ }
+
+ PKIX_RETURN(LOGGER);
+}
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_logger.h b/security/nss/lib/libpkix/pkix/util/pkix_logger.h
new file mode 100644
index 0000000000..9411aed2e2
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_logger.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/. */
+/*
+ * pkix_logger.h
+ *
+ * Logger Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_LOGGER_H
+#define _PKIX_LOGGER_H
+
+#include "pkix_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern PKIX_List *pkixLoggers;
+extern PKIX_List *pkixLoggersErrors;
+extern PKIX_List *pkixLoggersDebugTrace;
+
+struct PKIX_LoggerStruct {
+ PKIX_Logger_LogCallback callback;
+ PKIX_PL_Object *context;
+ PKIX_UInt32 maxLevel;
+ PKIX_ERRORCLASS logComponent;
+};
+
+PKIX_Error *
+pkix_Logger_Check(
+ PKIX_List *pkixLoggersList,
+ const char *message,
+ const char *message2,
+ PKIX_ERRORCLASS logComponent,
+ PKIX_UInt32 maxLevel,
+ void *plContext);
+
+PKIX_Error *
+pkix_Logger_CheckWithCode(
+ PKIX_List *pkixLoggersList,
+ PKIX_UInt32 errorCode,
+ const char *message2,
+ PKIX_ERRORCLASS logComponent,
+ PKIX_UInt32 maxLevel,
+ void *plContext);
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_Logger_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_LOGGER_H */
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_tools.c b/security/nss/lib/libpkix/pkix/util/pkix_tools.c
new file mode 100644
index 0000000000..4c01f8da14
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_tools.c
@@ -0,0 +1,1525 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_tools.c
+ *
+ * Private Utility Functions
+ *
+ */
+
+#include "pkix_tools.h"
+
+#define CACHE_ITEM_PERIOD_SECONDS (3600) /* one hour */
+
+/*
+ * This cahce period is only for CertCache. A Cert from a trusted CertStore
+ * should be checked more frequently for update new arrival, etc.
+ */
+#define CACHE_TRUST_ITEM_PERIOD_SECONDS (CACHE_ITEM_PERIOD_SECONDS/10)
+
+extern PKIX_PL_HashTable *cachedCertChainTable;
+extern PKIX_PL_HashTable *cachedCertTable;
+extern PKIX_PL_HashTable *cachedCrlEntryTable;
+
+/* Following variables are used to checked cache hits - can be taken out */
+extern int pkix_ccAddCount;
+extern int pkix_ccLookupCount;
+extern int pkix_ccRemoveCount;
+extern int pkix_cAddCount;
+extern int pkix_cLookupCount;
+extern int pkix_cRemoveCount;
+extern int pkix_ceAddCount;
+extern int pkix_ceLookupCount;
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+/* Following variables are used for object leak test */
+char *nonNullValue = "Non Empty Value";
+PKIX_Boolean noErrorState = PKIX_TRUE;
+PKIX_Boolean runningLeakTest;
+PKIX_Boolean errorGenerated;
+PKIX_UInt32 stackPosition;
+PKIX_UInt32 *fnStackInvCountArr;
+char **fnStackNameArr;
+PLHashTable *fnInvTable;
+PKIX_UInt32 testStartFnStackPosition;
+char *errorFnStackString;
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+/* --Private-Functions-------------------------------------------- */
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+/*
+ * FUNCTION: pkix_ErrorGen_Hash
+ * DESCRIPTION:
+ *
+ * Hash function to be used in object leak test hash table.
+ *
+ */
+PLHashNumber PR_CALLBACK
+pkix_ErrorGen_Hash (const void *key)
+{
+ char *str = NULL;
+ PLHashNumber rv = (*(PRUint8*)key) << 5;
+ PRUint32 i, counter = 0;
+ PRUint8 *rvc = (PRUint8 *)&rv;
+
+ while ((str = fnStackNameArr[counter++]) != NULL) {
+ PRUint32 len = strlen(str);
+ for( i = 0; i < len; i++ ) {
+ rvc[ i % sizeof(rv) ] ^= *str;
+ str++;
+ }
+ }
+
+ return rv;
+}
+
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+/*
+ * FUNCTION: pkix_IsCertSelfIssued
+ * DESCRIPTION:
+ *
+ * Checks whether the Cert pointed to by "cert" is self-issued and stores the
+ * Boolean result at "pSelfIssued". A Cert is considered self-issued if the
+ * Cert's issuer matches the Cert's subject. If the subject or issuer is
+ * not specified, a PKIX_FALSE is returned.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert used to determine whether Cert is self-issued.
+ * Must be non-NULL.
+ * "pSelfIssued"
+ * Address where Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_IsCertSelfIssued(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pSelfIssued,
+ void *plContext)
+{
+ PKIX_PL_X500Name *subject = NULL;
+ PKIX_PL_X500Name *issuer = NULL;
+
+ PKIX_ENTER(CERT, "pkix_IsCertSelfIssued");
+ PKIX_NULLCHECK_TWO(cert, pSelfIssued);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &subject, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetIssuer(cert, &issuer, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ if (subject == NULL || issuer == NULL) {
+ *pSelfIssued = PKIX_FALSE;
+ } else {
+
+ PKIX_CHECK(PKIX_PL_X500Name_Match
+ (subject, issuer, pSelfIssued, plContext),
+ PKIX_X500NAMEMATCHFAILED);
+ }
+
+cleanup:
+ PKIX_DECREF(subject);
+ PKIX_DECREF(issuer);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_Throw
+ * DESCRIPTION:
+ *
+ * Creates an Error using the value of "errorCode", the character array
+ * pointed to by "funcName", the character array pointed to by "errorText",
+ * and the Error pointed to by "cause" (if any), and stores it at "pError".
+ *
+ * If "cause" is not NULL and has an errorCode of "PKIX_FATAL_ERROR",
+ * then there is no point creating a new Error object. Rather, we simply
+ * store "cause" at "pError".
+ *
+ * PARAMETERS:
+ * "errorCode"
+ * Value of error code.
+ * "funcName"
+ * Address of EscASCII array representing name of function throwing error.
+ * Must be non-NULL.
+ * "errnum"
+ * PKIX_ERRMSGNUM of error description for new error.
+ * "cause"
+ * Address of Error representing error's cause.
+ * "pError"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_Throw(
+ PKIX_ERRORCLASS errorClass,
+ const char *funcName,
+ PKIX_ERRORCODE errorCode,
+ PKIX_ERRORCLASS overrideClass,
+ PKIX_Error *cause,
+ PKIX_Error **pError,
+ void *plContext)
+{
+ PKIX_Error *error = NULL;
+
+ PKIX_ENTER(ERROR, "pkix_Throw");
+ PKIX_NULLCHECK_TWO(funcName, pError);
+
+ *pError = NULL;
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+ noErrorState = PKIX_TRUE;
+ if (pkixLog) {
+#ifdef PKIX_ERROR_DESCRIPTION
+ PR_LOG(pkixLog, 4, ("Error in function \"%s\":\"%s\" with cause \"%s\"\n",
+ funcName, PKIX_ErrorText[errorCode],
+ (cause ? PKIX_ErrorText[cause->errCode] : "null")));
+#else
+ PR_LOG(pkixLog, 4, ("Error in function \"%s\": error code \"%d\"\n",
+ funcName, errorCode));
+#endif /* PKIX_ERROR_DESCRIPTION */
+ PORT_Assert(strcmp(funcName, "PKIX_PL_Object_DecRef"));
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+ /* if cause has error class of PKIX_FATAL_ERROR, return immediately */
+ if (cause) {
+ if (cause->errClass == PKIX_FATAL_ERROR){
+ PKIX_INCREF(cause);
+ *pError = cause;
+ goto cleanup;
+ }
+ }
+
+ if (overrideClass == PKIX_FATAL_ERROR){
+ errorClass = overrideClass;
+ }
+
+ pkixTempResult = PKIX_Error_Create(errorClass, cause, NULL,
+ errorCode, &error, plContext);
+
+ if (!pkixTempResult) {
+ /* Setting plErr error code:
+ * get it from PORT_GetError if it is a leaf error and
+ * default error code does not exist(eq 0) */
+ if (!cause && !error->plErr) {
+ error->plErr = PKIX_PL_GetPLErrorCode();
+ }
+ }
+
+ *pError = error;
+
+cleanup:
+
+ PKIX_DEBUG_EXIT(ERROR);
+ pkixErrorClass = 0;
+#ifdef PKIX_OBJECT_LEAK_TEST
+ noErrorState = PKIX_FALSE;
+
+ if (runningLeakTest && fnStackNameArr) {
+ PR_LOG(pkixLog, 5,
+ ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "),
+ stackPosition, " ", fnStackNameArr[stackPosition],
+ stackPosition, myFuncName));
+ fnStackNameArr[stackPosition--] = NULL;
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
+ return (pkixTempResult);
+}
+
+/*
+ * FUNCTION: pkix_CheckTypes
+ * DESCRIPTION:
+ *
+ * Checks that the types of the Object pointed to by "first" and the Object
+ * pointed to by "second" are both equal to the value of "type". If they
+ * are not equal, a PKIX_Error is returned.
+ *
+ * PARAMETERS:
+ * "first"
+ * Address of first Object. Must be non-NULL.
+ * "second"
+ * Address of second Object. Must be non-NULL.
+ * "type"
+ * Value of type to check against.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CheckTypes(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_UInt32 type,
+ void *plContext)
+{
+ PKIX_UInt32 firstType, secondType;
+
+ PKIX_ENTER(OBJECT, "pkix_CheckTypes");
+ PKIX_NULLCHECK_TWO(first, second);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(first, &firstType, plContext),
+ PKIX_COULDNOTGETFIRSTOBJECTTYPE);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETSECONDOBJECTTYPE);
+
+ if ((firstType != type)||(firstType != secondType)) {
+ PKIX_ERROR(PKIX_OBJECTTYPESDONOTMATCH);
+ }
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_CheckType
+ * DESCRIPTION:
+ *
+ * Checks that the type of the Object pointed to by "object" is equal to the
+ * value of "type". If it is not equal, a PKIX_Error is returned.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object. Must be non-NULL.
+ * "type"
+ * Value of type to check against.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CheckType(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 type,
+ void *plContext)
+{
+ return (pkix_CheckTypes(object, object, type, plContext));
+}
+
+/*
+ * FUNCTION: pkix_hash
+ * DESCRIPTION:
+ *
+ * Computes a hash value for "length" bytes starting at the array of bytes
+ * pointed to by "bytes" and stores the result at "pHash".
+ *
+ * XXX To speed this up, we could probably read 32 bits at a time from
+ * bytes (maybe even 64 bits on some platforms)
+ *
+ * PARAMETERS:
+ * "bytes"
+ * Address of array of bytes to hash. Must be non-NULL.
+ * "length"
+ * Number of bytes to hash.
+ * "pHash"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_hash(
+ const unsigned char *bytes,
+ PKIX_UInt32 length,
+ PKIX_UInt32 *pHash,
+ void *plContext)
+{
+ PKIX_UInt32 i;
+ PKIX_UInt32 hash;
+
+ PKIX_ENTER(OBJECT, "pkix_hash");
+ if (length != 0) {
+ PKIX_NULLCHECK_ONE(bytes);
+ }
+ PKIX_NULLCHECK_ONE(pHash);
+
+ hash = 0;
+ for (i = 0; i < length; i++) {
+ /* hash = 31 * hash + bytes[i]; */
+ hash = (hash << 5) - hash + bytes[i];
+ }
+
+ *pHash = hash;
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_countArray
+ * DESCRIPTION:
+ *
+ * Counts the number of elements in the null-terminated array of pointers
+ * pointed to by "array" and returns the result.
+ *
+ * PARAMETERS
+ * "array"
+ * Address of null-terminated array of pointers.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns the number of elements in the array.
+ */
+PKIX_UInt32
+pkix_countArray(void **array)
+{
+ PKIX_UInt32 count = 0;
+
+ if (array) {
+ while (*array++) {
+ count++;
+ }
+ }
+ return (count);
+}
+
+/*
+ * FUNCTION: pkix_duplicateImmutable
+ * DESCRIPTION:
+ *
+ * Convenience callback function used for duplicating immutable objects.
+ * Since the objects can not be modified, this function simply increments the
+ * reference count on the object, and returns a reference to that object.
+ *
+ * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
+ */
+PKIX_Error *
+pkix_duplicateImmutable(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_ENTER(OBJECT, "pkix_duplicateImmutable");
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_INCREF(object);
+
+ *pNewObject = object;
+
+cleanup:
+ PKIX_RETURN(OBJECT);
+}
+
+/* --String-Encoding-Conversion-Functions------------------------ */
+
+/*
+ * FUNCTION: pkix_hex2i
+ * DESCRIPTION:
+ *
+ * Converts hexadecimal character "c" to its integer value and returns result.
+ *
+ * PARAMETERS
+ * "c"
+ * Character to convert to a hex value.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * The hexadecimal value of "c". Otherwise -1. (Unsigned 0xFFFFFFFF).
+ */
+PKIX_UInt32
+pkix_hex2i(char c)
+{
+ if ((c >= '0')&&(c <= '9'))
+ return (c-'0');
+ else if ((c >= 'a')&&(c <= 'f'))
+ return (c-'a'+10);
+ else if ((c >= 'A')&&(c <= 'F'))
+ return (c-'A'+10);
+ else
+ return ((PKIX_UInt32)(-1));
+}
+
+/*
+ * FUNCTION: pkix_i2hex
+ * DESCRIPTION:
+ *
+ * Converts integer value "digit" to its ASCII hex value
+ *
+ * PARAMETERS
+ * "digit"
+ * Value of integer to convert to ASCII hex value. Must be 0-15.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * The ASCII hexadecimal value of "digit".
+ */
+char
+pkix_i2hex(char digit)
+{
+ if ((digit >= 0)&&(digit <= 9))
+ return (digit+'0');
+ else if ((digit >= 0xa)&&(digit <= 0xf))
+ return (digit - 10 + 'a');
+ else
+ return (-1);
+}
+
+/*
+ * FUNCTION: pkix_isPlaintext
+ * DESCRIPTION:
+ *
+ * Returns whether character "c" is plaintext using EscASCII or EscASCII_Debug
+ * depending on the value of "debug".
+ *
+ * In EscASCII, [01, 7E] except '&' are plaintext.
+ * In EscASCII_Debug [20, 7E] except '&' are plaintext.
+ *
+ * PARAMETERS:
+ * "c"
+ * Character to check.
+ * "debug"
+ * Value of debug flag.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * True if "c" is plaintext.
+ */
+PKIX_Boolean
+pkix_isPlaintext(unsigned char c, PKIX_Boolean debug) {
+ return ((c >= 0x01)&&(c <= 0x7E)&&(c != '&')&&(!debug || (c >= 20)));
+}
+
+/* --Cache-Functions------------------------ */
+
+/*
+ * FUNCTION: pkix_CacheCertChain_Lookup
+ * DESCRIPTION:
+ *
+ * Look up CertChain Hash Table for a cached BuildResult based on "targetCert"
+ * and "anchors" as the hash keys. If there is no item to match the key,
+ * PKIX_FALSE is stored at "pFound". If an item is found, its cache time is
+ * compared to "testDate". If expired, the item is removed and PKIX_FALSE is
+ * stored at "pFound". Otherwise, PKIX_TRUE is stored at "pFound" and the
+ * BuildResult is stored at "pBuildResult".
+ * The hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "targetCert"
+ * Address of Target Cert as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "anchors"
+ * Address of PKIX_List of "anchors" is used as key to retrive CertChain.
+ * Must be non-NULL.
+ * "testDate"
+ * Address of PKIX_PL_Date for verifying time validity and cache validity.
+ * May be NULL. If testDate is NULL, this cache item will not be out-dated.
+ * "pFound"
+ * Address of PKIX_Boolean indicating valid data is found.
+ * Must be non-NULL.
+ * "pBuildResult"
+ * Address where BuildResult will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCertChain_Lookup(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ PKIX_PL_Date *testDate,
+ PKIX_Boolean *pFound,
+ PKIX_BuildResult **pBuildResult,
+ void *plContext)
+{
+ PKIX_List *cachedValues = NULL;
+ PKIX_List *cachedKeys = NULL;
+ PKIX_Error *cachedCertChainError = NULL;
+ PKIX_PL_Date *cacheValidUntilDate = NULL;
+ PKIX_PL_Date *validityDate = NULL;
+ PKIX_Int32 cmpValidTimeResult = 0;
+ PKIX_Int32 cmpCacheTimeResult = 0;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCertChain_Lookup");
+
+ PKIX_NULLCHECK_FOUR(targetCert, anchors, pFound, pBuildResult);
+
+ *pFound = PKIX_FALSE;
+
+ /* use trust anchors and target cert as hash key */
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)targetCert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)anchors,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCertChainError = PKIX_PL_HashTable_Lookup
+ (cachedCertChainTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object **) &cachedValues,
+ plContext);
+
+ pkix_ccLookupCount++;
+
+ /* retrieve data from hashed value list */
+
+ if (cachedValues != NULL && cachedCertChainError == NULL) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 0,
+ (PKIX_PL_Object **) &cacheValidUntilDate,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /* check validity time and cache age time */
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 1,
+ (PKIX_PL_Object **) &validityDate,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /* if testDate is not set, this cache item is not out-dated */
+ if (testDate) {
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)testDate,
+ (PKIX_PL_Object *)cacheValidUntilDate,
+ &cmpCacheTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)testDate,
+ (PKIX_PL_Object *)validityDate,
+ &cmpValidTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+ }
+
+ /* certs' date are all valid and cache item is not old */
+ if (cmpValidTimeResult <= 0 && cmpCacheTimeResult <=0) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 2,
+ (PKIX_PL_Object **) pBuildResult,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ *pFound = PKIX_TRUE;
+
+ } else {
+
+ pkix_ccRemoveCount++;
+ *pFound = PKIX_FALSE;
+
+ /* out-dated item, remove it from cache */
+ PKIX_CHECK(PKIX_PL_HashTable_Remove
+ (cachedCertChainTable,
+ (PKIX_PL_Object *) cachedKeys,
+ plContext),
+ PKIX_HASHTABLEREMOVEFAILED);
+ }
+ }
+
+cleanup:
+
+ PKIX_DECREF(cachedValues);
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedCertChainError);
+ PKIX_DECREF(cacheValidUntilDate);
+ PKIX_DECREF(validityDate);
+
+ PKIX_RETURN(BUILD);
+
+}
+
+/*
+ * FUNCTION: pkix_CacheCertChain_Remove
+ * DESCRIPTION:
+ *
+ * Remove CertChain Hash Table entry based on "targetCert" and "anchors"
+ * as the hash keys. If there is no item to match the key, no action is
+ * taken.
+ * The hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "targetCert"
+ * Address of Target Cert as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "anchors"
+ * Address of PKIX_List of "anchors" is used as key to retrive CertChain.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCertChain_Remove(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ void *plContext)
+{
+ PKIX_List *cachedKeys = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCertChain_Remove");
+ PKIX_NULLCHECK_TWO(targetCert, anchors);
+
+ /* use trust anchors and target cert as hash key */
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)targetCert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)anchors,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK_ONLY_FATAL(PKIX_PL_HashTable_Remove
+ (cachedCertChainTable,
+ (PKIX_PL_Object *) cachedKeys,
+ plContext),
+ PKIX_HASHTABLEREMOVEFAILED);
+
+ pkix_ccRemoveCount++;
+
+cleanup:
+
+ PKIX_DECREF(cachedKeys);
+
+ PKIX_RETURN(BUILD);
+
+}
+
+/*
+ * FUNCTION: pkix_CacheCertChain_Add
+ * DESCRIPTION:
+ *
+ * Add a BuildResult to the CertChain Hash Table for a "buildResult" with
+ * "targetCert" and "anchors" as the hash keys.
+ * "validityDate" is the most restricted notAfter date of all Certs in
+ * this CertChain and is verified when this BuildChain is retrieved.
+ * The hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "targetCert"
+ * Address of Target Cert as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "anchors"
+ * Address of PKIX_List of "anchors" is used as key to retrive CertChain.
+ * Must be non-NULL.
+ * "validityDate"
+ * Address of PKIX_PL_Date contains the most restriced notAfter time of
+ * all "certs". Must be non-NULL.
+ * Address of PKIX_Boolean indicating valid data is found.
+ * Must be non-NULL.
+ * "buildResult"
+ * Address of BuildResult to be cached. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCertChain_Add(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ PKIX_PL_Date *validityDate,
+ PKIX_BuildResult *buildResult,
+ void *plContext)
+{
+ PKIX_List *cachedValues = NULL;
+ PKIX_List *cachedKeys = NULL;
+ PKIX_Error *cachedCertChainError = NULL;
+ PKIX_PL_Date *cacheValidUntilDate = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCertChain_Add");
+
+ PKIX_NULLCHECK_FOUR(targetCert, anchors, validityDate, buildResult);
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)targetCert, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)anchors, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
+ (CACHE_ITEM_PERIOD_SECONDS,
+ &cacheValidUntilDate,
+ plContext),
+ PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues,
+ (PKIX_PL_Object *)cacheValidUntilDate,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues, (PKIX_PL_Object *)validityDate, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues, (PKIX_PL_Object *)buildResult, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCertChainError = PKIX_PL_HashTable_Add
+ (cachedCertChainTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object *) cachedValues,
+ plContext);
+
+ pkix_ccAddCount++;
+
+ if (cachedCertChainError != NULL) {
+ PKIX_DEBUG("PKIX_PL_HashTable_Add for CertChain skipped: "
+ "entry existed\n");
+ }
+
+cleanup:
+
+ PKIX_DECREF(cachedValues);
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedCertChainError);
+ PKIX_DECREF(cacheValidUntilDate);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_CacheCert_Lookup
+ * DESCRIPTION:
+ *
+ * Look up Cert Hash Table for a cached item based on "store" and Subject in
+ * "certSelParams" as the hash keys and returns values Certs in "pCerts".
+ * If there isn't an item to match the key, a PKIX_FALSE is returned at
+ * "pFound". The item's cache time is verified with "testDate". If out-dated,
+ * this item is removed and PKIX_FALSE is returned at "pFound".
+ * This hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * If the CertStore this Cert is from is a trusted one, the cache period is
+ * shorter so cache can be updated more frequently.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "certSelParams"
+ * Address of ComCertSelParams that its subject is used as key to retrieve
+ * this CertChain. Must be non-NULL.
+ * "testDate"
+ * Address of PKIX_PL_Date for verifying time cache validity.
+ * Must be non-NULL. If testDate is NULL, this cache item won't be out
+ * dated.
+ * "pFound"
+ * Address of KPKIX_Boolean indicating valid data is found.
+ * Must be non-NULL.
+ * "pCerts"
+ * Address PKIX_List where the CertChain will be stored. Must be no-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCert_Lookup(
+ PKIX_CertStore *store,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_PL_Date *testDate,
+ PKIX_Boolean *pFound,
+ PKIX_List** pCerts,
+ void *plContext)
+{
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_List *cachedKeys = NULL;
+ PKIX_List *cachedValues = NULL;
+ PKIX_List *cachedCertList = NULL;
+ PKIX_List *selCertList = NULL;
+ PKIX_PL_X500Name *subject = NULL;
+ PKIX_PL_Date *invalidAfterDate = NULL;
+ PKIX_PL_Date *cacheValidUntilDate = NULL;
+ PKIX_CertSelector *certSel = NULL;
+ PKIX_Error *cachedCertError = NULL;
+ PKIX_Error *selectorError = NULL;
+ PKIX_CertSelector_MatchCallback selectorMatch = NULL;
+ PKIX_Int32 cmpValidTimeResult = PKIX_FALSE;
+ PKIX_Int32 cmpCacheTimeResult = 0;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCert_Lookup");
+ PKIX_NULLCHECK_TWO(store, certSelParams);
+ PKIX_NULLCHECK_TWO(pFound, pCerts);
+
+ *pFound = PKIX_FALSE;
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
+ (certSelParams, &subject, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
+
+ PKIX_NULLCHECK_ONE(subject);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)subject, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCertError = PKIX_PL_HashTable_Lookup
+ (cachedCertTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object **) &cachedValues,
+ plContext);
+ pkix_cLookupCount++;
+
+ if (cachedValues != NULL && cachedCertError == NULL) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 0,
+ (PKIX_PL_Object **) &cacheValidUntilDate,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (testDate) {
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)testDate,
+ (PKIX_PL_Object *)cacheValidUntilDate,
+ &cmpCacheTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+ }
+
+ if (cmpCacheTimeResult <= 0) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedValues,
+ 1,
+ (PKIX_PL_Object **) &cachedCertList,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /*
+ * Certs put on cache satifies only for Subject,
+ * user selector and ComCertSelParams to filter.
+ */
+ PKIX_CHECK(PKIX_CertSelector_Create
+ (NULL, NULL, &certSel, plContext),
+ PKIX_CERTSELECTORCREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSel, certSelParams, plContext),
+ PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
+ (certSel, &selectorMatch, plContext),
+ PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&selCertList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ /*
+ * If any of the Cert on the list is out-dated, invalidate
+ * this cache item.
+ */
+ PKIX_CHECK(PKIX_List_GetLength
+ (cachedCertList, &numItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numItems; i++){
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (cachedCertList,
+ i,
+ (PKIX_PL_Object **)&cert,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
+ (cert, &invalidAfterDate, plContext),
+ PKIX_CERTGETVALIDITYNOTAFTERFAILED);
+
+ if (testDate) {
+ PKIX_CHECK(PKIX_PL_Object_Compare
+ ((PKIX_PL_Object *)invalidAfterDate,
+ (PKIX_PL_Object *)testDate,
+ &cmpValidTimeResult,
+ plContext),
+ PKIX_OBJECTCOMPARATORFAILED);
+ }
+
+ if (cmpValidTimeResult < 0) {
+
+ pkix_cRemoveCount++;
+ *pFound = PKIX_FALSE;
+
+ /* one cert is out-dated, remove item from cache */
+ PKIX_CHECK(PKIX_PL_HashTable_Remove
+ (cachedCertTable,
+ (PKIX_PL_Object *) cachedKeys,
+ plContext),
+ PKIX_HASHTABLEREMOVEFAILED);
+ goto cleanup;
+ }
+
+ selectorError = selectorMatch(certSel, cert, plContext);
+ if (!selectorError){
+ /* put on the return list */
+ PKIX_CHECK(PKIX_List_AppendItem
+ (selCertList,
+ (PKIX_PL_Object *)cert,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ *pFound = PKIX_TRUE;
+ } else {
+ PKIX_DECREF(selectorError);
+ }
+
+ PKIX_DECREF(cert);
+ PKIX_DECREF(invalidAfterDate);
+
+ }
+
+ if (*pFound) {
+ PKIX_INCREF(selCertList);
+ *pCerts = selCertList;
+ }
+
+ } else {
+
+ pkix_cRemoveCount++;
+ *pFound = PKIX_FALSE;
+ /* cache item is out-dated, remove it from cache */
+ PKIX_CHECK(PKIX_PL_HashTable_Remove
+ (cachedCertTable,
+ (PKIX_PL_Object *) cachedKeys,
+ plContext),
+ PKIX_HASHTABLEREMOVEFAILED);
+ }
+
+ }
+
+cleanup:
+
+ PKIX_DECREF(subject);
+ PKIX_DECREF(certSel);
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedValues);
+ PKIX_DECREF(cacheValidUntilDate);
+ PKIX_DECREF(cert);
+ PKIX_DECREF(cachedCertList);
+ PKIX_DECREF(selCertList);
+ PKIX_DECREF(invalidAfterDate);
+ PKIX_DECREF(cachedCertError);
+ PKIX_DECREF(selectorError);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_CacheCert_Add
+ * DESCRIPTION:
+ *
+ * Add Cert Hash Table for a cached item based on "store" and Subject in
+ * "certSelParams" as the hash keys and have "certs" as the key value.
+ * This hashtable is maintained in the following ways:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ * 2) A PKIX_PL_Date created with current time offset by constant
+ * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table.
+ * If the CertStore this Cert is from is a trusted one, the cache period is
+ * shorter so cache can be updated more frequently.
+ * When an item is retrieved, this date is compared against "testDate" for
+ * validity. If comparison indicates this item is expired, the item is
+ * removed from the bucket.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "certSelParams"
+ * Address of ComCertSelParams that its subject is used as key to retrieve
+ * this CertChain. Must be non-NULL.
+ * "certs"
+ * Address PKIX_List of Certs will be stored. Must be no-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCert_Add(
+ PKIX_CertStore *store,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_List* certs,
+ void *plContext)
+{
+ PKIX_List *cachedKeys = NULL;
+ PKIX_List *cachedValues = NULL;
+ PKIX_List *cachedCerts = NULL;
+ PKIX_PL_Date *cacheValidUntilDate = NULL;
+ PKIX_PL_X500Name *subject = NULL;
+ PKIX_Error *cachedCertError = NULL;
+ PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
+ PKIX_UInt32 cachePeriod = CACHE_ITEM_PERIOD_SECONDS;
+ PKIX_UInt32 numCerts = 0;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCert_Add");
+ PKIX_NULLCHECK_THREE(store, certSelParams, certs);
+
+ PKIX_CHECK(PKIX_List_GetLength(certs, &numCerts,
+ plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ if (numCerts == 0) {
+ /* Don't want to add an empty list. */
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
+ (certSelParams, &subject, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
+
+ PKIX_NULLCHECK_ONE(subject);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)subject, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_CertStore_GetTrustCallback
+ (store, &trustCallback, plContext),
+ PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
+
+ if (trustCallback) {
+ cachePeriod = CACHE_TRUST_ITEM_PERIOD_SECONDS;
+ }
+
+ PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
+ (cachePeriod, &cacheValidUntilDate, plContext),
+ PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues,
+ (PKIX_PL_Object *)cacheValidUntilDate,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DUPLICATE(certs, &cachedCerts, plContext,
+ PKIX_OBJECTDUPLICATELISTFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedValues,
+ (PKIX_PL_Object *)cachedCerts,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCertError = PKIX_PL_HashTable_Add
+ (cachedCertTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object *) cachedValues,
+ plContext);
+
+ pkix_cAddCount++;
+
+ if (cachedCertError != NULL) {
+ PKIX_DEBUG("PKIX_PL_HashTable_Add for Certs skipped: "
+ "entry existed\n");
+ }
+
+cleanup:
+
+ PKIX_DECREF(subject);
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedValues);
+ PKIX_DECREF(cachedCerts);
+ PKIX_DECREF(cacheValidUntilDate);
+ PKIX_DECREF(cachedCertError);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_CacheCrlEntry_Lookup
+ * DESCRIPTION:
+ *
+ * Look up CrlEntry Hash Table for a cached item based on "store",
+ * "certIssuer" and "certSerialNumber" as the hash keys and returns values
+ * "pCrls". If there isn't an item to match the key, a PKIX_FALSE is
+ * returned at "pFound".
+ * This hashtable is maintained in the following way:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "certIssuer"
+ * Address of X500Name that is used as key to retrieve the CRLEntries.
+ * Must be non-NULL.
+ * "certSerialNumber"
+ * Address of BigInt that is used as key to retrieve the CRLEntries.
+ * Must be non-NULL.
+ * "pFound"
+ * Address of KPKIX_Boolean indicating valid data is found.
+ * Must be non-NULL.
+ * "pCrls"
+ * Address PKIX_List where the CRLEntry will be stored. Must be no-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCrlEntry_Lookup(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *certIssuer,
+ PKIX_PL_BigInt *certSerialNumber,
+ PKIX_Boolean *pFound,
+ PKIX_List** pCrls,
+ void *plContext)
+{
+ PKIX_List *cachedKeys = NULL;
+ PKIX_List *cachedCrlEntryList = NULL;
+ PKIX_Error *cachedCrlEntryError = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Lookup");
+ PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber);
+ PKIX_NULLCHECK_TWO(pFound, pCrls);
+
+ *pFound = PKIX_FALSE;
+
+ /* Find CrlEntry(s) by issuer and serial number */
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)certSerialNumber,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCrlEntryError = PKIX_PL_HashTable_Lookup
+ (cachedCrlEntryTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object **) &cachedCrlEntryList,
+ plContext);
+ pkix_ceLookupCount++;
+
+ /*
+ * We don't need check Date to invalidate this cache item,
+ * the item is uniquely defined and won't be reverted. Let
+ * the FIFO for cleaning up.
+ */
+
+ if (cachedCrlEntryList != NULL && cachedCrlEntryError == NULL ) {
+
+ PKIX_INCREF(cachedCrlEntryList);
+ *pCrls = cachedCrlEntryList;
+
+ *pFound = PKIX_TRUE;
+
+ } else {
+
+ *pFound = PKIX_FALSE;
+ }
+
+cleanup:
+
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedCrlEntryList);
+ PKIX_DECREF(cachedCrlEntryError);
+
+ PKIX_RETURN(BUILD);
+}
+
+/*
+ * FUNCTION: pkix_CacheCrlEntry_Add
+ * DESCRIPTION:
+ *
+ * Look up CrlEntry Hash Table for a cached item based on "store",
+ * "certIssuer" and "certSerialNumber" as the hash keys and have "pCrls" as
+ * the hash value. If there isn't an item to match the key, a PKIX_FALSE is
+ * returned at "pFound".
+ * This hashtable is maintained in the following way:
+ * 1) When creating the hashtable, maximum bucket size can be specified (0 for
+ * unlimited). If items in a bucket reaches its full size, an new addition
+ * will trigger the removal of the old as FIFO sequence.
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of CertStore as key to retrieve this CertChain. Must be
+ * non-NULL.
+ * "certIssuer"
+ * Address of X500Name that is used as key to retrieve the CRLEntries.
+ * Must be non-NULL.
+ * "certSerialNumber"
+ * Address of BigInt that is used as key to retrieve the CRLEntries.
+ * Must be non-NULL.
+ * "crls"
+ * Address PKIX_List where the CRLEntry is stored. Must be no-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Error Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_CacheCrlEntry_Add(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *certIssuer,
+ PKIX_PL_BigInt *certSerialNumber,
+ PKIX_List* crls,
+ void *plContext)
+{
+ PKIX_List *cachedKeys = NULL;
+ PKIX_Error *cachedCrlEntryError = NULL;
+
+ PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Add");
+ PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber);
+ PKIX_NULLCHECK_ONE(crls);
+
+ /* Add CrlEntry(s) by issuer and serial number */
+
+ PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)store, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (cachedKeys,
+ (PKIX_PL_Object *)certSerialNumber,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ cachedCrlEntryError = PKIX_PL_HashTable_Add
+ (cachedCrlEntryTable,
+ (PKIX_PL_Object *) cachedKeys,
+ (PKIX_PL_Object *) crls,
+ plContext);
+ pkix_ceAddCount++;
+
+cleanup:
+
+ PKIX_DECREF(cachedKeys);
+ PKIX_DECREF(cachedCrlEntryError);
+
+ PKIX_RETURN(BUILD);
+}
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+
+/* TEST_START_FN and testStartFnStackPosition define at what state
+ * of the stack the object leak testing should begin. The condition
+ * in pkix_CheckForGeneratedError works the following way: do leak
+ * testing if at position testStartFnStackPosition in stack array
+ * (fnStackNameArr) we have called function TEST_START_FN.
+ * Note, that stack array get filled only when executing libpkix
+ * functions.
+ * */
+#define TEST_START_FN "PKIX_BuildChain"
+
+PKIX_Error*
+pkix_CheckForGeneratedError(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ char * fnName,
+ PKIX_Boolean *errSetFlag,
+ void * plContext)
+{
+ PKIX_Error *genErr = NULL;
+ PKIX_UInt32 pos = 0;
+ PKIX_UInt32 strLen = 0;
+
+ if (fnName) {
+ if (fnStackNameArr[testStartFnStackPosition] == NULL ||
+ strcmp(fnStackNameArr[testStartFnStackPosition], TEST_START_FN)
+ ) {
+ /* return with out error if not with in boundary */
+ return NULL;
+ }
+ if (!strcmp(fnName, TEST_START_FN)) {
+ *errSetFlag = PKIX_TRUE;
+ noErrorState = PKIX_FALSE;
+ errorGenerated = PKIX_FALSE;
+ }
+ }
+
+ if (noErrorState || errorGenerated) return NULL;
+
+ if (fnName && (
+ !strcmp(fnName, "PKIX_PL_Object_DecRef") ||
+ !strcmp(fnName, "PKIX_PL_Object_Unlock") ||
+ !strcmp(fnName, "pkix_UnlockObject") ||
+ !strcmp(fnName, "pkix_Throw") ||
+ !strcmp(fnName, "pkix_trace_dump_cert") ||
+ !strcmp(fnName, "PKIX_PL_Free"))) {
+ /* do not generate error for this functions */
+ noErrorState = PKIX_TRUE;
+ *errSetFlag = PKIX_TRUE;
+ return NULL;
+ }
+
+ if (PL_HashTableLookup(fnInvTable, &fnStackInvCountArr[stackPosition - 1])) {
+ return NULL;
+ }
+
+ PL_HashTableAdd(fnInvTable, &fnStackInvCountArr[stackPosition - 1], nonNullValue);
+ errorGenerated = PKIX_TRUE;
+ noErrorState = PKIX_TRUE;
+ genErr = PKIX_DoThrow(stdVars, errClass, PKIX_MEMLEAKGENERATEDERROR,
+ errClass, plContext);
+ while(fnStackNameArr[pos]) {
+ strLen += PORT_Strlen(fnStackNameArr[pos++]) + 1;
+ }
+ strLen += 1; /* end of line. */
+ pos = 0;
+ errorFnStackString = PORT_ZAlloc(strLen);
+ while(fnStackNameArr[pos]) {
+ strcat(errorFnStackString, "/");
+ strcat(errorFnStackString, fnStackNameArr[pos++]);
+ }
+ noErrorState = PKIX_FALSE;
+
+ return genErr;
+}
+#endif /* PKIX_OBJECT_LEAK_TEST */
diff --git a/security/nss/lib/libpkix/pkix/util/pkix_tools.h b/security/nss/lib/libpkix/pkix/util/pkix_tools.h
new file mode 100644
index 0000000000..5a8ef2741e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/pkix_tools.h
@@ -0,0 +1,1588 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_tools.h
+ *
+ * Header for Utility Functions and Macros
+ *
+ */
+
+#ifndef _PKIX_TOOLS_H
+#define _PKIX_TOOLS_H
+
+#include "pkix.h"
+#include <stddef.h>
+#include <stdio.h>
+#include "secport.h"
+#include "prlong.h"
+
+/* private PKIX system headers */
+#include "pkix_basicconstraintschecker.h"
+#include "pkix_buildresult.h"
+#include "pkix_certchainchecker.h"
+#include "pkix_certselector.h"
+#include "pkix_comcertselparams.h"
+#include "pkix_comcrlselparams.h"
+#include "pkix_crlselector.h"
+#include "pkix_error.h"
+#include "pkix_expirationchecker.h"
+#include "pkix_list.h"
+#include "pkix_logger.h"
+#include "pkix_namechainingchecker.h"
+#include "pkix_nameconstraintschecker.h"
+#include "pkix_policychecker.h"
+#include "pkix_policynode.h"
+#include "pkix_procparams.h"
+#include "pkix_resourcelimits.h"
+#include "pkix_revocationmethod.h"
+#include "pkix_revocationchecker.h"
+#include "pkix_crlchecker.h"
+#include "pkix_ocspchecker.h"
+#include "pkix_signaturechecker.h"
+#include "pkix_store.h"
+#include "pkix_targetcertchecker.h"
+#include "pkix_validate.h"
+#include "pkix_valresult.h"
+#include "pkix_verifynode.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkixStdVarsStr {
+ const char *aMyFuncName;
+ PKIX_Error *aPkixErrorResult;
+ PKIX_Error *aPkixTempResult;
+ PKIX_Error *aPkixReturnResult;
+ PKIX_ERRORCODE aPkixErrorCode;
+ PKIX_Boolean aPkixErrorReceived;
+ PKIX_Boolean aPkixTempErrorReceived;
+ PKIX_ERRORCLASS aPkixErrorClass;
+ PKIX_UInt32 aPkixType;
+ PKIX_PL_Object *aLockedObject;
+ PKIX_List *aPkixErrorList;
+} PKIX_StdVars;
+
+#ifdef PKIX_STDVARS_POINTER
+#define myFuncName stdVars->aMyFuncName
+#define pkixErrorResult stdVars->aPkixErrorResult
+#define pkixTempResult stdVars->aPkixTempResult
+#define pkixReturnResult stdVars->aPkixReturnResult
+#define pkixErrorCode stdVars->aPkixErrorCode
+#define pkixErrorReceived stdVars->aPkixErrorReceived
+#define pkixTempErrorReceived stdVars->aPkixTempErrorReceived
+#define pkixErrorClass stdVars->aPkixErrorClass
+#define pkixType stdVars->aPkixType
+#define lockedObject stdVars->aLockedObject
+#define pkixErrorList stdVars->aPkixErrorList
+#define stdVarsPtr stdVars
+#else
+#define myFuncName stdVars.aMyFuncName
+#define pkixErrorResult stdVars.aPkixErrorResult
+#define pkixTempResult stdVars.aPkixTempResult
+#define pkixReturnResult stdVars.aPkixReturnResult
+#define pkixErrorCode stdVars.aPkixErrorCode
+#define pkixErrorReceived stdVars.aPkixErrorReceived
+#define pkixTempErrorReceived stdVars.aPkixTempErrorReceived
+#define pkixErrorClass stdVars.aPkixErrorClass
+#define pkixType stdVars.aPkixType
+#define lockedObject stdVars.aLockedObject
+#define pkixErrorList stdVars.aPkixErrorList
+#define stdVarsPtr &stdVars
+#endif
+
+extern PKIX_Error * PKIX_DoReturn(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ PKIX_Boolean doLogger,
+ void * plContext);
+
+extern PKIX_Error * PKIX_DoThrow(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ PKIX_ERRORCODE errCode,
+ PKIX_ERRORCLASS overrideClass,
+ void * plContext);
+
+extern void PKIX_DoAddError(PKIX_StdVars * stdVars,
+ PKIX_Error * error,
+ void * plContext);
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+extern PKIX_Error * pkix_CheckForGeneratedError(PKIX_StdVars * stdVars,
+ PKIX_ERRORCLASS errClass,
+ char * fnName,
+ PKIX_Boolean *errorStateSet,
+ void * plContext);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+extern const PKIX_StdVars zeroStdVars;
+
+extern PRLogModuleInfo *pkixLog;
+
+/*
+ * UTILITY MACROS
+ * Documentation for these common utility macros can be found in the
+ * Implementation Guidelines document (Section 4.3)
+ *
+ * In general, macros with multiple statements (or a single "if" statement)
+ * use the "do {<body>} while (0)" technique in order to convert the multiple
+ * statements into one statement, thus avoiding the dangling else problem.
+ * For macros which ALWAYS exit with a "return" or "goto", there is no
+ * need to use this technique (and it yields compiler warnings of "statement
+ * not reached"), so we just use "{<body>}" to group the statements together.
+ */
+
+#if !defined (PKIX_OBJECT_LEAK_TEST)
+
+#define PKIX_STD_VARS(funcName) \
+ static const char cMyFuncName[] = {funcName}; \
+ PKIX_StdVars stdVars = zeroStdVars; \
+ myFuncName = cMyFuncName
+
+
+#else /* PKIX_OBJECT_LEAK_TEST */
+
+extern char **fnStackNameArr;
+extern PKIX_UInt32 *fnStackInvCountArr;
+extern PKIX_UInt32 stackPosition;
+extern PKIX_Boolean noErrorState;
+extern PKIX_Boolean errorGenerated;
+extern PKIX_Boolean runningLeakTest;
+extern PLHashTable *fnInvTable;
+extern PKIX_UInt32 testStartFnStackPosition;
+extern char *errorFnStackString;
+
+extern PLHashNumber PR_CALLBACK pkix_ErrorGen_Hash (const void *key);
+
+#define PKIX_STD_VARS(funcName) \
+ static const char cMyFuncName[] = {funcName}; \
+ PKIX_StdVars stdVars = zeroStdVars; \
+ PKIX_Boolean errorSetFlag = PKIX_FALSE; \
+ myFuncName = cMyFuncName; \
+ if (runningLeakTest) { \
+ if (fnStackNameArr) { \
+ fnStackInvCountArr[stackPosition] += 1; \
+ stackPosition += 1; \
+ fnStackInvCountArr[stackPosition] = 0; \
+ fnStackNameArr[stackPosition] = (char*)myFuncName; \
+ fnStackNameArr[stackPosition + 1] = NULL; \
+ PR_LOG(pkixLog, 5, \
+ ("%s%*s+> %s(%d) - %s\n", (errorGenerated ? "*" : " "), \
+ stackPosition, " ", fnStackNameArr[stackPosition], \
+ stackPosition, myFuncName)); \
+ } \
+ do { \
+ pkixErrorResult = pkix_CheckForGeneratedError(&stdVars, PKIX_MEM_ERROR, \
+ funcName, &errorSetFlag, \
+ plContext); \
+ if (pkixErrorResult) { \
+ PR_LOG(pkixLog, 5, \
+ ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), \
+ stackPosition, " ", fnStackNameArr[stackPosition], \
+ stackPosition, myFuncName)); \
+ fnStackNameArr[stackPosition--] = NULL; \
+ if (errorSetFlag) { \
+ noErrorState = (noErrorState) ? PKIX_FALSE : PKIX_TRUE; \
+ } \
+ return pkixErrorResult; \
+ } \
+ } while (0); \
+ }
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+#ifdef DEBUG
+#define _PKIX_DEBUG_TRACE(cond, prefix, level) \
+ do { \
+ if (cond) { \
+ pkix_Logger_Check(pkixLoggersDebugTrace, myFuncName, \
+ prefix, pkixType, level, plContext); \
+ } \
+ } while (0)
+#else
+#define _PKIX_DEBUG_TRACE(cond, prefix, level)
+#endif
+
+#define _PKIX_LOG_ERROR(code, level) \
+ { \
+ if (pkixLoggersErrors) { \
+ pkix_Logger_CheckWithCode(pkixLoggersErrors, code, \
+ NULL, pkixType, level, plContext); \
+ } \
+ }
+
+#define PKIX_ENTER(type, funcName) \
+ PKIX_STD_VARS(funcName); \
+ pkixType = PKIX_ ## type ## _ERROR; \
+ PKIX_DEBUG_ENTER(type); \
+ _PKIX_DEBUG_TRACE(pkixLoggersDebugTrace, ">>>", PKIX_LOGGER_LEVEL_TRACE);
+
+#define PKIX_ENTER_NO_LOGGER(type, funcName) \
+ PKIX_STD_VARS(funcName); \
+ pkixType = PKIX_ ## type ## _ERROR; \
+ PKIX_DEBUG_ENTER(type);
+
+#define PKIX_DEBUG_ENTER(type) \
+ PKIX_ ## type ## _DEBUG_ARG("( Entering %s).\n", myFuncName)
+
+#define PKIX_DEBUG_EXIT(type) \
+ PKIX_ ## type ## _DEBUG_ARG("( Exiting %s).\n", myFuncName)
+
+#define PKIX_OBJECT_UNLOCK(obj) \
+ do { \
+ if (obj && lockedObject == (PKIX_PL_Object *)(obj)){ \
+ pkixTempResult = \
+ PKIX_PL_Object_Unlock \
+ ((PKIX_PL_Object *)(obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ } \
+ lockedObject = NULL; \
+ } else { \
+ PORT_Assert(lockedObject == NULL); \
+ } \
+ } while (0)
+
+#define PKIX_DECREF(obj) \
+ do { \
+ if (obj){ \
+ pkixTempResult = PKIX_PL_Object_DecRef \
+ ((PKIX_PL_Object *)(obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ } \
+ obj = NULL; \
+ } \
+ } while (0)
+
+#define PKIX_THROW(type, descNum) \
+ return PKIX_DoThrow(&stdVars, (PKIX_ ## type ## _ERROR), descNum, \
+ pkixErrorClass, plContext);
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+#define PKIX_RETURN(type) \
+ if (runningLeakTest && fnStackNameArr) { \
+ PR_LOG(pkixLog, 5, \
+ ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), \
+ stackPosition, " ", fnStackNameArr[stackPosition], \
+ stackPosition, myFuncName)); \
+ fnStackNameArr[stackPosition--] = NULL; \
+ if (errorSetFlag) noErrorState = (noErrorState) ? PKIX_FALSE : PKIX_TRUE; \
+ } \
+ return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_TRUE, plContext);
+#else
+#define PKIX_RETURN(type) \
+ return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_TRUE, plContext);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+
+#if defined(DEBUG) && !defined(DEBUG_nb95248)
+#define PKIX_RETURN_NO_LOGGER(type) \
+ { \
+ PKIX_OBJECT_UNLOCK(lockedObject); \
+ if ((pkixErrorReceived) || (pkixErrorResult) || pkixErrorList) \
+ PKIX_THROW(type, pkixErrorCode); \
+ PKIX_DEBUG_EXIT(type); \
+ return NULL; \
+ }
+#else
+#define PKIX_RETURN_NO_LOGGER(type) \
+ return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_FALSE, plContext);
+#endif
+
+/* disable to disable ;-) */
+/* #define WANT_TRACE_CHECK_FAILURES */
+
+#ifdef WANT_TRACE_CHECK_FAILURES
+#define TRACE_CHECK_FAILURE(what, errorstring) \
+ if (pkixLog) { \
+ PR_LOG(pkixLog, PR_LOG_DEBUG, \
+ ("====> [%s] failed: %s\n", #what, errorstring)); \
+ }
+#else
+#define TRACE_CHECK_FAILURE(what, errorstring)
+#endif
+
+#define PKIX_CHECK(func, descNum) \
+ do { \
+ pkixErrorResult = (func); \
+ if (pkixErrorResult) { \
+ TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \
+ pkixErrorClass = pkixErrorResult->errClass; \
+ pkixErrorCode = descNum; \
+ goto cleanup; \
+ } \
+ } while (0)
+
+/* like PKIX_CHECK but without goto cleanup */
+#define PKIX_CHECK_NO_GOTO(func, descNum) \
+ do { \
+ pkixErrorResult = (func); \
+ if (pkixErrorResult) { \
+ TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \
+ pkixErrorClass = pkixErrorResult->errClass; \
+ pkixErrorCode = descNum; \
+ } \
+ } while (0)
+
+#define PKIX_CHECK_ONLY_FATAL(func, descNum) \
+ do { \
+ pkixTempErrorReceived = PKIX_FALSE; \
+ pkixErrorResult = (func); \
+ if (pkixErrorResult) { \
+ TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \
+ pkixTempErrorReceived = PKIX_TRUE; \
+ pkixErrorClass = pkixErrorResult->errClass; \
+ if (pkixErrorClass == PKIX_FATAL_ERROR) { \
+ goto cleanup; \
+ } \
+ PKIX_DECREF(pkixErrorResult); \
+ } \
+ } while (0)
+
+#define PKIX_LOG_ERROR(descNum) \
+ _PKIX_LOG_ERROR(descNum, PKIX_LOGGER_LEVEL_ERROR)
+
+#define PKIX_ERROR(descNum) \
+ { \
+ PKIX_LOG_ERROR(descNum) \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = descNum; \
+ goto cleanup; \
+ }
+
+#define PKIX_ERROR_ALLOC_ERROR() \
+ { \
+ PKIX_LOG_ERROR(PKIX_ALLOCERROR) \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorResult = PKIX_ALLOC_ERROR(); \
+ goto cleanup; \
+ }
+
+#define PKIX_ERROR_FATAL(descNum) \
+ { \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = descNum; \
+ pkixErrorClass = PKIX_FATAL_ERROR; \
+ _PKIX_LOG_ERROR(pkixErrorCode, PKIX_LOGGER_LEVEL_FATALERROR); \
+ goto cleanup; \
+ }
+
+#define PKIX_CHECK_FATAL(func, descNum) \
+ do { \
+ pkixErrorResult = (func); \
+ if (pkixErrorResult) { \
+ TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = descNum; \
+ pkixErrorClass = PKIX_FATAL_ERROR; \
+ _PKIX_LOG_ERROR(pkixErrorCode, PKIX_LOGGER_LEVEL_FATALERROR); \
+ goto fatal; \
+ } \
+ } while (0)
+
+#define PKIX_NULLCHECK_ONE(a) \
+ do { \
+ if ((a) == NULL){ \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = PKIX_NULLARGUMENT; \
+ PKIX_RETURN(FATAL); \
+ } \
+ } while (0)
+
+#define PKIX_NULLCHECK_TWO(a, b) \
+ do { \
+ if (((a) == NULL) || ((b) == NULL)){ \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = PKIX_NULLARGUMENT; \
+ PKIX_RETURN(FATAL); \
+ } \
+ } while (0)
+
+#define PKIX_NULLCHECK_THREE(a, b, c) \
+ do { \
+ if (((a) == NULL) || ((b) == NULL) || ((c) == NULL)){ \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = PKIX_NULLARGUMENT; \
+ PKIX_RETURN(FATAL); \
+ } \
+ } while (0)
+
+#define PKIX_NULLCHECK_FOUR(a, b, c, d) \
+ do { \
+ if (((a) == NULL) || ((b) == NULL) || \
+ ((c) == NULL) || ((d) == NULL)){ \
+ pkixErrorReceived = PKIX_TRUE; \
+ pkixErrorCode = PKIX_NULLARGUMENT; \
+ PKIX_RETURN(FATAL); \
+ } \
+ } while (0)
+
+#define PKIX_OBJECT_LOCK(obj) \
+ do { \
+ if (obj) { \
+ pkixTempResult = \
+ PKIX_PL_Object_Lock((PKIX_PL_Object*)(obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ pkixErrorCode = PKIX_OBJECTLOCKFAILED; \
+ goto cleanup; \
+ } \
+ lockedObject = (PKIX_PL_Object *)(obj); \
+ } \
+ } while (0)
+
+#define PKIX_ERROR_CREATE(type, descNum, error) \
+ { \
+ pkixTempResult = (PKIX_Error*)pkix_Throw \
+ (PKIX_ ## type ## _ERROR, myFuncName, \
+ descNum, PKIX_ ## type ## _ERROR, pkixErrorResult, \
+ &error, plContext); \
+ if (pkixTempResult) { \
+ error = pkixTempResult; \
+ pkixTempResult = NULL; \
+ } \
+ }
+
+
+#define PKIX_ERROR_RECEIVED \
+ (pkixErrorReceived || pkixErrorResult || pkixTempErrorReceived || \
+ pkixErrorList)
+
+#define PKIX_INCREF(obj) \
+ do { \
+ if (obj){ \
+ pkixTempResult = PKIX_PL_Object_IncRef \
+ ((PKIX_PL_Object *)(obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ goto cleanup; \
+ } \
+ } \
+ } while (0)
+
+#define PKIX_FREE(obj) \
+ do { \
+ if (obj) { \
+ pkixTempResult = PKIX_PL_Free((obj), plContext); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ } \
+ obj = NULL; \
+ } \
+ } while (0)
+
+#define PKIX_EXACTLY_ONE_NULL(a, b) (((a) && !(b)) || ((b) && !(a)))
+
+/* DIGIT MACROS */
+
+#define PKIX_ISDIGIT(c) (((c) >= '0') && ((c) <= '9'))
+
+#define PKIX_ISXDIGIT(c) \
+ (PKIX_ISDIGIT(c) || ( (((c)|0x20) >= 'a') && (((c)|0x20) <= 'f') ))
+
+#define PKIX_TOSTRING(a, b, c, d) \
+ do { \
+ int descNum; \
+ if ((a) != NULL) { \
+ pkixErrorResult = \
+ PKIX_PL_Object_ToString((PKIX_PL_Object *)(a), (b), (c)); \
+ descNum = (d); \
+ } else { \
+ pkixErrorResult = \
+ PKIX_PL_String_Create(PKIX_ESCASCII, "(null)", 0, (b), (c)); \
+ descNum = PKIX_STRINGCREATEFAILED; \
+ } \
+ PKIX_CHECK(pkixErrorResult, descNum); \
+ } while (0)
+
+#define PKIX_EQUALS(a, b, c, d, e) \
+ do { \
+ if ((a) != NULL && (b) != NULL) { \
+ PKIX_CHECK(PKIX_PL_Object_Equals\
+ ((PKIX_PL_Object *)(a), \
+ (PKIX_PL_Object*)(b), \
+ (c), \
+ (d)), \
+ (e)); \
+ } else if ((a) == NULL && (b) == NULL) { \
+ *(c) = PKIX_TRUE; \
+ } else { \
+ *(c) = PKIX_FALSE; \
+ } \
+ } while (0)
+
+#define PKIX_HASHCODE(a, b, c, d) \
+ do { \
+ if ((a) != NULL) { \
+ PKIX_CHECK(PKIX_PL_Object_Hashcode\
+ ((PKIX_PL_Object *)(a), (b), (c)), (d)); \
+ } else { \
+ *(b) = 0; \
+ } \
+ } while (0)
+
+#define PKIX_DUPLICATE(a, b, c, d) \
+ do { \
+ if ((a) != NULL) { \
+ PKIX_CHECK(PKIX_PL_Object_Duplicate\
+ ((PKIX_PL_Object *)(a), \
+ (PKIX_PL_Object **)(b), \
+ (c)), \
+ (d)); \
+ } else { \
+ *(b) = (a); \
+ } \
+ } while (0)
+
+/*
+ * DEBUG MACROS
+ *
+ * Each type has an associated debug flag, which can
+ * be set on the compiler line using "-D<debugflag>". For convenience,
+ * "-DPKIX_DEBUGALL" turns on debug for all the components.
+ *
+ * If a type's debug flag is defined, then its two associated macros
+ * are defined: PKIX_type_DEBUG(expr) and PKIX_type_DEBUG_ARG(expr, arg),
+ * which call PKIX_DEBUG(expr) and PKIX_DEBUG_ARG(expr, arg) respectively,
+ * which, in turn, enable standard and consistently formatted output.
+ *
+ * If a type's debug flag is not defined, the two associated macros
+ * are defined as a NO-OP. As such, any PKIX_type_DEBUG or PKIX_type_DEBUG_ARG
+ * macros for an undefined type will be stripped from the code during
+ * pre-processing, thereby reducing code size.
+ */
+
+#ifdef PKIX_DEBUGALL
+#define PKIX_REFCOUNTDEBUG 1
+#define PKIX_MEMDEBUG 1
+#define PKIX_MUTEXDEBUG 1
+#define PKIX_OBJECTDEBUG 1
+#define PKIX_STRINGDEBUG 1
+#define PKIX_OIDDEBUG 1
+#define PKIX_LISTDEBUG 1
+#define PKIX_ERRORDEBUG 1
+#define PKIX_BYTEARRAYDEBUG 1
+#define PKIX_RWLOCKDEBUG 1
+#define PKIX_BIGINTDEBUG 1
+#define PKIX_HASHTABLEDEBUG 1
+#define PKIX_X500NAMEDEBUG 1
+#define PKIX_GENERALNAMEDEBUG 1
+#define PKIX_PUBLICKEYDEBUG 1
+#define PKIX_CERTDEBUG 1
+#define PKIX_HTTPCLIENTDEBUG 1
+#define PKIX_DATEDEBUG 1
+#define PKIX_TRUSTANCHORDEBUG 1
+#define PKIX_PROCESSINGPARAMSDEBUG 1
+#define PKIX_VALIDATEPARAMSDEBUG 1
+#define PKIX_VALIDATERESULTDEBUG 1
+#define PKIX_VALIDATEDEBUG 1
+#define PKIX_CERTCHAINCHECKERDEBUG 1
+#define PKIX_REVOCATIONCHECKERDEBUG 1
+#define PKIX_CERTSELECTORDEBUG 1
+#define PKIX_COMCERTSELPARAMSDEBUG 1
+#define PKIX_TARGETCERTCHECKERSTATEDEBUG 1
+#define PKIX_INITIALIZEPARAMSDEBUG 1
+#define PKIX_CERTBASICCONSTRAINTSDEBUG 1
+#define PKIX_CERTNAMECONSTRAINTSDEBUG 1
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATEDEBUG 1
+#define PKIX_SUBJALTNAMECHECKERSTATEDEBUG 1
+
+#define PKIX_CERTPOLICYQUALIFIERDEBUG 1
+#define PKIX_CERTPOLICYINFODEBUG 1
+#define PKIX_CERTPOLICYNODEDEBUG 1
+#define PKIX_CERTPOLICYCHECKERSTATEDEBUG 1
+#define PKIX_LIFECYCLEDEBUG 1
+#define PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG 1
+#define PKIX_CRLDEBUG 1
+#define PKIX_CRLENTRYDEBUG 1
+#define PKIX_CRLSELECTORDEBUG 1
+#define PKIX_COMCRLSELPARAMSDEBUG 1
+#define PKIX_CERTSTOREDEBUG 1
+#define PKIX_COLLECTIONCERTSTORECONTEXTDEBUG 1
+#define PKIX_DEFAULTCRLCHECKERSTATEDEBUG 1
+#define PKIX_CERTPOLICYMAPDEBUG 1
+#define PKIX_BUILDDEBUG 1
+#define PKIX_BUILDRESULTDEBUG 1
+#define PKIX_FORWARDBUILDERSTATEDEBUG 1
+#define PKIX_SIGNATURECHECKERSTATEDEBUG 1
+#define PKIX_USERDEFINEDMODULESDEBUG 1
+#define PKIX_CONTEXTDEBUG 1
+#define PKIX_DEFAULTREVOCATIONCHECKERDEBUG 1
+#define PKIX_LDAPREQUESTDEBUG 1
+#define PKIX_LDAPRESPONSEDEBUG 1
+#define PKIX_LDAPCLIENTDEBUG 1
+#define PKIX_LDAPDEFAULTCLIENTDEBUG 1
+#define PKIX_SOCKETDEBUG 1
+#define PKIX_RESOURCELIMITSDEBUG 1
+#define PKIX_LOGGERDEBUG 1
+#define PKIX_MONITORLOCKDEBUG 1
+#define PKIX_INFOACCESSDEBUG 1
+#define PKIX_AIAMGRDEBUG 1
+#define PKIX_OCSPCHECKERDEBUG 1
+#define PKIX_OCSPREQUESTDEBUG 1
+#define PKIX_OCSPRESPONSEDEBUG 1
+#define PKIX_HTTPDEFAULTCLIENTDEBUG 1
+#define PKIX_HTTPCERTSTORECONTEXTDEBUG 1
+#define PKIX_VERIFYNODEDEBUG 1
+#endif
+
+/*
+ * XXX Both PKIX_DEBUG and PKIX_DEBUG_ARG currently use printf.
+ * This needs to be replaced with Loggers.
+ */
+
+#ifdef DEBUG
+#define PKIX_DEBUG(expr) \
+ do { \
+ _PKIX_DEBUG_TRACE(pkixLoggersErrors, expr, PKIX_LOGGER_LEVEL_DEBUG); \
+ (void) fprintf(stderr, "(%s: ", myFuncName); \
+ (void) fprintf(stderr, expr); \
+ } while (0)
+#else
+#define PKIX_DEBUG(expr)
+#endif
+
+/* Logging doesn't support DEBUG with ARG: cannot convert control and arg */
+#define PKIX_DEBUG_ARG(expr, arg) \
+ do { \
+ (void) printf("(%s: ", myFuncName); \
+ (void) printf(expr, arg); \
+ } while (0)
+
+#if PKIX_FATALDEBUG
+#define PKIX_FATAL_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_FATAL_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_FATAL_DEBUG(expr)
+#define PKIX_FATAL_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_REFCOUNTDEBUG
+#define PKIX_REF_COUNT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_REF_COUNT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_REF_COUNT_DEBUG(expr)
+#define PKIX_REF_COUNT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_MEMDEBUG
+#define PKIX_MEM_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_MEM_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_MEM_DEBUG(expr)
+#define PKIX_MEM_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_MUTEXDEBUG
+#define PKIX_MUTEX_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_MUTEX_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_MUTEX_DEBUG(expr)
+#define PKIX_MUTEX_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OBJECTDEBUG
+#define PKIX_OBJECT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OBJECT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OBJECT_DEBUG(expr)
+#define PKIX_OBJECT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_ERRORDEBUG
+#define PKIX_ERROR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_ERROR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_ERROR_DEBUG(expr)
+#define PKIX_ERROR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_STRINGDEBUG
+#define PKIX_STRING_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_STRING_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_STRING_DEBUG(expr)
+#define PKIX_STRING_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OIDDEBUG
+#define PKIX_OID_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OID_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OID_DEBUG(expr)
+#define PKIX_OID_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LISTDEBUG
+#define PKIX_LIST_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LIST_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LIST_DEBUG(expr)
+#define PKIX_LIST_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_RWLOCKDEBUG
+#define PKIX_RWLOCK_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_RWLOCK_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_RWLOCK_DEBUG(expr)
+#define PKIX_RWLOCK_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BYTEARRAYDEBUG
+#define PKIX_BYTEARRAY_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BYTEARRAY_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BYTEARRAY_DEBUG(expr)
+#define PKIX_BYTEARRAY_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_HASHTABLEDEBUG
+#define PKIX_HASHTABLE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_HASHTABLE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_HASHTABLE_DEBUG(expr)
+#define PKIX_HASHTABLE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_X500NAMEDEBUG
+#define PKIX_X500NAME_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_X500NAME_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_X500NAME_DEBUG(expr)
+#define PKIX_X500NAME_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_GENERALNAMEDEBUG
+#define PKIX_GENERALNAME_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_GENERALNAME_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_GENERALNAME_DEBUG(expr)
+#define PKIX_GENERALNAME_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_PUBLICKEYDEBUG
+#define PKIX_PUBLICKEY_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_PUBLICKEY_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_PUBLICKEY_DEBUG(expr)
+#define PKIX_PUBLICKEY_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTDEBUG
+#define PKIX_CERT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERT_DEBUG(expr)
+#define PKIX_CERT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLDPDEBUG
+#define PKIX_CRLDP_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRLDP_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRLDP_DEBUG(expr)
+#define PKIX_CRLDP_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_HTTPCLIENTDEBUG
+#define PKIX_HTTPCLIENT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_HTTPCLIENT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_HTTPCLIENT_DEBUG(expr)
+#define PKIX_HTTPCLIENT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BIGINTDEBUG
+#define PKIX_BIGINT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BIGINT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BIGINT_DEBUG(expr)
+#define PKIX_BIGINT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_DATEDEBUG
+#define PKIX_DATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_DATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_DATE_DEBUG(expr)
+#define PKIX_DATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_TRUSTANCHORDEBUG
+#define PKIX_TRUSTANCHOR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_TRUSTANCHOR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_TRUSTANCHOR_DEBUG(expr)
+#define PKIX_TRUSTANCHOR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_PROCESSINGPARAMSDEBUG
+#define PKIX_PROCESSINGPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_PROCESSINGPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_PROCESSINGPARAMS_DEBUG(expr)
+#define PKIX_PROCESSINGPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_VALIDATEPARAMSDEBUG
+#define PKIX_VALIDATEPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_VALIDATEPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_VALIDATEPARAMS_DEBUG(expr)
+#define PKIX_VALIDATEPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_VALIDATERESULTDEBUG
+#define PKIX_VALIDATERESULT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_VALIDATERESULT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_VALIDATERESULT_DEBUG(expr)
+#define PKIX_VALIDATERESULT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_VALIDATEDEBUG
+#define PKIX_VALIDATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_VALIDATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_VALIDATE_DEBUG(expr)
+#define PKIX_VALIDATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BUILDDEBUG
+#define PKIX_BUILD_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BUILD_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BUILD_DEBUG(expr)
+#define PKIX_BUILD_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTCHAINCHECKERDEBUG
+#define PKIX_CERTCHAINCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTCHAINCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTCHAINCHECKER_DEBUG(expr)
+#define PKIX_CERTCHAINCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_REVOCATIONCHECKERDEBUG
+#define PKIX_REVOCATIONCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_REVOCATIONCHECKER_DEBUG(expr)
+#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_REVOCATIONMETHODDEBUG
+#define PKIX_REVOCATIONMETHOD_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_REVOCATIONMETHOD_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_REVOCATIONMETHOD_DEBUG(expr)
+#define PKIX_REVOCATIONMETHOD_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTSELECTORDEBUG
+#define PKIX_CERTSELECTOR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTSELECTOR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTSELECTOR_DEBUG(expr)
+#define PKIX_CERTSELECTOR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_COMCERTSELPARAMSDEBUG
+#define PKIX_COMCERTSELPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_COMCERTSELPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_COMCERTSELPARAMS_DEBUG(expr)
+#define PKIX_COMCERTSELPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_TARGETCERTCHECKERSTATEDEBUG
+#define PKIX_TARGETCERTCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_TARGETCERTCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_TARGETCERTCHECKERSTATE_DEBUG(expr)
+#define PKIX_TARGETCERTCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr)
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_INITIALIZEPARAMSDEBUG
+#define PKIX_INITIALIZEPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_INITIALIZEPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_INITIALIZEPARAMS_DEBUG(expr)
+#define PKIX_INITIALIZEPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTBASICCONSTRAINTSDEBUG
+#define PKIX_CERTBASICCONSTRAINTS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTBASICCONSTRAINTS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTBASICCONSTRAINTS_DEBUG(expr)
+#define PKIX_CERTBASICCONSTRAINTS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTNAMECONSTRAINTSDEBUG
+#define PKIX_CERTNAMECONSTRAINTS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTNAMECONSTRAINTS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTNAMECONSTRAINTS_DEBUG(expr)
+#define PKIX_CERTNAMECONSTRAINTS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTNAMECONSTRAINTSCHECKERSTATEDEBUG
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG(expr)
+#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_SUBJALTNAMECHECKERSTATEDEBUG
+#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG(expr)
+#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYQUALIFIERDEBUG
+#define PKIX_CERTPOLICYQUALIFIER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYQUALIFIER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYQUALIFIER_DEBUG(expr)
+#define PKIX_CERTPOLICYQUALIFIER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYINFODEBUG
+#define PKIX_CERTPOLICYINFO_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYINFO_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYINFO_DEBUG(expr)
+#define PKIX_CERTPOLICYINFO_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYNODEDEBUG
+#define PKIX_CERTPOLICYNODE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYNODE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYNODE_DEBUG(expr)
+#define PKIX_CERTPOLICYNODE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
+#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG(expr)
+#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LIFECYCLEDEBUG
+#define PKIX_LIFECYCLE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LIFECYCLE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LIFECYCLE_DEBUG(expr)
+#define PKIX_LIFECYCLE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr)
+#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLDEBUG
+#define PKIX_CRL_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRL_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRL_DEBUG(expr)
+#define PKIX_CRL_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLENTRYDEBUG
+#define PKIX_CRLENTRY_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRLENTRY_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRLENTRY_DEBUG(expr)
+#define PKIX_CRLENTRY_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLSELECTORDEBUG
+#define PKIX_CRLSELECTOR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRLSELECTOR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRLSELECTOR_DEBUG(expr)
+#define PKIX_CRLSELECTOR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_COMCRLSELPARAMSDEBUG
+#define PKIX_COMCRLSELPARAMS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_COMCRLSELPARAMS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_COMCRLSELPARAMS_DEBUG(expr)
+#define PKIX_COMCRLSELPARAMS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTSTOREDEBUG
+#define PKIX_CERTSTORE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTSTORE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTSTORE_DEBUG(expr)
+#define PKIX_CERTSTORE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_COLLECTIONCERTSTORECONTEXTDEBUG
+#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG(expr)
+#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CRLCHECKERDEBUG
+#define PKIX_CRLCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CRLCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CRLCHECKER_DEBUG(expr)
+#define PKIX_CRLCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTPOLICYMAPDEBUG
+#define PKIX_CERTPOLICYMAP_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTPOLICYMAP_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTPOLICYMAP_DEBUG(expr)
+#define PKIX_CERTPOLICYMAP_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_BUILDRESULTDEBUG
+#define PKIX_BUILDRESULT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_BUILDRESULT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_BUILDRESULT_DEBUG(expr)
+#define PKIX_BUILDRESULT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_FORWARDBUILDERSTATEDEBUG
+#define PKIX_FORWARDBUILDERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_FORWARDBUILDERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_FORWARDBUILDERSTATE_DEBUG(expr)
+#define PKIX_FORWARDBUILDERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_SIGNATURECHECKERSTATEDEBUG
+#define PKIX_SIGNATURECHECKERSTATE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_SIGNATURECHECKERSTATE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_SIGNATURECHECKERSTATE_DEBUG(expr)
+#define PKIX_SIGNATURECHECKERSTATE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_USERDEFINEDMODULESDEBUG
+#define PKIX_USERDEFINEDMODULES_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_USERDEFINEDMODULES_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_USERDEFINEDMODULES_DEBUG(expr)
+#define PKIX_USERDEFINEDMODULES_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CONTEXTDEBUG
+#define PKIX_CONTEXT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CONTEXT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CONTEXT_DEBUG(expr)
+#define PKIX_CONTEXT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_REVOCATIONCHECKERDEBUG
+#define PKIX_REVOCATIONCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_REVOCATIONCHECKER_DEBUG(expr)
+#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LDAPREQUESTDEBUG
+#define PKIX_LDAPREQUEST_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LDAPREQUEST_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LDAPREQUEST_DEBUG(expr)
+#define PKIX_LDAPREQUEST_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LDAPRESPONSEDEBUG
+#define PKIX_LDAPRESPONSE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LDAPRESPONSE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LDAPRESPONSE_DEBUG(expr)
+#define PKIX_LDAPRESPONSE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LDAPCLIENTDEBUG
+#define PKIX_LDAPCLIENT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LDAPCLIENT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LDAPCLIENT_DEBUG(expr)
+#define PKIX_LDAPCLIENT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LDAPDEFAULTCLIENTDEBUG
+#define PKIX_LDAPDEFAULTCLIENT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LDAPDEFAULTCLIENT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LDAPDEFAULTCLIENT_DEBUG(expr)
+#define PKIX_LDAPDEFAULTCLIENT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_SOCKETDEBUG
+#define PKIX_SOCKET_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_SOCKET_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_SOCKET_DEBUG(expr)
+#define PKIX_SOCKET_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_RESOURCELIMITSDEBUG
+#define PKIX_RESOURCELIMITS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_RESOURCELIMITS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_RESOURCELIMITS_DEBUG(expr)
+#define PKIX_RESOURCELIMITS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_LOGGERDEBUG
+#define PKIX_LOGGER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_LOGGER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_LOGGER_DEBUG(expr)
+#define PKIX_LOGGER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_MONITORLOCKDEBUG
+#define PKIX_MONITORLOCK_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_MONITORLOCK_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_MONITORLOCK_DEBUG(expr)
+#define PKIX_MONITORLOCK_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_INFOACCESSDEBUG
+#define PKIX_INFOACCESS_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_INFOACCESS_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_INFOACCESS_DEBUG(expr)
+#define PKIX_INFOACCESS_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_AIAMGRDEBUG
+#define PKIX_AIAMGR_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_AIAMGR_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_AIAMGR_DEBUG(expr)
+#define PKIX_AIAMGR_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OCSPCHECKERDEBUG
+#define PKIX_OCSPCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OCSPCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OCSPCHECKER_DEBUG(expr)
+#define PKIX_OCSPCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OCSPCERTIDDEBUG
+#define PKIX_OCSPCERTID_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OCSPCERTID_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OCSPCERTID_DEBUG(expr)
+#define PKIX_OCSPCERTID_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OCSPREQUESTDEBUG
+#define PKIX_OCSPREQUEST_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OCSPREQUEST_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OCSPREQUEST_DEBUG(expr)
+#define PKIX_OCSPREQUEST_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_OCSPRESPONSEDEBUG
+#define PKIX_OCSPRESPONSE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_OCSPRESPONSE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_OCSPRESPONSE_DEBUG(expr)
+#define PKIX_OCSPRESPONSE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_HTTPDEFAULTCLIENTDEBUG
+#define PKIX_HTTPDEFAULTCLIENT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_HTTPDEFAULTCLIENT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_HTTPDEFAULTCLIENT_DEBUG(expr)
+#define PKIX_HTTPDEFAULTCLIENT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_HTTPCERTSTORECONTEXTDEBUG
+#define PKIX_HTTPCERTSTORECONTEXT_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_HTTPCERTSTORECONTEXT_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_HTTPCERTSTORECONTEXT_DEBUG(expr)
+#define PKIX_HTTPCERTSTORECONTEXT_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_VERIFYNODEDEBUG
+#define PKIX_VERIFYNODE_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_VERIFYNODE_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_VERIFYNODE_DEBUG(expr)
+#define PKIX_VERIFYNODE_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_EKUCHECKER
+#define PKIX_EKUCHECKER_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_EKUCHECKER_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_EKUCHECKER_DEBUG(expr)
+#define PKIX_EKUCHECKER_DEBUG_ARG(expr, arg)
+#endif
+
+#if PKIX_CERTVFYPKIXDEBUG
+#define PKIX_CERTVFYPKIX_DEBUG(expr) \
+ PKIX_DEBUG(expr)
+#define PKIX_CERTVFYPKIX_DEBUG_ARG(expr, arg) \
+ PKIX_DEBUG_ARG(expr, arg)
+#else
+#define PKIX_CERTVFYPKIX_DEBUG(expr)
+#define PKIX_CERTVFYPKIX_DEBUG_ARG(expr, arg)
+#endif
+
+/*
+ * All object types register themselves with the system using a
+ * pkix_ClassTable_Entry, which consists of a set of functions for that
+ * type and an ASCII string (char *) which is used by the default
+ * ToStringCallback (if necessary). System types register themselves directly
+ * when their respective PKIX_"type"_RegisterSelf functions are called.
+ * User-defined types can be registered using PKIX_PL_Object_RegisterType.
+ * (see comments in pkix_pl_system.h)
+ */
+
+typedef struct pkix_ClassTable_EntryStruct pkix_ClassTable_Entry;
+struct pkix_ClassTable_EntryStruct {
+ char *description;
+ PKIX_UInt32 objCounter;
+ PKIX_UInt32 typeObjectSize;
+ PKIX_PL_DestructorCallback destructor;
+ PKIX_PL_EqualsCallback equalsFunction;
+ PKIX_PL_HashcodeCallback hashcodeFunction;
+ PKIX_PL_ToStringCallback toStringFunction;
+ PKIX_PL_ComparatorCallback comparator;
+ PKIX_PL_DuplicateCallback duplicateFunction;
+};
+
+/*
+ * PKIX_ERRORCLASSNAMES is an array of strings, with each string holding a
+ * descriptive name for an error code. This is used by the default
+ * PKIX_PL_Error_ToString function.
+ */
+extern const char *PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES];
+
+#define MAX_STACK_DEPTH 1000
+
+extern PRLogModuleInfo *pkixLog;
+
+#define PKIX_MAGIC_HEADER PR_UINT64(0xFEEDC0FFEEFACADE)
+#define PKIX_MAGIC_HEADER_DESTROYED PR_UINT64(0xBAADF00DDEADBEEF)
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_IsCertSelfIssued(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pSelfIssued,
+ void *plContext);
+
+PKIX_Error *
+pkix_Throw(
+ PKIX_ERRORCLASS errClass,
+ const char *funcName,
+ PKIX_ERRORCODE errorTextCode,
+ PKIX_ERRORCLASS overrideClass,
+ PKIX_Error *cause,
+ PKIX_Error **pError,
+ void *plContext);
+
+PKIX_Error *
+pkix_CheckTypes(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_UInt32 type,
+ void *plContext);
+
+PKIX_Error *
+pkix_CheckType(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 type,
+ void *plContext);
+
+PKIX_Error *
+pkix_hash(
+ const unsigned char *bytes,
+ PKIX_UInt32 length,
+ PKIX_UInt32 *hash,
+ void *plContext);
+
+PKIX_Error *
+pkix_duplicateImmutable(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext);
+
+PKIX_UInt32
+pkix_countArray(void **array);
+
+PKIX_UInt32
+pkix_hex2i(char c);
+
+char
+pkix_i2hex(char c);
+
+PKIX_Boolean
+pkix_isPlaintext(unsigned char c, PKIX_Boolean debug);
+
+PKIX_Error *
+pkix_CacheCertChain_Lookup(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ PKIX_PL_Date *testDate,
+ PKIX_Boolean *pFound,
+ PKIX_BuildResult **pBuildResult,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCertChain_Remove(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCertChain_Add(
+ PKIX_PL_Cert* targetCert,
+ PKIX_List* anchors,
+ PKIX_PL_Date *validityDate,
+ PKIX_BuildResult *buildResult,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCert_Lookup(
+ PKIX_CertStore *store,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_PL_Date *testDate,
+ PKIX_Boolean *pFound,
+ PKIX_List** pCerts,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCert_Add(
+ PKIX_CertStore *store,
+ PKIX_ComCertSelParams *certSelParams,
+ PKIX_List* certs,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCrlEntry_Lookup(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *certIssuer,
+ PKIX_PL_BigInt *certSerialNumber,
+ PKIX_Boolean *pFound,
+ PKIX_List** pCrlEntryList,
+ void *plContext);
+
+PKIX_Error *
+pkix_CacheCrlEntry_Add(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *certIssuer,
+ PKIX_PL_BigInt *certSerialNumber,
+ PKIX_List* crlEntryList,
+ void *plContext);
+
+#ifdef PR_LOGGING
+void
+pkix_trace_dump_cert(
+ const char *info,
+ PKIX_PL_Cert *cert,
+ void *plContext);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_TOOLS_H */
diff --git a/security/nss/lib/libpkix/pkix/util/util.gyp b/security/nss/lib/libpkix/pkix/util/util.gyp
new file mode 100644
index 0000000000..078852f52b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix/util/util.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': 'pkixutil',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_error.c',
+ 'pkix_errpaths.c',
+ 'pkix_list.c',
+ 'pkix_logger.c',
+ 'pkix_tools.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/Makefile b/security/nss/lib/libpkix/pkix_pl_nss/Makefile
new file mode 100644
index 0000000000..2b5492506c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/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). #
+#######################################################################
+
+
+#######################################################################
+# (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/lib/libpkix/pkix_pl_nss/manifest.mn b/security/nss/lib/libpkix/pkix_pl_nss/manifest.mn
new file mode 100644
index 0000000000..f3c83511a9
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/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/.
+CORE_DEPTH = ../../..
+DEPTH = ../../..
+
+#
+DIRS = pki system module \
+ $(NULL)
+
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/Makefile b/security/nss/lib/libpkix/pkix_pl_nss/module/Makefile
new file mode 100644
index 0000000000..e97ad8e4de
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/Makefile
@@ -0,0 +1,66 @@
+#! 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). #
+#######################################################################
+
+ifdef NSS_PKIX_NO_LDAP
+LDAP_HEADERS =
+LDAP_CSRCS =
+else
+LDAP_HEADERS = \
+ pkix_pl_ldapt.h \
+ pkix_pl_ldapcertstore.h \
+ pkix_pl_ldapresponse.h \
+ pkix_pl_ldaprequest.h \
+ pkix_pl_ldapdefaultclient.h \
+ $(NULL)
+
+LDAP_CSRCS = \
+ pkix_pl_ldaptemplates.c \
+ pkix_pl_ldapcertstore.c \
+ pkix_pl_ldapresponse.c \
+ pkix_pl_ldaprequest.c \
+ pkix_pl_ldapdefaultclient.c \
+ $(NULL)
+endif
+
+#######################################################################
+# (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/lib/libpkix/pkix_pl_nss/module/exports.gyp b/security/nss/lib/libpkix/pkix_pl_nss/module/exports.gyp
new file mode 100644
index 0000000000..064a17ce44
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/exports.gyp
@@ -0,0 +1,36 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_libpkix_pkix_pl_nss_module_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_pl_aiamgr.h',
+ 'pkix_pl_colcertstore.h',
+ 'pkix_pl_httpcertstore.h',
+ 'pkix_pl_httpdefaultclient.h',
+ 'pkix_pl_ldapcertstore.h',
+ 'pkix_pl_ldapdefaultclient.h',
+ 'pkix_pl_ldaprequest.h',
+ 'pkix_pl_ldapresponse.h',
+ 'pkix_pl_ldapt.h',
+ 'pkix_pl_nsscontext.h',
+ 'pkix_pl_pk11certstore.h',
+ 'pkix_pl_socket.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/manifest.mn b/security/nss/lib/libpkix/pkix_pl_nss/module/manifest.mn
new file mode 100644
index 0000000000..31231e4edf
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/manifest.mn
@@ -0,0 +1,34 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+CORE_DEPTH = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_pl_aiamgr.h \
+ pkix_pl_colcertstore.h \
+ pkix_pl_httpcertstore.h \
+ pkix_pl_httpdefaultclient.h \
+ $(LDAP_HEADERS) \
+ pkix_pl_nsscontext.h \
+ pkix_pl_pk11certstore.h \
+ pkix_pl_socket.h \
+ $(NULL)
+
+MODULE = nss
+
+DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" -DSHLIB_VERSION=\"$(LIBRARY_VERSION)\"
+
+CSRCS = \
+ pkix_pl_aiamgr.c \
+ pkix_pl_colcertstore.c \
+ pkix_pl_httpcertstore.c \
+ pkix_pl_httpdefaultclient.c \
+ $(LDAP_CSRCS) \
+ pkix_pl_nsscontext.c \
+ pkix_pl_pk11certstore.c \
+ pkix_pl_socket.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixmodule
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/module.gyp b/security/nss/lib/libpkix/pkix_pl_nss/module/module.gyp
new file mode 100644
index 0000000000..8d7459ded6
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/module.gyp
@@ -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/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixmodule',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_pl_aiamgr.c',
+ 'pkix_pl_colcertstore.c',
+ 'pkix_pl_httpcertstore.c',
+ 'pkix_pl_httpdefaultclient.c',
+ 'pkix_pl_ldapcertstore.c',
+ 'pkix_pl_ldapdefaultclient.c',
+ 'pkix_pl_ldaprequest.c',
+ 'pkix_pl_ldapresponse.c',
+ 'pkix_pl_ldaptemplates.c',
+ 'pkix_pl_nsscontext.c',
+ 'pkix_pl_pk11certstore.c',
+ 'pkix_pl_socket.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'SHLIB_SUFFIX=\"<(dll_suffix)\"',
+ 'SHLIB_PREFIX=\"<(dll_prefix)\"',
+ 'SHLIB_VERSION=\"\"'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c
new file mode 100644
index 0000000000..d9f5662303
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.c
@@ -0,0 +1,699 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_aiamgr.c
+ *
+ * AIAMgr Object Definitions
+ *
+ */
+
+#include "pkix_pl_aiamgr.h"
+extern PKIX_PL_HashTable *aiaConnectionCache;
+
+#ifndef NSS_PKIX_NO_LDAP
+/* --Virtual-LdapClient-Functions------------------------------------ */
+
+PKIX_Error *
+PKIX_PL_LdapClient_InitiateRequest(
+ PKIX_PL_LdapClient *client,
+ LDAPRequestParams *requestParams,
+ void **pNBIO,
+ PKIX_List **pResponse,
+ void *plContext)
+{
+ PKIX_ENTER(LDAPCLIENT, "PKIX_PL_LdapClient_InitiateRequest");
+ PKIX_NULLCHECK_TWO(client, client->initiateFcn);
+
+ PKIX_CHECK(client->initiateFcn
+ (client, requestParams, pNBIO, pResponse, plContext),
+ PKIX_LDAPCLIENTINITIATEREQUESTFAILED);
+cleanup:
+
+ PKIX_RETURN(LDAPCLIENT);
+
+}
+
+PKIX_Error *
+PKIX_PL_LdapClient_ResumeRequest(
+ PKIX_PL_LdapClient *client,
+ void **pNBIO,
+ PKIX_List **pResponse,
+ void *plContext)
+{
+ PKIX_ENTER(LDAPCLIENT, "PKIX_PL_LdapClient_ResumeRequest");
+ PKIX_NULLCHECK_TWO(client, client->resumeFcn);
+
+ PKIX_CHECK(client->resumeFcn
+ (client, pNBIO, pResponse, plContext),
+ PKIX_LDAPCLIENTRESUMEREQUESTFAILED);
+cleanup:
+
+ PKIX_RETURN(LDAPCLIENT);
+
+}
+#endif /* !NSS_PKIX_NO_LDAP */
+
+/* --Private-AIAMgr-Functions----------------------------------*/
+
+/*
+ * FUNCTION: pkix_pl_AIAMgr_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_pki.h)
+ */
+static PKIX_Error *
+pkix_pl_AIAMgr_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_AIAMgr *aiaMgr = NULL;
+
+ PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_AIAMGR_TYPE, plContext),
+ PKIX_OBJECTNOTAIAMGR);
+
+ aiaMgr = (PKIX_PL_AIAMgr *)object;
+
+ /* pointer to cert cache */
+ /* pointer to crl cache */
+ aiaMgr->method = 0;
+ aiaMgr->aiaIndex = 0;
+ aiaMgr->numAias = 0;
+ PKIX_DECREF(aiaMgr->aia);
+ PKIX_DECREF(aiaMgr->location);
+ PKIX_DECREF(aiaMgr->results);
+#ifndef NSS_PKIX_NO_LDAP
+ PKIX_DECREF(aiaMgr->client.ldapClient);
+#endif
+
+cleanup:
+
+ PKIX_RETURN(AIAMGR);
+}
+
+/*
+ * FUNCTION: pkix_pl_AIAMgr_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_AIAMGR_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_AIAMgr_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry *entry = &systemClasses[PKIX_AIAMGR_TYPE];
+
+ PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_RegisterSelf");
+
+ entry->description = "AIAMgr";
+ entry->typeObjectSize = sizeof(PKIX_PL_AIAMgr);
+ entry->destructor = pkix_pl_AIAMgr_Destroy;
+
+ PKIX_RETURN(AIAMGR);
+}
+
+#ifndef NSS_PKIX_NO_LDAP
+/*
+ * FUNCTION: pkix_pl_AiaMgr_FindLDAPClient
+ * DESCRIPTION:
+ *
+ * This function checks the collection of LDAPClient connections held by the
+ * AIAMgr pointed to by "aiaMgr" for one matching the domain name given by
+ * "domainName". The string may include a port number: e.g., "betty.nist.gov"
+ * or "nss.red.iplanet.com:1389". If a match is found, that LDAPClient is
+ * stored at "pClient". Otherwise, an LDAPClient is created and added to the
+ * collection, and then stored at "pClient".
+ *
+ * PARAMETERS:
+ * "aiaMgr"
+ * The AIAMgr whose LDAPClient connected are to be managed. Must be
+ * non-NULL.
+ * "domainName"
+ * Address of a string pointing to a server name. Must be non-NULL.
+ * An empty string (which means no <host> is given in the LDAP URL) is
+ * not supported.
+ * "pClient"
+ * Address at which the returned LDAPClient is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an AIAMgr Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_AiaMgr_FindLDAPClient(
+ PKIX_PL_AIAMgr *aiaMgr,
+ char *domainName,
+ PKIX_PL_LdapClient **pClient,
+ void *plContext)
+{
+ PKIX_PL_String *domainString = NULL;
+ PKIX_PL_LdapDefaultClient *client = NULL;
+
+ PKIX_ENTER(AIAMGR, "pkix_pl_AiaMgr_FindLDAPClient");
+ PKIX_NULLCHECK_THREE(aiaMgr, domainName, pClient);
+
+ /*
+ * An LDAP URL may not have a <host> part, for example,
+ * ldap:///o=University%20of%20Michigan,c=US
+ * PKIX_PL_LdapDefaultClient doesn't know how to discover the default
+ * LDAP server, so we don't support this kind of LDAP URL.
+ */
+ if (*domainName == '\0') {
+ /* Simulate a PKIX_PL_LdapDefaultClient_CreateByName failure. */
+ PKIX_ERROR(PKIX_LDAPDEFAULTCLIENTCREATEBYNAMEFAILED);
+ }
+
+ /* create PKIX_PL_String from domain name */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, domainName, 0, &domainString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Is this domainName already in cache? */
+ PKIX_CHECK(PKIX_PL_HashTable_Lookup
+ (aiaConnectionCache,
+ (PKIX_PL_Object *)domainString,
+ (PKIX_PL_Object **)&client,
+ plContext),
+ PKIX_HASHTABLELOOKUPFAILED);
+
+ if (client == NULL) {
+
+ /* No, create a connection (and cache it) */
+ PKIX_CHECK(PKIX_PL_LdapDefaultClient_CreateByName
+ (domainName,
+ /* Do not use NBIO until we verify, that
+ * it is working. For now use 1 min timeout. */
+ PR_SecondsToInterval(
+ ((PKIX_PL_NssContext*)plContext)->timeoutSeconds),
+ NULL,
+ &client,
+ plContext),
+ PKIX_LDAPDEFAULTCLIENTCREATEBYNAMEFAILED);
+
+ PKIX_CHECK(PKIX_PL_HashTable_Add
+ (aiaConnectionCache,
+ (PKIX_PL_Object *)domainString,
+ (PKIX_PL_Object *)client,
+ plContext),
+ PKIX_HASHTABLEADDFAILED);
+
+ }
+
+ *pClient = (PKIX_PL_LdapClient *)client;
+
+cleanup:
+
+ PKIX_DECREF(domainString);
+
+ PKIX_RETURN(AIAMGR);
+}
+#endif /* !NSS_PKIX_NO_LDAP */
+
+PKIX_Error *
+pkix_pl_AIAMgr_GetHTTPCerts(
+ PKIX_PL_AIAMgr *aiaMgr,
+ PKIX_PL_InfoAccess *ia,
+ void **pNBIOContext,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ PKIX_PL_GeneralName *location = NULL;
+ PKIX_PL_String *locationString = NULL;
+ PKIX_UInt32 len = 0;
+ PRUint16 port = 0;
+ const SEC_HttpClientFcn *httpClient = NULL;
+ const SEC_HttpClientFcnV1 *hcv1 = NULL;
+ SECStatus rv = SECFailure;
+ SEC_HTTP_SERVER_SESSION serverSession = NULL;
+ SEC_HTTP_REQUEST_SESSION requestSession = NULL;
+ char *path = NULL;
+ char *hostname = NULL;
+ char *locationAscii = NULL;
+ void *nbio = NULL;
+ PRUint16 responseCode = 0;
+ const char *responseContentType = NULL;
+ const char *responseData = NULL;
+
+ PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_GetHTTPCerts");
+ PKIX_NULLCHECK_FOUR(aiaMgr, ia, pNBIOContext, pCerts);
+
+ nbio = *pNBIOContext;
+ *pNBIOContext = NULL;
+ *pCerts = NULL;
+
+ if (nbio == NULL) { /* a new request */
+
+ PKIX_CHECK(PKIX_PL_InfoAccess_GetLocation
+ (ia, &location, plContext),
+ PKIX_INFOACCESSGETLOCATIONFAILED);
+
+ /* find or create httpClient = default client */
+ httpClient = SEC_GetRegisteredHttpClient();
+ aiaMgr->client.hdata.httpClient = httpClient;
+ if (!httpClient)
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+
+ if (httpClient->version == 1) {
+
+ PKIX_UInt32 timeout =
+ ((PKIX_PL_NssContext*)plContext)->timeoutSeconds;
+
+ hcv1 = &(httpClient->fcnTable.ftable1);
+
+ /* create server session */
+ PKIX_TOSTRING(location, &locationString, plContext,
+ PKIX_GENERALNAMETOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (locationString,
+ PKIX_ESCASCII,
+ (void **)&locationAscii,
+ &len,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ rv = CERT_ParseURL(locationAscii, &hostname, &port,
+ &path);
+ if ((rv != SECSuccess) ||
+ (hostname == NULL) ||
+ (path == NULL)) {
+ PKIX_ERROR(PKIX_URLPARSINGFAILED);
+ }
+
+ rv = (*hcv1->createSessionFcn)(hostname, port,
+ &serverSession);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_HTTPCLIENTCREATESESSIONFAILED);
+ }
+
+ aiaMgr->client.hdata.serverSession = serverSession;
+
+ /* create request session */
+ rv = (*hcv1->createFcn)(serverSession, "http", path,
+ "GET", PR_SecondsToInterval(timeout),
+ &requestSession);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_HTTPSERVERERROR);
+ }
+
+ aiaMgr->client.hdata.requestSession = requestSession;
+ } else {
+ PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
+ }
+ }
+
+ httpClient = aiaMgr->client.hdata.httpClient;
+
+ if (httpClient->version == 1) {
+ PRUint32 responseDataLen =
+ ((PKIX_PL_NssContext*)plContext)->maxResponseLength;
+
+ hcv1 = &(httpClient->fcnTable.ftable1);
+ requestSession = aiaMgr->client.hdata.requestSession;
+
+ /* trySendAndReceive */
+ rv = (*hcv1->trySendAndReceiveFcn)(requestSession,
+ (PRPollDesc **)&nbio,
+ &responseCode,
+ (const char **)&responseContentType,
+ NULL, /* &responseHeaders */
+ (const char **)&responseData,
+ &responseDataLen);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_HTTPSERVERERROR);
+ }
+
+ if (nbio != 0) {
+ *pNBIOContext = nbio;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCertResponse
+ (responseCode,
+ responseContentType,
+ responseData,
+ responseDataLen,
+ pCerts,
+ plContext),
+ PKIX_HTTPCERTSTOREPROCESSCERTRESPONSEFAILED);
+
+ /* Session and request cleanup in case of success */
+ if (aiaMgr->client.hdata.requestSession != NULL) {
+ (*hcv1->freeFcn)(aiaMgr->client.hdata.requestSession);
+ aiaMgr->client.hdata.requestSession = NULL;
+ }
+ if (aiaMgr->client.hdata.serverSession != NULL) {
+ (*hcv1->freeSessionFcn)(aiaMgr->client.hdata.serverSession);
+ aiaMgr->client.hdata.serverSession = NULL;
+ }
+ aiaMgr->client.hdata.httpClient = 0; /* callback fn */
+
+ } else {
+ PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
+ }
+
+cleanup:
+ /* Session and request cleanup in case of error. Passing through without cleanup
+ * if interrupted by blocked IO. */
+ if (PKIX_ERROR_RECEIVED) {
+ if (aiaMgr->client.hdata.requestSession != NULL) {
+ (*hcv1->freeFcn)(aiaMgr->client.hdata.requestSession);
+ aiaMgr->client.hdata.requestSession = NULL;
+ }
+ if (aiaMgr->client.hdata.serverSession != NULL) {
+ (*hcv1->freeSessionFcn)(aiaMgr->client.hdata.serverSession);
+ aiaMgr->client.hdata.serverSession = NULL;
+ }
+ aiaMgr->client.hdata.httpClient = 0; /* callback fn */
+ }
+
+ PKIX_DECREF(location);
+ PKIX_DECREF(locationString);
+
+ if (locationAscii) {
+ PORT_Free(locationAscii);
+ }
+ if (hostname) {
+ PORT_Free(hostname);
+ }
+ if (path) {
+ PORT_Free(path);
+ }
+
+ PKIX_RETURN(AIAMGR);
+}
+
+#ifndef NSS_PKIX_NO_LDAP
+PKIX_Error *
+pkix_pl_AIAMgr_GetLDAPCerts(
+ PKIX_PL_AIAMgr *aiaMgr,
+ PKIX_PL_InfoAccess *ia,
+ void **pNBIOContext,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ PKIX_List *result = NULL;
+ PKIX_PL_GeneralName *location = NULL;
+ PKIX_PL_LdapClient *client = NULL;
+ LDAPRequestParams request;
+ PLArenaPool *arena = NULL;
+ char *domainName = NULL;
+ void *nbio = NULL;
+
+ PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_GetLDAPCerts");
+ PKIX_NULLCHECK_FOUR(aiaMgr, ia, pNBIOContext, pCerts);
+
+ nbio = *pNBIOContext;
+ *pNBIOContext = NULL;
+ *pCerts = NULL;
+
+ if (nbio == NULL) { /* a new request */
+
+ /* Initiate an LDAP request */
+
+ request.scope = WHOLE_SUBTREE;
+ request.derefAliases = NEVER_DEREF;
+ request.sizeLimit = 0;
+ request.timeLimit = 0;
+
+ PKIX_CHECK(PKIX_PL_InfoAccess_GetLocation
+ (ia, &location, plContext),
+ PKIX_INFOACCESSGETLOCATIONFAILED);
+
+ /*
+ * Get a short-lived arena. We'll be done with
+ * this space once the request is encoded.
+ */
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CHECK(pkix_pl_InfoAccess_ParseLocation
+ (location, arena, &request, &domainName, plContext),
+ PKIX_INFOACCESSPARSELOCATIONFAILED);
+
+ PKIX_DECREF(location);
+
+ /* Find or create a connection to LDAP server */
+ PKIX_CHECK(pkix_pl_AiaMgr_FindLDAPClient
+ (aiaMgr, domainName, &client, plContext),
+ PKIX_AIAMGRFINDLDAPCLIENTFAILED);
+
+ aiaMgr->client.ldapClient = client;
+
+ PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest
+ (aiaMgr->client.ldapClient,
+ &request,
+ &nbio,
+ &result,
+ plContext),
+ PKIX_LDAPCLIENTINITIATEREQUESTFAILED);
+
+ PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE));
+
+ } else {
+
+ PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest
+ (aiaMgr->client.ldapClient, &nbio, &result, plContext),
+ PKIX_LDAPCLIENTRESUMEREQUESTFAILED);
+
+ }
+
+ if (nbio != NULL) { /* WOULDBLOCK */
+ *pNBIOContext = nbio;
+ *pCerts = NULL;
+ goto cleanup;
+ }
+
+ PKIX_DECREF(aiaMgr->client.ldapClient);
+
+ if (result == NULL) {
+ *pCerts = NULL;
+ } else {
+ PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList
+ (result, pCerts, plContext),
+ PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED);
+ }
+
+ *pNBIOContext = nbio;
+
+cleanup:
+
+ if (arena && (PKIX_ERROR_RECEIVED)) {
+ PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE));
+ }
+
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(aiaMgr->client.ldapClient);
+ }
+
+ PKIX_DECREF(location);
+
+ PKIX_RETURN(AIAMGR);
+}
+#endif /* !NSS_PKIX_NO_LDAP */
+
+/*
+ * FUNCTION: PKIX_PL_AIAMgr_Create
+ * DESCRIPTION:
+ *
+ * This function creates an AIAMgr, storing the result at "pAIAMgr".
+ *
+ * PARAMETERS:
+ * "pAIAMGR"
+ * Address at which the returned AIAMgr is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an AIAMgr Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_AIAMgr_Create(
+ PKIX_PL_AIAMgr **pAIAMgr,
+ void *plContext)
+{
+ PKIX_PL_AIAMgr *aiaMgr = NULL;
+
+ PKIX_ENTER(AIAMGR, "PKIX_PL_AIAMgr_Create");
+ PKIX_NULLCHECK_ONE(pAIAMgr);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_AIAMGR_TYPE,
+ sizeof(PKIX_PL_AIAMgr),
+ (PKIX_PL_Object **)&aiaMgr,
+ plContext),
+ PKIX_COULDNOTCREATEAIAMGROBJECT);
+ /* pointer to cert cache */
+ /* pointer to crl cache */
+ aiaMgr->method = 0;
+ aiaMgr->aiaIndex = 0;
+ aiaMgr->numAias = 0;
+ aiaMgr->aia = NULL;
+ aiaMgr->location = NULL;
+ aiaMgr->results = NULL;
+ aiaMgr->client.hdata.httpClient = NULL;
+ aiaMgr->client.hdata.serverSession = NULL;
+ aiaMgr->client.hdata.requestSession = NULL;
+
+ *pAIAMgr = aiaMgr;
+
+cleanup:
+
+ PKIX_RETURN(AIAMGR);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_AIAMgr_GetAIACerts (see description in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_AIAMgr_GetAIACerts(
+ PKIX_PL_AIAMgr *aiaMgr,
+ PKIX_PL_Cert *prevCert,
+ void **pNBIOContext,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ PKIX_UInt32 numAias = 0;
+ PKIX_UInt32 aiaIndex = 0;
+ PKIX_UInt32 iaType = PKIX_INFOACCESS_LOCATION_UNKNOWN;
+ PKIX_List *certs = NULL;
+ PKIX_PL_InfoAccess *ia = NULL;
+ void *nbio = NULL;
+
+ PKIX_ENTER(AIAMGR, "PKIX_PL_AIAMgr_GetAIACerts");
+ PKIX_NULLCHECK_FOUR(aiaMgr, prevCert, pNBIOContext, pCerts);
+
+ nbio = *pNBIOContext;
+ *pCerts = NULL;
+ *pNBIOContext = NULL;
+
+ if (nbio == NULL) { /* a new request */
+
+ /* Does this Cert have an AIA extension? */
+ PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess
+ (prevCert, &aiaMgr->aia, plContext),
+ PKIX_CERTGETAUTHORITYINFOACCESSFAILED);
+
+ if (aiaMgr->aia != NULL) {
+ PKIX_CHECK(PKIX_List_GetLength
+ (aiaMgr->aia, &numAias, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ /* And if so, does it have any entries? */
+ if ((aiaMgr->aia == NULL) || (numAias == 0)) {
+ *pCerts = NULL;
+ goto cleanup;
+ }
+
+ aiaMgr->aiaIndex = 0;
+ aiaMgr->numAias = numAias;
+ aiaMgr->results = NULL;
+
+ }
+
+ for (aiaIndex = aiaMgr->aiaIndex;
+ aiaIndex < aiaMgr->numAias;
+ aiaIndex ++) {
+ PKIX_UInt32 method = 0;
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (aiaMgr->aia,
+ aiaIndex,
+ (PKIX_PL_Object **)&ia,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(PKIX_PL_InfoAccess_GetMethod
+ (ia, &method, plContext),
+ PKIX_INFOACCESSGETMETHODFAILED);
+
+ if (method != PKIX_INFOACCESS_CA_ISSUERS &&
+ method != PKIX_INFOACCESS_CA_REPOSITORY) {
+ PKIX_DECREF(ia);
+ continue;
+ }
+
+ PKIX_CHECK(PKIX_PL_InfoAccess_GetLocationType
+ (ia, &iaType, plContext),
+ PKIX_INFOACCESSGETLOCATIONTYPEFAILED);
+
+ if (iaType == PKIX_INFOACCESS_LOCATION_HTTP) {
+ PKIX_CHECK(pkix_pl_AIAMgr_GetHTTPCerts
+ (aiaMgr, ia, &nbio, &certs, plContext),
+ PKIX_AIAMGRGETHTTPCERTSFAILED);
+#ifndef NSS_PKIX_NO_LDAP
+ } else if (iaType == PKIX_INFOACCESS_LOCATION_LDAP) {
+ PKIX_CHECK(pkix_pl_AIAMgr_GetLDAPCerts
+ (aiaMgr, ia, &nbio, &certs, plContext),
+ PKIX_AIAMGRGETLDAPCERTSFAILED);
+#endif
+ } else {
+ /* We only support http and ldap requests. */
+ PKIX_DECREF(ia);
+ continue;
+ }
+
+ if (nbio != NULL) { /* WOULDBLOCK */
+ aiaMgr->aiaIndex = aiaIndex;
+ *pNBIOContext = nbio;
+ *pCerts = NULL;
+ goto cleanup;
+ }
+
+ /*
+ * We can't just use and modify the List we received.
+ * Because it's cached, it's set immutable.
+ */
+ if (aiaMgr->results == NULL) {
+ PKIX_CHECK(PKIX_List_Create
+ (&(aiaMgr->results), plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+ PKIX_CHECK(pkix_List_AppendList
+ (aiaMgr->results, certs, plContext),
+ PKIX_APPENDLISTFAILED);
+ PKIX_DECREF(certs);
+
+ PKIX_DECREF(ia);
+ }
+
+ PKIX_DECREF(aiaMgr->aia);
+
+ *pNBIOContext = NULL;
+ *pCerts = aiaMgr->results;
+ aiaMgr->results = NULL;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(aiaMgr->aia);
+ PKIX_DECREF(aiaMgr->results);
+#ifndef NSS_PKIX_NO_LDAP
+ PKIX_DECREF(aiaMgr->client.ldapClient);
+#endif
+ }
+
+ PKIX_DECREF(certs);
+ PKIX_DECREF(ia);
+
+ PKIX_RETURN(AIAMGR);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.h
new file mode 100644
index 0000000000..356c1ecdf2
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_aiamgr.h
@@ -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/. */
+/*
+ * pkix_pl_aiamgr.h
+ *
+ * AIAMgr Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_AIAMGR_H
+#define _PKIX_PL_AIAMGR_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_AIAMgrStruct {
+ /* pointer to cert cache */
+ /* pointer to crl cache */
+ PKIX_UInt32 method;
+ PKIX_UInt32 aiaIndex;
+ PKIX_UInt32 numAias;
+ PKIX_List *aia;
+ PKIX_PL_GeneralName *location;
+ PKIX_List *results;
+ union {
+#ifndef NSS_PKIX_NO_LDAP
+ PKIX_PL_LdapClient *ldapClient;
+#endif
+ struct {
+ const SEC_HttpClientFcn *httpClient;
+ SEC_HTTP_SERVER_SESSION serverSession;
+ SEC_HTTP_REQUEST_SESSION requestSession;
+ char *path;
+ } hdata;
+ } client;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_AIAMgr_RegisterSelf(void *plContext);
+
+#ifndef NSS_PKIX_NO_LDAP
+PKIX_Error *PKIX_PL_LdapClient_InitiateRequest(
+ PKIX_PL_LdapClient *client,
+ LDAPRequestParams *requestParams,
+ void **pPollDesc,
+ PKIX_List **pResponse,
+ void *plContext);
+
+PKIX_Error *PKIX_PL_LdapClient_ResumeRequest(
+ PKIX_PL_LdapClient *client,
+ void **pPollDesc,
+ PKIX_List **pResponse,
+ void *plContext);
+#endif /* !NSS_PKIX_NO_LDAP */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_AIAMGR_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.c
new file mode 100644
index 0000000000..4cc5607cf6
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.c
@@ -0,0 +1,1292 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_colcertstore.c
+ *
+ * CollectionCertStore Function Definitions
+ *
+ */
+
+#include "pkix_pl_colcertstore.h"
+
+/*
+ * This Object is going to be taken out from libpkix SOON. The following
+ * function is copied from nss/cmd library, but not supported by NSS as
+ * public API. We use it since ColCertStore are read in Cert/Crl from
+ * files and need this support.
+ */
+
+static SECStatus
+SECU_FileToItem(SECItem *dst, PRFileDesc *src)
+{
+ PRFileInfo info;
+ PRInt32 numBytes;
+ PRStatus prStatus;
+
+ 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);
+ return SECFailure;
+}
+
+static SECStatus
+SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii)
+{
+ 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';
+
+ 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) {
+ return SECFailure;
+ }
+
+ PORT_Free(filedata.data);
+ } else {
+ /* Read in binary der */
+ rv = SECU_FileToItem(der, inFile);
+ if (rv) {
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+}
+
+/*
+ * FUNCTION: PKIX_PL_CollectionCertStoreContext_Create
+ * DESCRIPTION:
+ *
+ * Creates a new CollectionCertStoreContext using the String pointed to
+ * by "storeDir" and stores it at "pColCertStoreContext".
+ *
+ * PARAMETERS:
+ * "storeDir"
+ * The absolute path where *.crl and *.crt files are located.
+ * "pColCertStoreContext"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CollectionCertStoreContext Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CollectionCertStoreContext_Create(
+ PKIX_PL_String *storeDir,
+ PKIX_PL_CollectionCertStoreContext **pColCertStoreContext,
+ void *plContext)
+{
+ PKIX_PL_CollectionCertStoreContext *colCertStoreContext = NULL;
+
+ PKIX_ENTER(COLLECTIONCERTSTORECONTEXT,
+ "pkix_pl_CollectionCertStoreContext_Create");
+ PKIX_NULLCHECK_TWO(storeDir, pColCertStoreContext);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_COLLECTIONCERTSTORECONTEXT_TYPE,
+ sizeof (PKIX_PL_CollectionCertStoreContext),
+ (PKIX_PL_Object **)&colCertStoreContext,
+ plContext),
+ PKIX_COULDNOTCREATECOLLECTIONCERTSTORECONTEXTOBJECT);
+
+ PKIX_INCREF(storeDir);
+ colCertStoreContext->storeDir = storeDir;
+
+ colCertStoreContext->crlList = NULL;
+ colCertStoreContext->certList = NULL;
+
+ *pColCertStoreContext = colCertStoreContext;
+ colCertStoreContext = NULL;
+
+cleanup:
+
+ PKIX_DECREF(colCertStoreContext);
+
+ PKIX_RETURN(COLLECTIONCERTSTORECONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_CollectionCertStoreContext_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CollectionCertStoreContext_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CollectionCertStoreContext *colCertStoreContext = NULL;
+
+ PKIX_ENTER(COLLECTIONCERTSTORECONTEXT,
+ "pkix_pl_CollectionCertStoreContext_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_COLLECTIONCERTSTORECONTEXT_TYPE, plContext),
+ PKIX_OBJECTNOTCOLLECTIONCERTSTORECONTEXT);
+
+ colCertStoreContext = (PKIX_PL_CollectionCertStoreContext *)object;
+
+ PKIX_DECREF(colCertStoreContext->storeDir);
+ PKIX_DECREF(colCertStoreContext->crlList);
+ PKIX_DECREF(colCertStoreContext->certList);
+
+cleanup:
+ PKIX_RETURN(COLLECTIONCERTSTORECONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_CollectionCertStoreContext_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CollectionCertStoreContext_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_CollectionCertStoreContext *collectionCSContext = NULL;
+ PKIX_UInt32 tempHash = 0;
+
+ PKIX_ENTER(COLLECTIONCERTSTORECONTEXT,
+ "pkix_pl_CollectionCertStoreContext_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object,
+ PKIX_COLLECTIONCERTSTORECONTEXT_TYPE,
+ plContext),
+ PKIX_OBJECTNOTCOLLECTIONCERTSTORECONTEXT);
+
+ collectionCSContext = (PKIX_PL_CollectionCertStoreContext *)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *) collectionCSContext->storeDir,
+ &tempHash,
+ plContext),
+ PKIX_STRINGHASHCODEFAILED);
+
+ *pHashcode = tempHash << 7;
+
+ /* should not hash on crlList and certList, values are dynamic */
+
+cleanup:
+ PKIX_RETURN(COLLECTIONCERTSTORECONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_CollectionCertStoreContext_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CollectionCertStoreContext_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_PL_CollectionCertStoreContext *firstCCSContext = NULL;
+ PKIX_PL_CollectionCertStoreContext *secondCCSContext = NULL;
+ PKIX_Boolean cmpResult = 0;
+
+ PKIX_ENTER(COLLECTIONCERTSTORECONTEXT,
+ "pkix_pl_CollectionCertStoreContext_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ PKIX_CHECK(pkix_CheckTypes
+ (firstObject,
+ secondObject,
+ PKIX_COLLECTIONCERTSTORECONTEXT_TYPE,
+ plContext),
+ PKIX_OBJECTNOTCOLLECTIONCERTSTORECONTEXT);
+
+ firstCCSContext = (PKIX_PL_CollectionCertStoreContext *)firstObject;
+ secondCCSContext = (PKIX_PL_CollectionCertStoreContext *)secondObject;
+
+ if (firstCCSContext->storeDir == secondCCSContext->storeDir) {
+
+ cmpResult = PKIX_TRUE;
+
+ } else {
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *) firstCCSContext->storeDir,
+ (PKIX_PL_Object *) secondCCSContext->storeDir,
+ &cmpResult,
+ plContext),
+ PKIX_STRINGEQUALSFAILED);
+ }
+
+ *pResult = cmpResult;
+
+ /* should not check equal on crlList and certList, data are dynamic */
+
+cleanup:
+ PKIX_RETURN(COLLECTIONCERTSTORECONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_CollectionCertStore_CheckTrust
+ * DESCRIPTION:
+ * This function checks the trust status of this "cert" that was retrieved
+ * from the CertStore "store" and returns its trust status at "pTrusted".
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of the CertStore. Must be non-NULL.
+ * "cert"
+ * Address of the Cert. Must be non-NULL.
+ * "pTrusted"
+ * Address of PKIX_Boolean where the "cert" trust status is returned.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CollectionCertStore_CheckTrust(
+ PKIX_CertStore *store,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pTrusted,
+ void *plContext)
+{
+ PKIX_ENTER(CERTSTORE, "pkix_pl_CollectionCertStore_CheckTrust");
+ PKIX_NULLCHECK_THREE(store, cert, pTrusted);
+
+ *pTrusted = PKIX_TRUE;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_CollectionCertStoreContext_CreateCert
+ * DESCRIPTION:
+ *
+ * Creates Cert using data file path name pointed to by "certFileName" and
+ * stores it at "pCert". If the Cert can not be decoded, NULL is stored
+ * at "pCert".
+ *
+ * PARAMETERS
+ * "certFileName" - Address of Cert data file path name. Must be non-NULL.
+ * "pCert" - Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CollectionCertStoreContext Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CollectionCertStoreContext_CreateCert(
+ const char *certFileName,
+ PKIX_PL_Cert **pCert,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PRFileDesc *inFile = NULL;
+ SECItem certDER;
+ void *buf = NULL;
+ PKIX_UInt32 len;
+ SECStatus rv;
+
+ PKIX_ENTER(COLLECTIONCERTSTORECONTEXT,
+ "pkix_pl_CollectionCertStoreContext_CreateCert");
+ PKIX_NULLCHECK_TWO(certFileName, pCert);
+
+ *pCert = NULL;
+ certDER.data = NULL;
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_Open.\n");
+ inFile = PR_Open(certFileName, PR_RDONLY, 0);
+
+ if (!inFile){
+ PKIX_ERROR(PKIX_UNABLETOOPENCERTFILE);
+ } else {
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling SECU_ReadDerFromFile.\n");
+ rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE);
+ if (!rv){
+ buf = (void *)certDER.data;
+ len = certDER.len;
+
+ PKIX_CHECK(PKIX_PL_ByteArray_Create
+ (buf, len, &byteArray, plContext),
+ PKIX_BYTEARRAYCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_Create
+ (byteArray, &cert, plContext),
+ PKIX_CERTCREATEFAILED);
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling SECITEM_FreeItem.\n");
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+
+ } else {
+ PKIX_ERROR(PKIX_UNABLETOREADDERFROMCERTFILE);
+ }
+ }
+
+ *pCert = cert;
+
+cleanup:
+ if (inFile){
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PR_CloseDir.\n");
+ PR_Close(inFile);
+ }
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+
+ PKIX_DECREF(cert);
+ }
+ PKIX_DECREF(byteArray);
+ PKIX_RETURN(COLLECTIONCERTSTORECONTEXT);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_CollectionCertStoreContext_CreateCRL
+ * DESCRIPTION:
+ *
+ * Creates CRL using data file path name pointed to by "crlFileName" and
+ * stores it at "pCrl". If the CRL can not be decoded, NULL is stored
+ * at "pCrl".
+ *
+ * PARAMETERS
+ * "crlFileName" - Address of CRL data file path name. Must be non-NULL.
+ * "pCrl" - Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CollectionCertStoreContext Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CollectionCertStoreContext_CreateCRL(
+ const char *crlFileName,
+ PKIX_PL_CRL **pCrl,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ PKIX_PL_CRL *crl = NULL;
+ PRFileDesc *inFile = NULL;
+ SECItem crlDER;
+ void *buf = NULL;
+ PKIX_UInt32 len;
+ SECStatus rv;
+
+ PKIX_ENTER(COLLECTIONCERTSTORECONTEXT,
+ "pkix_pl_CollectionCertStoreContext_CreateCRL");
+ PKIX_NULLCHECK_TWO(crlFileName, pCrl);
+
+ *pCrl = NULL;
+ crlDER.data = NULL;
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_Open.\n");
+ inFile = PR_Open(crlFileName, PR_RDONLY, 0);
+
+ if (!inFile){
+ PKIX_ERROR(PKIX_UNABLETOOPENCRLFILE);
+ } else {
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling SECU_ReadDerFromFile.\n");
+ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE);
+ if (!rv){
+ buf = (void *)crlDER.data;
+ len = crlDER.len;
+
+ PKIX_CHECK(PKIX_PL_ByteArray_Create
+ (buf, len, &byteArray, plContext),
+ PKIX_BYTEARRAYCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_CRL_Create
+ (byteArray, &crl, plContext),
+ PKIX_CRLCREATEFAILED);
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling SECITEM_FreeItem.\n");
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+
+ } else {
+ PKIX_ERROR(PKIX_UNABLETOREADDERFROMCRLFILE);
+ }
+ }
+
+ *pCrl = crl;
+
+cleanup:
+ if (inFile){
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PR_CloseDir.\n");
+ PR_Close(inFile);
+ }
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+
+ PKIX_DECREF(crl);
+ if (crlDER.data != NULL) {
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+ }
+ }
+
+ PKIX_DECREF(byteArray);
+
+ PKIX_RETURN(COLLECTIONCERTSTORECONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_CollectionCertStoreContext_PopulateCert
+ * DESCRIPTION:
+ *
+ * Create list of Certs from *.crt files at directory specified in dirName,
+ * Not recursive to sub-directory. Also assume the directory contents are
+ * not changed dynamically.
+ *
+ * PARAMETERS
+ * "colCertStoreContext" - Address of CollectionCertStoreContext
+ * where the dirName is specified and where the return
+ * Certs are stored as a list. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - A lock at top level is required.
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CollectionCertStoreContext Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CollectionCertStoreContext_PopulateCert(
+ PKIX_PL_CollectionCertStoreContext *colCertStoreContext,
+ void *plContext)
+{
+ PKIX_List *certList = NULL;
+ PKIX_PL_Cert *certItem = NULL;
+ char *dirName = NULL;
+ char *pathName = NULL;
+ PKIX_UInt32 dirNameLen = 0;
+ PRErrorCode prError = 0;
+ PRDir *dir = NULL;
+ PRDirEntry *dirEntry = NULL;
+
+ PKIX_ENTER(COLLECTIONCERTSTORECONTEXT,
+ "pkix_pl_CollectionCertStoreContext_PopulateCert");
+ PKIX_NULLCHECK_ONE(colCertStoreContext);
+
+ /* convert directory to ascii */
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (colCertStoreContext->storeDir,
+ PKIX_ESCASCII,
+ (void **)&dirName,
+ &dirNameLen,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ /* create cert list, if no cert file, should return an empty list */
+
+ PKIX_CHECK(PKIX_List_Create(&certList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ /* open directory and read in .crt files */
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_OpenDir.\n");
+ dir = PR_OpenDir(dirName);
+
+ if (!dir) {
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG
+ ("\t\t Directory Name:%s\n", dirName);
+ PKIX_ERROR(PKIX_CANNOTOPENCOLLECTIONCERTSTORECONTEXTDIRECTORY);
+ }
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_ReadDir.\n");
+ dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH);
+
+ if (!dirEntry) {
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Empty directory.\n");
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PR_GetError.\n");
+ prError = PR_GetError();
+ }
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_SetError.\n");
+ PR_SetError(0, 0);
+
+ while (dirEntry != NULL && prError == 0) {
+ if (PL_strrstr(dirEntry->name, ".crt") ==
+ dirEntry->name + PL_strlen(dirEntry->name) - 4) {
+
+ PKIX_CHECK_ONLY_FATAL
+ (PKIX_PL_Malloc
+ (dirNameLen + PL_strlen(dirEntry->name) + 2,
+ (void **)&pathName,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ if ((!PKIX_ERROR_RECEIVED) && (pathName != NULL)){
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PL_strcpy for dirName.\n");
+ PL_strcpy(pathName, dirName);
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PL_strcat for dirName.\n");
+ PL_strcat(pathName, "/");
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PL_strcat for /.\n");
+ PL_strcat(pathName, dirEntry->name);
+
+ PKIX_CHECK_ONLY_FATAL
+ (pkix_pl_CollectionCertStoreContext_CreateCert
+ (pathName, &certItem, plContext),
+ PKIX_COLLECTIONCERTSTORECONTEXTCREATECERTFAILED);
+
+ if (!PKIX_ERROR_RECEIVED){
+ PKIX_CHECK_ONLY_FATAL
+ (PKIX_List_AppendItem
+ (certList,
+ (PKIX_PL_Object *)certItem,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+ }
+
+ PKIX_DECREF(certItem);
+ PKIX_FREE(pathName);
+ }
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PR_SetError.\n");
+ PR_SetError(0, 0);
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PR_ReadDir.\n");
+ dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH);
+
+ if (!dirEntry) {
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PR_GetError.\n");
+ prError = PR_GetError();
+ }
+ }
+
+ if ((prError != 0) && (prError != PR_NO_MORE_FILES_ERROR)) {
+ PKIX_ERROR(PKIX_COLLECTIONCERTSTOREPOPULATECERTFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(certList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ PKIX_INCREF(certList);
+ colCertStoreContext->certList = certList;
+
+cleanup:
+ if (dir) {
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PR_CloseDir.\n");
+ PR_CloseDir(dir);
+ }
+
+ PKIX_FREE(pathName);
+ PKIX_FREE(dirName);
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(certList);
+ }
+
+ PKIX_DECREF(certItem);
+ PKIX_DECREF(certList);
+
+ PKIX_RETURN(COLLECTIONCERTSTORECONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_CollectionCertStoreContext_PopulateCRL
+ * DESCRIPTION:
+ *
+ * Create list of CRLs from *.crl files at directory specified in dirName,
+ * Not recursive to sub-dirctory. Also assume the directory contents are
+ * not changed dynamically.
+ *
+ * PARAMETERS
+ * "colCertStoreContext" - Address of CollectionCertStoreContext
+ * where the dirName is specified and where the return
+ * CRLs are stored as a list. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - A lock at top level is required.
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CollectionCertStoreContext Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CollectionCertStoreContext_PopulateCRL(
+ PKIX_PL_CollectionCertStoreContext *colCertStoreContext,
+ void *plContext)
+{
+ PKIX_List *crlList = NULL;
+ PKIX_PL_CRL *crlItem = NULL;
+ char *dirName = NULL;
+ char *pathName = NULL;
+ PKIX_UInt32 dirNameLen = 0;
+ PRErrorCode prError = 0;
+ PRDir *dir = NULL;
+ PRDirEntry *dirEntry = NULL;
+
+ PKIX_ENTER(COLLECTIONCERTSTORECONTEXT,
+ "pkix_pl_CollectionCertStoreContext_PopulateCRL");
+ PKIX_NULLCHECK_ONE(colCertStoreContext);
+
+ /* convert directory to ascii */
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (colCertStoreContext->storeDir,
+ PKIX_ESCASCII,
+ (void **)&dirName,
+ &dirNameLen,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ /* create CRL list, if no CRL file, should return an empty list */
+
+ PKIX_CHECK(PKIX_List_Create(&crlList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ /* open directory and read in .crl files */
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_OpenDir.\n");
+ dir = PR_OpenDir(dirName);
+
+ if (!dir) {
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG
+ ("\t\t Directory Name:%s\n", dirName);
+ PKIX_ERROR(PKIX_CANNOTOPENCOLLECTIONCERTSTORECONTEXTDIRECTORY);
+ }
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_ReadDir.\n");
+ dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH);
+
+ if (!dirEntry) {
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Empty directory.\n");
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PR_GetError.\n");
+ prError = PR_GetError();
+ }
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_SetError.\n");
+ PR_SetError(0, 0);
+
+ while (dirEntry != NULL && prError == 0) {
+ if (PL_strrstr(dirEntry->name, ".crl") ==
+ dirEntry->name + PL_strlen(dirEntry->name) - 4) {
+
+ PKIX_CHECK_ONLY_FATAL
+ (PKIX_PL_Malloc
+ (dirNameLen + PL_strlen(dirEntry->name) + 2,
+ (void **)&pathName,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ if ((!PKIX_ERROR_RECEIVED) && (pathName != NULL)){
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PL_strcpy for dirName.\n");
+ PL_strcpy(pathName, dirName);
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PL_strcat for dirName.\n");
+ PL_strcat(pathName, "/");
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PL_strcat for /.\n");
+ PL_strcat(pathName, dirEntry->name);
+
+ PKIX_CHECK_ONLY_FATAL
+ (pkix_pl_CollectionCertStoreContext_CreateCRL
+ (pathName, &crlItem, plContext),
+ PKIX_COLLECTIONCERTSTORECONTEXTCREATECRLFAILED);
+
+ if (!PKIX_ERROR_RECEIVED){
+ PKIX_CHECK_ONLY_FATAL
+ (PKIX_List_AppendItem
+ (crlList,
+ (PKIX_PL_Object *)crlItem,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+ }
+
+ PKIX_DECREF(crlItem);
+ PKIX_FREE(pathName);
+ }
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PR_SetError.\n");
+ PR_SetError(0, 0);
+
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PR_ReadDir.\n");
+ dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH);
+
+ if (!dirEntry) {
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PR_GetError.\n");
+ prError = PR_GetError();
+ }
+ }
+
+ if ((prError != 0) && (prError != PR_NO_MORE_FILES_ERROR)) {
+ PKIX_ERROR(PKIX_COLLECTIONCERTSTORECONTEXTGETSELECTCRLFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(crlList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ PKIX_INCREF(crlList);
+ colCertStoreContext->crlList = crlList;
+
+cleanup:
+ if (dir) {
+ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
+ ("\t\t Calling PR_CloseDir.\n");
+ PR_CloseDir(dir);
+ }
+
+ PKIX_FREE(pathName);
+ PKIX_FREE(dirName);
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(crlList);
+ }
+
+ PKIX_DECREF(crlItem);
+ PKIX_DECREF(crlList);
+
+ PKIX_RETURN(COLLECTIONCERTSTORECONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_CollectionCertStoreContext_GetSelectedCert
+ * DESCRIPTION:
+ *
+ * Finds the Certs that match the criterion of the CertSelector pointed
+ * to by "selector" using the List of Certs pointed to by "certList" and
+ * stores the matching Certs at "pSelectedCertList".
+ *
+ * Not recursive to sub-directory.
+ *
+ * PARAMETERS
+ * "certList" - Address of List of Certs to be searched. Must be non-NULL.
+ * "colCertStoreContext" - Address of CollectionCertStoreContext
+ * where the cached Certs are stored.
+ * "selector" - CertSelector for chosing Cert based on Params set
+ * "pSelectedCertList" - Certs that qualified by selector.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - A lock at top level is required.
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CollectionCertStoreContext Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CollectionCertStoreContext_GetSelectedCert(
+ PKIX_List *certList,
+ PKIX_CertSelector *selector,
+ PKIX_List **pSelectedCertList,
+ void *plContext)
+{
+ PKIX_List *selectCertList = NULL;
+ PKIX_PL_Cert *certItem = NULL;
+ PKIX_CertSelector_MatchCallback certSelectorMatch = NULL;
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 i = 0;
+
+ PKIX_ENTER(COLLECTIONCERTSTORECONTEXT,
+ "pkix_pl_CollectionCertStoreContext_GetSelectedCert");
+ PKIX_NULLCHECK_THREE(certList, selector, pSelectedCertList);
+
+ PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
+ (selector, &certSelectorMatch, plContext),
+ PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(certList, &numCerts, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (certSelectorMatch) {
+
+ PKIX_CHECK(PKIX_List_Create(&selectCertList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_CHECK_ONLY_FATAL
+ (PKIX_List_GetItem
+ (certList,
+ i,
+ (PKIX_PL_Object **) &certItem,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (!PKIX_ERROR_RECEIVED){
+ PKIX_CHECK_ONLY_FATAL
+ (certSelectorMatch
+ (selector, certItem, plContext),
+ PKIX_CERTSELECTORMATCHFAILED);
+
+ if (!PKIX_ERROR_RECEIVED){
+ PKIX_CHECK_ONLY_FATAL
+ (PKIX_List_AppendItem
+ (selectCertList,
+ (PKIX_PL_Object *)certItem,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+ }
+
+ PKIX_DECREF(certItem);
+ }
+
+ } else {
+
+ PKIX_INCREF(certList);
+
+ selectCertList = certList;
+ }
+
+ *pSelectedCertList = selectCertList;
+
+cleanup:
+ PKIX_RETURN(COLLECTIONCERTSTORECONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_CollectionCertStoreContext_GetSelectedCRL
+ * DESCRIPTION:
+ *
+ * Finds the CRLs that match the criterion of the CRLSelector pointed
+ * to by "selector" using the List of CRLs pointed to by "crlList" and
+ * stores the matching CRLs at "pSelectedCrlList".
+ *
+ * Not recursive to sub-directory.
+ *
+ * PARAMETERS
+ * "crlList" - Address of List of CRLs to be searched. Must be non-NULL
+ * "selector" - CRLSelector for chosing CRL based on Params set
+ * "pSelectedCrlList" - CRLs that qualified by selector.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - A lock at top level is required.
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CollectionCertStoreContext Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CollectionCertStoreContext_GetSelectedCRL(
+ PKIX_List *crlList,
+ PKIX_CRLSelector *selector,
+ PKIX_List **pSelectedCrlList,
+ void *plContext)
+{
+ PKIX_List *selectCrlList = NULL;
+ PKIX_PL_CRL *crlItem = NULL;
+ PKIX_CRLSelector_MatchCallback crlSelectorMatch = NULL;
+ PKIX_UInt32 numCrls = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_Boolean match = PKIX_FALSE;
+
+ PKIX_ENTER(COLLECTIONCERTSTORECONTEXT,
+ "pkix_pl_CollectionCertStoreContext_GetSelectedCRL");
+ PKIX_NULLCHECK_THREE(crlList, selector, pSelectedCrlList);
+
+ PKIX_CHECK(PKIX_CRLSelector_GetMatchCallback
+ (selector, &crlSelectorMatch, plContext),
+ PKIX_CRLSELECTORGETMATCHCALLBACKFAILED);
+
+ PKIX_CHECK(PKIX_List_GetLength(crlList, &numCrls, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (crlSelectorMatch) {
+
+ PKIX_CHECK(PKIX_List_Create(&selectCrlList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ for (i = 0; i < numCrls; i++) {
+ PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem
+ (crlList,
+ i,
+ (PKIX_PL_Object **) &crlItem,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (!PKIX_ERROR_RECEIVED){
+ PKIX_CHECK_ONLY_FATAL
+ (crlSelectorMatch
+ (selector, crlItem, &match, plContext),
+ PKIX_CRLSELECTORMATCHFAILED);
+
+ if (!(PKIX_ERROR_RECEIVED) && match) {
+ PKIX_CHECK_ONLY_FATAL
+ (PKIX_List_AppendItem
+ (selectCrlList,
+ (PKIX_PL_Object *)crlItem,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ }
+ }
+
+ PKIX_DECREF(crlItem);
+ }
+ } else {
+
+ PKIX_INCREF(crlList);
+
+ selectCrlList = crlList;
+ }
+
+ /* Don't throw away the list if one CRL was bad! */
+ pkixTempErrorReceived = PKIX_FALSE;
+
+ *pSelectedCrlList = selectCrlList;
+
+cleanup:
+ PKIX_RETURN(COLLECTIONCERTSTORECONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_CollectionCertStore_GetCert
+ * DESCRIPTION:
+ *
+ * Retrieve Certs in a list of PKIX_PL_Cert object.
+ *
+ * PARAMETERS:
+ * "colCertStoreContext"
+ * The object CertStore is the object passed in by checker call.
+ * "crlSelector"
+ * CRLSelector specifies criteria for chosing CRL's
+ * "pNBIOContext"
+ * Address where platform-dependent information is returned for CertStores
+ * that use non-blocking I/O. Must be non-NULL.
+ * "pCertList"
+ * Address where object pointer will be returned. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CollectionCertStore_GetCert(
+ PKIX_CertStore *certStore,
+ PKIX_CertSelector *selector,
+ PKIX_VerifyNode *verifyNode,
+ void **pNBIOContext,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ PKIX_PL_CollectionCertStoreContext *colCertStoreContext = NULL;
+ PKIX_List *selectedCerts = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_CollectionCertStore_GetCert");
+ PKIX_NULLCHECK_FOUR(certStore, selector, pNBIOContext, pCerts);
+
+ *pNBIOContext = NULL; /* We don't use non-blocking I/O */
+
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
+ (certStore,
+ (PKIX_PL_Object **) &colCertStoreContext,
+ plContext),
+ PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
+
+ if (colCertStoreContext->certList == NULL) {
+
+ PKIX_OBJECT_LOCK(colCertStoreContext);
+
+ /*
+ * Certs in the directory are cached based on the
+ * assumption that the directory contents won't be
+ * changed dynamically.
+ */
+ if (colCertStoreContext->certList == NULL){
+ PKIX_CHECK(pkix_pl_CollectionCertStoreContext_PopulateCert
+ (colCertStoreContext, plContext),
+ PKIX_COLLECTIONCERTSTORECONTEXTPOPULATECERTFAILED);
+ }
+
+ PKIX_OBJECT_UNLOCK(colCertStoreContext);
+ }
+
+ PKIX_CHECK(pkix_pl_CollectionCertStoreContext_GetSelectedCert
+ (colCertStoreContext->certList,
+ selector,
+ &selectedCerts,
+ plContext),
+ PKIX_COLLECTIONCERTSTORECONTEXTGETSELECTCERTFAILED);
+
+ *pCerts = selectedCerts;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_DECREF(colCertStoreContext);
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_CollectionCertStore_GetCRL
+ * DESCRIPTION:
+ *
+ * Retrieve CRL's in a list of PKIX_PL_CRL object.
+ *
+ * PARAMETERS:
+ * "colCertStoreContext"
+ * The object CertStore is passed in by checker call.
+ * "crlSelector"
+ * CRLSelector specifies criteria for chosing CRL's
+ * "pNBIOContext"
+ * Address where platform-dependent information is returned for CertStores
+ * that use non-blocking I/O. Must be non-NULL.
+ * "pCrlList"
+ * Address where object pointer will be returned. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CollectionCertStore_GetCRL(
+ PKIX_CertStore *certStore,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrlList,
+ void *plContext)
+{
+ PKIX_PL_CollectionCertStoreContext *colCertStoreContext = NULL;
+ PKIX_List *selectCrl = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_CollectionCertStore_GetCRL");
+ PKIX_NULLCHECK_FOUR(certStore, selector, pNBIOContext, pCrlList);
+
+ *pNBIOContext = NULL; /* We don't use non-blocking I/O */
+
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
+ (certStore,
+ (PKIX_PL_Object **) &colCertStoreContext,
+ plContext),
+ PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
+
+ if (colCertStoreContext->crlList == NULL) {
+
+ PKIX_OBJECT_LOCK(colCertStoreContext);
+
+ /*
+ * CRLs in the directory are cached based on the
+ * assumption that the directory contents won't be
+ * changed dynamically.
+ */
+ if (colCertStoreContext->crlList == NULL){
+ PKIX_CHECK(pkix_pl_CollectionCertStoreContext_PopulateCRL
+ (colCertStoreContext, plContext),
+ PKIX_COLLECTIONCERTSTORECONTEXTPOPULATECRLFAILED);
+ }
+
+ PKIX_OBJECT_UNLOCK(colCertStoreContext);
+
+ }
+
+ PKIX_CHECK(pkix_pl_CollectionCertStoreContext_GetSelectedCRL
+ (colCertStoreContext->crlList,
+ selector,
+ &selectCrl,
+ plContext),
+ PKIX_COLLECTIONCERTSTORECONTEXTGETSELECTCRLFAILED);
+
+ *pCrlList = selectCrl;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_DECREF(colCertStoreContext);
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_CollectionCertStoreContext_RegisterSelf
+ * DESCRIPTION:
+ *
+ * Registers PKIX_PL_COLLECTIONCERTSTORECONTEXT_TYPE and its related
+ * functions with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CollectionCertStoreContext_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(COLLECTIONCERTSTORECONTEXT,
+ "pkix_pl_CollectionCertStoreContext_RegisterSelf");
+
+ entry.description = "CollectionCertStoreContext";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_CollectionCertStoreContext);
+ entry.destructor = pkix_pl_CollectionCertStoreContext_Destroy;
+ entry.equalsFunction = pkix_pl_CollectionCertStoreContext_Equals;
+ entry.hashcodeFunction = pkix_pl_CollectionCertStoreContext_Hashcode;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_COLLECTIONCERTSTORECONTEXT_TYPE] = entry;
+
+ PKIX_RETURN(COLLECTIONCERTSTORECONTEXT);
+}
+
+/* --Public-CollectionCertStoreContext-Functions--------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_CollectionCertStore_Create
+ * (see comments in pkix_samples_modules.h)
+ */
+PKIX_Error *
+PKIX_PL_CollectionCertStore_Create(
+ PKIX_PL_String *storeDir,
+ PKIX_CertStore **pCertStore,
+ void *plContext)
+{
+ PKIX_PL_CollectionCertStoreContext *colCertStoreContext = NULL;
+ PKIX_CertStore *certStore = NULL;
+
+ PKIX_ENTER(CERTSTORE, "PKIX_PL_CollectionCertStore_Create");
+ PKIX_NULLCHECK_TWO(storeDir, pCertStore);
+
+ PKIX_CHECK(pkix_pl_CollectionCertStoreContext_Create
+ (storeDir, &colCertStoreContext, plContext),
+ PKIX_COULDNOTCREATECOLLECTIONCERTSTORECONTEXTOBJECT);
+
+ PKIX_CHECK(PKIX_CertStore_Create
+ (pkix_pl_CollectionCertStore_GetCert,
+ pkix_pl_CollectionCertStore_GetCRL,
+ NULL, /* GetCertContinue */
+ NULL, /* GetCRLContinue */
+ pkix_pl_CollectionCertStore_CheckTrust,
+ NULL, /* can not store crls */
+ NULL, /* can not do revocation check */
+ (PKIX_PL_Object *)colCertStoreContext,
+ PKIX_TRUE, /* cache flag */
+ PKIX_TRUE, /* local - no network I/O */
+ &certStore,
+ plContext),
+ PKIX_CERTSTORECREATEFAILED);
+
+ PKIX_DECREF(colCertStoreContext);
+
+ *pCertStore = certStore;
+
+cleanup:
+ PKIX_RETURN(CERTSTORE);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.h
new file mode 100644
index 0000000000..f41e6fa5e8
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_colcertstore.h
@@ -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_pl_colcertstore.h
+ *
+ * CollectionCertstore Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_PL_COLCERTSTORE_H
+#define _PKIX_PL_COLCERTSTORE_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_CollectionCertStoreContext {
+ PKIX_PL_String *storeDir;
+ PKIX_List *crlList;
+ PKIX_List *certList;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_CollectionCertStoreContext_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_COLCERTSTORE_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c
new file mode 100644
index 0000000000..471f92004a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.c
@@ -0,0 +1,1147 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_httpcertstore.c
+ *
+ * HTTPCertStore Function Definitions
+ *
+ */
+
+/* We can't decode the length of a message without at least this many bytes */
+
+#include "pkix_pl_httpcertstore.h"
+extern PKIX_PL_HashTable *httpSocketCache;
+SEC_ASN1_MKSUB(CERT_IssuerAndSNTemplate)
+SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
+SEC_ASN1_MKSUB(SEC_SetOfAnyTemplate)
+SEC_ASN1_MKSUB(CERT_SetOfSignedCrlTemplate)
+
+SEC_ASN1_CHOOSER_DECLARE(CERT_IssuerAndSNTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SECOID_AlgorithmIDTemplate)
+/* SEC_ASN1_CHOOSER_DECLARE(SEC_SetOfAnyTemplate)
+SEC_ASN1_CHOOSER_DECLARE(CERT_SetOfSignedCrlTemplate)
+
+const SEC_ASN1Template CERT_IssuerAndSNTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTIssuerAndSN) },
+ { SEC_ASN1_SAVE,
+ offsetof(CERTIssuerAndSN,derIssuer) },
+ { SEC_ASN1_INLINE,
+ offsetof(CERTIssuerAndSN,issuer),
+ CERT_NameTemplate },
+ { SEC_ASN1_INTEGER,
+ offsetof(CERTIssuerAndSN,serialNumber) },
+ { 0 }
+};
+
+const SEC_ASN1Template SECOID_AlgorithmIDTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(SECAlgorithmID) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(SECAlgorithmID,algorithm) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY,
+ offsetof(SECAlgorithmID,parameters) },
+ { 0 }
+}; */
+
+/* --Private-HttpCertStoreContext-Object Functions----------------------- */
+
+/*
+ * FUNCTION: pkix_pl_HttpCertStoreContext_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_HttpCertStoreContext_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ const SEC_HttpClientFcnV1 *hcv1 = NULL;
+ PKIX_PL_HttpCertStoreContext *context = NULL;
+
+ PKIX_ENTER
+ (HTTPCERTSTORECONTEXT, "pkix_pl_HttpCertStoreContext_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_HTTPCERTSTORECONTEXT_TYPE, plContext),
+ PKIX_OBJECTNOTANHTTPCERTSTORECONTEXT);
+
+ context = (PKIX_PL_HttpCertStoreContext *)object;
+ hcv1 = (const SEC_HttpClientFcnV1 *)(context->client);
+ if (context->requestSession != NULL) {
+ (*hcv1->freeFcn)(context->requestSession);
+ context->requestSession = NULL;
+ }
+ if (context->serverSession != NULL) {
+ (*hcv1->freeSessionFcn)(context->serverSession);
+ context->serverSession = NULL;
+ }
+ if (context->path != NULL) {
+ PORT_Free(context->path);
+ context->path = NULL;
+ }
+
+cleanup:
+
+ PKIX_RETURN(HTTPCERTSTORECONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpCertStoreContext_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_PL_HTTPCERTSTORECONTEXT_TYPE and its related
+ * functions with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_HttpCertStoreContext_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry *entry = &systemClasses[PKIX_HTTPCERTSTORECONTEXT_TYPE];
+
+ PKIX_ENTER(HTTPCERTSTORECONTEXT,
+ "pkix_pl_HttpCertStoreContext_RegisterSelf");
+
+ entry->description = "HttpCertStoreContext";
+ entry->typeObjectSize = sizeof(PKIX_PL_HttpCertStoreContext);
+ entry->destructor = pkix_pl_HttpCertStoreContext_Destroy;
+
+ PKIX_RETURN(HTTPCERTSTORECONTEXT);
+}
+
+
+/* --Private-Http-CertStore-Database-Functions----------------------- */
+
+typedef struct callbackContextStruct {
+ PKIX_List *pkixCertList;
+ PKIX_Error *error;
+ void *plContext;
+} callbackContext;
+
+
+/*
+ * FUNCTION: certCallback
+ * DESCRIPTION:
+ *
+ * This function processes the null-terminated array of SECItems produced by
+ * extracting the contents of a signedData message received in response to an
+ * HTTP cert query. Its address is supplied as a callback function to
+ * CERT_DecodeCertPackage; it is not expected to be called directly.
+ *
+ * Note that it does not conform to the libpkix API standard of returning
+ * a PKIX_Error*. It returns a SECStatus.
+ *
+ * PARAMETERS:
+ * "arg"
+ * The address of the callbackContext provided as a void* argument to
+ * CERT_DecodeCertPackage. Must be non-NULL.
+ * "secitemCerts"
+ * The address of the null-terminated array of SECItems. Must be non-NULL.
+ * "numcerts"
+ * The number of SECItems found in the signedData. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns SECSuccess if the function succeeds.
+ * Returns SECFailure if the function fails.
+ */
+static SECStatus
+certCallback(void *arg, SECItem **secitemCerts, int numcerts)
+{
+ callbackContext *cbContext;
+ PKIX_List *pkixCertList = NULL;
+ PKIX_Error *error = NULL;
+ void *plContext = NULL;
+ int itemNum = 0;
+
+ if ((arg == NULL) || (secitemCerts == NULL)) {
+ return (SECFailure);
+ }
+
+ cbContext = (callbackContext *)arg;
+ plContext = cbContext->plContext;
+ pkixCertList = cbContext->pkixCertList;
+
+ for (; itemNum < numcerts; itemNum++ ) {
+ error = pkix_pl_Cert_CreateToList(secitemCerts[itemNum],
+ pkixCertList, plContext);
+ if (error != NULL) {
+ if (error->errClass == PKIX_FATAL_ERROR) {
+ cbContext->error = error;
+ return SECFailure;
+ }
+ /* reuse "error" since we could not destruct the old *
+ * value */
+ error = PKIX_PL_Object_DecRef((PKIX_PL_Object *)error,
+ plContext);
+ if (error) {
+ /* Treat decref failure as a fatal error.
+ * In this case will leak error, but can not do
+ * anything about it. */
+ error->errClass = PKIX_FATAL_ERROR;
+ cbContext->error = error;
+ return SECFailure;
+ }
+ }
+ }
+
+ return SECSuccess;
+}
+
+
+typedef SECStatus (*pkix_DecodeCertsFunc)(char *certbuf, int certlen,
+ CERTImportCertificateFunc f, void *arg);
+
+
+struct pkix_DecodeFuncStr {
+ pkix_DecodeCertsFunc func; /* function pointer to the
+ * CERT_DecodeCertPackage function */
+ PRLibrary *smimeLib; /* Pointer to the smime shared lib*/
+ PRCallOnceType once;
+};
+
+static struct pkix_DecodeFuncStr pkix_decodeFunc;
+static const PRCallOnceType pkix_pristine;
+
+#define SMIME_LIB_NAME SHLIB_PREFIX"smime3."SHLIB_SUFFIX
+
+/*
+ * load the smime library and look up the SEC_ReadPKCS7Certs function.
+ * we do this so we don't have a circular depenency on the smime library,
+ * and also so we don't have to load the smime library in applications that
+ * don't use it.
+ */
+static PRStatus PR_CALLBACK pkix_getDecodeFunction(void)
+{
+ pkix_decodeFunc.smimeLib =
+ PR_LoadLibrary(SHLIB_PREFIX"smime3."SHLIB_SUFFIX);
+ if (pkix_decodeFunc.smimeLib == NULL) {
+ return PR_FAILURE;
+ }
+
+ pkix_decodeFunc.func = (pkix_DecodeCertsFunc) PR_FindFunctionSymbol(
+ pkix_decodeFunc.smimeLib, "CERT_DecodeCertPackage");
+ if (!pkix_decodeFunc.func) {
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+
+}
+
+/*
+ * clears our global state on shutdown.
+ */
+void
+pkix_pl_HttpCertStore_Shutdown(void *plContext)
+{
+ if (pkix_decodeFunc.smimeLib) {
+ PR_UnloadLibrary(pkix_decodeFunc.smimeLib);
+ pkix_decodeFunc.smimeLib = NULL;
+ }
+ /* the function pointer just need to be cleared, not freed */
+ pkix_decodeFunc.func = NULL;
+ pkix_decodeFunc.once = pkix_pristine;
+}
+
+/*
+ * This function is based on CERT_DecodeCertPackage from lib/pkcs7/certread.c
+ * read an old style ascii or binary certificate chain
+ */
+PKIX_Error *
+pkix_pl_HttpCertStore_DecodeCertPackage
+ (const char *certbuf,
+ int certlen,
+ CERTImportCertificateFunc f,
+ void *arg,
+ void *plContext)
+{
+
+ PRStatus status;
+ SECStatus rv;
+
+ PKIX_ENTER
+ (HTTPCERTSTORECONTEXT,
+ "pkix_pl_HttpCertStore_DecodeCertPackage");
+ PKIX_NULLCHECK_TWO(certbuf, f);
+
+ status = PR_CallOnce(&pkix_decodeFunc.once, pkix_getDecodeFunction);
+
+ if (status != PR_SUCCESS) {
+ PKIX_ERROR(PKIX_CANTLOADLIBSMIME);
+ }
+
+ /* paranoia, shouldn't happen if status == PR_SUCCESS); */
+ if (!pkix_decodeFunc.func) {
+ PKIX_ERROR(PKIX_CANTLOADLIBSMIME);
+ }
+
+ rv = (*pkix_decodeFunc.func)((char*)certbuf, certlen, f, arg);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR (PKIX_SECREADPKCS7CERTSFAILED);
+ }
+
+
+cleanup:
+
+ PKIX_RETURN(HTTPCERTSTORECONTEXT);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_HttpCertStore_ProcessCertResponse
+ * DESCRIPTION:
+ *
+ * This function verifies that the response code pointed to by "responseCode"
+ * and the content type pointed to by "responseContentType" are as expected,
+ * and then decodes the data pointed to by "responseData", of length
+ * "responseDataLen", into a List of Certs, possibly empty, which is returned
+ * at "pCertList".
+ *
+ * PARAMETERS:
+ * "responseCode"
+ * The value of the HTTP response code.
+ * "responseContentType"
+ * The address of the Content-type string. Must be non-NULL.
+ * "responseData"
+ * The address of the message data. Must be non-NULL.
+ * "responseDataLen"
+ * The length of the message data.
+ * "pCertList"
+ * The address of the List that is created. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpCertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_HttpCertStore_ProcessCertResponse(
+ PRUint16 responseCode,
+ const char *responseContentType,
+ const char *responseData,
+ PRUint32 responseDataLen,
+ PKIX_List **pCertList,
+ void *plContext)
+{
+ callbackContext cbContext;
+
+ PKIX_ENTER(HTTPCERTSTORECONTEXT,
+ "pkix_pl_HttpCertStore_ProcessCertResponse");
+
+ cbContext.error = NULL;
+ cbContext.plContext = plContext;
+ cbContext.pkixCertList = NULL;
+
+ PKIX_NULLCHECK_ONE(pCertList);
+
+ if (responseCode != 200) {
+ PKIX_ERROR(PKIX_BADHTTPRESPONSE);
+ }
+
+ /* check that response type is application/pkcs7-mime */
+ if (responseContentType == NULL) {
+ PKIX_ERROR(PKIX_NOCONTENTTYPEINHTTPRESPONSE);
+ }
+
+ if (responseData == NULL) {
+ PKIX_ERROR(PKIX_NORESPONSEDATAINHTTPRESPONSE);
+ }
+
+ PKIX_CHECK(
+ PKIX_List_Create(&cbContext.pkixCertList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK_ONLY_FATAL(
+ pkix_pl_HttpCertStore_DecodeCertPackage(responseData,
+ responseDataLen,
+ certCallback,
+ &cbContext,
+ plContext),
+ PKIX_HTTPCERTSTOREDECODECERTPACKAGEFAILED);
+ if (cbContext.error) {
+ /* Aborting on a fatal error(See certCallback fn) */
+ pkixErrorResult = cbContext.error;
+ goto cleanup;
+ }
+
+ *pCertList = cbContext.pkixCertList;
+ cbContext.pkixCertList = NULL;
+
+cleanup:
+
+ PKIX_DECREF(cbContext.pkixCertList);
+
+ PKIX_RETURN(HTTPCERTSTORECONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpCertStore_ProcessCrlResponse
+ * DESCRIPTION:
+ *
+ * This function verifies that the response code pointed to by "responseCode"
+ * and the content type pointed to by "responseContentType" are as expected,
+ * and then decodes the data pointed to by "responseData", of length
+ * "responseDataLen", into a List of Crls, possibly empty, which is returned
+ * at "pCrlList".
+ *
+ * PARAMETERS:
+ * "responseCode"
+ * The value of the HTTP response code.
+ * "responseContentType"
+ * The address of the Content-type string. Must be non-NULL.
+ * "responseData"
+ * The address of the message data. Must be non-NULL.
+ * "responseDataLen"
+ * The length of the message data.
+ * "pCrlList"
+ * The address of the List that is created. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpCertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_HttpCertStore_ProcessCrlResponse(
+ PRUint16 responseCode,
+ const char *responseContentType,
+ const char *responseData,
+ PRUint32 responseDataLen,
+ PKIX_List **pCrlList,
+ void *plContext)
+{
+ SECItem encodedResponse;
+ PRInt16 compareVal = 0;
+ PKIX_List *crls = NULL;
+ SECItem *derCrlCopy = NULL;
+ CERTSignedCrl *nssCrl = NULL;
+ PKIX_PL_CRL *crl = NULL;
+
+ PKIX_ENTER(HTTPCERTSTORECONTEXT,
+ "pkix_pl_HttpCertStore_ProcessCrlResponse");
+ PKIX_NULLCHECK_ONE(pCrlList);
+
+ if (responseCode != 200) {
+ PKIX_ERROR(PKIX_BADHTTPRESPONSE);
+ }
+
+ /* check that response type is application/pkix-crl */
+ if (responseContentType == NULL) {
+ PKIX_ERROR(PKIX_NOCONTENTTYPEINHTTPRESPONSE);
+ }
+
+ compareVal = PORT_Strcasecmp(responseContentType,
+ "application/pkix-crl");
+ if (compareVal != 0) {
+ PKIX_ERROR(PKIX_CONTENTTYPENOTPKIXCRL);
+ }
+ encodedResponse.type = siBuffer;
+ encodedResponse.data = (void*)responseData;
+ encodedResponse.len = responseDataLen;
+
+ derCrlCopy = SECITEM_DupItem(&encodedResponse);
+ if (!derCrlCopy) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ /* crl will be based on derCrlCopy, but will not own the der. */
+ nssCrl =
+ CERT_DecodeDERCrlWithFlags(NULL, derCrlCopy, SEC_CRL_TYPE,
+ CRL_DECODE_DONT_COPY_DER |
+ CRL_DECODE_SKIP_ENTRIES);
+ if (!nssCrl) {
+ PKIX_ERROR(PKIX_FAILEDTODECODECRL);
+ }
+ /* pkix crls own the der. */
+ PKIX_CHECK(
+ pkix_pl_CRL_CreateWithSignedCRL(nssCrl, derCrlCopy, NULL,
+ &crl, plContext),
+ PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
+ /* Left control over memory pointed by derCrlCopy and
+ * nssCrl to pkix crl. */
+ derCrlCopy = NULL;
+ nssCrl = NULL;
+ PKIX_CHECK(PKIX_List_Create(&crls, plContext),
+ PKIX_LISTCREATEFAILED);
+ PKIX_CHECK(PKIX_List_AppendItem
+ (crls, (PKIX_PL_Object *) crl, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ *pCrlList = crls;
+ crls = NULL;
+cleanup:
+ if (derCrlCopy) {
+ SECITEM_FreeItem(derCrlCopy, PR_TRUE);
+ }
+ if (nssCrl) {
+ SEC_DestroyCrl(nssCrl);
+ }
+ PKIX_DECREF(crl);
+ PKIX_DECREF(crls);
+
+ PKIX_RETURN(HTTPCERTSTORECONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpCertStore_CreateRequestSession
+ * DESCRIPTION:
+ *
+ * This function takes elements from the HttpCertStoreContext pointed to by
+ * "context" (path, client, and serverSession) and creates a RequestSession.
+ * See the HTTPClient API described in ocspt.h for further details.
+ *
+ * PARAMETERS:
+ * "context"
+ * The address of the HttpCertStoreContext. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpCertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_HttpCertStore_CreateRequestSession(
+ PKIX_PL_HttpCertStoreContext *context,
+ void *plContext)
+{
+ const SEC_HttpClientFcnV1 *hcv1 = NULL;
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER
+ (HTTPCERTSTORECONTEXT,
+ "pkix_pl_HttpCertStore_CreateRequestSession");
+ PKIX_NULLCHECK_TWO(context, context->serverSession);
+
+ if (context->client->version != 1) {
+ PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
+ }
+
+ hcv1 = &(context->client->fcnTable.ftable1);
+ if (context->requestSession != NULL) {
+ (*hcv1->freeFcn)(context->requestSession);
+ context->requestSession = 0;
+ }
+
+ rv = (*hcv1->createFcn)(context->serverSession, "http",
+ context->path, "GET",
+ PR_SecondsToInterval(
+ ((PKIX_PL_NssContext*)plContext)->timeoutSeconds),
+ &(context->requestSession));
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_HTTPSERVERERROR);
+ }
+cleanup:
+
+ PKIX_RETURN(HTTPCERTSTORECONTEXT);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpCertStore_GetCert
+ * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h)
+ */
+PKIX_Error *
+pkix_pl_HttpCertStore_GetCert(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ PKIX_VerifyNode *verifyNode,
+ void **pNBIOContext,
+ PKIX_List **pCertList,
+ void *plContext)
+{
+ const SEC_HttpClientFcnV1 *hcv1 = NULL;
+ PKIX_PL_HttpCertStoreContext *context = NULL;
+ void *nbioContext = NULL;
+ SECStatus rv = SECFailure;
+ PRUint16 responseCode = 0;
+ const char *responseContentType = NULL;
+ const char *responseData = NULL;
+ PRUint32 responseDataLen = 0;
+ PKIX_List *certList = NULL;
+
+ PKIX_ENTER(HTTPCERTSTORECONTEXT, "pkix_pl_HttpCertStore_GetCert");
+ PKIX_NULLCHECK_THREE(store, selector, pCertList);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
+ (store, (PKIX_PL_Object **)&context, plContext),
+ PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
+
+ if (context->client->version != 1) {
+ PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
+ }
+
+ hcv1 = &(context->client->fcnTable.ftable1);
+
+ PKIX_CHECK(pkix_pl_HttpCertStore_CreateRequestSession
+ (context, plContext),
+ PKIX_HTTPCERTSTORECREATEREQUESTSESSIONFAILED);
+
+ responseDataLen =
+ ((PKIX_PL_NssContext*)plContext)->maxResponseLength;
+
+ rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession,
+ (PRPollDesc **)&nbioContext,
+ &responseCode,
+ (const char **)&responseContentType,
+ NULL, /* &responseHeaders */
+ (const char **)&responseData,
+ &responseDataLen);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_HTTPSERVERERROR);
+ }
+
+ if (nbioContext != 0) {
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCertResponse
+ (responseCode,
+ responseContentType,
+ responseData,
+ responseDataLen,
+ &certList,
+ plContext),
+ PKIX_HTTPCERTSTOREPROCESSCERTRESPONSEFAILED);
+
+ *pCertList = certList;
+
+cleanup:
+ PKIX_DECREF(context);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpCertStore_GetCertContinue
+ * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h)
+ */
+PKIX_Error *
+pkix_pl_HttpCertStore_GetCertContinue(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ PKIX_VerifyNode *verifyNode,
+ void **pNBIOContext,
+ PKIX_List **pCertList,
+ void *plContext)
+{
+ const SEC_HttpClientFcnV1 *hcv1 = NULL;
+ PKIX_PL_HttpCertStoreContext *context = NULL;
+ void *nbioContext = NULL;
+ SECStatus rv = SECFailure;
+ PRUint16 responseCode = 0;
+ const char *responseContentType = NULL;
+ const char *responseData = NULL;
+ PRUint32 responseDataLen = 0;
+ PKIX_List *certList = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_GetCertContinue");
+ PKIX_NULLCHECK_THREE(store, selector, pCertList);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
+ (store, (PKIX_PL_Object **)&context, plContext),
+ PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
+
+ if (context->client->version != 1) {
+ PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
+ }
+
+ hcv1 = &(context->client->fcnTable.ftable1);
+ PKIX_NULLCHECK_ONE(context->requestSession);
+
+ responseDataLen =
+ ((PKIX_PL_NssContext*)plContext)->maxResponseLength;
+
+ rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession,
+ (PRPollDesc **)&nbioContext,
+ &responseCode,
+ (const char **)&responseContentType,
+ NULL, /* &responseHeaders */
+ (const char **)&responseData,
+ &responseDataLen);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_HTTPSERVERERROR);
+ }
+
+ if (nbioContext != 0) {
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCertResponse
+ (responseCode,
+ responseContentType,
+ responseData,
+ responseDataLen,
+ &certList,
+ plContext),
+ PKIX_HTTPCERTSTOREPROCESSCERTRESPONSEFAILED);
+
+ *pCertList = certList;
+
+cleanup:
+ PKIX_DECREF(context);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpCertStore_GetCRL
+ * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h)
+ */
+PKIX_Error *
+pkix_pl_HttpCertStore_GetCRL(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrlList,
+ void *plContext)
+{
+
+ const SEC_HttpClientFcnV1 *hcv1 = NULL;
+ PKIX_PL_HttpCertStoreContext *context = NULL;
+ void *nbioContext = NULL;
+ SECStatus rv = SECFailure;
+ PRUint16 responseCode = 0;
+ const char *responseContentType = NULL;
+ const char *responseData = NULL;
+ PRUint32 responseDataLen = 0;
+ PKIX_List *crlList = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_GetCRL");
+ PKIX_NULLCHECK_THREE(store, selector, pCrlList);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
+ (store, (PKIX_PL_Object **)&context, plContext),
+ PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
+
+ if (context->client->version != 1) {
+ PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
+ }
+
+ hcv1 = &(context->client->fcnTable.ftable1);
+ PKIX_CHECK(pkix_pl_HttpCertStore_CreateRequestSession
+ (context, plContext),
+ PKIX_HTTPCERTSTORECREATEREQUESTSESSIONFAILED);
+
+ responseDataLen =
+ ((PKIX_PL_NssContext*)plContext)->maxResponseLength;
+
+ rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession,
+ (PRPollDesc **)&nbioContext,
+ &responseCode,
+ (const char **)&responseContentType,
+ NULL, /* &responseHeaders */
+ (const char **)&responseData,
+ &responseDataLen);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_HTTPSERVERERROR);
+ }
+
+ if (nbioContext != 0) {
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCrlResponse
+ (responseCode,
+ responseContentType,
+ responseData,
+ responseDataLen,
+ &crlList,
+ plContext),
+ PKIX_HTTPCERTSTOREPROCESSCRLRESPONSEFAILED);
+
+ *pCrlList = crlList;
+
+cleanup:
+ PKIX_DECREF(context);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpCertStore_GetCRLContinue
+ * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h)
+ */
+PKIX_Error *
+pkix_pl_HttpCertStore_GetCRLContinue(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrlList,
+ void *plContext)
+{
+ const SEC_HttpClientFcnV1 *hcv1 = NULL;
+ PKIX_PL_HttpCertStoreContext *context = NULL;
+ void *nbioContext = NULL;
+ SECStatus rv = SECFailure;
+ PRUint16 responseCode = 0;
+ const char *responseContentType = NULL;
+ const char *responseData = NULL;
+ PRUint32 responseDataLen = 0;
+ PKIX_List *crlList = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_GetCRLContinue");
+ PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCrlList);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
+ (store, (PKIX_PL_Object **)&context, plContext),
+ PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
+
+ if (context->client->version != 1) {
+ PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
+ }
+ hcv1 = &(context->client->fcnTable.ftable1);
+
+ PKIX_CHECK(pkix_pl_HttpCertStore_CreateRequestSession
+ (context, plContext),
+ PKIX_HTTPCERTSTORECREATEREQUESTSESSIONFAILED);
+
+ responseDataLen =
+ ((PKIX_PL_NssContext*)plContext)->maxResponseLength;
+
+ rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession,
+ (PRPollDesc **)&nbioContext,
+ &responseCode,
+ (const char **)&responseContentType,
+ NULL, /* &responseHeaders */
+ (const char **)&responseData,
+ &responseDataLen);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_HTTPSERVERERROR);
+ }
+
+ if (nbioContext != 0) {
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCrlResponse
+ (responseCode,
+ responseContentType,
+ responseData,
+ responseDataLen,
+ &crlList,
+ plContext),
+ PKIX_HTTPCERTSTOREPROCESSCRLRESPONSEFAILED);
+
+ *pCrlList = crlList;
+
+cleanup:
+ PKIX_DECREF(context);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/* --Public-HttpCertStore-Functions----------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_HttpCertStore_CreateWithAsciiName
+ * DESCRIPTION:
+ *
+ * This function uses the HttpClient pointed to by "client" and the string
+ * (hostname:portnum/path, with portnum optional) pointed to by "locationAscii"
+ * to create an HttpCertStore connected to the desired location, storing the
+ * created CertStore at "pCertStore".
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the HttpClient. Must be non-NULL.
+ * "locationAscii"
+ * The address of the character string indicating the hostname, port, and
+ * path to be queried for Certs or Crls. Must be non-NULL.
+ * "pCertStore"
+ * The address in which the object is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpCertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_HttpCertStore_CreateWithAsciiName(
+ PKIX_PL_HttpClient *client,
+ char *locationAscii,
+ PKIX_CertStore **pCertStore,
+ void *plContext)
+{
+ const SEC_HttpClientFcn *clientFcn = NULL;
+ const SEC_HttpClientFcnV1 *hcv1 = NULL;
+ PKIX_PL_HttpCertStoreContext *httpCertStore = NULL;
+ PKIX_CertStore *certStore = NULL;
+ char *hostname = NULL;
+ char *path = NULL;
+ PRUint16 port = 0;
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_CreateWithAsciiName");
+ PKIX_NULLCHECK_TWO(locationAscii, pCertStore);
+
+ if (client == NULL) {
+ clientFcn = SEC_GetRegisteredHttpClient();
+ if (clientFcn == NULL) {
+ PKIX_ERROR(PKIX_NOREGISTEREDHTTPCLIENT);
+ }
+ } else {
+ clientFcn = (const SEC_HttpClientFcn *)client;
+ }
+
+ if (clientFcn->version != 1) {
+ PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
+ }
+
+ /* create a PKIX_PL_HttpCertStore object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_HTTPCERTSTORECONTEXT_TYPE,
+ sizeof (PKIX_PL_HttpCertStoreContext),
+ (PKIX_PL_Object **)&httpCertStore,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* Initialize fields */
+ httpCertStore->client = clientFcn; /* not a PKIX object! */
+
+ /* parse location -> hostname, port, path */
+ rv = CERT_ParseURL(locationAscii, &hostname, &port, &path);
+ if (rv == SECFailure || hostname == NULL || path == NULL) {
+ PKIX_ERROR(PKIX_URLPARSINGFAILED);
+ }
+
+ httpCertStore->path = path;
+ path = NULL;
+
+ hcv1 = &(clientFcn->fcnTable.ftable1);
+ rv = (*hcv1->createSessionFcn)(hostname, port,
+ &(httpCertStore->serverSession));
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_HTTPCLIENTCREATESESSIONFAILED);
+ }
+
+ httpCertStore->requestSession = NULL;
+
+ PKIX_CHECK(PKIX_CertStore_Create
+ (pkix_pl_HttpCertStore_GetCert,
+ pkix_pl_HttpCertStore_GetCRL,
+ pkix_pl_HttpCertStore_GetCertContinue,
+ pkix_pl_HttpCertStore_GetCRLContinue,
+ NULL, /* don't support trust */
+ NULL, /* can not store crls */
+ NULL, /* can not do revocation check */
+ (PKIX_PL_Object *)httpCertStore,
+ PKIX_TRUE, /* cache flag */
+ PKIX_FALSE, /* not local */
+ &certStore,
+ plContext),
+ PKIX_CERTSTORECREATEFAILED);
+
+ *pCertStore = certStore;
+ certStore = NULL;
+
+cleanup:
+ PKIX_DECREF(httpCertStore);
+ if (hostname) {
+ PORT_Free(hostname);
+ }
+ if (path) {
+ PORT_Free(path);
+ }
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: PKIX_PL_HttpCertStore_Create
+ * (see comments in pkix_samples_modules.h)
+ */
+PKIX_Error *
+PKIX_PL_HttpCertStore_Create(
+ PKIX_PL_HttpClient *client,
+ PKIX_PL_GeneralName *location,
+ PKIX_CertStore **pCertStore,
+ void *plContext)
+{
+ PKIX_PL_String *locationString = NULL;
+ char *locationAscii = NULL;
+ PKIX_UInt32 len = 0;
+
+ PKIX_ENTER(CERTSTORE, "PKIX_PL_HttpCertStore_Create");
+ PKIX_NULLCHECK_TWO(location, pCertStore);
+
+ PKIX_TOSTRING(location, &locationString, plContext,
+ PKIX_GENERALNAMETOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (locationString,
+ PKIX_ESCASCII,
+ (void **)&locationAscii,
+ &len,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_CHECK(pkix_pl_HttpCertStore_CreateWithAsciiName
+ (client, locationAscii, pCertStore, plContext),
+ PKIX_HTTPCERTSTORECREATEWITHASCIINAMEFAILED);
+
+cleanup:
+
+ PKIX_DECREF(locationString);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_HttpCertStore_FindSocketConnection
+ * DESCRIPTION:
+ *
+ PRIntervalTime timeout,
+ char *hostname,
+ PRUint16 portnum,
+ PRErrorCode *pStatus,
+ PKIX_PL_Socket **pSocket,
+
+ * This function checks for an existing socket, creating a new one if unable
+ * to find an existing one, for the host pointed to by "hostname" and the port
+ * pointed to by "portnum". If a new socket is created the PRIntervalTime in
+ * "timeout" will be used for the timeout value and a creation status is
+ * returned at "pStatus". The address of the socket is stored at "pSocket".
+ *
+ * PARAMETERS:
+ * "timeout"
+ * The PRIntervalTime of the timeout value.
+ * "hostname"
+ * The address of the string containing the hostname. Must be non-NULL.
+ * "portnum"
+ * The port number for the desired socket.
+ * "pStatus"
+ * The address at which the status is stored. Must be non-NULL.
+ * "pSocket"
+ * The address at which the socket is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpCertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_HttpCertStore_FindSocketConnection(
+ PRIntervalTime timeout,
+ char *hostname,
+ PRUint16 portnum,
+ PRErrorCode *pStatus,
+ PKIX_PL_Socket **pSocket,
+ void *plContext)
+{
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *hostString = NULL;
+ PKIX_PL_String *domainString = NULL;
+ PKIX_PL_Socket *socket = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_HttpCertStore_FindSocketConnection");
+ PKIX_NULLCHECK_THREE(hostname, pStatus, pSocket);
+
+ *pStatus = 0;
+
+ /* create PKIX_PL_String from hostname and port */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s:%d", 0, &formatString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+#if 0
+hostname = "variation.red.iplanet.com";
+portnum = 2001;
+#endif
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, hostname, 0, &hostString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&domainString, plContext, formatString, hostString, portnum),
+ PKIX_STRINGCREATEFAILED);
+
+#ifdef PKIX_SOCKETCACHE
+ /* Is this domainName already in cache? */
+ PKIX_CHECK(PKIX_PL_HashTable_Lookup
+ (httpSocketCache,
+ (PKIX_PL_Object *)domainString,
+ (PKIX_PL_Object **)&socket,
+ plContext),
+ PKIX_HASHTABLELOOKUPFAILED);
+#endif
+ if (socket == NULL) {
+
+ /* No, create a connection (and cache it) */
+ PKIX_CHECK(pkix_pl_Socket_CreateByHostAndPort
+ (PKIX_FALSE, /* create a client, not a server */
+ timeout,
+ hostname,
+ portnum,
+ pStatus,
+ &socket,
+ plContext),
+ PKIX_SOCKETCREATEBYHOSTANDPORTFAILED);
+
+#ifdef PKIX_SOCKETCACHE
+ PKIX_CHECK(PKIX_PL_HashTable_Add
+ (httpSocketCache,
+ (PKIX_PL_Object *)domainString,
+ (PKIX_PL_Object *)socket,
+ plContext),
+ PKIX_HASHTABLEADDFAILED);
+#endif
+ }
+
+ *pSocket = socket;
+ socket = NULL;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(hostString);
+ PKIX_DECREF(domainString);
+ PKIX_DECREF(socket);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.h
new file mode 100644
index 0000000000..a03ea94d86
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpcertstore.h
@@ -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/. */
+/*
+ * pkix_pl_httpcertstore.h
+ *
+ * HTTPCertstore Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_PL_HTTPCERTSTORE_H
+#define _PKIX_PL_HTTPCERTSTORE_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_HttpCertStoreContextStruct {
+ const SEC_HttpClientFcn *client;
+ SEC_HTTP_SERVER_SESSION serverSession;
+ SEC_HTTP_REQUEST_SESSION requestSession;
+ char *path;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_HttpCertStoreContext_RegisterSelf(void *plContext);
+
+void pkix_pl_HttpCertStore_Shutdown(void *plContext);
+
+PKIX_Error *
+pkix_pl_HttpCertStore_CreateWithAsciiName(
+ PKIX_PL_HttpClient *client,
+ char *locationAscii,
+ PKIX_CertStore **pCertStore,
+ void *plContext);
+
+PKIX_Error *
+pkix_HttpCertStore_FindSocketConnection(
+ PRIntervalTime timeout,
+ char *hostname,
+ PRUint16 portnum,
+ PRErrorCode *pStatus,
+ PKIX_PL_Socket **pSocket,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_HttpCertStore_ProcessCertResponse(
+ PRUint16 responseCode,
+ const char *responseContentType,
+ const char *responseData,
+ PRUint32 responseDataLen,
+ PKIX_List **pCertList,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_HTTPCERTSTORE_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c
new file mode 100644
index 0000000000..f73b95f686
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.c
@@ -0,0 +1,1654 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_httpdefaultclient.c
+ *
+ * HTTPDefaultClient Function Definitions
+ *
+ */
+
+#include "pkix_pl_httpdefaultclient.h"
+
+static void *plContext = NULL;
+
+/*
+ * The interface specification for an http client requires that it register
+ * a function table of type SEC_HttpClientFcn, which is defined as a union
+ * of tables, of which only version 1 is defined at present.
+ *
+ * Note: these functions violate the PKIX calling conventions, in that they
+ * return SECStatus rather than PKIX_Error*, and that they do not provide a
+ * plContext argument. They are implemented here as calls to PKIX functions,
+ * but the plContext value is circularly defined - a true kludge. Its value
+ * is saved at the time of the call to pkix_pl_HttpDefaultClient_Create for
+ * subsequent use, but since that initial call comes from the
+ * pkix_pl_HttpDefaultClient_CreateSessionFcn, it's not really getting saved.
+ */
+static SEC_HttpClientFcnV1 vtable = {
+ pkix_pl_HttpDefaultClient_CreateSessionFcn,
+ pkix_pl_HttpDefaultClient_KeepAliveSessionFcn,
+ pkix_pl_HttpDefaultClient_FreeSessionFcn,
+ pkix_pl_HttpDefaultClient_RequestCreateFcn,
+ pkix_pl_HttpDefaultClient_SetPostDataFcn,
+ pkix_pl_HttpDefaultClient_AddHeaderFcn,
+ pkix_pl_HttpDefaultClient_TrySendAndReceiveFcn,
+ pkix_pl_HttpDefaultClient_CancelFcn,
+ pkix_pl_HttpDefaultClient_FreeFcn
+};
+
+static SEC_HttpClientFcn httpClient;
+
+static const char *eohMarker = "\r\n\r\n";
+static const PKIX_UInt32 eohMarkLen = 4; /* strlen(eohMarker) */
+static const char *crlf = "\r\n";
+static const PKIX_UInt32 crlfLen = 2; /* strlen(crlf) */
+static const char *httpprotocol = "HTTP/";
+static const PKIX_UInt32 httpprotocolLen = 5; /* strlen(httpprotocol) */
+
+
+#define HTTP_UNKNOWN_CONTENT_LENGTH -1
+
+/* --Private-HttpDefaultClient-Functions------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_HttpDefaultClient_HdrCheckComplete
+ * DESCRIPTION:
+ *
+ * This function determines whether the headers in the current receive buffer
+ * in the HttpDefaultClient pointed to by "client" are complete. If so, the
+ * input data is checked for status code, content-type and content-length are
+ * extracted, and the client is set up to read the body of the response.
+ * Otherwise, the client is set up to continue reading header data.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the HttpDefaultClient object. Must be non-NULL.
+ * "bytesRead"
+ * The UInt32 number of bytes received in the latest read.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plCtx"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_HttpDefaultClient_HdrCheckComplete(
+ PKIX_PL_HttpDefaultClient *client,
+ PKIX_UInt32 bytesRead,
+ PKIX_Boolean *pKeepGoing,
+ void *plCtx)
+{
+ PKIX_UInt32 alreadyScanned = 0;
+ PKIX_UInt32 comp = 0;
+ PKIX_UInt32 headerLength = 0;
+ PKIX_Int32 contentLength = HTTP_UNKNOWN_CONTENT_LENGTH;
+ char *eoh = NULL;
+ char *statusLineEnd = NULL;
+ char *space = NULL;
+ char *nextHeader = NULL;
+ const char *httpcode = NULL;
+ char *thisHeaderEnd = NULL;
+ char *value = NULL;
+ char *colon = NULL;
+ char *copy = NULL;
+ char *body = NULL;
+
+ PKIX_ENTER
+ (HTTPDEFAULTCLIENT,
+ "pkix_pl_HttpDefaultClient_HdrCheckComplete");
+ PKIX_NULLCHECK_TWO(client, pKeepGoing);
+
+ *pKeepGoing = PKIX_FALSE;
+
+ /* Does buffer contain end-of-header marker? */
+
+ /* Copy number of scanned bytes into a variable. */
+ alreadyScanned = client->filledupBytes;
+ /*
+ * If this is the initial buffer, we have to scan from the beginning.
+ * If we scanned, failed to find eohMarker, and read some more, we
+ * only have to scan from where we left off.
+ */
+ if (alreadyScanned > eohMarkLen) {
+ /* Back up and restart scanning over a few bytes that were
+ * scanned before */
+ PKIX_UInt32 searchStartPos = alreadyScanned - eohMarkLen;
+ eoh = PL_strnstr(&(client->rcvBuf[searchStartPos]), eohMarker,
+ bytesRead + searchStartPos);
+ } else {
+ /* A search from the beginning of the buffer. */
+ eoh = PL_strnstr(client->rcvBuf, eohMarker, bytesRead);
+ }
+
+ client->filledupBytes += bytesRead;
+
+ if (eoh == NULL) { /* did we see end-of-header? */
+ /* No. Continue to read header data */
+ client->connectStatus = HTTP_RECV_HDR;
+ *pKeepGoing = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /* Yes. Calculate how many bytes in header (not counting eohMarker) */
+ headerLength = (eoh - client->rcvBuf);
+
+ /* allocate space to copy header (and for the NULL terminator) */
+ PKIX_CHECK(PKIX_PL_Malloc(headerLength + 1, (void **)&copy, plCtx),
+ PKIX_MALLOCFAILED);
+
+ /* copy header data before we corrupt it (by storing NULLs) */
+ PORT_Memcpy(copy, client->rcvBuf, headerLength);
+ /* Store the NULL terminator */
+ copy[headerLength] = '\0';
+ client->rcvHeaders = copy;
+
+ /* Did caller want a pointer to header? */
+ if (client->rcv_http_headers != NULL) {
+ /* store pointer for caller */
+ *(client->rcv_http_headers) = copy;
+ }
+
+ /* Check that message status is okay. */
+ statusLineEnd = PL_strnstr(client->rcvBuf, crlf, client->capacity);
+ if (statusLineEnd == NULL) {
+ client->connectStatus = HTTP_ERROR;
+ PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
+ goto cleanup;
+ }
+
+ *statusLineEnd = '\0';
+
+ space = strchr((const char *)client->rcvBuf, ' ');
+ if (space == NULL) {
+ client->connectStatus = HTTP_ERROR;
+ goto cleanup;
+ }
+
+ comp = PORT_Strncasecmp((const char *)client->rcvBuf, httpprotocol,
+ httpprotocolLen);
+ if (comp != 0) {
+ client->connectStatus = HTTP_ERROR;
+ goto cleanup;
+ }
+
+ httpcode = space + 1;
+ space = strchr(httpcode, ' ');
+ if (space == NULL) {
+ client->connectStatus = HTTP_ERROR;
+ goto cleanup;
+ }
+ *space = '\0';
+
+ client->responseCode = atoi(httpcode);
+ if (client->responseCode != 200) {
+ client->connectStatus = HTTP_ERROR;
+ goto cleanup;
+ }
+
+ /* Find the content-type and content-length */
+ nextHeader = statusLineEnd + crlfLen;
+ *eoh = '\0';
+ do {
+ thisHeaderEnd = NULL;
+ value = NULL;
+
+ colon = strchr(nextHeader, ':');
+ if (colon == NULL) {
+ client->connectStatus = HTTP_ERROR;
+ goto cleanup;
+ }
+ *colon = '\0';
+ value = colon + 1;
+ if (*value != ' ') {
+ client->connectStatus = HTTP_ERROR;
+ goto cleanup;
+ }
+ value++;
+ thisHeaderEnd = strstr(value, crlf);
+ if (thisHeaderEnd != NULL) {
+ *thisHeaderEnd = '\0';
+ }
+ comp = PORT_Strcasecmp(nextHeader, "content-type");
+ if (comp == 0) {
+ client->rcvContentType = PORT_Strdup(value);
+ } else {
+ comp = PORT_Strcasecmp(nextHeader, "content-length");
+ if (comp == 0) {
+ contentLength = atoi(value);
+ }
+ }
+ if (thisHeaderEnd != NULL) {
+ nextHeader = thisHeaderEnd + crlfLen;
+ } else {
+ nextHeader = NULL;
+ }
+ } while ((nextHeader != NULL) && (nextHeader < (eoh + crlfLen)));
+
+ /* Did caller provide a pointer to return content-type? */
+ if (client->rcv_http_content_type != NULL) {
+ *(client->rcv_http_content_type) = client->rcvContentType;
+ }
+
+ if (client->rcvContentType == NULL) {
+ client->connectStatus = HTTP_ERROR;
+ goto cleanup;
+ }
+
+ /* How many bytes remain in current buffer, beyond the header? */
+ headerLength += eohMarkLen;
+ client->filledupBytes -= headerLength;
+
+ /*
+ * The headers have passed validation. Now figure out whether the
+ * message is within the caller's size limit (if one was specified).
+ */
+ switch (contentLength) {
+ case 0:
+ client->rcv_http_data_len = 0;
+ client->connectStatus = HTTP_COMPLETE;
+ *pKeepGoing = PKIX_FALSE;
+ break;
+
+ case HTTP_UNKNOWN_CONTENT_LENGTH:
+ /* Unknown contentLength indicator.Will be set by
+ * pkix_pl_HttpDefaultClient_RecvBody whey connection get closed */
+ client->rcv_http_data_len = HTTP_UNKNOWN_CONTENT_LENGTH;
+ contentLength = /* Try to reserve 4K+ buffer */
+ client->filledupBytes + HTTP_DATA_BUFSIZE;
+ if (client->maxResponseLen > 0 &&
+ contentLength > (PKIX_Int32)client->maxResponseLen) {
+ if (client->filledupBytes < client->maxResponseLen) {
+ contentLength = client->maxResponseLen;
+ } else {
+ client->connectStatus = HTTP_ERROR;
+ goto cleanup;
+ }
+ }
+ /* set available number of bytes in the buffer */
+ client->capacity = contentLength;
+ client->connectStatus = HTTP_RECV_BODY;
+ *pKeepGoing = PKIX_TRUE;
+ break;
+
+ default:
+ client->rcv_http_data_len = contentLength;
+ if (client->maxResponseLen > 0 &&
+ (PKIX_Int32)client->maxResponseLen < contentLength) {
+ client->connectStatus = HTTP_ERROR;
+ goto cleanup;
+ }
+
+ /*
+ * Do we have all of the message body, or do we need to read some more?
+ */
+ if ((PKIX_Int32)client->filledupBytes < contentLength) {
+ client->connectStatus = HTTP_RECV_BODY;
+ *pKeepGoing = PKIX_TRUE;
+ } else {
+ client->connectStatus = HTTP_COMPLETE;
+ *pKeepGoing = PKIX_FALSE;
+ }
+ }
+
+ if (contentLength > 0) {
+ /* allocate a buffer of size contentLength for the content */
+ PKIX_CHECK(PKIX_PL_Malloc(contentLength, (void **)&body, plCtx),
+ PKIX_MALLOCFAILED);
+
+ /* copy any remaining bytes in current buffer into new buffer */
+ if (client->filledupBytes > 0) {
+ PORT_Memcpy(body, &(client->rcvBuf[headerLength]),
+ client->filledupBytes);
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Free(client->rcvBuf, plCtx),
+ PKIX_FREEFAILED);
+ client->rcvBuf = body;
+
+cleanup:
+
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_HttpDefaultClient_Create
+ * DESCRIPTION:
+ *
+ * This function creates a new HttpDefaultClient, and stores the result at
+ * "pClient".
+ *
+ * The HttpClient API does not include a plContext argument in its
+ * function calls. Its value at the time of this Create call must be the
+ * same as when the client is invoked.
+ *
+ * PARAMETERS:
+ * "host"
+ * The name of the server with which we hope to exchange messages. Must
+ * be non-NULL.
+ * "portnum"
+ * The port number to be used for our connection to the server.
+ * "pClient"
+ * The address at which the created HttpDefaultClient is to be stored.
+ * Must be non-NULL.
+ * "plCtx"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpDefaultClient Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_HttpDefaultClient_Create(
+ const char *host,
+ PRUint16 portnum,
+ PKIX_PL_HttpDefaultClient **pClient,
+ void *plCtx)
+{
+ PKIX_PL_HttpDefaultClient *client = NULL;
+
+ PKIX_ENTER(HTTPDEFAULTCLIENT, "PKIX_PL_HttpDefaultClient_Create");
+ PKIX_NULLCHECK_TWO(pClient, host);
+
+ /* allocate an HttpDefaultClient */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_HTTPDEFAULTCLIENT_TYPE,
+ sizeof (PKIX_PL_HttpDefaultClient),
+ (PKIX_PL_Object **)&client,
+ plCtx),
+ PKIX_COULDNOTCREATEHTTPDEFAULTCLIENTOBJECT);
+
+ /* Client timeout is overwritten in HttpDefaultClient_RequestCreate
+ * function. Default value will be ignored. */
+ client->timeout = 0;
+ client->connectStatus = HTTP_NOT_CONNECTED;
+ client->portnum = portnum;
+ client->bytesToWrite = 0;
+ client->send_http_data_len = 0;
+ client->rcv_http_data_len = 0;
+ client->capacity = 0;
+ client->filledupBytes = 0;
+ client->responseCode = 0;
+ client->maxResponseLen = 0;
+ client->GETLen = 0;
+ client->POSTLen = 0;
+ client->pRcv_http_data_len = NULL;
+ client->callbackList = NULL;
+ client->GETBuf = NULL;
+ client->POSTBuf = NULL;
+ client->rcvBuf = NULL;
+ /* "host" is a parsing result by CERT_GetURL function that adds
+ * "end of line" to the value. OK to dup the string. */
+ client->host = PORT_Strdup(host);
+ if (!client->host) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ client->path = NULL;
+ client->rcvContentType = NULL;
+ client->rcvHeaders = NULL;
+ client->send_http_method = HTTP_POST_METHOD;
+ client->send_http_content_type = NULL;
+ client->send_http_data = NULL;
+ client->rcv_http_response_code = NULL;
+ client->rcv_http_content_type = NULL;
+ client->rcv_http_headers = NULL;
+ client->rcv_http_data = NULL;
+ client->socket = NULL;
+
+ /*
+ * The HttpClient API does not include a plCtx argument in its
+ * function calls. Save it here.
+ */
+ client->plContext = plCtx;
+
+ *pClient = client;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(client);
+ }
+
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpDefaultClient_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_HttpDefaultClient_Destroy(
+ PKIX_PL_Object *object,
+ void *plCtx)
+{
+ PKIX_PL_HttpDefaultClient *client = NULL;
+
+ PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_HTTPDEFAULTCLIENT_TYPE, plCtx),
+ PKIX_OBJECTNOTANHTTPDEFAULTCLIENT);
+
+ client = (PKIX_PL_HttpDefaultClient *)object;
+
+ if (client->rcvHeaders) {
+ PKIX_PL_Free(client->rcvHeaders, plCtx);
+ client->rcvHeaders = NULL;
+ }
+ if (client->rcvContentType) {
+ PORT_Free(client->rcvContentType);
+ client->rcvContentType = NULL;
+ }
+ if (client->GETBuf != NULL) {
+ PR_smprintf_free(client->GETBuf);
+ client->GETBuf = NULL;
+ }
+ if (client->POSTBuf != NULL) {
+ PKIX_PL_Free(client->POSTBuf, plCtx);
+ client->POSTBuf = NULL;
+ }
+ if (client->rcvBuf != NULL) {
+ PKIX_PL_Free(client->rcvBuf, plCtx);
+ client->rcvBuf = NULL;
+ }
+ if (client->host) {
+ PORT_Free(client->host);
+ client->host = NULL;
+ }
+ if (client->path) {
+ PORT_Free(client->path);
+ client->path = NULL;
+ }
+ PKIX_DECREF(client->socket);
+
+cleanup:
+
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpDefaultClient_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_PL_HTTPDEFAULTCLIENT_TYPE and its related
+ * functions with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_HttpDefaultClient_RegisterSelf(void *plCtx)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry *entry =
+ &systemClasses[PKIX_HTTPDEFAULTCLIENT_TYPE];
+
+ PKIX_ENTER(HTTPDEFAULTCLIENT,
+ "pkix_pl_HttpDefaultClient_RegisterSelf");
+
+ entry->description = "HttpDefaultClient";
+ entry->typeObjectSize = sizeof(PKIX_PL_HttpDefaultClient);
+ entry->destructor = pkix_pl_HttpDefaultClient_Destroy;
+
+ httpClient.version = 1;
+ httpClient.fcnTable.ftable1 = vtable;
+ (void)SEC_RegisterDefaultHttpClient(&httpClient);
+
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+}
+
+/* --Private-HttpDefaultClient-I/O-Functions---------------------------- */
+/*
+ * FUNCTION: pkix_pl_HttpDefaultClient_ConnectContinue
+ * DESCRIPTION:
+ *
+ * This function determines whether a socket Connect initiated earlier for the
+ * HttpDefaultClient "client" has completed, and stores in "pKeepGoing" a flag
+ * indicating whether processing can continue without further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the HttpDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plCtx"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_HttpDefaultClient_ConnectContinue(
+ PKIX_PL_HttpDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plCtx)
+{
+ PRErrorCode status;
+ PKIX_Boolean keepGoing = PKIX_FALSE;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER
+ (HTTPDEFAULTCLIENT,
+ "pkix_pl_HttpDefaultClient_ConnectContinue");
+ PKIX_NULLCHECK_ONE(client);
+
+ callbackList = (PKIX_PL_Socket_Callback *)client->callbackList;
+
+ PKIX_CHECK(callbackList->connectcontinueCallback
+ (client->socket, &status, plCtx),
+ PKIX_SOCKETCONNECTCONTINUEFAILED);
+
+ if (status == 0) {
+ client->connectStatus = HTTP_CONNECTED;
+ keepGoing = PKIX_TRUE;
+ } else if (status != PR_IN_PROGRESS_ERROR) {
+ PKIX_ERROR(PKIX_UNEXPECTEDERRORINESTABLISHINGCONNECTION);
+ }
+
+ *pKeepGoing = keepGoing;
+
+cleanup:
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpDefaultClient_Send
+ * DESCRIPTION:
+ *
+ * This function creates and sends HTTP-protocol headers and, if applicable,
+ * data, for the HttpDefaultClient "client", and stores in "pKeepGoing" a flag
+ * indicating whether processing can continue without further input, and at
+ * "pBytesTransferred" the number of bytes sent.
+ *
+ * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use
+ * and that transmission has not completed.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the HttpDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "pBytesTransferred"
+ * The address at which the number of bytes sent is stored. Must be
+ * non-NULL.
+ * "plCtx"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_HttpDefaultClient_Send(
+ PKIX_PL_HttpDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ PKIX_UInt32 *pBytesTransferred,
+ void *plCtx)
+{
+ PKIX_Int32 bytesWritten = 0;
+ PKIX_Int32 lenToWrite = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+ char *dataToWrite = NULL;
+
+ PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Send");
+ PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred);
+
+ *pKeepGoing = PKIX_FALSE;
+
+ /* Do we have anything waiting to go? */
+ if ((client->GETBuf) || (client->POSTBuf)) {
+
+ if (client->GETBuf) {
+ dataToWrite = client->GETBuf;
+ lenToWrite = client->GETLen;
+ } else {
+ dataToWrite = client->POSTBuf;
+ lenToWrite = client->POSTLen;
+ }
+
+ callbackList = (PKIX_PL_Socket_Callback *)client->callbackList;
+
+ PKIX_CHECK(callbackList->sendCallback
+ (client->socket,
+ dataToWrite,
+ lenToWrite,
+ &bytesWritten,
+ plCtx),
+ PKIX_SOCKETSENDFAILED);
+
+ client->rcvBuf = NULL;
+ client->capacity = 0;
+ client->filledupBytes = 0;
+
+ /*
+ * If the send completed we can proceed to try for the
+ * response. If the send did not complete we will have
+ * to poll for completion later.
+ */
+ if (bytesWritten >= 0) {
+ client->connectStatus = HTTP_RECV_HDR;
+ *pKeepGoing = PKIX_TRUE;
+ } else {
+ client->connectStatus = HTTP_SEND_PENDING;
+ *pKeepGoing = PKIX_FALSE;
+ }
+
+ }
+
+ *pBytesTransferred = bytesWritten;
+
+cleanup:
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpDefaultClient_SendContinue
+ * DESCRIPTION:
+ *
+ * This function determines whether the sending of the HTTP message for the
+ * HttpDefaultClient "client" has completed, and stores in "pKeepGoing" a
+ * flag indicating whether processing can continue without further input, and
+ * at "pBytesTransferred" the number of bytes sent.
+ *
+ * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use
+ * and that transmission has not completed.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the HttpDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "pBytesTransferred"
+ * The address at which the number of bytes sent is stored. Must be
+ * non-NULL.
+ * "plCtx"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_HttpDefaultClient_SendContinue(
+ PKIX_PL_HttpDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ PKIX_UInt32 *pBytesTransferred,
+ void *plCtx)
+{
+ PKIX_Int32 bytesWritten = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_SendContinue");
+ PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred);
+
+ *pKeepGoing = PKIX_FALSE;
+
+ callbackList = (PKIX_PL_Socket_Callback *)client->callbackList;
+
+ PKIX_CHECK(callbackList->pollCallback
+ (client->socket, &bytesWritten, NULL, plCtx),
+ PKIX_SOCKETPOLLFAILED);
+
+ /*
+ * If the send completed we can proceed to try for the
+ * response. If the send did not complete we will have
+ * continue to poll.
+ */
+ if (bytesWritten >= 0) {
+ client->connectStatus = HTTP_RECV_HDR;
+ *pKeepGoing = PKIX_TRUE;
+ }
+
+ *pBytesTransferred = bytesWritten;
+
+cleanup:
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpDefaultClient_RecvHdr
+ * DESCRIPTION:
+ *
+ * This function receives HTTP headers for the HttpDefaultClient "client", and
+ * stores in "pKeepGoing" a flag indicating whether processing can continue
+ * without further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the HttpDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plCtx"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_HttpDefaultClient_RecvHdr(
+ PKIX_PL_HttpDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plCtx)
+{
+ PKIX_UInt32 bytesToRead = 0;
+ PKIX_Int32 bytesRead = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_RecvHdr");
+ PKIX_NULLCHECK_TWO(client, pKeepGoing);
+
+ /*
+ * rcvbuf, capacity, and filledupBytes were
+ * initialized when we wrote the headers. We begin by reading
+ * HTTP_HEADER_BUFSIZE bytes, repeatedly increasing the buffersize and
+ * reading again if necessary, until we have read the end-of-header
+ * marker, "\r\n\r\n", or have reached our maximum.
+ */
+ client->capacity += HTTP_HEADER_BUFSIZE;
+ PKIX_CHECK(PKIX_PL_Realloc
+ (client->rcvBuf,
+ client->capacity,
+ (void **)&(client->rcvBuf),
+ plCtx),
+ PKIX_REALLOCFAILED);
+
+ bytesToRead = client->capacity - client->filledupBytes;
+
+ callbackList = (PKIX_PL_Socket_Callback *)client->callbackList;
+
+ PKIX_CHECK(callbackList->recvCallback
+ (client->socket,
+ (void *)&(client->rcvBuf[client->filledupBytes]),
+ bytesToRead,
+ &bytesRead,
+ plCtx),
+ PKIX_SOCKETRECVFAILED);
+
+ if (bytesRead > 0) {
+ /* client->filledupBytes will be adjusted by
+ * pkix_pl_HttpDefaultClient_HdrCheckComplete */
+ PKIX_CHECK(
+ pkix_pl_HttpDefaultClient_HdrCheckComplete(client, bytesRead,
+ pKeepGoing,
+ plCtx),
+ PKIX_HTTPDEFAULTCLIENTHDRCHECKCOMPLETEFAILED);
+ } else {
+ client->connectStatus = HTTP_RECV_HDR_PENDING;
+ *pKeepGoing = PKIX_FALSE;
+ }
+
+cleanup:
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpDefaultClient_RecvHdrContinue
+ * DESCRIPTION:
+ *
+ * This function determines whether the receiving of the HTTP headers for the
+ * HttpDefaultClient "client" has completed, and stores in "pKeepGoing" a flag
+ * indicating whether processing can continue without further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the HttpDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plCtx"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_HttpDefaultClient_RecvHdrContinue(
+ PKIX_PL_HttpDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plCtx)
+{
+ PKIX_Int32 bytesRead = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER
+ (HTTPDEFAULTCLIENT,
+ "pkix_pl_HttpDefaultClient_RecvHdrContinue");
+ PKIX_NULLCHECK_TWO(client, pKeepGoing);
+
+ callbackList = (PKIX_PL_Socket_Callback *)client->callbackList;
+
+ PKIX_CHECK(callbackList->pollCallback
+ (client->socket, NULL, &bytesRead, plCtx),
+ PKIX_SOCKETPOLLFAILED);
+
+ if (bytesRead > 0) {
+ client->filledupBytes += bytesRead;
+
+ PKIX_CHECK(pkix_pl_HttpDefaultClient_HdrCheckComplete
+ (client, bytesRead, pKeepGoing, plCtx),
+ PKIX_HTTPDEFAULTCLIENTHDRCHECKCOMPLETEFAILED);
+
+ } else {
+
+ *pKeepGoing = PKIX_FALSE;
+
+ }
+
+cleanup:
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpDefaultClient_RecvBody
+ * DESCRIPTION:
+ *
+ * This function processes the contents of the first buffer of a received
+ * HTTP-protocol message for the HttpDefaultClient "client", and stores in
+ * "pKeepGoing" a flag indicating whether processing can continue without
+ * further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the HttpDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plCtx"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_HttpDefaultClient_RecvBody(
+ PKIX_PL_HttpDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plCtx)
+{
+ PKIX_Int32 bytesRead = 0;
+ PKIX_Int32 bytesToRead = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_RecvBody");
+ PKIX_NULLCHECK_TWO(client, pKeepGoing);
+
+ callbackList = (PKIX_PL_Socket_Callback *)client->callbackList;
+
+ if (client->rcv_http_data_len != HTTP_UNKNOWN_CONTENT_LENGTH) {
+ bytesToRead = client->rcv_http_data_len -
+ client->filledupBytes;
+ } else {
+ /* Reading till the EOF. Context length is not known.*/
+ /* Check the buffer capacity: increase and
+ * reallocate if it is low. */
+ int freeBuffSize = client->capacity - client->filledupBytes;
+ if (freeBuffSize < HTTP_MIN_AVAILABLE_BUFFER_SIZE) {
+ /* New length will be consist of available(downloaded) bytes,
+ * plus remaining capacity, plus new expansion. */
+ int currBuffSize = client->capacity;
+ /* Try to increase the buffer by 4K */
+ unsigned int newLength = currBuffSize + HTTP_DATA_BUFSIZE;
+ if (client->maxResponseLen > 0 &&
+ newLength > client->maxResponseLen) {
+ newLength = client->maxResponseLen;
+ }
+ /* Check if we can grow the buffer and report an error if
+ * new size is not larger than the current size of the buffer.*/
+ if (newLength <= client->filledupBytes) {
+ client->rcv_http_data_len = client->filledupBytes;
+ client->connectStatus = HTTP_ERROR;
+ *pKeepGoing = PKIX_FALSE;
+ goto cleanup;
+ }
+ if (client->capacity < newLength) {
+ client->capacity = newLength;
+ PKIX_CHECK(
+ PKIX_PL_Realloc(client->rcvBuf, newLength,
+ (void**)&client->rcvBuf, plCtx),
+ PKIX_REALLOCFAILED);
+ freeBuffSize = client->capacity -
+ client->filledupBytes;
+ }
+ }
+ bytesToRead = freeBuffSize;
+ }
+
+ /* Use poll callback if waiting on non-blocking IO */
+ if (client->connectStatus == HTTP_RECV_BODY_PENDING) {
+ PKIX_CHECK(callbackList->pollCallback
+ (client->socket, NULL, &bytesRead, plCtx),
+ PKIX_SOCKETPOLLFAILED);
+ } else {
+ PKIX_CHECK(callbackList->recvCallback
+ (client->socket,
+ (void *)&(client->rcvBuf[client->filledupBytes]),
+ bytesToRead,
+ &bytesRead,
+ plCtx),
+ PKIX_SOCKETRECVFAILED);
+ }
+
+ /* If bytesRead < 0, an error will be thrown by recvCallback, so
+ * need to handle >= 0 cases. */
+
+ /* bytesRead == 0 - IO was blocked. */
+ if (bytesRead == 0) {
+ client->connectStatus = HTTP_RECV_BODY_PENDING;
+ *pKeepGoing = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /* We got something. Did we get it all? */
+ client->filledupBytes += bytesRead;
+
+ /* continue if not enough bytes read or if complete size of
+ * transfer is unknown */
+ if (bytesToRead > bytesRead ||
+ client->rcv_http_data_len == HTTP_UNKNOWN_CONTENT_LENGTH) {
+ *pKeepGoing = PKIX_TRUE;
+ goto cleanup;
+ }
+ client->connectStatus = HTTP_COMPLETE;
+ *pKeepGoing = PKIX_FALSE;
+
+cleanup:
+ if (pkixErrorResult && pkixErrorResult->errCode ==
+ PKIX_PRRECVREPORTSNETWORKCONNECTIONCLOSED) {
+ if (client->rcv_http_data_len == HTTP_UNKNOWN_CONTENT_LENGTH) {
+ client->rcv_http_data_len = client->filledupBytes;
+ client->connectStatus = HTTP_COMPLETE;
+ *pKeepGoing = PKIX_FALSE;
+ PKIX_DECREF(pkixErrorResult);
+ } else {
+ client->connectStatus = HTTP_ERROR;
+ }
+ }
+
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_HttpDefaultClient_Dispatch
+ * DESCRIPTION:
+ *
+ * This function is the state machine dispatcher for the HttpDefaultClient
+ * pointed to by "client". Results are returned by changes to various fields
+ * in the context.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the HttpDefaultClient object. Must be non-NULL.
+ * "plCtx"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HttpDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_HttpDefaultClient_Dispatch(
+ PKIX_PL_HttpDefaultClient *client,
+ void *plCtx)
+{
+ PKIX_UInt32 bytesTransferred = 0;
+ PKIX_Boolean keepGoing = PKIX_TRUE;
+
+ PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Dispatch");
+ PKIX_NULLCHECK_ONE(client);
+
+ while (keepGoing) {
+ switch (client->connectStatus) {
+ case HTTP_CONNECT_PENDING:
+ PKIX_CHECK(pkix_pl_HttpDefaultClient_ConnectContinue
+ (client, &keepGoing, plCtx),
+ PKIX_HTTPDEFAULTCLIENTCONNECTCONTINUEFAILED);
+ break;
+ case HTTP_CONNECTED:
+ PKIX_CHECK(pkix_pl_HttpDefaultClient_Send
+ (client, &keepGoing, &bytesTransferred, plCtx),
+ PKIX_HTTPDEFAULTCLIENTSENDFAILED);
+ break;
+ case HTTP_SEND_PENDING:
+ PKIX_CHECK(pkix_pl_HttpDefaultClient_SendContinue
+ (client, &keepGoing, &bytesTransferred, plCtx),
+ PKIX_HTTPDEFAULTCLIENTSENDCONTINUEFAILED);
+ break;
+ case HTTP_RECV_HDR:
+ PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvHdr
+ (client, &keepGoing, plCtx),
+ PKIX_HTTPDEFAULTCLIENTRECVHDRFAILED);
+ break;
+ case HTTP_RECV_HDR_PENDING:
+ PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvHdrContinue
+ (client, &keepGoing, plCtx),
+ PKIX_HTTPDEFAULTCLIENTRECVHDRCONTINUEFAILED);
+ break;
+ case HTTP_RECV_BODY:
+ case HTTP_RECV_BODY_PENDING:
+ PKIX_CHECK(pkix_pl_HttpDefaultClient_RecvBody
+ (client, &keepGoing, plCtx),
+ PKIX_HTTPDEFAULTCLIENTRECVBODYFAILED);
+ break;
+ case HTTP_ERROR:
+ case HTTP_COMPLETE:
+ keepGoing = PKIX_FALSE;
+ break;
+ case HTTP_NOT_CONNECTED:
+ default:
+ PKIX_ERROR(PKIX_HTTPDEFAULTCLIENTINILLEGALSTATE);
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+}
+
+/*
+ * --HttpClient vtable functions
+ * See comments in ocspt.h for the function (wrappers) that return SECStatus.
+ * The functions that return PKIX_Error* are the libpkix implementations.
+ */
+
+PKIX_Error *
+pkix_pl_HttpDefaultClient_CreateSession(
+ const char *host,
+ PRUint16 portnum,
+ SEC_HTTP_SERVER_SESSION *pSession,
+ void *plCtx)
+{
+ PKIX_PL_HttpDefaultClient *client = NULL;
+
+ PKIX_ENTER
+ (HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_CreateSession");
+ PKIX_NULLCHECK_TWO(host, pSession);
+
+ PKIX_CHECK(pkix_pl_HttpDefaultClient_Create
+ (host, portnum, &client, plCtx),
+ PKIX_HTTPDEFAULTCLIENTCREATEFAILED);
+
+ *pSession = (SEC_HTTP_SERVER_SESSION)client;
+
+cleanup:
+
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+
+}
+
+PKIX_Error *
+pkix_pl_HttpDefaultClient_KeepAliveSession(
+ SEC_HTTP_SERVER_SESSION session,
+ PRPollDesc **pPollDesc,
+ void *plCtx)
+{
+ PKIX_ENTER
+ (HTTPDEFAULTCLIENT,
+ "pkix_pl_HttpDefaultClient_KeepAliveSession");
+ PKIX_NULLCHECK_TWO(session, pPollDesc);
+
+ PKIX_CHECK(pkix_CheckType
+ ((PKIX_PL_Object *)session,
+ PKIX_HTTPDEFAULTCLIENT_TYPE,
+ plCtx),
+ PKIX_SESSIONNOTANHTTPDEFAULTCLIENT);
+
+ /* XXX Not implemented */
+
+cleanup:
+
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+
+}
+
+PKIX_Error *
+pkix_pl_HttpDefaultClient_RequestCreate(
+ SEC_HTTP_SERVER_SESSION session,
+ const char *http_protocol_variant, /* usually "http" */
+ const char *path_and_query_string,
+ const char *http_request_method,
+ const PRIntervalTime timeout,
+ SEC_HTTP_REQUEST_SESSION *pRequest,
+ void *plCtx)
+{
+ PKIX_PL_HttpDefaultClient *client = NULL;
+ PKIX_PL_Socket *socket = NULL;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+ PRFileDesc *fileDesc = NULL;
+ PRErrorCode status = 0;
+
+ PKIX_ENTER
+ (HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_RequestCreate");
+ PKIX_NULLCHECK_TWO(session, pRequest);
+
+ PKIX_CHECK(pkix_CheckType
+ ((PKIX_PL_Object *)session,
+ PKIX_HTTPDEFAULTCLIENT_TYPE,
+ plCtx),
+ PKIX_SESSIONNOTANHTTPDEFAULTCLIENT);
+
+ client = (PKIX_PL_HttpDefaultClient *)session;
+
+ /* We only know how to do http */
+ if (PORT_Strncasecmp(http_protocol_variant, "http", 4) != 0) {
+ PKIX_ERROR(PKIX_UNRECOGNIZEDPROTOCOLREQUESTED);
+ }
+
+ if (PORT_Strncasecmp(http_request_method, "POST", 4) == 0) {
+ client->send_http_method = HTTP_POST_METHOD;
+ } else if (PORT_Strncasecmp(http_request_method, "GET", 3) == 0) {
+ client->send_http_method = HTTP_GET_METHOD;
+ } else {
+ /* We only know how to do POST and GET */
+ PKIX_ERROR(PKIX_UNRECOGNIZEDREQUESTMETHOD);
+ }
+
+ if (path_and_query_string) {
+ /* "path_and_query_string" is a parsing result by CERT_GetURL
+ * function that adds "end of line" to the value. OK to dup
+ * the string. */
+ client->path = PORT_Strdup(path_and_query_string);
+ if (!client->path) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ }
+
+ client->timeout = timeout;
+
+#if 0
+ PKIX_CHECK(pkix_HttpCertStore_FindSocketConnection
+ (timeout,
+ "variation.red.iplanet.com", /* (char *)client->host, */
+ 2001, /* client->portnum, */
+ &status,
+ &socket,
+ plCtx),
+ PKIX_HTTPCERTSTOREFINDSOCKETCONNECTIONFAILED);
+#else
+ PKIX_CHECK(pkix_HttpCertStore_FindSocketConnection
+ (timeout,
+ (char *)client->host,
+ client->portnum,
+ &status,
+ &socket,
+ plCtx),
+ PKIX_HTTPCERTSTOREFINDSOCKETCONNECTIONFAILED);
+#endif
+
+ client->socket = socket;
+
+ PKIX_CHECK(pkix_pl_Socket_GetCallbackList
+ (socket, &callbackList, plCtx),
+ PKIX_SOCKETGETCALLBACKLISTFAILED);
+
+ client->callbackList = (void *)callbackList;
+
+ PKIX_CHECK(pkix_pl_Socket_GetPRFileDesc
+ (socket, &fileDesc, plCtx),
+ PKIX_SOCKETGETPRFILEDESCFAILED);
+
+ client->pollDesc.fd = fileDesc;
+ client->pollDesc.in_flags = 0;
+ client->pollDesc.out_flags = 0;
+
+ client->send_http_data = NULL;
+ client->send_http_data_len = 0;
+ client->send_http_content_type = NULL;
+
+ client->connectStatus =
+ ((status == 0) ? HTTP_CONNECTED : HTTP_CONNECT_PENDING);
+
+ /* Request object is the same object as Session object */
+ PKIX_INCREF(client);
+ *pRequest = client;
+
+cleanup:
+
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+
+}
+
+PKIX_Error *
+pkix_pl_HttpDefaultClient_SetPostData(
+ SEC_HTTP_REQUEST_SESSION request,
+ const char *http_data,
+ const PRUint32 http_data_len,
+ const char *http_content_type,
+ void *plCtx)
+{
+ PKIX_PL_HttpDefaultClient *client = NULL;
+
+ PKIX_ENTER
+ (HTTPDEFAULTCLIENT,
+ "pkix_pl_HttpDefaultClient_SetPostData");
+ PKIX_NULLCHECK_ONE(request);
+
+ PKIX_CHECK(pkix_CheckType
+ ((PKIX_PL_Object *)request,
+ PKIX_HTTPDEFAULTCLIENT_TYPE,
+ plCtx),
+ PKIX_REQUESTNOTANHTTPDEFAULTCLIENT);
+
+ client = (PKIX_PL_HttpDefaultClient *)request;
+
+ client->send_http_data = http_data;
+ client->send_http_data_len = http_data_len;
+ client->send_http_content_type = http_content_type;
+
+ /* Caller is allowed to give NULL or empty string for content_type */
+ if ((client->send_http_content_type == NULL) ||
+ (*(client->send_http_content_type) == '\0')) {
+ client->send_http_content_type = "application/ocsp-request";
+ }
+
+cleanup:
+
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+
+}
+
+PKIX_Error *
+pkix_pl_HttpDefaultClient_TrySendAndReceive(
+ SEC_HTTP_REQUEST_SESSION request,
+ PRUint16 *http_response_code,
+ const char **http_response_content_type,
+ const char **http_response_headers,
+ const char **http_response_data,
+ PRUint32 *http_response_data_len,
+ PRPollDesc **pPollDesc,
+ SECStatus *pSECReturn,
+ void *plCtx)
+{
+ PKIX_PL_HttpDefaultClient *client = NULL;
+ PKIX_UInt32 postLen = 0;
+ PRPollDesc *pollDesc = NULL;
+ char *sendbuf = NULL;
+ char portstr[16];
+
+ PKIX_ENTER
+ (HTTPDEFAULTCLIENT,
+ "pkix_pl_HttpDefaultClient_TrySendAndReceive");
+
+ PKIX_NULLCHECK_ONE(request);
+
+ PKIX_CHECK(pkix_CheckType
+ ((PKIX_PL_Object *)request,
+ PKIX_HTTPDEFAULTCLIENT_TYPE,
+ plCtx),
+ PKIX_REQUESTNOTANHTTPDEFAULTCLIENT);
+
+ client = (PKIX_PL_HttpDefaultClient *)request;
+
+ if (!pPollDesc && client->timeout == 0) {
+ PKIX_ERROR_FATAL(PKIX_NULLARGUMENT);
+ }
+
+ if (pPollDesc) {
+ pollDesc = *pPollDesc;
+ }
+
+ /* if not continuing from an earlier WOULDBLOCK return... */
+ if (pollDesc == NULL) {
+
+ if (!((client->connectStatus == HTTP_CONNECTED) ||
+ (client->connectStatus == HTTP_CONNECT_PENDING))) {
+ PKIX_ERROR(PKIX_HTTPCLIENTININVALIDSTATE);
+ }
+
+ /* Did caller provide a value for response length? */
+ if (http_response_data_len != NULL) {
+ client->pRcv_http_data_len = http_response_data_len;
+ client->maxResponseLen = *http_response_data_len;
+ }
+
+ client->rcv_http_response_code = http_response_code;
+ client->rcv_http_content_type = http_response_content_type;
+ client->rcv_http_headers = http_response_headers;
+ client->rcv_http_data = http_response_data;
+
+ /* prepare the message */
+ portstr[0] = '\0';
+ if (client->portnum != 80) {
+ PR_snprintf(portstr, sizeof(portstr), ":%d",
+ client->portnum);
+ }
+
+ if (client->send_http_method == HTTP_POST_METHOD) {
+ sendbuf = PR_smprintf
+ ("POST %s HTTP/1.0\r\nHost: %s%s\r\n"
+ "Content-Type: %s\r\nContent-Length: %u\r\n\r\n",
+ client->path,
+ client->host,
+ portstr,
+ client->send_http_content_type,
+ client->send_http_data_len);
+ postLen = PORT_Strlen(sendbuf);
+
+ client->POSTLen = postLen + client->send_http_data_len;
+
+ /* allocate postBuffer big enough for header + data */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (client->POSTLen,
+ (void **)&(client->POSTBuf),
+ plCtx),
+ PKIX_MALLOCFAILED);
+
+ /* copy header into postBuffer */
+ PORT_Memcpy(client->POSTBuf, sendbuf, postLen);
+
+ /* append data after header */
+ PORT_Memcpy(&client->POSTBuf[postLen],
+ client->send_http_data,
+ client->send_http_data_len);
+
+ /* PR_smprintf_free original header buffer */
+ PR_smprintf_free(sendbuf);
+ sendbuf = NULL;
+
+ } else if (client->send_http_method == HTTP_GET_METHOD) {
+ client->GETBuf = PR_smprintf
+ ("GET %s HTTP/1.0\r\nHost: %s%s\r\n\r\n",
+ client->path,
+ client->host,
+ portstr);
+ client->GETLen = PORT_Strlen(client->GETBuf);
+ }
+
+ }
+
+ /* continue according to state */
+ PKIX_CHECK(pkix_pl_HttpDefaultClient_Dispatch(client, plCtx),
+ PKIX_HTTPDEFAULTCLIENTDISPATCHFAILED);
+
+ switch (client->connectStatus) {
+ case HTTP_CONNECT_PENDING:
+ case HTTP_SEND_PENDING:
+ case HTTP_RECV_HDR_PENDING:
+ case HTTP_RECV_BODY_PENDING:
+ pollDesc = &(client->pollDesc);
+ *pSECReturn = SECWouldBlock;
+ break;
+ case HTTP_ERROR:
+ /* Did caller provide a pointer for length? */
+ if (client->pRcv_http_data_len != NULL) {
+ /* Was error "response too big?" */
+ if (client->rcv_http_data_len !=
+ HTTP_UNKNOWN_CONTENT_LENGTH &&
+ client->maxResponseLen >=
+ client->rcv_http_data_len) {
+ /* Yes, report needed space */
+ *(client->pRcv_http_data_len) =
+ client->rcv_http_data_len;
+ } else {
+ /* No, report problem other than size */
+ *(client->pRcv_http_data_len) = 0;
+ }
+ }
+
+ pollDesc = NULL;
+ *pSECReturn = SECFailure;
+ break;
+ case HTTP_COMPLETE:
+ *(client->rcv_http_response_code) =
+ client->responseCode;
+ if (client->pRcv_http_data_len != NULL) {
+ *http_response_data_len =
+ client->rcv_http_data_len;
+ }
+ if (client->rcv_http_data != NULL) {
+ *(client->rcv_http_data) = client->rcvBuf;
+ }
+ pollDesc = NULL;
+ *pSECReturn = SECSuccess;
+ break;
+ case HTTP_NOT_CONNECTED:
+ case HTTP_CONNECTED:
+ case HTTP_RECV_HDR:
+ case HTTP_RECV_BODY:
+ default:
+ pollDesc = NULL;
+ *pSECReturn = SECFailure;
+ PKIX_ERROR(PKIX_HTTPCLIENTININVALIDSTATE);
+ break;
+ }
+
+ if (pPollDesc) {
+ *pPollDesc = pollDesc;
+ }
+
+cleanup:
+ if (sendbuf) {
+ PR_smprintf_free(sendbuf);
+ }
+
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+
+}
+
+PKIX_Error *
+pkix_pl_HttpDefaultClient_Cancel(
+ SEC_HTTP_REQUEST_SESSION request,
+ void *plCtx)
+{
+ PKIX_ENTER(HTTPDEFAULTCLIENT, "pkix_pl_HttpDefaultClient_Cancel");
+ PKIX_NULLCHECK_ONE(request);
+
+ PKIX_CHECK(pkix_CheckType
+ ((PKIX_PL_Object *)request,
+ PKIX_HTTPDEFAULTCLIENT_TYPE,
+ plCtx),
+ PKIX_REQUESTNOTANHTTPDEFAULTCLIENT);
+
+ /* XXX Not implemented */
+
+cleanup:
+
+ PKIX_RETURN(HTTPDEFAULTCLIENT);
+
+}
+
+SECStatus
+pkix_pl_HttpDefaultClient_CreateSessionFcn(
+ const char *host,
+ PRUint16 portnum,
+ SEC_HTTP_SERVER_SESSION *pSession)
+{
+ PKIX_Error *err = pkix_pl_HttpDefaultClient_CreateSession
+ (host, portnum, pSession, plContext);
+
+ if (err) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+pkix_pl_HttpDefaultClient_KeepAliveSessionFcn(
+ SEC_HTTP_SERVER_SESSION session,
+ PRPollDesc **pPollDesc)
+{
+ PKIX_Error *err = pkix_pl_HttpDefaultClient_KeepAliveSession
+ (session, pPollDesc, plContext);
+
+ if (err) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+pkix_pl_HttpDefaultClient_FreeSessionFcn(
+ SEC_HTTP_SERVER_SESSION session)
+{
+ PKIX_Error *err =
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(session), plContext);
+
+ if (err) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+pkix_pl_HttpDefaultClient_RequestCreateFcn(
+ SEC_HTTP_SERVER_SESSION session,
+ const char *http_protocol_variant, /* usually "http" */
+ const char *path_and_query_string,
+ const char *http_request_method,
+ const PRIntervalTime timeout,
+ SEC_HTTP_REQUEST_SESSION *pRequest)
+{
+ PKIX_Error *err = pkix_pl_HttpDefaultClient_RequestCreate
+ (session,
+ http_protocol_variant,
+ path_and_query_string,
+ http_request_method,
+ timeout,
+ pRequest,
+ plContext);
+
+ if (err) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+pkix_pl_HttpDefaultClient_SetPostDataFcn(
+ SEC_HTTP_REQUEST_SESSION request,
+ const char *http_data,
+ const PRUint32 http_data_len,
+ const char *http_content_type)
+{
+ PKIX_Error *err =
+ pkix_pl_HttpDefaultClient_SetPostData(request, http_data,
+ http_data_len,
+ http_content_type,
+ plContext);
+ if (err) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+pkix_pl_HttpDefaultClient_AddHeaderFcn(
+ SEC_HTTP_REQUEST_SESSION request,
+ const char *http_header_name,
+ const char *http_header_value)
+{
+ /* Not supported */
+ return SECFailure;
+}
+
+SECStatus
+pkix_pl_HttpDefaultClient_TrySendAndReceiveFcn(
+ SEC_HTTP_REQUEST_SESSION request,
+ PRPollDesc **pPollDesc,
+ PRUint16 *http_response_code,
+ const char **http_response_content_type,
+ const char **http_response_headers,
+ const char **http_response_data,
+ PRUint32 *http_response_data_len)
+{
+ SECStatus rv = SECFailure;
+
+ PKIX_Error *err = pkix_pl_HttpDefaultClient_TrySendAndReceive
+ (request,
+ http_response_code,
+ http_response_content_type,
+ http_response_headers,
+ http_response_data,
+ http_response_data_len,
+ pPollDesc,
+ &rv,
+ plContext);
+
+ if (err) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext);
+ return rv;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+pkix_pl_HttpDefaultClient_CancelFcn(
+ SEC_HTTP_REQUEST_SESSION request)
+{
+ PKIX_Error *err = pkix_pl_HttpDefaultClient_Cancel(request, plContext);
+
+ if (err) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+pkix_pl_HttpDefaultClient_FreeFcn(
+ SEC_HTTP_REQUEST_SESSION request)
+{
+ PKIX_Error *err =
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(request), plContext);
+
+ if (err) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)err, plContext);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.h
new file mode 100644
index 0000000000..91916a0ab4
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_httpdefaultclient.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/. */
+/*
+ * pkix_pl_httpdefaultclient.h
+ *
+ * HTTPDefaultClient Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_PL_HTTPDEFAULTCLIENT_H
+#define _PKIX_PL_HTTPDEFAULTCLIENT_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define HTTP_DATA_BUFSIZE 4096
+#define HTTP_HEADER_BUFSIZE 1024
+#define HTTP_MIN_AVAILABLE_BUFFER_SIZE 512
+
+typedef enum {
+ HTTP_NOT_CONNECTED,
+ HTTP_CONNECT_PENDING,
+ HTTP_CONNECTED,
+ HTTP_SEND_PENDING,
+ HTTP_RECV_HDR,
+ HTTP_RECV_HDR_PENDING,
+ HTTP_RECV_BODY,
+ HTTP_RECV_BODY_PENDING,
+ HTTP_COMPLETE,
+ HTTP_ERROR
+} HttpConnectStatus;
+
+typedef enum {
+ HTTP_POST_METHOD,
+ HTTP_GET_METHOD
+} HttpMethod;
+
+struct PKIX_PL_HttpDefaultClientStruct {
+ HttpConnectStatus connectStatus;
+ PRUint16 portnum;
+ PRIntervalTime timeout;
+ PKIX_UInt32 bytesToWrite;
+ PKIX_UInt32 send_http_data_len;
+ PKIX_UInt32 rcv_http_data_len;
+ PKIX_UInt32 capacity;
+ PKIX_UInt32 filledupBytes;
+ PKIX_UInt32 responseCode;
+ PKIX_UInt32 maxResponseLen;
+ PKIX_UInt32 GETLen;
+ PKIX_UInt32 POSTLen;
+ PRUint32 *pRcv_http_data_len;
+ PRPollDesc pollDesc;
+ void *callbackList; /* cast this to (PKIX_PL_Socket_Callback *) */
+ char *GETBuf;
+ char *POSTBuf;
+ char *rcvBuf;
+ char *host;
+ char *path;
+ char *rcvContentType;
+ void *rcvHeaders;
+ HttpMethod send_http_method;
+ const char *send_http_content_type;
+ const char *send_http_data;
+ PRUint16 *rcv_http_response_code;
+ const char **rcv_http_content_type;
+ const char **rcv_http_headers;
+ const char **rcv_http_data;
+ PKIX_PL_Socket *socket;
+ void *plContext;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_HttpDefaultClient_RegisterSelf(void *plContext);
+
+SECStatus
+pkix_pl_HttpDefaultClient_CreateSessionFcn(
+ const char *host,
+ PRUint16 portnum,
+ SEC_HTTP_SERVER_SESSION *pSession);
+
+SECStatus
+pkix_pl_HttpDefaultClient_KeepAliveSessionFcn(
+ SEC_HTTP_SERVER_SESSION session,
+ PRPollDesc **pPollDesc);
+
+SECStatus
+pkix_pl_HttpDefaultClient_FreeSessionFcn(
+ SEC_HTTP_SERVER_SESSION session);
+
+SECStatus
+pkix_pl_HttpDefaultClient_RequestCreateFcn(
+ SEC_HTTP_SERVER_SESSION session,
+ const char *http_protocol_variant, /* usually "http" */
+ const char *path_and_query_string,
+ const char *http_request_method,
+ const PRIntervalTime timeout,
+ SEC_HTTP_REQUEST_SESSION *pRequest);
+
+SECStatus
+pkix_pl_HttpDefaultClient_SetPostDataFcn(
+ SEC_HTTP_REQUEST_SESSION request,
+ const char *http_data,
+ const PRUint32 http_data_len,
+ const char *http_content_type);
+
+SECStatus
+pkix_pl_HttpDefaultClient_AddHeaderFcn(
+ SEC_HTTP_REQUEST_SESSION request,
+ const char *http_header_name,
+ const char *http_header_value);
+
+SECStatus
+pkix_pl_HttpDefaultClient_TrySendAndReceiveFcn(
+ SEC_HTTP_REQUEST_SESSION request,
+ PRPollDesc **pPollDesc,
+ PRUint16 *http_response_code,
+ const char **http_response_content_type,
+ const char **http_response_headers,
+ const char **http_response_data,
+ PRUint32 *http_response_data_len);
+
+SECStatus
+pkix_pl_HttpDefaultClient_CancelFcn(
+ SEC_HTTP_REQUEST_SESSION request);
+
+SECStatus
+pkix_pl_HttpDefaultClient_FreeFcn(
+ SEC_HTTP_REQUEST_SESSION request);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_HTTPDEFAULTCLIENT_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.c
new file mode 100644
index 0000000000..dd32334ab3
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.c
@@ -0,0 +1,1113 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_ldapcertstore.c
+ *
+ * LDAPCertStore Function Definitions
+ *
+ */
+
+/* We can't decode the length of a message without at least this many bytes */
+#define MINIMUM_MSG_LENGTH 5
+
+#include "pkix_pl_ldapcertstore.h"
+
+/* --Private-Ldap-CertStore-Database-Functions----------------------- */
+
+/*
+ * FUNCTION: pkix_pl_LdapCertStore_DecodeCrossCertPair
+ * DESCRIPTION:
+ *
+ * This function decodes a DER-encoded CrossCertPair pointed to by
+ * "responseList" and extracts and decodes the Certificates in that pair,
+ * adding the resulting Certs, if the decoding was successful, to the List
+ * (possibly empty) pointed to by "certList". If none of the objects
+ * can be decoded into a Cert, the List is returned unchanged.
+ *
+ * PARAMETERS:
+ * "derCCPItem"
+ * The address of the SECItem containing the DER representation of the
+ * CrossCertPair. Must be non-NULL.
+ * "certList"
+ * The address of the List to which the decoded Certs are added. May be
+ * empty, but must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapCertStore_DecodeCrossCertPair(
+ SECItem *derCCPItem,
+ PKIX_List *certList,
+ void *plContext)
+{
+ LDAPCertPair certPair = {{ siBuffer, NULL, 0 }, { siBuffer, NULL, 0 }};
+ SECStatus rv = SECFailure;
+
+ PLArenaPool *tempArena = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_DecodeCrossCertPair");
+ PKIX_NULLCHECK_TWO(derCCPItem, certList);
+
+ tempArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!tempArena) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ rv = SEC_ASN1DecodeItem(tempArena, &certPair, PKIX_PL_LDAPCrossCertPairTemplate,
+ derCCPItem);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+
+ if (certPair.forward.data != NULL) {
+
+ PKIX_CHECK(
+ pkix_pl_Cert_CreateToList(&certPair.forward, certList,
+ plContext),
+ PKIX_CERTCREATETOLISTFAILED);
+ }
+
+ if (certPair.reverse.data != NULL) {
+
+ PKIX_CHECK(
+ pkix_pl_Cert_CreateToList(&certPair.reverse, certList,
+ plContext),
+ PKIX_CERTCREATETOLISTFAILED);
+ }
+
+cleanup:
+ if (tempArena) {
+ PORT_FreeArena(tempArena, PR_FALSE);
+ }
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapCertStore_BuildCertList
+ * DESCRIPTION:
+ *
+ * This function takes a List of LdapResponse objects pointed to by
+ * "responseList" and extracts and decodes the Certificates in those responses,
+ * storing the List of those Certificates at "pCerts". If none of the objects
+ * can be decoded into a Cert, the returned List is empty.
+ *
+ * PARAMETERS:
+ * "responseList"
+ * The address of the List of LdapResponses. Must be non-NULL.
+ * "pCerts"
+ * The address at which the result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapCertStore_BuildCertList(
+ PKIX_List *responseList,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ PKIX_UInt32 numResponses = 0;
+ PKIX_UInt32 respIx = 0;
+ LdapAttrMask attrBits = 0;
+ PKIX_PL_LdapResponse *response = NULL;
+ PKIX_List *certList = NULL;
+ LDAPMessage *message = NULL;
+ LDAPSearchResponseEntry *sre = NULL;
+ LDAPSearchResponseAttr **sreAttrArray = NULL;
+ LDAPSearchResponseAttr *sreAttr = NULL;
+ SECItem *attrType = NULL;
+ SECItem **attrVal = NULL;
+ SECItem *derCertItem = NULL;
+
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_BuildCertList");
+ PKIX_NULLCHECK_TWO(responseList, pCerts);
+
+ PKIX_CHECK(PKIX_List_Create(&certList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ /* extract certs from response */
+ PKIX_CHECK(PKIX_List_GetLength
+ (responseList, &numResponses, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (respIx = 0; respIx < numResponses; respIx++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (responseList,
+ respIx,
+ (PKIX_PL_Object **)&response,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_pl_LdapResponse_GetMessage
+ (response, &message, plContext),
+ PKIX_LDAPRESPONSEGETMESSAGEFAILED);
+
+ sre = &(message->protocolOp.op.searchResponseEntryMsg);
+ sreAttrArray = sre->attributes;
+
+ /* Get next element of null-terminated array */
+ sreAttr = *sreAttrArray++;
+ while (sreAttr != NULL) {
+ attrType = &(sreAttr->attrType);
+ PKIX_CHECK(pkix_pl_LdapRequest_AttrTypeToBit
+ (attrType, &attrBits, plContext),
+ PKIX_LDAPREQUESTATTRTYPETOBITFAILED);
+ /* Is this attrVal a Certificate? */
+ if (((LDAPATTR_CACERT | LDAPATTR_USERCERT) &
+ attrBits) == attrBits) {
+ attrVal = sreAttr->val;
+ derCertItem = *attrVal++;
+ while (derCertItem != 0) {
+ /* create a PKIX_PL_Cert from derCert */
+ PKIX_CHECK(pkix_pl_Cert_CreateToList
+ (derCertItem, certList, plContext),
+ PKIX_CERTCREATETOLISTFAILED);
+ derCertItem = *attrVal++;
+ }
+ } else if ((LDAPATTR_CROSSPAIRCERT & attrBits) == attrBits){
+ /* Is this attrVal a CrossPairCertificate? */
+ attrVal = sreAttr->val;
+ derCertItem = *attrVal++;
+ while (derCertItem != 0) {
+ /* create PKIX_PL_Certs from derCert */
+ PKIX_CHECK(pkix_pl_LdapCertStore_DecodeCrossCertPair
+ (derCertItem, certList, plContext),
+ PKIX_LDAPCERTSTOREDECODECROSSCERTPAIRFAILED);
+ derCertItem = *attrVal++;
+ }
+ }
+ sreAttr = *sreAttrArray++;
+ }
+ PKIX_DECREF(response);
+ }
+
+ *pCerts = certList;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(certList);
+ }
+
+ PKIX_DECREF(response);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapCertStore_BuildCrlList
+ * DESCRIPTION:
+ *
+ * This function takes a List of LdapResponse objects pointed to by
+ * "responseList" and extracts and decodes the CRLs in those responses, storing
+ * the List of those CRLs at "pCrls". If none of the objects can be decoded
+ * into a CRL, the returned List is empty.
+ *
+ * PARAMETERS:
+ * "responseList"
+ * The address of the List of LdapResponses. Must be non-NULL.
+ * "pCrls"
+ * The address at which the result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapCertStore_BuildCrlList(
+ PKIX_List *responseList,
+ PKIX_List **pCrls,
+ void *plContext)
+{
+ PKIX_UInt32 numResponses = 0;
+ PKIX_UInt32 respIx = 0;
+ LdapAttrMask attrBits = 0;
+ CERTSignedCrl *nssCrl = NULL;
+ PKIX_PL_LdapResponse *response = NULL;
+ PKIX_List *crlList = NULL;
+ PKIX_PL_CRL *crl = NULL;
+ LDAPMessage *message = NULL;
+ LDAPSearchResponseEntry *sre = NULL;
+ LDAPSearchResponseAttr **sreAttrArray = NULL;
+ LDAPSearchResponseAttr *sreAttr = NULL;
+ SECItem *attrType = NULL;
+ SECItem **attrVal = NULL;
+ SECItem *derCrlCopy = NULL;
+ SECItem *derCrlItem = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_BuildCrlList");
+ PKIX_NULLCHECK_TWO(responseList, pCrls);
+
+ PKIX_CHECK(PKIX_List_Create(&crlList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ /* extract crls from response */
+ PKIX_CHECK(PKIX_List_GetLength
+ (responseList, &numResponses, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (respIx = 0; respIx < numResponses; respIx++) {
+ PKIX_CHECK(PKIX_List_GetItem
+ (responseList,
+ respIx,
+ (PKIX_PL_Object **)&response,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_pl_LdapResponse_GetMessage
+ (response, &message, plContext),
+ PKIX_LDAPRESPONSEGETMESSAGEFAILED);
+
+ sre = &(message->protocolOp.op.searchResponseEntryMsg);
+ sreAttrArray = sre->attributes;
+
+ /* Get next element of null-terminated array */
+ sreAttr = *sreAttrArray++;
+ while (sreAttr != NULL) {
+ attrType = &(sreAttr->attrType);
+ PKIX_CHECK(pkix_pl_LdapRequest_AttrTypeToBit
+ (attrType, &attrBits, plContext),
+ PKIX_LDAPREQUESTATTRTYPETOBITFAILED);
+ /* Is this attrVal a Revocation List? */
+ if (((LDAPATTR_CERTREVLIST | LDAPATTR_AUTHREVLIST) &
+ attrBits) == attrBits) {
+ attrVal = sreAttr->val;
+ derCrlItem = *attrVal++;
+ while (derCrlItem != 0) {
+ /* create a PKIX_PL_Crl from derCrl */
+ derCrlCopy = SECITEM_DupItem(derCrlItem);
+ if (!derCrlCopy) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ /* crl will be based on derCrlCopy, but wont
+ * own the der. */
+ nssCrl =
+ CERT_DecodeDERCrlWithFlags(NULL, derCrlCopy,
+ SEC_CRL_TYPE,
+ CRL_DECODE_DONT_COPY_DER |
+ CRL_DECODE_SKIP_ENTRIES);
+ if (!nssCrl) {
+ SECITEM_FreeItem(derCrlCopy, PKIX_TRUE);
+ continue;
+ }
+ /* pkix crl own the der. */
+ PKIX_CHECK(
+ pkix_pl_CRL_CreateWithSignedCRL(nssCrl,
+ derCrlCopy, NULL, &crl, plContext),
+ PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
+ /* Left control over memory pointed by derCrlCopy and
+ * nssCrl to pkix crl. */
+ derCrlCopy = NULL;
+ nssCrl = NULL;
+ PKIX_CHECK(PKIX_List_AppendItem
+ (crlList, (PKIX_PL_Object *) crl, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(crl);
+ derCrlItem = *attrVal++;
+ }
+ /* Clean up after PKIX_CHECK_ONLY_FATAL */
+ pkixTempErrorReceived = PKIX_FALSE;
+ }
+ sreAttr = *sreAttrArray++;
+ }
+ PKIX_DECREF(response);
+ }
+
+ *pCrls = crlList;
+ crlList = NULL;
+cleanup:
+ if (derCrlCopy) {
+ SECITEM_FreeItem(derCrlCopy, PKIX_TRUE);
+ }
+ if (nssCrl) {
+ SEC_DestroyCrl(nssCrl);
+ }
+ PKIX_DECREF(crl);
+ PKIX_DECREF(crlList);
+ PKIX_DECREF(response);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapCertStore_DestroyAVAList
+ * DESCRIPTION:
+ *
+ * This function frees the space allocated for the components of the
+ * equalFilters that make up the andFilter pointed to by "filter".
+ *
+ * PARAMETERS:
+ * "requestParams"
+ * The address of the andFilter whose components are to be freed. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapCertStore_DestroyAVAList(
+ LDAPNameComponent **nameComponents,
+ void *plContext)
+{
+ LDAPNameComponent **currentNC = NULL;
+ unsigned char *component = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_DestroyAVAList");
+ PKIX_NULLCHECK_ONE(nameComponents);
+
+ /* Set currentNC to point to first AVA pointer */
+ currentNC = nameComponents;
+
+ while ((*currentNC) != NULL) {
+ component = (*currentNC)->attrValue;
+ if (component != NULL) {
+ PORT_Free(component);
+ }
+ currentNC++;
+ }
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapCertStore_MakeNameAVAList
+ * DESCRIPTION:
+ *
+ * This function allocates space from the arena pointed to by "arena" to
+ * construct a filter that will match components of the X500Name pointed to
+ * by "name", and stores the resulting filter at "pFilter".
+ *
+ * "name" is checked for commonName and organizationName components (cn=,
+ * and o=). The component strings are extracted using the family of
+ * CERT_Get* functions, and each must be freed with PORT_Free.
+ *
+ * It is not clear which components should be in a request, so, for now,
+ * we stop adding components after we have found one.
+ *
+ * PARAMETERS:
+ * "arena"
+ * The address of the PLArenaPool used in creating the filter. Must be
+ * non-NULL.
+ * "name"
+ * The address of the X500Name whose components define the desired
+ * matches. Must be non-NULL.
+ * "pList"
+ * The address at which the result is stored.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapCertStore_MakeNameAVAList(
+ PLArenaPool *arena,
+ PKIX_PL_X500Name *subjectName,
+ LDAPNameComponent ***pList,
+ void *plContext)
+{
+ LDAPNameComponent **setOfNameComponents;
+ LDAPNameComponent *currentNameComponent = NULL;
+ PKIX_UInt32 componentsPresent = 0;
+ void *v = NULL;
+ unsigned char *component = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_MakeNameAVAList");
+ PKIX_NULLCHECK_THREE(arena, subjectName, pList);
+
+ /* Increase this if additional components may be extracted */
+#define MAX_NUM_COMPONENTS 3
+
+ /* Space for (MAX_NUM_COMPONENTS + 1) pointers to LDAPNameComponents */
+ PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZAlloc,
+ (arena, (MAX_NUM_COMPONENTS + 1)*sizeof(LDAPNameComponent *)));
+ setOfNameComponents = (LDAPNameComponent **)v;
+
+ /* Space for MAX_NUM_COMPONENTS LDAPNameComponents */
+ PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZNewArray,
+ (arena, LDAPNameComponent, MAX_NUM_COMPONENTS));
+
+ currentNameComponent = (LDAPNameComponent *)v;
+
+ /* Try for commonName */
+ PKIX_CHECK(pkix_pl_X500Name_GetCommonName
+ (subjectName, &component, plContext),
+ PKIX_X500NAMEGETCOMMONNAMEFAILED);
+ if (component) {
+ setOfNameComponents[componentsPresent] = currentNameComponent;
+ currentNameComponent->attrType = (unsigned char *)"cn";
+ currentNameComponent->attrValue = component;
+ componentsPresent++;
+ currentNameComponent++;
+ }
+
+ /*
+ * The LDAP specification says we can send multiple name components
+ * in an "AND" filter, but the LDAP Servers don't seem to be able to
+ * handle such requests. So we'll quit after the cn component.
+ */
+#if 0
+ /* Try for orgName */
+ PKIX_CHECK(pkix_pl_X500Name_GetOrgName
+ (subjectName, &component, plContext),
+ PKIX_X500NAMEGETORGNAMEFAILED);
+ if (component) {
+ setOfNameComponents[componentsPresent] = currentNameComponent;
+ currentNameComponent->attrType = (unsigned char *)"o";
+ currentNameComponent->attrValue = component;
+ componentsPresent++;
+ currentNameComponent++;
+ }
+
+ /* Try for countryName */
+ PKIX_CHECK(pkix_pl_X500Name_GetCountryName
+ (subjectName, &component, plContext),
+ PKIX_X500NAMEGETCOUNTRYNAMEFAILED);
+ if (component) {
+ setOfNameComponents[componentsPresent] = currentNameComponent;
+ currentNameComponent->attrType = (unsigned char *)"c";
+ currentNameComponent->attrValue = component;
+ componentsPresent++;
+ currentNameComponent++;
+ }
+#endif
+
+ setOfNameComponents[componentsPresent] = NULL;
+
+ *pList = setOfNameComponents;
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+
+}
+
+#if 0
+/*
+ * FUNCTION: pkix_pl_LdapCertstore_ConvertCertResponses
+ * DESCRIPTION:
+ *
+ * This function processes the List of LDAPResponses pointed to by "responses"
+ * into a List of resulting Certs, storing the result at "pCerts". If there
+ * are no responses converted successfully, a NULL may be stored.
+ *
+ * PARAMETERS:
+ * "responses"
+ * The LDAPResponses whose contents are to be converted. Must be non-NULL.
+ * "pCerts"
+ * Address at which the returned List is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapCertStore_ConvertCertResponses(
+ PKIX_List *responses,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ PKIX_List *unfiltered = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_ConvertCertResponses");
+ PKIX_NULLCHECK_TWO(responses, pCerts);
+
+ /*
+ * We have a List of LdapResponse objects that have to be
+ * turned into Certs.
+ */
+ PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList
+ (responses, &unfiltered, plContext),
+ PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED);
+
+ *pCerts = unfiltered;
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+}
+#endif
+
+/*
+ * FUNCTION: pkix_pl_LdapCertStore_GetCert
+ * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h)
+ */
+PKIX_Error *
+pkix_pl_LdapCertStore_GetCert(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ PKIX_VerifyNode *verifyNode,
+ void **pNBIOContext,
+ PKIX_List **pCertList,
+ void *plContext)
+{
+ PLArenaPool *requestArena = NULL;
+ LDAPRequestParams requestParams;
+ void *pollDesc = NULL;
+ PKIX_Int32 minPathLen = 0;
+ PKIX_Boolean cacheFlag = PKIX_FALSE;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_LdapCertStoreContext *lcs = NULL;
+ PKIX_List *responses = NULL;
+ PKIX_List *unfilteredCerts = NULL;
+ PKIX_List *filteredCerts = NULL;
+ PKIX_PL_X500Name *subjectName = 0;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCert");
+ PKIX_NULLCHECK_THREE(store, selector, pCertList);
+
+ requestParams.baseObject = "c=US";
+ requestParams.scope = WHOLE_SUBTREE;
+ requestParams.derefAliases = NEVER_DEREF;
+ requestParams.sizeLimit = 0;
+ requestParams.timeLimit = 0;
+
+ /* Prepare elements for request filter */
+
+ /*
+ * Get a short-lived arena. We'll be done with this space once
+ * the request is encoded.
+ */
+ requestArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!requestArena) {
+ PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
+ (selector, &params, plContext),
+ PKIX_CERTSELECTORGETCOMCERTSELPARAMSFAILED);
+
+ /*
+ * If we have the subject name for the desired subject,
+ * ask the server for Certs with that subject.
+ */
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
+ (params, &subjectName, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetBasicConstraints
+ (params, &minPathLen, plContext),
+ PKIX_COMCERTSELPARAMSGETBASICCONSTRAINTSFAILED);
+
+ if (subjectName) {
+ PKIX_CHECK(pkix_pl_LdapCertStore_MakeNameAVAList
+ (requestArena,
+ subjectName,
+ &(requestParams.nc),
+ plContext),
+ PKIX_LDAPCERTSTOREMAKENAMEAVALISTFAILED);
+
+ if (*requestParams.nc == NULL) {
+ /*
+ * The subjectName may not include any components
+ * that we know how to encode. We do not return
+ * an error, because the caller did not necessarily
+ * do anything wrong, but we return an empty List.
+ */
+ PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena,
+ (requestArena, PR_FALSE));
+
+ PKIX_CHECK(PKIX_List_Create(&filteredCerts, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (filteredCerts, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pNBIOContext = NULL;
+ *pCertList = filteredCerts;
+ filteredCerts = NULL;
+ goto cleanup;
+ }
+ } else {
+ PKIX_ERROR(PKIX_INSUFFICIENTCRITERIAFORCERTQUERY);
+ }
+
+ /* Prepare attribute field of request */
+
+ requestParams.attributes = 0;
+
+ if (minPathLen < 0) {
+ requestParams.attributes |= LDAPATTR_USERCERT;
+ }
+
+ if (minPathLen > -2) {
+ requestParams.attributes |=
+ LDAPATTR_CACERT | LDAPATTR_CROSSPAIRCERT;
+ }
+
+ /* All request fields are done */
+
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
+ (store, (PKIX_PL_Object **)&lcs, plContext),
+ PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
+
+ PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest
+ ((PKIX_PL_LdapClient *)lcs,
+ &requestParams,
+ &pollDesc,
+ &responses,
+ plContext),
+ PKIX_LDAPCLIENTINITIATEREQUESTFAILED);
+
+ PKIX_CHECK(pkix_pl_LdapCertStore_DestroyAVAList
+ (requestParams.nc, plContext),
+ PKIX_LDAPCERTSTOREDESTROYAVALISTFAILED);
+
+ if (requestArena) {
+ PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena,
+ (requestArena, PR_FALSE));
+ requestArena = NULL;
+ }
+
+ if (pollDesc != NULL) {
+ /* client is waiting for non-blocking I/O to complete */
+ *pNBIOContext = (void *)pollDesc;
+ *pCertList = NULL;
+ goto cleanup;
+ }
+ /* LdapClient has given us a response! */
+
+ if (responses) {
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag
+ (store, &cacheFlag, plContext),
+ PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED);
+
+ PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList
+ (responses, &unfilteredCerts, plContext),
+ PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Select
+ (selector, unfilteredCerts, &filteredCerts, plContext),
+ PKIX_CERTSELECTORSELECTFAILED);
+ }
+
+ *pNBIOContext = NULL;
+ *pCertList = filteredCerts;
+ filteredCerts = NULL;
+
+cleanup:
+
+ PKIX_DECREF(params);
+ PKIX_DECREF(subjectName);
+ PKIX_DECREF(responses);
+ PKIX_DECREF(unfilteredCerts);
+ PKIX_DECREF(filteredCerts);
+ PKIX_DECREF(lcs);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapCertStore_GetCertContinue
+ * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h)
+ */
+PKIX_Error *
+pkix_pl_LdapCertStore_GetCertContinue(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ PKIX_VerifyNode *verifyNode,
+ void **pNBIOContext,
+ PKIX_List **pCertList,
+ void *plContext)
+{
+ PKIX_Boolean cacheFlag = PKIX_FALSE;
+ PKIX_PL_LdapCertStoreContext *lcs = NULL;
+ void *pollDesc = NULL;
+ PKIX_List *responses = NULL;
+ PKIX_List *unfilteredCerts = NULL;
+ PKIX_List *filteredCerts = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCertContinue");
+ PKIX_NULLCHECK_THREE(store, selector, pCertList);
+
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
+ (store, (PKIX_PL_Object **)&lcs, plContext),
+ PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
+
+ PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest
+ ((PKIX_PL_LdapClient *)lcs, &pollDesc, &responses, plContext),
+ PKIX_LDAPCLIENTRESUMEREQUESTFAILED);
+
+ if (pollDesc != NULL) {
+ /* client is waiting for non-blocking I/O to complete */
+ *pNBIOContext = (void *)pollDesc;
+ *pCertList = NULL;
+ goto cleanup;
+ }
+ /* LdapClient has given us a response! */
+
+ if (responses) {
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag
+ (store, &cacheFlag, plContext),
+ PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED);
+
+ PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList
+ (responses, &unfilteredCerts, plContext),
+ PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED);
+
+ PKIX_CHECK(pkix_CertSelector_Select
+ (selector, unfilteredCerts, &filteredCerts, plContext),
+ PKIX_CERTSELECTORSELECTFAILED);
+ }
+
+ *pNBIOContext = NULL;
+ *pCertList = filteredCerts;
+
+cleanup:
+
+ PKIX_DECREF(responses);
+ PKIX_DECREF(unfilteredCerts);
+ PKIX_DECREF(lcs);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapCertStore_GetCRL
+ * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h)
+ */
+PKIX_Error *
+pkix_pl_LdapCertStore_GetCRL(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrlList,
+ void *plContext)
+{
+ LDAPRequestParams requestParams;
+ void *pollDesc = NULL;
+ PLArenaPool *requestArena = NULL;
+ PKIX_UInt32 numNames = 0;
+ PKIX_UInt32 thisName = 0;
+ PKIX_PL_CRL *candidate = NULL;
+ PKIX_List *responses = NULL;
+ PKIX_List *issuerNames = NULL;
+ PKIX_List *filteredCRLs = NULL;
+ PKIX_List *unfilteredCRLs = NULL;
+ PKIX_PL_X500Name *issuer = NULL;
+ PKIX_PL_LdapCertStoreContext *lcs = NULL;
+ PKIX_ComCRLSelParams *params = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCRL");
+ PKIX_NULLCHECK_THREE(store, selector, pCrlList);
+
+ requestParams.baseObject = "c=US";
+ requestParams.scope = WHOLE_SUBTREE;
+ requestParams.derefAliases = NEVER_DEREF;
+ requestParams.sizeLimit = 0;
+ requestParams.timeLimit = 0;
+ requestParams.attributes = LDAPATTR_CERTREVLIST | LDAPATTR_AUTHREVLIST;
+ /* Prepare elements for request filter */
+
+ /* XXX Place CRLDP code here. Handle the case when */
+ /* RFC 5280. Paragraph: 4.2.1.13: */
+ /* If the distributionPoint field contains a directoryName, the entry */
+ /* for that directoryName contains the current CRL for the associated */
+ /* reasons and the CRL is issued by the associated cRLIssuer. The CRL */
+ /* may be stored in either the certificateRevocationList or */
+ /* authorityRevocationList attribute. The CRL is to be obtained by the */
+ /* application from whatever directory server is locally configured. */
+ /* The protocol the application uses to access the directory (e.g., DAP */
+ /* or LDAP) is a local matter. */
+
+
+
+ /*
+ * Get a short-lived arena. We'll be done with this space once
+ * the request is encoded.
+ */
+ PKIX_PL_NSSCALLRV
+ (CERTSTORE, requestArena, PORT_NewArena, (DER_DEFAULT_CHUNKSIZE));
+
+ if (!requestArena) {
+ PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CHECK(PKIX_CRLSelector_GetCommonCRLSelectorParams
+ (selector, &params, plContext),
+ PKIX_CRLSELECTORGETCOMCERTSELPARAMSFAILED);
+
+ PKIX_CHECK(PKIX_ComCRLSelParams_GetIssuerNames
+ (params, &issuerNames, plContext),
+ PKIX_COMCRLSELPARAMSGETISSUERNAMESFAILED);
+
+ /*
+ * The specification for PKIX_ComCRLSelParams_GetIssuerNames in
+ * pkix_crlsel.h says that if the criterion is not set we get a null
+ * pointer. If we get an empty List the criterion is impossible to
+ * meet ("must match at least one of the names in the List").
+ */
+ if (issuerNames) {
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (issuerNames, &numNames, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ if (numNames > 0) {
+ /*
+ * LDAP Servers don't seem to be able to handle
+ * requests with more than more than one name.
+ * So only use first name.
+ */
+ PKIX_CHECK(PKIX_List_GetItem
+ (issuerNames,
+ thisName,
+ (PKIX_PL_Object **)&issuer,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK
+ (pkix_pl_LdapCertStore_MakeNameAVAList
+ (requestArena,
+ issuer,
+ &(requestParams.nc),
+ plContext),
+ PKIX_LDAPCERTSTOREMAKENAMEAVALISTFAILED);
+
+ PKIX_DECREF(issuer);
+
+ if (*requestParams.nc == NULL) {
+ /*
+ * The issuer may not include any
+ * components that we know how to
+ * encode. We do not return an error,
+ * because the caller did not
+ * necessarily do anything wrong, but
+ * we return an empty List.
+ */
+ PKIX_PL_NSSCALL
+ (CERTSTORE, PORT_FreeArena,
+ (requestArena, PR_FALSE));
+
+ PKIX_CHECK(PKIX_List_Create
+ (&filteredCRLs, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (filteredCRLs, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pNBIOContext = NULL;
+ *pCrlList = filteredCRLs;
+ goto cleanup;
+ }
+ } else {
+ PKIX_ERROR(PKIX_IMPOSSIBLECRITERIONFORCRLQUERY);
+ }
+ } else {
+ PKIX_ERROR(PKIX_IMPOSSIBLECRITERIONFORCRLQUERY);
+ }
+
+ /* All request fields are done */
+
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
+ (store, (PKIX_PL_Object **)&lcs, plContext),
+ PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
+
+ PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest
+ ((PKIX_PL_LdapClient *)lcs,
+ &requestParams,
+ &pollDesc,
+ &responses,
+ plContext),
+ PKIX_LDAPCLIENTINITIATEREQUESTFAILED);
+
+ PKIX_CHECK(pkix_pl_LdapCertStore_DestroyAVAList
+ (requestParams.nc, plContext),
+ PKIX_LDAPCERTSTOREDESTROYAVALISTFAILED);
+
+ if (requestArena) {
+ PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena,
+ (requestArena, PR_FALSE));
+ }
+
+ if (pollDesc != NULL) {
+ /* client is waiting for non-blocking I/O to complete */
+ *pNBIOContext = (void *)pollDesc;
+ *pCrlList = NULL;
+ goto cleanup;
+ }
+ /* client has finished! */
+
+ if (responses) {
+
+ /*
+ * We have a List of LdapResponse objects that still have to be
+ * turned into Crls.
+ */
+ PKIX_CHECK(pkix_pl_LdapCertStore_BuildCrlList
+ (responses, &unfilteredCRLs, plContext),
+ PKIX_LDAPCERTSTOREBUILDCRLLISTFAILED);
+
+ PKIX_CHECK(pkix_CRLSelector_Select
+ (selector, unfilteredCRLs, &filteredCRLs, plContext),
+ PKIX_CRLSELECTORSELECTFAILED);
+
+ }
+
+ /* Don't throw away the list if one CRL was bad! */
+ pkixTempErrorReceived = PKIX_FALSE;
+
+ *pNBIOContext = NULL;
+ *pCrlList = filteredCRLs;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(filteredCRLs);
+ }
+
+ PKIX_DECREF(params);
+ PKIX_DECREF(issuerNames);
+ PKIX_DECREF(issuer);
+ PKIX_DECREF(candidate);
+ PKIX_DECREF(responses);
+ PKIX_DECREF(unfilteredCRLs);
+ PKIX_DECREF(lcs);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapCertStore_GetCRLContinue
+ * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h)
+ */
+PKIX_Error *
+pkix_pl_LdapCertStore_GetCRLContinue(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrlList,
+ void *plContext)
+{
+ void *nbio = NULL;
+ PKIX_PL_CRL *candidate = NULL;
+ PKIX_List *responses = NULL;
+ PKIX_PL_LdapCertStoreContext *lcs = NULL;
+ PKIX_List *filteredCRLs = NULL;
+ PKIX_List *unfilteredCRLs = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCRLContinue");
+ PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCrlList);
+
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
+ (store, (PKIX_PL_Object **)&lcs, plContext),
+ PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
+
+ PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest
+ ((PKIX_PL_LdapClient *)lcs, &nbio, &responses, plContext),
+ PKIX_LDAPCLIENTRESUMEREQUESTFAILED);
+
+ if (nbio != NULL) {
+ /* client is waiting for non-blocking I/O to complete */
+ *pNBIOContext = (void *)nbio;
+ *pCrlList = NULL;
+ goto cleanup;
+ }
+ /* client has finished! */
+
+ if (responses) {
+
+ /*
+ * We have a List of LdapResponse objects that still have to be
+ * turned into Crls.
+ */
+ PKIX_CHECK(pkix_pl_LdapCertStore_BuildCrlList
+ (responses, &unfilteredCRLs, plContext),
+ PKIX_LDAPCERTSTOREBUILDCRLLISTFAILED);
+
+ PKIX_CHECK(pkix_CRLSelector_Select
+ (selector, unfilteredCRLs, &filteredCRLs, plContext),
+ PKIX_CRLSELECTORSELECTFAILED);
+
+ PKIX_CHECK(PKIX_List_SetImmutable(filteredCRLs, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ }
+
+ /* Don't throw away the list if one CRL was bad! */
+ pkixTempErrorReceived = PKIX_FALSE;
+
+ *pCrlList = filteredCRLs;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(filteredCRLs);
+ }
+
+ PKIX_DECREF(candidate);
+ PKIX_DECREF(responses);
+ PKIX_DECREF(unfilteredCRLs);
+ PKIX_DECREF(lcs);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/* --Public-LdapCertStore-Functions----------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_LdapCertStore_Create
+ * (see comments in pkix_samples_modules.h)
+ */
+PKIX_Error *
+PKIX_PL_LdapCertStore_Create(
+ PKIX_PL_LdapClient *client,
+ PKIX_CertStore **pCertStore,
+ void *plContext)
+{
+ PKIX_CertStore *certStore = NULL;
+
+ PKIX_ENTER(CERTSTORE, "PKIX_PL_LdapCertStore_Create");
+ PKIX_NULLCHECK_TWO(client, pCertStore);
+
+ PKIX_CHECK(PKIX_CertStore_Create
+ (pkix_pl_LdapCertStore_GetCert,
+ pkix_pl_LdapCertStore_GetCRL,
+ pkix_pl_LdapCertStore_GetCertContinue,
+ pkix_pl_LdapCertStore_GetCRLContinue,
+ NULL, /* don't support trust */
+ NULL, /* can not store crls */
+ NULL, /* can not do revocation check */
+ (PKIX_PL_Object *)client,
+ PKIX_TRUE, /* cache flag */
+ PKIX_FALSE, /* not local */
+ &certStore,
+ plContext),
+ PKIX_CERTSTORECREATEFAILED);
+
+ *pCertStore = certStore;
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.h
new file mode 100644
index 0000000000..5bbe5385ca
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapcertstore.h
@@ -0,0 +1,75 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_ldapcertstore.h
+ *
+ * LDAPCertstore Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_PL_LDAPCERTSTORE_H
+#define _PKIX_PL_LDAPCERTSTORE_H
+
+#include "pkix_pl_ldapt.h"
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * At the time of this version, there are unresolved questions about the LDAP
+ * protocol. Although RFC1777 describes a BIND and UNBIND message, it is not
+ * clear whether they are appropriate to this application. We have tested only
+ * using servers that do not expect authentication, and that reject BIND
+ * messages. It is not clear what values might be appropriate for the bindname
+ * and authentication fields, which are currently implemented as char strings
+ * supplied by the caller. (If this changes, the API and possibly the templates
+ * will have to change.) Therefore the CertStore_Create API contains a BindAPI
+ * structure, a union, which will have to be revised and extended when this
+ * area of the protocol is better understood.
+ *
+ * It is further assumed that a given LdapCertStore will connect only to a
+ * single server, and that the creation of the socket will initiate the
+ * CONNECT. Therefore the LdapCertStore handles only the case of continuing
+ * the connection, if nonblocking I/O is being used.
+ */
+
+typedef enum {
+ LDAP_CONNECT_PENDING,
+ LDAP_CONNECTED,
+ LDAP_BIND_PENDING,
+ LDAP_BIND_RESPONSE,
+ LDAP_BIND_RESPONSE_PENDING,
+ LDAP_BOUND,
+ LDAP_SEND_PENDING,
+ LDAP_RECV,
+ LDAP_RECV_PENDING,
+ LDAP_RECV_INITIAL,
+ LDAP_RECV_NONINITIAL,
+ LDAP_ABANDON_PENDING
+} LDAPConnectStatus;
+
+#define LDAP_CACHEBUCKETS 128
+#define RCVBUFSIZE 512
+
+struct PKIX_PL_LdapCertStoreContext {
+ PKIX_PL_LdapClient *client;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_LdapCertStoreContext_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_LdapCertStore_BuildCertList(
+ PKIX_List *responseList,
+ PKIX_List **pCerts,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_LDAPCERTSTORE_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.c
new file mode 100644
index 0000000000..9b6f8d688d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.c
@@ -0,0 +1,2494 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_ldapdefaultclient.c
+ *
+ * LDAPDefaultClient Function Definitions
+ *
+ */
+
+/* We can't decode the length of a message without at least this many bytes */
+#define MINIMUM_MSG_LENGTH 5
+
+#include "pkix_pl_ldapdefaultclient.h"
+
+/* --Private-LdapDefaultClient-Message-Building-Functions---------------- */
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_MakeBind
+ * DESCRIPTION:
+ *
+ * This function creates and encodes a Bind message, using the arena pointed
+ * to by "arena", the version number contained in "versionData", the
+ * LDAPBindAPI pointed to by "bindAPI", and the messageID contained in
+ * "msgNum", and stores a pointer to the encoded string at "pBindMsg".
+ *
+ * See pkix_pl_ldaptemplates.c for the ASN.1 description of a Bind message.
+ *
+ * This code is not used if the DefaultClient was created with a NULL pointer
+ * supplied for the LDAPBindAPI structure. (Bind and Unbind do not seem to be
+ * expected for anonymous Search requests.)
+ *
+ * PARAMETERS:
+ * "arena"
+ * The address of the PLArenaPool used in encoding the message. Must be
+ * non-NULL.
+ * "versionData"
+ * The Int32 containing the version number to be encoded in the Bind
+ * message.
+ * "bindAPI"
+ * The address of the LDAPBindAPI to be encoded in the Bind message. Must
+ * be non-NULL.
+ * "msgNum"
+ * The Int32 containing the MessageID to be encoded in the Bind message.
+ * "pBindMsg"
+ * The address at which the encoded Bind message will be stored. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_MakeBind(
+ PLArenaPool *arena,
+ PKIX_Int32 versionData,
+ LDAPBindAPI *bindAPI,
+ PKIX_UInt32 msgNum,
+ SECItem **pBindMsg,
+ void *plContext)
+{
+ LDAPMessage msg;
+ char version = '\0';
+ SECItem *encoded = NULL;
+ PKIX_UInt32 len = 0;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_MakeBind");
+ PKIX_NULLCHECK_TWO(arena, pBindMsg);
+
+ PKIX_PL_NSSCALL(LDAPDEFAULTCLIENT, PORT_Memset,
+ (&msg, 0, sizeof (LDAPMessage)));
+
+ version = (char)versionData;
+
+ msg.messageID.type = siUnsignedInteger;
+ msg.messageID.data = (void*)&msgNum;
+ msg.messageID.len = sizeof (msgNum);
+
+ msg.protocolOp.selector = LDAP_BIND_TYPE;
+
+ msg.protocolOp.op.bindMsg.version.type = siUnsignedInteger;
+ msg.protocolOp.op.bindMsg.version.data = (void *)&version;
+ msg.protocolOp.op.bindMsg.version.len = sizeof (char);
+
+ /*
+ * XXX At present we only know how to handle anonymous requests (no
+ * authentication), and we are guessing how to do simple authentication.
+ * This section will need to be revised and extended when other
+ * authentication is needed.
+ */
+ if (bindAPI->selector == SIMPLE_AUTH) {
+ msg.protocolOp.op.bindMsg.bindName.type = siAsciiString;
+ msg.protocolOp.op.bindMsg.bindName.data =
+ (void *)bindAPI->chooser.simple.bindName;
+ len = PL_strlen(bindAPI->chooser.simple.bindName);
+ msg.protocolOp.op.bindMsg.bindName.len = len;
+
+ msg.protocolOp.op.bindMsg.authentication.type = siAsciiString;
+ msg.protocolOp.op.bindMsg.authentication.data =
+ (void *)bindAPI->chooser.simple.authentication;
+ len = PL_strlen(bindAPI->chooser.simple.authentication);
+ msg.protocolOp.op.bindMsg.authentication.len = len;
+ }
+
+ PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, encoded, SEC_ASN1EncodeItem,
+ (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate));
+ if (!encoded) {
+ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
+ }
+
+ *pBindMsg = encoded;
+cleanup:
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_MakeUnbind
+ * DESCRIPTION:
+ *
+ * This function creates and encodes a Unbind message, using the arena pointed
+ * to by "arena" and the messageID contained in "msgNum", and stores a pointer
+ * to the encoded string at "pUnbindMsg".
+ *
+ * See pkix_pl_ldaptemplates.c for the ASN.1 description of an Unbind message.
+ *
+ * This code is not used if the DefaultClient was created with a NULL pointer
+ * supplied for the LDAPBindAPI structure. (Bind and Unbind do not seem to be
+ * expected for anonymous Search requests.)
+ *
+ * PARAMETERS:
+ * "arena"
+ * The address of the PLArenaPool used in encoding the message. Must be
+ * non-NULL.
+ * "msgNum"
+ * The Int32 containing the MessageID to be encoded in the Unbind message.
+ * "pUnbindMsg"
+ * The address at which the encoded Unbind message will be stored. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_MakeUnbind(
+ PLArenaPool *arena,
+ PKIX_UInt32 msgNum,
+ SECItem **pUnbindMsg,
+ void *plContext)
+{
+ LDAPMessage msg;
+ SECItem *encoded = NULL;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_MakeUnbind");
+ PKIX_NULLCHECK_TWO(arena, pUnbindMsg);
+
+ PKIX_PL_NSSCALL(LDAPDEFAULTCLIENT, PORT_Memset,
+ (&msg, 0, sizeof (LDAPMessage)));
+
+ msg.messageID.type = siUnsignedInteger;
+ msg.messageID.data = (void*)&msgNum;
+ msg.messageID.len = sizeof (msgNum);
+
+ msg.protocolOp.selector = LDAP_UNBIND_TYPE;
+
+ msg.protocolOp.op.unbindMsg.dummy.type = siBuffer;
+ msg.protocolOp.op.unbindMsg.dummy.data = NULL;
+ msg.protocolOp.op.unbindMsg.dummy.len = 0;
+
+ PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, encoded, SEC_ASN1EncodeItem,
+ (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate));
+ if (!encoded) {
+ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
+ }
+
+ *pUnbindMsg = encoded;
+cleanup:
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_MakeAbandon
+ * DESCRIPTION:
+ *
+ * This function creates and encodes a Abandon message, using the arena pointed
+ * to by "arena" and the messageID contained in "msgNum", and stores a pointer
+ * to the encoded string at "pAbandonMsg".
+ *
+ * See pkix_pl_ldaptemplates.c for the ASN.1 description of an Abandon message.
+ *
+ * PARAMETERS:
+ * "arena"
+ * The address of the PLArenaPool used in encoding the message. Must be
+ * non-NULL.
+ * "msgNum"
+ * The Int32 containing the MessageID to be encoded in the Abandon message.
+ * "pAbandonMsg"
+ * The address at which the encoded Abandon message will be stored. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_MakeAbandon(
+ PLArenaPool *arena,
+ PKIX_UInt32 msgNum,
+ SECItem **pAbandonMsg,
+ void *plContext)
+{
+ LDAPMessage msg;
+ SECItem *encoded = NULL;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_MakeAbandon");
+ PKIX_NULLCHECK_TWO(arena, pAbandonMsg);
+
+ PKIX_PL_NSSCALL(LDAPDEFAULTCLIENT, PORT_Memset,
+ (&msg, 0, sizeof (LDAPMessage)));
+
+ msg.messageID.type = siUnsignedInteger;
+ msg.messageID.data = (void*)&msgNum;
+ msg.messageID.len = sizeof (msgNum);
+
+ msg.protocolOp.selector = LDAP_ABANDONREQUEST_TYPE;
+
+ msg.protocolOp.op.abandonRequestMsg.messageID.type = siBuffer;
+ msg.protocolOp.op.abandonRequestMsg.messageID.data = (void*)&msgNum;
+ msg.protocolOp.op.abandonRequestMsg.messageID.len = sizeof (msgNum);
+
+ PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, encoded, SEC_ASN1EncodeItem,
+ (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate));
+ if (!encoded) {
+ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
+ }
+
+ *pAbandonMsg = encoded;
+cleanup:
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_DecodeBindResponse
+ * DESCRIPTION:
+ *
+ * This function decodes the encoded data pointed to by "src", using the arena
+ * pointed to by "arena", storing the decoded LDAPMessage at "pBindResponse"
+ * and the decoding status at "pStatus".
+ *
+ * PARAMETERS:
+ * "arena"
+ * The address of the PLArenaPool to be used in decoding the message. Must
+ * be non-NULL.
+ * "src"
+ * The address of the SECItem containing the DER- (or BER-)encoded string.
+ * Must be non-NULL.
+ * "pBindResponse"
+ * The address at which the LDAPMessage is stored, if the decoding is
+ * successful (the returned status is SECSuccess). Must be non-NULL.
+ * "pStatus"
+ * The address at which the decoding status is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_DecodeBindResponse(
+ PLArenaPool *arena,
+ SECItem *src,
+ LDAPMessage *pBindResponse,
+ SECStatus *pStatus,
+ void *plContext)
+{
+ SECStatus rv = SECFailure;
+ LDAPMessage response;
+
+ PKIX_ENTER
+ (LDAPDEFAULTCLIENT,
+ "pkix_pl_LdapDefaultClient_DecodeBindResponse");
+ PKIX_NULLCHECK_FOUR(arena, src, pBindResponse, pStatus);
+
+ PKIX_PL_NSSCALL
+ (LDAPDEFAULTCLIENT,
+ PORT_Memset,
+ (&response, 0, sizeof (LDAPMessage)));
+
+ PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, rv, SEC_ASN1DecodeItem,
+ (arena, &response, PKIX_PL_LDAPMessageTemplate, src));
+
+ if (rv == SECSuccess) {
+ *pBindResponse = response;
+ }
+
+ *pStatus = rv;
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_VerifyBindResponse
+ * DESCRIPTION:
+ *
+ * This function verifies that the contents of the message in the rcvbuf of
+ * the LdapDefaultClient object pointed to by "client", and whose length is
+ * provided by "buflen", is a response to a successful Bind.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "buflen"
+ * The value of the number of bytes in the receive buffer.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_VerifyBindResponse(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_UInt32 bufLen,
+ void *plContext)
+{
+ SECItem decode = {siBuffer, NULL, 0};
+ SECStatus rv = SECFailure;
+ LDAPMessage msg;
+ LDAPBindResponse *ldapBindResponse = &msg.protocolOp.op.bindResponseMsg;
+
+ ldapBindResponse->resultCode.data = NULL;
+
+ PKIX_ENTER
+ (LDAPDEFAULTCLIENT,
+ "pkix_pl_LdapDefaultClient_VerifyBindResponse");
+ PKIX_NULLCHECK_TWO(client, client->rcvBuf);
+
+ decode.data = (unsigned char *)(client->rcvBuf);
+ decode.len = bufLen;
+
+ PKIX_CHECK(pkix_pl_LdapDefaultClient_DecodeBindResponse
+ (client->arena, &decode, &msg, &rv, plContext),
+ PKIX_LDAPDEFAULTCLIENTDECODEBINDRESPONSEFAILED);
+
+ if (rv == SECSuccess) {
+ if (*(ldapBindResponse->resultCode.data) == SUCCESS) {
+ client->connectStatus = BOUND;
+ } else {
+ PKIX_ERROR(PKIX_BINDREJECTEDBYSERVER);
+ }
+ } else {
+ PKIX_ERROR(PKIX_CANTDECODEBINDRESPONSEFROMSERVER);
+ }
+
+cleanup:
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_RecvCheckComplete
+ * DESCRIPTION:
+ *
+ * This function determines whether the current response in the
+ * LdapDefaultClient pointed to by "client" is complete, in the sense that all
+ * bytes required to satisfy the message length field in the encoding have been
+ * received. If so, the pointer to input data is updated to reflect the number
+ * of bytes consumed, provided by "bytesProcessed". The state machine flag
+ * pointed to by "pKeepGoing" is updated to indicate whether processing can
+ * continue without further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "bytesProcessed"
+ * The UInt32 value of the number of bytes consumed from the current
+ * buffer.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_RecvCheckComplete(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_UInt32 bytesProcessed,
+ PKIX_Boolean *pKeepGoing,
+ void *plContext)
+{
+ PKIX_Boolean complete = PKIX_FALSE;
+ SECStatus rv = SECFailure;
+ LDAPMessageType messageType = 0;
+ LDAPResultCode resultCode = 0;
+
+ PKIX_ENTER
+ (LDAPDEFAULTCLIENT,
+ "pkix_pl_LdapDefaultClient_RecvCheckComplete");
+ PKIX_NULLCHECK_TWO(client, pKeepGoing);
+
+ PKIX_CHECK(pkix_pl_LdapResponse_IsComplete
+ (client->currentResponse, &complete, plContext),
+ PKIX_LDAPRESPONSEISCOMPLETEFAILED);
+
+ if (complete) {
+ PKIX_CHECK(pkix_pl_LdapResponse_Decode
+ (client->arena, client->currentResponse, &rv, plContext),
+ PKIX_LDAPRESPONSEDECODEFAILED);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_CANTDECODESEARCHRESPONSEFROMSERVER);
+ }
+
+ PKIX_CHECK(pkix_pl_LdapResponse_GetMessageType
+ (client->currentResponse, &messageType, plContext),
+ PKIX_LDAPRESPONSEGETMESSAGETYPEFAILED);
+
+ if (messageType == LDAP_SEARCHRESPONSEENTRY_TYPE) {
+
+ if (client->entriesFound == NULL) {
+ PKIX_CHECK(PKIX_List_Create
+ (&(client->entriesFound), plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (client->entriesFound,
+ (PKIX_PL_Object *)client->currentResponse,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(client->currentResponse);
+
+ /* current receive buffer empty? */
+ if (client->currentBytesAvailable == 0) {
+ client->connectStatus = RECV;
+ *pKeepGoing = PKIX_TRUE;
+ } else {
+ client->connectStatus = RECV_INITIAL;
+ client->currentInPtr = &((char *)
+ (client->currentInPtr))[bytesProcessed];
+ *pKeepGoing = PKIX_TRUE;
+ }
+
+ } else if (messageType == LDAP_SEARCHRESPONSERESULT_TYPE) {
+ PKIX_CHECK(pkix_pl_LdapResponse_GetResultCode
+ (client->currentResponse,
+ &resultCode,
+ plContext),
+ PKIX_LDAPRESPONSEGETRESULTCODEFAILED);
+
+ if ((client->entriesFound == NULL) &&
+ ((resultCode == SUCCESS) ||
+ (resultCode == NOSUCHOBJECT))) {
+ PKIX_CHECK(PKIX_List_Create
+ (&(client->entriesFound), plContext),
+ PKIX_LISTCREATEFAILED);
+ } else if (resultCode == SUCCESS) {
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (client->entriesFound, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+ PKIX_CHECK(PKIX_PL_HashTable_Add
+ (client->cachePtr,
+ (PKIX_PL_Object *)client->currentRequest,
+ (PKIX_PL_Object *)client->entriesFound,
+ plContext),
+ PKIX_HASHTABLEADDFAILED);
+ } else {
+ PKIX_ERROR(PKIX_UNEXPECTEDRESULTCODEINRESPONSE);
+ }
+
+ client->connectStatus = BOUND;
+ *pKeepGoing = PKIX_FALSE;
+ PKIX_DECREF(client->currentResponse);
+
+ } else {
+ PKIX_ERROR(PKIX_SEARCHRESPONSEPACKETOFUNKNOWNTYPE);
+ }
+ } else {
+ client->connectStatus = RECV;
+ *pKeepGoing = PKIX_TRUE;
+ }
+
+cleanup:
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/* --Private-LdapDefaultClient-Object-Functions------------------------- */
+
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_InitiateRequest(
+ PKIX_PL_LdapClient *client,
+ LDAPRequestParams *requestParams,
+ void **pPollDesc,
+ PKIX_List **pResponse,
+ void *plContext);
+
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_ResumeRequest(
+ PKIX_PL_LdapClient *client,
+ void **pPollDesc,
+ PKIX_List **pResponse,
+ void *plContext);
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_CreateHelper
+ * DESCRIPTION:
+ *
+ * This function creates a new LdapDefaultClient using the Socket pointed to
+ * by "socket", the PRIntervalTime pointed to by "timeout", and the
+ * LDAPBindAPI pointed to by "bindAPI", and stores the result at "pClient".
+ *
+ * A value of zero for "timeout" means the LDAPClient will use non-blocking
+ * I/O.
+ *
+ * PARAMETERS:
+ * "socket"
+ * Address of the Socket to be used for the client. Must be non-NULL.
+ * "bindAPI"
+ * The address of the LDAPBindAPI containing the Bind information to be
+ * encoded in the Bind message.
+ * "pClient"
+ * The address at which the created LdapDefaultClient is to be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapDefaultClient_CreateHelper(
+ PKIX_PL_Socket *socket,
+ LDAPBindAPI *bindAPI,
+ PKIX_PL_LdapDefaultClient **pClient,
+ void *plContext)
+{
+ PKIX_PL_HashTable *ht;
+ PKIX_PL_LdapDefaultClient *ldapDefaultClient = NULL;
+ PKIX_PL_Socket_Callback *callbackList;
+ PRFileDesc *fileDesc = NULL;
+ PLArenaPool *arena = NULL;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_CreateHelper");
+ PKIX_NULLCHECK_TWO(socket, pClient);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_LDAPDEFAULTCLIENT_TYPE,
+ sizeof (PKIX_PL_LdapDefaultClient),
+ (PKIX_PL_Object **)&ldapDefaultClient,
+ plContext),
+ PKIX_COULDNOTCREATELDAPDEFAULTCLIENTOBJECT);
+
+ ldapDefaultClient->vtable.initiateFcn =
+ pkix_pl_LdapDefaultClient_InitiateRequest;
+ ldapDefaultClient->vtable.resumeFcn =
+ pkix_pl_LdapDefaultClient_ResumeRequest;
+
+ PKIX_CHECK(pkix_pl_Socket_GetPRFileDesc
+ (socket, &fileDesc, plContext),
+ PKIX_SOCKETGETPRFILEDESCFAILED);
+
+ ldapDefaultClient->pollDesc.fd = fileDesc;
+ ldapDefaultClient->pollDesc.in_flags = 0;
+ ldapDefaultClient->pollDesc.out_flags = 0;
+
+ ldapDefaultClient->bindAPI = bindAPI;
+
+ PKIX_CHECK(PKIX_PL_HashTable_Create
+ (LDAP_CACHEBUCKETS, 0, &ht, plContext),
+ PKIX_HASHTABLECREATEFAILED);
+
+ ldapDefaultClient->cachePtr = ht;
+
+ PKIX_CHECK(pkix_pl_Socket_GetCallbackList
+ (socket, &callbackList, plContext),
+ PKIX_SOCKETGETCALLBACKLISTFAILED);
+
+ ldapDefaultClient->callbackList = callbackList;
+
+ PKIX_INCREF(socket);
+ ldapDefaultClient->clientSocket = socket;
+
+ ldapDefaultClient->messageID = 0;
+
+ ldapDefaultClient->bindAPI = bindAPI;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY);
+ }
+ ldapDefaultClient->arena = arena;
+
+ ldapDefaultClient->sendBuf = NULL;
+ ldapDefaultClient->bytesToWrite = 0;
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (RCVBUFSIZE, &ldapDefaultClient->rcvBuf, plContext),
+ PKIX_MALLOCFAILED);
+ ldapDefaultClient->capacity = RCVBUFSIZE;
+
+ ldapDefaultClient->bindMsg = NULL;
+ ldapDefaultClient->bindMsgLen = 0;
+
+ ldapDefaultClient->entriesFound = NULL;
+ ldapDefaultClient->currentRequest = NULL;
+ ldapDefaultClient->currentResponse = NULL;
+
+ *pClient = ldapDefaultClient;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(ldapDefaultClient);
+ }
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_LdapDefaultClient_Create
+ * DESCRIPTION:
+ *
+ * This function creates a new LdapDefaultClient using the PRNetAddr pointed to
+ * by "sockaddr", the PRIntervalTime pointed to by "timeout", and the
+ * LDAPBindAPI pointed to by "bindAPI", and stores the result at "pClient".
+ *
+ * A value of zero for "timeout" means the LDAPClient will use non-blocking
+ * I/O.
+ *
+ * PARAMETERS:
+ * "sockaddr"
+ * Address of the PRNetAddr to be used for the socket connection. Must be
+ * non-NULL.
+ * "timeout"
+ * The PRIntervalTime to be used in I/O requests for this client.
+ * "bindAPI"
+ * The address of the LDAPBindAPI containing the Bind information to be
+ * encoded in the Bind message.
+ * "pClient"
+ * The address at which the created LdapDefaultClient is to be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_LdapDefaultClient_Create(
+ PRNetAddr *sockaddr,
+ PRIntervalTime timeout,
+ LDAPBindAPI *bindAPI,
+ PKIX_PL_LdapDefaultClient **pClient,
+ void *plContext)
+{
+ PRErrorCode status = 0;
+ PKIX_PL_Socket *socket = NULL;
+ PKIX_PL_LdapDefaultClient *client = NULL;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "PKIX_PL_LdapDefaultClient_Create");
+ PKIX_NULLCHECK_TWO(sockaddr, pClient);
+
+ PKIX_CHECK(pkix_pl_Socket_Create
+ (PKIX_FALSE, timeout, sockaddr, &status, &socket, plContext),
+ PKIX_SOCKETCREATEFAILED);
+
+ PKIX_CHECK(pkix_pl_LdapDefaultClient_CreateHelper
+ (socket, bindAPI, &client, plContext),
+ PKIX_LDAPDEFAULTCLIENTCREATEHELPERFAILED);
+
+ /* Did Socket_Create say the connection was made? */
+ if (status == 0) {
+ if (client->bindAPI != NULL) {
+ client->connectStatus = CONNECTED;
+ } else {
+ client->connectStatus = BOUND;
+ }
+ } else {
+ client->connectStatus = CONNECT_PENDING;
+ }
+
+ *pClient = client;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(client);
+ }
+
+ PKIX_DECREF(socket);
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_LdapDefaultClient_CreateByName
+ * DESCRIPTION:
+ *
+ * This function creates a new LdapDefaultClient using the hostname pointed to
+ * by "hostname", the PRIntervalTime pointed to by "timeout", and the
+ * LDAPBindAPI pointed to by "bindAPI", and stores the result at "pClient".
+ *
+ * A value of zero for "timeout" means the LDAPClient will use non-blocking
+ * I/O.
+ *
+ * PARAMETERS:
+ * "hostname"
+ * Address of the hostname to be used for the socket connection. Must be
+ * non-NULL.
+ * "timeout"
+ * The PRIntervalTime to be used in I/O requests for this client.
+ * "bindAPI"
+ * The address of the LDAPBindAPI containing the Bind information to be
+ * encoded in the Bind message.
+ * "pClient"
+ * The address at which the created LdapDefaultClient is to be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_LdapDefaultClient_CreateByName(
+ char *hostname,
+ PRIntervalTime timeout,
+ LDAPBindAPI *bindAPI,
+ PKIX_PL_LdapDefaultClient **pClient,
+ void *plContext)
+{
+ PRErrorCode status = 0;
+ PKIX_PL_Socket *socket = NULL;
+ PKIX_PL_LdapDefaultClient *client = NULL;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "PKIX_PL_LdapDefaultClient_CreateByName");
+ PKIX_NULLCHECK_TWO(hostname, pClient);
+
+ PKIX_CHECK(pkix_pl_Socket_CreateByName
+ (PKIX_FALSE, timeout, hostname, &status, &socket, plContext),
+ PKIX_SOCKETCREATEBYNAMEFAILED);
+
+ PKIX_CHECK(pkix_pl_LdapDefaultClient_CreateHelper
+ (socket, bindAPI, &client, plContext),
+ PKIX_LDAPDEFAULTCLIENTCREATEHELPERFAILED);
+
+ /* Did Socket_Create say the connection was made? */
+ if (status == 0) {
+ if (client->bindAPI != NULL) {
+ client->connectStatus = CONNECTED;
+ } else {
+ client->connectStatus = BOUND;
+ }
+ } else {
+ client->connectStatus = CONNECT_PENDING;
+ }
+
+ *pClient = client;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(client);
+ }
+
+ PKIX_DECREF(socket);
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_Int32 bytesWritten = 0;
+ PKIX_PL_LdapDefaultClient *client = NULL;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+ SECItem *encoded = NULL;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT,
+ "pkix_pl_LdapDefaultClient_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_LDAPDEFAULTCLIENT_TYPE, plContext),
+ PKIX_OBJECTNOTANLDAPDEFAULTCLIENT);
+
+ client = (PKIX_PL_LdapDefaultClient *)object;
+
+ switch (client->connectStatus) {
+ case CONNECT_PENDING:
+ break;
+ case CONNECTED:
+ case BIND_PENDING:
+ case BIND_RESPONSE:
+ case BIND_RESPONSE_PENDING:
+ case BOUND:
+ case SEND_PENDING:
+ case RECV:
+ case RECV_PENDING:
+ case RECV_INITIAL:
+ case RECV_NONINITIAL:
+ case ABANDON_PENDING:
+ if (client->bindAPI != NULL) {
+ PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeUnbind
+ (client->arena,
+ ++(client->messageID),
+ &encoded,
+ plContext),
+ PKIX_LDAPDEFAULTCLIENTMAKEUNBINDFAILED);
+
+ callbackList =
+ (PKIX_PL_Socket_Callback *)(client->callbackList);
+ PKIX_CHECK(callbackList->sendCallback
+ (client->clientSocket,
+ encoded->data,
+ encoded->len,
+ &bytesWritten,
+ plContext),
+ PKIX_SOCKETSENDFAILED);
+ }
+ break;
+ default:
+ PKIX_ERROR(PKIX_LDAPDEFAULTCLIENTINILLEGALSTATE);
+ }
+
+ PKIX_DECREF(client->cachePtr);
+ PKIX_DECREF(client->clientSocket);
+ PKIX_DECREF(client->entriesFound);
+ PKIX_DECREF(client->currentRequest);
+ PKIX_DECREF(client->currentResponse);
+
+ PKIX_CHECK(PKIX_PL_Free
+ (client->rcvBuf, plContext), PKIX_FREEFAILED);
+
+ PKIX_PL_NSSCALL
+ (LDAPDEFAULTCLIENT,
+ PORT_FreeArena,
+ (client->arena, PR_FALSE));
+
+cleanup:
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_LdapDefaultClient *ldapDefaultClient = NULL;
+ PKIX_UInt32 tempHash = 0;
+
+ PKIX_ENTER
+ (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_LDAPDEFAULTCLIENT_TYPE, plContext),
+ PKIX_OBJECTNOTANLDAPDEFAULTCLIENT);
+
+ ldapDefaultClient = (PKIX_PL_LdapDefaultClient *)object;
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)ldapDefaultClient->clientSocket,
+ &tempHash,
+ plContext),
+ PKIX_SOCKETHASHCODEFAILED);
+
+ if (ldapDefaultClient->bindAPI != NULL) {
+ tempHash = (tempHash << 7) +
+ ldapDefaultClient->bindAPI->selector;
+ }
+
+ *pHashcode = tempHash;
+
+cleanup:
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_PL_LdapDefaultClient *firstClientContext = NULL;
+ PKIX_PL_LdapDefaultClient *secondClientContext = NULL;
+ PKIX_Int32 compare = 0;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ *pResult = PKIX_FALSE;
+
+ PKIX_CHECK(pkix_CheckTypes
+ (firstObject,
+ secondObject,
+ PKIX_LDAPDEFAULTCLIENT_TYPE,
+ plContext),
+ PKIX_OBJECTNOTANLDAPDEFAULTCLIENT);
+
+ firstClientContext = (PKIX_PL_LdapDefaultClient *)firstObject;
+ secondClientContext = (PKIX_PL_LdapDefaultClient *)secondObject;
+
+ if (firstClientContext == secondClientContext) {
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstClientContext->clientSocket,
+ (PKIX_PL_Object *)secondClientContext->clientSocket,
+ &compare,
+ plContext),
+ PKIX_SOCKETEQUALSFAILED);
+
+ if (!compare) {
+ goto cleanup;
+ }
+
+ if (PKIX_EXACTLY_ONE_NULL
+ (firstClientContext->bindAPI, secondClientContext->bindAPI)) {
+ goto cleanup;
+ }
+
+ if (firstClientContext->bindAPI) {
+ if (firstClientContext->bindAPI->selector !=
+ secondClientContext->bindAPI->selector) {
+ goto cleanup;
+ }
+ }
+
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_PL_LDAPDEFAULTCLIENT_TYPE and its related
+ * functions with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_LdapDefaultClient_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER
+ (LDAPDEFAULTCLIENT,
+ "pkix_pl_LdapDefaultClient_RegisterSelf");
+
+ entry.description = "LdapDefaultClient";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_LdapDefaultClient);
+ entry.destructor = pkix_pl_LdapDefaultClient_Destroy;
+ entry.equalsFunction = pkix_pl_LdapDefaultClient_Equals;
+ entry.hashcodeFunction = pkix_pl_LdapDefaultClient_Hashcode;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_LDAPDEFAULTCLIENT_TYPE] = entry;
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_GetPollDesc
+ * DESCRIPTION:
+ *
+ * This function retrieves the PRPollDesc from the LdapDefaultClient
+ * pointed to by "context" and stores the address at "pPollDesc".
+ *
+ * PARAMETERS:
+ * "context"
+ * The LdapDefaultClient whose PRPollDesc is desired. Must be non-NULL.
+ * "pPollDesc"
+ * Address where PRPollDesc will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapDefaultClient_GetPollDesc(
+ PKIX_PL_LdapDefaultClient *context,
+ PRPollDesc **pPollDesc,
+ void *plContext)
+{
+ PKIX_ENTER
+ (LDAPDEFAULTCLIENT,
+ "pkix_pl_LdapDefaultClient_GetPollDesc");
+ PKIX_NULLCHECK_TWO(context, pPollDesc);
+
+ *pPollDesc = &(context->pollDesc);
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/* --Private-Ldap-CertStore-I/O-Functions---------------------------- */
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_ConnectContinue
+ * DESCRIPTION:
+ *
+ * This function determines whether a socket Connect initiated earlier for the
+ * CertStore embodied in the LdapDefaultClient "client" has completed, and
+ * stores in "pKeepGoing" a flag indicating whether processing can continue
+ * without further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_ConnectContinue(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plContext)
+{
+ PKIX_PL_Socket_Callback *callbackList;
+ PRErrorCode status;
+ PKIX_Boolean keepGoing = PKIX_FALSE;
+
+ PKIX_ENTER
+ (LDAPDEFAULTCLIENT,
+ "pkix_pl_LdapDefaultClient_ConnectContinue");
+ PKIX_NULLCHECK_ONE(client);
+
+ callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
+
+ PKIX_CHECK(callbackList->connectcontinueCallback
+ (client->clientSocket, &status, plContext),
+ PKIX_SOCKETCONNECTCONTINUEFAILED);
+
+ if (status == 0) {
+ if (client->bindAPI != NULL) {
+ client->connectStatus = CONNECTED;
+ } else {
+ client->connectStatus = BOUND;
+ }
+ keepGoing = PKIX_FALSE;
+ } else if (status != PR_IN_PROGRESS_ERROR) {
+ PKIX_ERROR(PKIX_UNEXPECTEDERRORINESTABLISHINGCONNECTION);
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)client, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ *pKeepGoing = keepGoing;
+
+cleanup:
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_Bind
+ * DESCRIPTION:
+ *
+ * This function creates and sends the LDAP-protocol Bind message for the
+ * CertStore embodied in the LdapDefaultClient "client", and stores in
+ * "pKeepGoing" a flag indicating whether processing can continue without
+ * further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_Bind(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plContext)
+{
+ SECItem *encoded = NULL;
+ PKIX_Int32 bytesWritten = 0;
+ PKIX_PL_Socket_Callback *callbackList;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Bind");
+ PKIX_NULLCHECK_ONE(client);
+
+ /* if we have not yet constructed the BIND message, build it now */
+ if (!(client->bindMsg)) {
+ PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeBind
+ (client->arena,
+ 3,
+ client->bindAPI,
+ client->messageID,
+ &encoded,
+ plContext),
+ PKIX_LDAPDEFAULTCLIENTMAKEBINDFAILED);
+ client->bindMsg = encoded->data;
+ client->bindMsgLen = encoded->len;
+ }
+
+ callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
+
+ PKIX_CHECK(callbackList->sendCallback
+ (client->clientSocket,
+ client->bindMsg,
+ client->bindMsgLen,
+ &bytesWritten,
+ plContext),
+ PKIX_SOCKETSENDFAILED);
+
+ client->lastIO = PR_Now();
+
+ if (bytesWritten < 0) {
+ client->connectStatus = BIND_PENDING;
+ *pKeepGoing = PKIX_FALSE;
+ } else {
+ client->connectStatus = BIND_RESPONSE;
+ *pKeepGoing = PKIX_TRUE;
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)client, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_BindContinue
+ * DESCRIPTION:
+ *
+ * This function determines whether the LDAP-protocol Bind message for the
+ * CertStore embodied in the LdapDefaultClient "client" has completed, and
+ * stores in "pKeepGoing" a flag indicating whether processing can continue
+ * without further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *pkix_pl_LdapDefaultClient_BindContinue(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plContext)
+{
+ PKIX_Int32 bytesWritten = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_BindContinue");
+ PKIX_NULLCHECK_ONE(client);
+
+ *pKeepGoing = PKIX_FALSE;
+
+ callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
+
+ PKIX_CHECK(callbackList->pollCallback
+ (client->clientSocket, &bytesWritten, NULL, plContext),
+ PKIX_SOCKETPOLLFAILED);
+
+ /*
+ * If the send completed we can proceed to try for the
+ * response. If the send did not complete we will have
+ * continue to poll.
+ */
+ if (bytesWritten >= 0) {
+
+ client->connectStatus = BIND_RESPONSE;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)client, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ *pKeepGoing = PKIX_TRUE;
+ }
+
+cleanup:
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_BindResponse
+ * DESCRIPTION:
+ *
+ * This function attempts to read the LDAP-protocol BindResponse message for
+ * the CertStore embodied in the LdapDefaultClient "client", and stores in
+ * "pKeepGoing" a flag indicating whether processing can continue without
+ * further input.
+ *
+ * If a BindResponse is received with a Result code of 0 (success), we
+ * continue with the connection. If a non-zero Result code is received,
+ * we throw an Error. Some more sophisticated handling of that condition
+ * might be in order in the future.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_BindResponse(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plContext)
+{
+ PKIX_Int32 bytesRead = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_BindResponse");
+ PKIX_NULLCHECK_TWO(client, client->rcvBuf);
+
+ callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
+
+ PKIX_CHECK(callbackList->recvCallback
+ (client->clientSocket,
+ client->rcvBuf,
+ client->capacity,
+ &bytesRead,
+ plContext),
+ PKIX_SOCKETRECVFAILED);
+
+ client->lastIO = PR_Now();
+
+ if (bytesRead > 0) {
+ PKIX_CHECK(pkix_pl_LdapDefaultClient_VerifyBindResponse
+ (client, bytesRead, plContext),
+ PKIX_LDAPDEFAULTCLIENTVERIFYBINDRESPONSEFAILED);
+ /*
+ * XXX What should we do if failure? At present if
+ * VerifyBindResponse throws an Error, we do too.
+ */
+ client->connectStatus = BOUND;
+ } else {
+ client->connectStatus = BIND_RESPONSE_PENDING;
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)client, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ *pKeepGoing = PKIX_TRUE;
+
+cleanup:
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_BindResponseContinue
+ * DESCRIPTION:
+ *
+ * This function determines whether the LDAP-protocol BindResponse message for
+ * the CertStore embodied in the LdapDefaultClient "client" has completed, and
+ * stores in "pKeepGoing" a flag indicating whether processing can continue
+ * without further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_BindResponseContinue(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plContext)
+{
+ PKIX_Int32 bytesRead = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER
+ (LDAPDEFAULTCLIENT,
+ "pkix_pl_LdapDefaultClient_BindResponseContinue");
+ PKIX_NULLCHECK_ONE(client);
+
+ callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
+
+ PKIX_CHECK(callbackList->pollCallback
+ (client->clientSocket, NULL, &bytesRead, plContext),
+ PKIX_SOCKETPOLLFAILED);
+
+ if (bytesRead > 0) {
+ PKIX_CHECK(pkix_pl_LdapDefaultClient_VerifyBindResponse
+ (client, bytesRead, plContext),
+ PKIX_LDAPDEFAULTCLIENTVERIFYBINDRESPONSEFAILED);
+ client->connectStatus = BOUND;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)client, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ *pKeepGoing = PKIX_TRUE;
+ } else {
+ *pKeepGoing = PKIX_FALSE;
+ }
+
+cleanup:
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_Send
+ * DESCRIPTION:
+ *
+ * This function creates and sends an LDAP-protocol message for the
+ * CertStore embodied in the LdapDefaultClient "client", and stores in
+ * "pKeepGoing" a flag indicating whether processing can continue without
+ * further input, and at "pBytesTransferred" the number of bytes sent.
+ *
+ * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use
+ * and that transmission has not completed.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "pBytesTransferred"
+ * The address at which the number of bytes sent is stored. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_Send(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ PKIX_UInt32 *pBytesTransferred,
+ void *plContext)
+{
+ PKIX_Int32 bytesWritten = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Send");
+ PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred);
+
+ *pKeepGoing = PKIX_FALSE;
+
+ /* Do we have anything waiting to go? */
+ if (client->sendBuf) {
+ callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
+
+ PKIX_CHECK(callbackList->sendCallback
+ (client->clientSocket,
+ client->sendBuf,
+ client->bytesToWrite,
+ &bytesWritten,
+ plContext),
+ PKIX_SOCKETSENDFAILED);
+
+ client->lastIO = PR_Now();
+
+ /*
+ * If the send completed we can proceed to try for the
+ * response. If the send did not complete we will have
+ * to poll for completion later.
+ */
+ if (bytesWritten >= 0) {
+ client->sendBuf = NULL;
+ client->connectStatus = RECV;
+ *pKeepGoing = PKIX_TRUE;
+
+ } else {
+ *pKeepGoing = PKIX_FALSE;
+ client->connectStatus = SEND_PENDING;
+ }
+
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)client, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ *pBytesTransferred = bytesWritten;
+
+cleanup:
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_SendContinue
+ * DESCRIPTION:
+ *
+ * This function determines whether the sending of the LDAP-protocol message
+ * for the CertStore embodied in the LdapDefaultClient "client" has completed,
+ * and stores in "pKeepGoing" a flag indicating whether processing can continue
+ * without further input, and at "pBytesTransferred" the number of bytes sent.
+ *
+ * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use
+ * and that transmission has not completed.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "pBytesTransferred"
+ * The address at which the number of bytes sent is stored. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_SendContinue(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ PKIX_UInt32 *pBytesTransferred,
+ void *plContext)
+{
+ PKIX_Int32 bytesWritten = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_SendContinue");
+ PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred);
+
+ *pKeepGoing = PKIX_FALSE;
+
+ callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
+
+ PKIX_CHECK(callbackList->pollCallback
+ (client->clientSocket, &bytesWritten, NULL, plContext),
+ PKIX_SOCKETPOLLFAILED);
+
+ /*
+ * If the send completed we can proceed to try for the
+ * response. If the send did not complete we will have
+ * continue to poll.
+ */
+ if (bytesWritten >= 0) {
+ client->sendBuf = NULL;
+ client->connectStatus = RECV;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)client, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+ *pKeepGoing = PKIX_TRUE;
+ }
+
+ *pBytesTransferred = bytesWritten;
+
+cleanup:
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_Recv
+ * DESCRIPTION:
+ *
+ * This function receives an LDAP-protocol message for the CertStore embodied
+ * in the LdapDefaultClient "client", and stores in "pKeepGoing" a flag
+ * indicating whether processing can continue without further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_Recv(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plContext)
+{
+ PKIX_Int32 bytesRead = 0;
+ PKIX_UInt32 bytesToRead = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Recv");
+ PKIX_NULLCHECK_THREE(client, pKeepGoing, client->rcvBuf);
+
+ callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
+
+ /*
+ * If we attempt to fill our buffer with every read, we increase
+ * the risk of an ugly situation: one or two bytes of a new message
+ * left over at the end of processing one message. With such a
+ * fragment, we can't decode a byte count and so won't know how much
+ * space to allocate for the next LdapResponse. We try to avoid that
+ * case by reading just enough to complete the current message, unless
+ * there will be at least MINIMUM_MSG_LENGTH bytes left over.
+ */
+ if (client->currentResponse) {
+ PKIX_CHECK(pkix_pl_LdapResponse_GetCapacity
+ (client->currentResponse, &bytesToRead, plContext),
+ PKIX_LDAPRESPONSEGETCAPACITYFAILED);
+ if ((bytesToRead > client->capacity) ||
+ ((bytesToRead + MINIMUM_MSG_LENGTH) < client->capacity)) {
+ bytesToRead = client->capacity;
+ }
+ } else {
+ bytesToRead = client->capacity;
+ }
+
+ client->currentBytesAvailable = 0;
+
+ PKIX_CHECK(callbackList->recvCallback
+ (client->clientSocket,
+ (void *)client->rcvBuf,
+ bytesToRead,
+ &bytesRead,
+ plContext),
+ PKIX_SOCKETRECVFAILED);
+
+ client->currentInPtr = client->rcvBuf;
+ client->lastIO = PR_Now();
+
+ if (bytesRead > 0) {
+ client->currentBytesAvailable = bytesRead;
+ client->connectStatus = RECV_INITIAL;
+ *pKeepGoing = PKIX_TRUE;
+ } else {
+ client->connectStatus = RECV_PENDING;
+ *pKeepGoing = PKIX_FALSE;
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)client, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+
+cleanup:
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_RecvContinue
+ * DESCRIPTION:
+ *
+ * This function determines whether the receiving of the LDAP-protocol message
+ * for the CertStore embodied in the LdapDefaultClient "client" has completed,
+ * and stores in "pKeepGoing" a flag indicating whether processing can continue
+ * without further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_RecvContinue(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plContext)
+{
+ PKIX_Int32 bytesRead = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_RecvContinue");
+ PKIX_NULLCHECK_TWO(client, pKeepGoing);
+
+ callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
+
+ PKIX_CHECK(callbackList->pollCallback
+ (client->clientSocket, NULL, &bytesRead, plContext),
+ PKIX_SOCKETPOLLFAILED);
+
+ if (bytesRead > 0) {
+ client->currentBytesAvailable += bytesRead;
+ client->connectStatus = RECV_INITIAL;
+ *pKeepGoing = PKIX_TRUE;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)client, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ } else {
+ *pKeepGoing = PKIX_FALSE;
+ }
+
+cleanup:
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_AbandonContinue
+ * DESCRIPTION:
+ *
+ * This function determines whether the abandon-message request of the
+ * LDAP-protocol message for the CertStore embodied in the LdapDefaultClient
+ * "client" has completed, and stores in "pKeepGoing" a flag indicating whether
+ * processing can continue without further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_AbandonContinue(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plContext)
+{
+ PKIX_Int32 bytesWritten = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER
+ (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_AbandonContinue");
+ PKIX_NULLCHECK_TWO(client, pKeepGoing);
+
+ callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
+
+ PKIX_CHECK(callbackList->pollCallback
+ (client->clientSocket, &bytesWritten, NULL, plContext),
+ PKIX_SOCKETPOLLFAILED);
+
+ if (bytesWritten > 0) {
+ client->connectStatus = BOUND;
+ *pKeepGoing = PKIX_TRUE;
+
+ PKIX_CHECK(PKIX_PL_Object_InvalidateCache
+ ((PKIX_PL_Object *)client, plContext),
+ PKIX_OBJECTINVALIDATECACHEFAILED);
+ } else {
+ *pKeepGoing = PKIX_FALSE;
+ }
+
+cleanup:
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_RecvInitial
+ * DESCRIPTION:
+ *
+ * This function processes the contents of the first buffer of a received
+ * LDAP-protocol message for the CertStore embodied in the LdapDefaultClient
+ * "client", and stores in "pKeepGoing" a flag indicating whether processing can
+ * continue without further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_RecvInitial(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plContext)
+{
+ unsigned char *msgBuf = NULL;
+ unsigned char *to = NULL;
+ unsigned char *from = NULL;
+ PKIX_UInt32 dataIndex = 0;
+ PKIX_UInt32 messageIdLen = 0;
+ PKIX_UInt32 messageLength = 0;
+ PKIX_UInt32 sizeofLength = 0;
+ PKIX_UInt32 bytesProcessed = 0;
+ unsigned char messageChar = 0;
+ LDAPMessageType messageType = 0;
+ PKIX_Int32 bytesRead = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_RecvInitial");
+ PKIX_NULLCHECK_TWO(client, pKeepGoing);
+
+ /*
+ * Is there an LDAPResponse in progress? I.e., have we
+ * already processed the tag and length at the beginning of
+ * the message?
+ */
+ if (client->currentResponse) {
+ client->connectStatus = RECV_NONINITIAL;
+ *pKeepGoing = PKIX_TRUE;
+ goto cleanup;
+ }
+ msgBuf = client->currentInPtr;
+
+ /* Do we have enough of the message to decode the message length? */
+ if (client->currentBytesAvailable < MINIMUM_MSG_LENGTH) {
+ /*
+ * No! Move these few bytes to the beginning of rcvBuf
+ * and hang another read.
+ */
+
+ to = (unsigned char *)client->rcvBuf;
+ from = client->currentInPtr;
+ for (dataIndex = 0;
+ dataIndex < client->currentBytesAvailable;
+ dataIndex++) {
+ *to++ = *from++;
+ }
+ callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
+ PKIX_CHECK(callbackList->recvCallback
+ (client->clientSocket,
+ (void *)to,
+ client->capacity - client->currentBytesAvailable,
+ &bytesRead,
+ plContext),
+ PKIX_SOCKETRECVFAILED);
+
+ client->currentInPtr = client->rcvBuf;
+ client->lastIO = PR_Now();
+
+ if (bytesRead <= 0) {
+ client->connectStatus = RECV_PENDING;
+ *pKeepGoing = PKIX_FALSE;
+ goto cleanup;
+ } else {
+ client->currentBytesAvailable += bytesRead;
+ }
+ }
+
+ /*
+ * We have to determine whether the response is an entry, with
+ * application-specific tag LDAP_SEARCHRESPONSEENTRY_TYPE, or a
+ * resultCode, with application tag LDAP_SEARCHRESPONSERESULT_TYPE.
+ * First, we have to figure out where to look for the tag.
+ */
+
+ /* Is the message length short form (one octet) or long form? */
+ if ((msgBuf[1] & 0x80) != 0) {
+ sizeofLength = msgBuf[1] & 0x7F;
+ for (dataIndex = 0; dataIndex < sizeofLength; dataIndex++) {
+ messageLength =
+ (messageLength << 8) + msgBuf[dataIndex + 2];
+ }
+ } else {
+ messageLength = msgBuf[1];
+ }
+
+ /* How many bytes did the messageID require? */
+ messageIdLen = msgBuf[dataIndex + 3];
+
+ messageChar = msgBuf[dataIndex + messageIdLen + 4];
+
+ /* Are we looking at an Entry message or a ResultCode message? */
+ if ((SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION |
+ LDAP_SEARCHRESPONSEENTRY_TYPE) == messageChar) {
+
+ messageType = LDAP_SEARCHRESPONSEENTRY_TYPE;
+
+ } else if ((SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION |
+ LDAP_SEARCHRESPONSERESULT_TYPE) == messageChar) {
+
+ messageType = LDAP_SEARCHRESPONSERESULT_TYPE;
+
+ } else {
+
+ PKIX_ERROR(PKIX_SEARCHRESPONSEPACKETOFUNKNOWNTYPE);
+
+ }
+
+ /*
+ * messageLength is the length from (tag, length, value).
+ * We have to allocate space for the tag and length bits too.
+ */
+ PKIX_CHECK(pkix_pl_LdapResponse_Create
+ (messageType,
+ messageLength + dataIndex + 2,
+ client->currentBytesAvailable,
+ msgBuf,
+ &bytesProcessed,
+ &(client->currentResponse),
+ plContext),
+ PKIX_LDAPRESPONSECREATEFAILED);
+
+ client->currentBytesAvailable -= bytesProcessed;
+
+ PKIX_CHECK(pkix_pl_LdapDefaultClient_RecvCheckComplete
+ (client, bytesProcessed, pKeepGoing, plContext),
+ PKIX_LDAPDEFAULTCLIENTRECVCHECKCOMPLETEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_RecvNonInitial
+ * DESCRIPTION:
+ *
+ * This function processes the contents of buffers, after the first, of a
+ * received LDAP-protocol message for the CertStore embodied in the
+ * LdapDefaultClient "client", and stores in "pKeepGoing" a flag indicating
+ * whether processing can continue without further input.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "pKeepGoing"
+ * The address at which the Boolean state machine flag is stored to
+ * indicate whether processing can continue without further input.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_RecvNonInitial(
+ PKIX_PL_LdapDefaultClient *client,
+ PKIX_Boolean *pKeepGoing,
+ void *plContext)
+{
+
+ PKIX_UInt32 bytesProcessed = 0;
+
+ PKIX_ENTER
+ (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_RecvNonInitial");
+ PKIX_NULLCHECK_TWO(client, pKeepGoing);
+
+ PKIX_CHECK(pkix_pl_LdapResponse_Append
+ (client->currentResponse,
+ client->currentBytesAvailable,
+ client->currentInPtr,
+ &bytesProcessed,
+ plContext),
+ PKIX_LDAPRESPONSEAPPENDFAILED);
+
+ client->currentBytesAvailable -= bytesProcessed;
+
+ PKIX_CHECK(pkix_pl_LdapDefaultClient_RecvCheckComplete
+ (client, bytesProcessed, pKeepGoing, plContext),
+ PKIX_LDAPDEFAULTCLIENTRECVCHECKCOMPLETEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_Dispatch
+ * DESCRIPTION:
+ *
+ * This function is the state machine dispatcher for the CertStore embodied in
+ * the LdapDefaultClient pointed to by "client". Results are returned by
+ * changes to various fields in the context.
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_Dispatch(
+ PKIX_PL_LdapDefaultClient *client,
+ void *plContext)
+{
+ PKIX_UInt32 bytesTransferred = 0;
+ PKIX_Boolean keepGoing = PKIX_TRUE;
+
+ PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Dispatch");
+ PKIX_NULLCHECK_ONE(client);
+
+ while (keepGoing) {
+ switch (client->connectStatus) {
+ case CONNECT_PENDING:
+ PKIX_CHECK
+ (pkix_pl_LdapDefaultClient_ConnectContinue
+ (client, &keepGoing, plContext),
+ PKIX_LDAPDEFAULTCLIENTCONNECTCONTINUEFAILED);
+ break;
+ case CONNECTED:
+ PKIX_CHECK
+ (pkix_pl_LdapDefaultClient_Bind
+ (client, &keepGoing, plContext),
+ PKIX_LDAPDEFAULTCLIENTBINDFAILED);
+ break;
+ case BIND_PENDING:
+ PKIX_CHECK
+ (pkix_pl_LdapDefaultClient_BindContinue
+ (client, &keepGoing, plContext),
+ PKIX_LDAPDEFAULTCLIENTBINDCONTINUEFAILED);
+ break;
+ case BIND_RESPONSE:
+ PKIX_CHECK
+ (pkix_pl_LdapDefaultClient_BindResponse
+ (client, &keepGoing, plContext),
+ PKIX_LDAPDEFAULTCLIENTBINDRESPONSEFAILED);
+ break;
+ case BIND_RESPONSE_PENDING:
+ PKIX_CHECK
+ (pkix_pl_LdapDefaultClient_BindResponseContinue
+ (client, &keepGoing, plContext),
+ PKIX_LDAPDEFAULTCLIENTBINDRESPONSECONTINUEFAILED);
+ break;
+ case BOUND:
+ PKIX_CHECK
+ (pkix_pl_LdapDefaultClient_Send
+ (client, &keepGoing, &bytesTransferred, plContext),
+ PKIX_LDAPDEFAULTCLIENTSENDFAILED);
+ break;
+ case SEND_PENDING:
+ PKIX_CHECK
+ (pkix_pl_LdapDefaultClient_SendContinue
+ (client, &keepGoing, &bytesTransferred, plContext),
+ PKIX_LDAPDEFAULTCLIENTSENDCONTINUEFAILED);
+ break;
+ case RECV:
+ PKIX_CHECK
+ (pkix_pl_LdapDefaultClient_Recv
+ (client, &keepGoing, plContext),
+ PKIX_LDAPDEFAULTCLIENTRECVFAILED);
+ break;
+ case RECV_PENDING:
+ PKIX_CHECK
+ (pkix_pl_LdapDefaultClient_RecvContinue
+ (client, &keepGoing, plContext),
+ PKIX_LDAPDEFAULTCLIENTRECVCONTINUEFAILED);
+ break;
+ case RECV_INITIAL:
+ PKIX_CHECK
+ (pkix_pl_LdapDefaultClient_RecvInitial
+ (client, &keepGoing, plContext),
+ PKIX_LDAPDEFAULTCLIENTRECVINITIALFAILED);
+ break;
+ case RECV_NONINITIAL:
+ PKIX_CHECK
+ (pkix_pl_LdapDefaultClient_RecvNonInitial
+ (client, &keepGoing, plContext),
+ PKIX_LDAPDEFAULTCLIENTRECVNONINITIALFAILED);
+ break;
+ case ABANDON_PENDING:
+ PKIX_CHECK
+ (pkix_pl_LdapDefaultClient_AbandonContinue
+ (client, &keepGoing, plContext),
+ PKIX_LDAPDEFAULTCLIENTABANDONCONTINUEFAILED);
+ break;
+ default:
+ PKIX_ERROR(PKIX_LDAPCERTSTOREINILLEGALSTATE);
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_MakeAndFilter
+ * DESCRIPTION:
+ *
+ * This function allocates space from the arena pointed to by "arena" to
+ * construct a filter that will match components of the X500Name pointed to by
+ * XXX...
+ *
+ * PARAMETERS:
+ * "arena"
+ * The address of the PLArenaPool used in creating the filter. Must be
+ * non-NULL.
+ * "nameComponent"
+ * The address of a NULL-terminated list of LDAPNameComponents
+ * Must be non-NULL.
+ * "pFilter"
+ * The address at which the result is stored.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_MakeAndFilter(
+ PLArenaPool *arena,
+ LDAPNameComponent **nameComponents,
+ LDAPFilter **pFilter,
+ void *plContext)
+{
+ LDAPFilter **setOfFilter;
+ LDAPFilter *andFilter = NULL;
+ LDAPFilter *currentFilter = NULL;
+ PKIX_UInt32 componentsPresent = 0;
+ void *v = NULL;
+ unsigned char *component = NULL;
+ LDAPNameComponent **componentP = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_LdapDefaultClient_MakeAndFilter");
+ PKIX_NULLCHECK_THREE(arena, nameComponents, pFilter);
+
+ /* count how many components we were provided */
+ for (componentP = nameComponents, componentsPresent = 0;
+ *(componentP++) != NULL;
+ componentsPresent++) {}
+
+ /* Space for (componentsPresent + 1) pointers to LDAPFilter */
+ PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZAlloc,
+ (arena, (componentsPresent + 1)*sizeof(LDAPFilter *)));
+ setOfFilter = (LDAPFilter **)v;
+
+ /* Space for AndFilter and <componentsPresent> EqualFilters */
+ PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZNewArray,
+ (arena, LDAPFilter, componentsPresent + 1));
+ setOfFilter[0] = (LDAPFilter *)v;
+
+ /* Claim the first array element for the ANDFilter */
+ andFilter = setOfFilter[0];
+
+ /* Set ANDFilter to point to the first EqualFilter pointer */
+ andFilter->selector = LDAP_ANDFILTER_TYPE;
+ andFilter->filter.andFilter.filters = setOfFilter;
+
+ currentFilter = andFilter + 1;
+
+ for (componentP = nameComponents, componentsPresent = 0;
+ *(componentP) != NULL; componentP++) {
+ setOfFilter[componentsPresent++] = currentFilter;
+ currentFilter->selector = LDAP_EQUALFILTER_TYPE;
+ component = (*componentP)->attrType;
+ currentFilter->filter.equalFilter.attrType.data = component;
+ currentFilter->filter.equalFilter.attrType.len =
+ PL_strlen((const char *)component);
+ component = (*componentP)->attrValue;
+ currentFilter->filter.equalFilter.attrValue.data = component;
+ currentFilter->filter.equalFilter.attrValue.len =
+ PL_strlen((const char *)component);
+ currentFilter++;
+ }
+
+ setOfFilter[componentsPresent] = NULL;
+
+ *pFilter = andFilter;
+
+ PKIX_RETURN(CERTSTORE);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_InitiateRequest
+ * DESCRIPTION:
+ *
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "requestParams"
+ * The address of an LdapClientParams object. Must be non-NULL.
+ * "pPollDesc"
+ * The location where the address of the PRPollDesc is stored, if the
+ * client returns with I/O pending.
+ * "pResponse"
+ * The address where the List of LDAPResponses, or NULL for an
+ * unfinished request, is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_InitiateRequest(
+ PKIX_PL_LdapClient *genericClient,
+ LDAPRequestParams *requestParams,
+ void **pPollDesc,
+ PKIX_List **pResponse,
+ void *plContext)
+{
+ PKIX_List *searchResponseList = NULL;
+ SECItem *encoded = NULL;
+ LDAPFilter *filter = NULL;
+ PKIX_PL_LdapDefaultClient *client = 0;
+
+ PKIX_ENTER
+ (LDAPDEFAULTCLIENT,
+ "pkix_pl_LdapDefaultClient_InitiateRequest");
+ PKIX_NULLCHECK_FOUR(genericClient, requestParams, pPollDesc, pResponse);
+
+ PKIX_CHECK(pkix_CheckType
+ ((PKIX_PL_Object *)genericClient,
+ PKIX_LDAPDEFAULTCLIENT_TYPE,
+ plContext),
+ PKIX_GENERICCLIENTNOTANLDAPDEFAULTCLIENT);
+
+ client = (PKIX_PL_LdapDefaultClient *)genericClient;
+
+ PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeAndFilter
+ (client->arena, requestParams->nc, &filter, plContext),
+ PKIX_LDAPDEFAULTCLIENTMAKEANDFILTERFAILED);
+
+ PKIX_CHECK(pkix_pl_LdapRequest_Create
+ (client->arena,
+ client->messageID++,
+ requestParams->baseObject,
+ requestParams->scope,
+ requestParams->derefAliases,
+ requestParams->sizeLimit,
+ requestParams->timeLimit,
+ PKIX_FALSE, /* attrs only */
+ filter,
+ requestParams->attributes,
+ &client->currentRequest,
+ plContext),
+ PKIX_LDAPREQUESTCREATEFAILED);
+
+ /* check hashtable for matching request */
+ PKIX_CHECK(PKIX_PL_HashTable_Lookup
+ (client->cachePtr,
+ (PKIX_PL_Object *)(client->currentRequest),
+ (PKIX_PL_Object **)&searchResponseList,
+ plContext),
+ PKIX_HASHTABLELOOKUPFAILED);
+
+ if (searchResponseList != NULL) {
+ *pPollDesc = NULL;
+ *pResponse = searchResponseList;
+ PKIX_DECREF(client->currentRequest);
+ goto cleanup;
+ }
+
+ /* It wasn't cached. We'll have to actually send it. */
+
+ PKIX_CHECK(pkix_pl_LdapRequest_GetEncoded
+ (client->currentRequest, &encoded, plContext),
+ PKIX_LDAPREQUESTGETENCODEDFAILED);
+
+ client->sendBuf = encoded->data;
+ client->bytesToWrite = encoded->len;
+
+ PKIX_CHECK(pkix_pl_LdapDefaultClient_Dispatch(client, plContext),
+ PKIX_LDAPDEFAULTCLIENTDISPATCHFAILED);
+
+ /*
+ * It's not enough that we may be done with a particular read.
+ * We're still processing the transaction until we've gotten the
+ * SearchResponseResult message and returned to the BOUND state.
+ * Otherwise we must still have a read pending, and must hold off
+ * on returning results.
+ */
+ if ((client->connectStatus == BOUND) &&
+ (client->entriesFound != NULL)) {
+ *pPollDesc = NULL;
+ *pResponse = client->entriesFound;
+ client->entriesFound = NULL;
+ PKIX_DECREF(client->currentRequest);
+ } else {
+ *pPollDesc = &client->pollDesc;
+ *pResponse = NULL;
+ }
+
+cleanup:
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapDefaultClient_ResumeRequest
+ * DESCRIPTION:
+ *
+ *
+ * PARAMETERS:
+ * "client"
+ * The address of the LdapDefaultClient object. Must be non-NULL.
+ * "pPollDesc"
+ * The location where the address of the PRPollDesc is stored, if the
+ * client returns with I/O pending.
+ * "pResponse"
+ * The address where the List of LDAPResponses, or NULL for an
+ * unfinished request, is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a LdapDefaultClient Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapDefaultClient_ResumeRequest(
+ PKIX_PL_LdapClient *genericClient,
+ void **pPollDesc,
+ PKIX_List **pResponse,
+ void *plContext)
+{
+ PKIX_PL_LdapDefaultClient *client = 0;
+
+ PKIX_ENTER
+ (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_ResumeRequest");
+ PKIX_NULLCHECK_THREE(genericClient, pPollDesc, pResponse);
+
+ PKIX_CHECK(pkix_CheckType
+ ((PKIX_PL_Object *)genericClient,
+ PKIX_LDAPDEFAULTCLIENT_TYPE,
+ plContext),
+ PKIX_GENERICCLIENTNOTANLDAPDEFAULTCLIENT);
+
+ client = (PKIX_PL_LdapDefaultClient *)genericClient;
+
+ PKIX_CHECK(pkix_pl_LdapDefaultClient_Dispatch(client, plContext),
+ PKIX_LDAPDEFAULTCLIENTDISPATCHFAILED);
+
+ /*
+ * It's not enough that we may be done with a particular read.
+ * We're still processing the transaction until we've gotten the
+ * SearchResponseResult message and returned to the BOUND state.
+ * Otherwise we must still have a read pending, and must hold off
+ * on returning results.
+ */
+ if ((client->connectStatus == BOUND) &&
+ (client->entriesFound != NULL)) {
+ *pPollDesc = NULL;
+ *pResponse = client->entriesFound;
+ client->entriesFound = NULL;
+ PKIX_DECREF(client->currentRequest);
+ } else {
+ *pPollDesc = &client->pollDesc;
+ *pResponse = NULL;
+ }
+
+cleanup:
+
+ PKIX_RETURN(LDAPDEFAULTCLIENT);
+
+}
+
+/* --Public-LdapDefaultClient-Functions----------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_LdapDefaultClient_AbandonRequest
+ * DESCRIPTION:
+ *
+ * This function creates and sends an LDAP-protocol "Abandon" message to the
+ * server connected to the LdapDefaultClient pointed to by "client".
+ *
+ * PARAMETERS:
+ * "client"
+ * The LdapDefaultClient whose connection is to be abandoned. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_LdapDefaultClient_AbandonRequest(
+ PKIX_PL_LdapDefaultClient *client,
+ void *plContext)
+{
+ PKIX_Int32 bytesWritten = 0;
+ PKIX_PL_Socket_Callback *callbackList = NULL;
+ SECItem *encoded = NULL;
+
+ PKIX_ENTER(CERTSTORE, "PKIX_PL_LdapDefaultClient_AbandonRequest");
+ PKIX_NULLCHECK_ONE(client);
+
+ if (client->connectStatus == RECV_PENDING) {
+ PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeAbandon
+ (client->arena,
+ (client->messageID) - 1,
+ &encoded,
+ plContext),
+ PKIX_LDAPDEFAULTCLIENTMAKEABANDONFAILED);
+
+ callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
+ PKIX_CHECK(callbackList->sendCallback
+ (client->clientSocket,
+ encoded->data,
+ encoded->len,
+ &bytesWritten,
+ plContext),
+ PKIX_SOCKETSENDFAILED);
+
+ if (bytesWritten < 0) {
+ client->connectStatus = ABANDON_PENDING;
+ } else {
+ client->connectStatus = BOUND;
+ }
+ }
+
+ PKIX_DECREF(client->entriesFound);
+ PKIX_DECREF(client->currentRequest);
+ PKIX_DECREF(client->currentResponse);
+
+cleanup:
+
+ PKIX_DECREF(client);
+
+ PKIX_RETURN(CERTSTORE);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.h
new file mode 100644
index 0000000000..4abe043281
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapdefaultclient.h
@@ -0,0 +1,82 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_ldapdefaultclient.h
+ *
+ * LDAPDefaultClient Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_PL_LDAPDEFAULTCLIENT_H
+#define _PKIX_PL_LDAPDEFAULTCLIENT_H
+
+#include "pkix_pl_ldapt.h"
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * At the time of this version, there are unresolved questions about the LDAP
+ * protocol. Although RFC1777 describes a BIND and UNBIND message, it is not
+ * clear whether they are appropriate to this application. We have tested only
+ * using servers that do not expect authentication, and that reject BIND
+ * messages. It is not clear what values might be appropriate for the bindname
+ * and authentication fields, which are currently implemented as char strings
+ * supplied by the caller. (If this changes, the API and possibly the templates
+ * will have to change.) Therefore the LDAPClient_Create API contains a
+ * BindAPI structure, a union, which will have to be revised and extended when
+ * this area of the protocol is better understood.
+ *
+ */
+
+typedef enum {
+ CONNECT_PENDING,
+ CONNECTED,
+ BIND_PENDING,
+ BIND_RESPONSE,
+ BIND_RESPONSE_PENDING,
+ BOUND,
+ SEND_PENDING,
+ RECV,
+ RECV_PENDING,
+ RECV_INITIAL,
+ RECV_NONINITIAL,
+ ABANDON_PENDING
+} LdapClientConnectStatus;
+
+struct PKIX_PL_LdapDefaultClientStruct {
+ PKIX_PL_LdapClient vtable;
+ LdapClientConnectStatus connectStatus;
+ PKIX_UInt32 messageID;
+ PKIX_PL_HashTable *cachePtr;
+ PKIX_PL_Socket *clientSocket;
+ PRPollDesc pollDesc;
+ void *callbackList; /* cast this to (PKIX_PL_Socket_Callback *) */
+ LDAPBindAPI *bindAPI;
+ PLArenaPool *arena;
+ PRTime lastIO;
+ void *sendBuf;
+ PKIX_UInt32 bytesToWrite;
+ void *rcvBuf;
+ PKIX_UInt32 capacity;
+ void *currentInPtr;
+ PKIX_UInt32 currentBytesAvailable;
+ void *bindMsg;
+ PKIX_UInt32 bindMsgLen;
+ PKIX_List *entriesFound;
+ PKIX_PL_LdapRequest *currentRequest;
+ PKIX_PL_LdapResponse *currentResponse;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_LdapDefaultClient_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_LDAPDEFAULTCLIENT_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c
new file mode 100644
index 0000000000..4546e339a5
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c
@@ -0,0 +1,757 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_ldaprequest.c
+ *
+ */
+
+#include "pkix_pl_ldaprequest.h"
+
+/* --Private-LdapRequest-Functions------------------------------------- */
+
+/* Note: lengths do not include the NULL terminator */
+static const char caAttr[] = "caCertificate;binary";
+static unsigned int caAttrLen = sizeof(caAttr) - 1;
+static const char uAttr[] = "userCertificate;binary";
+static unsigned int uAttrLen = sizeof(uAttr) - 1;
+static const char ccpAttr[] = "crossCertificatePair;binary";
+static unsigned int ccpAttrLen = sizeof(ccpAttr) - 1;
+static const char crlAttr[] = "certificateRevocationList;binary";
+static unsigned int crlAttrLen = sizeof(crlAttr) - 1;
+static const char arlAttr[] = "authorityRevocationList;binary";
+static unsigned int arlAttrLen = sizeof(arlAttr) - 1;
+
+/*
+ * XXX If this function were moved into pkix_pl_ldapcertstore.c then all of
+ * LdapRequest and LdapResponse could be considered part of the LDAP client.
+ * But the constants, above, would have to be copied as well, and they are
+ * also needed in pkix_pl_LdapRequest_EncodeAttrs. So there would have to be
+ * two copies.
+ */
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_AttrTypeToBit
+ * DESCRIPTION:
+ *
+ * This function creates an attribute mask bit corresponding to the SECItem
+ * pointed to by "attrType", storing the result at "pAttrBit". The comparison
+ * is case-insensitive. If "attrType" does not match any of the known types,
+ * zero is stored at "pAttrBit".
+ *
+ * PARAMETERS
+ * "attrType"
+ * The address of the SECItem whose string contents are to be compared to
+ * the various known attribute types. Must be non-NULL.
+ * "pAttrBit"
+ * The address where the result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapRequest Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapRequest_AttrTypeToBit(
+ SECItem *attrType,
+ LdapAttrMask *pAttrBit,
+ void *plContext)
+{
+ LdapAttrMask attrBit = 0;
+ unsigned int attrLen = 0;
+ const char *s = NULL;
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_AttrTypeToBit");
+ PKIX_NULLCHECK_TWO(attrType, pAttrBit);
+
+ s = (const char *)attrType->data;
+ attrLen = attrType->len;
+
+ /*
+ * Taking note of the fact that all of the comparand strings are
+ * different lengths, we do a slight optimization. If a string
+ * length matches but the string does not match, we skip comparing
+ * to the other strings. If new strings are added to the comparand
+ * list, and any are of equal length, be careful to change the
+ * grouping of tests accordingly.
+ */
+ if (attrLen == caAttrLen) {
+ if (PORT_Strncasecmp(caAttr, s, attrLen) == 0) {
+ attrBit = LDAPATTR_CACERT;
+ }
+ } else if (attrLen == uAttrLen) {
+ if (PORT_Strncasecmp(uAttr, s, attrLen) == 0) {
+ attrBit = LDAPATTR_USERCERT;
+ }
+ } else if (attrLen == ccpAttrLen) {
+ if (PORT_Strncasecmp(ccpAttr, s, attrLen) == 0) {
+ attrBit = LDAPATTR_CROSSPAIRCERT;
+ }
+ } else if (attrLen == crlAttrLen) {
+ if (PORT_Strncasecmp(crlAttr, s, attrLen) == 0) {
+ attrBit = LDAPATTR_CERTREVLIST;
+ }
+ } else if (attrLen == arlAttrLen) {
+ if (PORT_Strncasecmp(arlAttr, s, attrLen) == 0) {
+ attrBit = LDAPATTR_AUTHREVLIST;
+ }
+ }
+
+ *pAttrBit = attrBit;
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_AttrStringToBit
+ * DESCRIPTION:
+ *
+ * This function creates an attribute mask bit corresponding to the null-
+ * terminated string pointed to by "attrString", storing the result at
+ * "pAttrBit". The comparison is case-insensitive. If "attrString" does not
+ * match any of the known types, zero is stored at "pAttrBit".
+ *
+ * PARAMETERS
+ * "attrString"
+ * The address of the null-terminated string whose contents are to be compared to
+ * the various known attribute types. Must be non-NULL.
+ * "pAttrBit"
+ * The address where the result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapRequest Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapRequest_AttrStringToBit(
+ char *attrString,
+ LdapAttrMask *pAttrBit,
+ void *plContext)
+{
+ LdapAttrMask attrBit = 0;
+ unsigned int attrLen = 0;
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_AttrStringToBit");
+ PKIX_NULLCHECK_TWO(attrString, pAttrBit);
+
+ attrLen = PL_strlen(attrString);
+
+ /*
+ * Taking note of the fact that all of the comparand strings are
+ * different lengths, we do a slight optimization. If a string
+ * length matches but the string does not match, we skip comparing
+ * to the other strings. If new strings are added to the comparand
+ * list, and any are of equal length, be careful to change the
+ * grouping of tests accordingly.
+ */
+ if (attrLen == caAttrLen) {
+ if (PORT_Strncasecmp(caAttr, attrString, attrLen) == 0) {
+ attrBit = LDAPATTR_CACERT;
+ }
+ } else if (attrLen == uAttrLen) {
+ if (PORT_Strncasecmp(uAttr, attrString, attrLen) == 0) {
+ attrBit = LDAPATTR_USERCERT;
+ }
+ } else if (attrLen == ccpAttrLen) {
+ if (PORT_Strncasecmp(ccpAttr, attrString, attrLen) == 0) {
+ attrBit = LDAPATTR_CROSSPAIRCERT;
+ }
+ } else if (attrLen == crlAttrLen) {
+ if (PORT_Strncasecmp(crlAttr, attrString, attrLen) == 0) {
+ attrBit = LDAPATTR_CERTREVLIST;
+ }
+ } else if (attrLen == arlAttrLen) {
+ if (PORT_Strncasecmp(arlAttr, attrString, attrLen) == 0) {
+ attrBit = LDAPATTR_AUTHREVLIST;
+ }
+ }
+
+ *pAttrBit = attrBit;
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_EncodeAttrs
+ * DESCRIPTION:
+ *
+ * This function obtains the attribute mask bits from the LdapRequest pointed
+ * to by "request", creates the corresponding array of AttributeTypes for the
+ * encoding of the SearchRequest message.
+ *
+ * PARAMETERS
+ * "request"
+ * The address of the LdapRequest whose attributes are to be encoded. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapRequest Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapRequest_EncodeAttrs(
+ PKIX_PL_LdapRequest *request,
+ void *plContext)
+{
+ SECItem **attrArray = NULL;
+ PKIX_UInt32 attrIndex = 0;
+ LdapAttrMask attrBits;
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_EncodeAttrs");
+ PKIX_NULLCHECK_ONE(request);
+
+ /* construct "attrs" according to bits in request->attrBits */
+ attrBits = request->attrBits;
+ attrArray = request->attrArray;
+ if ((attrBits & LDAPATTR_CACERT) == LDAPATTR_CACERT) {
+ attrArray[attrIndex] = &(request->attributes[attrIndex]);
+ request->attributes[attrIndex].type = siAsciiString;
+ request->attributes[attrIndex].data = (unsigned char *)caAttr;
+ request->attributes[attrIndex].len = caAttrLen;
+ attrIndex++;
+ }
+ if ((attrBits & LDAPATTR_USERCERT) == LDAPATTR_USERCERT) {
+ attrArray[attrIndex] = &(request->attributes[attrIndex]);
+ request->attributes[attrIndex].type = siAsciiString;
+ request->attributes[attrIndex].data = (unsigned char *)uAttr;
+ request->attributes[attrIndex].len = uAttrLen;
+ attrIndex++;
+ }
+ if ((attrBits & LDAPATTR_CROSSPAIRCERT) == LDAPATTR_CROSSPAIRCERT) {
+ attrArray[attrIndex] = &(request->attributes[attrIndex]);
+ request->attributes[attrIndex].type = siAsciiString;
+ request->attributes[attrIndex].data = (unsigned char *)ccpAttr;
+ request->attributes[attrIndex].len = ccpAttrLen;
+ attrIndex++;
+ }
+ if ((attrBits & LDAPATTR_CERTREVLIST) == LDAPATTR_CERTREVLIST) {
+ attrArray[attrIndex] = &(request->attributes[attrIndex]);
+ request->attributes[attrIndex].type = siAsciiString;
+ request->attributes[attrIndex].data = (unsigned char *)crlAttr;
+ request->attributes[attrIndex].len = crlAttrLen;
+ attrIndex++;
+ }
+ if ((attrBits & LDAPATTR_AUTHREVLIST) == LDAPATTR_AUTHREVLIST) {
+ attrArray[attrIndex] = &(request->attributes[attrIndex]);
+ request->attributes[attrIndex].type = siAsciiString;
+ request->attributes[attrIndex].data = (unsigned char *)arlAttr;
+ request->attributes[attrIndex].len = arlAttrLen;
+ attrIndex++;
+ }
+ attrArray[attrIndex] = (SECItem *)NULL;
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_LdapRequest_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPREQUEST_TYPE, plContext),
+ PKIX_OBJECTNOTLDAPREQUEST);
+
+ /*
+ * All dynamic fields in an LDAPRequest are allocated
+ * in an arena, and will be freed when the arena is destroyed.
+ */
+
+cleanup:
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_LdapRequest_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_UInt32 dataLen = 0;
+ PKIX_UInt32 dindex = 0;
+ PKIX_UInt32 sizeOfLength = 0;
+ PKIX_UInt32 idLen = 0;
+ const unsigned char *msgBuf = NULL;
+ PKIX_PL_LdapRequest *ldapRq = NULL;
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPREQUEST_TYPE, plContext),
+ PKIX_OBJECTNOTLDAPREQUEST);
+
+ ldapRq = (PKIX_PL_LdapRequest *)object;
+
+ *pHashcode = 0;
+
+ /*
+ * Two requests that differ only in msgnum are a match! Therefore,
+ * start hashcoding beyond the encoded messageID field.
+ */
+ if (ldapRq->encoded) {
+ msgBuf = (const unsigned char *)ldapRq->encoded->data;
+ /* Is message length short form (one octet) or long form? */
+ if ((msgBuf[1] & 0x80) != 0) {
+ sizeOfLength = msgBuf[1] & 0x7F;
+ for (dindex = 0; dindex < sizeOfLength; dindex++) {
+ dataLen = (dataLen << 8) + msgBuf[dindex + 2];
+ }
+ } else {
+ dataLen = msgBuf[1];
+ }
+
+ /* How many bytes for the messageID? (Assume short form) */
+ idLen = msgBuf[dindex + 3] + 2;
+ dindex += idLen;
+ dataLen -= idLen;
+ msgBuf = &msgBuf[dindex + 2];
+
+ PKIX_CHECK(pkix_hash(msgBuf, dataLen, pHashcode, plContext),
+ PKIX_HASHFAILED);
+ }
+
+cleanup:
+
+ PKIX_RETURN(LDAPREQUEST);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_LdapRequest_Equals(
+ PKIX_PL_Object *firstObj,
+ PKIX_PL_Object *secondObj,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_LdapRequest *firstReq = NULL;
+ PKIX_PL_LdapRequest *secondReq = NULL;
+ PKIX_UInt32 secondType = 0;
+ PKIX_UInt32 firstLen = 0;
+ const unsigned char *firstData = NULL;
+ const unsigned char *secondData = NULL;
+ PKIX_UInt32 sizeOfLength = 0;
+ PKIX_UInt32 dindex = 0;
+ PKIX_UInt32 i = 0;
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Equals");
+ PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
+
+ /* test that firstObj is a LdapRequest */
+ PKIX_CHECK(pkix_CheckType(firstObj, PKIX_LDAPREQUEST_TYPE, plContext),
+ PKIX_FIRSTOBJARGUMENTNOTLDAPREQUEST);
+
+ /*
+ * Since we know firstObj is a LdapRequest, if both references are
+ * identical, they must be equal
+ */
+ if (firstObj == secondObj){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObj isn't a LdapRequest, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObj, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_LDAPREQUEST_TYPE) {
+ goto cleanup;
+ }
+
+ firstReq = (PKIX_PL_LdapRequest *)firstObj;
+ secondReq = (PKIX_PL_LdapRequest *)secondObj;
+
+ /* If either lacks an encoded string, they cannot be compared */
+ if (!(firstReq->encoded) || !(secondReq->encoded)) {
+ goto cleanup;
+ }
+
+ if (firstReq->encoded->len != secondReq->encoded->len) {
+ goto cleanup;
+ }
+
+ firstData = (const unsigned char *)firstReq->encoded->data;
+ secondData = (const unsigned char *)secondReq->encoded->data;
+
+ /*
+ * Two requests that differ only in msgnum are equal! Therefore,
+ * start the byte comparison beyond the encoded messageID field.
+ */
+
+ /* Is message length short form (one octet) or long form? */
+ if ((firstData[1] & 0x80) != 0) {
+ sizeOfLength = firstData[1] & 0x7F;
+ for (dindex = 0; dindex < sizeOfLength; dindex++) {
+ firstLen = (firstLen << 8) + firstData[dindex + 2];
+ }
+ } else {
+ firstLen = firstData[1];
+ }
+
+ /* How many bytes for the messageID? (Assume short form) */
+ i = firstData[dindex + 3] + 2;
+ dindex += i;
+ firstLen -= i;
+ firstData = &firstData[dindex + 2];
+
+ /*
+ * In theory, we have to calculate where the second message data
+ * begins by checking its length encodings. But if these messages
+ * are equal, we can re-use the calculation we already did. If they
+ * are not equal, the byte comparisons will surely fail.
+ */
+
+ secondData = &secondData[dindex + 2];
+
+ for (i = 0; i < firstLen; i++) {
+ if (firstData[i] != secondData[i]) {
+ goto cleanup;
+ }
+ }
+
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_LDAPREQUEST_TYPE and its related functions with
+ * systemClasses[]
+ * PARAMETERS:
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_LdapRequest_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_RegisterSelf");
+
+ entry.description = "LdapRequest";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_LdapRequest);
+ entry.destructor = pkix_pl_LdapRequest_Destroy;
+ entry.equalsFunction = pkix_pl_LdapRequest_Equals;
+ entry.hashcodeFunction = pkix_pl_LdapRequest_Hashcode;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_LDAPREQUEST_TYPE] = entry;
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_Create
+ * DESCRIPTION:
+ *
+ * This function creates an LdapRequest using the PLArenaPool pointed to by
+ * "arena", a message number whose value is "msgnum", a base object pointed to
+ * by "issuerDN", a scope whose value is "scope", a derefAliases flag whose
+ * value is "derefAliases", a sizeLimit whose value is "sizeLimit", a timeLimit
+ * whose value is "timeLimit", an attrsOnly flag whose value is "attrsOnly", a
+ * filter whose value is "filter", and attribute bits whose value is
+ * "attrBits"; storing the result at "pRequestMsg".
+ *
+ * See pkix_pl_ldaptemplates.c (and below) for the ASN.1 representation of
+ * message components, and see pkix_pl_ldapt.h for data types.
+ *
+ * PARAMETERS
+ * "arena"
+ * The address of the PLArenaPool to be used in the encoding. Must be
+ * non-NULL.
+ * "msgnum"
+ * The UInt32 message number to be used for the messageID component of the
+ * LDAP message exchange.
+ * "issuerDN"
+ * The address of the string to be used for the baseObject component of the
+ * LDAP SearchRequest message. Must be non-NULL.
+ * "scope"
+ * The (enumerated) ScopeType to be used for the scope component of the
+ * LDAP SearchRequest message
+ * "derefAliases"
+ * The (enumerated) DerefType to be used for the derefAliases component of
+ * the LDAP SearchRequest message
+ * "sizeLimit"
+ * The UInt32 value to be used for the sizeLimit component of the LDAP
+ * SearchRequest message
+ * "timeLimit"
+ * The UInt32 value to be used for the timeLimit component of the LDAP
+ * SearchRequest message
+ * "attrsOnly"
+ * The Boolean value to be used for the attrsOnly component of the LDAP
+ * SearchRequest message
+ * "filter"
+ * The filter to be used for the filter component of the LDAP
+ * SearchRequest message
+ * "attrBits"
+ * The LdapAttrMask bits indicating the attributes to be included in the
+ * attributes sequence of the LDAP SearchRequest message
+ * "pRequestMsg"
+ * The address at which the address of the LdapRequest is stored. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapRequest Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+/*
+ * SearchRequest ::=
+ * [APPLICATION 3] SEQUENCE {
+ * baseObject LDAPDN,
+ * scope ENUMERATED {
+ * baseObject (0),
+ * singleLevel (1),
+ * wholeSubtree (2)
+ * },
+ * derefAliases ENUMERATED {
+ * neverDerefAliases (0),
+ * derefInSearching (1),
+ * derefFindingBaseObj (2),
+ * alwaysDerefAliases (3)
+ * },
+ * sizeLimit INTEGER (0 .. MAXINT),
+ * -- value of 0 implies no sizeLimit
+ * timeLimit INTEGER (0 .. MAXINT),
+ * -- value of 0 implies no timeLimit
+ * attrsOnly BOOLEAN,
+ * -- TRUE, if only attributes (without values)
+ * -- to be returned
+ * filter Filter,
+ * attributes SEQUENCE OF AttributeType
+ * }
+ *
+ * Filter ::=
+ * CHOICE {
+ * and [0] SET OF Filter,
+ * or [1] SET OF Filter,
+ * not [2] Filter,
+ * equalityMatch [3] AttributeValueAssertion,
+ * substrings [4] SubstringFilter,
+ * greaterOrEqual [5] AttributeValueAssertion,
+ * lessOrEqual [6] AttributeValueAssertion,
+ * present [7] AttributeType,
+ * approxMatch [8] AttributeValueAssertion
+ * }
+ *
+ * SubstringFilter ::=
+ * SEQUENCE {
+ * type AttributeType,
+ * SEQUENCE OF CHOICE {
+ * initial [0] LDAPString,
+ * any [1] LDAPString,
+ * final [2] LDAPString,
+ * }
+ * }
+ *
+ * AttributeValueAssertion ::=
+ * SEQUENCE {
+ * attributeType AttributeType,
+ * attributeValue AttributeValue,
+ * }
+ *
+ * AttributeValue ::= OCTET STRING
+ *
+ * AttributeType ::= LDAPString
+ * -- text name of the attribute, or dotted
+ * -- OID representation
+ *
+ * LDAPDN ::= LDAPString
+ *
+ * LDAPString ::= OCTET STRING
+ *
+ */
+PKIX_Error *
+pkix_pl_LdapRequest_Create(
+ PLArenaPool *arena,
+ PKIX_UInt32 msgnum,
+ char *issuerDN,
+ ScopeType scope,
+ DerefType derefAliases,
+ PKIX_UInt32 sizeLimit,
+ PKIX_UInt32 timeLimit,
+ char attrsOnly,
+ LDAPFilter *filter,
+ LdapAttrMask attrBits,
+ PKIX_PL_LdapRequest **pRequestMsg,
+ void *plContext)
+{
+ LDAPMessage msg;
+ LDAPSearch *search;
+ PKIX_PL_LdapRequest *ldapRequest = NULL;
+ char scopeTypeAsChar;
+ char derefAliasesTypeAsChar;
+ SECItem *attrArray[MAX_LDAPATTRS + 1];
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Create");
+ PKIX_NULLCHECK_THREE(arena, issuerDN, pRequestMsg);
+
+ /* create a PKIX_PL_LdapRequest object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_LDAPREQUEST_TYPE,
+ sizeof (PKIX_PL_LdapRequest),
+ (PKIX_PL_Object **)&ldapRequest,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ ldapRequest->arena = arena;
+ ldapRequest->msgnum = msgnum;
+ ldapRequest->issuerDN = issuerDN;
+ ldapRequest->scope = scope;
+ ldapRequest->derefAliases = derefAliases;
+ ldapRequest->sizeLimit = sizeLimit;
+ ldapRequest->timeLimit = timeLimit;
+ ldapRequest->attrsOnly = attrsOnly;
+ ldapRequest->filter = filter;
+ ldapRequest->attrBits = attrBits;
+
+ ldapRequest->attrArray = attrArray;
+
+ PKIX_CHECK(pkix_pl_LdapRequest_EncodeAttrs
+ (ldapRequest, plContext),
+ PKIX_LDAPREQUESTENCODEATTRSFAILED);
+
+ PKIX_PL_NSSCALL
+ (LDAPREQUEST, PORT_Memset, (&msg, 0, sizeof (LDAPMessage)));
+
+ msg.messageID.type = siUnsignedInteger;
+ msg.messageID.data = (void*)&msgnum;
+ msg.messageID.len = sizeof (msgnum);
+
+ msg.protocolOp.selector = LDAP_SEARCH_TYPE;
+
+ search = &(msg.protocolOp.op.searchMsg);
+
+ search->baseObject.type = siAsciiString;
+ search->baseObject.data = (void *)issuerDN;
+ search->baseObject.len = PL_strlen(issuerDN);
+ scopeTypeAsChar = (char)scope;
+ search->scope.type = siUnsignedInteger;
+ search->scope.data = (void *)&scopeTypeAsChar;
+ search->scope.len = sizeof (scopeTypeAsChar);
+ derefAliasesTypeAsChar = (char)derefAliases;
+ search->derefAliases.type = siUnsignedInteger;
+ search->derefAliases.data =
+ (void *)&derefAliasesTypeAsChar;
+ search->derefAliases.len =
+ sizeof (derefAliasesTypeAsChar);
+ search->sizeLimit.type = siUnsignedInteger;
+ search->sizeLimit.data = (void *)&sizeLimit;
+ search->sizeLimit.len = sizeof (PKIX_UInt32);
+ search->timeLimit.type = siUnsignedInteger;
+ search->timeLimit.data = (void *)&timeLimit;
+ search->timeLimit.len = sizeof (PKIX_UInt32);
+ search->attrsOnly.type = siBuffer;
+ search->attrsOnly.data = (void *)&attrsOnly;
+ search->attrsOnly.len = sizeof (attrsOnly);
+
+ PKIX_PL_NSSCALL
+ (LDAPREQUEST,
+ PORT_Memcpy,
+ (&search->filter, filter, sizeof (LDAPFilter)));
+
+ search->attributes = attrArray;
+
+ PKIX_PL_NSSCALLRV
+ (LDAPREQUEST, ldapRequest->encoded, SEC_ASN1EncodeItem,
+ (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate));
+
+ if (!(ldapRequest->encoded)) {
+ PKIX_ERROR(PKIX_FAILEDINENCODINGSEARCHREQUEST);
+ }
+
+ *pRequestMsg = ldapRequest;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(ldapRequest);
+ }
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_GetEncoded
+ * DESCRIPTION:
+ *
+ * This function obtains the encoded message from the LdapRequest pointed to
+ * by "request", storing the result at "pRequestBuf".
+ *
+ * PARAMETERS
+ * "request"
+ * The address of the LdapRequest whose encoded message is to be
+ * retrieved. Must be non-NULL.
+ * "pRequestBuf"
+ * The address at which is stored the address of the encoded message. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapRequest Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapRequest_GetEncoded(
+ PKIX_PL_LdapRequest *request,
+ SECItem **pRequestBuf,
+ void *plContext)
+{
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_GetEncoded");
+ PKIX_NULLCHECK_TWO(request, pRequestBuf);
+
+ *pRequestBuf = request->encoded;
+
+ PKIX_RETURN(LDAPREQUEST);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.h
new file mode 100644
index 0000000000..1d05a9447e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.h
@@ -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/. */
+/*
+ * pkix_pl_ldaprequest.h
+ *
+ * LdapRequest Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_LDAPREQUEST_H
+#define _PKIX_PL_LDAPREQUEST_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ USER_CERT,
+ CA_CERT,
+ CROSS_CERT,
+ CRL,
+ ARL,
+ DELTA_CRL
+} PKIX_PL_LdapAttr;
+
+struct PKIX_PL_LdapRequestStruct{
+ PLArenaPool *arena;
+ PKIX_UInt32 msgnum;
+ char *issuerDN;
+ ScopeType scope;
+ DerefType derefAliases;
+ PKIX_UInt32 sizeLimit;
+ PKIX_UInt32 timeLimit;
+ char attrsOnly;
+ LDAPFilter *filter;
+ LdapAttrMask attrBits;
+ SECItem attributes[MAX_LDAPATTRS];
+ SECItem **attrArray;
+ SECItem *encoded;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_LdapRequest_Create(
+ PLArenaPool *arena,
+ PKIX_UInt32 msgnum,
+ char *issuerDN,
+ ScopeType scope,
+ DerefType derefAliases,
+ PKIX_UInt32 sizeLimit,
+ PKIX_UInt32 timeLimit,
+ char attrsOnly,
+ LDAPFilter *filter,
+ LdapAttrMask attrBits,
+ PKIX_PL_LdapRequest **pRequestMsg,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_LdapRequest_AttrTypeToBit(
+ SECItem *attrType,
+ LdapAttrMask *pAttrBit,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_LdapRequest_AttrStringToBit(
+ char *attrString,
+ LdapAttrMask *pAttrBit,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_LdapRequest_GetEncoded(
+ PKIX_PL_LdapRequest *request,
+ SECItem **pRequestBuf,
+ void *plContext);
+
+PKIX_Error *pkix_pl_LdapRequest_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_LDAPREQUEST_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.c
new file mode 100644
index 0000000000..cd2543f3be
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.c
@@ -0,0 +1,786 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_ldapresponse.c
+ *
+ */
+
+#include <fcntl.h>
+#include "pkix_pl_ldapresponse.h"
+
+/* --Private-LdapResponse-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_LdapResponse_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_LdapResponse_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_LdapResponse *ldapRsp = NULL;
+ LDAPMessage *m = NULL;
+ LDAPSearchResponseEntry *entry = NULL;
+ LDAPSearchResponseResult *result = NULL;
+ LDAPSearchResponseAttr **attributes = NULL;
+ LDAPSearchResponseAttr *attr = NULL;
+ SECItem **valp = NULL;
+ SECItem *val = NULL;
+
+ PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPRESPONSE_TYPE, plContext),
+ PKIX_OBJECTNOTLDAPRESPONSE);
+
+ ldapRsp = (PKIX_PL_LdapResponse *)object;
+
+ m = &ldapRsp->decoded;
+
+ if (m->messageID.data != NULL) {
+ PR_Free(m->messageID.data);
+ }
+
+ if (m->protocolOp.selector ==
+ LDAP_SEARCHRESPONSEENTRY_TYPE) {
+ entry = &m->protocolOp.op.searchResponseEntryMsg;
+ if (entry->objectName.data != NULL) {
+ PR_Free(entry->objectName.data);
+ }
+ if (entry->attributes != NULL) {
+ for (attributes = entry->attributes;
+ *attributes != NULL;
+ attributes++) {
+ attr = *attributes;
+ PR_Free(attr->attrType.data);
+ for (valp = attr->val; *valp != NULL; valp++) {
+ val = *valp;
+ if (val->data != NULL) {
+ PR_Free(val->data);
+ }
+ PR_Free(val);
+ }
+ PR_Free(attr->val);
+ PR_Free(attr);
+ }
+ PR_Free(entry->attributes);
+ }
+ } else if (m->protocolOp.selector ==
+ LDAP_SEARCHRESPONSERESULT_TYPE) {
+ result = &m->protocolOp.op.searchResponseResultMsg;
+ if (result->resultCode.data != NULL) {
+ PR_Free(result->resultCode.data);
+ }
+ }
+
+ PKIX_FREE(ldapRsp->derEncoded.data);
+
+cleanup:
+
+ PKIX_RETURN(LDAPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapResponse_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_LdapResponse_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_UInt32 dataLen = 0;
+ PKIX_UInt32 dindex = 0;
+ PKIX_UInt32 sizeOfLength = 0;
+ PKIX_UInt32 idLen = 0;
+ const unsigned char *msgBuf = NULL;
+ PKIX_PL_LdapResponse *ldapRsp = NULL;
+
+ PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPRESPONSE_TYPE, plContext),
+ PKIX_OBJECTNOTLDAPRESPONSE);
+
+ ldapRsp = (PKIX_PL_LdapResponse *)object;
+
+ *pHashcode = 0;
+
+ /*
+ * Two responses that differ only in msgnum are a match! Therefore,
+ * start hashcoding beyond the encoded messageID field.
+ */
+ if (ldapRsp->derEncoded.data) {
+ msgBuf = (const unsigned char *)ldapRsp->derEncoded.data;
+ /* Is message length short form (one octet) or long form? */
+ if ((msgBuf[1] & 0x80) != 0) {
+ sizeOfLength = msgBuf[1] & 0x7F;
+ for (dindex = 0; dindex < sizeOfLength; dindex++) {
+ dataLen = (dataLen << 8) + msgBuf[dindex + 2];
+ }
+ } else {
+ dataLen = msgBuf[1];
+ }
+
+ /* How many bytes for the messageID? (Assume short form) */
+ idLen = msgBuf[dindex + 3] + 2;
+ dindex += idLen;
+ dataLen -= idLen;
+ msgBuf = &msgBuf[dindex + 2];
+
+ PKIX_CHECK(pkix_hash(msgBuf, dataLen, pHashcode, plContext),
+ PKIX_HASHFAILED);
+ }
+
+cleanup:
+
+ PKIX_RETURN(LDAPRESPONSE);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapResponse_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_LdapResponse_Equals(
+ PKIX_PL_Object *firstObj,
+ PKIX_PL_Object *secondObj,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_LdapResponse *rsp1 = NULL;
+ PKIX_PL_LdapResponse *rsp2 = NULL;
+ PKIX_UInt32 secondType = 0;
+ PKIX_UInt32 firstLen = 0;
+ const unsigned char *firstData = NULL;
+ const unsigned char *secondData = NULL;
+ PKIX_UInt32 sizeOfLength = 0;
+ PKIX_UInt32 dindex = 0;
+ PKIX_UInt32 i = 0;
+
+ PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Equals");
+ PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
+
+ /* test that firstObj is a LdapResponse */
+ PKIX_CHECK(pkix_CheckType(firstObj, PKIX_LDAPRESPONSE_TYPE, plContext),
+ PKIX_FIRSTOBJARGUMENTNOTLDAPRESPONSE);
+
+ /*
+ * Since we know firstObj is a LdapResponse, if both references are
+ * identical, they must be equal
+ */
+ if (firstObj == secondObj){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObj isn't a LdapResponse, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType(secondObj, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_LDAPRESPONSE_TYPE) {
+ goto cleanup;
+ }
+
+ rsp1 = (PKIX_PL_LdapResponse *)firstObj;
+ rsp2 = (PKIX_PL_LdapResponse *)secondObj;
+
+ /* If either lacks an encoded string, they cannot be compared */
+ if (!(rsp1->derEncoded.data) || !(rsp2->derEncoded.data)) {
+ goto cleanup;
+ }
+
+ if (rsp1->derEncoded.len != rsp2->derEncoded.len) {
+ goto cleanup;
+ }
+
+ firstData = (const unsigned char *)rsp1->derEncoded.data;
+ secondData = (const unsigned char *)rsp2->derEncoded.data;
+
+ /*
+ * Two responses that differ only in msgnum are equal! Therefore,
+ * start the byte comparison beyond the encoded messageID field.
+ */
+
+ /* Is message length short form (one octet) or long form? */
+ if ((firstData[1] & 0x80) != 0) {
+ sizeOfLength = firstData[1] & 0x7F;
+ for (dindex = 0; dindex < sizeOfLength; dindex++) {
+ firstLen = (firstLen << 8) + firstData[dindex + 2];
+ }
+ } else {
+ firstLen = firstData[1];
+ }
+
+ /* How many bytes for the messageID? (Assume short form) */
+ i = firstData[dindex + 3] + 2;
+ dindex += i;
+ firstLen -= i;
+ firstData = &firstData[dindex + 2];
+
+ /*
+ * In theory, we have to calculate where the second message data
+ * begins by checking its length encodings. But if these messages
+ * are equal, we can re-use the calculation we already did. If they
+ * are not equal, the byte comparisons will surely fail.
+ */
+
+ secondData = &secondData[dindex + 2];
+
+ for (i = 0; i < firstLen; i++) {
+ if (firstData[i] != secondData[i]) {
+ goto cleanup;
+ }
+ }
+
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(LDAPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapResponse_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_LDAPRESPONSE_TYPE and its related functions with
+ * systemClasses[]
+ * PARAMETERS:
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_LdapResponse_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_RegisterSelf");
+
+ entry.description = "LdapResponse";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_LdapResponse);
+ entry.destructor = pkix_pl_LdapResponse_Destroy;
+ entry.equalsFunction = pkix_pl_LdapResponse_Equals;
+ entry.hashcodeFunction = pkix_pl_LdapResponse_Hashcode;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_LDAPRESPONSE_TYPE] = entry;
+
+ PKIX_RETURN(LDAPRESPONSE);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_LdapResponse_Create
+ * DESCRIPTION:
+ *
+ * This function creates an LdapResponse for the LDAPMessageType provided in
+ * "responseType" and a buffer capacity provided by "totalLength". It copies
+ * into its buffer either "totalLength" or "bytesAvailable" bytes, whichever
+ * is less, from the buffer pointed to by "partialData", storing the number of
+ * bytes copied at "pBytesConsumed" and storing the address of the LdapResponse
+ * at "pLdapResponse".
+ *
+ * If a message is complete in a single I/O buffer, the LdapResponse will be
+ * complete when this function returns. If the message carries over into
+ * additional buffers, their contents will be added to the LdapResponse by
+ * susequent calls to pkix_pl_LdapResponse_Append.
+ *
+ * PARAMETERS
+ * "responseType"
+ * The value of the message type (LDAP_SEARCHRESPONSEENTRY_TYPE or
+ * LDAP_SEARCHRESPONSERESULT_TYPE) for the LdapResponse being created
+ * "totalLength"
+ * The UInt32 value for the total length of the encoded message to be
+ * stored in the LdapResponse
+ * "bytesAvailable"
+ * The UInt32 value for the number of bytes of data available in the
+ * current buffer.
+ * "partialData"
+ * The address from which data is to be copied.
+ * "pBytesConsumed"
+ * The address at which is stored the UInt32 number of bytes taken from the
+ * current buffer. If this number is less than "bytesAvailable", then bytes
+ * remain in the buffer for the next LdapResponse. Must be non-NULL.
+ * "pLdapResponse"
+ * The address where the created LdapResponse is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapResponse_Create(
+ LDAPMessageType responseType,
+ PKIX_UInt32 totalLength,
+ PKIX_UInt32 bytesAvailable,
+ void *partialData,
+ PKIX_UInt32 *pBytesConsumed,
+ PKIX_PL_LdapResponse **pLdapResponse,
+ void *plContext)
+{
+ PKIX_UInt32 bytesConsumed = 0;
+ PKIX_PL_LdapResponse *ldapResponse = NULL;
+ void *data = NULL;
+
+ PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Create");
+ PKIX_NULLCHECK_ONE(pLdapResponse);
+
+ if (bytesAvailable <= totalLength) {
+ bytesConsumed = bytesAvailable;
+ } else {
+ bytesConsumed = totalLength;
+ }
+
+ /* create a PKIX_PL_LdapResponse object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_LDAPRESPONSE_TYPE,
+ sizeof (PKIX_PL_LdapResponse),
+ (PKIX_PL_Object **)&ldapResponse,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ ldapResponse->decoded.protocolOp.selector = responseType;
+ ldapResponse->totalLength = totalLength;
+ ldapResponse->partialLength = bytesConsumed;
+
+ if (totalLength != 0){
+ /* Alloc space for array */
+ PKIX_NULLCHECK_ONE(partialData);
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (totalLength,
+ &data,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ PKIX_PL_NSSCALL
+ (LDAPRESPONSE,
+ PORT_Memcpy,
+ (data, partialData, bytesConsumed));
+ }
+
+ ldapResponse->derEncoded.type = siBuffer;
+ ldapResponse->derEncoded.data = data;
+ ldapResponse->derEncoded.len = totalLength;
+ *pBytesConsumed = bytesConsumed;
+ *pLdapResponse = ldapResponse;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(ldapResponse);
+ }
+
+ PKIX_RETURN(LDAPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapResponse_Append
+ * DESCRIPTION:
+ *
+ * This function updates the LdapResponse pointed to by "response" with up to
+ * "incrLength" from the buffer pointer to by "incrData", storing the number of
+ * bytes copied at "pBytesConsumed".
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the LdapResponse being updated. Must be non-zero.
+ * "incrLength"
+ * The UInt32 value for the number of bytes of data available in the
+ * current buffer.
+ * "incrData"
+ * The address from which data is to be copied.
+ * "pBytesConsumed"
+ * The address at which is stored the UInt32 number of bytes taken from the
+ * current buffer. If this number is less than "incrLength", then bytes
+ * remain in the buffer for the next LdapResponse. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapResponse_Append(
+ PKIX_PL_LdapResponse *response,
+ PKIX_UInt32 incrLength,
+ void *incrData,
+ PKIX_UInt32 *pBytesConsumed,
+ void *plContext)
+{
+ PKIX_UInt32 newPartialLength = 0;
+ PKIX_UInt32 bytesConsumed = 0;
+ void *dest = NULL;
+
+ PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Append");
+ PKIX_NULLCHECK_TWO(response, pBytesConsumed);
+
+ if (incrLength > 0) {
+
+ /* Calculate how many bytes we have room for. */
+ bytesConsumed =
+ response->totalLength - response->partialLength;
+
+ if (bytesConsumed > incrLength) {
+ bytesConsumed = incrLength;
+ }
+
+ newPartialLength = response->partialLength + bytesConsumed;
+
+ PKIX_NULLCHECK_ONE(incrData);
+
+ dest = &(((char *)response->derEncoded.data)[
+ response->partialLength]);
+
+ PKIX_PL_NSSCALL
+ (LDAPRESPONSE,
+ PORT_Memcpy,
+ (dest, incrData, bytesConsumed));
+
+ response->partialLength = newPartialLength;
+ }
+
+ *pBytesConsumed = bytesConsumed;
+
+ PKIX_RETURN(LDAPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapResponse_IsComplete
+ * DESCRIPTION:
+ *
+ * This function determines whether the LdapResponse pointed to by "response"
+ * contains all the data called for by the "totalLength" parameter provided
+ * when it was created, storing PKIX_TRUE at "pIsComplete" if so, and
+ * PKIX_FALSE otherwise.
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the LdapResponse being evaluaTED. Must be non-zero.
+ * "incrLength"
+ * The UInt32 value for the number of bytes of data available in the
+ * current buffer.
+ * "incrData"
+ * The address from which data is to be copied.
+ * "pIsComplete"
+ * The address at which is stored the Boolean indication of whether the
+ * LdapResponse is complete. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapResponse_IsComplete(
+ PKIX_PL_LdapResponse *response,
+ PKIX_Boolean *pIsComplete,
+ void *plContext)
+{
+ PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_IsComplete");
+ PKIX_NULLCHECK_TWO(response, pIsComplete);
+
+ if (response->totalLength == response->partialLength) {
+ *pIsComplete = PKIX_TRUE;
+ } else {
+ *pIsComplete = PKIX_FALSE;
+ }
+
+ PKIX_RETURN(LDAPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapResponse_Decode
+ * DESCRIPTION:
+ *
+ * This function decodes the DER data contained in the LdapResponse pointed to
+ * by "response", using the arena pointed to by "arena", and storing at
+ * "pStatus" SECSuccess if the decoding was successful and SECFailure
+ * otherwise. The decoded message is stored in an element of "response".
+ *
+ * PARAMETERS
+ * "arena"
+ * The address of the PLArenaPool to be used in the decoding. Must be
+ * non-NULL.
+ * "response"
+ * The address of the LdapResponse whose DER data is to be decoded. Must
+ * be non-NULL.
+ * "pStatus"
+ * The address at which is stored the status from the decoding, SECSuccess
+ * if successful, SECFailure otherwise. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapResponse_Decode(
+ PLArenaPool *arena,
+ PKIX_PL_LdapResponse *response,
+ SECStatus *pStatus,
+ void *plContext)
+{
+ LDAPMessage *msg;
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Decode");
+ PKIX_NULLCHECK_THREE(arena, response, pStatus);
+
+ if (response->totalLength != response->partialLength) {
+ PKIX_ERROR(PKIX_ATTEMPTTODECODEANINCOMPLETERESPONSE);
+ }
+
+ msg = &(response->decoded);
+
+ PKIX_PL_NSSCALL
+ (LDAPRESPONSE, PORT_Memset, (msg, 0, sizeof (LDAPMessage)));
+
+ PKIX_PL_NSSCALLRV(LDAPRESPONSE, rv, SEC_ASN1DecodeItem,
+ (NULL, msg, PKIX_PL_LDAPMessageTemplate, &(response->derEncoded)));
+
+ *pStatus = rv;
+cleanup:
+
+ PKIX_RETURN(LDAPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapResponse_GetMessage
+ * DESCRIPTION:
+ *
+ * This function obtains the decoded message from the LdapResponse pointed to
+ * by "response", storing the result at "pMessage".
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the LdapResponse whose decoded message is to be
+ * retrieved. Must be non-NULL.
+ * "pMessage"
+ * The address at which is stored the address of the decoded message. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapResponse_GetMessage(
+ PKIX_PL_LdapResponse *response,
+ LDAPMessage **pMessage,
+ void *plContext)
+{
+ PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetMessage");
+ PKIX_NULLCHECK_TWO(response, pMessage);
+
+ *pMessage = &response->decoded;
+
+ PKIX_RETURN(LDAPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapResponse_GetCapacity
+ * DESCRIPTION:
+ *
+ * This function obtains from the LdapResponse pointed to by "response" the
+ * number of bytes remaining to be read, based on the totalLength that was
+ * provided to LdapResponse_Create and the data subsequently provided to
+ * LdapResponse_Append, storing the result at "pMessage".
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the LdapResponse whose remaining capacity is to be
+ * retrieved. Must be non-NULL.
+ * "pCapacity"
+ * The address at which is stored the address of the decoded message. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapResponse_GetCapacity(
+ PKIX_PL_LdapResponse *response,
+ PKIX_UInt32 *pCapacity,
+ void *plContext)
+{
+ PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetCapacity");
+ PKIX_NULLCHECK_TWO(response, pCapacity);
+
+ *pCapacity = response->totalLength - response->partialLength;
+
+ PKIX_RETURN(LDAPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapResponse_GetMessageType
+ * DESCRIPTION:
+ *
+ * This function obtains the message type from the LdapResponse pointed to
+ * by "response", storing the result at "pMessageType".
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the LdapResponse whose message type is to be
+ * retrieved. Must be non-NULL.
+ * "pMessageType"
+ * The address at which is stored the type of the response message. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapResponse_GetMessageType(
+ PKIX_PL_LdapResponse *response,
+ LDAPMessageType *pMessageType,
+ void *plContext)
+{
+ PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetMessageType");
+ PKIX_NULLCHECK_TWO(response, pMessageType);
+
+ *pMessageType = response->decoded.protocolOp.selector;
+
+ PKIX_RETURN(LDAPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapResponse_GetResultCode
+ * DESCRIPTION:
+ *
+ * This function obtains the result code from the LdapResponse pointed to
+ * by "response", storing the result at "pResultCode".
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the LdapResponse whose result code is to be
+ * retrieved. Must be non-NULL.
+ * "pResultCode"
+ * The address at which is stored the address of the decoded message. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapResponse_GetResultCode(
+ PKIX_PL_LdapResponse *response,
+ LDAPResultCode *pResultCode,
+ void *plContext)
+{
+ LDAPMessageType messageType = 0;
+ LDAPSearchResponseResult *resultMsg = NULL;
+
+ PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetResultCode");
+ PKIX_NULLCHECK_TWO(response, pResultCode);
+
+ messageType = response->decoded.protocolOp.selector;
+
+ if (messageType != LDAP_SEARCHRESPONSERESULT_TYPE) {
+ PKIX_ERROR(PKIX_GETRESULTCODECALLEDFORNONRESULTMESSAGE);
+ }
+
+ resultMsg = &response->decoded.protocolOp.op.searchResponseResultMsg;
+
+ *pResultCode = *(resultMsg->resultCode.data);
+
+cleanup:
+
+ PKIX_RETURN(LDAPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapResponse_GetAttributes
+ * DESCRIPTION:
+ *
+ * This function obtains the attributes from the LdapResponse pointed to
+ * by "response", storing the result at "pAttributes".
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the LdapResponse whose decoded message is to be
+ * retrieved. Must be non-NULL.
+ * "pAttributes"
+ * The address at which is stored the attributes of the message. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapResponse_GetAttributes(
+ PKIX_PL_LdapResponse *response,
+ LDAPSearchResponseAttr ***pAttributes,
+ void *plContext)
+{
+ LDAPMessageType messageType = 0;
+
+ PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetResultCode");
+ PKIX_NULLCHECK_TWO(response, pAttributes);
+
+ messageType = response->decoded.protocolOp.selector;
+
+ if (messageType != LDAP_SEARCHRESPONSEENTRY_TYPE) {
+ PKIX_ERROR(PKIX_GETATTRIBUTESCALLEDFORNONENTRYMESSAGE);
+ }
+
+ *pAttributes = response->
+ decoded.protocolOp.op.searchResponseEntryMsg.attributes;
+
+cleanup:
+
+ PKIX_RETURN(LDAPRESPONSE);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.h
new file mode 100644
index 0000000000..37dc916b1e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.h
@@ -0,0 +1,96 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_ldapresponse.h
+ *
+ * LdapResponse Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_LDAPRESPONSE_H
+#define _PKIX_PL_LDAPRESPONSE_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_LdapResponseStruct{
+ LDAPMessage decoded;
+ PKIX_UInt32 partialLength;
+ PKIX_UInt32 totalLength;
+ SECItem derEncoded;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_LdapResponse_Create(
+ LDAPMessageType responseType,
+ PKIX_UInt32 totalLength,
+ PKIX_UInt32 bytesAvailable,
+ void *partialData,
+ PKIX_UInt32 *pBytesConsumed,
+ PKIX_PL_LdapResponse **pResponse,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_LdapResponse_Append(
+ PKIX_PL_LdapResponse *response,
+ PKIX_UInt32 partialLength,
+ void *partialData,
+ PKIX_UInt32 *bytesConsumed,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_LdapResponse_IsComplete(
+ PKIX_PL_LdapResponse *response,
+ PKIX_Boolean *pIsComplete,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_LdapResponse_Decode(
+ PLArenaPool *arena,
+ PKIX_PL_LdapResponse *response,
+ SECStatus *pStatus,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_LdapResponse_GetMessage(
+ PKIX_PL_LdapResponse *response,
+ LDAPMessage **pMessage,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_LdapResponse_GetMessageType(
+ PKIX_PL_LdapResponse *response,
+ LDAPMessageType *pMessageType,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_LdapResponse_GetCapacity(
+ PKIX_PL_LdapResponse *response,
+ PKIX_UInt32 *pCapacity,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_LdapResponse_GetResultCode(
+ PKIX_PL_LdapResponse *response,
+ LDAPResultCode *pResultCode,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_LdapResponse_GetAttributes(
+ PKIX_PL_LdapResponse *response,
+ LDAPSearchResponseAttr ***pAttributes,
+ void *plContext);
+
+PKIX_Error *pkix_pl_LdapResponse_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_LDAPRESPONSE_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapt.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapt.h
new file mode 100644
index 0000000000..539803638c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapt.h
@@ -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/. */
+
+#ifndef _LDAP_H_
+#define _LDAP_H_
+
+#include "certt.h"
+#include "pkixt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const SEC_ASN1Template PKIX_PL_LDAPCrossCertPairTemplate[];
+SEC_ASN1_CHOOSER_DECLARE(PKIX_PL_LDAPCrossCertPairTemplate)
+extern const SEC_ASN1Template PKIX_PL_LDAPMessageTemplate[];
+SEC_ASN1_CHOOSER_DECLARE(PKIX_PL_LDAPMessageTemplate)
+extern const SEC_ASN1Template LDAPFilterTemplate[];
+SEC_ASN1_CHOOSER_DECLARE(LDAPFilterTemplate)
+
+/* ********************************************************************** */
+
+#define SEC_ASN1_LDAP_STRING SEC_ASN1_OCTET_STRING
+
+#define LDAPATTR_CACERT (1<<0)
+#define LDAPATTR_USERCERT (1<<1)
+#define LDAPATTR_CROSSPAIRCERT (1<<2)
+#define LDAPATTR_CERTREVLIST (1<<3)
+#define LDAPATTR_AUTHREVLIST (1<<4)
+#define MAX_LDAPATTRS 5
+typedef PKIX_UInt32 LdapAttrMask;
+
+typedef enum {
+ SIMPLE_AUTH = 0,
+ KRBV42LDAP_AUTH = 1,
+ KRBV42DSA_AUTH = 2
+} AuthType;
+
+typedef enum {
+ BASE_OBJECT = 0,
+ SINGLE_LEVEL = 1,
+ WHOLE_SUBTREE = 2
+} ScopeType;
+
+typedef enum {
+ NEVER_DEREF = 0,
+ DEREF_IN_SEARCHING = 1,
+ DEREF_FINDING_BASEOBJ = 2,
+ ALWAYS_DEREF = 3
+} DerefType;
+
+typedef enum {
+ LDAP_INITIALSUBSTRING_TYPE = 0,
+ LDAP_ANYSUBSTRING_TYPE = 1,
+ LDAP_FINALSUBSTRING_TYPE = 2
+} LDAPSubstringFilterType;
+
+typedef enum {
+ LDAP_ANDFILTER_TYPE = 0,
+ LDAP_ORFILTER_TYPE = 1,
+ LDAP_NOTFILTER_TYPE = 2,
+ LDAP_EQUALFILTER_TYPE = 3,
+ LDAP_SUBSTRINGFILTER_TYPE = 4,
+ LDAP_GREATEROREQUALFILTER_TYPE = 5,
+ LDAP_LESSOREQUALFILTER_TYPE = 6,
+ LDAP_PRESENTFILTER_TYPE = 7,
+ LDAP_APPROXMATCHFILTER_TYPE = 8
+} LDAPFilterType;
+
+typedef enum {
+ LDAP_BIND_TYPE = 0,
+ LDAP_BINDRESPONSE_TYPE = 1,
+ LDAP_UNBIND_TYPE = 2,
+ LDAP_SEARCH_TYPE = 3,
+ LDAP_SEARCHRESPONSEENTRY_TYPE = 4,
+ LDAP_SEARCHRESPONSERESULT_TYPE = 5,
+ LDAP_ABANDONREQUEST_TYPE = 16
+} LDAPMessageType;
+
+typedef enum {
+ SUCCESS = 0,
+ OPERATIONSERROR = 1,
+ PROTOCOLERROR = 2,
+ TIMELIMITEXCEEDED = 3,
+ SIZELIMITEXCEEDED = 4,
+ COMPAREFALSE = 5,
+ COMPARETRUE = 6,
+ AUTHMETHODNOTSUPPORTED = 7,
+ STRONGAUTHREQUIRED = 8,
+ NOSUCHATTRIBUTE = 16,
+ UNDEFINEDATTRIBUTETYPE = 17,
+ INAPPROPRIATEMATCHING = 18,
+ CONSTRAINTVIOLATION = 19,
+ ATTRIBUTEORVALUEEXISTS = 20,
+ INVALIDATTRIBUTESYNTAX = 21,
+ NOSUCHOBJECT = 32,
+ ALIASPROBLEM = 33,
+ INVALIDDNSYNTAX = 34,
+ ISLEAF = 35,
+ ALIASDEREFERENCINGPROBLEM = 36,
+ INAPPROPRIATEAUTHENTICATION = 48,
+ INVALIDCREDENTIALS = 49,
+ INSUFFICIENTACCESSRIGHTS = 50,
+ BUSY = 51,
+ UNAVAILABLE = 52,
+ UNWILLINGTOPERFORM = 53,
+ LOOPDETECT = 54,
+ NAMINGVIOLATION = 64,
+ OBJECTCLASSVIOLATION = 65,
+ NOTALLOWEDONNONLEAF = 66,
+ NOTALLOWEDONRDN = 67,
+ ENTRYALREADYEXISTS = 68,
+ OBJECTCLASSMODSPROHIBITED = 69,
+ OTHER = 80
+} LDAPResultCode;
+
+typedef struct LDAPLocationStruct LDAPLocation;
+typedef struct LDAPCertPairStruct LDAPCertPair;
+typedef struct LDAPSimpleBindStruct LDAPSimpleBind;
+typedef struct LDAPBindAPIStruct LDAPBindAPI;
+typedef struct LDAPBindStruct LDAPBind;
+typedef struct LDAPResultStruct LDAPBindResponse;
+typedef struct LDAPResultStruct LDAPResult;
+typedef struct LDAPSearchResponseAttrStruct LDAPSearchResponseAttr;
+typedef struct LDAPSearchResponseEntryStruct LDAPSearchResponseEntry;
+typedef struct LDAPResultStruct LDAPSearchResponseResult;
+typedef struct LDAPUnbindStruct LDAPUnbind;
+typedef struct LDAPFilterStruct LDAPFilter;
+typedef struct LDAPAndFilterStruct LDAPAndFilter;
+typedef struct LDAPNotFilterStruct LDAPNotFilter;
+typedef struct LDAPSubstringStruct LDAPSubstring;
+typedef struct LDAPSubstringFilterStruct LDAPSubstringFilter;
+typedef struct LDAPPresentFilterStruct LDAPPresentFilter;
+typedef struct LDAPAttributeValueAssertionStruct LDAPAttributeValueAssertion;
+typedef struct LDAPNameComponentStruct LDAPNameComponent;
+typedef struct LDAPRequestParamsStruct LDAPRequestParams;
+typedef struct LDAPSearchStruct LDAPSearch;
+typedef struct LDAPAbandonRequestStruct LDAPAbandonRequest;
+typedef struct protocolOpStruct LDAPProtocolOp;
+typedef struct LDAPMessageStruct LDAPMessage;
+typedef LDAPAndFilter LDAPOrFilter;
+typedef LDAPAttributeValueAssertion LDAPEqualFilter;
+typedef LDAPAttributeValueAssertion LDAPGreaterOrEqualFilter;
+typedef LDAPAttributeValueAssertion LDAPLessOrEqualFilter;
+typedef LDAPAttributeValueAssertion LDAPApproxMatchFilter;
+
+struct LDAPLocationStruct {
+ PLArenaPool *arena;
+ void *serverSite;
+ void **filterString;
+ void **attrBitString;
+};
+
+struct LDAPCertPairStruct {
+ SECItem forward;
+ SECItem reverse;
+};
+
+struct LDAPSimpleBindStruct {
+ char *bindName;
+ char *authentication;
+};
+
+struct LDAPBindAPIStruct {
+ AuthType selector;
+ union {
+ LDAPSimpleBind simple;
+ } chooser;
+};
+
+struct LDAPBindStruct {
+ SECItem version;
+ SECItem bindName;
+ SECItem authentication;
+};
+
+struct LDAPResultStruct {
+ SECItem resultCode;
+ SECItem matchedDN;
+ SECItem errorMessage;
+};
+
+struct LDAPSearchResponseAttrStruct {
+ SECItem attrType;
+ SECItem **val;
+};
+
+struct LDAPSearchResponseEntryStruct {
+ SECItem objectName;
+ LDAPSearchResponseAttr **attributes;
+};
+
+struct LDAPUnbindStruct {
+ SECItem dummy;
+};
+
+struct LDAPAndFilterStruct {
+ LDAPFilter **filters;
+};
+
+struct LDAPNotFilterStruct {
+ LDAPFilter *filter;
+};
+
+struct LDAPSubstringStruct {
+ LDAPSubstringFilterType selector;
+ SECItem item;
+};
+
+struct LDAPSubstringFilterStruct {
+ SECItem attrType;
+ LDAPSubstring *strings;
+};
+
+struct LDAPPresentFilterStruct {
+ SECItem attrType;
+};
+
+struct LDAPAttributeValueAssertionStruct {
+ SECItem attrType;
+ SECItem attrValue;
+};
+
+struct LDAPFilterStruct {
+ LDAPFilterType selector;
+ union {
+ LDAPAndFilter andFilter;
+ LDAPOrFilter orFilter;
+ LDAPNotFilter notFilter;
+ LDAPEqualFilter equalFilter;
+ LDAPSubstringFilter substringFilter;
+ LDAPGreaterOrEqualFilter greaterOrEqualFilter;
+ LDAPLessOrEqualFilter lessOrEqualFilter;
+ LDAPPresentFilter presentFilter;
+ LDAPApproxMatchFilter approxMatchFilter;
+ } filter;
+};
+
+struct LDAPNameComponentStruct {
+ unsigned char *attrType;
+ unsigned char *attrValue;
+};
+
+struct LDAPRequestParamsStruct {
+ char *baseObject; /* e.g. "c=US" */
+ ScopeType scope;
+ DerefType derefAliases;
+ PKIX_UInt32 sizeLimit; /* 0 = no limit */
+ PRIntervalTime timeLimit; /* 0 = no limit */
+ LDAPNameComponent **nc; /* e.g. {{"cn","xxx"},{"o","yyy"},NULL} */
+ LdapAttrMask attributes;
+};
+
+struct LDAPSearchStruct {
+ SECItem baseObject;
+ SECItem scope;
+ SECItem derefAliases;
+ SECItem sizeLimit;
+ SECItem timeLimit;
+ SECItem attrsOnly;
+ LDAPFilter filter;
+ SECItem **attributes;
+};
+
+struct LDAPAbandonRequestStruct {
+ SECItem messageID;
+};
+
+struct protocolOpStruct {
+ LDAPMessageType selector;
+ union {
+ LDAPBind bindMsg;
+ LDAPBindResponse bindResponseMsg;
+ LDAPUnbind unbindMsg;
+ LDAPSearch searchMsg;
+ LDAPSearchResponseEntry searchResponseEntryMsg;
+ LDAPSearchResponseResult searchResponseResultMsg;
+ LDAPAbandonRequest abandonRequestMsg;
+ } op;
+};
+
+struct LDAPMessageStruct {
+ SECItem messageID;
+ LDAPProtocolOp protocolOp;
+};
+
+typedef struct PKIX_PL_LdapClientStruct PKIX_PL_LdapClient;
+
+typedef PKIX_Error *
+(*PKIX_PL_LdapClient_InitiateFcn)(
+ PKIX_PL_LdapClient *client,
+ LDAPRequestParams *requestParams,
+ void **pNBIO,
+ PKIX_List **pResponse,
+ void *plContext);
+
+typedef PKIX_Error *
+(*PKIX_PL_LdapClient_ResumeFcn)(
+ PKIX_PL_LdapClient *client,
+ void **pNBIO,
+ PKIX_List **pResponse,
+ void *plContext);
+
+struct PKIX_PL_LdapClientStruct {
+ PKIX_PL_LdapClient_InitiateFcn initiateFcn;
+ PKIX_PL_LdapClient_ResumeFcn resumeFcn;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaptemplates.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaptemplates.c
new file mode 100644
index 0000000000..ecb681929b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaptemplates.c
@@ -0,0 +1,417 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 "pkix_pl_ldapt.h"
+
+SEC_ASN1_MKSUB(SEC_AnyTemplate)
+SEC_ASN1_MKSUB(SEC_NullTemplate)
+SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
+
+/*
+ * CertificatePair ::= SEQUENCE {
+ * forward [0] Certificate OPTIONAL,
+ * reverse [1] Certificate OPTIONAL
+ * -- at least one of the pair shall be present --
+ * }
+ */
+
+const SEC_ASN1Template PKIX_PL_LDAPCrossCertPairTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(LDAPCertPair) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
+ SEC_ASN1_EXPLICIT | SEC_ASN1_XTRN | 0,
+ offsetof(LDAPCertPair, forward), SEC_ASN1_SUB(SEC_AnyTemplate) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
+ SEC_ASN1_EXPLICIT | SEC_ASN1_XTRN | 1,
+ offsetof(LDAPCertPair, reverse), SEC_ASN1_SUB(SEC_AnyTemplate) },
+ { 0 }
+};
+
+/*
+ * BindRequest ::=
+ * [APPLICATION 0] SEQUENCE {
+ * version INTEGER (1..127),
+ * name LDAPDN,
+ * authentication CHOICE {
+ * simple [0] OCTET STRING,
+ * krbv42LDAP [1] OCTET STRING,
+ * krbv42DSA [2] OCTET STRING
+ * }
+ * }
+ *
+ * LDAPDN ::= LDAPString
+ *
+ * LDAPString ::= OCTET STRING
+ */
+
+#define LDAPStringTemplate SEC_ASN1_SUB(SEC_OctetStringTemplate)
+
+static const SEC_ASN1Template LDAPBindApplTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL },
+ { SEC_ASN1_INTEGER, offsetof(LDAPBind, version) },
+ { SEC_ASN1_LDAP_STRING, offsetof(LDAPBind, bindName) },
+ { SEC_ASN1_LDAP_STRING, offsetof(LDAPBind, authentication) },
+ { 0 }
+};
+
+static const SEC_ASN1Template LDAPBindTemplate[] = {
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_BIND_TYPE, 0,
+ LDAPBindApplTemplate, sizeof (LDAPBind) }
+};
+
+/*
+ * BindResponse ::= [APPLICATION 1] LDAPResult
+ *
+ * LDAPResult ::=
+ * SEQUENCE {
+ * resultCode ENUMERATED {
+ * success (0),
+ * operationsError (1),
+ * protocolError (2),
+ * timeLimitExceeded (3),
+ * sizeLimitExceeded (4),
+ * compareFalse (5),
+ * compareTrue (6),
+ * authMethodNotSupported (7),
+ * strongAuthRequired (8),
+ * noSuchAttribute (16),
+ * undefinedAttributeType (17),
+ * inappropriateMatching (18),
+ * constraintViolation (19),
+ * attributeOrValueExists (20),
+ * invalidAttributeSyntax (21),
+ * noSuchObject (32),
+ * aliasProblem (33),
+ * invalidDNSyntax (34),
+ * isLeaf (35),
+ * aliasDereferencingProblem (36),
+ * inappropriateAuthentication (48),
+ * invalidCredentials (49),
+ * insufficientAccessRights (50),
+ * busy (51),
+ * unavailable (52),
+ * unwillingToPerform (53),
+ * loopDetect (54),
+ * namingViolation (64),
+ * objectClassViolation (65),
+ * notAllowedOnNonLeaf (66),
+ * notAllowedOnRDN (67),
+ * entryAlreadyExists (68),
+ * objectClassModsProhibited (69),
+ * other (80)
+ * },
+ * matchedDN LDAPDN,
+ * errorMessage LDAPString
+ * }
+ */
+
+static const SEC_ASN1Template LDAPResultTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL },
+ { SEC_ASN1_ENUMERATED, offsetof(LDAPResult, resultCode) },
+ { SEC_ASN1_LDAP_STRING, offsetof(LDAPResult, matchedDN) },
+ { SEC_ASN1_LDAP_STRING, offsetof(LDAPResult, errorMessage) },
+ { 0 }
+};
+
+static const SEC_ASN1Template LDAPBindResponseTemplate[] = {
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_BINDRESPONSE_TYPE, 0,
+ LDAPResultTemplate, sizeof (LDAPBindResponse) }
+};
+
+/*
+ * UnbindRequest ::= [APPLICATION 2] NULL
+ */
+
+static const SEC_ASN1Template LDAPUnbindTemplate[] = {
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | SEC_ASN1_XTRN |
+ LDAP_UNBIND_TYPE , 0, SEC_ASN1_SUB(SEC_NullTemplate) }
+};
+
+/*
+ * AttributeValueAssertion ::=
+ * SEQUENCE {
+ * attributeType AttributeType,
+ * attributeValue AttributeValue,
+ * }
+ *
+ * AttributeType ::= LDAPString
+ * -- text name of the attribute, or dotted
+ * -- OID representation
+ *
+ * AttributeValue ::= OCTET STRING
+ */
+
+#define LDAPAttributeTypeTemplate LDAPStringTemplate
+
+/*
+ * SubstringFilter ::=
+ * SEQUENCE {
+ * type AttributeType,
+ * SEQUENCE OF CHOICE {
+ * initial [0] LDAPString,
+ * any [1] LDAPString,
+ * final [2] LDAPString,
+ * }
+ * }
+ */
+
+#define LDAPSubstringFilterInitialTemplate LDAPStringTemplate
+#define LDAPSubstringFilterAnyTemplate LDAPStringTemplate
+#define LDAPSubstringFilterFinalTemplate LDAPStringTemplate
+
+static const SEC_ASN1Template LDAPSubstringFilterChoiceTemplate[] = {
+ { SEC_ASN1_CHOICE, offsetof(LDAPSubstring, selector), 0,
+ sizeof (LDAPFilter) },
+ { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
+ offsetof(LDAPSubstring, item),
+ LDAPSubstringFilterInitialTemplate,
+ LDAP_INITIALSUBSTRING_TYPE },
+ { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
+ offsetof(LDAPSubstring, item),
+ LDAPSubstringFilterAnyTemplate,
+ LDAP_ANYSUBSTRING_TYPE },
+ { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2,
+ offsetof(LDAPSubstring, item),
+ LDAPSubstringFilterFinalTemplate,
+ LDAP_FINALSUBSTRING_TYPE },
+ { 0 }
+};
+
+/*
+ * Filter ::=
+ * CHOICE {
+ * and [0] SET OF Filter,
+ * or [1] SET OF Filter,
+ * not [2] Filter,
+ * equalityMatch [3] AttributeValueAssertion,
+ * substrings [4] SubstringFilter,
+ * greaterOrEqual [5] AttributeValueAssertion,
+ * lessOrEqual [6] AttributeValueAssertion,
+ * present [7] AttributeType,
+ * approxMatch [8] AttributeValueAssertion
+ }
+ */
+
+static const SEC_ASN1Template LDAPSubstringFilterTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (LDAPSubstringFilter) },
+ { SEC_ASN1_LDAP_STRING, offsetof(LDAPSubstringFilter, attrType) },
+ { SEC_ASN1_SEQUENCE_OF, offsetof(LDAPSubstringFilter, strings),
+ LDAPSubstringFilterChoiceTemplate },
+ { 0 }
+};
+
+const SEC_ASN1Template LDAPFilterTemplate[]; /* forward reference */
+
+static const SEC_ASN1Template LDAPSetOfFiltersTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, LDAPFilterTemplate }
+};
+
+static const SEC_ASN1Template LDAPAVAFilterTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (LDAPAttributeValueAssertion) },
+ { SEC_ASN1_LDAP_STRING, offsetof(LDAPAttributeValueAssertion, attrType) },
+ { SEC_ASN1_OCTET_STRING, offsetof(LDAPAttributeValueAssertion, attrValue) },
+ { 0 }
+};
+
+static const SEC_ASN1Template LDAPPresentFilterTemplate[] = {
+ { SEC_ASN1_LDAP_STRING, offsetof(LDAPPresentFilter, attrType) }
+};
+
+#define LDAPEqualFilterTemplate LDAPAVAFilterTemplate
+#define LDAPGreaterOrEqualFilterTemplate LDAPAVAFilterTemplate
+#define LDAPLessOrEqualFilterTemplate LDAPAVAFilterTemplate
+#define LDAPApproxMatchFilterTemplate LDAPAVAFilterTemplate
+
+const SEC_ASN1Template LDAPFilterTemplate[] = {
+ { SEC_ASN1_CHOICE, offsetof(LDAPFilter, selector), 0, sizeof(LDAPFilter) },
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
+ LDAP_ANDFILTER_TYPE,
+ offsetof(LDAPFilter, filter.andFilter.filters),
+ LDAPSetOfFiltersTemplate, LDAP_ANDFILTER_TYPE },
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
+ LDAP_ORFILTER_TYPE,
+ offsetof(LDAPFilter, filter.orFilter.filters),
+ LDAPSetOfFiltersTemplate, LDAP_ORFILTER_TYPE },
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
+ LDAP_NOTFILTER_TYPE | SEC_ASN1_POINTER,
+ offsetof(LDAPFilter, filter.notFilter),
+ LDAPFilterTemplate, LDAP_NOTFILTER_TYPE },
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
+ LDAP_EQUALFILTER_TYPE,
+ offsetof(LDAPFilter, filter.equalFilter),
+ LDAPEqualFilterTemplate, LDAP_EQUALFILTER_TYPE },
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
+ LDAP_SUBSTRINGFILTER_TYPE, offsetof(LDAPFilter, filter.substringFilter),
+ LDAPSubstringFilterTemplate, LDAP_SUBSTRINGFILTER_TYPE },
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
+ LDAP_GREATEROREQUALFILTER_TYPE,
+ offsetof(LDAPFilter, filter.greaterOrEqualFilter),
+ LDAPGreaterOrEqualFilterTemplate, LDAP_GREATEROREQUALFILTER_TYPE },
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
+ LDAP_LESSOREQUALFILTER_TYPE,
+ offsetof(LDAPFilter, filter.lessOrEqualFilter),
+ LDAPLessOrEqualFilterTemplate, LDAP_LESSOREQUALFILTER_TYPE },
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
+ LDAP_PRESENTFILTER_TYPE,
+ offsetof(LDAPFilter, filter.presentFilter),
+ LDAPPresentFilterTemplate, LDAP_PRESENTFILTER_TYPE },
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
+ LDAP_APPROXMATCHFILTER_TYPE,
+ offsetof(LDAPFilter, filter.approxMatchFilter),
+ LDAPApproxMatchFilterTemplate, LDAP_APPROXMATCHFILTER_TYPE },
+ { 0 }
+};
+
+/*
+ * SearchRequest ::=
+ * [APPLICATION 3] SEQUENCE {
+ * baseObject LDAPDN,
+ * scope ENUMERATED {
+ * baseObject (0),
+ * singleLevel (1),
+ * wholeSubtree (2)
+ * },
+ * derefAliases ENUMERATED {
+ * neverDerefAliases (0),
+ * derefInSearching (1),
+ * derefFindingBaseObj (2),
+ * alwaysDerefAliases (3)
+ * },
+ * sizeLimit INTEGER (0 .. MAXINT),
+ * -- value of 0 implies no sizeLimit
+ * timeLimit INTEGER (0 .. MAXINT),
+ * -- value of 0 implies no timeLimit
+ * attrsOnly BOOLEAN,
+ * -- TRUE, if only attributes (without values)
+ * -- to be returned
+ * filter Filter,
+ * attributes SEQUENCE OF AttributeType
+ * }
+ */
+
+static const SEC_ASN1Template LDAPAttributeTemplate[] = {
+ { SEC_ASN1_LDAP_STRING, 0, NULL, sizeof (SECItem) }
+};
+
+static const SEC_ASN1Template LDAPSearchApplTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL },
+ { SEC_ASN1_LDAP_STRING, offsetof(LDAPSearch, baseObject) },
+ { SEC_ASN1_ENUMERATED, offsetof(LDAPSearch, scope) },
+ { SEC_ASN1_ENUMERATED, offsetof(LDAPSearch, derefAliases) },
+ { SEC_ASN1_INTEGER, offsetof(LDAPSearch, sizeLimit) },
+ { SEC_ASN1_INTEGER, offsetof(LDAPSearch, timeLimit) },
+ { SEC_ASN1_BOOLEAN, offsetof(LDAPSearch, attrsOnly) },
+ { SEC_ASN1_INLINE, offsetof(LDAPSearch, filter), LDAPFilterTemplate },
+ { SEC_ASN1_SEQUENCE_OF, offsetof(LDAPSearch, attributes), LDAPAttributeTemplate },
+ { 0 }
+};
+
+static const SEC_ASN1Template LDAPSearchTemplate[] = {
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_SEARCH_TYPE, 0,
+ LDAPSearchApplTemplate, sizeof (LDAPSearch) }
+};
+
+/*
+ * SearchResponse ::=
+ * CHOICE {
+ * entry [APPLICATION 4] SEQUENCE {
+ * objectName LDAPDN,
+ * attributes SEQUENCE OF SEQUENCE {
+ * AttributeType,
+ * SET OF AttributeValue
+ * }
+ * }
+ * resultCode [APPLICATION 5] LDAPResult
+ * }
+ */
+
+static const SEC_ASN1Template LDAPSearchResponseAttrTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(LDAPSearchResponseAttr) },
+ { SEC_ASN1_LDAP_STRING, offsetof(LDAPSearchResponseAttr, attrType) },
+ { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(LDAPSearchResponseAttr, val),
+ LDAPStringTemplate },
+ { 0 }
+};
+
+static const SEC_ASN1Template LDAPEntryTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL },
+ { SEC_ASN1_LDAP_STRING, offsetof(LDAPSearchResponseEntry, objectName) },
+ { SEC_ASN1_SEQUENCE_OF, offsetof(LDAPSearchResponseEntry, attributes),
+ LDAPSearchResponseAttrTemplate },
+ { 0 }
+};
+
+static const SEC_ASN1Template LDAPSearchResponseEntryTemplate[] = {
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_SEARCHRESPONSEENTRY_TYPE, 0,
+ LDAPEntryTemplate, sizeof (LDAPSearchResponseEntry) }
+};
+
+static const SEC_ASN1Template LDAPSearchResponseResultTemplate[] = {
+ { SEC_ASN1_APPLICATION | LDAP_SEARCHRESPONSERESULT_TYPE, 0,
+ LDAPResultTemplate, sizeof (LDAPSearchResponseResult) }
+};
+
+/*
+ * AbandonRequest ::=
+ * [APPLICATION 16] MessageID
+ */
+
+static const SEC_ASN1Template LDAPAbandonTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(LDAPAbandonRequest, messageID) }
+};
+
+static const SEC_ASN1Template LDAPAbandonRequestTemplate[] = {
+ { SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | LDAP_ABANDONREQUEST_TYPE, 0,
+ LDAPAbandonTemplate, sizeof (LDAPAbandonRequest) }
+};
+
+/*
+ * LDAPMessage ::=
+ * SEQUENCE {
+ * messageID MessageID,
+ * protocolOp CHOICE {
+ * bindRequest BindRequest,
+ * bindResponse BindResponse,
+ * unbindRequest UnbindRequest,
+ * searchRequest SearchRequest,
+ * searchResponse SearchResponse,
+ * abandonRequest AbandonRequest
+ * }
+ * }
+ *
+ * (other choices exist, not shown)
+ *
+ * MessageID ::= INTEGER (0 .. maxInt)
+ */
+
+static const SEC_ASN1Template LDAPMessageProtocolOpTemplate[] = {
+ { SEC_ASN1_CHOICE, offsetof(LDAPProtocolOp, selector), 0, sizeof (LDAPProtocolOp) },
+ { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.bindMsg),
+ LDAPBindTemplate, LDAP_BIND_TYPE },
+ { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.bindResponseMsg),
+ LDAPBindResponseTemplate, LDAP_BINDRESPONSE_TYPE },
+ { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.unbindMsg),
+ LDAPUnbindTemplate, LDAP_UNBIND_TYPE },
+ { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.searchMsg),
+ LDAPSearchTemplate, LDAP_SEARCH_TYPE },
+ { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.searchResponseEntryMsg),
+ LDAPSearchResponseEntryTemplate, LDAP_SEARCHRESPONSEENTRY_TYPE },
+ { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.searchResponseResultMsg),
+ LDAPSearchResponseResultTemplate, LDAP_SEARCHRESPONSERESULT_TYPE },
+ { SEC_ASN1_INLINE, offsetof(LDAPProtocolOp, op.abandonRequestMsg),
+ LDAPAbandonRequestTemplate, LDAP_ABANDONREQUEST_TYPE },
+ { 0 }
+};
+
+const SEC_ASN1Template PKIX_PL_LDAPMessageTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL },
+ { SEC_ASN1_INTEGER, offsetof(LDAPMessage, messageID) },
+ { SEC_ASN1_INLINE, offsetof(LDAPMessage, protocolOp),
+ LDAPMessageProtocolOpTemplate },
+ { 0 }
+};
+
+/* This function simply returns the address of the message template.
+ * This is necessary for Windows DLLs.
+ */
+SEC_ASN1_CHOOSER_IMPLEMENT(PKIX_PL_LDAPMessageTemplate)
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.c
new file mode 100644
index 0000000000..966c6f37e4
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.c
@@ -0,0 +1,389 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_nsscontext.c
+ *
+ * NSSContext Function Definitions
+ *
+ */
+
+
+#include "pkix_pl_nsscontext.h"
+
+#define PKIX_DEFAULT_MAX_RESPONSE_LENGTH 64 * 1024
+#define PKIX_DEFAULT_COMM_TIMEOUT_SECONDS 60
+
+#define PKIX_DEFAULT_CRL_RELOAD_DELAY_SECONDS 6 * 24 * 60 * 60
+#define PKIX_DEFAULT_BAD_CRL_RELOAD_DELAY_SECONDS 60 * 60
+
+/* --Public-NSSContext-Functions--------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_NssContext_Create
+ * (see comments in pkix_samples_modules.h)
+ */
+PKIX_Error *
+PKIX_PL_NssContext_Create(
+ PKIX_UInt32 certificateUsage,
+ PKIX_Boolean useNssArena,
+ void *wincx,
+ void **pNssContext)
+{
+ PKIX_PL_NssContext *context = NULL;
+ PLArenaPool *arena = NULL;
+ void *plContext = NULL;
+
+ PKIX_ENTER(CONTEXT, "PKIX_PL_NssContext_Create");
+ PKIX_NULLCHECK_ONE(pNssContext);
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (sizeof(PKIX_PL_NssContext), (void **)&context, NULL),
+ PKIX_MALLOCFAILED);
+
+ if (useNssArena == PKIX_TRUE) {
+ PKIX_CONTEXT_DEBUG("\t\tCalling PORT_NewArena\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ }
+
+ context->arena = arena;
+ context->certificateUsage = (SECCertificateUsage)certificateUsage;
+ context->wincx = wincx;
+ context->timeoutSeconds = PKIX_DEFAULT_COMM_TIMEOUT_SECONDS;
+ context->maxResponseLength = PKIX_DEFAULT_MAX_RESPONSE_LENGTH;
+ context->crlReloadDelay = PKIX_DEFAULT_CRL_RELOAD_DELAY_SECONDS;
+ context->badDerCrlReloadDelay =
+ PKIX_DEFAULT_BAD_CRL_RELOAD_DELAY_SECONDS;
+ context->certSignatureCheck = PKIX_TRUE;
+ context->chainVerifyCallback.isChainValid = NULL;
+ context->chainVerifyCallback.isChainValidArg = NULL;
+ *pNssContext = context;
+
+cleanup:
+
+ PKIX_RETURN(CONTEXT);
+}
+
+
+/*
+ * FUNCTION: PKIX_PL_NssContext_Destroy
+ * (see comments in pkix_samples_modules.h)
+ */
+PKIX_Error *
+PKIX_PL_NssContext_Destroy(
+ void *nssContext)
+{
+ void *plContext = NULL;
+ PKIX_PL_NssContext *context = NULL;
+
+ PKIX_ENTER(CONTEXT, "PKIX_PL_NssContext_Destroy");
+ PKIX_NULLCHECK_ONE(nssContext);
+
+ context = (PKIX_PL_NssContext*)nssContext;
+
+ if (context->arena != NULL) {
+ PKIX_CONTEXT_DEBUG("\t\tCalling PORT_FreeArena\n");
+ PORT_FreeArena(context->arena, PKIX_FALSE);
+ }
+
+ PKIX_PL_Free(nssContext, NULL);
+
+ PKIX_RETURN(CONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_NssContext_GetCertUsage
+ * DESCRIPTION:
+ *
+ * This function obtains the platform-dependent SECCertificateUsage parameter
+ * from the context object pointed to by "nssContext", storing the result at
+ * "pCertUsage".
+ *
+ * PARAMETERS:
+ * "nssContext"
+ * The address of the context object whose wincx parameter is to be
+ * obtained. Must be non-NULL.
+ * "pCertUsage"
+ * The address where the result is stored. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_NssContext_GetCertUsage(
+ PKIX_PL_NssContext *nssContext,
+ SECCertificateUsage *pCertUsage)
+{
+ void *plContext = NULL;
+
+ PKIX_ENTER(CONTEXT, "pkix_pl_NssContext_GetCertUsage");
+ PKIX_NULLCHECK_TWO(nssContext, pCertUsage);
+
+ *pCertUsage = nssContext->certificateUsage;
+
+ PKIX_RETURN(CONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_NssContext_SetCertUsage
+ * DESCRIPTION:
+ *
+ * This function sets the platform-dependent SECCertificateUsage parameter in
+ * the context object pointed to by "nssContext" to the value provided in
+ * "certUsage".
+ *
+ * PARAMETERS:
+ * "certUsage"
+ * Platform-dependent value to be stored.
+ * "nssContext"
+ * The address of the context object whose wincx parameter is to be
+ * obtained. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_NssContext_SetCertUsage(
+ SECCertificateUsage certUsage,
+ PKIX_PL_NssContext *nssContext)
+{
+ void *plContext = NULL;
+
+ PKIX_ENTER(CONTEXT, "pkix_pl_NssContext_SetCertUsage");
+ PKIX_NULLCHECK_ONE(nssContext);
+
+ nssContext->certificateUsage = certUsage;
+
+ PKIX_RETURN(CONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_NssContext_GetCertSignatureCheck
+ * DESCRIPTION:
+ *
+ * This function obtains the platform-dependent flag to turn on or off
+ * signature checks.
+ *
+ * PARAMETERS:
+ * "nssContext"
+ * The address of the context object whose wincx parameter is to be
+ * obtained. Must be non-NULL.
+ * "pCheckSig"
+ * The address where the result is stored. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_NssContext_GetCertSignatureCheck(
+ PKIX_PL_NssContext *nssContext,
+ PKIX_Boolean *pCheckSig)
+{
+ void *plContext = NULL;
+
+ PKIX_ENTER(CONTEXT, "pkix_pl_NssContext_GetCertUsage");
+ PKIX_NULLCHECK_TWO(nssContext, pCheckSig);
+
+ *pCheckSig = nssContext->certSignatureCheck;
+
+ PKIX_RETURN(CONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_NssContext_SetCertSignatureCheck
+ * DESCRIPTION:
+ *
+ * This function sets the check signature flag in
+ * the context object pointed to by "nssContext" to the value provided in
+ * "checkSig".
+ *
+ * PARAMETERS:
+ * "checkSig"
+ * Boolean that tells whether or not to check the signatues on certs.
+ * "nssContext"
+ * The address of the context object whose wincx parameter is to be
+ * obtained. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_NssContext_SetCertSignatureCheck(
+ PKIX_Boolean checkSig,
+ PKIX_PL_NssContext *nssContext)
+{
+ void *plContext = NULL;
+
+ PKIX_ENTER(CONTEXT, "pkix_pl_NssContext_SetCertUsage");
+ PKIX_NULLCHECK_ONE(nssContext);
+
+ nssContext->certSignatureCheck = checkSig;
+
+ PKIX_RETURN(CONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_NssContext_GetWincx
+ * DESCRIPTION:
+ *
+ * This function obtains the platform-dependent wincx parameter from the
+ * context object pointed to by "nssContext", storing the result at "pWincx".
+ *
+ * PARAMETERS:
+ * "nssContext"
+ * The address of the context object whose wincx parameter is to be
+ * obtained. Must be non-NULL.
+ * "pWincx"
+ * The address where the result is stored. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_NssContext_GetWincx(
+ PKIX_PL_NssContext *nssContext,
+ void **pWincx)
+{
+ void *plContext = NULL;
+ PKIX_PL_NssContext *context = NULL;
+
+ PKIX_ENTER(CONTEXT, "pkix_pl_NssContext_GetWincx");
+ PKIX_NULLCHECK_TWO(nssContext, pWincx);
+
+ context = (PKIX_PL_NssContext *)nssContext;
+
+ *pWincx = context->wincx;
+
+ PKIX_RETURN(CONTEXT);
+}
+
+/*
+ * FUNCTION: pkix_pl_NssContext_SetWincx
+ * DESCRIPTION:
+ *
+ * This function sets the platform-dependent wincx parameter in the context
+ * object pointed to by "nssContext" to the value provided in "wincx".
+ *
+ * PARAMETERS:
+ * "wincx"
+ * Platform-dependent value to be stored.
+ * "nssContext"
+ * The address of the context object whose wincx parameter is to be
+ * obtained. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_NssContext_SetWincx(
+ void *wincx,
+ PKIX_PL_NssContext *nssContext)
+{
+ void *plContext = NULL;
+
+ PKIX_ENTER(CONTEXT, "pkix_pl_NssContext_SetWincx");
+ PKIX_NULLCHECK_ONE(nssContext);
+
+ nssContext->wincx = wincx;
+
+ PKIX_RETURN(CONTEXT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_NssContext_SetTimeout
+ * DESCRIPTION:
+ *
+ * Sets user defined socket timeout for the validation
+ * session. Default is 60 seconds.
+ *
+ */
+PKIX_Error *
+PKIX_PL_NssContext_SetTimeout(PKIX_UInt32 timeout,
+ PKIX_PL_NssContext *nssContext)
+{
+ void *plContext = NULL;
+
+ PKIX_ENTER(CONTEXT, "PKIX_PL_NssContext_SetTimeout");
+ PKIX_NULLCHECK_ONE(nssContext);
+
+ nssContext->timeoutSeconds = timeout;
+
+ PKIX_RETURN(CONTEXT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_NssContext_SetMaxResponseLen
+ * DESCRIPTION:
+ *
+ * Sets user defined maximum transmission length of a message.
+ *
+ */
+PKIX_Error *
+PKIX_PL_NssContext_SetMaxResponseLen(PKIX_UInt32 len,
+ PKIX_PL_NssContext *nssContext)
+{
+ void *plContext = NULL;
+
+ PKIX_ENTER(CONTEXT, "PKIX_PL_NssContext_SetMaxResponseLen");
+ PKIX_NULLCHECK_ONE(nssContext);
+
+ nssContext->maxResponseLength = len;
+
+ PKIX_RETURN(CONTEXT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_NssContext_SetCrlReloadDelay
+ * DESCRIPTION:
+ *
+ * Sets user defined delay between attempts to load crl using
+ * CRLDP.
+ *
+ */
+PKIX_Error *
+PKIX_PL_NssContext_SetCrlReloadDelay(PKIX_UInt32 delay,
+ PKIX_PL_NssContext *nssContext)
+{
+ void *plContext = NULL;
+
+ PKIX_ENTER(CONTEXT, "PKIX_PL_NssContext_SetCrlReloadDelay");
+ PKIX_NULLCHECK_ONE(nssContext);
+
+ nssContext->crlReloadDelay = delay;
+
+ PKIX_RETURN(CONTEXT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_NssContext_SetBadDerCrlReloadDelay
+ * DESCRIPTION:
+ *
+ * Sets user defined delay between attempts to load crl that
+ * failed to decode.
+ *
+ */
+PKIX_Error *
+PKIX_PL_NssContext_SetBadDerCrlReloadDelay(PKIX_UInt32 delay,
+ PKIX_PL_NssContext *nssContext)
+{
+ void *plContext = NULL;
+
+ PKIX_ENTER(CONTEXT, "PKIX_PL_NssContext_SetBadDerCrlReloadDelay");
+ PKIX_NULLCHECK_ONE(nssContext);
+
+ nssContext->badDerCrlReloadDelay = delay;
+
+ PKIX_RETURN(CONTEXT);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.h
new file mode 100644
index 0000000000..5de44214e5
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_nsscontext.h
@@ -0,0 +1,61 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_nsscontext.h
+ *
+ * NSSContext Object Type Definition
+ *
+ */
+
+
+#ifndef _PKIX_PL_NSSCONTEXT_H
+#define _PKIX_PL_NSSCONTEXT_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_NssContextStruct {
+ SECCertificateUsage certificateUsage;
+ PLArenaPool *arena;
+ void *wincx;
+ PKIX_UInt32 timeoutSeconds;
+ PKIX_UInt32 maxResponseLength;
+ PRTime crlReloadDelay;
+ PRTime badDerCrlReloadDelay;
+ CERTChainVerifyCallback chainVerifyCallback;
+ PKIX_Boolean certSignatureCheck;
+};
+
+PKIX_Error *
+pkix_pl_NssContext_GetCertUsage
+ (PKIX_PL_NssContext *nssContext, SECCertificateUsage *pCertUsage);
+
+/* XXX move the setter into the public header. */
+PKIX_Error *
+pkix_pl_NssContext_SetCertUsage
+ (SECCertificateUsage certUsage, PKIX_PL_NssContext *nssContext);
+
+PKIX_Error *
+pkix_pl_NssContext_GetCertSignatureCheck
+ (PKIX_PL_NssContext *nssContext, PKIX_Boolean *pCheckSig);
+
+PKIX_Error *
+pkix_pl_NssContext_SetCertSignatureCheck
+ (PKIX_Boolean checkSig, PKIX_PL_NssContext *nssContext);
+
+PKIX_Error *
+pkix_pl_NssContext_GetWincx(PKIX_PL_NssContext *nssContext, void **pWincx);
+
+/* XXX move the setter into the public header. */
+PKIX_Error *
+pkix_pl_NssContext_SetWincx(void *wincx, PKIX_PL_NssContext *nssContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_NSSCONTEXT_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.c
new file mode 100644
index 0000000000..7de614ea68
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.c
@@ -0,0 +1,1039 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_pk11certstore.c
+ *
+ * PKCS11CertStore Function Definitions
+ *
+ */
+
+#include "pkix_pl_pk11certstore.h"
+
+/*
+ * PKIX_DEFAULT_MAX_RESPONSE_LENGTH (64 * 1024) is too small for downloading
+ * CRLs. We observed CRLs of sizes 338759 and 439035 in practice. So we
+ * need to use a higher max response length for CRLs.
+ */
+#define PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH (512 * 1024)
+
+/* --Private-Pk11CertStore-Functions---------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_Pk11CertStore_CheckTrust
+ * DESCRIPTION:
+ * This function checks the trust status of this "cert" that was retrieved
+ * from the CertStore "store" and returns its trust status at "pTrusted".
+ *
+ * PARAMETERS:
+ * "store"
+ * Address of the CertStore. Must be non-NULL.
+ * "cert"
+ * Address of the Cert. Must be non-NULL.
+ * "pTrusted"
+ * Address of PKIX_Boolean where the "cert" trust status is returned.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Pk11CertStore_CheckTrust(
+ PKIX_CertStore *store,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pTrusted,
+ void *plContext)
+{
+ SECStatus rv = SECFailure;
+ PKIX_Boolean trusted = PKIX_FALSE;
+ SECCertUsage certUsage = 0;
+ SECCertificateUsage certificateUsage;
+ unsigned int requiredFlags;
+ SECTrustType trustType;
+ CERTCertTrust trust;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CheckTrust");
+ PKIX_NULLCHECK_THREE(store, cert, pTrusted);
+ PKIX_NULLCHECK_ONE(cert->nssCert);
+
+ certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
+
+ /* ensure we obtained a single usage bit only */
+ PORT_Assert(!(certificateUsage & (certificateUsage - 1)));
+
+ /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */
+ while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; }
+
+ rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, &trustType);
+ if (rv == SECSuccess) {
+ rv = CERT_GetCertTrust(cert->nssCert, &trust);
+ }
+
+ if (rv == SECSuccess) {
+ unsigned int certFlags;
+
+ if (certUsage != certUsageAnyCA &&
+ certUsage != certUsageStatusResponder) {
+ CERTCertificate *nssCert = cert->nssCert;
+
+ if (certUsage == certUsageVerifyCA) {
+ if (nssCert->nsCertType & NS_CERT_TYPE_EMAIL_CA) {
+ trustType = trustEmail;
+ } else if (nssCert->nsCertType & NS_CERT_TYPE_SSL_CA) {
+ trustType = trustSSL;
+ } else {
+ trustType = trustObjectSigning;
+ }
+ }
+
+ certFlags = SEC_GET_TRUST_FLAGS((&trust), trustType);
+ if ((certFlags & requiredFlags) == requiredFlags) {
+ trusted = PKIX_TRUE;
+ }
+ } else {
+ for (trustType = trustSSL; trustType < trustTypeNone;
+ trustType++) {
+ certFlags =
+ SEC_GET_TRUST_FLAGS((&trust), trustType);
+ if ((certFlags & requiredFlags) == requiredFlags) {
+ trusted = PKIX_TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ *pTrusted = trusted;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Pk11CertStore_CertQuery
+ * DESCRIPTION:
+ *
+ * This function obtains from the database the Certs specified by the
+ * ComCertSelParams pointed to by "params" and stores the resulting
+ * List at "pSelected". If no matching Certs are found, a NULL pointer
+ * will be stored.
+ *
+ * This function uses a "smart" database query if the Subject has been set
+ * in ComCertSelParams. Otherwise, it uses a very inefficient call to
+ * retrieve all Certs in the database (and run them through the selector).
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of the ComCertSelParams. Must be non-NULL.
+ * "pSelected"
+ * Address at which List will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Pk11CertStore_CertQuery(
+ PKIX_ComCertSelParams *params,
+ PKIX_List **pSelected,
+ void *plContext)
+{
+ PRBool validOnly = PR_FALSE;
+ PRTime prtime = 0;
+ PKIX_PL_X500Name *subjectName = NULL;
+ PKIX_PL_Date *certValid = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ CERTCertList *pk11CertList = NULL;
+ CERTCertListNode *node = NULL;
+ CERTCertificate *nssCert = NULL;
+ CERTCertDBHandle *dbHandle = NULL;
+
+ PLArenaPool *arena = NULL;
+ SECItem *nameItem = NULL;
+ void *wincx = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CertQuery");
+ PKIX_NULLCHECK_TWO(params, pSelected);
+
+ /* avoid multiple calls to retrieve a constant */
+ PKIX_PL_NSSCALLRV(CERTSTORE, dbHandle, CERT_GetDefaultCertDB, ());
+
+ /*
+ * Any of the ComCertSelParams may be obtained and used to constrain
+ * the database query, to allow the use of a "smart" query. See
+ * pkix_certsel.h for a list of the PKIX_ComCertSelParams_Get*
+ * calls available. No corresponding "smart" queries exist at present,
+ * except for CERT_CreateSubjectCertList based on Subject. When others
+ * are added, corresponding code should be added to
+ * pkix_pl_Pk11CertStore_CertQuery to use them when appropriate
+ * selector parameters have been set.
+ */
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
+ (params, &subjectName, plContext),
+ PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_GetCertificateValid
+ (params, &certValid, plContext),
+ PKIX_COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED);
+
+ /* If caller specified a Date, convert it to PRTime */
+ if (certValid) {
+ PKIX_CHECK(pkix_pl_Date_GetPRTime
+ (certValid, &prtime, plContext),
+ PKIX_DATEGETPRTIMEFAILED);
+ validOnly = PR_TRUE;
+ }
+
+ /*
+ * If we have the subject name for the desired subject,
+ * ask the database for Certs with that subject. Otherwise
+ * ask the database for all Certs.
+ */
+ if (subjectName) {
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena) {
+
+ PKIX_CHECK(pkix_pl_X500Name_GetDERName
+ (subjectName, arena, &nameItem, plContext),
+ PKIX_X500NAMEGETSECNAMEFAILED);
+
+ if (nameItem) {
+
+ PKIX_PL_NSSCALLRV
+ (CERTSTORE,
+ pk11CertList,
+ CERT_CreateSubjectCertList,
+ (NULL, dbHandle, nameItem, prtime, validOnly));
+ }
+ PKIX_PL_NSSCALL
+ (CERTSTORE, PORT_FreeArena, (arena, PR_FALSE));
+ arena = NULL;
+ }
+
+ } else {
+
+ PKIX_CHECK(pkix_pl_NssContext_GetWincx
+ ((PKIX_PL_NssContext *)plContext, &wincx),
+ PKIX_NSSCONTEXTGETWINCXFAILED);
+
+ PKIX_PL_NSSCALLRV
+ (CERTSTORE,
+ pk11CertList,
+ PK11_ListCerts,
+ (PK11CertListAll, wincx));
+ }
+
+ if (pk11CertList) {
+
+ PKIX_CHECK(PKIX_List_Create(&certList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ for (node = CERT_LIST_HEAD(pk11CertList);
+ !(CERT_LIST_END(node, pk11CertList));
+ node = CERT_LIST_NEXT(node)) {
+
+ PKIX_PL_NSSCALLRV
+ (CERTSTORE,
+ nssCert,
+ CERT_DupCertificate,
+ (node->cert));
+
+ if (!nssCert) {
+ continue; /* just skip bad certs */
+ }
+
+ PKIX_CHECK_ONLY_FATAL(pkix_pl_Cert_CreateWithNSSCert
+ (nssCert, &cert, plContext),
+ PKIX_CERTCREATEWITHNSSCERTFAILED);
+
+ if (PKIX_ERROR_RECEIVED) {
+ CERT_DestroyCertificate(nssCert);
+ nssCert = NULL;
+ continue; /* just skip bad certs */
+ }
+
+ PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem
+ (certList, (PKIX_PL_Object *)cert, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(cert);
+
+ }
+
+ /* Don't throw away the list if one cert was bad! */
+ pkixTempErrorReceived = PKIX_FALSE;
+ }
+
+ *pSelected = certList;
+ certList = NULL;
+
+cleanup:
+
+ if (pk11CertList) {
+ CERT_DestroyCertList(pk11CertList);
+ }
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ PKIX_DECREF(subjectName);
+ PKIX_DECREF(certValid);
+ PKIX_DECREF(cert);
+ PKIX_DECREF(certList);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Pk11CertStore_ImportCrl
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of the ComCRLSelParams. Must be non-NULL.
+ * "pSelected"
+ * Address at which List will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Pk11CertStore_ImportCrl(
+ PKIX_CertStore *store,
+ PKIX_PL_X500Name *issuerName,
+ PKIX_List *crlList,
+ void *plContext)
+{
+ CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
+ PKIX_PL_CRL *crl = NULL;
+ SECItem *derCrl = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_ImportCrl");
+ PKIX_NULLCHECK_TWO(store, plContext);
+
+ if (!crlList) {
+ goto cleanup;
+ }
+ while (crlList->length > 0) {
+ PKIX_CHECK(
+ PKIX_List_GetItem(crlList, 0, (PKIX_PL_Object**)&crl,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ /* Delete crl from the list to keep controll of the
+ * last reference. crl need to be destroyed right after
+ * it released the ownership of the crl der. */
+ PKIX_CHECK(
+ PKIX_List_DeleteItem(crlList, 0, plContext),
+ PKIX_LISTDELETEITEMFAILED);
+
+ /* acquire the crlder ownership */
+ pkixErrorResult =
+ PKIX_PL_CRL_ReleaseDerCrl(crl, &derCrl, plContext);
+ PORT_Assert(!pkixErrorResult && derCrl);
+ if (pkixErrorResult || !derCrl) {
+ /* All pkix delivered crls should be able to
+ * release their ders. */
+ PKIX_DECREF(pkixErrorResult);
+ PKIX_DECREF(crl);
+ continue;
+ }
+ cert_CacheCRLByGeneralName(certHandle, derCrl,
+ crl->derGenName);
+ /* Do not check the status. If it is a SECFailure,
+ * derCrl is already destroyed. */
+ derCrl = NULL;
+ PKIX_DECREF(crl);
+ }
+
+cleanup:
+ PKIX_DECREF(crl);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+static PKIX_Error *
+NameCacheHasFetchedCrlInfo(PKIX_PL_Cert *pkixCert,
+ PRTime time,
+ PKIX_Boolean *pHasFetchedCrlInCache,
+ void *plContext)
+{
+ /* Returning true result in this case will mean, that case info
+ * is currect and should used as is. */
+ NamedCRLCache* nameCrlCache = NULL;
+ PKIX_Boolean hasFetchedCrlInCache = PKIX_TRUE;
+ PKIX_List *dpList = NULL;
+ pkix_pl_CrlDp *dp = NULL;
+ PKIX_UInt32 dpIndex = 0;
+ SECStatus rv = SECSuccess;
+ PRTime reloadDelay = 0, badCrlInvalDelay = 0;
+
+ PKIX_ENTER(CERTSTORE, "ChechCacheHasFetchedCrl");
+
+ reloadDelay =
+ ((PKIX_PL_NssContext*)plContext)->crlReloadDelay *
+ PR_USEC_PER_SEC;
+ badCrlInvalDelay =
+ ((PKIX_PL_NssContext*)plContext)->badDerCrlReloadDelay *
+ PR_USEC_PER_SEC;
+ if (!time) {
+ time = PR_Now();
+ }
+ /* If we already download the crl and inserted into the cache, then
+ * there is no need to check for fetched crl. We have what we have. */
+ PKIX_CHECK(
+ PKIX_PL_Cert_GetCrlDp(pkixCert, &dpList, plContext),
+ PKIX_CERTGETCRLDPFAILED);
+ if (dpList && dpList->length) {
+ hasFetchedCrlInCache = PKIX_FALSE;
+ rv = cert_AcquireNamedCRLCache(&nameCrlCache);
+ if (rv != SECSuccess) {
+ PKIX_DECREF(dpList);
+ }
+ } else {
+ /* If no dp then treat it as if we already have
+ * a fetched crl. */
+ PKIX_DECREF(dpList);
+ }
+ for (;!hasFetchedCrlInCache &&
+ dpList && dpIndex < dpList->length;dpIndex++) {
+ SECItem **derDpNames = NULL;
+ pkixErrorResult =
+ PKIX_List_GetItem(dpList, dpIndex, (PKIX_PL_Object **)&dp,
+ plContext);
+ if (pkixErrorResult) {
+ PKIX_DECREF(pkixErrorResult);
+ continue;
+ }
+ if (dp->nssdp->distPointType == generalName) {
+ /* dp can only be created from nssdp. */
+ derDpNames = dp->nssdp->derFullName;
+ }
+ while (derDpNames && *derDpNames != NULL) {
+ NamedCRLCacheEntry* cacheEntry = NULL;
+ const SECItem *derDpName = *derDpNames++;
+ rv = cert_FindCRLByGeneralName(nameCrlCache, derDpName,
+ &cacheEntry);
+ if (rv == SECSuccess && cacheEntry) {
+ if ((cacheEntry->inCRLCache &&
+ (cacheEntry->successfulInsertionTime + reloadDelay > time ||
+ (cacheEntry->dupe &&
+ cacheEntry->lastAttemptTime + reloadDelay > time))) ||
+ (cacheEntry->badDER &&
+ cacheEntry->lastAttemptTime + badCrlInvalDelay > time)) {
+ hasFetchedCrlInCache = PKIX_TRUE;
+ break;
+ }
+ }
+ }
+ PKIX_DECREF(dp);
+ }
+cleanup:
+ *pHasFetchedCrlInCache = hasFetchedCrlInCache;
+ if (nameCrlCache) {
+ cert_ReleaseNamedCRLCache(nameCrlCache);
+ }
+ PKIX_DECREF(dpList);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Pk11CertStore_CheckCrl
+ * DESCRIPTION:
+ *
+ * PARAMETERS:
+ * "params"
+ * Address of the ComCRLSelParams. Must be non-NULL.
+ * "pSelected"
+ * Address at which List will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertStore Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Pk11CertStore_CheckRevByCrl(
+ PKIX_CertStore *store,
+ PKIX_PL_Cert *pkixCert,
+ PKIX_PL_Cert *pkixIssuer,
+ PKIX_PL_Date *date,
+ PKIX_Boolean crlDownloadDone,
+ CERTCRLEntryReasonCode *pReasonCode,
+ PKIX_RevocationStatus *pStatus,
+ void *plContext)
+{
+ PKIX_RevocationStatus pkixRevStatus = PKIX_RevStatus_NoInfo;
+ CERTRevocationStatus revStatus = certRevocationStatusUnknown;
+ PKIX_Boolean hasFetchedCrlInCache = PKIX_TRUE;
+ CERTCertificate *cert = NULL, *issuer = NULL;
+ SECStatus rv = SECSuccess;
+ void *wincx = NULL;
+ PRTime time = 0;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CheckRevByCrl");
+ PKIX_NULLCHECK_FOUR(store, pkixCert, pkixIssuer, plContext);
+
+ cert = pkixCert->nssCert;
+ issuer = pkixIssuer->nssCert;
+ if (date) {
+ PKIX_CHECK(
+ pkix_pl_Date_GetPRTime(date, &time, plContext),
+ PKIX_DATEGETPRTIMEFAILED);
+ }
+ PKIX_CHECK(
+ pkix_pl_NssContext_GetWincx((PKIX_PL_NssContext*)plContext,
+ &wincx),
+ PKIX_NSSCONTEXTGETWINCXFAILED);
+ /* No need to check any cDPs, since partitioned crls are not
+ * supported. If a ds does not point to partitioned crl, then
+ * the crl should be in issuer cache that is unrelated to any
+ * dp. Using NULL as a dp pointer to check it.*/
+ rv = cert_CheckCertRevocationStatus(cert, issuer, NULL,
+ /* Will not validate the signature
+ * on the crl if time is not specified.*/
+ time, wincx, &revStatus, pReasonCode);
+ if (rv == SECFailure) {
+ pkixRevStatus = PKIX_RevStatus_Revoked;
+ goto cleanup;
+ }
+ if (crlDownloadDone) {
+ if (revStatus == certRevocationStatusRevoked) {
+ pkixRevStatus = PKIX_RevStatus_Revoked;
+ } else if (revStatus == certRevocationStatusValid) {
+ pkixRevStatus = PKIX_RevStatus_Success;
+ }
+ } else {
+ pkixErrorResult =
+ NameCacheHasFetchedCrlInfo(pkixCert, time, &hasFetchedCrlInCache,
+ plContext);
+ if (pkixErrorResult) {
+ goto cleanup;
+ }
+ if (revStatus == certRevocationStatusRevoked &&
+ (hasFetchedCrlInCache ||
+ *pReasonCode != crlEntryReasoncertificatedHold)) {
+ pkixRevStatus = PKIX_RevStatus_Revoked;
+ } else if (revStatus == certRevocationStatusValid &&
+ hasFetchedCrlInCache) {
+ pkixRevStatus = PKIX_RevStatus_Success;
+ }
+ }
+cleanup:
+ *pStatus = pkixRevStatus;
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_Pk11CertStore_GetCert
+ * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h)
+ */
+PKIX_Error *
+pkix_pl_Pk11CertStore_GetCert(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ PKIX_VerifyNode *parentVerifyNode,
+ void **pNBIOContext,
+ PKIX_List **pCertList,
+ void *plContext)
+{
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 numFound = 0;
+ PKIX_PL_Cert *candidate = NULL;
+ PKIX_List *selected = NULL;
+ PKIX_List *filtered = NULL;
+ PKIX_CertSelector_MatchCallback selectorCallback = NULL;
+ PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_Boolean cacheFlag = PKIX_FALSE;
+ PKIX_VerifyNode *verifyNode = NULL;
+ PKIX_Error *selectorError = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_GetCert");
+ PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCertList);
+
+ *pNBIOContext = NULL; /* We don't use non-blocking I/O */
+
+ PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
+ (selector, &selectorCallback, plContext),
+ PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
+ (selector, &params, plContext),
+ PKIX_CERTSELECTORGETCOMCERTSELPARAMSFAILED);
+
+ PKIX_CHECK(pkix_pl_Pk11CertStore_CertQuery
+ (params, &selected, plContext),
+ PKIX_PK11CERTSTORECERTQUERYFAILED);
+
+ if (selected) {
+ PKIX_CHECK(PKIX_List_GetLength(selected, &numFound, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+ }
+
+ PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag
+ (store, &cacheFlag, plContext),
+ PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED);
+
+ PKIX_CHECK(PKIX_CertStore_GetTrustCallback
+ (store, &trustCallback, plContext),
+ PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
+
+ PKIX_CHECK(PKIX_List_Create(&filtered, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ for (i = 0; i < numFound; i++) {
+ PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem
+ (selected,
+ i,
+ (PKIX_PL_Object **)&candidate,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ if (PKIX_ERROR_RECEIVED) {
+ continue; /* just skip bad certs */
+ }
+
+ selectorError =
+ selectorCallback(selector, candidate, plContext);
+ if (!selectorError) {
+ PKIX_CHECK(PKIX_PL_Cert_SetCacheFlag
+ (candidate, cacheFlag, plContext),
+ PKIX_CERTSETCACHEFLAGFAILED);
+
+ if (trustCallback) {
+ PKIX_CHECK(PKIX_PL_Cert_SetTrustCertStore
+ (candidate, store, plContext),
+ PKIX_CERTSETTRUSTCERTSTOREFAILED);
+ }
+
+ PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem
+ (filtered,
+ (PKIX_PL_Object *)candidate,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ } else if (parentVerifyNode) {
+ PKIX_CHECK_FATAL(
+ pkix_VerifyNode_Create(candidate, 0, selectorError,
+ &verifyNode, plContext),
+ PKIX_VERIFYNODECREATEFAILED);
+ PKIX_CHECK_FATAL(
+ pkix_VerifyNode_AddToTree(parentVerifyNode,
+ verifyNode,
+ plContext),
+ PKIX_VERIFYNODEADDTOTREEFAILED);
+ PKIX_DECREF(verifyNode);
+ }
+ PKIX_DECREF(selectorError);
+ PKIX_DECREF(candidate);
+ }
+
+ /* Don't throw away the list if one cert was bad! */
+ pkixTempErrorReceived = PKIX_FALSE;
+
+ *pCertList = filtered;
+ filtered = NULL;
+
+cleanup:
+fatal:
+ PKIX_DECREF(filtered);
+ PKIX_DECREF(candidate);
+ PKIX_DECREF(selected);
+ PKIX_DECREF(params);
+ PKIX_DECREF(verifyNode);
+ PKIX_DECREF(selectorError);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+static PKIX_Error *
+RemovePartitionedDpsFromList(PKIX_List *dpList, PKIX_PL_Date *date,
+ void *plContext)
+{
+ NamedCRLCache* nameCrlCache = NULL;
+ pkix_pl_CrlDp *dp = NULL;
+ unsigned int dpIndex = 0;
+ PRTime time;
+ PRTime reloadDelay = 0, badCrlInvalDelay = 0;
+ SECStatus rv;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_ListRemovePrtDp");
+
+ if (!dpList || !dpList->length) {
+ PKIX_RETURN(CERTSTORE);
+ }
+ reloadDelay =
+ ((PKIX_PL_NssContext*)plContext)->crlReloadDelay *
+ PR_USEC_PER_SEC;
+ badCrlInvalDelay =
+ ((PKIX_PL_NssContext*)plContext)->badDerCrlReloadDelay *
+ PR_USEC_PER_SEC;
+ PKIX_CHECK(pkix_pl_Date_GetPRTime(date, &time, plContext),
+ PKIX_DATEGETPRTIMEFAILED);
+ rv = cert_AcquireNamedCRLCache(&nameCrlCache);
+ if (rv == SECFailure) {
+ /* Baling out. Wont find out any thing useful. */
+ PKIX_RETURN(CERTSTORE);
+ }
+ while (dpIndex < dpList->length) {
+ SECItem **derDpNames = NULL;
+ PKIX_Boolean removeDp = PKIX_FALSE;
+
+ PKIX_CHECK(
+ PKIX_List_GetItem(dpList, dpIndex, (PKIX_PL_Object **)&dp,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+ if (!dp->isPartitionedByReasonCode) {
+ /* See if we know about this dp anything why we should
+ * not use it to download a crl. */
+ if (dp->nssdp->distPointType == generalName) {
+ /* dp can only be created from nssdp. */
+ derDpNames = dp->nssdp->derFullName;
+ } else {
+ removeDp = PKIX_TRUE;
+ }
+ while (derDpNames && *derDpNames != NULL) {
+ NamedCRLCacheEntry* cacheEntry = NULL;
+ const SECItem *derDpName = *derDpNames++;
+ /* Removing from the list all dps that we know about. */
+ rv = cert_FindCRLByGeneralName(nameCrlCache, derDpName,
+ &cacheEntry);
+ if (rv && cacheEntry) {
+ if (cacheEntry->unsupported ||
+ (cacheEntry->inCRLCache &&
+ (cacheEntry->successfulInsertionTime + reloadDelay > time ||
+ (cacheEntry->dupe &&
+ cacheEntry->lastAttemptTime + reloadDelay > time))) ||
+ (cacheEntry->badDER &&
+ cacheEntry->lastAttemptTime + badCrlInvalDelay > time)) {
+ removeDp = PKIX_TRUE;
+ }
+ }
+ }
+ } else {
+ /* Remove dp that point to a partitioned crl . RFC 5280
+ * recommends against crl partitioned by reason code.
+ * Will skip such crls */
+ removeDp = PKIX_TRUE;
+ }
+ if (removeDp) {
+ PKIX_CHECK_ONLY_FATAL(
+ pkix_List_Remove(dpList,(PKIX_PL_Object*)dp,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+ } else {
+ dpIndex += 1;
+ }
+ PKIX_DECREF(dp);
+ }
+
+cleanup:
+ if (nameCrlCache) {
+ cert_ReleaseNamedCRLCache(nameCrlCache);
+ }
+ PKIX_DECREF(dp);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Pk11CertStore_DownloadCrl
+ */
+static PKIX_Error *
+DownloadCrl(pkix_pl_CrlDp *dp, PKIX_PL_CRL **crl,
+ const SEC_HttpClientFcnV1 *hcv1, void *plContext)
+{
+ char *location = NULL;
+ char *hostname = NULL;
+ char *path = NULL;
+ PRUint16 port;
+ SEC_HTTP_SERVER_SESSION pServerSession = NULL;
+ SEC_HTTP_REQUEST_SESSION pRequestSession = NULL;
+ PRUint16 myHttpResponseCode;
+ const char *myHttpResponseData = NULL;
+ PRUint32 myHttpResponseDataLen;
+ SECItem *uri = NULL;
+ SECItem *derCrlCopy = NULL;
+ CERTSignedCrl *nssCrl = NULL;
+ CERTGeneralName *genName = NULL;
+ SECItem **derGenNames = NULL;
+ SECItem *derGenName = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_DownloadCrl");
+
+ /* Do not support dps others than a one with GeneralName
+ * name type. */
+ if (dp->distPointType != generalName ||
+ !dp->nssdp->derFullName) {
+ PKIX_ERROR(PKIX_UNSUPPORTEDCRLDPTYPE);
+ }
+ genName = dp->name.fullName;
+ derGenNames = dp->nssdp->derFullName;
+ do {
+ derGenName = *derGenNames;
+ do {
+ if (!derGenName ||
+ !genName->name.other.data) {
+ /* get to next name if no data. */
+ break;
+ }
+ uri = &genName->name.other;
+ location = (char*)PR_Malloc(1 + uri->len);
+ if (!location) {
+ break;
+ }
+ PORT_Memcpy(location, uri->data, uri->len);
+ location[uri->len] = 0;
+ if (CERT_ParseURL(location, &hostname,
+ &port, &path) != SECSuccess) {
+ PORT_SetError(SEC_ERROR_BAD_CRL_DP_URL);
+ break;
+ }
+
+ PORT_Assert(hostname != NULL);
+ PORT_Assert(path != NULL);
+
+ if ((*hcv1->createSessionFcn)(hostname, port,
+ &pServerSession) != SECSuccess) {
+ PORT_SetError(SEC_ERROR_BAD_CRL_DP_URL);
+ break;
+ }
+
+ if ((*hcv1->createFcn)(pServerSession, "http", path, "GET",
+ /* Users with slow connections might not get CRL revocation
+ checking for certs that use big CRLs because of the timeout
+ We absolutely need code that limits our retry attempts.
+ */
+ PR_SecondsToInterval(
+ ((PKIX_PL_NssContext*)plContext)->timeoutSeconds),
+ &pRequestSession) != SECSuccess) {
+ break;
+ }
+
+ myHttpResponseDataLen =
+ ((PKIX_PL_NssContext*)plContext)->maxResponseLength;
+ if (myHttpResponseDataLen < PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH)
+ myHttpResponseDataLen = PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH;
+
+ /* We use a non-zero timeout, which means:
+ - the client will use blocking I/O
+ - TryFcn will not return WOULD_BLOCK nor a poll descriptor
+ - it's sufficient to call TryFcn once
+ */
+ /* we don't want result objects larger than this: */
+ if ((*hcv1->trySendAndReceiveFcn)(
+ pRequestSession,
+ NULL,
+ &myHttpResponseCode,
+ NULL,
+ NULL,
+ &myHttpResponseData,
+ &myHttpResponseDataLen) != SECSuccess) {
+ break;
+ }
+
+ if (myHttpResponseCode != 200) {
+ break;
+ }
+ } while(0);
+ if (!myHttpResponseData) {
+ /* Going to the next one. */
+ genName = CERT_GetNextGeneralName(genName);
+ derGenNames++;
+ }
+ /* Staing in the loop through all the names until
+ * we have a successful download. */
+ } while (!myHttpResponseData && *derGenNames &&
+ genName != dp->name.fullName);
+ /* Need this name to track the crl source location. */
+ PORT_Assert(derGenName);
+
+ if (!myHttpResponseData) {
+ /* Generating fake bad CRL to keep track of this dp */
+ SECItem derCrl = {siBuffer, (void*)"BadCrl", 6 };
+
+ derCrlCopy = SECITEM_DupItem(&derCrl);
+ if (!derCrlCopy) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ derGenName = *dp->nssdp->derFullName;
+ } else {
+ SECItem derCrl = { siBuffer,
+ (void*)myHttpResponseData,
+ myHttpResponseDataLen };
+ derCrlCopy = SECITEM_DupItem(&derCrl);
+ if (!derCrlCopy) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ /* crl will be based on derCrlCopy, but will not own the der. */
+ nssCrl =
+ CERT_DecodeDERCrlWithFlags(NULL, derCrlCopy, SEC_CRL_TYPE,
+ CRL_DECODE_DONT_COPY_DER |
+ CRL_DECODE_SKIP_ENTRIES);
+ }
+ /* pkix crl owns the der. */
+ PKIX_CHECK(
+ pkix_pl_CRL_CreateWithSignedCRL(nssCrl, derCrlCopy,
+ derGenName,
+ crl, plContext),
+ PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
+ /* pkix crl now own both objects. */
+ derCrlCopy = NULL;
+ nssCrl = NULL;
+
+cleanup:
+ if (derCrlCopy)
+ PORT_Free(derCrlCopy);
+ if (nssCrl)
+ SEC_DestroyCrl(nssCrl);
+ if (pRequestSession != NULL)
+ (*hcv1->freeFcn)(pRequestSession);
+ if (pServerSession != NULL)
+ (*hcv1->freeSessionFcn)(pServerSession);
+ if (path != NULL)
+ PORT_Free(path);
+ if (hostname != NULL)
+ PORT_Free(hostname);
+ if (location) {
+ PORT_Free(location);
+ }
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Pk11CertStore_GetCRL
+ * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h)
+ */
+static PKIX_Error *
+pkix_pl_Pk11CertStore_GetCRL(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrlList,
+ void *plContext)
+{
+ PKIX_UInt32 dpIndex = 0;
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_List *crlList = NULL;
+ PKIX_List *dpList = NULL;
+ pkix_pl_CrlDp *dp = NULL;
+ PKIX_PL_Date *date = NULL;
+ const SEC_HttpClientFcn *registeredHttpClient = NULL;
+
+ PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_GetCRL");
+ PKIX_NULLCHECK_THREE(store, pNBIOContext, pCrlList);
+ PKIX_NULLCHECK_TWO(selector, selector->params);
+
+ registeredHttpClient = SEC_GetRegisteredHttpClient();
+ if (!registeredHttpClient || registeredHttpClient->version != 1) {
+ goto cleanup;
+ }
+ dpList = selector->params->crldpList;
+ date = selector->params->date;
+ PKIX_CHECK(
+ RemovePartitionedDpsFromList(dpList, date,
+ plContext),
+ PKIX_FAILTOREMOVEDPFROMLIST);
+ for (;dpIndex < dpList->length;dpIndex++) {
+ PKIX_DECREF(dp);
+ pkixErrorResult =
+ PKIX_List_GetItem(dpList, dpIndex,
+ (PKIX_PL_Object **)&dp,
+ plContext);
+ if (pkixErrorResult) {
+ PKIX_DECREF(pkixErrorResult);
+ continue;
+ }
+ pkixErrorResult =
+ DownloadCrl(dp, &crl,
+ &registeredHttpClient->fcnTable.ftable1,
+ plContext);
+ if (pkixErrorResult || !crl) {
+ /* continue to next dp in case of unsuccesfull
+ * download attempt. */
+ PKIX_DECREF(pkixErrorResult);
+ continue;
+ }
+ if (!crlList) {
+ PKIX_CHECK(PKIX_List_Create(&crlList, plContext),
+ PKIX_LISTCREATEFAILED);
+ }
+ pkixErrorResult =
+ PKIX_List_AppendItem(crlList, (PKIX_PL_Object *)crl,
+ plContext);
+ if (pkixErrorResult) {
+ PKIX_DECREF(pkixErrorResult);
+ }
+ PKIX_DECREF(crl);
+ }
+ *pCrlList = crlList;
+ crlList = NULL;
+
+cleanup:
+ PKIX_DECREF(dp);
+ PKIX_DECREF(crl);
+ PKIX_DECREF(crlList);
+
+ PKIX_RETURN(CERTSTORE);
+}
+
+
+/* --Public-Pk11CertStore-Functions----------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_Pk11CertStore_Create
+ * (see comments in pkix_samples_modules.h)
+ */
+PKIX_Error *
+PKIX_PL_Pk11CertStore_Create(
+ PKIX_CertStore **pCertStore,
+ void *plContext)
+{
+ PKIX_CertStore *certStore = NULL;
+
+ PKIX_ENTER(CERTSTORE, "PKIX_PL_Pk11CertStore_Create");
+ PKIX_NULLCHECK_ONE(pCertStore);
+
+ PKIX_CHECK(PKIX_CertStore_Create
+ (pkix_pl_Pk11CertStore_GetCert,
+ pkix_pl_Pk11CertStore_GetCRL,
+ NULL, /* getCertContinue */
+ NULL, /* getCrlContinue */
+ pkix_pl_Pk11CertStore_CheckTrust,
+ pkix_pl_Pk11CertStore_ImportCrl,
+ pkix_pl_Pk11CertStore_CheckRevByCrl,
+ NULL,
+ PKIX_TRUE, /* cache flag */
+ PKIX_TRUE, /* local - no network I/O */
+ &certStore,
+ plContext),
+ PKIX_CERTSTORECREATEFAILED);
+
+ *pCertStore = certStore;
+
+cleanup:
+
+ PKIX_RETURN(CERTSTORE);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.h
new file mode 100644
index 0000000000..506707683d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.h
@@ -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/. */
+/*
+ * pkix_pl_pk11certstore.h
+ *
+ * PK11Certstore Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_PL_PK11CERTSTORE_H
+#define _PKIX_PL_PK11CERTSTORE_H
+
+#include "pkix_pl_common.h"
+#include "certi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* see source file for function documentation */
+PKIX_Error *
+PKIX_PL_Pk11CertStore_Create(
+ PKIX_CertStore **pCertStore,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_PK11CERTSTORE_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c
new file mode 100644
index 0000000000..e8698376b5
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c
@@ -0,0 +1,1695 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_socket.c
+ *
+ * Socket Function Definitions
+ *
+ */
+
+/*
+ * If Socket Tracing is active, messages sent and received will be
+ * timestamped and dumped (to stdout) in standard hex-dump format. E.g.,
+ *
+ * 1116612359156140:
+ * 28F0: 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 00 Hello, world!.
+ *
+ * The timestamp is not formatted to be meaningful except as an increasing
+ * value of seconds.microseconds, which is good enough to correlate two
+ * sides of a message exchange and to figure durations.
+ *
+ * Code to perform Socket tracing will be compiled in if PKIX_SOCKETTRACE
+ * is defined, but that doesn't mean socket tracing is active. Tracing also
+ * requires that the Boolean socketTraceFlag is set to PKIX_TRUE. That is
+ * the default value, but it can be overridden by using the debugger to
+ * change its value -- allowing tracing to be turned on and off at various
+ * breakpoints -- or by setting the environment variable SOCKETTRACE. A
+ * value of 1 sets socketTraceFlag to PKIX_TRUE (tracing on), and any other
+ * value sets socketTraceFlag to PKIX_FALSE (tracing off). The environment
+ * value is checked during system initialization.
+ */
+#ifndef BUILD_OPT
+#define PKIX_SOCKETTRACE 1
+#endif
+
+#ifdef PKIX_SOCKETDEBUG
+#define PKIX_SOCKETTRACE 1
+#endif
+
+#include "pkix_pl_socket.h"
+
+/* --Private-Socket-Functions---------------------------------- */
+
+#ifdef PKIX_SOCKETTRACE
+static PKIX_Boolean socketTraceFlag = PKIX_FALSE;
+
+/*
+ * FUNCTION: pkix_pl_socket_timestamp
+ * DESCRIPTION:
+ *
+ * This functions prints to stdout the time of day, as obtained from the
+ * system function gettimeofday, as seconds.microseconds. Its resolution
+ * is whatever the system call provides.
+ *
+ * PARAMETERS:
+ * none
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static void pkix_pl_socket_timestamp() {
+ PRInt64 prTime;
+ prTime = PR_Now();
+/* We shouldn't use PR_ALTERNATE_INT64_TYPEDEF, but nor can we use PRId64 */
+#if PR_BYTES_PER_LONG == 8 && !defined(PR_ALTERNATE_INT64_TYPEDEF)
+ printf("%ld:\n", prTime);
+#else
+ printf("%lld:\n", prTime);
+#endif
+}
+
+/*
+ * FUNCTION: pkix_pl_socket_hexDigit
+ * DESCRIPTION:
+ *
+ * This functions prints to stdout the byte "byteVal" as two hex digits.
+ *
+ * PARAMETERS:
+ * "byteVal"
+ * The value to be printed.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static void pkix_pl_socket_hexDigit(char byteVal) {
+ int n = 0;
+ char cHi = '\0';
+ char cLow = '\0';
+ n = ((byteVal >> 4) & 0xf);
+ if (n > 9) {
+ cHi = (char) ((n - 10) + 'A');
+ } else {
+ cHi = (char) (n + '0');
+ }
+ n = byteVal & 0xf;
+ if (n > 9) {
+ cLow = (char) ((n - 10) + 'A');
+ } else {
+ cLow = (char) (n + '0');
+ }
+ (void) printf("%c%c", cHi, cLow);
+}
+
+/*
+ * FUNCTION: pkix_pl_socket_linePrefix
+ * DESCRIPTION:
+ *
+ * This functions prints to stdout the address provided by "addr" as four
+ * hexadecimal digits followed by a colon and a space.
+ *
+ * PARAMETERS:
+ * "addr"
+ * The address to be printed
+ * none
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static void pkix_pl_socket_linePrefix(PKIX_UInt32 addr) {
+ pkix_pl_socket_hexDigit((char)((addr >> 8) & 0xff));
+ pkix_pl_socket_hexDigit((char)(addr & 0xff));
+ (void) printf(": ");
+}
+
+/*
+ * FUNCTION: pkix_pl_socket_traceLine
+ * DESCRIPTION:
+ *
+ * This functions prints to stdout the sixteen bytes beginning at the
+ * address pointed to by "ptr". The bytes are printed as sixteen pairs
+ * of hexadecimal characters followed by an ascii interpretation, in which
+ * characters from 0x20 to 0x7d are shown as their ascii equivalents, and
+ * other values are represented as periods.
+ *
+ * PARAMETERS:
+ * "ptr"
+ * The address of the first of the bytes to be printed
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static void pkix_pl_socket_traceLine(char *ptr) {
+ PKIX_UInt32 i = 0;
+ pkix_pl_socket_linePrefix((PKIX_UInt32)((char *)ptr - (char *)NULL));
+ for (i = 0; i < 16; i++) {
+ printf(" ");
+ pkix_pl_socket_hexDigit(ptr[i]);
+ if (i == 7) {
+ printf(" ");
+ }
+ }
+ printf(" ");
+ for (i = 0; i < 16; i++) {
+ if ((ptr[i] < ' ') || (ptr[i] > '}')) {
+ printf(".");
+ } else {
+ printf("%c", ptr[i]);
+ }
+ }
+ printf("\n");
+}
+
+/*
+ * FUNCTION: pkix_pl_socket_tracePartialLine
+ * DESCRIPTION:
+ *
+ * This functions prints to stdout the number of bytes given by "nBytes",
+ * beginning at the address pointed to by "ptr". The bytes are printed as
+ * pairs of hexadecimal characters followed by an ascii interpretation, in
+ * which characters from 0x20 to 0x7d are shown as their ascii equivalents,
+ * and other values are represented as periods.
+ *
+ * PARAMETERS:
+ * "ptr"
+ * The address of the first of the bytes to be printed
+ * "nBytes"
+ * The Int32 value giving the number of bytes to be printed. If "nBytes"
+ * is greater than sixteen, the results will be unattractive.
+ * none
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static void pkix_pl_socket_tracePartialLine(char *ptr, PKIX_UInt32 nBytes) {
+ PKIX_UInt32 i = 0;
+ if (nBytes > 0) {
+ pkix_pl_socket_linePrefix((PKIX_UInt32)((char *)ptr - (char *)NULL));
+ }
+ for (i = 0; i < nBytes; i++) {
+ printf(" ");
+ pkix_pl_socket_hexDigit(ptr[i]);
+ if (i == 7) {
+ printf(" ");
+ }
+ }
+ for (i = nBytes; i < 16; i++) {
+ printf(" ");
+ if (i == 7) {
+ printf(" ");
+ }
+ }
+ printf(" ");
+ for (i = 0; i < nBytes; i++) {
+ if ((ptr[i] < ' ') || (ptr[i] > '}')) {
+ printf(".");
+ } else {
+ printf("%c", ptr[i]);
+ }
+ }
+ printf("\n");
+}
+
+/*
+ * FUNCTION: pkix_pl_socket_tracebuff
+ * DESCRIPTION:
+ *
+ * This functions prints to stdout the number of bytes given by "nBytes",
+ * beginning with the byte pointed to by "buf". The output is preceded by
+ * a timestamp, and each group of sixteen (and a remainder, if any) is
+ * preceded by its address. The contents are shown in hexadecimal and as
+ * ascii characters. If "nBytes" is zero, the timestamp and starting
+ * address are displayed.
+ *
+ * PARAMETERS:
+ * "buf"
+ * The starting address of the bytes to be printed
+ * "nBytes"
+ * The number of bytes to be printed
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+void pkix_pl_socket_tracebuff(void *buf, PKIX_UInt32 nBytes) {
+ PKIX_UInt32 bytesRemaining = nBytes;
+ PKIX_UInt32 offset = 0;
+ char *bufptr = (char *)buf;
+
+ if (socketTraceFlag == PKIX_FALSE) return;
+
+ pkix_pl_socket_timestamp();
+ /*
+ * Special case: if called with length of zero, just do address
+ */
+ if (nBytes == 0) {
+ pkix_pl_socket_linePrefix((PKIX_UInt32)((char *)buf - (char *)NULL));
+ printf("\n");
+ } else {
+ while (bytesRemaining >= 16) {
+ pkix_pl_socket_traceLine(&bufptr[offset]);
+ bytesRemaining -= 16;
+ offset += 16;
+ }
+ pkix_pl_socket_tracePartialLine
+ (&bufptr[offset], bytesRemaining);
+ }
+}
+
+#endif
+
+/*
+ * FUNCTION: pkix_pl_Socket_SetNonBlocking
+ * DESCRIPTION:
+ *
+ * This functions sets the socket represented by the PRFileDesc "fileDesc"
+ * to nonblocking mode.
+ *
+ * PARAMETERS:
+ * "fileDesc"
+ * The address of the PRFileDesc whose I/O mode is to be set
+ * non-blocking. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static PKIX_Error *
+pkix_pl_Socket_SetNonBlocking(
+ PRFileDesc *fileDesc,
+ void *plContext)
+{
+ PRStatus rv = PR_FAILURE;
+ PRSocketOptionData sockOptionData;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_SetNonBlocking");
+ PKIX_NULLCHECK_ONE(fileDesc);
+
+ sockOptionData.option = PR_SockOpt_Nonblocking;
+ sockOptionData.value.non_blocking = PR_TRUE;
+
+ PKIX_PL_NSSCALLRV(SOCKET, rv, fileDesc->methods->setsocketoption,
+ (fileDesc, &sockOptionData));
+
+ if (rv != PR_SUCCESS) {
+ PKIX_ERROR(PKIX_UNABLETOSETSOCKETTONONBLOCKING);
+ }
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_CreateClient
+ * DESCRIPTION:
+ *
+ * This functions creates a client socket for the PKIX_PL_Socket pointed to
+ * by "socket". If "socket" was created with a timeout value of zero, the
+ * client socket is set to use nonblocking I/O.
+ *
+ * PARAMETERS:
+ * "socket"
+ * The address of the Socket for which a client socket is to be
+ * created. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+
+static PKIX_Error *
+pkix_pl_Socket_CreateClient(
+ PKIX_PL_Socket *socket,
+ void *plContext)
+{
+#ifdef PKIX_SOCKETDEBUG
+ PRErrorCode errorcode = 0;
+#endif
+ PRFileDesc *mySock = NULL;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateClient");
+ PKIX_NULLCHECK_ONE(socket);
+
+ PKIX_PL_NSSCALLRV(SOCKET, mySock, PR_NewTCPSocket, ());
+ if (!mySock) {
+#ifdef PKIX_SOCKETDEBUG
+ errorcode = PR_GetError();
+ printf
+ ("pkix_pl_Socket_CreateClient: %s\n",
+ PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
+#endif
+ PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED);
+ }
+
+#ifdef PKIX_SOCKETDEBUG
+ printf("Created socket, PRFileDesc @ %#X\n", mySock);
+#endif
+
+ socket->clientSock = mySock;
+ socket->status = SOCKET_UNCONNECTED;
+ if (socket->timeout == 0) {
+ PKIX_CHECK(pkix_pl_Socket_SetNonBlocking(mySock, plContext),
+ PKIX_SOCKETSETNONBLOCKINGFAILED);
+ }
+
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_CreateServer
+ * DESCRIPTION:
+ *
+ * This functions creates a server socket for the PKIX_PL_Socket pointed to
+ * by "socket". If "socket" was created with a timeout value of zero, the
+ * server socket is set to use nonblocking I/O.
+ *
+ * Warning: there seems to be a problem with operating a server socket in
+ * non-blocking mode. If the server calls Recv prior to a corresponding
+ * Send, the message may be lost.
+ *
+ * PARAMETERS:
+ * "socket"
+ * The address of the Socket for which a server socket is to be
+ * created. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static PKIX_Error *
+pkix_pl_Socket_CreateServer(
+ PKIX_PL_Socket *socket,
+ void *plContext)
+{
+/* #ifdef PKIX_SOCKETDEBUG */
+ PRErrorCode errorcode = 0;
+/* #endif */
+ PRStatus rv = PR_FAILURE;
+ PRFileDesc *serverSock = NULL;
+ PRSocketOptionData sockOptionData;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateServer");
+ PKIX_NULLCHECK_ONE(socket);
+
+ PKIX_PL_NSSCALLRV(SOCKET, serverSock, PR_NewTCPSocket, ());
+ if (!serverSock) {
+#ifdef PKIX_SOCKETDEBUG
+ errorcode = PR_GetError();
+ printf
+ ("pkix_pl_Socket_CreateServer: %s\n",
+ PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
+#endif
+ PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED);
+ }
+
+ socket->serverSock = serverSock;
+
+#ifdef PKIX_SOCKETDEBUG
+ printf("Created socket, PRFileDesc @ %#X\n", serverSock);
+#endif
+
+ if (socket->timeout == 0) {
+ PKIX_CHECK(pkix_pl_Socket_SetNonBlocking(serverSock, plContext),
+ PKIX_SOCKETSETNONBLOCKINGFAILED);
+ }
+
+ sockOptionData.option = PR_SockOpt_Reuseaddr;
+ sockOptionData.value.reuse_addr = PR_TRUE;
+
+ PKIX_PL_NSSCALLRV(SOCKET, rv, serverSock->methods->setsocketoption,
+ (serverSock, &sockOptionData));
+
+ if (rv != PR_SUCCESS) {
+ PKIX_ERROR(PKIX_UNABLETOSETSOCKETTONONBLOCKING);
+ }
+
+ PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Bind, (serverSock, socket->netAddr));
+
+ if (rv == PR_FAILURE) {
+/* #ifdef PKIX_SOCKETDEBUG */
+ errorcode = PR_GetError();
+ printf
+ ("pkix_pl_Socket_CreateServer: %s\n",
+ PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
+/* #endif */
+ PKIX_ERROR(PKIX_PRBINDFAILED);
+ }
+
+#ifdef PKIX_SOCKETDEBUG
+ printf("Successful bind!\n");
+#endif
+
+ socket->status = SOCKET_BOUND;
+
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_Connect
+ * DESCRIPTION:
+ *
+ * This functions performs the connect function for the client socket
+ * specified in "socket", storing the status at "pStatus".
+ *
+ * PARAMETERS:
+ * "socket"
+ * The address of the Socket for which a connect is to be performed.
+ * Must be non-NULL.
+ * "pStatus"
+ * The address at which the connection status is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static PKIX_Error *
+pkix_pl_Socket_Connect(
+ PKIX_PL_Socket *socket,
+ PRErrorCode *pStatus,
+ void *plContext)
+{
+ PRStatus rv = PR_FAILURE;
+ PRErrorCode errorcode = 0;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_Connect");
+ PKIX_NULLCHECK_TWO(socket, socket->clientSock);
+
+ PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Connect,
+ (socket->clientSock, socket->netAddr, socket->timeout));
+
+ if (rv == PR_FAILURE) {
+ errorcode = PR_GetError();
+ *pStatus = errorcode;
+ if (errorcode == PR_IN_PROGRESS_ERROR) {
+ socket->status = SOCKET_CONNECTPENDING;
+ goto cleanup;
+ } else {
+#ifdef PKIX_SOCKETDEBUG
+ printf
+ ("pkix_pl_Socket_Connect: %s\n",
+ PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
+#endif
+ PKIX_ERROR(PKIX_PRCONNECTFAILED);
+ }
+ }
+
+#ifdef PKIX_SOCKETDEBUG
+ printf("Successful connect!\n");
+#endif
+
+ *pStatus = 0;
+ socket->status = SOCKET_CONNECTED;
+
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_ConnectContinue
+ * DESCRIPTION:
+ *
+ * This functions continues the connect function for the client socket
+ * specified in "socket", storing the status at "pStatus". It is expected that
+ * the non-blocking connect has returned PR_IN_PROGRESS_ERROR.
+ *
+ * PARAMETERS:
+ * "socket"
+ * The address of the Socket for which a connect is to be continued.
+ * Must be non-NULL.
+ * "pStatus"
+ * The address at which the connection status is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static PKIX_Error *
+pkix_pl_Socket_ConnectContinue(
+ PKIX_PL_Socket *socket,
+ PRErrorCode *pStatus,
+ void *plContext)
+{
+ PRStatus rv = PR_FAILURE;
+ PRErrorCode errorcode = 0;
+ PRPollDesc pollDesc;
+ PRInt32 numEvents = 0;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_ConnectContinue");
+ PKIX_NULLCHECK_TWO(socket, socket->clientSock);
+
+ pollDesc.fd = socket->clientSock;
+ pollDesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ pollDesc.out_flags = 0;
+ PKIX_PL_NSSCALLRV(SOCKET, numEvents, PR_Poll, (&pollDesc, 1, 0));
+ if (numEvents < 0) {
+ PKIX_ERROR(PKIX_PRPOLLFAILED);
+ }
+
+ if (numEvents == 0) {
+ *pStatus = PR_IN_PROGRESS_ERROR;
+ goto cleanup;
+ }
+
+ PKIX_PL_NSSCALLRV(SOCKET, rv, PR_ConnectContinue,
+ (socket->clientSock, pollDesc.out_flags));
+
+ /*
+ * PR_ConnectContinue sometimes lies. It returns PR_SUCCESS
+ * even though the connection is not yet ready. But its deceit
+ * is betrayed by the contents of out_flags!
+ */
+ if ((rv == PR_SUCCESS) && (pollDesc.out_flags == PR_POLL_ERR)) {
+ *pStatus = PR_IN_PROGRESS_ERROR;
+ goto cleanup;
+ }
+
+ if (rv == PR_FAILURE) {
+ errorcode = PR_GetError();
+ *pStatus = errorcode;
+ if (errorcode == PR_IN_PROGRESS_ERROR) {
+ goto cleanup;
+ } else {
+#ifdef PKIX_SOCKETDEBUG
+ printf
+ ("pkix_pl_Socket_ConnectContinue: %s\n",
+ PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
+#endif
+ PKIX_ERROR(PKIX_PRCONNECTCONTINUEFAILED);
+ }
+ }
+
+#ifdef PKIX_SOCKETDEBUG
+ printf("Successful connect!\n");
+#endif
+
+ *pStatus = 0;
+ socket->status = SOCKET_CONNECTED;
+
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Socket_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Socket *socket = NULL;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_SOCKET_TYPE, plContext),
+ PKIX_OBJECTNOTANSOCKET);
+
+ socket = (PKIX_PL_Socket *)object;
+
+ if (socket->isServer) {
+ if (socket->serverSock) {
+ PR_Close(socket->serverSock);
+ }
+ } else {
+ if (socket->clientSock) {
+ PR_Close(socket->clientSock);
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Socket_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_Socket *socket = NULL;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_SOCKET_TYPE, plContext),
+ PKIX_OBJECTNOTSOCKET);
+
+ socket = (PKIX_PL_Socket *)object;
+
+ *pHashcode = (((socket->timeout << 3) +
+ (socket->netAddr->inet.family << 3)) +
+ (*((PKIX_UInt32 *)&(socket->netAddr->inet.ip)))) +
+ socket->netAddr->inet.port;
+
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Socket_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_PL_Socket *firstSocket = NULL;
+ PKIX_PL_Socket *secondSocket = NULL;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ *pResult = PKIX_FALSE;
+
+ PKIX_CHECK(pkix_CheckTypes
+ (firstObject, secondObject, PKIX_SOCKET_TYPE, plContext),
+ PKIX_OBJECTNOTSOCKET);
+
+ firstSocket = (PKIX_PL_Socket *)firstObject;
+ secondSocket = (PKIX_PL_Socket *)secondObject;
+
+ if (firstSocket->timeout != secondSocket->timeout) {
+ goto cleanup;
+ }
+
+ if (firstSocket->netAddr == secondSocket->netAddr) {
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ if ((firstSocket->netAddr->inet.family !=
+ secondSocket->netAddr->inet.family) ||
+ (*((PKIX_UInt32 *)&(firstSocket->netAddr->inet.ip)) !=
+ *((PKIX_UInt32 *)&(secondSocket->netAddr->inet.ip))) ||
+ (firstSocket->netAddr->inet.port !=
+ secondSocket->netAddr->inet.port)) {
+
+ goto cleanup;
+
+ }
+
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_PL_SOCKET_TYPE and its related
+ * functions with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_Socket_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_RegisterSelf");
+
+ entry.description = "Socket";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_Socket);
+ entry.destructor = pkix_pl_Socket_Destroy;
+ entry.equalsFunction = pkix_pl_Socket_Equals;
+ entry.hashcodeFunction = pkix_pl_Socket_Hashcode;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_SOCKET_TYPE] = entry;
+
+#ifdef PKIX_SOCKETTRACE
+ {
+ char *val = NULL;
+ val = PR_GetEnvSecure("SOCKETTRACE");
+ /* Is SOCKETTRACE set in the environment? */
+ if ((val != NULL) && (*val != '\0')) {
+ socketTraceFlag =
+ ((*val == '1')?PKIX_TRUE:PKIX_FALSE);
+ }
+ }
+#endif
+
+ PKIX_RETURN(SOCKET);
+}
+
+/* --Public-Socket-Functions----------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_Socket_Listen
+ * DESCRIPTION:
+ *
+ * This functions establishes a listening queue for the server Socket
+ * pointed to by "socket".
+ *
+ * PARAMETERS:
+ * "socket"
+ * The address of the server socket for which the queue is to be
+ * established. Must be non-NULL.
+ * "backlog"
+ * The UInt32 value of the length of the queue to be established.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static PKIX_Error *
+pkix_pl_Socket_Listen(
+ PKIX_PL_Socket *socket,
+ PKIX_UInt32 backlog,
+ void *plContext)
+{
+#ifdef PKIX_SOCKETDEBUG
+ PRErrorCode errorcode = 0;
+#endif
+ PRStatus rv = PR_FAILURE;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_Listen");
+ PKIX_NULLCHECK_TWO(socket, socket->serverSock);
+
+ PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Listen,
+ (socket->serverSock, (PRIntn)backlog));
+
+ if (rv == PR_FAILURE) {
+#ifdef PKIX_SOCKETDEBUG
+ errorcode = PR_GetError();
+ printf
+ ("pkix_pl_Socket_Listen: %s\n",
+ PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
+#endif
+ PKIX_ERROR(PKIX_PRLISTENFAILED);
+ }
+
+#ifdef PKIX_SOCKETDEBUG
+ printf("Successful listen!\n");
+#endif
+
+ socket->status = SOCKET_LISTENING;
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_Shutdown
+ * DESCRIPTION:
+ *
+ * This functions performs the shutdown of any connections controlled by the
+ * socket pointed to by "socket".
+ *
+ * PARAMETERS:
+ * "socket"
+ * The address of the socket to be shut down. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static PKIX_Error *
+pkix_pl_Socket_Shutdown(
+ PKIX_PL_Socket *socket,
+ void *plContext)
+{
+#ifdef PKIX_SOCKETDEBUG
+ PRErrorCode errorcode = 0;
+#endif
+ PRStatus rv = PR_FAILURE;
+ PRFileDesc *fileDesc = NULL;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_Shutdown");
+ PKIX_NULLCHECK_ONE(socket);
+
+ fileDesc =
+ (socket->isServer)?(socket->serverSock):(socket->clientSock);
+
+ PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Shutdown,
+ (fileDesc, PR_SHUTDOWN_BOTH));
+
+ if (rv == PR_FAILURE) {
+#ifdef PKIX_SOCKETDEBUG
+ errorcode = PR_GetError();
+ printf
+ ("pkix_pl_Socket_Shutdown: %s\n",
+ PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
+#endif
+ PKIX_ERROR(PKIX_PRSHUTDOWNFAILED);
+ }
+ socket->status = SOCKET_SHUTDOWN;
+
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_Send
+ * DESCRIPTION:
+ *
+ * This functions sends a message using the socket pointed to by "sendSock",
+ * from the buffer pointed to by "buf", of the number of bytes given by
+ * "bytesToWrite", storing the number of bytes actually written at
+ * "pBytesWritten". If "socket" is in non-blocking mode, the send operation
+ * may store -1 at "pBytesWritten" and the write is not complete until a
+ * corresponding pkix_pl_Poll call has indicated its completion by returning
+ * a non-negative value for bytes written.
+ *
+ * PARAMETERS:
+ * "sendSock"
+ * The address of the Socket on which the message is to be sent. Must
+ * be non-NULL.
+ * "buf"
+ * The address of the data to be sent. Must be non-NULL.
+ * "bytesToWrite""
+ * The UInt32 value indicating the number of bytes to write.
+ * "pBytesWritten"
+ * The address at which the Int32 value indicating the number of bytes
+ * actually written is to be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static PKIX_Error *
+pkix_pl_Socket_Send(
+ PKIX_PL_Socket *sendSock,
+ void *buf,
+ PKIX_UInt32 bytesToWrite,
+ PKIX_Int32 *pBytesWritten,
+ void *plContext)
+{
+ PRInt32 bytesWritten = 0;
+ PRErrorCode errorcode = 0;
+ PRFileDesc *fd = NULL;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_Send");
+ PKIX_NULLCHECK_TWO(buf, pBytesWritten);
+
+ fd = sendSock->clientSock;
+
+ PKIX_PL_NSSCALLRV(SOCKET, bytesWritten, PR_Send,
+ (fd, buf, (PRInt32)bytesToWrite, 0, sendSock->timeout));
+
+ if (bytesWritten >= 0) {
+ if (sendSock->status == SOCKET_SENDRCVPENDING) {
+ sendSock->status = SOCKET_RCVPENDING;
+ } else {
+ sendSock->status = SOCKET_CONNECTED;
+ }
+#ifdef PKIX_SOCKETTRACE
+ pkix_pl_socket_tracebuff(buf, bytesWritten);
+#endif
+ } else {
+ errorcode = PR_GetError();
+ if (errorcode != PR_WOULD_BLOCK_ERROR) {
+#ifdef PKIX_SOCKETDEBUG
+ printf
+ ("pkix_pl_Socket_Send: %s\n",
+ PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
+#endif
+ PKIX_ERROR(PKIX_PRSENDFAILED);
+ }
+
+ sendSock->writeBuf = buf;
+ sendSock->writeBufSize = bytesToWrite;
+ if (sendSock->status == SOCKET_RCVPENDING) {
+ sendSock->status = SOCKET_SENDRCVPENDING;
+ } else {
+ sendSock->status = SOCKET_SENDPENDING;
+ }
+ }
+
+ *pBytesWritten = (PKIX_Int32)bytesWritten;
+
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_Recv
+ * DESCRIPTION:
+ *
+ * This functions receives a message on the socket pointed to by "rcvSock",
+ * into the buffer pointed to by "buf", of capacity given by "capacity",
+ * storing the number of bytes actually received at "pBytesRead". If "socket"
+ * is in non-blocking mode, the receive operation may store -1 at
+ * "pBytesWritten". In that case the write is not complete until a
+ * corresponding pkix_pl_Poll call has indicated its completion by returning
+ * a non-negative value for bytes read.
+ *
+ * PARAMETERS:
+ * "rcvSock"
+ * The address of the Socket on which the message is to be received.
+ * Must be non-NULL.
+ * "buf"
+ * The address of the buffer into which the message is to be received.
+ * Must be non-NULL.
+ * "capacity"
+ * The UInt32 value of the size of the buffer; that is, the maximum
+ * number of bytes that can be received.
+ * "pBytesRead"
+ * The address at which is stored the Int32 value of the number of bytes
+ * actually received.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static PKIX_Error *
+pkix_pl_Socket_Recv(
+ PKIX_PL_Socket *rcvSock,
+ void *buf,
+ PKIX_UInt32 capacity,
+ PKIX_Int32 *pBytesRead,
+ void *plContext)
+{
+ PRErrorCode errorcode = 0;
+ PRInt32 bytesRead = 0;
+ PRFileDesc *fd = NULL;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_Recv");
+ PKIX_NULLCHECK_THREE(rcvSock, buf, pBytesRead);
+
+ fd = rcvSock->clientSock;
+
+ PKIX_PL_NSSCALLRV(SOCKET, bytesRead, PR_Recv,
+ (fd, buf, (PRInt32)capacity, 0, rcvSock->timeout));
+
+ if (bytesRead > 0) {
+ if (rcvSock->status == SOCKET_SENDRCVPENDING) {
+ rcvSock->status = SOCKET_SENDPENDING;
+ } else {
+ rcvSock->status = SOCKET_CONNECTED;
+ }
+#ifdef PKIX_SOCKETTRACE
+ pkix_pl_socket_tracebuff(buf, bytesRead);
+#endif
+ } else if (bytesRead == 0) {
+ PKIX_ERROR(PKIX_PRRECVREPORTSNETWORKCONNECTIONCLOSED);
+ } else {
+ errorcode = PR_GetError();
+ if (errorcode != PR_WOULD_BLOCK_ERROR) {
+#ifdef PKIX_SOCKETDEBUG
+ printf
+ ("pkix_pl_Socket_Recv: %s\n",
+ PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
+#endif
+ PKIX_ERROR(PKIX_PRRECVFAILED);
+ }
+ rcvSock->readBuf = buf;
+ rcvSock->readBufSize = capacity;
+ if (rcvSock->status == SOCKET_SENDPENDING) {
+ rcvSock->status = SOCKET_SENDRCVPENDING;
+ } else {
+ rcvSock->status = SOCKET_RCVPENDING;
+ }
+
+ }
+
+ *pBytesRead = (PKIX_Int32)bytesRead;
+
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_Poll
+ * DESCRIPTION:
+ *
+ * This functions checks for completion of an earlier Send or Recv on the
+ * socket pointed to by "sock", storing in "pBytesWritten" the number of bytes
+ * written by a completed Send and in "pBytesRead" the number of bytes
+ * received in a completed Recv. A value of -1 returned indicates the
+ * operation has still not completed. A NULL pointer may be supplied for
+ * "pBytesWritten" to avoid checking for completion of a Send. A NULL pointer
+ * may be supplied for "pBytesRead" to avoid checking for completion of a Recv.
+ *
+ * PARAMETERS:
+ * "sock"
+ * The address of the socket for which completions are to be checked.
+ * "pBytesWritten"
+ * The address at which the number of bytes written is to be stored, if
+ * a pending Send has completed. If NULL, Sends are not checked.
+ * "pBytesRead"
+ * The address at which the number of bytes read is to be stored, if
+ * a pending Recv has completed. If NULL, Recvs are not checked.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static PKIX_Error *
+pkix_pl_Socket_Poll(
+ PKIX_PL_Socket *sock,
+ PKIX_Int32 *pBytesWritten,
+ PKIX_Int32 *pBytesRead,
+ void *plContext)
+{
+ PRPollDesc pollDesc;
+ PRInt32 numEvents = 0;
+ PKIX_Int32 bytesRead = 0;
+ PKIX_Int32 bytesWritten = 0;
+ PRErrorCode errorcode = 0;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_Poll");
+ PKIX_NULLCHECK_ONE(sock);
+
+ pollDesc.fd = sock->clientSock;
+ pollDesc.in_flags = 0;
+ pollDesc.out_flags = 0;
+
+ if ((pBytesWritten) &&
+ ((sock->status == SOCKET_SENDPENDING) ||
+ (sock->status == SOCKET_SENDRCVPENDING))) {
+ pollDesc.in_flags = PR_POLL_WRITE;
+ }
+
+ if ((pBytesRead) &&
+ ((sock->status == SOCKET_RCVPENDING) ||
+ (sock->status == SOCKET_SENDRCVPENDING))) {
+ pollDesc.in_flags |= PR_POLL_READ;
+ }
+
+ PKIX_PL_NSSCALLRV(SOCKET, numEvents, PR_Poll, (&pollDesc, 1, 0));
+
+ if (numEvents < 0) {
+ PKIX_ERROR(PKIX_PRPOLLFAILED);
+ } else if (numEvents > 0) {
+ if (pollDesc.out_flags & PR_POLL_WRITE) {
+ PKIX_CHECK(pkix_pl_Socket_Send
+ (sock,
+ sock->writeBuf,
+ sock->writeBufSize,
+ &bytesWritten,
+ plContext),
+ PKIX_SOCKETSENDFAILED);
+ *pBytesWritten = (PKIX_Int32)bytesWritten;
+ if (bytesWritten >= 0) {
+ sock->writeBuf = NULL;
+ sock->writeBufSize = 0;
+ }
+ }
+
+ if (pollDesc.out_flags & PR_POLL_READ) {
+ PKIX_CHECK(pkix_pl_Socket_Recv
+ (sock,
+ sock->readBuf,
+ sock->readBufSize,
+ &bytesRead,
+ plContext),
+ PKIX_SOCKETRECVFAILED);
+ *pBytesRead = (PKIX_Int32)bytesRead;
+ if (bytesRead >= 0) {
+ sock->readBuf = NULL;
+ sock->readBufSize = 0;
+ }
+ }
+ } else if (numEvents == 0) {
+ errorcode = PR_GetError();
+ if (errorcode != PR_WOULD_BLOCK_ERROR) {
+#ifdef PKIX_SOCKETDEBUG
+ printf
+ ("pkix_pl_Socket_Poll: %s\n",
+ PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
+#endif
+ PKIX_ERROR(PKIX_PRPOLLFAILED);
+ }
+ if (pBytesWritten) {
+ *pBytesWritten = 0;
+ }
+ if (pBytesRead) {
+ *pBytesRead = 0;
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_Accept
+ * DESCRIPTION:
+ *
+ * This functions accepts a client connection for the server Socket pointed
+ * to by "serverSocket", creating a new Socket and storing the result at
+ * "pRendezvousSocket". If "serverSocket" is in non-blocking mode, this
+ * function will return NULL if there is no client connection to accept.
+ * Otherwise this function will block until a connection is available.
+ * When a client connection is available the new Socket will have the same
+ * blocking/non-blocking property as "serverSocket".
+ *
+ * PARAMETERS:
+ * "serverSocket"
+ * The address of the Socket for which a client connection is to be
+ * accepted. Must be non-NULL.
+ * "pRendezvousSocket"
+ * The address at which the created Socket is stored, when a client
+ * connection is available, or at which NULL is stored, if no connection
+ * is available for a non-blocking "serverSocket". Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety definitions in Programmer's Guide)
+ * RETURNS:
+ * none
+ */
+static PKIX_Error *
+pkix_pl_Socket_Accept(
+ PKIX_PL_Socket *serverSocket,
+ PKIX_PL_Socket **pRendezvousSocket,
+ void *plContext)
+{
+ PRErrorCode errorcode = 0;
+ PRFileDesc *rendezvousSock = NULL;
+ PRNetAddr *clientAddr = NULL;
+ PKIX_PL_Socket *newSocket = NULL;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_Accept");
+ PKIX_NULLCHECK_TWO(serverSocket, pRendezvousSocket);
+
+ PKIX_PL_NSSCALLRV(SOCKET, rendezvousSock, PR_Accept,
+ (serverSocket->serverSock, clientAddr, serverSocket->timeout));
+
+ if (!rendezvousSock) {
+ errorcode = PR_GetError();
+ if (errorcode != PR_WOULD_BLOCK_ERROR) {
+#ifdef PKIX_SOCKETDEBUG
+ printf
+ ("pkix_pl_Socket_Accept: %s\n",
+ PR_ErrorToString(errorcode, PR_LANGUAGE_EN));
+#endif
+ PKIX_ERROR(PKIX_PRACCEPTFAILED);
+ }
+ serverSocket->status = SOCKET_ACCEPTPENDING;
+ *pRendezvousSocket = NULL;
+ goto cleanup;
+
+ }
+
+#ifdef PKIX_SOCKETDEBUG
+ printf("Successful accept!\n");
+#endif
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_SOCKET_TYPE,
+ sizeof (PKIX_PL_Socket),
+ (PKIX_PL_Object **)&newSocket,
+ plContext),
+ PKIX_COULDNOTCREATESOCKETOBJECT);
+
+ newSocket->isServer = PKIX_FALSE;
+ newSocket->timeout = serverSocket->timeout;
+ newSocket->clientSock = rendezvousSock;
+ newSocket->serverSock = NULL;
+ newSocket->netAddr = NULL;
+ newSocket->status = SOCKET_CONNECTED;
+ newSocket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown;
+ newSocket->callbackList.listenCallback = pkix_pl_Socket_Listen;
+ newSocket->callbackList.acceptCallback = pkix_pl_Socket_Accept;
+ newSocket->callbackList.connectcontinueCallback =
+ pkix_pl_Socket_ConnectContinue;
+ newSocket->callbackList.sendCallback = pkix_pl_Socket_Send;
+ newSocket->callbackList.recvCallback = pkix_pl_Socket_Recv;
+ newSocket->callbackList.pollCallback = pkix_pl_Socket_Poll;
+
+ if (serverSocket->timeout == 0) {
+ PKIX_CHECK(pkix_pl_Socket_SetNonBlocking
+ (rendezvousSock, plContext),
+ PKIX_SOCKETSETNONBLOCKINGFAILED);
+ }
+
+ *pRendezvousSocket = newSocket;
+
+cleanup:
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_Create
+ * DESCRIPTION:
+ *
+ * This function creates a new Socket, setting it to be a server or a client
+ * according to the value of "isServer", setting its timeout value from
+ * "timeout" and server address from "netAddr", and stores the created Socket
+ * at "pSocket".
+ *
+ * PARAMETERS:
+ * "isServer"
+ * The Boolean value indicating if PKIX_TRUE, that a server socket (using
+ * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a
+ * client socket (using Connect) is to be created.
+ * "timeout"
+ * A PRTimeInterval value to be used for I/O waits for this socket. If
+ * zero, non-blocking I/O is to be used.
+ * "netAddr"
+ * The PRNetAddr to be used for the Bind function, if this is a server
+ * socket, or for the Connect, if this is a client socket.
+ * "pSocket"
+ * The address at which the Socket is to be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Socket Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Socket_Create(
+ PKIX_Boolean isServer,
+ PRIntervalTime timeout,
+ PRNetAddr *netAddr,
+ PRErrorCode *status,
+ PKIX_PL_Socket **pSocket,
+ void *plContext)
+{
+ PKIX_PL_Socket *socket = NULL;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_Create");
+ PKIX_NULLCHECK_ONE(pSocket);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_SOCKET_TYPE,
+ sizeof (PKIX_PL_Socket),
+ (PKIX_PL_Object **)&socket,
+ plContext),
+ PKIX_COULDNOTCREATESOCKETOBJECT);
+
+ socket->isServer = isServer;
+ socket->timeout = timeout;
+ socket->clientSock = NULL;
+ socket->serverSock = NULL;
+ socket->netAddr = netAddr;
+
+ socket->callbackList.listenCallback = pkix_pl_Socket_Listen;
+ socket->callbackList.acceptCallback = pkix_pl_Socket_Accept;
+ socket->callbackList.connectcontinueCallback =
+ pkix_pl_Socket_ConnectContinue;
+ socket->callbackList.sendCallback = pkix_pl_Socket_Send;
+ socket->callbackList.recvCallback = pkix_pl_Socket_Recv;
+ socket->callbackList.pollCallback = pkix_pl_Socket_Poll;
+ socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown;
+
+ if (isServer) {
+ PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext),
+ PKIX_SOCKETCREATESERVERFAILED);
+ *status = 0;
+ } else {
+ socket->timeout = timeout;
+ PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext),
+ PKIX_SOCKETCREATECLIENTFAILED);
+ PKIX_CHECK(pkix_pl_Socket_Connect(socket, status, plContext),
+ PKIX_SOCKETCONNECTFAILED);
+ }
+
+ *pSocket = socket;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(socket);
+ }
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_CreateByName
+ * DESCRIPTION:
+ *
+ * This function creates a new Socket, setting it to be a server or a client
+ * according to the value of "isServer", setting its timeout value from
+ * "timeout" and server address and port number from "serverName", and stores
+ * the status at "pStatus" and the created Socket at "pSocket".
+ *
+ * If isServer is PKIX_TRUE, it is attempted to create the socket with an ip
+ * address of PR_INADDR_ANY.
+ *
+ * PARAMETERS:
+ * "isServer"
+ * The Boolean value indicating if PKIX_TRUE, that a server socket (using
+ * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a
+ * client socket (using Connect) is to be created.
+ * "timeout"
+ * A PRTimeInterval value to be used for I/O waits for this socket. If
+ * zero, non-blocking I/O is to be used.
+ * "serverName"
+ * Address of a character string consisting of the server's domain name
+ * followed by a colon and a port number for the desired socket.
+ * "pStatus"
+ * Address at which the PRErrorCode resulting from the create is
+ * stored. Must be non-NULL.
+ * "pSocket"
+ * The address at which the Socket is to be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Socket Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Socket_CreateByName(
+ PKIX_Boolean isServer,
+ PRIntervalTime timeout,
+ char *serverName,
+ PRErrorCode *pStatus,
+ PKIX_PL_Socket **pSocket,
+ void *plContext)
+{
+ PRNetAddr netAddr;
+ PKIX_PL_Socket *socket = NULL;
+ char *sepPtr = NULL;
+ PRHostEnt hostent;
+ PRIntn hostenum;
+ PRStatus prstatus = PR_FAILURE;
+ char buf[PR_NETDB_BUF_SIZE];
+ PRUint16 portNum = 0;
+ char *localCopyName = NULL;
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateByName");
+ PKIX_NULLCHECK_TWO(serverName, pSocket);
+
+ localCopyName = PL_strdup(serverName);
+
+ sepPtr = strchr(localCopyName, ':');
+ /* 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;
+ }
+
+ prstatus = PR_GetHostByName(localCopyName, buf, sizeof(buf), &hostent);
+
+ if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) {
+ /*
+ * The hostname may be a fully-qualified name. Try using just
+ * the leftmost component in our lookup.
+ */
+ sepPtr = strchr(localCopyName, '.');
+ if (sepPtr) {
+ *sepPtr++ = '\0';
+ }
+ prstatus = PR_GetHostByName
+ (localCopyName, buf, sizeof(buf), &hostent);
+
+ if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) {
+ PKIX_ERROR
+ (PKIX_PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT);
+ }
+ }
+
+ netAddr.inet.family = PR_AF_INET;
+ netAddr.inet.port = PR_htons(portNum);
+
+ if (isServer) {
+
+ netAddr.inet.ip = PR_INADDR_ANY;
+
+ } else {
+
+ hostenum = PR_EnumerateHostEnt(0, &hostent, portNum, &netAddr);
+ if (hostenum == -1) {
+ PKIX_ERROR(PKIX_PRENUMERATEHOSTENTFAILED);
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_SOCKET_TYPE,
+ sizeof (PKIX_PL_Socket),
+ (PKIX_PL_Object **)&socket,
+ plContext),
+ PKIX_COULDNOTCREATESOCKETOBJECT);
+
+ socket->isServer = isServer;
+ socket->timeout = timeout;
+ socket->clientSock = NULL;
+ socket->serverSock = NULL;
+ socket->netAddr = &netAddr;
+
+ socket->callbackList.listenCallback = pkix_pl_Socket_Listen;
+ socket->callbackList.acceptCallback = pkix_pl_Socket_Accept;
+ socket->callbackList.connectcontinueCallback =
+ pkix_pl_Socket_ConnectContinue;
+ socket->callbackList.sendCallback = pkix_pl_Socket_Send;
+ socket->callbackList.recvCallback = pkix_pl_Socket_Recv;
+ socket->callbackList.pollCallback = pkix_pl_Socket_Poll;
+ socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown;
+
+ if (isServer) {
+ PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext),
+ PKIX_SOCKETCREATESERVERFAILED);
+ *pStatus = 0;
+ } else {
+ PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext),
+ PKIX_SOCKETCREATECLIENTFAILED);
+ PKIX_CHECK(pkix_pl_Socket_Connect(socket, pStatus, plContext),
+ PKIX_SOCKETCONNECTFAILED);
+ }
+
+ *pSocket = socket;
+
+cleanup:
+ PL_strfree(localCopyName);
+
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(socket);
+ }
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_CreateByHostAndPort
+ * DESCRIPTION:
+ *
+ * This function creates a new Socket, setting it to be a server or a client
+ * according to the value of "isServer", setting its timeout value from
+ * "timeout", host from "hostname", and port number from "portNum", and stores
+ * the status at "pStatus" and the created Socket at "pSocket".
+ *
+ * If isServer is PKIX_TRUE, it is attempted to create the socket with an ip
+ * address of PR_INADDR_ANY.
+ *
+ * PARAMETERS:
+ * "isServer"
+ * The Boolean value indicating if PKIX_TRUE, that a server socket (using
+ * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a
+ * client socket (using Connect) is to be created.
+ * "timeout"
+ * A PRTimeInterval value to be used for I/O waits for this socket. If
+ * zero, non-blocking I/O is to be used.
+ * "hostname"
+ * Address of a character string consisting of the server's domain name.
+ * "portNum"
+ * UInt16 value of the port number for the desired socket.
+ * "pStatus"
+ * Address at which the PRErrorCode resulting from the create is
+ * stored. Must be non-NULL.
+ * "pSocket"
+ * The address at which the Socket is to be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Socket Error if the function fails in
+ * a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Socket_CreateByHostAndPort(
+ PKIX_Boolean isServer,
+ PRIntervalTime timeout,
+ char *hostname,
+ PRUint16 portnum,
+ PRErrorCode *pStatus,
+ PKIX_PL_Socket **pSocket,
+ void *plContext)
+{
+ PRNetAddr netAddr;
+ PKIX_PL_Socket *socket = NULL;
+ char *sepPtr = NULL;
+ PRHostEnt hostent;
+ PRIntn hostenum;
+ PRStatus prstatus = PR_FAILURE;
+ char buf[PR_NETDB_BUF_SIZE];
+
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateByHostAndPort");
+ PKIX_NULLCHECK_THREE(hostname, pStatus, pSocket);
+
+
+ prstatus = PR_GetHostByName(hostname, buf, sizeof(buf), &hostent);
+
+ if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) {
+ /*
+ * The hostname may be a fully-qualified name. Try using just
+ * the leftmost component in our lookup.
+ */
+ sepPtr = strchr(hostname, '.');
+ if (sepPtr) {
+ *sepPtr++ = '\0';
+ }
+ prstatus = PR_GetHostByName(hostname, buf, sizeof(buf), &hostent);
+
+ if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) {
+ PKIX_ERROR
+ (PKIX_PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT);
+ }
+ }
+
+ netAddr.inet.family = PR_AF_INET;
+ netAddr.inet.port = PR_htons(portnum);
+
+ if (isServer) {
+
+ netAddr.inet.ip = PR_INADDR_ANY;
+
+ } else {
+
+ hostenum = PR_EnumerateHostEnt(0, &hostent, portnum, &netAddr);
+ if (hostenum == -1) {
+ PKIX_ERROR(PKIX_PRENUMERATEHOSTENTFAILED);
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_SOCKET_TYPE,
+ sizeof (PKIX_PL_Socket),
+ (PKIX_PL_Object **)&socket,
+ plContext),
+ PKIX_COULDNOTCREATESOCKETOBJECT);
+
+ socket->isServer = isServer;
+ socket->timeout = timeout;
+ socket->clientSock = NULL;
+ socket->serverSock = NULL;
+ socket->netAddr = &netAddr;
+
+ socket->callbackList.listenCallback = pkix_pl_Socket_Listen;
+ socket->callbackList.acceptCallback = pkix_pl_Socket_Accept;
+ socket->callbackList.connectcontinueCallback =
+ pkix_pl_Socket_ConnectContinue;
+ socket->callbackList.sendCallback = pkix_pl_Socket_Send;
+ socket->callbackList.recvCallback = pkix_pl_Socket_Recv;
+ socket->callbackList.pollCallback = pkix_pl_Socket_Poll;
+ socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown;
+
+ if (isServer) {
+ PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext),
+ PKIX_SOCKETCREATESERVERFAILED);
+ *pStatus = 0;
+ } else {
+ PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext),
+ PKIX_SOCKETCREATECLIENTFAILED);
+ PKIX_CHECK(pkix_pl_Socket_Connect(socket, pStatus, plContext),
+ PKIX_SOCKETCONNECTFAILED);
+ }
+
+ *pSocket = socket;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(socket);
+ }
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_GetCallbackList
+ */
+PKIX_Error *
+pkix_pl_Socket_GetCallbackList(
+ PKIX_PL_Socket *socket,
+ PKIX_PL_Socket_Callback **pCallbackList,
+ void *plContext)
+{
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_GetCallbackList");
+ PKIX_NULLCHECK_TWO(socket, pCallbackList);
+
+ *pCallbackList = &(socket->callbackList);
+
+ PKIX_RETURN(SOCKET);
+}
+
+/*
+ * FUNCTION: pkix_pl_Socket_GetPRFileDesc
+ */
+PKIX_Error *
+pkix_pl_Socket_GetPRFileDesc(
+ PKIX_PL_Socket *socket,
+ PRFileDesc **pDesc,
+ void *plContext)
+{
+ PKIX_ENTER(SOCKET, "pkix_pl_Socket_GetPRFileDesc");
+ PKIX_NULLCHECK_TWO(socket, pDesc);
+
+ *pDesc = socket->clientSock;
+
+ PKIX_RETURN(SOCKET);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.h b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.h
new file mode 100644
index 0000000000..abf6628b32
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.h
@@ -0,0 +1,209 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_socket.h
+ *
+ * Socket Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_PL_SOCKET_H
+#define _PKIX_PL_SOCKET_H
+
+#include <errno.h>
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ SOCKET_BOUND,
+ SOCKET_LISTENING,
+ SOCKET_ACCEPTPENDING,
+ SOCKET_UNCONNECTED,
+ SOCKET_CONNECTPENDING,
+ SOCKET_CONNECTED,
+ SOCKET_SENDPENDING,
+ SOCKET_RCVPENDING,
+ SOCKET_SENDRCVPENDING,
+ SOCKET_SHUTDOWN
+} SockStatus;
+
+/* This is the default port number, if none is supplied to CreateByName. */
+#define LDAP_PORT 389
+
+/*
+ * These callbacks allow a user to substitute a counterfeit socket in places
+ * where a PKIX_PL_Socket is expected. A conforming usage will use the
+ * ListenCallback function instead of Listen, AcceptCallback instead of Accept,
+ * etc. The counterfeit socket may have special capabilites such as the
+ * ability to do proxy authentication, etc.
+ */
+
+typedef PKIX_Error *
+(*pkix_pl_Socket_ListenCallback)(
+ PKIX_PL_Socket *socket,
+ PKIX_UInt32 backlog,
+ void *plContext);
+
+typedef PKIX_Error *
+(*pkix_pl_Socket_AcceptCallback)(
+ PKIX_PL_Socket *socket,
+ PKIX_PL_Socket **pRendezvousSock,
+ void *plContext);
+
+typedef PKIX_Error *
+(*pkix_pl_Socket_ConnectContinueCallback)(
+ PKIX_PL_Socket *socket,
+ PRErrorCode *pStatus,
+ void *plContext);
+
+typedef PKIX_Error *
+(*pkix_pl_Socket_SendCallback)(
+ PKIX_PL_Socket *sendSock,
+ void *buf,
+ PKIX_UInt32 bytesToWrite,
+ PKIX_Int32 *pBytesWritten,
+ void *plContext);
+
+typedef PKIX_Error *
+(*pkix_pl_Socket_RecvCallback)(
+ PKIX_PL_Socket *rcvSock,
+ void *buf,
+ PKIX_UInt32 capacity,
+ PKIX_Int32 *pBytesRead,
+ void *plContext);
+
+typedef PKIX_Error *
+(*pkix_pl_Socket_PollCallback)(
+ PKIX_PL_Socket *sock,
+ PKIX_Int32 *pBytesWritten,
+ PKIX_Int32 *pBytesRead,
+ void *plContext);
+
+typedef PKIX_Error *
+(*pkix_pl_Socket_ShutdownCallback)(
+ PKIX_PL_Socket *socket, void *plContext);
+
+typedef struct PKIX_PL_Socket_CallbackStruct {
+ pkix_pl_Socket_ListenCallback listenCallback;
+ pkix_pl_Socket_AcceptCallback acceptCallback;
+ pkix_pl_Socket_ConnectContinueCallback connectcontinueCallback;
+ pkix_pl_Socket_SendCallback sendCallback;
+ pkix_pl_Socket_RecvCallback recvCallback;
+ pkix_pl_Socket_PollCallback pollCallback;
+ pkix_pl_Socket_ShutdownCallback shutdownCallback;
+} PKIX_PL_Socket_Callback;
+
+struct PKIX_PL_SocketStruct {
+ PKIX_Boolean isServer;
+ PRIntervalTime timeout; /* zero for non-blocking I/O */
+ SockStatus status;
+ PRFileDesc *clientSock;
+ PRFileDesc *serverSock;
+ void *readBuf;
+ void *writeBuf;
+ PKIX_UInt32 readBufSize;
+ PKIX_UInt32 writeBufSize;
+ PRNetAddr *netAddr;
+ PKIX_PL_Socket_Callback callbackList;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_Socket_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_Socket_Create(
+ PKIX_Boolean isServer,
+ PRIntervalTime timeout, /* zero for non-blocking I/O */
+ PRNetAddr *netAddr,
+ PRErrorCode *status,
+ PKIX_PL_Socket **pSocket,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_Socket_CreateByName(
+ PKIX_Boolean isServer,
+ PRIntervalTime timeout,
+ char *serverName,
+ PRErrorCode *pStatus,
+ PKIX_PL_Socket **pSocket,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_Socket_CreateByHostAndPort(
+ PKIX_Boolean isServer,
+ PRIntervalTime timeout,
+ char *hostname,
+ PRUint16 portnum,
+ PRErrorCode *pStatus,
+ PKIX_PL_Socket **pSocket,
+ void *plContext);
+
+/* Do not use these functions directly; use their callback variants instead
+ * static PKIX_Error *
+ * pkix_pl_Socket_Listen(
+ * PKIX_PL_Socket *socket,
+ * PKIX_UInt32 backlog,
+ * void *plContext);
+ *
+ * static PKIX_Error *
+ * pkix_pl_Socket_Accept(
+ * PKIX_PL_Socket *socket,
+ * PKIX_PL_Socket **pRendezvousSock,
+ * void *plContext);
+ *
+ * static PKIX_Error *
+ * pkix_pl_Socket_ConnectContinue(
+ * PKIX_PL_Socket *socket,
+ * PRErrorCode *pStatus,
+ * void *plContext);
+ *
+ * static PKIX_Error *
+ * pkix_pl_Socket_Send(
+ * PKIX_PL_Socket *sendSock,
+ * void *buf,
+ * PKIX_UInt32 bytesToWrite,
+ * PKIX_Int32 *pBytesWritten,
+ * void *plContext);
+ *
+ * static PKIX_Error *
+ * pkix_pl_Socket_Recv(
+ * PKIX_PL_Socket *rcvSock,
+ * void *buf,
+ * PKIX_UInt32 capacity,
+ * PKIX_Int32 *pBytesRead,
+ * void *plContext);
+ *
+ * static PKIX_Error *
+ * pkix_pl_Socket_Poll(
+ * PKIX_PL_Socket *sock,
+ * PKIX_Int32 *pBytesWritten,
+ * PKIX_Int32 *pBytesRead,
+ * void *plContext);
+ *
+ * static PKIX_Error *
+ * pkix_pl_Socket_Shutdown(
+ * PKIX_PL_Socket *socket, void *plContext);
+ */
+
+PKIX_Error *
+pkix_pl_Socket_GetCallbackList(
+ PKIX_PL_Socket *socket,
+ PKIX_PL_Socket_Callback **pCallbackList,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_Socket_GetPRFileDesc(
+ PKIX_PL_Socket *socket,
+ PRFileDesc **pDesc,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_SOCKET_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/Makefile b/security/nss/lib/libpkix/pkix_pl_nss/pki/Makefile
new file mode 100644
index 0000000000..2b4b1574ab
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+
+#######################################################################
+# (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/lib/libpkix/pkix_pl_nss/pki/exports.gyp b/security/nss/lib/libpkix/pkix_pl_nss/pki/exports.gyp
new file mode 100644
index 0000000000..616f94fd46
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/exports.gyp
@@ -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/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_libpkix_pkix_pl_nss_pki_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_pl_basicconstraints.h',
+ 'pkix_pl_cert.h',
+ 'pkix_pl_certpolicyinfo.h',
+ 'pkix_pl_certpolicymap.h',
+ 'pkix_pl_certpolicyqualifier.h',
+ 'pkix_pl_crl.h',
+ 'pkix_pl_crldp.h',
+ 'pkix_pl_crlentry.h',
+ 'pkix_pl_date.h',
+ 'pkix_pl_generalname.h',
+ 'pkix_pl_infoaccess.h',
+ 'pkix_pl_nameconstraints.h',
+ 'pkix_pl_ocspcertid.h',
+ 'pkix_pl_ocsprequest.h',
+ 'pkix_pl_ocspresponse.h',
+ 'pkix_pl_publickey.h',
+ 'pkix_pl_x500name.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/manifest.mn b/security/nss/lib/libpkix/pkix_pl_nss/pki/manifest.mn
new file mode 100644
index 0000000000..aba1367e56
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/manifest.mn
@@ -0,0 +1,50 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.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 = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_pl_basicconstraints.h \
+ pkix_pl_cert.h \
+ pkix_pl_certpolicyinfo.h \
+ pkix_pl_certpolicymap.h \
+ pkix_pl_certpolicyqualifier.h \
+ pkix_pl_crl.h \
+ pkix_pl_crldp.h \
+ pkix_pl_crlentry.h \
+ pkix_pl_date.h \
+ pkix_pl_generalname.h \
+ pkix_pl_infoaccess.h \
+ pkix_pl_nameconstraints.h \
+ pkix_pl_ocsprequest.h \
+ pkix_pl_ocspresponse.h \
+ pkix_pl_publickey.h \
+ pkix_pl_x500name.h \
+ pkix_pl_ocspcertid.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_pl_basicconstraints.c \
+ pkix_pl_cert.c \
+ pkix_pl_certpolicyinfo.c \
+ pkix_pl_certpolicymap.c \
+ pkix_pl_certpolicyqualifier.c \
+ pkix_pl_crl.c \
+ pkix_pl_crldp.c \
+ pkix_pl_crlentry.c \
+ pkix_pl_date.c \
+ pkix_pl_generalname.c \
+ pkix_pl_infoaccess.c \
+ pkix_pl_nameconstraints.c \
+ pkix_pl_ocsprequest.c \
+ pkix_pl_ocspresponse.c \
+ pkix_pl_publickey.c \
+ pkix_pl_x500name.c \
+ pkix_pl_ocspcertid.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixpki
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pki.gyp b/security/nss/lib/libpkix/pkix_pl_nss/pki/pki.gyp
new file mode 100644
index 0000000000..af7730c0bf
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pki.gyp
@@ -0,0 +1,39 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixpki',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_pl_basicconstraints.c',
+ 'pkix_pl_cert.c',
+ 'pkix_pl_certpolicyinfo.c',
+ 'pkix_pl_certpolicymap.c',
+ 'pkix_pl_certpolicyqualifier.c',
+ 'pkix_pl_crl.c',
+ 'pkix_pl_crldp.c',
+ 'pkix_pl_crlentry.c',
+ 'pkix_pl_date.c',
+ 'pkix_pl_generalname.c',
+ 'pkix_pl_infoaccess.c',
+ 'pkix_pl_nameconstraints.c',
+ 'pkix_pl_ocspcertid.c',
+ 'pkix_pl_ocsprequest.c',
+ 'pkix_pl_ocspresponse.c',
+ 'pkix_pl_publickey.c',
+ 'pkix_pl_x500name.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.c
new file mode 100644
index 0000000000..81615da37a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.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/. */
+/*
+ * pkix_pl_basicconstraints.c
+ *
+ * BasicConstraints Object Functions
+ *
+ */
+
+#include "pkix_pl_basicconstraints.h"
+
+/*
+ * FUNCTION: pkix_pl_CertBasicConstraints_Create
+ * DESCRIPTION:
+ *
+ * Creates a new CertBasicConstraints object whose CA Flag has the value
+ * given by the Boolean value of "isCA" and whose path length field has the
+ * value given by the "pathLen" argument and stores it at "pObject".
+ *
+ * PARAMETERS
+ * "isCA"
+ * Boolean value with the desired value of CA Flag.
+ * "pathLen"
+ * a PKIX_Int32 with the desired value of path length
+ * "pObject"
+ * Address of object pointer's destination. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertBasicConstraints Error if the function fails
+ * in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertBasicConstraints_Create(
+ PKIX_Boolean isCA,
+ PKIX_Int32 pathLen,
+ PKIX_PL_CertBasicConstraints **pObject,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *basic = NULL;
+
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "pkix_pl_CertBasicConstraints_Create");
+ PKIX_NULLCHECK_ONE(pObject);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTBASICCONSTRAINTS_TYPE,
+ sizeof (PKIX_PL_CertBasicConstraints),
+ (PKIX_PL_Object **)&basic,
+ plContext),
+ PKIX_COULDNOTCREATECERTBASICCONSTRAINTSOBJECT);
+
+ basic->isCA = isCA;
+
+ /* pathLen has meaning only for CAs, but it's not worth checking */
+ basic->pathLen = pathLen;
+
+ *pObject = basic;
+
+cleanup:
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertBasicConstraints_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertBasicConstraints_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *certB = NULL;
+
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "pkix_pl_CertBasicConstraints_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext),
+ PKIX_OBJECTNOTCERTBASICCONSTRAINTS);
+
+ certB = (PKIX_PL_CertBasicConstraints*)object;
+
+ certB->isCA = PKIX_FALSE;
+ certB->pathLen = 0;
+
+cleanup:
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertBasicConstraints_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertBasicConstraints_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *certBasicConstraintsString = NULL;
+ PKIX_PL_CertBasicConstraints *certB = NULL;
+ PKIX_Boolean isCA = PKIX_FALSE;
+ PKIX_Int32 pathLen = 0;
+ PKIX_PL_String *outString = NULL;
+ char *fmtString = NULL;
+ PKIX_Boolean pathlenArg = PKIX_FALSE;
+
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "pkix_pl_CertBasicConstraints_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext),
+ PKIX_FIRSTARGUMENTNOTCERTBASICCONSTRAINTSOBJECT);
+
+ certB = (PKIX_PL_CertBasicConstraints *)object;
+
+ /*
+ * if CA == TRUE
+ * if pathLen == CERT_UNLIMITED_PATH_CONSTRAINT
+ * print "CA(-1)"
+ * else print "CA(nnn)"
+ * if CA == FALSE, print "~CA"
+ */
+
+ isCA = certB->isCA;
+
+ if (isCA) {
+ pathLen = certB->pathLen;
+
+ if (pathLen == CERT_UNLIMITED_PATH_CONSTRAINT) {
+ /* print "CA(-1)" */
+ fmtString = "CA(-1)";
+ pathlenArg = PKIX_FALSE;
+ } else {
+ /* print "CA(pathLen)" */
+ fmtString = "CA(%d)";
+ pathlenArg = PKIX_TRUE;
+ }
+ } else {
+ /* print "~CA" */
+ fmtString = "~CA";
+ pathlenArg = PKIX_FALSE;
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ fmtString,
+ 0,
+ &certBasicConstraintsString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ if (pathlenArg) {
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString,
+ plContext,
+ certBasicConstraintsString,
+ pathLen),
+ PKIX_SPRINTFFAILED);
+ } else {
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString,
+ plContext,
+ certBasicConstraintsString),
+ PKIX_SPRINTFFAILED);
+ }
+
+ *pString = outString;
+
+cleanup:
+
+ PKIX_DECREF(certBasicConstraintsString);
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertBasicConstraints_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertBasicConstraints_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *certB = NULL;
+ PKIX_Boolean isCA = PKIX_FALSE;
+ PKIX_Int32 pathLen = 0;
+ PKIX_Int32 hashInput = 0;
+ PKIX_UInt32 cbcHash = 0;
+
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "pkix_pl_CertBasicConstraints_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext),
+ PKIX_OBJECTNOTCERTBASICCONSTRAINTS);
+
+ certB = (PKIX_PL_CertBasicConstraints *)object;
+
+ /*
+ * if CA == TRUE
+ * hash(pathLen + 1 - PKIX_UNLIMITED_PATH_CONSTRAINT)
+ * if CA == FALSE, hash(0)
+ */
+
+ isCA = certB->isCA;
+
+ if (isCA) {
+ pathLen = certB->pathLen;
+
+ hashInput = pathLen + 1 - PKIX_UNLIMITED_PATH_CONSTRAINT;
+ }
+
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)&hashInput,
+ sizeof (hashInput),
+ &cbcHash,
+ plContext),
+ PKIX_HASHFAILED);
+
+ *pHashcode = cbcHash;
+
+cleanup:
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_CertBasicConstraints_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertBasicConstraints_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *firstCBC = NULL;
+ PKIX_PL_CertBasicConstraints *secondCBC = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean firstIsCA = PKIX_FALSE;
+ PKIX_Boolean secondIsCA = PKIX_FALSE;
+ PKIX_Int32 firstPathLen = 0;
+ PKIX_Int32 secondPathLen = 0;
+
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "pkix_pl_CertBasicConstraints_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CertBasicConstraints */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CERTBASICCONSTRAINTS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCERTBASICCONSTRAINTS);
+
+ /*
+ * Since we know firstObject is a CertBasicConstraints,
+ * if both references are identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a CertBasicConstraints, we
+ * don't throw an error. We simply return FALSE.
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CERTBASICCONSTRAINTS_TYPE) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ firstCBC = (PKIX_PL_CertBasicConstraints *)firstObject;
+ secondCBC = (PKIX_PL_CertBasicConstraints *)secondObject;
+
+ /*
+ * Compare the value of the CAFlag components
+ */
+
+ firstIsCA = firstCBC->isCA;
+
+ /*
+ * Failure here would be an error, not merely a miscompare,
+ * since we know second is a CertBasicConstraints.
+ */
+ secondIsCA = secondCBC->isCA;
+
+ /*
+ * If isCA flags differ, the objects are not equal.
+ */
+ if (secondIsCA != firstIsCA) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ /*
+ * If isCA was FALSE, the objects are equal, because
+ * pathLen is meaningless in that case.
+ */
+ if (!firstIsCA) {
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ firstPathLen = firstCBC->pathLen;
+ secondPathLen = secondCBC->pathLen;
+
+ *pResult = (secondPathLen == firstPathLen);
+
+cleanup:
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertBasicConstraints_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTBASICCONSTRAINTS_TYPE and its related
+ * functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize,
+ * which should only be called once, it is acceptable that
+ * this function is not thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CertBasicConstraints_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "pkix_pl_CertBasicConstraints_RegisterSelf");
+
+ entry.description = "CertBasicConstraints";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_CertBasicConstraints);
+ entry.destructor = pkix_pl_CertBasicConstraints_Destroy;
+ entry.equalsFunction = pkix_pl_CertBasicConstraints_Equals;
+ entry.hashcodeFunction = pkix_pl_CertBasicConstraints_Hashcode;
+ entry.toStringFunction = pkix_pl_CertBasicConstraints_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CERTBASICCONSTRAINTS_TYPE] = entry;
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_BasicConstraints_GetCAFlag
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_BasicConstraints_GetCAFlag(
+ PKIX_PL_CertBasicConstraints *basicConstraints,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "PKIX_PL_BasicConstraintsGetCAFlag");
+ PKIX_NULLCHECK_TWO(basicConstraints, pResult);
+
+ *pResult = basicConstraints->isCA;
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
+
+/*
+ * FUNCTION: PKIX_PL_BasicConstraints_GetPathLenConstraint
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_BasicConstraints_GetPathLenConstraint(
+ PKIX_PL_CertBasicConstraints *basicConstraints,
+ PKIX_Int32 *pPathLenConstraint,
+ void *plContext)
+{
+ PKIX_ENTER(CERTBASICCONSTRAINTS,
+ "PKIX_PL_BasicConstraintsGetPathLenConstraint");
+ PKIX_NULLCHECK_TWO(basicConstraints, pPathLenConstraint);
+
+ *pPathLenConstraint = basicConstraints->pathLen;
+
+ PKIX_RETURN(CERTBASICCONSTRAINTS);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.h
new file mode 100644
index 0000000000..857529c95c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_basicconstraints.h
@@ -0,0 +1,47 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_basicconstraints.h
+ *
+ * BasicConstraints Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_BASICCONSTRAINTS_H
+#define _PKIX_PL_BASICCONSTRAINTS_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This structure reflects the contents of the basic constraints
+ * extension as described in Section 4.2.1.10 of RFC 3280.
+ * The cA flag indicates whether the public key in this certificate
+ * belongs to a certification authority. The pathLen constraint
+ * gives the maximum number of non-self-issued intermediate certificates
+ * that may follow this certificate in a valid certification path.
+ */
+struct PKIX_PL_CertBasicConstraintsStruct {
+ PKIX_Boolean isCA;
+ PKIX_Int32 pathLen;
+};
+
+PKIX_Error *
+pkix_pl_CertBasicConstraints_Create(
+ PKIX_Boolean isCA,
+ PKIX_Int32 pathLen,
+ PKIX_PL_CertBasicConstraints **object,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertBasicConstraints_RegisterSelf(
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_BASICCONSTRAINTS_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c
new file mode 100644
index 0000000000..9dddd2e40f
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.c
@@ -0,0 +1,3734 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_cert.c
+ *
+ * Certificate Object Functions
+ *
+ */
+
+#include "pkix_pl_cert.h"
+
+extern PKIX_PL_HashTable *cachedCertSigTable;
+
+/* --Private-Cert-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_Cert_IsExtensionCritical
+ * DESCRIPTION:
+ *
+ * Checks the Cert specified by "cert" to determine whether the extension
+ * whose tag is the UInt32 value given by "tag" is marked as a critical
+ * extension, and stores the result in "pCritical".
+ *
+ * Tags are the index into the table "oids" of SECOidData defined in the
+ * file secoid.c. Constants, such as SEC_OID_X509_CERTIFICATE_POLICIES, are
+ * are defined in secoidt.h for most of the table entries.
+ *
+ * If the specified tag is invalid (not in the list of tags) or if the
+ * extension is not found in the certificate, PKIX_FALSE is stored.
+ *
+ * PARAMETERS
+ * "cert"
+ * Address of Cert whose extensions are to be examined. Must be non-NULL.
+ * "tag"
+ * The UInt32 value of the tag for the extension whose criticality is
+ * to be determined
+ * "pCritical"
+ * Address where the Boolean value will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Cert_IsExtensionCritical(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 tag,
+ PKIX_Boolean *pCritical,
+ void *plContext)
+{
+ PKIX_Boolean criticality = PKIX_FALSE;
+ CERTCertExtension **extensions = NULL;
+ SECStatus rv;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_IsExtensionCritical");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCritical);
+
+ extensions = cert->nssCert->extensions;
+ PKIX_NULLCHECK_ONE(extensions);
+
+ PKIX_CERT_DEBUG("\t\tCalling CERT_GetExtenCriticality).\n");
+ rv = CERT_GetExtenCriticality(extensions, tag, &criticality);
+ if (SECSuccess == rv) {
+ *pCritical = criticality;
+ } else {
+ *pCritical = PKIX_FALSE;
+ }
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_DecodePolicyInfo
+ * DESCRIPTION:
+ *
+ * Decodes the contents of the CertificatePolicy extension in the
+ * CERTCertificate pointed to by "nssCert", to create a List of
+ * CertPolicyInfos, which is stored at the address "pCertPolicyInfos".
+ * A CERTCertificate contains the DER representation of the Cert.
+ * If this certificate does not have a CertificatePolicy extension,
+ * NULL will be stored. If a List is returned, it will be immutable.
+ *
+ * PARAMETERS
+ * "nssCert"
+ * Address of the Cert data whose extension is to be examined. Must be
+ * non-NULL.
+ * "pCertPolicyInfos"
+ * Address where the List of CertPolicyInfos will be stored. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Cert_DecodePolicyInfo(
+ CERTCertificate *nssCert,
+ PKIX_List **pCertPolicyInfos,
+ void *plContext)
+{
+
+ SECStatus rv;
+ SECItem encodedCertPolicyInfo;
+
+ /* Allocated in the arena; freed in CERT_Destroy... */
+ CERTCertificatePolicies *certPol = NULL;
+ CERTPolicyInfo **policyInfos = NULL;
+
+ /* Holder for the return value */
+ PKIX_List *infos = NULL;
+
+ PKIX_PL_OID *pkixOID = NULL;
+ PKIX_List *qualifiers = NULL;
+ PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL;
+ PKIX_PL_CertPolicyQualifier *certPolicyQualifier = NULL;
+ PKIX_PL_ByteArray *qualifierArray = NULL;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyInfo");
+ PKIX_NULLCHECK_TWO(nssCert, pCertPolicyInfos);
+
+ /* get PolicyInfo as a SECItem */
+ PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n");
+ rv = CERT_FindCertExtension
+ (nssCert,
+ SEC_OID_X509_CERTIFICATE_POLICIES,
+ &encodedCertPolicyInfo);
+ if (SECSuccess != rv) {
+ *pCertPolicyInfos = NULL;
+ goto cleanup;
+ }
+
+ /* translate PolicyInfo to CERTCertificatePolicies */
+ PKIX_CERT_DEBUG("\t\tCERT_DecodeCertificatePoliciesExtension).\n");
+ certPol = CERT_DecodeCertificatePoliciesExtension
+ (&encodedCertPolicyInfo);
+
+ PORT_Free(encodedCertPolicyInfo.data);
+
+ if (NULL == certPol) {
+ PKIX_ERROR(PKIX_CERTDECODECERTIFICATEPOLICIESEXTENSIONFAILED);
+ }
+
+ /*
+ * Check whether there are any policyInfos, so we can
+ * avoid creating an unnecessary List
+ */
+ policyInfos = certPol->policyInfos;
+ if (!policyInfos) {
+ *pCertPolicyInfos = NULL;
+ goto cleanup;
+ }
+
+ /* create a List of CertPolicyInfo Objects */
+ PKIX_CHECK(PKIX_List_Create(&infos, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ /*
+ * Traverse the CERTCertificatePolicies structure,
+ * building each PKIX_PL_CertPolicyInfo object in turn
+ */
+ while (*policyInfos != NULL) {
+ CERTPolicyInfo *policyInfo = *policyInfos;
+ CERTPolicyQualifier **policyQualifiers =
+ policyInfo->policyQualifiers;
+ if (policyQualifiers) {
+ /* create a PKIX_List of PKIX_PL_CertPolicyQualifiers */
+ PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ while (*policyQualifiers != NULL) {
+ CERTPolicyQualifier *policyQualifier =
+ *policyQualifiers;
+
+ /* create the qualifier's OID object */
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (&policyQualifier->qualifierID,
+ &pkixOID, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* create qualifier's ByteArray object */
+
+ PKIX_CHECK(PKIX_PL_ByteArray_Create
+ (policyQualifier->qualifierValue.data,
+ policyQualifier->qualifierValue.len,
+ &qualifierArray,
+ plContext),
+ PKIX_BYTEARRAYCREATEFAILED);
+
+ /* create a CertPolicyQualifier object */
+
+ PKIX_CHECK(pkix_pl_CertPolicyQualifier_Create
+ (pkixOID,
+ qualifierArray,
+ &certPolicyQualifier,
+ plContext),
+ PKIX_CERTPOLICYQUALIFIERCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (qualifiers,
+ (PKIX_PL_Object *)certPolicyQualifier,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(pkixOID);
+ PKIX_DECREF(qualifierArray);
+ PKIX_DECREF(certPolicyQualifier);
+
+ policyQualifiers++;
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (qualifiers, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+ }
+
+
+ /*
+ * Create an OID object pkixOID from policyInfo->policyID.
+ * (The CERTPolicyInfo structure has an oid field, but it
+ * is of type SECOidTag. This function wants a SECItem.)
+ */
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (&policyInfo->policyID, &pkixOID, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* Create a CertPolicyInfo object */
+ PKIX_CHECK(pkix_pl_CertPolicyInfo_Create
+ (pkixOID, qualifiers, &certPolicyInfo, plContext),
+ PKIX_CERTPOLICYINFOCREATEFAILED);
+
+ /* Append the new CertPolicyInfo object to the list */
+ PKIX_CHECK(PKIX_List_AppendItem
+ (infos, (PKIX_PL_Object *)certPolicyInfo, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(pkixOID);
+ PKIX_DECREF(qualifiers);
+ PKIX_DECREF(certPolicyInfo);
+
+ policyInfos++;
+ }
+
+ /*
+ * If there were no policies, we went straight to
+ * cleanup, so we don't have to NULLCHECK infos.
+ */
+ PKIX_CHECK(PKIX_List_SetImmutable(infos, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pCertPolicyInfos = infos;
+ infos = NULL;
+
+cleanup:
+ if (certPol) {
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_DestroyCertificatePoliciesExtension).\n");
+ CERT_DestroyCertificatePoliciesExtension(certPol);
+ }
+
+ PKIX_DECREF(infos);
+ PKIX_DECREF(pkixOID);
+ PKIX_DECREF(qualifiers);
+ PKIX_DECREF(certPolicyInfo);
+ PKIX_DECREF(certPolicyQualifier);
+ PKIX_DECREF(qualifierArray);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_DecodePolicyMapping
+ * DESCRIPTION:
+ *
+ * Decodes the contents of the PolicyMapping extension of the CERTCertificate
+ * pointed to by "nssCert", storing the resulting List of CertPolicyMaps at
+ * the address pointed to by "pCertPolicyMaps". If this certificate does not
+ * have a PolicyMapping extension, NULL will be stored. If a List is returned,
+ * it will be immutable.
+ *
+ * PARAMETERS
+ * "nssCert"
+ * Address of the Cert data whose extension is to be examined. Must be
+ * non-NULL.
+ * "pCertPolicyMaps"
+ * Address where the List of CertPolicyMaps will be stored. Must be
+ * non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Cert_DecodePolicyMapping(
+ CERTCertificate *nssCert,
+ PKIX_List **pCertPolicyMaps,
+ void *plContext)
+{
+ SECStatus rv;
+ SECItem encodedCertPolicyMaps;
+
+ /* Allocated in the arena; freed in CERT_Destroy... */
+ CERTCertificatePolicyMappings *certPolMaps = NULL;
+ CERTPolicyMap **policyMaps = NULL;
+
+ /* Holder for the return value */
+ PKIX_List *maps = NULL;
+
+ PKIX_PL_OID *issuerDomainOID = NULL;
+ PKIX_PL_OID *subjectDomainOID = NULL;
+ PKIX_PL_CertPolicyMap *certPolicyMap = NULL;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyMapping");
+ PKIX_NULLCHECK_TWO(nssCert, pCertPolicyMaps);
+
+ /* get PolicyMappings as a SECItem */
+ PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n");
+ rv = CERT_FindCertExtension
+ (nssCert, SEC_OID_X509_POLICY_MAPPINGS, &encodedCertPolicyMaps);
+ if (SECSuccess != rv) {
+ *pCertPolicyMaps = NULL;
+ goto cleanup;
+ }
+
+ /* translate PolicyMaps to CERTCertificatePolicyMappings */
+ certPolMaps = CERT_DecodePolicyMappingsExtension
+ (&encodedCertPolicyMaps);
+
+ PORT_Free(encodedCertPolicyMaps.data);
+
+ if (!certPolMaps) {
+ PKIX_ERROR(PKIX_CERTDECODEPOLICYMAPPINGSEXTENSIONFAILED);
+ }
+
+ PKIX_NULLCHECK_ONE(certPolMaps->policyMaps);
+
+ policyMaps = certPolMaps->policyMaps;
+
+ /* create a List of CertPolicyMap Objects */
+ PKIX_CHECK(PKIX_List_Create(&maps, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ /*
+ * Traverse the CERTCertificatePolicyMappings structure,
+ * building each CertPolicyMap object in turn
+ */
+ do {
+ CERTPolicyMap *policyMap = *policyMaps;
+
+ /* create the OID for the issuer Domain Policy */
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (&policyMap->issuerDomainPolicy,
+ &issuerDomainOID, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* create the OID for the subject Domain Policy */
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (&policyMap->subjectDomainPolicy,
+ &subjectDomainOID, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* create the CertPolicyMap */
+
+ PKIX_CHECK(pkix_pl_CertPolicyMap_Create
+ (issuerDomainOID,
+ subjectDomainOID,
+ &certPolicyMap,
+ plContext),
+ PKIX_CERTPOLICYMAPCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (maps, (PKIX_PL_Object *)certPolicyMap, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(issuerDomainOID);
+ PKIX_DECREF(subjectDomainOID);
+ PKIX_DECREF(certPolicyMap);
+
+ policyMaps++;
+ } while (*policyMaps != NULL);
+
+ PKIX_CHECK(PKIX_List_SetImmutable(maps, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ *pCertPolicyMaps = maps;
+ maps = NULL;
+
+cleanup:
+ if (certPolMaps) {
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_DestroyPolicyMappingsExtension).\n");
+ CERT_DestroyPolicyMappingsExtension(certPolMaps);
+ }
+
+ PKIX_DECREF(maps);
+ PKIX_DECREF(issuerDomainOID);
+ PKIX_DECREF(subjectDomainOID);
+ PKIX_DECREF(certPolicyMap);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_DecodePolicyConstraints
+ * DESCRIPTION:
+ *
+ * Decodes the contents of the PolicyConstraints extension in the
+ * CERTCertificate pointed to by "nssCert", to obtain SkipCerts values
+ * which are stored at the addresses "pExplicitPolicySkipCerts" and
+ * "pInhibitMappingSkipCerts", respectively. If this certificate does
+ * not have an PolicyConstraints extension, or if either of the optional
+ * components is not supplied, this function stores a value of -1 for any
+ * missing component.
+ *
+ * PARAMETERS
+ * "nssCert"
+ * Address of the Cert data whose extension is to be examined. Must be
+ * non-NULL.
+ * "pExplicitPolicySkipCerts"
+ * Address where the SkipCert value for the requireExplicitPolicy
+ * component will be stored. Must be non-NULL.
+ * "pInhibitMappingSkipCerts"
+ * Address where the SkipCert value for the inhibitPolicyMapping
+ * component will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Cert_DecodePolicyConstraints(
+ CERTCertificate *nssCert,
+ PKIX_Int32 *pExplicitPolicySkipCerts,
+ PKIX_Int32 *pInhibitMappingSkipCerts,
+ void *plContext)
+{
+ CERTCertificatePolicyConstraints policyConstraints;
+ SECStatus rv;
+ SECItem encodedCertPolicyConstraints;
+ PKIX_Int32 explicitPolicySkipCerts = -1;
+ PKIX_Int32 inhibitMappingSkipCerts = -1;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyConstraints");
+ PKIX_NULLCHECK_THREE
+ (nssCert, pExplicitPolicySkipCerts, pInhibitMappingSkipCerts);
+
+ /* get the two skipCert values as SECItems */
+ PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n");
+ rv = CERT_FindCertExtension
+ (nssCert,
+ SEC_OID_X509_POLICY_CONSTRAINTS,
+ &encodedCertPolicyConstraints);
+
+ if (rv == SECSuccess) {
+
+ policyConstraints.explicitPolicySkipCerts.data =
+ (unsigned char *)&explicitPolicySkipCerts;
+ policyConstraints.inhibitMappingSkipCerts.data =
+ (unsigned char *)&inhibitMappingSkipCerts;
+
+ /* translate DER to CERTCertificatePolicyConstraints */
+ rv = CERT_DecodePolicyConstraintsExtension
+ (&policyConstraints, &encodedCertPolicyConstraints);
+
+ PORT_Free(encodedCertPolicyConstraints.data);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR
+ (PKIX_CERTDECODEPOLICYCONSTRAINTSEXTENSIONFAILED);
+ }
+ }
+
+ *pExplicitPolicySkipCerts = explicitPolicySkipCerts;
+ *pInhibitMappingSkipCerts = inhibitMappingSkipCerts;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_DecodeInhibitAnyPolicy
+ * DESCRIPTION:
+ *
+ * Decodes the contents of the InhibitAnyPolicy extension in the
+ * CERTCertificate pointed to by "nssCert", to obtain a SkipCerts value,
+ * which is stored at the address "pSkipCerts". If this certificate does
+ * not have an InhibitAnyPolicy extension, -1 will be stored.
+ *
+ * PARAMETERS
+ * "nssCert"
+ * Address of the Cert data whose InhibitAnyPolicy extension is to be
+ * processed. Must be non-NULL.
+ * "pSkipCerts"
+ * Address where the SkipCert value from the InhibitAnyPolicy extension
+ * will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Cert_DecodeInhibitAnyPolicy(
+ CERTCertificate *nssCert,
+ PKIX_Int32 *pSkipCerts,
+ void *plContext)
+{
+ CERTCertificateInhibitAny inhibitAny;
+ SECStatus rv;
+ SECItem encodedCertInhibitAny;
+ PKIX_Int32 skipCerts = -1;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_DecodeInhibitAnyPolicy");
+ PKIX_NULLCHECK_TWO(nssCert, pSkipCerts);
+
+ /* get InhibitAny as a SECItem */
+ PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n");
+ rv = CERT_FindCertExtension
+ (nssCert, SEC_OID_X509_INHIBIT_ANY_POLICY, &encodedCertInhibitAny);
+
+ if (rv == SECSuccess) {
+ inhibitAny.inhibitAnySkipCerts.data =
+ (unsigned char *)&skipCerts;
+
+ /* translate DER to CERTCertificateInhibitAny */
+ rv = CERT_DecodeInhibitAnyExtension
+ (&inhibitAny, &encodedCertInhibitAny);
+
+ PORT_Free(encodedCertInhibitAny.data);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_CERTDECODEINHIBITANYEXTENSIONFAILED);
+ }
+ }
+
+ *pSkipCerts = skipCerts;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_GetNssSubjectAltNames
+ * DESCRIPTION:
+ *
+ * Retrieves the Subject Alternative Names of the certificate specified by
+ * "cert" and stores it at "pNssSubjAltNames". If the Subject Alternative
+ * Name extension is not present, NULL is returned at "pNssSubjAltNames".
+ * If the Subject Alternative Names has not been previously decoded, it is
+ * decoded here with lock on the "cert" unless the flag "hasLock" indicates
+ * the lock had been obtained at a higher call level.
+ *
+ * PARAMETERS
+ * "cert"
+ * Address of the certificate whose Subject Alternative Names extensions
+ * is retrieved. Must be non-NULL.
+ * "hasLock"
+ * Boolean indicates caller has acquired a lock.
+ * Must be non-NULL.
+ * "pNssSubjAltNames"
+ * Address where the returned Subject Alternative Names will be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Cert_GetNssSubjectAltNames(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean hasLock,
+ CERTGeneralName **pNssSubjAltNames,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ CERTGeneralName *nssOriginalAltName = NULL;
+ PLArenaPool *arena = NULL;
+ SECItem altNameExtension = {siBuffer, NULL, 0};
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_GetNssSubjectAltNames");
+ PKIX_NULLCHECK_THREE(cert, pNssSubjAltNames, cert->nssCert);
+
+ nssCert = cert->nssCert;
+
+ if ((cert->nssSubjAltNames == NULL) && (!cert->subjAltNamesAbsent)){
+
+ if (!hasLock) {
+ PKIX_OBJECT_LOCK(cert);
+ }
+
+ if ((cert->nssSubjAltNames == NULL) &&
+ (!cert->subjAltNamesAbsent)){
+
+ PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension,
+ (nssCert,
+ SEC_OID_X509_SUBJECT_ALT_NAME,
+ &altNameExtension));
+
+ if (rv != SECSuccess) {
+ *pNssSubjAltNames = NULL;
+ cert->subjAltNamesAbsent = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ if (cert->arenaNameConstraints == NULL) {
+ PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena,
+ (DER_DEFAULT_CHUNKSIZE));
+
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ cert->arenaNameConstraints = arena;
+ }
+
+ PKIX_PL_NSSCALLRV
+ (CERT,
+ nssOriginalAltName,
+ (CERTGeneralName *) CERT_DecodeAltNameExtension,
+ (cert->arenaNameConstraints, &altNameExtension));
+
+ PKIX_PL_NSSCALL(CERT, PORT_Free, (altNameExtension.data));
+
+ if (nssOriginalAltName == NULL) {
+ PKIX_ERROR(PKIX_CERTDECODEALTNAMEEXTENSIONFAILED);
+ }
+ cert->nssSubjAltNames = nssOriginalAltName;
+
+ }
+
+ if (!hasLock) {
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+ }
+
+ *pNssSubjAltNames = cert->nssSubjAltNames;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_CheckExtendKeyUsage
+ * DESCRIPTION:
+ *
+ * For each of the ON bit in "requiredExtendedKeyUsages" that represents its
+ * SECCertUsageEnum type, this function checks "cert"'s certType (extended
+ * key usage) and key usage with what is required for SECCertUsageEnum type.
+ *
+ * PARAMETERS
+ * "cert"
+ * Address of the certificate whose Extended Key Usage extensions
+ * is retrieved. Must be non-NULL.
+ * "requiredExtendedKeyUsages"
+ * An unsigned integer, its bit location is ON based on the required key
+ * usage value representing in SECCertUsageEnum.
+ * "pPass"
+ * Address where the return value, indicating key usage check passed, is
+ * stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Cert_CheckExtendedKeyUsage(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 requiredExtendedKeyUsages,
+ PKIX_Boolean *pPass,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
+ PKIX_UInt32 certType = 0;
+ PKIX_UInt32 requiredKeyUsage = 0;
+ PKIX_UInt32 requiredCertType = 0;
+ PKIX_UInt32 requiredExtendedKeyUsage = 0;
+ PKIX_UInt32 i;
+ PKIX_Boolean isCA = PKIX_FALSE;
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_CheckExtendKeyUsage");
+ PKIX_NULLCHECK_THREE(cert, pPass, cert->nssCert);
+
+ *pPass = PKIX_FALSE;
+
+ PKIX_CERT_DEBUG("\t\tCalling cert_GetCertType).\n");
+ cert_GetCertType(cert->nssCert);
+ certType = cert->nssCert->nsCertType;
+
+ PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
+ (cert,
+ &basicConstraints,
+ plContext),
+ PKIX_CERTGETBASICCONSTRAINTFAILED);
+
+ if (basicConstraints != NULL) {
+ PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag
+ (basicConstraints, &isCA, plContext),
+ PKIX_BASICCONSTRAINTSGETCAFLAGFAILED);
+ }
+
+ i = 0;
+ while (requiredExtendedKeyUsages != 0) {
+
+ /* Find the bit location of the right-most non-zero bit */
+ while (requiredExtendedKeyUsages != 0) {
+ if (((1 << i) & requiredExtendedKeyUsages) != 0) {
+ requiredExtendedKeyUsage = 1 << i;
+ break;
+ }
+ i++;
+ }
+ requiredExtendedKeyUsages ^= requiredExtendedKeyUsage;
+
+ requiredExtendedKeyUsage = i;
+
+ PKIX_PL_NSSCALLRV(CERT, rv, CERT_KeyUsageAndTypeForCertUsage,
+ (requiredExtendedKeyUsage,
+ isCA,
+ &requiredKeyUsage,
+ &requiredCertType));
+
+ if (!(certType & requiredCertType)) {
+ goto cleanup;
+ }
+
+ PKIX_PL_NSSCALLRV(CERT, rv, CERT_CheckKeyUsage,
+ (cert->nssCert, requiredKeyUsage));
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+ i++;
+
+ }
+
+ *pPass = PKIX_TRUE;
+
+cleanup:
+ PKIX_DECREF(basicConstraints);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the Cert pointed
+ * to by "cert" and stores it at "pString", where the value of
+ * "partialString" determines whether a full or partial representation of
+ * the Cert is stored.
+ *
+ * PARAMETERS
+ * "cert"
+ * Address of Cert whose string representation is desired.
+ * Must be non-NULL.
+ * "partialString"
+ * Boolean indicating whether a partial Cert representation is desired.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Cert_ToString_Helper(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean partialString,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *certString = NULL;
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_UInt32 certVersion;
+ PKIX_PL_BigInt *certSN = NULL;
+ PKIX_PL_String *certSNString = NULL;
+ PKIX_PL_X500Name *certIssuer = NULL;
+ PKIX_PL_String *certIssuerString = NULL;
+ PKIX_PL_X500Name *certSubject = NULL;
+ PKIX_PL_String *certSubjectString = NULL;
+ PKIX_PL_String *notBeforeString = NULL;
+ PKIX_PL_String *notAfterString = NULL;
+ PKIX_List *subjAltNames = NULL;
+ PKIX_PL_String *subjAltNamesString = NULL;
+ PKIX_PL_ByteArray *authKeyId = NULL;
+ PKIX_PL_String *authKeyIdString = NULL;
+ PKIX_PL_ByteArray *subjKeyId = NULL;
+ PKIX_PL_String *subjKeyIdString = NULL;
+ PKIX_PL_PublicKey *nssPubKey = NULL;
+ PKIX_PL_String *nssPubKeyString = NULL;
+ PKIX_List *critExtOIDs = NULL;
+ PKIX_PL_String *critExtOIDsString = NULL;
+ PKIX_List *extKeyUsages = NULL;
+ PKIX_PL_String *extKeyUsagesString = NULL;
+ PKIX_PL_CertBasicConstraints *basicConstraint = NULL;
+ PKIX_PL_String *certBasicConstraintsString = NULL;
+ PKIX_List *policyInfo = NULL;
+ PKIX_PL_String *certPolicyInfoString = NULL;
+ PKIX_List *certPolicyMappings = NULL;
+ PKIX_PL_String *certPolicyMappingsString = NULL;
+ PKIX_Int32 certExplicitPolicy = 0;
+ PKIX_Int32 certInhibitMapping = 0;
+ PKIX_Int32 certInhibitAnyPolicy = 0;
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ PKIX_PL_String *nameConstraintsString = NULL;
+ PKIX_List *authorityInfoAccess = NULL;
+ PKIX_PL_String *authorityInfoAccessString = NULL;
+ PKIX_List *subjectInfoAccess = NULL;
+ PKIX_PL_String *subjectInfoAccessString = NULL;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_ToString_Helper");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pString);
+
+ /*
+ * XXX Add to this format as certificate components are developed.
+ */
+
+ if (partialString){
+ asciiFormat =
+ "\t[Issuer: %s\n"
+ "\t Subject: %s]";
+ } else {
+ asciiFormat =
+ "[\n"
+ "\tVersion: v%d\n"
+ "\tSerialNumber: %s\n"
+ "\tIssuer: %s\n"
+ "\tSubject: %s\n"
+ "\tValidity: [From: %s\n"
+ "\t To: %s]\n"
+ "\tSubjectAltNames: %s\n"
+ "\tAuthorityKeyId: %s\n"
+ "\tSubjectKeyId: %s\n"
+ "\tSubjPubKeyAlgId: %s\n"
+ "\tCritExtOIDs: %s\n"
+ "\tExtKeyUsages: %s\n"
+ "\tBasicConstraint: %s\n"
+ "\tCertPolicyInfo: %s\n"
+ "\tPolicyMappings: %s\n"
+ "\tExplicitPolicy: %d\n"
+ "\tInhibitMapping: %d\n"
+ "\tInhibitAnyPolicy:%d\n"
+ "\tNameConstraints: %s\n"
+ "\tAuthorityInfoAccess: %s\n"
+ "\tSubjectInfoAccess: %s\n"
+ "\tCacheFlag: %d\n"
+ "]\n";
+ }
+
+
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Issuer */
+ PKIX_CHECK(PKIX_PL_Cert_GetIssuer
+ (cert, &certIssuer, plContext),
+ PKIX_CERTGETISSUERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)certIssuer, &certIssuerString, plContext),
+ PKIX_X500NAMETOSTRINGFAILED);
+
+ /* Subject */
+ PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &certSubject, plContext),
+ PKIX_CERTGETSUBJECTFAILED);
+
+ PKIX_TOSTRING(certSubject, &certSubjectString, plContext,
+ PKIX_X500NAMETOSTRINGFAILED);
+
+ if (partialString){
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&certString,
+ plContext,
+ formatString,
+ certIssuerString,
+ certSubjectString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = certString;
+ goto cleanup;
+ }
+
+ /* Version */
+ PKIX_CHECK(PKIX_PL_Cert_GetVersion(cert, &certVersion, plContext),
+ PKIX_CERTGETVERSIONFAILED);
+
+ /* SerialNumber */
+ PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber(cert, &certSN, plContext),
+ PKIX_CERTGETSERIALNUMBERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)certSN, &certSNString, plContext),
+ PKIX_BIGINTTOSTRINGFAILED);
+
+ /* Validity: NotBefore */
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&(cert->nssCert->validity.notBefore),
+ &notBeforeString,
+ plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+
+ /* Validity: NotAfter */
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&(cert->nssCert->validity.notAfter),
+ &notAfterString,
+ plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+
+ /* SubjectAltNames */
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
+ (cert, &subjAltNames, plContext),
+ PKIX_CERTGETSUBJECTALTNAMESFAILED);
+
+ PKIX_TOSTRING(subjAltNames, &subjAltNamesString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* AuthorityKeyIdentifier */
+ PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier
+ (cert, &authKeyId, plContext),
+ PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED);
+
+ PKIX_TOSTRING(authKeyId, &authKeyIdString, plContext,
+ PKIX_BYTEARRAYTOSTRINGFAILED);
+
+ /* SubjectKeyIdentifier */
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier
+ (cert, &subjKeyId, plContext),
+ PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED);
+
+ PKIX_TOSTRING(subjKeyId, &subjKeyIdString, plContext,
+ PKIX_BYTEARRAYTOSTRINGFAILED);
+
+ /* SubjectPublicKey */
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
+ (cert, &nssPubKey, plContext),
+ PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)nssPubKey, &nssPubKeyString, plContext),
+ PKIX_PUBLICKEYTOSTRINGFAILED);
+
+ /* CriticalExtensionOIDs */
+ PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs
+ (cert, &critExtOIDs, plContext),
+ PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED);
+
+ PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* ExtendedKeyUsages */
+ PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
+ (cert, &extKeyUsages, plContext),
+ PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
+
+ PKIX_TOSTRING(extKeyUsages, &extKeyUsagesString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* CertBasicConstraints */
+ PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
+ (cert, &basicConstraint, plContext),
+ PKIX_CERTGETBASICCONSTRAINTSFAILED);
+
+ PKIX_TOSTRING(basicConstraint, &certBasicConstraintsString, plContext,
+ PKIX_CERTBASICCONSTRAINTSTOSTRINGFAILED);
+
+ /* CertPolicyInfo */
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation
+ (cert, &policyInfo, plContext),
+ PKIX_CERTGETPOLICYINFORMATIONFAILED);
+
+ PKIX_TOSTRING(policyInfo, &certPolicyInfoString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* Advanced Policies */
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings
+ (cert, &certPolicyMappings, plContext),
+ PKIX_CERTGETPOLICYMAPPINGSFAILED);
+
+ PKIX_TOSTRING(certPolicyMappings, &certPolicyMappingsString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy
+ (cert, &certExplicitPolicy, plContext),
+ PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited
+ (cert, &certInhibitMapping, plContext),
+ PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED);
+
+ PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy
+ (cert, &certInhibitAnyPolicy, plContext),
+ PKIX_CERTGETINHIBITANYPOLICYFAILED);
+
+ /* Name Constraints */
+ PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
+ (cert, &nameConstraints, plContext),
+ PKIX_CERTGETNAMECONSTRAINTSFAILED);
+
+ PKIX_TOSTRING(nameConstraints, &nameConstraintsString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* Authority Information Access */
+ PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess
+ (cert, &authorityInfoAccess, plContext),
+ PKIX_CERTGETAUTHORITYINFOACCESSFAILED);
+
+ PKIX_TOSTRING(authorityInfoAccess, &authorityInfoAccessString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* Subject Information Access */
+ PKIX_CHECK(PKIX_PL_Cert_GetSubjectInfoAccess
+ (cert, &subjectInfoAccess, plContext),
+ PKIX_CERTGETSUBJECTINFOACCESSFAILED);
+
+ PKIX_TOSTRING(subjectInfoAccess, &subjectInfoAccessString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&certString,
+ plContext,
+ formatString,
+ certVersion + 1,
+ certSNString,
+ certIssuerString,
+ certSubjectString,
+ notBeforeString,
+ notAfterString,
+ subjAltNamesString,
+ authKeyIdString,
+ subjKeyIdString,
+ nssPubKeyString,
+ critExtOIDsString,
+ extKeyUsagesString,
+ certBasicConstraintsString,
+ certPolicyInfoString,
+ certPolicyMappingsString,
+ certExplicitPolicy, /* an Int32, not a String */
+ certInhibitMapping, /* an Int32, not a String */
+ certInhibitAnyPolicy, /* an Int32, not a String */
+ nameConstraintsString,
+ authorityInfoAccessString,
+ subjectInfoAccessString,
+ cert->cacheFlag), /* a boolean */
+ PKIX_SPRINTFFAILED);
+
+ *pString = certString;
+
+cleanup:
+ PKIX_DECREF(certSN);
+ PKIX_DECREF(certSNString);
+ PKIX_DECREF(certIssuer);
+ PKIX_DECREF(certIssuerString);
+ PKIX_DECREF(certSubject);
+ PKIX_DECREF(certSubjectString);
+ PKIX_DECREF(notBeforeString);
+ PKIX_DECREF(notAfterString);
+ PKIX_DECREF(subjAltNames);
+ PKIX_DECREF(subjAltNamesString);
+ PKIX_DECREF(authKeyId);
+ PKIX_DECREF(authKeyIdString);
+ PKIX_DECREF(subjKeyId);
+ PKIX_DECREF(subjKeyIdString);
+ PKIX_DECREF(nssPubKey);
+ PKIX_DECREF(nssPubKeyString);
+ PKIX_DECREF(critExtOIDs);
+ PKIX_DECREF(critExtOIDsString);
+ PKIX_DECREF(extKeyUsages);
+ PKIX_DECREF(extKeyUsagesString);
+ PKIX_DECREF(basicConstraint);
+ PKIX_DECREF(certBasicConstraintsString);
+ PKIX_DECREF(policyInfo);
+ PKIX_DECREF(certPolicyInfoString);
+ PKIX_DECREF(certPolicyMappings);
+ PKIX_DECREF(certPolicyMappingsString);
+ PKIX_DECREF(nameConstraints);
+ PKIX_DECREF(nameConstraintsString);
+ PKIX_DECREF(authorityInfoAccess);
+ PKIX_DECREF(authorityInfoAccessString);
+ PKIX_DECREF(subjectInfoAccess);
+ PKIX_DECREF(subjectInfoAccessString);
+ PKIX_DECREF(formatString);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Cert_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Cert *cert = NULL;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
+ PKIX_OBJECTNOTCERT);
+
+ cert = (PKIX_PL_Cert*)object;
+
+ PKIX_DECREF(cert->subject);
+ PKIX_DECREF(cert->issuer);
+ PKIX_DECREF(cert->subjAltNames);
+ PKIX_DECREF(cert->publicKeyAlgId);
+ PKIX_DECREF(cert->publicKey);
+ PKIX_DECREF(cert->serialNumber);
+ PKIX_DECREF(cert->critExtOids);
+ PKIX_DECREF(cert->authKeyId);
+ PKIX_DECREF(cert->subjKeyId);
+ PKIX_DECREF(cert->extKeyUsages);
+ PKIX_DECREF(cert->certBasicConstraints);
+ PKIX_DECREF(cert->certPolicyInfos);
+ PKIX_DECREF(cert->certPolicyMappings);
+ PKIX_DECREF(cert->nameConstraints);
+ PKIX_DECREF(cert->store);
+ PKIX_DECREF(cert->authorityInfoAccess);
+ PKIX_DECREF(cert->subjectInfoAccess);
+ PKIX_DECREF(cert->crldpList);
+
+ if (cert->arenaNameConstraints){
+ /* This arena was allocated for SubjectAltNames */
+ PKIX_PL_NSSCALL(CERT, PORT_FreeArena,
+ (cert->arenaNameConstraints, PR_FALSE));
+
+ cert->arenaNameConstraints = NULL;
+ cert->nssSubjAltNames = NULL;
+ }
+
+ CERT_DestroyCertificate(cert->nssCert);
+ cert->nssCert = NULL;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Cert_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *certString = NULL;
+ PKIX_PL_Cert *pkixCert = NULL;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
+ PKIX_OBJECTNOTCERT);
+
+ pkixCert = (PKIX_PL_Cert *)object;
+
+ PKIX_CHECK(pkix_pl_Cert_ToString_Helper
+ (pkixCert, PKIX_FALSE, &certString, plContext),
+ PKIX_CERTTOSTRINGHELPERFAILED);
+
+ *pString = certString;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Cert_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_Cert *pkixCert = NULL;
+ CERTCertificate *nssCert = NULL;
+ unsigned char *derBytes = NULL;
+ PKIX_UInt32 derLength;
+ PKIX_UInt32 certHash;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
+ PKIX_OBJECTNOTCERT);
+
+ pkixCert = (PKIX_PL_Cert *)object;
+
+ nssCert = pkixCert->nssCert;
+ derBytes = (nssCert->derCert).data;
+ derLength = (nssCert->derCert).len;
+
+ PKIX_CHECK(pkix_hash(derBytes, derLength, &certHash, plContext),
+ PKIX_HASHFAILED);
+
+ *pHashcode = certHash;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_Cert_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Cert_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ CERTCertificate *firstCert = NULL;
+ CERTCertificate *secondCert = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a Cert */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CERT_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCERT);
+
+ /*
+ * Since we know firstObject is a Cert, if both references are
+ * identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a Cert, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CERT_TYPE) goto cleanup;
+
+ firstCert = ((PKIX_PL_Cert *)firstObject)->nssCert;
+ secondCert = ((PKIX_PL_Cert *)secondObject)->nssCert;
+
+ PKIX_NULLCHECK_TWO(firstCert, secondCert);
+
+ /* CERT_CompareCerts does byte comparison on DER encodings of certs */
+ PKIX_CERT_DEBUG("\t\tCalling CERT_CompareCerts).\n");
+ cmpResult = CERT_CompareCerts(firstCert, secondCert);
+
+ *pResult = cmpResult;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERT_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_Cert_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_RegisterSelf");
+
+ entry.description = "Cert";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_Cert);
+ entry.destructor = pkix_pl_Cert_Destroy;
+ entry.equalsFunction = pkix_pl_Cert_Equals;
+ entry.hashcodeFunction = pkix_pl_Cert_Hashcode;
+ entry.toStringFunction = pkix_pl_Cert_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CERT_TYPE] = entry;
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_CreateWithNSSCert
+ * DESCRIPTION:
+ *
+ * Creates a new certificate using the CERTCertificate pointed to by "nssCert"
+ * and stores it at "pCert". Once created, a Cert is immutable.
+ *
+ * This function is primarily used as a convenience function for the
+ * performance tests that have easy access to a CERTCertificate.
+ *
+ * PARAMETERS:
+ * "nssCert"
+ * Address of CERTCertificate representing the NSS certificate.
+ * Must be non-NULL.
+ * "pCert"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Cert_CreateWithNSSCert(
+ CERTCertificate *nssCert,
+ PKIX_PL_Cert **pCert,
+ void *plContext)
+{
+ PKIX_PL_Cert *cert = NULL;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_CreateWithNSSCert");
+ PKIX_NULLCHECK_TWO(pCert, nssCert);
+
+ /* create a PKIX_PL_Cert object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERT_TYPE,
+ sizeof (PKIX_PL_Cert),
+ (PKIX_PL_Object **)&cert,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* populate the nssCert field */
+ cert->nssCert = nssCert;
+
+ /* initialize remaining fields */
+ /*
+ * Fields ending with Absent are initialized to PKIX_FALSE so that the
+ * first time we need the value we will look for it. If we find it is
+ * actually absent, the flag will at that time be set to PKIX_TRUE to
+ * prevent searching for it later.
+ * Fields ending with Processed are those where a value is defined
+ * for the Absent case, and a value of zero is possible. When the
+ * flag is still true we have to look for the field, set the default
+ * value if necessary, and set the Processed flag to PKIX_TRUE.
+ */
+ cert->subject = NULL;
+ cert->issuer = NULL;
+ cert->subjAltNames = NULL;
+ cert->subjAltNamesAbsent = PKIX_FALSE;
+ cert->publicKeyAlgId = NULL;
+ cert->publicKey = NULL;
+ cert->serialNumber = NULL;
+ cert->critExtOids = NULL;
+ cert->subjKeyId = NULL;
+ cert->subjKeyIdAbsent = PKIX_FALSE;
+ cert->authKeyId = NULL;
+ cert->authKeyIdAbsent = PKIX_FALSE;
+ cert->extKeyUsages = NULL;
+ cert->extKeyUsagesAbsent = PKIX_FALSE;
+ cert->certBasicConstraints = NULL;
+ cert->basicConstraintsAbsent = PKIX_FALSE;
+ cert->certPolicyInfos = NULL;
+ cert->policyInfoAbsent = PKIX_FALSE;
+ cert->policyMappingsAbsent = PKIX_FALSE;
+ cert->certPolicyMappings = NULL;
+ cert->policyConstraintsProcessed = PKIX_FALSE;
+ cert->policyConstraintsExplicitPolicySkipCerts = 0;
+ cert->policyConstraintsInhibitMappingSkipCerts = 0;
+ cert->inhibitAnyPolicyProcessed = PKIX_FALSE;
+ cert->inhibitAnySkipCerts = 0;
+ cert->nameConstraints = NULL;
+ cert->nameConstraintsAbsent = PKIX_FALSE;
+ cert->arenaNameConstraints = NULL;
+ cert->nssSubjAltNames = NULL;
+ cert->cacheFlag = PKIX_FALSE;
+ cert->store = NULL;
+ cert->authorityInfoAccess = NULL;
+ cert->subjectInfoAccess = NULL;
+ cert->isUserTrustAnchor = PKIX_FALSE;
+ cert->crldpList = NULL;
+
+ *pCert = cert;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Cert_CreateToList
+ * DESCRIPTION:
+ *
+ * Creates a new certificate using the DER-encoding pointed to by "derCertItem"
+ * and appends it to the list pointed to by "certList". If Cert creation fails,
+ * the function returns with certList unchanged, but any decoding Error is
+ * discarded.
+ *
+ * PARAMETERS:
+ * "derCertItem"
+ * Address of SECItem containing the DER representation of a certificate.
+ * Must be non-NULL.
+ * "certList"
+ * Address of List to which the Cert will be appended, if successfully
+ * created. May be empty, but must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Cert_CreateToList(
+ SECItem *derCertItem,
+ PKIX_List *certList,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ CERTCertDBHandle *handle;
+
+ PKIX_ENTER(CERT, "pkix_pl_Cert_CreateToList");
+ PKIX_NULLCHECK_TWO(derCertItem, certList);
+
+ handle = CERT_GetDefaultCertDB();
+ nssCert = CERT_NewTempCertificate(handle, derCertItem,
+ /* nickname */ NULL,
+ /* isPerm */ PR_FALSE,
+ /* copyDer */ PR_TRUE);
+ if (!nssCert) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
+ (nssCert, &cert, plContext),
+ PKIX_CERTCREATEWITHNSSCERTFAILED);
+
+ nssCert = NULL;
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (certList, (PKIX_PL_Object *) cert, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+cleanup:
+ if (nssCert) {
+ CERT_DestroyCertificate(nssCert);
+ }
+
+ PKIX_DECREF(cert);
+ PKIX_RETURN(CERT);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_Cert_Create (see comments in pkix_pl_pki.h)
+ * XXX We may want to cache the cert after parsing it, so it can be reused
+ * XXX Are the NSS/NSPR functions thread safe
+ */
+PKIX_Error *
+PKIX_PL_Cert_Create(
+ PKIX_PL_ByteArray *byteArray,
+ PKIX_PL_Cert **pCert,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ SECItem *derCertItem = NULL;
+ void *derBytes = NULL;
+ PKIX_UInt32 derLength;
+ PKIX_PL_Cert *cert = NULL;
+ CERTCertDBHandle *handle;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_Create");
+ PKIX_NULLCHECK_TWO(pCert, byteArray);
+
+ PKIX_CHECK(PKIX_PL_ByteArray_GetPointer
+ (byteArray, &derBytes, plContext),
+ PKIX_BYTEARRAYGETPOINTERFAILED);
+
+ PKIX_CHECK(PKIX_PL_ByteArray_GetLength
+ (byteArray, &derLength, plContext),
+ PKIX_BYTEARRAYGETLENGTHFAILED);
+
+ derCertItem = SECITEM_AllocItem(NULL, NULL, derLength);
+ if (derCertItem == NULL){
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ (void) PORT_Memcpy(derCertItem->data, derBytes, derLength);
+
+ /*
+ * setting copyDER to true forces NSS to make its own copy of the DER,
+ * allowing us to free our copy without worrying about whether NSS
+ * is still using it
+ */
+ handle = CERT_GetDefaultCertDB();
+ nssCert = CERT_NewTempCertificate(handle, derCertItem,
+ /* nickname */ NULL,
+ /* isPerm */ PR_FALSE,
+ /* copyDer */ PR_TRUE);
+ if (!nssCert){
+ PKIX_ERROR(PKIX_CERTDECODEDERCERTIFICATEFAILED);
+ }
+
+ PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
+ (nssCert, &cert, plContext),
+ PKIX_CERTCREATEWITHNSSCERTFAILED);
+
+ *pCert = cert;
+
+cleanup:
+ if (derCertItem){
+ SECITEM_FreeItem(derCertItem, PKIX_TRUE);
+ }
+
+ if (nssCert && PKIX_ERROR_RECEIVED){
+ PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n");
+ CERT_DestroyCertificate(nssCert);
+ nssCert = NULL;
+ }
+
+ PKIX_FREE(derBytes);
+ PKIX_RETURN(CERT);
+}
+
+
+/*
+ * FUNCTION: PKIX_PL_Cert_CreateFromCERTCertificate
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_CreateFromCERTCertificate(
+ const CERTCertificate *nssCert,
+ PKIX_PL_Cert **pCert,
+ void *plContext)
+{
+ void *buf = NULL;
+ PKIX_UInt32 len;
+ PKIX_PL_ByteArray *byteArray = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_CreateWithNssCert");
+ PKIX_NULLCHECK_TWO(pCert, nssCert);
+
+ buf = (void*)nssCert->derCert.data;
+ len = nssCert->derCert.len;
+
+ PKIX_CHECK(
+ PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext),
+ PKIX_BYTEARRAYCREATEFAILED);
+
+ PKIX_CHECK(
+ PKIX_PL_Cert_Create(byteArray, pCert, plContext),
+ PKIX_CERTCREATEWITHNSSCERTFAILED);
+
+#ifdef PKIX_UNDEF
+ /* will be tested and used as a patch for bug 391612 */
+ nssCert = CERT_DupCertificate(nssInCert);
+
+ PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
+ (nssCert, &cert, plContext),
+ PKIX_CERTCREATEWITHNSSCERTFAILED);
+#endif /* PKIX_UNDEF */
+
+cleanup:
+
+#ifdef PKIX_UNDEF
+ if (nssCert && PKIX_ERROR_RECEIVED){
+ PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n");
+ CERT_DestroyCertificate(nssCert);
+ nssCert = NULL;
+ }
+#endif /* PKIX_UNDEF */
+
+ PKIX_DECREF(byteArray);
+ PKIX_RETURN(CERT);
+}
+
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetVersion (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetVersion(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 *pVersion,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ PKIX_UInt32 myVersion = 0; /* v1 */
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetVersion");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pVersion);
+
+ nssCert = cert->nssCert;
+ if (nssCert->version.len != 0) {
+ myVersion = *(nssCert->version.data);
+ }
+
+ if (myVersion > 2){
+ PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1V2ORV3);
+ }
+
+ *pVersion = myVersion;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSerialNumber (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSerialNumber(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_BigInt **pSerialNumber,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ SECItem serialNumItem;
+ PKIX_PL_BigInt *serialNumber = NULL;
+ char *bytes = NULL;
+ PKIX_UInt32 length;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSerialNumber");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSerialNumber);
+
+ if (cert->serialNumber == NULL){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->serialNumber == NULL){
+
+ nssCert = cert->nssCert;
+ serialNumItem = nssCert->serialNumber;
+
+ length = serialNumItem.len;
+ bytes = (char *)serialNumItem.data;
+
+ PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
+ (bytes, length, &serialNumber, plContext),
+ PKIX_BIGINTCREATEWITHBYTESFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->serialNumber = serialNumber;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->serialNumber);
+ *pSerialNumber = cert->serialNumber;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubject (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubject(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_X500Name **pCertSubject,
+ void *plContext)
+{
+ PKIX_PL_X500Name *pkixSubject = NULL;
+ CERTName *subjName = NULL;
+ SECItem *derSubjName = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubject");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertSubject);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->subject == NULL){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->subject == NULL){
+
+ subjName = &cert->nssCert->subject;
+ derSubjName = &cert->nssCert->derSubject;
+
+ /* if there is no subject name */
+ if (derSubjName->data == NULL) {
+
+ pkixSubject = NULL;
+
+ } else {
+ PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName
+ (derSubjName, subjName, &pkixSubject,
+ plContext),
+ PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
+
+ }
+ /* save a cached copy in case it is asked for again */
+ cert->subject = pkixSubject;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->subject);
+ *pCertSubject = cert->subject;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetIssuer (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetIssuer(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_X500Name **pCertIssuer,
+ void *plContext)
+{
+ PKIX_PL_X500Name *pkixIssuer = NULL;
+ SECItem *derIssuerName = NULL;
+ CERTName *issuerName = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetIssuer");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertIssuer);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->issuer == NULL){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->issuer == NULL){
+
+ issuerName = &cert->nssCert->issuer;
+ derIssuerName = &cert->nssCert->derIssuer;
+
+ /* if there is no subject name */
+ PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName
+ (derIssuerName, issuerName,
+ &pkixIssuer, plContext),
+ PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->issuer = pkixIssuer;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->issuer);
+ *pCertIssuer = cert->issuer;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectAltNames(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pSubjectAltNames, /* list of PKIX_PL_GeneralName */
+ void *plContext)
+{
+ PKIX_PL_GeneralName *pkixAltName = NULL;
+ PKIX_List *altNamesList = NULL;
+
+ CERTGeneralName *nssOriginalAltName = NULL;
+ CERTGeneralName *nssTempAltName = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectAltNames");
+ PKIX_NULLCHECK_TWO(cert, pSubjectAltNames);
+
+ /* if we don't have a cached copy from before, we create one */
+ if ((cert->subjAltNames == NULL) && (!cert->subjAltNamesAbsent)){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if ((cert->subjAltNames == NULL) &&
+ (!cert->subjAltNamesAbsent)){
+
+ PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames
+ (cert,
+ PKIX_TRUE,
+ &nssOriginalAltName,
+ plContext),
+ PKIX_CERTGETNSSSUBJECTALTNAMESFAILED);
+
+ if (nssOriginalAltName == NULL) {
+ cert->subjAltNamesAbsent = PKIX_TRUE;
+ pSubjectAltNames = NULL;
+ goto cleanup;
+ }
+
+ nssTempAltName = nssOriginalAltName;
+
+ PKIX_CHECK(PKIX_List_Create(&altNamesList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ do {
+ PKIX_CHECK(pkix_pl_GeneralName_Create
+ (nssTempAltName, &pkixAltName, plContext),
+ PKIX_GENERALNAMECREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (altNamesList,
+ (PKIX_PL_Object *)pkixAltName,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(pkixAltName);
+
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_GetNextGeneralName).\n");
+ nssTempAltName = CERT_GetNextGeneralName
+ (nssTempAltName);
+
+ } while (nssTempAltName != nssOriginalAltName);
+
+ /* save a cached copy in case it is asked for again */
+ cert->subjAltNames = altNamesList;
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (cert->subjAltNames, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->subjAltNames);
+
+ *pSubjectAltNames = cert->subjAltNames;
+
+cleanup:
+ PKIX_DECREF(pkixAltName);
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(altNamesList);
+ }
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetAllSubjectNames(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pAllSubjectNames, /* list of PKIX_PL_GeneralName */
+ void *plContext)
+{
+ CERTGeneralName *nssOriginalSubjectName = NULL;
+ CERTGeneralName *nssTempSubjectName = NULL;
+ PKIX_List *allSubjectNames = NULL;
+ PKIX_PL_GeneralName *pkixSubjectName = NULL;
+ PLArenaPool *arena = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAllSubjectNames");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAllSubjectNames);
+
+
+ if (cert->nssCert->subjectName == NULL){
+ /* if there is no subject DN, just get altnames */
+
+ PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames
+ (cert,
+ PKIX_FALSE, /* hasLock */
+ &nssOriginalSubjectName,
+ plContext),
+ PKIX_CERTGETNSSSUBJECTALTNAMESFAILED);
+
+ } else { /* get subject DN and altnames */
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ /* This NSS call returns both Subject and Subject Alt Names */
+ PKIX_CERT_DEBUG("\t\tCalling CERT_GetCertificateNames\n");
+ nssOriginalSubjectName =
+ CERT_GetCertificateNames(cert->nssCert, arena);
+ }
+
+ if (nssOriginalSubjectName == NULL) {
+ pAllSubjectNames = NULL;
+ goto cleanup;
+ }
+
+ nssTempSubjectName = nssOriginalSubjectName;
+
+ PKIX_CHECK(PKIX_List_Create(&allSubjectNames, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ do {
+ PKIX_CHECK(pkix_pl_GeneralName_Create
+ (nssTempSubjectName, &pkixSubjectName, plContext),
+ PKIX_GENERALNAMECREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (allSubjectNames,
+ (PKIX_PL_Object *)pkixSubjectName,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(pkixSubjectName);
+
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_GetNextGeneralName).\n");
+ nssTempSubjectName = CERT_GetNextGeneralName
+ (nssTempSubjectName);
+ } while (nssTempSubjectName != nssOriginalSubjectName);
+
+ *pAllSubjectNames = allSubjectNames;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(allSubjectNames);
+ }
+
+ if (arena){
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ PKIX_DECREF(pkixSubjectName);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKeyAlgId
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectPublicKeyAlgId(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_OID **pSubjKeyAlgId,
+ void *plContext)
+{
+ PKIX_PL_OID *pubKeyAlgId = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKeyAlgId");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyAlgId);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->publicKeyAlgId == NULL){
+ PKIX_OBJECT_LOCK(cert);
+ if (cert->publicKeyAlgId == NULL){
+ CERTCertificate *nssCert = cert->nssCert;
+ SECAlgorithmID *algorithm;
+ SECItem *algBytes;
+
+ algorithm = &nssCert->subjectPublicKeyInfo.algorithm;
+ algBytes = &algorithm->algorithm;
+ if (!algBytes->data || !algBytes->len) {
+ PKIX_ERROR_FATAL(PKIX_ALGORITHMBYTESLENGTH0);
+ }
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (algBytes, &pubKeyAlgId, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->publicKeyAlgId = pubKeyAlgId;
+ pubKeyAlgId = NULL;
+ }
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->publicKeyAlgId);
+ *pSubjKeyAlgId = cert->publicKeyAlgId;
+
+cleanup:
+ PKIX_DECREF(pubKeyAlgId);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKey (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectPublicKey(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_PublicKey **pPublicKey,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *pkixPubKey = NULL;
+ SECStatus rv;
+
+ CERTSubjectPublicKeyInfo *from = NULL;
+ CERTSubjectPublicKeyInfo *to = NULL;
+ SECItem *fromItem = NULL;
+ SECItem *toItem = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKey");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPublicKey);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->publicKey == NULL){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->publicKey == NULL){
+
+ /* create a PKIX_PL_PublicKey object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_PUBLICKEY_TYPE,
+ sizeof (PKIX_PL_PublicKey),
+ (PKIX_PL_Object **)&pkixPubKey,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* initialize fields */
+ pkixPubKey->nssSPKI = NULL;
+
+ /* populate the SPKI field */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (sizeof (CERTSubjectPublicKeyInfo),
+ (void **)&pkixPubKey->nssSPKI,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ to = pkixPubKey->nssSPKI;
+ from = &cert->nssCert->subjectPublicKeyInfo;
+
+ PKIX_NULLCHECK_TWO(to, from);
+
+ PKIX_CERT_DEBUG
+ ("\t\tCalling SECOID_CopyAlgorithmID).\n");
+ rv = SECOID_CopyAlgorithmID
+ (NULL, &to->algorithm, &from->algorithm);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_SECOIDCOPYALGORITHMIDFAILED);
+ }
+
+ /*
+ * NSS stores the length of subjectPublicKey in bits.
+ * Therefore, we use that length converted to bytes
+ * using ((length+7)>>3) before calling PORT_Memcpy
+ * in order to avoid "read from uninitialized memory"
+ * errors.
+ */
+
+ toItem = &to->subjectPublicKey;
+ fromItem = &from->subjectPublicKey;
+
+ PKIX_NULLCHECK_TWO(toItem, fromItem);
+
+ toItem->type = fromItem->type;
+
+ toItem->data =
+ (unsigned char*) PORT_ZAlloc(fromItem->len);
+ if (!toItem->data){
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ (void) PORT_Memcpy(toItem->data,
+ fromItem->data,
+ (fromItem->len + 7)>>3);
+ toItem->len = fromItem->len;
+
+ /* save a cached copy in case it is asked for again */
+ cert->publicKey = pkixPubKey;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->publicKey);
+ *pPublicKey = cert->publicKey;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED && pkixPubKey){
+ PKIX_DECREF(pkixPubKey);
+ cert->publicKey = NULL;
+ }
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetCriticalExtensionOIDs
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetCriticalExtensionOIDs(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pList, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_List *oidsList = NULL;
+ CERTCertExtension **extensions = NULL;
+ CERTCertificate *nssCert = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCriticalExtensionOIDs");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pList);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->critExtOids == NULL) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->critExtOids == NULL) {
+
+ nssCert = cert->nssCert;
+
+ /*
+ * ASN.1 for Extension
+ *
+ * Extension ::= SEQUENCE {
+ * extnID OBJECT IDENTIFIER,
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING }
+ *
+ */
+
+ extensions = nssCert->extensions;
+
+ PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
+ (extensions, &oidsList, plContext),
+ PKIX_GETCRITICALEXTENSIONOIDSFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->critExtOids = oidsList;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ /* We should return a copy of the List since this list changes */
+ PKIX_DUPLICATE(cert->critExtOids, pList, plContext,
+ PKIX_OBJECTDUPLICATELISTFAILED);
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetAuthorityKeyIdentifier
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetAuthorityKeyIdentifier(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_ByteArray **pAuthKeyId,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *authKeyId = NULL;
+ CERTCertificate *nssCert = NULL;
+ CERTAuthKeyID *authKeyIdExtension = NULL;
+ PLArenaPool *arena = NULL;
+ SECItem retItem;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityKeyIdentifier");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAuthKeyId);
+
+ /* if we don't have a cached copy from before, we create one */
+ if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ nssCert = cert->nssCert;
+
+ authKeyIdExtension =
+ CERT_FindAuthKeyIDExten(arena, nssCert);
+ if (authKeyIdExtension == NULL){
+ cert->authKeyIdAbsent = PKIX_TRUE;
+ *pAuthKeyId = NULL;
+ goto cleanup;
+ }
+
+ retItem = authKeyIdExtension->keyID;
+
+ if (retItem.len == 0){
+ cert->authKeyIdAbsent = PKIX_TRUE;
+ *pAuthKeyId = NULL;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_PL_ByteArray_Create
+ (retItem.data,
+ retItem.len,
+ &authKeyId,
+ plContext),
+ PKIX_BYTEARRAYCREATEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->authKeyId = authKeyId;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->authKeyId);
+ *pAuthKeyId = cert->authKeyId;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ if (arena){
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectKeyIdentifier
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectKeyIdentifier(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_ByteArray **pSubjKeyId,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *subjKeyId = NULL;
+ CERTCertificate *nssCert = NULL;
+ SECItem *retItem = NULL;
+ SECStatus status;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectKeyIdentifier");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyId);
+
+ /* if we don't have a cached copy from before, we create one */
+ if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){
+
+ retItem = SECITEM_AllocItem(NULL, NULL, 0);
+ if (retItem == NULL){
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ nssCert = cert->nssCert;
+
+ status = CERT_FindSubjectKeyIDExtension
+ (nssCert, retItem);
+ if (status != SECSuccess) {
+ cert->subjKeyIdAbsent = PKIX_TRUE;
+ *pSubjKeyId = NULL;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_PL_ByteArray_Create
+ (retItem->data,
+ retItem->len,
+ &subjKeyId,
+ plContext),
+ PKIX_BYTEARRAYCREATEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->subjKeyId = subjKeyId;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->subjKeyId);
+ *pSubjKeyId = cert->subjKeyId;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ if (retItem){
+ SECITEM_FreeItem(retItem, PKIX_TRUE);
+ }
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetExtendedKeyUsage (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetExtendedKeyUsage(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pKeyUsage, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ CERTOidSequence *extKeyUsage = NULL;
+ CERTCertificate *nssCert = NULL;
+ PKIX_PL_OID *pkixOID = NULL;
+ PKIX_List *oidsList = NULL;
+ SECItem **oids = NULL;
+ SECItem encodedExtKeyUsage;
+ SECStatus rv;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetExtendedKeyUsage");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pKeyUsage);
+
+ /* if we don't have a cached copy from before, we create one */
+ if ((cert->extKeyUsages == NULL) && (!cert->extKeyUsagesAbsent)){
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if ((cert->extKeyUsages == NULL) &&
+ (!cert->extKeyUsagesAbsent)){
+
+ nssCert = cert->nssCert;
+
+ rv = CERT_FindCertExtension
+ (nssCert, SEC_OID_X509_EXT_KEY_USAGE,
+ &encodedExtKeyUsage);
+ if (rv != SECSuccess){
+ cert->extKeyUsagesAbsent = PKIX_TRUE;
+ *pKeyUsage = NULL;
+ goto cleanup;
+ }
+
+ extKeyUsage =
+ CERT_DecodeOidSequence(&encodedExtKeyUsage);
+ if (extKeyUsage == NULL){
+ PKIX_ERROR(PKIX_CERTDECODEOIDSEQUENCEFAILED);
+ }
+
+ PORT_Free(encodedExtKeyUsage.data);
+
+ oids = extKeyUsage->oids;
+
+ if (!oids){
+ /* no extended key usage extensions found */
+ cert->extKeyUsagesAbsent = PKIX_TRUE;
+ *pKeyUsage = NULL;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_List_Create(&oidsList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ while (*oids){
+ SECItem *oid = *oids++;
+
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (oid, &pkixOID, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (oidsList,
+ (PKIX_PL_Object *)pkixOID,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(pkixOID);
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (oidsList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->extKeyUsages = oidsList;
+ oidsList = NULL;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->extKeyUsages);
+ *pKeyUsage = cert->extKeyUsages;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+
+ PKIX_DECREF(pkixOID);
+ PKIX_DECREF(oidsList);
+ CERT_DestroyOidSequence(extKeyUsage);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetBasicConstraints
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetBasicConstraints(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_CertBasicConstraints **pBasicConstraints,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ CERTBasicConstraints nssBasicConstraint;
+ SECStatus rv;
+ PKIX_PL_CertBasicConstraints *basic;
+ PKIX_Int32 pathLen = 0;
+ PKIX_Boolean isCA = PKIX_FALSE;
+ enum {
+ realBC, synthBC, absentBC
+ } constraintSource = absentBC;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetBasicConstraints");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pBasicConstraints);
+
+ /* if we don't have a cached copy from before, we create one */
+ if ((cert->certBasicConstraints == NULL) &&
+ (!cert->basicConstraintsAbsent)) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if ((cert->certBasicConstraints == NULL) &&
+ (!cert->basicConstraintsAbsent)) {
+
+ nssCert = cert->nssCert;
+
+ PKIX_CERT_DEBUG(
+ "\t\tCalling Cert_FindBasicConstraintExten\n");
+ rv = CERT_FindBasicConstraintExten
+ (nssCert, &nssBasicConstraint);
+ if (rv == SECSuccess) {
+ constraintSource = realBC;
+ }
+
+ if (constraintSource == absentBC) {
+ /* can we deduce it's a CA and create a
+ synthetic constraint?
+ */
+ CERTCertTrust trust;
+ rv = CERT_GetCertTrust(nssCert, &trust);
+ if (rv == SECSuccess) {
+ int anyWantedFlag = CERTDB_TRUSTED_CA | CERTDB_VALID_CA;
+ if ((trust.sslFlags & anyWantedFlag)
+ || (trust.emailFlags & anyWantedFlag)
+ || (trust.objectSigningFlags & anyWantedFlag)) {
+
+ constraintSource = synthBC;
+ }
+ }
+ }
+
+ if (constraintSource == absentBC) {
+ cert->basicConstraintsAbsent = PKIX_TRUE;
+ *pBasicConstraints = NULL;
+ goto cleanup;
+ }
+ }
+
+ if (constraintSource == synthBC) {
+ isCA = PKIX_TRUE;
+ pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT;
+ } else {
+ isCA = (nssBasicConstraint.isCA)?PKIX_TRUE:PKIX_FALSE;
+
+ /* The pathLen has meaning only for CAs */
+ if (isCA) {
+ if (CERT_UNLIMITED_PATH_CONSTRAINT ==
+ nssBasicConstraint.pathLenConstraint) {
+ pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT;
+ } else {
+ pathLen = nssBasicConstraint.pathLenConstraint;
+ }
+ }
+ }
+
+ PKIX_CHECK(pkix_pl_CertBasicConstraints_Create
+ (isCA, pathLen, &basic, plContext),
+ PKIX_CERTBASICCONSTRAINTSCREATEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ cert->certBasicConstraints = basic;
+ }
+
+ PKIX_INCREF(cert->certBasicConstraints);
+ *pBasicConstraints = cert->certBasicConstraints;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetPolicyInformation
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetPolicyInformation(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pPolicyInfo,
+ void *plContext)
+{
+ PKIX_List *policyList = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyInformation");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyInfo);
+
+ /* if we don't have a cached copy from before, we create one */
+ if ((cert->certPolicyInfos == NULL) &&
+ (!cert->policyInfoAbsent)) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if ((cert->certPolicyInfos == NULL) &&
+ (!cert->policyInfoAbsent)) {
+
+ PKIX_CHECK(pkix_pl_Cert_DecodePolicyInfo
+ (cert->nssCert, &policyList, plContext),
+ PKIX_CERTDECODEPOLICYINFOFAILED);
+
+ if (!policyList) {
+ cert->policyInfoAbsent = PKIX_TRUE;
+ *pPolicyInfo = NULL;
+ goto cleanup;
+ }
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+
+ /* save a cached copy in case it is asked for again */
+ cert->certPolicyInfos = policyList;
+ policyList = NULL;
+ }
+
+ PKIX_INCREF(cert->certPolicyInfos);
+ *pPolicyInfo = cert->certPolicyInfos;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+
+ PKIX_DECREF(policyList);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetPolicyMappings (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetPolicyMappings(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pPolicyMappings, /* list of PKIX_PL_CertPolicyMap */
+ void *plContext)
+{
+ PKIX_List *policyMappings = NULL; /* list of PKIX_PL_CertPolicyMap */
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappings");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyMappings);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (!(cert->certPolicyMappings) && !(cert->policyMappingsAbsent)) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (!(cert->certPolicyMappings) &&
+ !(cert->policyMappingsAbsent)) {
+
+ PKIX_CHECK(pkix_pl_Cert_DecodePolicyMapping
+ (cert->nssCert, &policyMappings, plContext),
+ PKIX_CERTDECODEPOLICYMAPPINGFAILED);
+
+ if (!policyMappings) {
+ cert->policyMappingsAbsent = PKIX_TRUE;
+ *pPolicyMappings = NULL;
+ goto cleanup;
+ }
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+
+ /* save a cached copy in case it is asked for again */
+ cert->certPolicyMappings = policyMappings;
+ policyMappings = NULL;
+ }
+
+ PKIX_INCREF(cert->certPolicyMappings);
+ *pPolicyMappings = cert->certPolicyMappings;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+
+ PKIX_DECREF(policyMappings);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetRequireExplicitPolicy
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetRequireExplicitPolicy(
+ PKIX_PL_Cert *cert,
+ PKIX_Int32 *pSkipCerts,
+ void *plContext)
+{
+ PKIX_Int32 explicitPolicySkipCerts = 0;
+ PKIX_Int32 inhibitMappingSkipCerts = 0;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetRequireExplicitPolicy");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
+
+ if (!(cert->policyConstraintsProcessed)) {
+ PKIX_OBJECT_LOCK(cert);
+
+ if (!(cert->policyConstraintsProcessed)) {
+
+ /*
+ * If we can't process it now, we probably will be
+ * unable to process it later. Set the default value.
+ */
+ cert->policyConstraintsProcessed = PKIX_TRUE;
+ cert->policyConstraintsExplicitPolicySkipCerts = -1;
+ cert->policyConstraintsInhibitMappingSkipCerts = -1;
+
+ PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints
+ (cert->nssCert,
+ &explicitPolicySkipCerts,
+ &inhibitMappingSkipCerts,
+ plContext),
+ PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED);
+
+ cert->policyConstraintsExplicitPolicySkipCerts =
+ explicitPolicySkipCerts;
+ cert->policyConstraintsInhibitMappingSkipCerts =
+ inhibitMappingSkipCerts;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ *pSkipCerts = cert->policyConstraintsExplicitPolicySkipCerts;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetPolicyMappingInhibited
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetPolicyMappingInhibited(
+ PKIX_PL_Cert *cert,
+ PKIX_Int32 *pSkipCerts,
+ void *plContext)
+{
+ PKIX_Int32 explicitPolicySkipCerts = 0;
+ PKIX_Int32 inhibitMappingSkipCerts = 0;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappingInhibited");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
+
+ if (!(cert->policyConstraintsProcessed)) {
+ PKIX_OBJECT_LOCK(cert);
+
+ if (!(cert->policyConstraintsProcessed)) {
+
+ /*
+ * If we can't process it now, we probably will be
+ * unable to process it later. Set the default value.
+ */
+ cert->policyConstraintsProcessed = PKIX_TRUE;
+ cert->policyConstraintsExplicitPolicySkipCerts = -1;
+ cert->policyConstraintsInhibitMappingSkipCerts = -1;
+
+ PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints
+ (cert->nssCert,
+ &explicitPolicySkipCerts,
+ &inhibitMappingSkipCerts,
+ plContext),
+ PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED);
+
+ cert->policyConstraintsExplicitPolicySkipCerts =
+ explicitPolicySkipCerts;
+ cert->policyConstraintsInhibitMappingSkipCerts =
+ inhibitMappingSkipCerts;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ *pSkipCerts = cert->policyConstraintsInhibitMappingSkipCerts;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetInhibitAnyPolicy (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetInhibitAnyPolicy(
+ PKIX_PL_Cert *cert,
+ PKIX_Int32 *pSkipCerts,
+ void *plContext)
+{
+ PKIX_Int32 skipCerts = 0;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetInhibitAnyPolicy");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
+
+ if (!(cert->inhibitAnyPolicyProcessed)) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (!(cert->inhibitAnyPolicyProcessed)) {
+
+ /*
+ * If we can't process it now, we probably will be
+ * unable to process it later. Set the default value.
+ */
+ cert->inhibitAnyPolicyProcessed = PKIX_TRUE;
+ cert->inhibitAnySkipCerts = -1;
+
+ PKIX_CHECK(pkix_pl_Cert_DecodeInhibitAnyPolicy
+ (cert->nssCert, &skipCerts, plContext),
+ PKIX_CERTDECODEINHIBITANYPOLICYFAILED);
+
+ cert->inhibitAnySkipCerts = skipCerts;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ *pSkipCerts = cert->inhibitAnySkipCerts;
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_AreCertPoliciesCritical
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_AreCertPoliciesCritical(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pCritical,
+ void *plContext)
+{
+ PKIX_Boolean criticality = PKIX_FALSE;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_AreCertPoliciesCritical");
+ PKIX_NULLCHECK_TWO(cert, pCritical);
+
+ PKIX_CHECK(pkix_pl_Cert_IsExtensionCritical(
+ cert,
+ SEC_OID_X509_CERTIFICATE_POLICIES,
+ &criticality,
+ plContext),
+ PKIX_CERTISEXTENSIONCRITICALFAILED);
+
+ *pCritical = criticality;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_VerifySignature (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_VerifySignature(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_PublicKey *pubKey,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ SECKEYPublicKey *nssPubKey = NULL;
+ CERTSignedData *tbsCert = NULL;
+ PKIX_PL_Cert *cachedCert = NULL;
+ PKIX_Error *verifySig = NULL;
+ PKIX_Error *cachedSig = NULL;
+ PKIX_Error *checkSig = NULL;
+ SECStatus status;
+ PKIX_Boolean certEqual = PKIX_FALSE;
+ PKIX_Boolean certInHash = PKIX_FALSE;
+ PKIX_Boolean checkCertSig = PKIX_TRUE;
+ void* wincx = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifySignature");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pubKey);
+
+ /* if the cert check flag is off, skip the check */
+ checkSig = pkix_pl_NssContext_GetCertSignatureCheck(
+ (PKIX_PL_NssContext *)plContext, &checkCertSig);
+ if ((checkCertSig == PKIX_FALSE) && (checkSig == NULL)) {
+ goto cleanup;
+ }
+
+ verifySig = PKIX_PL_HashTable_Lookup
+ (cachedCertSigTable,
+ (PKIX_PL_Object *) pubKey,
+ (PKIX_PL_Object **) &cachedCert,
+ plContext);
+
+ if (cachedCert != NULL && verifySig == NULL) {
+ /* Cached Signature Table lookup succeed */
+ PKIX_EQUALS(cert, cachedCert, &certEqual, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+ if (certEqual == PKIX_TRUE) {
+ goto cleanup;
+ }
+ /* Different PubKey may hash to same value, skip add */
+ certInHash = PKIX_TRUE;
+ }
+
+ nssCert = cert->nssCert;
+ tbsCert = &nssCert->signatureWrap;
+
+ PKIX_CERT_DEBUG("\t\tCalling SECKEY_ExtractPublicKey).\n");
+ nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI);
+ if (!nssPubKey){
+ PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED);
+ }
+
+ PKIX_CERT_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey).\n");
+
+ PKIX_CHECK(pkix_pl_NssContext_GetWincx
+ ((PKIX_PL_NssContext *)plContext, &wincx),
+ PKIX_NSSCONTEXTGETWINCXFAILED);
+
+ status = CERT_VerifySignedDataWithPublicKey(tbsCert, nssPubKey, wincx);
+
+ if (status != SECSuccess) {
+ if (PORT_GetError() != SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ }
+ PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY);
+ }
+
+ if (certInHash == PKIX_FALSE) {
+ cachedSig = PKIX_PL_HashTable_Add
+ (cachedCertSigTable,
+ (PKIX_PL_Object *) pubKey,
+ (PKIX_PL_Object *) cert,
+ plContext);
+
+ if (cachedSig != NULL) {
+ PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n");
+ }
+ }
+
+cleanup:
+ if (nssPubKey){
+ PKIX_CERT_DEBUG("\t\tCalling SECKEY_DestroyPublicKey).\n");
+ SECKEY_DestroyPublicKey(nssPubKey);
+ }
+
+ PKIX_DECREF(cachedCert);
+ PKIX_DECREF(checkSig);
+ PKIX_DECREF(verifySig);
+ PKIX_DECREF(cachedSig);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_CheckValidity (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_CheckValidity(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Date *date,
+ void *plContext)
+{
+ SECCertTimeValidity val;
+ PRTime timeToCheck;
+ PKIX_Boolean allowOverride;
+ SECCertificateUsage requiredUsages;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckValidity");
+ PKIX_NULLCHECK_ONE(cert);
+
+ /* if the caller supplies a date, we use it; else, use current time */
+ if (date != NULL){
+ PKIX_CHECK(pkix_pl_Date_GetPRTime
+ (date, &timeToCheck, plContext),
+ PKIX_DATEGETPRTIMEFAILED);
+ } else {
+ timeToCheck = PR_Now();
+ }
+
+ requiredUsages = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
+ allowOverride =
+ (PRBool)((requiredUsages & certificateUsageSSLServer) ||
+ (requiredUsages & certificateUsageSSLServerWithStepUp) ||
+ (requiredUsages & certificateUsageIPsec));
+ val = CERT_CheckCertValidTimes(cert->nssCert, timeToCheck, allowOverride);
+ if (val != secCertTimeValid){
+ PKIX_ERROR(PKIX_CERTCHECKCERTVALIDTIMESFAILED);
+ }
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetValidityNotAfter (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetValidityNotAfter(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PRTime prtime;
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetValidityNotAfter");
+ PKIX_NULLCHECK_TWO(cert, pDate);
+
+ PKIX_DATE_DEBUG("\t\tCalling DER_DecodeTimeChoice).\n");
+ rv = DER_DecodeTimeChoice(&prtime, &(cert->nssCert->validity.notAfter));
+ if (rv != SECSuccess){
+ PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED);
+ }
+
+ PKIX_CHECK(pkix_pl_Date_CreateFromPRTime
+ (prtime, pDate, plContext),
+ PKIX_DATECREATEFROMPRTIMEFAILED);
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_VerifyCertAndKeyType (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_VerifyCertAndKeyType(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean isChainCert,
+ void *plContext)
+{
+ PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
+ SECCertificateUsage certificateUsage;
+ SECCertUsage certUsage = 0;
+ unsigned int requiredKeyUsage;
+ unsigned int requiredCertType;
+ unsigned int certType;
+ SECStatus rv = SECSuccess;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyCertType");
+ PKIX_NULLCHECK_TWO(cert, plContext);
+
+ certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
+
+ /* ensure we obtained a single usage bit only */
+ PORT_Assert(!(certificateUsage & (certificateUsage - 1)));
+
+ /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */
+ while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; }
+
+ /* check key usage and netscape cert type */
+ cert_GetCertType(cert->nssCert);
+ certType = cert->nssCert->nsCertType;
+ if (isChainCert ||
+ (certUsage != certUsageVerifyCA && certUsage != certUsageAnyCA)) {
+ rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, isChainCert,
+ &requiredKeyUsage,
+ &requiredCertType);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_UNSUPPORTEDCERTUSAGE);
+ }
+ } else {
+ /* use this key usage and cert type for certUsageAnyCA and
+ * certUsageVerifyCA. */
+ requiredKeyUsage = KU_KEY_CERT_SIGN;
+ requiredCertType = NS_CERT_TYPE_CA;
+ }
+ if (CERT_CheckKeyUsage(cert->nssCert, requiredKeyUsage) != SECSuccess) {
+ PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED);
+ }
+ if (!(certType & requiredCertType)) {
+ PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED);
+ }
+cleanup:
+ PKIX_DECREF(basicConstraints);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_VerifyKeyUsage (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_VerifyKeyUsage(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 keyUsage,
+ void *plContext)
+{
+ CERTCertificate *nssCert = NULL;
+ PKIX_UInt32 nssKeyUsage = 0;
+ SECStatus status;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyKeyUsage");
+ PKIX_NULLCHECK_TWO(cert, cert->nssCert);
+
+ nssCert = cert->nssCert;
+
+ /* if cert doesn't have keyUsage extension, all keyUsages are valid */
+ if (!nssCert->keyUsagePresent){
+ goto cleanup;
+ }
+
+ if (keyUsage & PKIX_DIGITAL_SIGNATURE){
+ nssKeyUsage = nssKeyUsage | KU_DIGITAL_SIGNATURE;
+ }
+
+ if (keyUsage & PKIX_NON_REPUDIATION){
+ nssKeyUsage = nssKeyUsage | KU_NON_REPUDIATION;
+ }
+
+ if (keyUsage & PKIX_KEY_ENCIPHERMENT){
+ nssKeyUsage = nssKeyUsage | KU_KEY_ENCIPHERMENT;
+ }
+
+ if (keyUsage & PKIX_DATA_ENCIPHERMENT){
+ nssKeyUsage = nssKeyUsage | KU_DATA_ENCIPHERMENT;
+ }
+
+ if (keyUsage & PKIX_KEY_AGREEMENT){
+ nssKeyUsage = nssKeyUsage | KU_KEY_AGREEMENT;
+ }
+
+ if (keyUsage & PKIX_KEY_CERT_SIGN){
+ nssKeyUsage = nssKeyUsage | KU_KEY_CERT_SIGN;
+ }
+
+ if (keyUsage & PKIX_CRL_SIGN){
+ nssKeyUsage = nssKeyUsage | KU_CRL_SIGN;
+ }
+
+ if (keyUsage & PKIX_ENCIPHER_ONLY){
+ nssKeyUsage = nssKeyUsage | 0x01;
+ }
+
+ if (keyUsage & PKIX_DECIPHER_ONLY){
+ /* XXX we should support this once it is fixed in NSS */
+ PKIX_ERROR(PKIX_DECIPHERONLYKEYUSAGENOTSUPPORTED);
+ }
+
+ status = CERT_CheckKeyUsage(nssCert, nssKeyUsage);
+ if (status != SECSuccess) {
+ PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED);
+ }
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetNameConstraints
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetNameConstraints(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNameConstraints");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pNameConstraints);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->nameConstraints == NULL && !cert->nameConstraintsAbsent) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->nameConstraints == NULL &&
+ !cert->nameConstraintsAbsent) {
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_Create
+ (cert->nssCert, &nameConstraints, plContext),
+ PKIX_CERTNAMECONSTRAINTSCREATEFAILED);
+
+ if (nameConstraints == NULL) {
+ cert->nameConstraintsAbsent = PKIX_TRUE;
+ }
+
+ cert->nameConstraints = nameConstraints;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+
+ }
+
+ PKIX_INCREF(cert->nameConstraints);
+
+ *pNameConstraints = cert->nameConstraints;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_CheckNameConstraints
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_CheckNameConstraints(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean treatCommonNameAsDNSName,
+ void *plContext)
+{
+ PKIX_Boolean checkPass = PKIX_TRUE;
+ CERTGeneralName *nssSubjectNames = NULL;
+ PLArenaPool *arena = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckNameConstraints");
+ PKIX_NULLCHECK_ONE(cert);
+
+ if (nameConstraints != NULL) {
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ /* only check common Name if the usage requires it */
+ if (treatCommonNameAsDNSName) {
+ SECCertificateUsage certificateUsage;
+ certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
+ if ((certificateUsage != certificateUsageSSLServer) &&
+ (certificateUsage != certificateUsageIPsec)) {
+ treatCommonNameAsDNSName = PKIX_FALSE;
+ }
+ }
+
+ /* This NSS call returns Subject Alt Names. If
+ * treatCommonNameAsDNSName is true, it also returns the
+ * Subject Common Name
+ */
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_GetConstrainedCertificateNames\n");
+ nssSubjectNames = CERT_GetConstrainedCertificateNames
+ (cert->nssCert, arena, treatCommonNameAsDNSName);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_CheckNameSpaceNssNames
+ (nssSubjectNames,
+ nameConstraints,
+ &checkPass,
+ plContext),
+ PKIX_CERTNAMECONSTRAINTSCHECKNAMESPACENSSNAMESFAILED);
+
+ if (checkPass != PKIX_TRUE) {
+ PKIX_ERROR(PKIX_CERTFAILEDNAMECONSTRAINTSCHECKING);
+ }
+ }
+
+cleanup:
+ if (arena){
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_MergeNameConstraints
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_MergeNameConstraints(
+ PKIX_PL_CertNameConstraints *firstNC,
+ PKIX_PL_CertNameConstraints *secondNC,
+ PKIX_PL_CertNameConstraints **pResultNC,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *mergedNC = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_MergeNameConstraints");
+ PKIX_NULLCHECK_TWO(firstNC, pResultNC);
+
+ if (secondNC == NULL) {
+
+ PKIX_INCREF(firstNC);
+ *pResultNC = firstNC;
+
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_Merge
+ (firstNC, secondNC, &mergedNC, plContext),
+ PKIX_CERTNAMECONSTRAINTSMERGEFAILED);
+
+ *pResultNC = mergedNC;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * Find out the state of the NSS trust bits for the requested usage.
+ * Returns SECFailure if the cert is explicitly distrusted.
+ * Returns SECSuccess if the cert can be used to form a chain (normal case),
+ * or it is explicitly trusted. The trusted bool is set to true if it is
+ * explicitly trusted.
+ */
+static SECStatus
+pkix_pl_Cert_GetTrusted(void *plContext,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *trusted,
+ PKIX_Boolean isCA)
+{
+ SECStatus rv;
+ CERTCertificate *nssCert = NULL;
+ SECCertUsage certUsage = 0;
+ SECCertificateUsage certificateUsage;
+ SECTrustType trustType;
+ unsigned int trustFlags;
+ unsigned int requiredFlags;
+ CERTCertTrust trust;
+
+ *trusted = PKIX_FALSE;
+
+ /* no key usage information */
+ if (plContext == NULL) {
+ return SECSuccess;
+ }
+
+ certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
+
+ /* ensure we obtained a single usage bit only */
+ PORT_Assert(!(certificateUsage & (certificateUsage - 1)));
+
+ /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */
+ while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; }
+
+ nssCert = cert->nssCert;
+
+ if (!isCA) {
+ PRBool prTrusted;
+ unsigned int failedFlags;
+ rv = cert_CheckLeafTrust(nssCert, certUsage,
+ &failedFlags, &prTrusted);
+ *trusted = (PKIX_Boolean) prTrusted;
+ return rv;
+ }
+ rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
+ &trustType);
+ if (rv != SECSuccess) {
+ return SECSuccess;
+ }
+
+ rv = CERT_GetCertTrust(nssCert, &trust);
+ if (rv != SECSuccess) {
+ return SECSuccess;
+ }
+ trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType);
+ /* normally trustTypeNone usages accept any of the given trust bits
+ * being on as acceptable. If any are distrusted (and none are trusted),
+ * then we will also distrust the cert */
+ if ((trustFlags == 0) && (trustType == trustTypeNone)) {
+ trustFlags = trust.sslFlags | trust.emailFlags |
+ trust.objectSigningFlags;
+ }
+ if ((trustFlags & requiredFlags) == requiredFlags) {
+ *trusted = PKIX_TRUE;
+ return SECSuccess;
+ }
+ if ((trustFlags & CERTDB_TERMINAL_RECORD) &&
+ ((trustFlags & (CERTDB_VALID_CA|CERTDB_TRUSTED)) == 0)) {
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_IsCertTrusted
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_IsCertTrusted(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_TrustAnchorMode trustAnchorMode,
+ PKIX_Boolean *pTrusted,
+ void *plContext)
+{
+ PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
+ PKIX_Boolean trusted = PKIX_FALSE;
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_IsCertTrusted");
+ PKIX_NULLCHECK_TWO(cert, pTrusted);
+
+ /* Call GetTrusted first to see if we are going to distrust the
+ * certificate */
+ rv = pkix_pl_Cert_GetTrusted(plContext, cert, &trusted, PKIX_TRUE);
+ if (rv != SECSuccess) {
+ /* Failure means the cert is explicitly distrusted,
+ * let the next level know not to use it. */
+ *pTrusted = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED);
+ }
+
+ if (trustAnchorMode == PKIX_PL_TrustAnchorMode_Exclusive ||
+ (trustAnchorMode == PKIX_PL_TrustAnchorMode_Additive &&
+ cert->isUserTrustAnchor)) {
+ /* Use the trust anchor's |trusted| value */
+ *pTrusted = cert->isUserTrustAnchor;
+ goto cleanup;
+ }
+
+ /* no key usage information or store is not trusted */
+ if (plContext == NULL || cert->store == NULL) {
+ *pTrusted = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ PKIX_CHECK(PKIX_CertStore_GetTrustCallback
+ (cert->store, &trustCallback, plContext),
+ PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
+
+ PKIX_CHECK_ONLY_FATAL(trustCallback
+ (cert->store, cert, &trusted, plContext),
+ PKIX_CHECKTRUSTCALLBACKFAILED);
+
+ /* allow trust store to override if we can trust the trust
+ * bits */
+ if (PKIX_ERROR_RECEIVED || (trusted == PKIX_FALSE)) {
+ *pTrusted = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ *pTrusted = trusted;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_IsLeafCertTrusted
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_IsLeafCertTrusted(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pTrusted,
+ void *plContext)
+{
+ SECStatus rv;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_IsLeafCertTrusted");
+ PKIX_NULLCHECK_TWO(cert, pTrusted);
+
+ *pTrusted = PKIX_FALSE;
+
+ rv = pkix_pl_Cert_GetTrusted(plContext, cert, pTrusted, PKIX_FALSE);
+ if (rv != SECSuccess) {
+ /* Failure means the cert is explicitly distrusted,
+ * let the next level know not to use it. */
+ *pTrusted = PKIX_FALSE;
+ PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED);
+ }
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/* FUNCTION: PKIX_PL_Cert_SetAsTrustAnchor */
+PKIX_Error*
+PKIX_PL_Cert_SetAsTrustAnchor(PKIX_PL_Cert *cert,
+ void *plContext)
+{
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_SetAsTrustAnchor");
+ PKIX_NULLCHECK_ONE(cert);
+
+ cert->isUserTrustAnchor = PKIX_TRUE;
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetCacheFlag (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetCacheFlag(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pCacheFlag,
+ void *plContext)
+{
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCacheFlag");
+ PKIX_NULLCHECK_TWO(cert, pCacheFlag);
+
+ *pCacheFlag = cert->cacheFlag;
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_SetCacheFlag (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_SetCacheFlag(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean cacheFlag,
+ void *plContext)
+{
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_SetCacheFlag");
+ PKIX_NULLCHECK_ONE(cert);
+
+ cert->cacheFlag = cacheFlag;
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetTrustCertStore (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetTrustCertStore(
+ PKIX_PL_Cert *cert,
+ PKIX_CertStore **pTrustCertStore,
+ void *plContext)
+{
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetTrustCertStore");
+ PKIX_NULLCHECK_TWO(cert, pTrustCertStore);
+
+ PKIX_INCREF(cert->store);
+ *pTrustCertStore = cert->store;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_SetTrustCertStore (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_SetTrustCertStore(
+ PKIX_PL_Cert *cert,
+ PKIX_CertStore *trustCertStore,
+ void *plContext)
+{
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_SetTrustCertStore");
+ PKIX_NULLCHECK_TWO(cert, trustCertStore);
+
+ PKIX_INCREF(trustCertStore);
+ cert->store = trustCertStore;
+
+cleanup:
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetAuthorityInfoAccess
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetAuthorityInfoAccess(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */
+ void *plContext)
+{
+ PKIX_List *aiaList = NULL; /* of PKIX_PL_InfoAccess */
+ SECItem *encodedAIA = NULL;
+ CERTAuthInfoAccess **aia = NULL;
+ PLArenaPool *arena = NULL;
+ SECStatus rv;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityInfoAccess");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAiaList);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->authorityInfoAccess == NULL) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->authorityInfoAccess == NULL) {
+
+ PKIX_PL_NSSCALLRV(CERT, encodedAIA, SECITEM_AllocItem,
+ (NULL, NULL, 0));
+
+ if (encodedAIA == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension,
+ (cert->nssCert,
+ SEC_OID_X509_AUTH_INFO_ACCESS,
+ encodedAIA));
+
+ if (rv == SECFailure) {
+ goto cleanup;
+ }
+
+ PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena,
+ (DER_DEFAULT_CHUNKSIZE));
+
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_PL_NSSCALLRV
+ (CERT, aia, CERT_DecodeAuthInfoAccessExtension,
+ (arena, encodedAIA));
+
+ PKIX_CHECK(pkix_pl_InfoAccess_CreateList
+ (aia, &aiaList, plContext),
+ PKIX_INFOACCESSCREATELISTFAILED);
+
+ cert->authorityInfoAccess = aiaList;
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->authorityInfoAccess);
+
+ *pAiaList = cert->authorityInfoAccess;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ if (arena != NULL) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ if (encodedAIA != NULL) {
+ SECITEM_FreeItem(encodedAIA, PR_TRUE);
+ }
+
+ PKIX_RETURN(CERT);
+}
+
+/* XXX Following defines belongs to NSS */
+static const unsigned char siaOIDString[] = {0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x01, 0x0b};
+#define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetSubjectInfoAccess
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetSubjectInfoAccess(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pSiaList, /* of PKIX_PL_InfoAccess */
+ void *plContext)
+{
+ PKIX_List *siaList; /* of PKIX_PL_InfoAccess */
+ SECItem siaOID = OI(siaOIDString);
+ SECItem *encodedSubjInfoAccess = NULL;
+ CERTAuthInfoAccess **subjInfoAccess = NULL;
+ PLArenaPool *arena = NULL;
+ SECStatus rv;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectInfoAccess");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSiaList);
+
+ /* XXX
+ * Codes to deal with SubjectInfoAccess OID should be moved to
+ * NSS soon. I implemented them here so we don't touch NSS
+ * source tree, from JP's suggestion.
+ */
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->subjectInfoAccess == NULL) {
+
+ PKIX_OBJECT_LOCK(cert);
+
+ if (cert->subjectInfoAccess == NULL) {
+
+ encodedSubjInfoAccess = SECITEM_AllocItem(NULL, NULL, 0);
+ if (encodedSubjInfoAccess == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_FindCertExtensionByOID).\n");
+ rv = CERT_FindCertExtensionByOID
+ (cert->nssCert, &siaOID, encodedSubjInfoAccess);
+
+ if (rv == SECFailure) {
+ goto cleanup;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ /* XXX
+ * Decode Subject Information Access -
+ * since its type is the same as Authority Information
+ * Access, reuse the call. NSS- change name to avoid
+ * confusion.
+ */
+ PKIX_CERT_DEBUG
+ ("\t\tCalling CERT_DecodeAuthInfoAccessExtension).\n");
+ subjInfoAccess = CERT_DecodeAuthInfoAccessExtension
+ (arena, encodedSubjInfoAccess);
+
+ PKIX_CHECK(pkix_pl_InfoAccess_CreateList
+ (subjInfoAccess, &siaList, plContext),
+ PKIX_INFOACCESSCREATELISTFAILED);
+
+ cert->subjectInfoAccess = siaList;
+
+ }
+
+ PKIX_OBJECT_UNLOCK(cert);
+ }
+
+ PKIX_INCREF(cert->subjectInfoAccess);
+ *pSiaList = cert->subjectInfoAccess;
+
+cleanup:
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ if (arena != NULL) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ if (encodedSubjInfoAccess != NULL) {
+ SECITEM_FreeItem(encodedSubjInfoAccess, PR_TRUE);
+ }
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetCrlDp
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetCrlDp(
+ PKIX_PL_Cert *cert,
+ PKIX_List **pDpList,
+ void *plContext)
+{
+ PKIX_UInt32 dpIndex = 0;
+ pkix_pl_CrlDp *dp = NULL;
+ CERTCrlDistributionPoints *dpoints = NULL;
+
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCrlDp");
+ PKIX_NULLCHECK_THREE(cert, cert->nssCert, pDpList);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (cert->crldpList == NULL) {
+ PKIX_OBJECT_LOCK(cert);
+ if (cert->crldpList != NULL) {
+ goto cleanup;
+ }
+ PKIX_CHECK(PKIX_List_Create(&cert->crldpList, plContext),
+ PKIX_LISTCREATEFAILED);
+ dpoints = CERT_FindCRLDistributionPoints(cert->nssCert);
+ if (!dpoints || !dpoints->distPoints) {
+ goto cleanup;
+ }
+ for (;dpoints->distPoints[dpIndex];dpIndex++) {
+ PKIX_CHECK(
+ pkix_pl_CrlDp_Create(dpoints->distPoints[dpIndex],
+ &cert->nssCert->issuer,
+ &dp, plContext),
+ PKIX_CRLDPCREATEFAILED);
+ /* Create crldp list in reverse order in attempt to get
+ * to the whole crl first. */
+ PKIX_CHECK(
+ PKIX_List_InsertItem(cert->crldpList, 0,
+ (PKIX_PL_Object*)dp,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(dp);
+ }
+ }
+cleanup:
+ PKIX_INCREF(cert->crldpList);
+ *pDpList = cert->crldpList;
+
+ PKIX_OBJECT_UNLOCK(lockedObject);
+ PKIX_DECREF(dp);
+
+ PKIX_RETURN(CERT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Cert_GetCERTCertificate
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Cert_GetCERTCertificate(
+ PKIX_PL_Cert *cert,
+ CERTCertificate **pnssCert,
+ void *plContext)
+{
+ PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNssCert");
+ PKIX_NULLCHECK_TWO(cert, pnssCert);
+
+ *pnssCert = CERT_DupCertificate(cert->nssCert);
+
+ PKIX_RETURN(CERT);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.h
new file mode 100644
index 0000000000..56fe64228d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_cert.h
@@ -0,0 +1,107 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_cert.h
+ *
+ * Certificate Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_CERT_H
+#define _PKIX_PL_CERT_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_CertStruct {
+ CERTCertificate *nssCert; /* Must be the first field. The
+ * cert_NSSCertFromPKIXCert function in
+ * lib/certhigh/certvfypkix.c depends on
+ * this. */
+ CERTGeneralName *nssSubjAltNames;
+ PLArenaPool *arenaNameConstraints;
+ PKIX_PL_X500Name *issuer;
+ PKIX_PL_X500Name *subject;
+ PKIX_List *subjAltNames;
+ PKIX_Boolean subjAltNamesAbsent;
+ PKIX_PL_OID *publicKeyAlgId;
+ PKIX_PL_PublicKey *publicKey;
+ PKIX_PL_BigInt *serialNumber;
+ PKIX_List *critExtOids;
+ PKIX_PL_ByteArray *subjKeyId;
+ PKIX_Boolean subjKeyIdAbsent;
+ PKIX_PL_ByteArray *authKeyId;
+ PKIX_Boolean authKeyIdAbsent;
+ PKIX_List *extKeyUsages;
+ PKIX_Boolean extKeyUsagesAbsent;
+ PKIX_PL_CertBasicConstraints *certBasicConstraints;
+ PKIX_Boolean basicConstraintsAbsent;
+ PKIX_List *certPolicyInfos;
+ PKIX_Boolean policyInfoAbsent;
+ PKIX_Boolean policyMappingsAbsent;
+ PKIX_List *certPolicyMappings; /* List of PKIX_PL_CertPolicyMap */
+ PKIX_Boolean policyConstraintsProcessed;
+ PKIX_Int32 policyConstraintsExplicitPolicySkipCerts;
+ PKIX_Int32 policyConstraintsInhibitMappingSkipCerts;
+ PKIX_Boolean inhibitAnyPolicyProcessed;
+ PKIX_Int32 inhibitAnySkipCerts;
+ PKIX_PL_CertNameConstraints *nameConstraints;
+ PKIX_Boolean nameConstraintsAbsent;
+ PKIX_Boolean cacheFlag;
+ PKIX_CertStore *store;
+ PKIX_List *authorityInfoAccess; /* list of PKIX_PL_InfoAccess */
+ PKIX_List *subjectInfoAccess; /* list of PKIX_PL_InfoAccess */
+ PKIX_Boolean isUserTrustAnchor;
+ PKIX_List *crldpList; /* list of CRL DPs based on der in nssCert arena.
+ * Destruction is needed for pkix object and
+ * not for undelying der as it is a part
+ * nssCert arena. */
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_Cert_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_Cert_CreateWithNSSCert(
+ CERTCertificate *nssCert,
+ PKIX_PL_Cert **pCert,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_Cert_CreateToList(
+ SECItem *derCertItem,
+ PKIX_List *certList,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_Cert_CheckSubjectAltNameConstraints(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean matchAll,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_Cert_ToString_Helper(
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean partialString,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_Cert_CheckExtendedKeyUsage(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 requiredExtendedKeyUsages,
+ PKIX_Boolean *pPass,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_CERT_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.c
new file mode 100644
index 0000000000..a44ac65900
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.c
@@ -0,0 +1,371 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_certpolicyinfo.c
+ *
+ * CertPolicyInfo Type Functions
+ *
+ */
+
+#include "pkix_pl_certpolicyinfo.h"
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyInfo_Create
+ * DESCRIPTION:
+ *
+ * Creates a new CertPolicyInfo Object using the OID pointed to by "oid" and
+ * the List of CertPolicyQualifiers pointed to by "qualifiers", and stores it
+ * at "pObject". If a non-NULL list is provided, the caller is expected to
+ * have already set it to be immutable. The caller may provide an empty List,
+ * but a NULL List is preferable so a user does not need to call
+ * List_GetLength to get the number of qualifiers.
+ *
+ * PARAMETERS
+ * "oid"
+ * OID of the desired PolicyInfo ID; must be non-NULL
+ * "qualifiers"
+ * List of CertPolicyQualifiers; may be NULL or empty
+ * "pObject"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertPolicyInfo_Create(
+ PKIX_PL_OID *oid,
+ PKIX_List *qualifiers,
+ PKIX_PL_CertPolicyInfo **pObject,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyInfo *policyInfo = NULL;
+
+ PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_Create");
+
+ PKIX_NULLCHECK_TWO(oid, pObject);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTPOLICYINFO_TYPE,
+ sizeof (PKIX_PL_CertPolicyInfo),
+ (PKIX_PL_Object **)&policyInfo,
+ plContext),
+ PKIX_COULDNOTCREATECERTPOLICYINFOOBJECT);
+
+ PKIX_INCREF(oid);
+ policyInfo->cpID = oid;
+
+ PKIX_INCREF(qualifiers);
+ policyInfo->policyQualifiers = qualifiers;
+
+ *pObject = policyInfo;
+ policyInfo = NULL;
+
+cleanup:
+ PKIX_DECREF(policyInfo);
+
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyInfo_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyInfo_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyInfo *certPI = NULL;
+
+ PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYINFO_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYINFO);
+
+ certPI = (PKIX_PL_CertPolicyInfo*)object;
+
+ PKIX_DECREF(certPI->cpID);
+ PKIX_DECREF(certPI->policyQualifiers);
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyInfo_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyInfo_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyInfo *certPI = NULL;
+ PKIX_PL_String *oidString = NULL;
+ PKIX_PL_String *listString = NULL;
+ PKIX_PL_String *format = NULL;
+ PKIX_PL_String *outString = NULL;
+
+ PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_ToString");
+
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYINFO_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYINFO);
+
+ certPI = (PKIX_PL_CertPolicyInfo *)object;
+
+ PKIX_NULLCHECK_ONE(certPI->cpID);
+
+ PKIX_TOSTRING
+ (certPI->cpID,
+ &oidString,
+ plContext,
+ PKIX_OIDTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (certPI->policyQualifiers,
+ &listString,
+ plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* Put them together in the form OID[Qualifiers] */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s[%s]", 0, &format, plContext),
+ PKIX_ERRORINSTRINGCREATE);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString, plContext, format, oidString, listString),
+ PKIX_ERRORINSPRINTF);
+
+ *pString = outString;
+
+cleanup:
+
+ PKIX_DECREF(oidString);
+ PKIX_DECREF(listString);
+ PKIX_DECREF(format);
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyInfo_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyInfo_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyInfo *certPI = NULL;
+ PKIX_UInt32 oidHash = 0;
+ PKIX_UInt32 listHash = 0;
+
+ PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_Hashcode");
+
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYINFO_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYINFO);
+
+ certPI = (PKIX_PL_CertPolicyInfo *)object;
+
+ PKIX_NULLCHECK_ONE(certPI->cpID);
+
+ PKIX_HASHCODE
+ (certPI->cpID,
+ &oidHash,
+ plContext,
+ PKIX_ERRORINOIDHASHCODE);
+
+ PKIX_HASHCODE
+ (certPI->policyQualifiers,
+ &listHash,
+ plContext,
+ PKIX_ERRORINLISTHASHCODE);
+
+ *pHashcode = (31 * oidHash) + listHash;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyInfo_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyInfo_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyInfo *firstCPI = NULL;
+ PKIX_PL_CertPolicyInfo *secondCPI = NULL;
+ PKIX_UInt32 secondType = 0;
+ PKIX_Boolean compare = PKIX_FALSE;
+
+ PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CertPolicyInfo */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CERTPOLICYINFO_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCERTPOLICYINFO);
+
+ /*
+ * Since we know firstObject is a CertPolicyInfo,
+ * if both references are identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a CertPolicyInfo, we
+ * don't throw an error. We simply return FALSE.
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CERTPOLICYINFO_TYPE) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ firstCPI = (PKIX_PL_CertPolicyInfo *)firstObject;
+ secondCPI = (PKIX_PL_CertPolicyInfo *)secondObject;
+
+ /*
+ * Compare the value of the OID components
+ */
+
+ PKIX_NULLCHECK_TWO(firstCPI->cpID, secondCPI->cpID);
+
+ PKIX_EQUALS
+ (firstCPI->cpID,
+ secondCPI->cpID,
+ &compare,
+ plContext,
+ PKIX_OIDEQUALSFAILED);
+
+ /*
+ * If the OIDs did not match, we don't need to
+ * compare the Lists. If the OIDs did match,
+ * the return value is the value of the
+ * List comparison.
+ */
+ if (compare) {
+ PKIX_EQUALS
+ (firstCPI->policyQualifiers,
+ secondCPI->policyQualifiers,
+ &compare,
+ plContext,
+ PKIX_LISTEQUALSFAILED);
+ }
+
+ *pResult = compare;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyInfo_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTPOLICYINFO_TYPE and its related
+ * functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize,
+ * which should only be called once, it is acceptable that
+ * this function is not thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CertPolicyInfo_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTPOLICYINFO, "pkix_pl_CertPolicyInfo_RegisterSelf");
+
+ entry.description = "CertPolicyInfo";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_CertPolicyInfo);
+ entry.destructor = pkix_pl_CertPolicyInfo_Destroy;
+ entry.equalsFunction = pkix_pl_CertPolicyInfo_Equals;
+ entry.hashcodeFunction = pkix_pl_CertPolicyInfo_Hashcode;
+ entry.toStringFunction = pkix_pl_CertPolicyInfo_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CERTPOLICYINFO_TYPE] = entry;
+
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+/* --Public-CertPolicyInfo-Functions------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_CertPolicyInfo_GetPolicyId
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CertPolicyInfo_GetPolicyId(
+ PKIX_PL_CertPolicyInfo *policyInfo,
+ PKIX_PL_OID **pPolicyId,
+ void *plContext)
+{
+ PKIX_ENTER(CERTPOLICYINFO, "PKIX_PL_CertPolicyInfo_GetPolicyId");
+
+ PKIX_NULLCHECK_TWO(policyInfo, pPolicyId);
+
+ PKIX_INCREF(policyInfo->cpID);
+
+ *pPolicyId = policyInfo->cpID;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYINFO);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CertPolicyInfo_GetPolQualifiers
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CertPolicyInfo_GetPolQualifiers(
+ PKIX_PL_CertPolicyInfo *policyInfo,
+ PKIX_List **pQuals,
+ void *plContext)
+{
+ PKIX_ENTER(CERTPOLICYINFO, "PKIX_PL_CertPolicyInfo_GetPolQualifiers");
+
+ PKIX_NULLCHECK_TWO(policyInfo, pQuals);
+
+ PKIX_INCREF(policyInfo->policyQualifiers);
+
+ /*
+ * This List is created in PKIX_PL_Cert_DecodePolicyInfo
+ * and is set immutable immediately after being created.
+ */
+ *pQuals = policyInfo->policyQualifiers;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYINFO);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.h
new file mode 100644
index 0000000000..5c324e6cd2
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyinfo.h
@@ -0,0 +1,50 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_certpolicyinfo.h
+ *
+ * PolicyInfo Type Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_POLICYINFO_H
+#define _PKIX_PL_POLICYINFO_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This structure reflects the contents of the policy info extension as
+ * described in Section 4.2.1.5 of RFC3280.
+ *
+ * PolicyInformation ::= SEQUENCE {
+ * policyIdentifier CertPolicyId,
+ * PolicyQualifiers SEQUENCE SIZE (1..MAX) OF
+ * PolicyQualifierInfo OPTIONAL }
+ *
+ */
+struct PKIX_PL_CertPolicyInfoStruct {
+ PKIX_PL_OID *cpID;
+ PKIX_List *policyQualifiers; /* LIST of PKIX_PL_CertPolicyQualifier */
+};
+
+PKIX_Error *
+pkix_pl_CertPolicyInfo_Create(
+ PKIX_PL_OID *oid,
+ PKIX_List *qualifiers,
+ PKIX_PL_CertPolicyInfo **pObject,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertPolicyInfo_RegisterSelf(
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_POLICYINFO_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.c
new file mode 100644
index 0000000000..08b1ca9df1
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.c
@@ -0,0 +1,386 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_certpolicymap.c
+ *
+ * CertPolicyMap Type Functions
+ *
+ */
+
+#include "pkix_pl_certpolicymap.h"
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_Create
+ * DESCRIPTION:
+ *
+ * Creates a new CertPolicyMap Object pairing the OID given by
+ * "issuerDomainPolicy" with the OID given by "subjectDomainPolicy", and
+ * stores the result at "pCertPolicyMap".
+ *
+ * PARAMETERS
+ * "issuerDomainPolicy"
+ * Address of the OID of the IssuerDomainPolicy. Must be non-NULL.
+ * "subjectDomainPolicy"
+ * Address of the OID of the SubjectDomainPolicy. Must be non-NULL.
+ * "pCertPolicyMap"
+ * Address where CertPolicyMap pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CertPolicyMap Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertPolicyMap_Create(
+ PKIX_PL_OID *issuerDomainPolicy,
+ PKIX_PL_OID *subjectDomainPolicy,
+ PKIX_PL_CertPolicyMap **pCertPolicyMap,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *policyMap = NULL;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Create");
+
+ PKIX_NULLCHECK_THREE
+ (issuerDomainPolicy, subjectDomainPolicy, pCertPolicyMap);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTPOLICYMAP_TYPE,
+ sizeof (PKIX_PL_CertPolicyMap),
+ (PKIX_PL_Object **)&policyMap,
+ plContext),
+ PKIX_COULDNOTCREATECERTPOLICYMAPOBJECT);
+
+ PKIX_INCREF(issuerDomainPolicy);
+ policyMap->issuerDomainPolicy = issuerDomainPolicy;
+
+ PKIX_INCREF(subjectDomainPolicy);
+ policyMap->subjectDomainPolicy = subjectDomainPolicy;
+
+ *pCertPolicyMap = policyMap;
+ policyMap = NULL;
+
+cleanup:
+ PKIX_DECREF(policyMap);
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyMap_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *certMap = NULL;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYMAP_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYMAP);
+
+ certMap = (PKIX_PL_CertPolicyMap*)object;
+
+ PKIX_DECREF(certMap->issuerDomainPolicy);
+ PKIX_DECREF(certMap->subjectDomainPolicy);
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyMap_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *certMap = NULL;
+ PKIX_PL_String *format = NULL;
+ PKIX_PL_String *outString = NULL;
+ PKIX_PL_String *issuerString = NULL;
+ PKIX_PL_String *subjectString = NULL;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_ToString");
+
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYMAP_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYMAP);
+
+ certMap = (PKIX_PL_CertPolicyMap *)object;
+
+ PKIX_TOSTRING
+ (certMap->issuerDomainPolicy,
+ &issuerString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ PKIX_TOSTRING
+ (certMap->subjectDomainPolicy,
+ &subjectString,
+ plContext,
+ PKIX_OBJECTTOSTRINGFAILED);
+
+ /* Put them together in the form issuerPolicy=>subjectPolicy */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "%s=>%s", 0, &format, plContext),
+ PKIX_ERRORINSTRINGCREATE);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString, plContext, format, issuerString, subjectString),
+ PKIX_ERRORINSPRINTF);
+
+ *pString = outString;
+
+cleanup:
+ PKIX_DECREF(format);
+ PKIX_DECREF(issuerString);
+ PKIX_DECREF(subjectString);
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyMap_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_UInt32 issuerHash = 0;
+ PKIX_UInt32 subjectHash = 0;
+ PKIX_PL_CertPolicyMap *certMap = NULL;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Hashcode");
+
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CERTPOLICYMAP_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYMAP);
+
+ certMap = (PKIX_PL_CertPolicyMap *)object;
+
+ PKIX_HASHCODE
+ (certMap->issuerDomainPolicy,
+ &issuerHash,
+ plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_HASHCODE
+ (certMap->subjectDomainPolicy,
+ &subjectHash,
+ plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ *pHashcode = issuerHash*31 + subjectHash;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyMap_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *firstCertMap = NULL;
+ PKIX_PL_CertPolicyMap *secondCertMap = NULL;
+ PKIX_UInt32 secondType = 0;
+ PKIX_Boolean compare = PKIX_FALSE;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CertPolicyMap */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CERTPOLICYMAP_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCERTPOLICYMAP);
+
+ /*
+ * Since we know firstObject is a CertPolicyMap,
+ * if both references are identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a CertPolicyMap, we
+ * don't throw an error. We simply return FALSE.
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CERTPOLICYMAP_TYPE) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ firstCertMap = (PKIX_PL_CertPolicyMap *)firstObject;
+ secondCertMap = (PKIX_PL_CertPolicyMap *)secondObject;
+
+ PKIX_EQUALS
+ (firstCertMap->issuerDomainPolicy,
+ secondCertMap->issuerDomainPolicy,
+ &compare,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (compare) {
+ PKIX_EQUALS
+ (firstCertMap->subjectDomainPolicy,
+ secondCertMap->subjectDomainPolicy,
+ &compare,
+ plContext,
+ PKIX_OBJECTEQUALSFAILED);
+ }
+
+ *pResult = compare;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_Duplicate
+ * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyMap_Duplicate(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyMap *original = NULL;
+ PKIX_PL_CertPolicyMap *copy = NULL;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_Duplicate");
+
+ PKIX_NULLCHECK_TWO(object, pNewObject);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYMAP_TYPE, plContext),
+ PKIX_OBJECTARGUMENTNOTPOLICYMAP);
+
+ original = (PKIX_PL_CertPolicyMap *)object;
+
+ PKIX_CHECK(pkix_pl_CertPolicyMap_Create
+ (original->issuerDomainPolicy,
+ original->subjectDomainPolicy,
+ &copy,
+ plContext),
+ PKIX_CERTPOLICYMAPCREATEFAILED);
+
+ *pNewObject = (PKIX_PL_Object *)copy;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyMap_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTPOLICYMAP_TYPE and its related
+ * functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize,
+ * which should only be called once, it is acceptable that
+ * this function is not thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CertPolicyMap_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTPOLICYMAP, "pkix_pl_CertPolicyMap_RegisterSelf");
+
+ entry.description = "CertPolicyMap";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_CertPolicyMap);
+ entry.destructor = pkix_pl_CertPolicyMap_Destroy;
+ entry.equalsFunction = pkix_pl_CertPolicyMap_Equals;
+ entry.hashcodeFunction = pkix_pl_CertPolicyMap_Hashcode;
+ entry.toStringFunction = pkix_pl_CertPolicyMap_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_pl_CertPolicyMap_Duplicate;
+
+ systemClasses[PKIX_CERTPOLICYMAP_TYPE] = entry;
+
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/* --Public-CertPolicyMap-Functions------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy(
+ PKIX_PL_CertPolicyMap *policyMapping,
+ PKIX_PL_OID **pIssuerDomainPolicy,
+ void *plContext)
+{
+ PKIX_ENTER
+ (CERTPOLICYMAP, "PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy");
+
+ PKIX_NULLCHECK_TWO(policyMapping, pIssuerDomainPolicy);
+
+ PKIX_INCREF(policyMapping->issuerDomainPolicy);
+ *pIssuerDomainPolicy = policyMapping->issuerDomainPolicy;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYMAP);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy(
+ PKIX_PL_CertPolicyMap *policyMapping,
+ PKIX_PL_OID **pSubjectDomainPolicy,
+ void *plContext)
+{
+ PKIX_ENTER
+ (CERTPOLICYMAP, "PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy");
+
+ PKIX_NULLCHECK_TWO(policyMapping, pSubjectDomainPolicy);
+
+ PKIX_INCREF(policyMapping->subjectDomainPolicy);
+ *pSubjectDomainPolicy = policyMapping->subjectDomainPolicy;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYMAP);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.h
new file mode 100644
index 0000000000..a03bce2c8c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicymap.h
@@ -0,0 +1,49 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_certpolicymap.h
+ *
+ * CertPolicyMap Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_CERTPOLICYMAP_H
+#define _PKIX_PL_CERTPOLICYMAP_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This structure reflects the contents of the policy mapping extension as
+ * described in Section 4.2.1.6 of RFC3280.
+ *
+ * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
+ * issuerDomainPolicy CertPolicyId,
+ * subjectDomainPolicy CertPolicyId }
+ *
+ */
+struct PKIX_PL_CertPolicyMapStruct {
+ PKIX_PL_OID *issuerDomainPolicy;
+ PKIX_PL_OID *subjectDomainPolicy;
+};
+
+PKIX_Error *
+pkix_pl_CertPolicyMap_Create(
+ PKIX_PL_OID *issuerDomainPolicy,
+ PKIX_PL_OID *subjectDomainPolicy,
+ PKIX_PL_CertPolicyMap **pObject,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertPolicyMap_RegisterSelf(
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_CERTPOLICYMAP_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.c
new file mode 100644
index 0000000000..b57623d269
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.c
@@ -0,0 +1,365 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_certpolicyqualifier.c
+ *
+ * CertPolicyQualifier Type Functions
+ *
+ */
+
+#include "pkix_pl_certpolicyqualifier.h"
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyQualifier_Create
+ * DESCRIPTION:
+ *
+ * Creates a CertPolicyQualifier object with the OID given by "oid"
+ * and the ByteArray given by "qualifier", and stores it at "pObject".
+ *
+ * PARAMETERS
+ * "oid"
+ * Address of OID of the desired policyQualifierId; must be non-NULL
+ * "qualifier"
+ * Address of ByteArray with the desired value of the qualifier;
+ * must be non-NULL
+ * "pObject"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertPolicyQualifier_Create(
+ PKIX_PL_OID *oid,
+ PKIX_PL_ByteArray *qualifier,
+ PKIX_PL_CertPolicyQualifier **pObject,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyQualifier *qual = NULL;
+
+ PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_Create");
+
+ PKIX_NULLCHECK_THREE(oid, qualifier, pObject);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTPOLICYQUALIFIER_TYPE,
+ sizeof (PKIX_PL_CertPolicyQualifier),
+ (PKIX_PL_Object **)&qual,
+ plContext),
+ PKIX_COULDNOTCREATECERTPOLICYQUALIFIEROBJECT);
+
+ PKIX_INCREF(oid);
+ qual->policyQualifierId = oid;
+
+ PKIX_INCREF(qualifier);
+ qual->qualifier = qualifier;
+
+ *pObject = qual;
+ qual = NULL;
+
+cleanup:
+ PKIX_DECREF(qual);
+
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyQualifier_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyQualifier_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyQualifier *certPQ = NULL;
+
+ PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYQUALIFIER_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYQUALIFIER);
+
+ certPQ = (PKIX_PL_CertPolicyQualifier*)object;
+
+ PKIX_DECREF(certPQ->policyQualifierId);
+ PKIX_DECREF(certPQ->qualifier);
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyQualifier_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyQualifier_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyQualifier *certPQ = NULL;
+ char *asciiFormat = "%s:%s";
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *pqIDString = NULL;
+ PKIX_PL_String *pqValString = NULL;
+ PKIX_PL_String *outString = NULL;
+
+ PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_ToString");
+
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYQUALIFIER_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYQUALIFIER);
+
+ certPQ = (PKIX_PL_CertPolicyQualifier *)object;
+
+ /*
+ * The policyQualifierId is required. If there is no qualifier,
+ * we should have a ByteArray of zero length.
+ */
+ PKIX_NULLCHECK_TWO(certPQ->policyQualifierId, certPQ->qualifier);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_TOSTRING(certPQ->policyQualifierId, &pqIDString, plContext,
+ PKIX_OIDTOSTRINGFAILED);
+
+ PKIX_CHECK(pkix_pl_ByteArray_ToHexString
+ (certPQ->qualifier, &pqValString, plContext),
+ PKIX_BYTEARRAYTOHEXSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&outString, plContext, formatString, pqIDString, pqValString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = outString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(pqIDString);
+ PKIX_DECREF(pqValString);
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyQualifier_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyQualifier_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyQualifier *certPQ = NULL;
+ PKIX_UInt32 cpidHash = 0;
+ PKIX_UInt32 cpqHash = 0;
+
+ PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTPOLICYQUALIFIER_TYPE, plContext),
+ PKIX_OBJECTNOTCERTPOLICYQUALIFIER);
+
+ certPQ = (PKIX_PL_CertPolicyQualifier *)object;
+
+ PKIX_NULLCHECK_TWO(certPQ->policyQualifierId, certPQ->qualifier);
+
+ PKIX_HASHCODE(certPQ->policyQualifierId, &cpidHash, plContext,
+ PKIX_ERRORINOIDHASHCODE);
+
+ PKIX_HASHCODE(certPQ->qualifier, &cpqHash, plContext,
+ PKIX_ERRORINBYTEARRAYHASHCODE);
+
+ *pHashcode = cpidHash*31 + cpqHash;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyQualifier_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertPolicyQualifier_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertPolicyQualifier *firstCPQ = NULL;
+ PKIX_PL_CertPolicyQualifier *secondCPQ = NULL;
+ PKIX_UInt32 secondType = 0;
+ PKIX_Boolean compare = PKIX_FALSE;
+
+ PKIX_ENTER(CERTPOLICYQUALIFIER, "pkix_pl_CertPolicyQualifier_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CertPolicyQualifier */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CERTPOLICYQUALIFIER_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCERTPOLICYQUALIFIER);
+
+ /*
+ * Since we know firstObject is a CertPolicyQualifier,
+ * if both references are identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a CertPolicyQualifier, we
+ * don't throw an error. We simply return FALSE.
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CERTPOLICYQUALIFIER_TYPE) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ firstCPQ = (PKIX_PL_CertPolicyQualifier *)firstObject;
+ secondCPQ = (PKIX_PL_CertPolicyQualifier *)secondObject;
+
+ /*
+ * Compare the value of the OID components
+ */
+
+ PKIX_NULLCHECK_TWO
+ (firstCPQ->policyQualifierId, secondCPQ->policyQualifierId);
+
+ PKIX_EQUALS
+ (firstCPQ->policyQualifierId,
+ secondCPQ->policyQualifierId,
+ &compare,
+ plContext,
+ PKIX_OIDEQUALSFAILED);
+
+ /*
+ * If the OIDs did not match, we don't need to
+ * compare the ByteArrays. If the OIDs did match,
+ * the return value is the value of the
+ * ByteArray comparison.
+ */
+ if (compare) {
+ PKIX_NULLCHECK_TWO(firstCPQ->qualifier, secondCPQ->qualifier);
+
+ PKIX_EQUALS
+ (firstCPQ->qualifier,
+ secondCPQ->qualifier,
+ &compare,
+ plContext,
+ PKIX_BYTEARRAYEQUALSFAILED);
+ }
+
+ *pResult = compare;
+
+cleanup:
+
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertPolicyQualifier_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTPOLICYQUALIFIER_TYPE and its related
+ * functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize,
+ * which should only be called once, it is acceptable that
+ * this function is not thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CertPolicyQualifier_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTPOLICYQUALIFIER,
+ "pkix_pl_CertPolicyQualifier_RegisterSelf");
+
+ entry.description = "CertPolicyQualifier";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_CertPolicyQualifier);
+ entry.destructor = pkix_pl_CertPolicyQualifier_Destroy;
+ entry.equalsFunction = pkix_pl_CertPolicyQualifier_Equals;
+ entry.hashcodeFunction = pkix_pl_CertPolicyQualifier_Hashcode;
+ entry.toStringFunction = pkix_pl_CertPolicyQualifier_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CERTPOLICYQUALIFIER_TYPE] = entry;
+
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+/* --Public-CertPolicyQualifier-Functions------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_PolicyQualifier_GetPolicyQualifierId
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_PolicyQualifier_GetPolicyQualifierId(
+ PKIX_PL_CertPolicyQualifier *policyQualifierInfo,
+ PKIX_PL_OID **pPolicyQualifierId,
+ void *plContext)
+{
+ PKIX_ENTER(CERTPOLICYQUALIFIER,
+ "PKIX_PL_PolicyQualifier_GetPolicyQualifierId");
+
+ PKIX_NULLCHECK_TWO(policyQualifierInfo, pPolicyQualifierId);
+
+ PKIX_INCREF(policyQualifierInfo->policyQualifierId);
+
+ *pPolicyQualifierId = policyQualifierInfo->policyQualifierId;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
+
+/*
+ * FUNCTION: PKIX_PL_PolicyQualifier_GetQualifier
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_PolicyQualifier_GetQualifier(
+ PKIX_PL_CertPolicyQualifier *policyQualifierInfo,
+ PKIX_PL_ByteArray **pQualifier,
+ void *plContext)
+{
+ PKIX_ENTER(CERTPOLICYQUALIFIER, "PKIX_PL_PolicyQualifier_GetQualifier");
+
+ PKIX_NULLCHECK_TWO(policyQualifierInfo, pQualifier);
+
+ PKIX_INCREF(policyQualifierInfo->qualifier);
+
+ *pQualifier = policyQualifierInfo->qualifier;
+
+cleanup:
+ PKIX_RETURN(CERTPOLICYQUALIFIER);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.h
new file mode 100644
index 0000000000..4c6c8a21ba
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_certpolicyqualifier.h
@@ -0,0 +1,52 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_certpolicyqualifier.h
+ *
+ * PolicyQualifier Type Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_POLICYQUALIFIER_H
+#define _PKIX_PL_POLICYQUALIFIER_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This structure reflects the contents of the policy qualifier extension as
+ * described in Section 4.2.1.5 of RFC3280.
+ *
+ * PolicyQualifierInfo ::= SEQUENCE {
+ * policyQualifierId PolicyQualifierId,
+ * qualifier ANY DEFINED BY policyQualifierId }
+ *
+ * PolicyQualifierId ::=
+ * OBJECT IDENTIFIER (id-qt-cps | id-qt-unotice)
+ *
+ */
+struct PKIX_PL_CertPolicyQualifierStruct {
+ PKIX_PL_OID *policyQualifierId;
+ PKIX_PL_ByteArray *qualifier;
+};
+
+PKIX_Error *
+pkix_pl_CertPolicyQualifier_Create(
+ PKIX_PL_OID *oid,
+ PKIX_PL_ByteArray *qualifierArray,
+ PKIX_PL_CertPolicyQualifier **pObject,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertPolicyQualifier_RegisterSelf(
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_POLICYQUALIFIER_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c
new file mode 100644
index 0000000000..b83db357ac
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c
@@ -0,0 +1,1068 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_crl.c
+ *
+ * CRL Function Definitions
+ *
+ */
+
+#include "pkix_pl_crl.h"
+#include "certxutl.h"
+
+extern PKIX_PL_HashTable *cachedCrlSigTable;
+
+/* --Private-CRL-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_CRL_GetVersion
+ * DESCRIPTION:
+ *
+ * Retrieves the version of the CRL pointed to by "crl" and stores it at
+ * "pVersion". The version number will either be 0 or 1 (corresponding to
+ * v1 or v2, respectively).
+ *
+ * Version ::= INTEGER { v1(0), v2(1), v3(2) }
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose version is to be stored. Must be non-NULL.
+ * "pVersion"
+ * Address where a version will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRL_GetVersion(
+ PKIX_PL_CRL *crl,
+ PKIX_UInt32 *pVersion,
+ void *plContext)
+{
+ PKIX_UInt32 myVersion;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_GetVersion");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pVersion);
+
+ PKIX_NULLCHECK_ONE(crl->nssSignedCrl->crl.version.data);
+
+ myVersion = *(crl->nssSignedCrl->crl.version.data);
+
+ if (myVersion > 1) {
+ PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1ORV2);
+ }
+
+ *pVersion = myVersion;
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRL_GetCRLNumber (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_GetCRLNumber(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_BigInt **pCrlNumber,
+ void *plContext)
+{
+ PKIX_PL_BigInt *crlNumber = NULL;
+ SECItem nssCrlNumber;
+ PLArenaPool *arena = NULL;
+ SECStatus status;
+ PKIX_UInt32 length = 0;
+ char *bytes = NULL;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCRLNumber");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlNumber);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ if (!crl->crlNumberAbsent && crl->crlNumber == NULL) {
+
+ PKIX_OBJECT_LOCK(crl);
+
+ if (!crl->crlNumberAbsent && crl->crlNumber == NULL) {
+
+ nssCrlNumber.type = 0;
+ nssCrlNumber.len = 0;
+ nssCrlNumber.data = NULL;
+
+ PKIX_CRL_DEBUG("\t\tCalling PORT_NewArena).\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CRL_DEBUG("\t\tCalling CERT_FindCRLNumberExten\n");
+ status = CERT_FindCRLNumberExten
+ (arena, &crl->nssSignedCrl->crl, &nssCrlNumber);
+
+ if (status == SECSuccess) {
+ /* Get data in bytes then convert to bigint */
+ length = nssCrlNumber.len;
+ bytes = (char *)nssCrlNumber.data;
+
+ PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
+ (bytes, length, &crlNumber, plContext),
+ PKIX_BIGINTCREATEWITHBYTESFAILED);
+
+ /* arena release does the job
+ PKIX_CRL_DEBUG("\t\tCalling SECITEM_FreeItem\n");
+ SECITEM_FreeItem(&nssCrlNumber, PKIX_FALSE);
+ */
+ crl->crlNumber = crlNumber;
+
+ } else {
+
+ crl->crlNumberAbsent = PKIX_TRUE;
+ }
+ }
+
+ PKIX_OBJECT_UNLOCK(crl);
+
+ }
+
+ PKIX_INCREF(crl->crlNumber);
+
+ *pCrlNumber = crl->crlNumber;
+
+cleanup:
+
+ if (arena){
+ PKIX_CRL_DEBUG("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_GetSignatureAlgId
+ *
+ * DESCRIPTION:
+ * Retrieves a pointer to the OID that represents the signature algorithm of
+ * the CRL pointed to by "crl" and stores it at "pSignatureAlgId".
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose signature algorithm OID is to be stored.
+ * Must be non-NULL.
+ * "pSignatureAlgId"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRL_GetSignatureAlgId(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_OID **pSignatureAlgId,
+ void *plContext)
+{
+ PKIX_PL_OID *signatureAlgId = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_GetSignatureAlgId");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pSignatureAlgId);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crl->signatureAlgId == NULL){
+ PKIX_OBJECT_LOCK(crl);
+ if (crl->signatureAlgId == NULL){
+ CERTCrl *nssCrl = &(crl->nssSignedCrl->crl);
+ SECAlgorithmID *algorithm = &nssCrl->signatureAlg;
+ SECItem *algBytes = &algorithm->algorithm;
+
+ if (!algBytes->data || !algBytes->len) {
+ PKIX_ERROR(PKIX_OIDBYTESLENGTH0);
+ }
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (algBytes, &signatureAlgId, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ crl->signatureAlgId = signatureAlgId;
+ signatureAlgId = NULL;
+ }
+ PKIX_OBJECT_UNLOCK(crl);
+ }
+ PKIX_INCREF(crl->signatureAlgId);
+ *pSignatureAlgId = crl->signatureAlgId;
+cleanup:
+ PKIX_DECREF(signatureAlgId);
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_GetCRLEntries
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of CRLEntries found in the CRL pointed to
+ * by "crl" and stores it at "pCRLEntries". If there are no CRLEntries,
+ * this functions stores NULL at "pCRLEntries".
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose CRL Entries are to be retrieved. Must be non-NULL.
+ * "pCRLEntries"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRL_GetCRLEntries(
+ PKIX_PL_CRL *crl,
+ PKIX_List **pCrlEntries,
+ void *plContext)
+{
+ PKIX_List *entryList = NULL;
+ CERTCrl *nssCrl = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_GetCRLEntries");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlEntries);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crl->crlEntryList == NULL) {
+
+ PKIX_OBJECT_LOCK(crl);
+
+ if (crl->crlEntryList == NULL){
+
+ nssCrl = &(crl->nssSignedCrl->crl);
+
+ PKIX_CHECK(pkix_pl_CRLEntry_Create
+ (nssCrl->entries, &entryList, plContext),
+ PKIX_CRLENTRYCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (entryList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ crl->crlEntryList = entryList;
+ }
+
+ PKIX_OBJECT_UNLOCK(crl);
+
+ }
+
+ PKIX_INCREF(crl->crlEntryList);
+
+ *pCrlEntries = crl->crlEntryList;
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRL_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CRL *crl = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
+ PKIX_OBJECTNOTCRL);
+
+ crl = (PKIX_PL_CRL*)object;
+
+ PKIX_CRL_DEBUG("\t\tCalling CERT_DestroyCrl\n");
+ if (crl->nssSignedCrl) {
+ CERT_DestroyCrl(crl->nssSignedCrl);
+ }
+ if (crl->adoptedDerCrl) {
+ SECITEM_FreeItem(crl->adoptedDerCrl, PR_TRUE);
+ }
+ crl->nssSignedCrl = NULL;
+ crl->adoptedDerCrl = NULL;
+ crl->crlNumberAbsent = PKIX_FALSE;
+
+ PKIX_DECREF(crl->issuer);
+ PKIX_DECREF(crl->signatureAlgId);
+ PKIX_DECREF(crl->crlNumber);
+ PKIX_DECREF(crl->crlEntryList);
+ PKIX_DECREF(crl->critExtOids);
+ if (crl->derGenName) {
+ SECITEM_FreeItem(crl->derGenName, PR_TRUE);
+ }
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the CRL pointed
+ * to by "crl" and stores it at "pString".
+ *
+ * PARAMETERS
+ * "crl"
+ * Address of CRL whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRL_ToString_Helper(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ char *asciiFormat = NULL;
+ PKIX_UInt32 crlVersion = 0;
+ PKIX_PL_X500Name *crlIssuer = NULL;
+ PKIX_PL_OID *nssSignatureAlgId = NULL;
+ PKIX_PL_BigInt *crlNumber = NULL;
+ PKIX_List *crlEntryList = NULL;
+ PKIX_List *critExtOIDs = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *crlIssuerString = NULL;
+ PKIX_PL_String *lastUpdateString = NULL;
+ PKIX_PL_String *nextUpdateString = NULL;
+ PKIX_PL_String *nssSignatureAlgIdString = NULL;
+ PKIX_PL_String *crlNumberString = NULL;
+ PKIX_PL_String *crlEntryListString = NULL;
+ PKIX_PL_String *critExtOIDsString = NULL;
+ PKIX_PL_String *crlString = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_ToString_Helper");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pString);
+
+ asciiFormat =
+ "[\n"
+ "\tVersion: v%d\n"
+ "\tIssuer: %s\n"
+ "\tUpdate: [Last: %s\n"
+ "\t Next: %s]\n"
+ "\tSignatureAlgId: %s\n"
+ "\tCRL Number : %s\n"
+ "\n"
+ "\tEntry List: %s\n"
+ "\n"
+ "\tCritExtOIDs: %s\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Version */
+ PKIX_CHECK(pkix_pl_CRL_GetVersion(crl, &crlVersion, plContext),
+ PKIX_CRLGETVERSIONFAILED);
+
+ /* Issuer */
+ PKIX_CHECK(PKIX_PL_CRL_GetIssuer(crl, &crlIssuer, plContext),
+ PKIX_CRLGETISSUERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)crlIssuer, &crlIssuerString, plContext),
+ PKIX_X500NAMETOSTRINGFAILED);
+
+ /* This update - No Date object created, use nss data directly */
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&(crl->nssSignedCrl->crl.lastUpdate),
+ &lastUpdateString,
+ plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+
+ /* Next update - No Date object created, use nss data directly */
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&(crl->nssSignedCrl->crl.nextUpdate),
+ &nextUpdateString,
+ plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+
+ /* Signature Algorithm Id */
+ PKIX_CHECK(pkix_pl_CRL_GetSignatureAlgId
+ (crl, &nssSignatureAlgId, plContext),
+ PKIX_CRLGETSIGNATUREALGIDFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)nssSignatureAlgId,
+ &nssSignatureAlgIdString,
+ plContext),
+ PKIX_OIDTOSTRINGFAILED);
+
+ /* CRL Number */
+ PKIX_CHECK(PKIX_PL_CRL_GetCRLNumber
+ (crl, &crlNumber, plContext),
+ PKIX_CRLGETCRLNUMBERFAILED);
+
+ PKIX_TOSTRING(crlNumber, &crlNumberString, plContext,
+ PKIX_BIGINTTOSTRINGFAILED);
+
+ /* CRL Entries */
+ PKIX_CHECK(pkix_pl_CRL_GetCRLEntries(crl, &crlEntryList, plContext),
+ PKIX_CRLGETCRLENTRIESFAILED);
+
+ PKIX_TOSTRING(crlEntryList, &crlEntryListString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* CriticalExtensionOIDs */
+ PKIX_CHECK(PKIX_PL_CRL_GetCriticalExtensionOIDs
+ (crl, &critExtOIDs, plContext),
+ PKIX_CRLGETCRITICALEXTENSIONOIDSFAILED);
+
+ PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&crlString,
+ plContext,
+ formatString,
+ crlVersion + 1,
+ crlIssuerString,
+ lastUpdateString,
+ nextUpdateString,
+ nssSignatureAlgIdString,
+ crlNumberString,
+ crlEntryListString,
+ critExtOIDsString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = crlString;
+
+cleanup:
+
+ PKIX_DECREF(crlIssuer);
+ PKIX_DECREF(nssSignatureAlgId);
+ PKIX_DECREF(crlNumber);
+ PKIX_DECREF(crlEntryList);
+ PKIX_DECREF(critExtOIDs);
+ PKIX_DECREF(crlIssuerString);
+ PKIX_DECREF(lastUpdateString);
+ PKIX_DECREF(nextUpdateString);
+ PKIX_DECREF(nssSignatureAlgIdString);
+ PKIX_DECREF(crlNumberString);
+ PKIX_DECREF(crlEntryListString);
+ PKIX_DECREF(critExtOIDsString);
+ PKIX_DECREF(formatString);
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRL_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *crlString = NULL;
+ PKIX_PL_CRL *crl = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
+ PKIX_OBJECTNOTCRL);
+
+ crl = (PKIX_PL_CRL *) object;
+
+ PKIX_CHECK(pkix_pl_CRL_ToString_Helper(crl, &crlString, plContext),
+ PKIX_CRLTOSTRINGHELPERFAILED);
+
+ *pString = crlString;
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRL_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_UInt32 certHash;
+ SECItem *crlDer = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
+ PKIX_OBJECTNOTCRL);
+
+ crl = (PKIX_PL_CRL *)object;
+ if (crl->adoptedDerCrl) {
+ crlDer = crl->adoptedDerCrl;
+ } else if (crl->nssSignedCrl && crl->nssSignedCrl->derCrl) {
+ crlDer = crl->nssSignedCrl->derCrl;
+ }
+ if (!crlDer || !crlDer->data) {
+ PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER);
+ }
+
+ PKIX_CHECK(pkix_hash(crlDer->data, crlDer->len,
+ &certHash, plContext),
+ PKIX_ERRORINHASH);
+
+ *pHashcode = certHash;
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRL_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CRL *firstCrl = NULL;
+ PKIX_PL_CRL *secondCrl = NULL;
+ SECItem *crlDerOne = NULL, *crlDerTwo = NULL;
+ PKIX_UInt32 secondType;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CRL */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRL_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCRL);
+
+ firstCrl = (PKIX_PL_CRL *)firstObject;
+ secondCrl = (PKIX_PL_CRL *)secondObject;
+
+ /*
+ * Since we know firstObject is a CRL, if both references are
+ * identical, they must be equal
+ */
+ if (firstCrl == secondCrl){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondCrl isn't a CRL, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ ((PKIX_PL_Object *)secondCrl, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CRL_TYPE) goto cleanup;
+
+ if (firstCrl->adoptedDerCrl) {
+ crlDerOne = firstCrl->adoptedDerCrl;
+ } else if (firstCrl->nssSignedCrl && firstCrl->nssSignedCrl->derCrl) {
+ crlDerOne = firstCrl->nssSignedCrl->derCrl;
+ }
+
+ if (secondCrl->adoptedDerCrl) {
+ crlDerTwo = secondCrl->adoptedDerCrl;
+ } else if (secondCrl->nssSignedCrl && secondCrl->nssSignedCrl->derCrl) {
+ crlDerTwo = secondCrl->nssSignedCrl->derCrl;
+ }
+
+ if (SECITEM_CompareItem(crlDerOne, crlDerTwo) == SECEqual) {
+ *pResult = PKIX_TRUE;
+ }
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_CRL_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ *
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CRL_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry *entry = &systemClasses[PKIX_CRL_TYPE];
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_RegisterSelf");
+
+ entry->description = "CRL";
+ entry->typeObjectSize = sizeof(PKIX_PL_CRL);
+ entry->destructor = pkix_pl_CRL_Destroy;
+ entry->equalsFunction = pkix_pl_CRL_Equals;
+ entry->hashcodeFunction = pkix_pl_CRL_Hashcode;
+ entry->toStringFunction = pkix_pl_CRL_ToString;
+ entry->duplicateFunction = pkix_duplicateImmutable;
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRL_VerifyUpdateTime (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_VerifyUpdateTime(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_Date *date,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PRTime timeToCheck;
+ PRTime nextUpdate;
+ PRTime lastUpdate;
+ SECStatus status;
+ CERTCrl *nssCrl = NULL;
+ SECItem *nextUpdateDer = NULL;
+ PKIX_Boolean haveNextUpdate = PR_FALSE;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifyUpdateTime");
+ PKIX_NULLCHECK_FOUR(crl, crl->nssSignedCrl, date, pResult);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ nssCrl = &(crl->nssSignedCrl->crl);
+ timeToCheck = date->nssTime;
+
+ /* nextUpdate can be NULL. Checking before using it */
+ nextUpdateDer = &nssCrl->nextUpdate;
+ if (nextUpdateDer->data && nextUpdateDer->len) {
+ haveNextUpdate = PR_TRUE;
+ status = DER_DecodeTimeChoice(&nextUpdate, nextUpdateDer);
+ if (status != SECSuccess) {
+ PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORNEXTUPDATEFAILED);
+ }
+ }
+
+ status = DER_DecodeTimeChoice(&lastUpdate, &(nssCrl->lastUpdate));
+ if (status != SECSuccess) {
+ PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORLASTUPDATEFAILED);
+ }
+
+ if (!haveNextUpdate || nextUpdate < timeToCheck) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ if (lastUpdate <= timeToCheck) {
+ *pResult = PKIX_TRUE;
+ } else {
+ *pResult = PKIX_FALSE;
+ }
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_CreateWithSignedCRL
+ * DESCRIPTION:
+ *
+ * Creates a new CRL using the CERTSignedCrl pointed to by "nssSignedCrl"
+ * and stores it at "pCRL". If the decoding of the CERTSignedCrl fails,
+ * a PKIX_Error is returned.
+ *
+ * PARAMETERS:
+ * "nssSignedCrl"
+ * Address of CERTSignedCrl. Must be non-NULL.
+ * "adoptedDerCrl"
+ * SECItem ponter that if not NULL is indicating that memory used
+ * for der should be adopted by crl that is about to be created.
+ * "pCRL"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CRL_CreateWithSignedCRL(
+ CERTSignedCrl *nssSignedCrl,
+ SECItem *adoptedDerCrl,
+ SECItem *derGenName,
+ PKIX_PL_CRL **pCrl,
+ void *plContext)
+{
+ PKIX_PL_CRL *crl = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_CreateWithSignedCRL");
+ PKIX_NULLCHECK_ONE(pCrl);
+
+ /* create a PKIX_PL_CRL object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CRL_TYPE,
+ sizeof (PKIX_PL_CRL),
+ (PKIX_PL_Object **)&crl,
+ plContext),
+ PKIX_COULDNOTCREATECRLOBJECT);
+
+ /* populate the nssSignedCrl field */
+ crl->nssSignedCrl = nssSignedCrl;
+ crl->adoptedDerCrl = adoptedDerCrl;
+ crl->issuer = NULL;
+ crl->signatureAlgId = NULL;
+ crl->crlNumber = NULL;
+ crl->crlNumberAbsent = PKIX_FALSE;
+ crl->crlEntryList = NULL;
+ crl->critExtOids = NULL;
+ if (derGenName) {
+ crl->derGenName =
+ SECITEM_DupItem(derGenName);
+ if (!crl->derGenName) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ }
+
+ *pCrl = crl;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(crl);
+ }
+
+ PKIX_RETURN(CRL);
+}
+
+/* --Public-CRL-Functions------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_CRL_Create (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_Create(
+ PKIX_PL_ByteArray *byteArray,
+ PKIX_PL_CRL **pCrl,
+ void *plContext)
+{
+ CERTSignedCrl *nssSignedCrl = NULL;
+ SECItem derItem, *derCrl = NULL;
+ PKIX_PL_CRL *crl = NULL;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_Create");
+ PKIX_NULLCHECK_TWO(byteArray, pCrl);
+
+ if (byteArray->length == 0){
+ PKIX_ERROR(PKIX_ZEROLENGTHBYTEARRAYFORCRLENCODING);
+ }
+ derItem.type = siBuffer;
+ derItem.data = byteArray->array;
+ derItem.len = byteArray->length;
+ derCrl = SECITEM_DupItem(&derItem);
+ if (!derCrl) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ nssSignedCrl =
+ CERT_DecodeDERCrlWithFlags(NULL, derCrl, SEC_CRL_TYPE,
+ CRL_DECODE_DONT_COPY_DER |
+ CRL_DECODE_SKIP_ENTRIES);
+ if (!nssSignedCrl) {
+ PKIX_ERROR(PKIX_CERTDECODEDERCRLFAILED);
+ }
+ PKIX_CHECK(
+ pkix_pl_CRL_CreateWithSignedCRL(nssSignedCrl, derCrl, NULL,
+ &crl, plContext),
+ PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
+ nssSignedCrl = NULL;
+ derCrl = NULL;
+ *pCrl = crl;
+
+cleanup:
+ if (derCrl) {
+ SECITEM_FreeItem(derCrl, PR_TRUE);
+ }
+ if (nssSignedCrl) {
+ SEC_DestroyCrl(nssSignedCrl);
+ }
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRL_GetIssuer (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_GetIssuer(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_X500Name **pCRLIssuer,
+ void *plContext)
+{
+ PKIX_PL_String *crlString = NULL;
+ PKIX_PL_X500Name *issuer = NULL;
+ SECItem *derIssuerName = NULL;
+ CERTName *issuerName = NULL;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_GetIssuer");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCRLIssuer);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crl->issuer == NULL){
+
+ PKIX_OBJECT_LOCK(crl);
+
+ if (crl->issuer == NULL) {
+
+ issuerName = &crl->nssSignedCrl->crl.name;
+ derIssuerName = &crl->nssSignedCrl->crl.derName;
+
+ PKIX_CHECK(
+ PKIX_PL_X500Name_CreateFromCERTName(derIssuerName,
+ issuerName,
+ &issuer,
+ plContext),
+ PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ crl->issuer = issuer;
+ }
+
+ PKIX_OBJECT_UNLOCK(crl);
+
+ }
+
+ PKIX_INCREF(crl->issuer);
+
+ *pCRLIssuer = crl->issuer;
+
+cleanup:
+
+ PKIX_DECREF(crlString);
+
+ PKIX_RETURN(CRL);
+}
+
+
+/*
+ * FUNCTION: PKIX_PL_CRL_GetCriticalExtensionOIDs
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_GetCriticalExtensionOIDs(
+ PKIX_PL_CRL *crl,
+ PKIX_List **pExtensions, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_List *oidsList = NULL;
+ CERTCertExtension **extensions = NULL;
+ CERTCrl *nssSignedCrl = NULL;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCriticalExtensionOIDs");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pExtensions);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crl->critExtOids == NULL) {
+
+ PKIX_OBJECT_LOCK(crl);
+
+ nssSignedCrl = &(crl->nssSignedCrl->crl);
+ extensions = nssSignedCrl->extensions;
+
+ if (crl->critExtOids == NULL) {
+
+ PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
+ (extensions, &oidsList, plContext),
+ PKIX_GETCRITICALEXTENSIONOIDSFAILED);
+
+ crl->critExtOids = oidsList;
+ }
+
+ PKIX_OBJECT_UNLOCK(crl);
+
+ }
+
+ /* We should return a copy of the List since this list changes */
+ PKIX_DUPLICATE(crl->critExtOids, pExtensions, plContext,
+ PKIX_OBJECTDUPLICATELISTFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRL_VerifySignature (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_VerifySignature(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_PublicKey *pubKey,
+ void *plContext)
+{
+ PKIX_PL_CRL *cachedCrl = NULL;
+ PKIX_Error *verifySig = NULL;
+ PKIX_Error *cachedSig = NULL;
+ PKIX_Boolean crlEqual = PKIX_FALSE;
+ PKIX_Boolean crlInHash= PKIX_FALSE;
+ CERTSignedCrl *nssSignedCrl = NULL;
+ SECKEYPublicKey *nssPubKey = NULL;
+ CERTSignedData *tbsCrl = NULL;
+ void* wincx = NULL;
+ SECStatus status;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifySignature");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pubKey);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ verifySig = PKIX_PL_HashTable_Lookup
+ (cachedCrlSigTable,
+ (PKIX_PL_Object *) pubKey,
+ (PKIX_PL_Object **) &cachedCrl,
+ plContext);
+
+ if (cachedCrl != NULL && verifySig == NULL) {
+ /* Cached Signature Table lookup succeed */
+ PKIX_EQUALS(crl, cachedCrl, &crlEqual, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+ if (crlEqual == PKIX_TRUE) {
+ goto cleanup;
+ }
+ /* Different PubKey may hash to same value, skip add */
+ crlInHash = PKIX_TRUE;
+ }
+
+ nssSignedCrl = crl->nssSignedCrl;
+ tbsCrl = &nssSignedCrl->signatureWrap;
+
+ PKIX_CRL_DEBUG("\t\tCalling SECKEY_ExtractPublicKey\n");
+ nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI);
+ if (!nssPubKey){
+ PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED);
+ }
+
+ PKIX_CHECK(pkix_pl_NssContext_GetWincx
+ ((PKIX_PL_NssContext *)plContext, &wincx),
+ PKIX_NSSCONTEXTGETWINCXFAILED);
+
+ PKIX_CRL_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey\n");
+ status = CERT_VerifySignedDataWithPublicKey(tbsCrl, nssPubKey, wincx);
+
+ if (status != SECSuccess) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY);
+ }
+
+ if (crlInHash == PKIX_FALSE) {
+ cachedSig = PKIX_PL_HashTable_Add
+ (cachedCrlSigTable,
+ (PKIX_PL_Object *) pubKey,
+ (PKIX_PL_Object *) crl,
+ plContext);
+
+ if (cachedSig != NULL) {
+ PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n");
+ }
+ }
+
+cleanup:
+
+ if (nssPubKey){
+ PKIX_CRL_DEBUG("\t\tCalling SECKEY_DestroyPublicKey\n");
+ SECKEY_DestroyPublicKey(nssPubKey);
+ nssPubKey = NULL;
+ }
+
+ PKIX_DECREF(cachedCrl);
+ PKIX_DECREF(verifySig);
+ PKIX_DECREF(cachedSig);
+
+ PKIX_RETURN(CRL);
+}
+
+PKIX_Error*
+PKIX_PL_CRL_ReleaseDerCrl(PKIX_PL_CRL *crl,
+ SECItem **derCrl,
+ void *plContext)
+{
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_ReleaseDerCrl");
+ *derCrl = crl->adoptedDerCrl;
+ crl->adoptedDerCrl = NULL;
+
+ PKIX_RETURN(CRL);
+}
+
+PKIX_Error*
+PKIX_PL_CRL_AdoptDerCrl(PKIX_PL_CRL *crl,
+ SECItem *derCrl,
+ void *plContext)
+{
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_AquireDerCrl");
+ if (crl->adoptedDerCrl) {
+ PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER);
+ }
+ crl->adoptedDerCrl = derCrl;
+cleanup:
+ PKIX_RETURN(CRL);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.h
new file mode 100644
index 0000000000..a45059ea0d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.h
@@ -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/. */
+/*
+ * pkix_pl_crl.h
+ *
+ * CRL Object Type Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_CRL_H
+#define _PKIX_PL_CRL_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_CRLStruct {
+ CERTSignedCrl *nssSignedCrl;
+ PKIX_PL_X500Name *issuer;
+ PKIX_PL_OID *signatureAlgId;
+ PKIX_PL_BigInt *crlNumber;
+ PKIX_Boolean crlNumberAbsent;
+ PKIX_List *crlEntryList; /* list of PKIX_PL_CRLEntry */
+ PKIX_List *critExtOids;
+ SECItem *adoptedDerCrl;
+ SECItem *derGenName; /* der of general name which was used
+ * to download the crl. */
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_CRL_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_CRL_CreateWithSignedCRL(CERTSignedCrl *nssSignedCrl,
+ SECItem *derCrl,
+ SECItem *derGenName,
+ PKIX_PL_CRL **pCrl,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_CRL_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.c
new file mode 100644
index 0000000000..4f29de2849
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.c
@@ -0,0 +1,151 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_crldp.c
+ *
+ * Crl DP Object Functions
+ *
+ */
+
+#include "pkix_pl_crldp.h"
+
+static PKIX_Error *
+pkix_pl_CrlDp_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ pkix_pl_CrlDp *crldp = NULL;
+
+ PKIX_ENTER(CRLCHECKER, "pkix_CrlDp_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Check that this object is a default CRL checker state */
+ PKIX_CHECK(
+ pkix_CheckType(object, PKIX_CRLDP_TYPE, plContext),
+ PKIX_OBJECTNOTCRLCHECKER);
+
+ crldp = (pkix_pl_CrlDp *)object;
+ if (crldp->distPointType == relativeDistinguishedName) {
+ CERT_DestroyName(crldp->name.issuerName);
+ crldp->name.issuerName = NULL;
+ }
+ crldp->nssdp = NULL;
+cleanup:
+ PKIX_RETURN(CRLCHECKER);
+}
+
+/*
+ * FUNCTION: pkix_pl_CrlDp_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_CRLDP_TYPE and its related functions
+ * with systemClasses[]
+ *
+ * THREAD SAFETY:
+ * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CrlDp_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry* entry = &systemClasses[PKIX_CRLDP_TYPE];
+
+ PKIX_ENTER(CRLCHECKER, "pkix_CrlDp_RegisterSelf");
+
+ entry->description = "CrlDistPoint";
+ entry->typeObjectSize = sizeof(pkix_pl_CrlDp);
+ entry->destructor = pkix_pl_CrlDp_Destroy;
+ entry->duplicateFunction = pkix_duplicateImmutable;
+
+ PKIX_RETURN(CRLCHECKER);
+}
+
+
+
+PKIX_Error *
+pkix_pl_CrlDp_Create(
+ const CRLDistributionPoint *dp,
+ const CERTName *certIssuerName,
+ pkix_pl_CrlDp **pPkixDP,
+ void *plContext)
+{
+ PLArenaPool *rdnArena = NULL;
+ CERTName *issuerNameCopy = NULL;
+ pkix_pl_CrlDp *dpl = NULL;
+
+ /* Need to save the following info to update crl cache:
+ * - reasons if partitioned(but can not return revocation check
+ * success if not all crl are downloaded)
+ * - issuer name if different from issuer of the cert
+ * - url to upload a crl if needed.
+ * */
+ PKIX_ENTER(CRLDP, "pkix_pl_CrlDp_Create");
+ PKIX_NULLCHECK_ONE(dp);
+
+ PKIX_CHECK(
+ PKIX_PL_Object_Alloc(PKIX_CRLDP_TYPE,
+ sizeof (pkix_pl_CrlDp),
+ (PKIX_PL_Object **)&dpl,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ dpl->nssdp = dp;
+ dpl->isPartitionedByReasonCode = PKIX_FALSE;
+ if (dp->reasons.data) {
+ dpl->isPartitionedByReasonCode = PKIX_TRUE;
+ }
+ if (dp->distPointType == generalName) {
+ dpl->distPointType = generalName;
+ dpl->name.fullName = dp->distPoint.fullName;
+ } else {
+ SECStatus rv;
+ const CERTName *issuerName = NULL;
+ const CERTRDN *relName = &dp->distPoint.relativeName;
+
+ if (dp->crlIssuer) {
+ if (dp->crlIssuer->l.next) {
+ /* Violate RFC 5280: in this case crlIssuer
+ * should have only one name and should be
+ * a distinguish name. */
+ PKIX_ERROR(PKIX_NOTCONFORMINGCRLDP);
+ }
+ issuerName = &dp->crlIssuer->name.directoryName;
+ } else {
+ issuerName = certIssuerName;
+ }
+ rdnArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!rdnArena) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+ issuerNameCopy = (CERTName *)PORT_ArenaZNew(rdnArena, CERTName);
+ if (!issuerNameCopy) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ rv = CERT_CopyName(rdnArena, issuerNameCopy, (CERTName*)issuerName);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ rv = CERT_AddRDN(issuerNameCopy, (CERTRDN*)relName);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ dpl->distPointType = relativeDistinguishedName;
+ dpl->name.issuerName = issuerNameCopy;
+ rdnArena = NULL;
+ }
+ *pPkixDP = dpl;
+ dpl = NULL;
+
+cleanup:
+ if (rdnArena) {
+ PORT_FreeArena(rdnArena, PR_FALSE);
+ }
+ PKIX_DECREF(dpl);
+
+ PKIX_RETURN(CRLDP);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.h
new file mode 100644
index 0000000000..49cd9d2cdf
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crldp.h
@@ -0,0 +1,53 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_crldp.h
+ *
+ * Crp DP Object Definitions
+ *
+ */
+#include "pkix_pl_common.h"
+
+#ifndef _PKIX_PL_CRLDP_H
+#define _PKIX_PL_CRLDP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* CRLDP object can not be used without holding a reference
+ * to the pkix certificate they belong to. The memory for dp der
+ * object is allocated on nssCert certificate - a member of
+ * PKIX_PL_Cert struct. */
+typedef struct pkix_pl_CrlDpStruct {
+ /* reference to decoded crldp that allocated on nssCert arena. */
+ const CRLDistributionPoint *nssdp;
+ DistributionPointTypes distPointType;
+ union {
+ CERTGeneralName *fullName;
+ /* if dp is a relative name, the issuerName is a merged value
+ * of crlIssuer and a relative name. Must be destroyed by CrlDp
+ * destructor. */
+ CERTName *issuerName;
+ } name;
+ PKIX_Boolean isPartitionedByReasonCode;
+} pkix_pl_CrlDp;
+
+
+PKIX_Error *
+pkix_pl_CrlDp_RegisterSelf(void *plContext);
+
+/* Parses CRLDistributionPoint structure and creaetes
+ * pkix_pl_CrlDp object. */
+PKIX_Error *
+pkix_pl_CrlDp_Create(const CRLDistributionPoint *dp,
+ const CERTName *certIssuerName,
+ pkix_pl_CrlDp **pPkixDP,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_CRLDP_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c
new file mode 100644
index 0000000000..e2b3e02688
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c
@@ -0,0 +1,880 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_crlentry.c
+ *
+ * CRLENTRY Function Definitions
+ *
+ */
+
+#include "pkix_pl_crlentry.h"
+
+/* --Private-CRLEntry-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CRLEntry *crlEntry = NULL;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
+ PKIX_OBJECTNOTCRLENTRY);
+
+ crlEntry = (PKIX_PL_CRLEntry*)object;
+
+ /* crlEntry->nssCrlEntry is freed by NSS when freeing CRL */
+ crlEntry->userReasonCode = 0;
+ crlEntry->userReasonCodeAbsent = PKIX_FALSE;
+ crlEntry->nssCrlEntry = NULL;
+ PKIX_DECREF(crlEntry->serialNumber);
+ PKIX_DECREF(crlEntry->critExtOids);
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_ToString_Helper
+ *
+ * DESCRIPTION:
+ * Helper function that creates a string representation of the CRLEntry
+ * pointed to by "crlEntry" and stores it at "pString".
+ *
+ * PARAMETERS
+ * "crlEntry"
+ * Address of CRLEntry whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLEntry Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CRLEntry_ToString_Helper(
+ PKIX_PL_CRLEntry *crlEntry,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ char *asciiFormat = NULL;
+ PKIX_List *critExtOIDs = NULL;
+ PKIX_PL_String *crlEntryString = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *crlSerialNumberString = NULL;
+ PKIX_PL_String *crlRevocationDateString = NULL;
+ PKIX_PL_String *critExtOIDsString = NULL;
+ PKIX_Int32 reasonCode = 0;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString_Helper");
+ PKIX_NULLCHECK_FOUR
+ (crlEntry,
+ crlEntry->serialNumber,
+ crlEntry->nssCrlEntry,
+ pString);
+
+ asciiFormat =
+ "\n\t[\n"
+ "\tSerialNumber: %s\n"
+ "\tReasonCode: %d\n"
+ "\tRevocationDate: %s\n"
+ "\tCritExtOIDs: %s\n"
+ "\t]\n\t";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* SerialNumber */
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)crlEntry->serialNumber,
+ &crlSerialNumberString,
+ plContext),
+ PKIX_BIGINTTOSTRINGHELPERFAILED);
+
+ /* RevocationDate - No Date object created, use nss data directly */
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&(crlEntry->nssCrlEntry->revocationDate),
+ &crlRevocationDateString,
+ plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+
+ /* CriticalExtensionOIDs */
+ PKIX_CHECK(PKIX_PL_CRLEntry_GetCriticalExtensionOIDs
+ (crlEntry, &critExtOIDs, plContext),
+ PKIX_CRLENTRYGETCRITICALEXTENSIONOIDSFAILED);
+
+ PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* Revocation Reason Code */
+ PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode
+ (crlEntry, &reasonCode, plContext),
+ PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&crlEntryString,
+ plContext,
+ formatString,
+ crlSerialNumberString,
+ reasonCode,
+ crlRevocationDateString,
+ critExtOIDsString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = crlEntryString;
+
+cleanup:
+
+ PKIX_DECREF(critExtOIDs);
+ PKIX_DECREF(crlSerialNumberString);
+ PKIX_DECREF(crlRevocationDateString);
+ PKIX_DECREF(critExtOIDsString);
+ PKIX_DECREF(formatString);
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *crlEntryString = NULL;
+ PKIX_PL_CRLEntry *crlEntry = NULL;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
+ PKIX_OBJECTNOTCRLENTRY);
+
+ crlEntry = (PKIX_PL_CRLEntry *) object;
+
+ PKIX_CHECK(pkix_pl_CRLEntry_ToString_Helper
+ (crlEntry, &crlEntryString, plContext),
+ PKIX_CRLENTRYTOSTRINGHELPERFAILED);
+
+ *pString = crlEntryString;
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_Extensions_Hashcode
+ * DESCRIPTION:
+ *
+ * For each CRL Entry extension stored at NSS structure CERTCertExtension,
+ * get its derbyte data and do the hash.
+ *
+ * PARAMETERS
+ * "extensions"
+ * Address of arrray of CERTCertExtension whose hash value is desired.
+ * Must be non-NULL.
+ * "pHashValue"
+ * Address where the final hash value is returned. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditional Thread Safe
+ * Though the value of extensions once created is not supposed to change,
+ * it may be de-allocated while we are accessing it. But since we are
+ * validating the object, it is unlikely we or someone is de-allocating
+ * at the moment.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OID Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_Extensions_Hashcode(
+ CERTCertExtension **extensions,
+ PKIX_UInt32 *pHashValue,
+ void *plContext)
+{
+ CERTCertExtension *extension = NULL;
+ PLArenaPool *arena = NULL;
+ PKIX_UInt32 extHash = 0;
+ PKIX_UInt32 hashValue = 0;
+ SECItem *derBytes = NULL;
+ SECItem *resultSecItem = NULL;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Hashcode");
+ PKIX_NULLCHECK_TWO(extensions, pHashValue);
+
+ if (extensions) {
+
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ while (*extensions) {
+
+ extension = *extensions++;
+
+ PKIX_NULLCHECK_ONE(extension);
+
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
+ derBytes = PORT_ArenaZNew(arena, SECItem);
+ if (derBytes == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ PKIX_CRLENTRY_DEBUG
+ ("\t\tCalling SEC_ASN1EncodeItem\n");
+ resultSecItem = SEC_ASN1EncodeItem
+ (arena,
+ derBytes,
+ extension,
+ CERT_CertExtensionTemplate);
+
+ if (resultSecItem == NULL){
+ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
+ }
+
+ PKIX_CHECK(pkix_hash
+ (derBytes->data,
+ derBytes->len,
+ &extHash,
+ plContext),
+ PKIX_HASHFAILED);
+
+ hashValue += (extHash << 7);
+
+ }
+ }
+
+ *pHashValue = hashValue;
+
+cleanup:
+
+ if (arena){
+ /* Note that freeing the arena also frees derBytes */
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ arena = NULL;
+ }
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ SECItem *nssDate = NULL;
+ PKIX_PL_CRLEntry *crlEntry = NULL;
+ PKIX_UInt32 crlEntryHash;
+ PKIX_UInt32 hashValue;
+ PKIX_Int32 reasonCode = 0;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
+ PKIX_OBJECTNOTCRLENTRY);
+
+ crlEntry = (PKIX_PL_CRLEntry *)object;
+
+ PKIX_NULLCHECK_ONE(crlEntry->nssCrlEntry);
+ nssDate = &(crlEntry->nssCrlEntry->revocationDate);
+
+ PKIX_NULLCHECK_ONE(nssDate->data);
+
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)nssDate->data,
+ nssDate->len,
+ &crlEntryHash,
+ plContext),
+ PKIX_ERRORGETTINGHASHCODE);
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)crlEntry->serialNumber,
+ &hashValue,
+ plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ crlEntryHash += (hashValue << 7);
+
+ hashValue = 0;
+
+ if (crlEntry->nssCrlEntry->extensions) {
+
+ PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Hashcode
+ (crlEntry->nssCrlEntry->extensions, &hashValue, plContext),
+ PKIX_CRLENTRYEXTENSIONSHASHCODEFAILED);
+ }
+
+ crlEntryHash += (hashValue << 7);
+
+ PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode
+ (crlEntry, &reasonCode, plContext),
+ PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED);
+
+ crlEntryHash += (reasonCode + 777) << 3;
+
+ *pHashcode = crlEntryHash;
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLENTRY_Extensions_Equals
+ * DESCRIPTION:
+ *
+ * Compare each extension's DERbyte data in "firstExtensions" with extension
+ * in "secondExtensions" in sequential order and store the result in
+ * "pResult".
+ *
+ * PARAMETERS
+ * "firstExtensions"
+ * Address of first NSS structure CERTCertExtension to be compared.
+ * Must be non-NULL.
+ * "secondExtensions"
+ * Address of second NSS structure CERTCertExtension to be compared.
+ * Must be non-NULL.
+ * "pResult"
+ * Address where the comparison result is returned. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * Though the value of extensions once created is not supposed to change,
+ * it may be de-allocated while we are accessing it. But since we are
+ * validating the object, it is unlikely we or someone is de-allocating
+ * at the moment.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OID Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_Extensions_Equals(
+ CERTCertExtension **extensions1,
+ CERTCertExtension **extensions2,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ CERTCertExtension **firstExtensions;
+ CERTCertExtension **secondExtensions;
+ CERTCertExtension *firstExtension = NULL;
+ CERTCertExtension *secondExtension = NULL;
+ PLArenaPool *arena = NULL;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+ SECItem *firstDerBytes = NULL;
+ SECItem *secondDerBytes = NULL;
+ SECItem *firstResultSecItem = NULL;
+ SECItem *secondResultSecItem = NULL;
+ PKIX_UInt32 firstNumExt = 0;
+ PKIX_UInt32 secondNumExt = 0;
+ SECComparison secResult;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Equals");
+ PKIX_NULLCHECK_THREE(extensions1, extensions2, pResult);
+
+ firstExtensions = extensions1;
+ secondExtensions = extensions2;
+
+ if (firstExtensions) {
+ while (*firstExtensions) {
+ firstExtension = *firstExtensions++;
+ firstNumExt++;
+ }
+ }
+
+ if (secondExtensions) {
+ while (*secondExtensions) {
+ secondExtension = *secondExtensions++;
+ secondNumExt++;
+ }
+ }
+
+ if (firstNumExt != secondNumExt) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ if (firstNumExt == 0 && secondNumExt == 0) {
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /* now have equal number, but non-zero extension items to compare */
+
+ firstExtensions = extensions1;
+ secondExtensions = extensions2;
+
+ cmpResult = PKIX_TRUE;
+
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE*2);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ while (firstNumExt--) {
+
+ firstExtension = *firstExtensions++;
+ secondExtension = *secondExtensions++;
+
+ PKIX_NULLCHECK_TWO(firstExtension, secondExtension);
+
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
+ firstDerBytes = PORT_ArenaZNew(arena, SECItem);
+ if (firstDerBytes == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
+ secondDerBytes = PORT_ArenaZNew(arena, SECItem);
+ if (secondDerBytes == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ PKIX_CRLENTRY_DEBUG
+ ("\t\tCalling SEC_ASN1EncodeItem\n");
+ firstResultSecItem = SEC_ASN1EncodeItem
+ (arena,
+ firstDerBytes,
+ firstExtension,
+ CERT_CertExtensionTemplate);
+
+ if (firstResultSecItem == NULL){
+ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
+ }
+
+ PKIX_CRLENTRY_DEBUG
+ ("\t\tCalling SEC_ASN1EncodeItem\n");
+ secondResultSecItem = SEC_ASN1EncodeItem
+ (arena,
+ secondDerBytes,
+ secondExtension,
+ CERT_CertExtensionTemplate);
+
+ if (secondResultSecItem == NULL){
+ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
+ }
+
+ PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n");
+ secResult = SECITEM_CompareItem
+ (firstResultSecItem, secondResultSecItem);
+
+ if (secResult != SECEqual) {
+ cmpResult = PKIX_FALSE;
+ break;
+ }
+
+ }
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ if (arena){
+ /* Note that freeing the arena also frees derBytes */
+ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ arena = NULL;
+ }
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CRLEntry *firstCrlEntry = NULL;
+ PKIX_PL_CRLEntry *secondCrlEntry = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CRLEntry */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRLENTRY_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCRLENTRY);
+
+ firstCrlEntry = (PKIX_PL_CRLEntry *)firstObject;
+ secondCrlEntry = (PKIX_PL_CRLEntry *)secondObject;
+
+ PKIX_NULLCHECK_TWO
+ (firstCrlEntry->nssCrlEntry, secondCrlEntry->nssCrlEntry);
+
+ /*
+ * Since we know firstObject is a CRLEntry, if both references are
+ * identical, they must be equal
+ */
+ if (firstCrlEntry == secondCrlEntry){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondCrlEntry isn't a CRL Entry, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ ((PKIX_PL_Object *)secondCrlEntry, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CRLENTRY_TYPE) goto cleanup;
+
+ /* Compare userSerialNumber */
+ PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n");
+ if (SECITEM_CompareItem(
+ &(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry->serialNumber),
+ &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry->serialNumber))
+ != SECEqual) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ /* Compare revocationDate */
+ PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n");
+ if (SECITEM_CompareItem
+ (&(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry->
+ revocationDate),
+ &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry->
+ revocationDate))
+ != SECEqual) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ /* Compare Critical Extension List */
+ PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Equals
+ (firstCrlEntry->nssCrlEntry->extensions,
+ secondCrlEntry->nssCrlEntry->extensions,
+ &cmpResult,
+ plContext),
+ PKIX_CRLENTRYEXTENSIONSEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE){
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ cmpResult = (firstCrlEntry->userReasonCode ==
+ secondCrlEntry->userReasonCode);
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CRLEntry_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CRLEntry_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_RegisterSelf");
+
+ entry.description = "CRLEntry";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_CRLEntry);
+ entry.destructor = pkix_pl_CRLEntry_Destroy;
+ entry.equalsFunction = pkix_pl_CRLEntry_Equals;
+ entry.hashcodeFunction = pkix_pl_CRLEntry_Hashcode;
+ entry.toStringFunction = pkix_pl_CRLEntry_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CRLENTRY_TYPE] = entry;
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_CreateEntry
+ * DESCRIPTION:
+ *
+ * Creates a new CRLEntry using the CertCrlEntry pointed to by "nssCrlEntry"
+ * and stores it at "pCrlEntry". Once created, a CRLEntry is immutable.
+ *
+ * revokedCertificates SEQUENCE OF SEQUENCE {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate Time,
+ * crlEntryExtensions Extensions OPTIONAL
+ * -- if present, MUST be v2
+ *
+ * PARAMETERS:
+ * "nssCrlEntry"
+ * Address of CERTCrlEntry representing an NSS CRL entry.
+ * Must be non-NULL.
+ * "pCrlEntry"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLEntry Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRLEntry_CreateEntry(
+ CERTCrlEntry *nssCrlEntry, /* entry data to be created from */
+ PKIX_PL_CRLEntry **pCrlEntry,
+ void *plContext)
+{
+ PKIX_PL_CRLEntry *crlEntry = NULL;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_CreateEntry");
+ PKIX_NULLCHECK_TWO(nssCrlEntry, pCrlEntry);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CRLENTRY_TYPE,
+ sizeof (PKIX_PL_CRLEntry),
+ (PKIX_PL_Object **)&crlEntry,
+ plContext),
+ PKIX_COULDNOTCREATECRLENTRYOBJECT);
+
+ crlEntry->nssCrlEntry = nssCrlEntry;
+ crlEntry->serialNumber = NULL;
+ crlEntry->critExtOids = NULL;
+ crlEntry->userReasonCode = 0;
+ crlEntry->userReasonCodeAbsent = PKIX_FALSE;
+
+ *pCrlEntry = crlEntry;
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRLEntry_Create
+ * DESCRIPTION:
+ *
+ * Creates a List of CRLEntries using the array of CERTCrlEntries pointed to
+ * by "nssCrlEntries" and stores it at "pCrlEntryList". If "nssCrlEntries" is
+ * NULL, this function stores an empty List at "pCrlEntryList".
+ * }
+ * PARAMETERS:
+ * "nssCrlEntries"
+ * Address of array of CERTCrlEntries representing NSS CRL entries.
+ * Can be NULL if CRL has no NSS CRL entries.
+ * "pCrlEntryList"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRLEntry Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CRLEntry_Create(
+ CERTCrlEntry **nssCrlEntries, /* head of entry list */
+ PKIX_List **pCrlEntryList,
+ void *plContext)
+{
+ PKIX_List *entryList = NULL;
+ PKIX_PL_CRLEntry *crlEntry = NULL;
+ CERTCrlEntry **entries = NULL;
+ SECItem serialNumberItem;
+ PKIX_PL_BigInt *serialNumber;
+ char *bytes = NULL;
+ PKIX_UInt32 length;
+
+ PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Create");
+ PKIX_NULLCHECK_ONE(pCrlEntryList);
+
+ entries = nssCrlEntries;
+
+ PKIX_CHECK(PKIX_List_Create(&entryList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ if (entries) {
+ while (*entries){
+ PKIX_CHECK(pkix_pl_CRLEntry_CreateEntry
+ (*entries, &crlEntry, plContext),
+ PKIX_COULDNOTCREATECRLENTRYOBJECT);
+
+ /* Get Serial Number */
+ serialNumberItem = (*entries)->serialNumber;
+ length = serialNumberItem.len;
+ bytes = (char *)serialNumberItem.data;
+
+ PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
+ (bytes, length, &serialNumber, plContext),
+ PKIX_BIGINTCREATEWITHBYTESFAILED);
+
+ crlEntry->serialNumber = serialNumber;
+ crlEntry->nssCrlEntry = *entries;
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (entryList, (PKIX_PL_Object *)crlEntry, plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(crlEntry);
+
+ entries++;
+ }
+ }
+
+ *pCrlEntryList = entryList;
+
+cleanup:
+ PKIX_DECREF(crlEntry);
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(entryList);
+ }
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/* --Public-CRLENTRY-Functions------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_CRLEntry_GetCRLEntryReasonCode
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRLEntry_GetCRLEntryReasonCode (
+ PKIX_PL_CRLEntry *crlEntry,
+ PKIX_Int32 *pReason,
+ void *plContext)
+{
+ SECStatus status;
+ CERTCRLEntryReasonCode nssReasonCode;
+
+ PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCRLEntryReasonCode");
+ PKIX_NULLCHECK_TWO(crlEntry, pReason);
+
+ if (!crlEntry->userReasonCodeAbsent && crlEntry->userReasonCode == 0) {
+
+ PKIX_OBJECT_LOCK(crlEntry);
+
+ if (!crlEntry->userReasonCodeAbsent &&
+ crlEntry->userReasonCode == 0) {
+
+ /* reason code has not been cached in */
+ PKIX_CRLENTRY_DEBUG("\t\tCERT_FindCRLEntryReasonExten.\n");
+ status = CERT_FindCRLEntryReasonExten
+ (crlEntry->nssCrlEntry, &nssReasonCode);
+
+ if (status == SECSuccess) {
+ crlEntry->userReasonCode = (PKIX_Int32) nssReasonCode;
+ } else {
+ crlEntry->userReasonCodeAbsent = PKIX_TRUE;
+ }
+ }
+
+ PKIX_OBJECT_UNLOCK(crlEntry);
+
+ }
+
+ *pReason = crlEntry->userReasonCode;
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRLEntry_GetCriticalExtensionOIDs
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRLEntry_GetCriticalExtensionOIDs (
+ PKIX_PL_CRLEntry *crlEntry,
+ PKIX_List **pList, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_List *oidsList = NULL;
+ CERTCertExtension **extensions;
+
+ PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCriticalExtensionOIDs");
+ PKIX_NULLCHECK_THREE(crlEntry, crlEntry->nssCrlEntry, pList);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crlEntry->critExtOids == NULL) {
+
+ PKIX_OBJECT_LOCK(crlEntry);
+
+ if (crlEntry->critExtOids == NULL) {
+
+ extensions = crlEntry->nssCrlEntry->extensions;
+
+ PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
+ (extensions, &oidsList, plContext),
+ PKIX_GETCRITICALEXTENSIONOIDSFAILED);
+
+ crlEntry->critExtOids = oidsList;
+ }
+
+ PKIX_OBJECT_UNLOCK(crlEntry);
+
+ }
+
+ /* We should return a copy of the List since this list changes */
+ PKIX_DUPLICATE(crlEntry->critExtOids, pList, plContext,
+ PKIX_OBJECTDUPLICATELISTFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CRLENTRY);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.h
new file mode 100644
index 0000000000..9cdb6bc927
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.h
@@ -0,0 +1,46 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_crlentry.h
+ *
+ * CRL Entry Type Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_CRLENTRY_H
+#define _PKIX_PL_CRLENTRY_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PKIX_PL_CRL_REASONCODE_NOTSET (-1)
+
+struct PKIX_PL_CRLEntryStruct {
+ CERTCrlEntry *nssCrlEntry;
+ PKIX_PL_BigInt *serialNumber;
+ PKIX_List *critExtOids;
+ PKIX_Int32 userReasonCode;
+ PKIX_Boolean userReasonCodeAbsent;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_CRLEntry_RegisterSelf(void *plContext);
+
+/* following functions are called by CRL only hence not public */
+
+PKIX_Error *
+pkix_pl_CRLEntry_Create(
+ CERTCrlEntry **nssCrlEntry, /* head of entry list */
+ PKIX_List **pCrlEntryList,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_CRLENTRY_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c
new file mode 100644
index 0000000000..4b5016bd01
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.c
@@ -0,0 +1,466 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_date.c
+ *
+ * Date Object Definitions
+ *
+ */
+
+#include "pkix_pl_date.h"
+
+/* --Private-Date-Functions------------------------------------- */
+/*
+ * FUNCTION: pkix_pl_Date_GetPRTime
+ * DESCRIPTION:
+ *
+ * Translates into a PRTime the Date embodied by the Date object pointed to
+ * by "date", and stores it at "pPRTime".
+ *
+ * PARAMETERS
+ * "date"
+ * Address of Date whose PRTime representation is desired. Must be
+ * non-NULL.
+ * "pPRTime"
+ * Address where PRTime value will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Date Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Date_GetPRTime(
+ PKIX_PL_Date *date,
+ PRTime *pPRTime,
+ void *plContext)
+{
+ PKIX_ENTER(DATE, "PKIX_PL_Date_GetPRTime");
+ PKIX_NULLCHECK_TWO(date, pPRTime);
+
+ *pPRTime = date->nssTime;
+
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_CreateFromPRTime
+ * DESCRIPTION:
+ *
+ * Creates a new Date from the PRTime whose value is "prtime", and stores the
+ * result at "pDate".
+ *
+ * PARAMETERS
+ * "prtime"
+ * The PRTime value to be embodied in the new Date object.
+ * "pDate"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Date Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Date_CreateFromPRTime(
+ PRTime prtime,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_PL_Date *date = NULL;
+
+ PKIX_ENTER(DATE, "PKIX_PL_Date_CreateFromPRTime");
+ PKIX_NULLCHECK_ONE(pDate);
+
+ /* create a PKIX_PL_Date object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_DATE_TYPE,
+ sizeof (PKIX_PL_Date),
+ (PKIX_PL_Object **)&date,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+ /* populate the nssTime field */
+ date->nssTime = prtime;
+ *pDate = date;
+cleanup:
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the SECItem pointed
+ * to by "nssTime" (which represents a date) and stores it at "pString".
+ *
+ * PARAMETERS
+ * "nssTime"
+ * Address of SECItem whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Date Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Date_ToString_Helper(
+ SECItem *nssTime,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ char *asciiDate = NULL;
+
+ PKIX_ENTER(DATE, "pkix_pl_Date_ToString_Helper");
+ PKIX_NULLCHECK_TWO(nssTime, pString);
+
+ switch (nssTime->type) {
+ case siUTCTime:
+ PKIX_PL_NSSCALLRV
+ (DATE, asciiDate, DER_UTCDayToAscii, (nssTime));
+ if (!asciiDate){
+ PKIX_ERROR(PKIX_DERUTCTIMETOASCIIFAILED);
+ }
+ break;
+ case siGeneralizedTime:
+ /*
+ * we don't currently have any way to create GeneralizedTime.
+ * this code is only here so that it will be in place when
+ * we do have the capability to create GeneralizedTime.
+ */
+ PKIX_PL_NSSCALLRV
+ (DATE, asciiDate, DER_GeneralizedDayToAscii, (nssTime));
+ if (!asciiDate){
+ PKIX_ERROR(PKIX_DERGENERALIZEDDAYTOASCIIFAILED);
+ }
+ break;
+ default:
+ PKIX_ERROR(PKIX_UNRECOGNIZEDTIMETYPE);
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiDate, 0, pString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+cleanup:
+ PR_Free(asciiDate);
+
+ PKIX_RETURN(DATE);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_Date_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Date_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ENTER(DATE, "pkix_pl_Date_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext),
+ PKIX_OBJECTNOTDATE);
+cleanup:
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Date_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_Date *date = NULL;
+ SECItem nssTime = {siBuffer, NULL, 0};
+ SECStatus rv;
+
+ PKIX_ENTER(DATE, "pkix_pl_Date_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext),
+ PKIX_OBJECTNOTDATE);
+
+ date = (PKIX_PL_Date *)object;
+ rv = DER_EncodeTimeChoice(NULL, &nssTime, date->nssTime);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_DERENCODETIMECHOICEFAILED);
+ }
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&nssTime, pString, plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+cleanup:
+ if (nssTime.data) {
+ SECITEM_FreeItem(&nssTime, PR_FALSE);
+ }
+
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Date_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_Date *date = NULL;
+ PKIX_UInt32 dateHash;
+
+ PKIX_ENTER(DATE, "pkix_pl_Date_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_DATE_TYPE, plContext),
+ PKIX_OBJECTNOTDATE);
+
+ date = (PKIX_PL_Date *)object;
+
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)&date->nssTime,
+ sizeof(date->nssTime),
+ &dateHash,
+ plContext),
+ PKIX_HASHFAILED);
+
+ *pHashcode = dateHash;
+
+cleanup:
+
+ PKIX_RETURN(DATE);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_Comparator
+ * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Date_Comparator(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PRTime firstTime;
+ PRTime secondTime;
+ SECComparison cmpResult;
+
+ PKIX_ENTER(DATE, "pkix_pl_Date_Comparator");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ PKIX_CHECK(pkix_CheckTypes
+ (firstObject, secondObject, PKIX_DATE_TYPE, plContext),
+ PKIX_ARGUMENTSNOTDATES);
+
+ firstTime = ((PKIX_PL_Date *)firstObject)->nssTime;
+ secondTime = ((PKIX_PL_Date *)secondObject)->nssTime;
+
+ if (firstTime == secondTime)
+ cmpResult = SECEqual;
+ else if (firstTime < secondTime)
+ cmpResult = SECLessThan;
+ else
+ cmpResult = SECGreaterThan;
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Date_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_ENTER(DATE, "pkix_pl_Date_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a Date */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_DATE_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTDATE);
+
+ /*
+ * Since we know firstObject is a Date, if both references are
+ * identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ *pResult = PKIX_FALSE;
+ pkixErrorResult =
+ pkix_pl_Date_Comparator(firstObject, secondObject,
+ pResult, plContext);
+ if (pkixErrorResult) {
+ PKIX_DECREF(pkixErrorResult);
+ }
+
+cleanup:
+
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: pkix_pl_Date_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_DATE_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_Date_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry* entry = &systemClasses[PKIX_DATE_TYPE];
+
+ PKIX_ENTER(CRLCHECKER, "pkix_CrlDp_RegisterSelf");
+
+ entry->description = "Date";
+ entry->typeObjectSize = sizeof(PKIX_PL_Date);
+ entry->destructor = pkix_pl_Date_Destroy;
+ entry->equalsFunction = pkix_pl_Date_Equals;
+ entry->hashcodeFunction = pkix_pl_Date_Hashcode;
+ entry->toStringFunction = pkix_pl_Date_ToString;
+ entry->comparator = pkix_pl_Date_Comparator;
+ entry->duplicateFunction = pkix_duplicateImmutable;
+
+ PKIX_RETURN(DATE);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_Date_Create_UTCTime (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Date_Create_UTCTime(
+ PKIX_PL_String *stringRep,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_PL_Date *date = NULL;
+ char *asciiString = NULL;
+ PKIX_UInt32 escAsciiLength;
+ SECStatus rv;
+ PRTime time;
+
+ PKIX_ENTER(DATE, "PKIX_PL_Date_Create_UTCTime");
+ PKIX_NULLCHECK_ONE(pDate);
+
+ if (stringRep == NULL){
+ PKIX_DATE_DEBUG("\t\tCalling PR_Now).\n");
+ time = PR_Now();
+ } else {
+ /* convert the input PKIX_PL_String to PKIX_ESCASCII */
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stringRep,
+ PKIX_ESCASCII,
+ (void **)&asciiString,
+ &escAsciiLength,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_DATE_DEBUG("\t\tCalling DER_AsciiToTime).\n");
+ /* DER_AsciiToTime only supports UTCTime (2-digit years) */
+ rv = DER_AsciiToTime(&time, asciiString);
+ if (rv != SECSuccess){
+ PKIX_ERROR(PKIX_DERASCIITOTIMEFAILED);
+ }
+ }
+
+ /* create a PKIX_PL_Date object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_DATE_TYPE,
+ sizeof (PKIX_PL_Date),
+ (PKIX_PL_Object **)&date,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* populate the nssTime field */
+ date->nssTime = time;
+ *pDate = date;
+
+cleanup:
+ PKIX_FREE(asciiString);
+
+ PKIX_RETURN(DATE);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Date_Create_CurrentOffBySeconds
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_Date_Create_CurrentOffBySeconds(
+ PKIX_Int32 secondsOffset,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_PL_Date *date = NULL;
+ PRTime time;
+
+ PKIX_ENTER(DATE, "PKIX_PL_Date_Create_CurrentOffBySeconds");
+ PKIX_NULLCHECK_ONE(pDate);
+
+ time = PR_Now() + PR_SecondsToInterval(secondsOffset);
+ /* create a PKIX_PL_Date object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_DATE_TYPE,
+ sizeof (PKIX_PL_Date),
+ (PKIX_PL_Object **)&date,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* populate the nssTime field */
+ date->nssTime = time;
+ *pDate = date;
+
+cleanup:
+ PKIX_RETURN(DATE);
+}
+
+PKIX_Error *
+PKIX_PL_Date_CreateFromPRTime(
+ PRTime prtime,
+ PKIX_PL_Date **pDate,
+ void *plContext)
+{
+ PKIX_ENTER(DATE, "PKIX_PL_Date_CreateFromPRTime");
+ PKIX_CHECK(
+ pkix_pl_Date_CreateFromPRTime(prtime, pDate, plContext),
+ PKIX_DATECREATEFROMPRTIMEFAILED);
+
+cleanup:
+ PKIX_RETURN(DATE);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.h
new file mode 100644
index 0000000000..415597580a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_date.h
@@ -0,0 +1,55 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_date.h
+ *
+ * Date Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_DATE_H
+#define _PKIX_PL_DATE_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_DateStruct{
+ PRTime nssTime;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_Date_ToString_Helper(
+ SECItem *nssTime,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+PKIX_Error *pkix_pl_Date_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_Date_GetPRTime(
+ PKIX_PL_Date *date,
+ PRTime *pPRTime,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_Date_CreateFromPRTime(
+ PRTime prtime,
+ PKIX_PL_Date **pDate,
+ void *plContext);
+
+PKIX_Error *
+PKIX_PL_Date_CreateFromPRTime(
+ PRTime prtime,
+ PKIX_PL_Date **pDate,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_DATE_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c
new file mode 100644
index 0000000000..9e9a74c783
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c
@@ -0,0 +1,873 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_generalname.c
+ *
+ * GeneralName Object Definitions
+ *
+ */
+
+#include "pkix_pl_generalname.h"
+
+/* --Private-GeneralName-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_GetNssGeneralName
+ * DESCRIPTION:
+ *
+ * Retrieves the NSS representation of the PKIX_PL_GeneralName pointed by
+ * "genName" and stores it at "pNssGenName". The NSS data type CERTGeneralName
+ * is stored in this object when the object was created.
+ *
+ * PARAMETERS:
+ * "genName"
+ * Address of PKIX_PL_GeneralName. Must be non-NULL.
+ * "pNssGenName"
+ * Address where CERTGeneralName will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a GeneralName Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_GeneralName_GetNssGeneralName(
+ PKIX_PL_GeneralName *genName,
+ CERTGeneralName **pNssGenName,
+ void *plContext)
+{
+ CERTGeneralName *nssGenName = NULL;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_GetNssGeneralName");
+ PKIX_NULLCHECK_THREE(genName, pNssGenName, genName->nssGeneralNameList);
+
+ nssGenName = genName->nssGeneralNameList->name;
+
+ *pNssGenName = nssGenName;
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_OtherName_Create
+ * DESCRIPTION:
+ *
+ * Creates new OtherName which represents the CERTGeneralName pointed to by
+ * "nssAltName" and stores it at "pOtherName".
+ *
+ * PARAMETERS:
+ * "nssAltName"
+ * Address of CERTGeneralName. Must be non-NULL.
+ * "pOtherName"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a GeneralName Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_OtherName_Create(
+ CERTGeneralName *nssAltName,
+ OtherName **pOtherName,
+ void *plContext)
+{
+ OtherName *otherName = NULL;
+ SECItem secItemName;
+ SECItem secItemOID;
+ SECStatus rv;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_OtherName_Create");
+ PKIX_NULLCHECK_TWO(nssAltName, pOtherName);
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (sizeof (OtherName), (void **)&otherName, plContext),
+ PKIX_MALLOCFAILED);
+
+ /* make a copy of the name field */
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CopyItem).\n");
+ rv = SECITEM_CopyItem
+ (NULL, &otherName->name, &nssAltName->name.OthName.name);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ /* make a copy of the oid field */
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CopyItem).\n");
+ rv = SECITEM_CopyItem
+ (NULL, &otherName->oid, &nssAltName->name.OthName.oid);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ *pOtherName = otherName;
+
+cleanup:
+
+ if (otherName && PKIX_ERROR_RECEIVED){
+ secItemName = otherName->name;
+ secItemOID = otherName->oid;
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(&secItemName, PR_FALSE);
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(&secItemOID, PR_FALSE);
+
+ PKIX_FREE(otherName);
+ otherName = NULL;
+ }
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_DirectoryName_Create
+ * DESCRIPTION:
+ *
+ * Creates a new X500Name which represents the directoryName component of the
+ * CERTGeneralName pointed to by "nssAltName" and stores it at "pX500Name".
+ *
+ * PARAMETERS:
+ * "nssAltName"
+ * Address of CERTGeneralName. Must be non-NULL.
+ * "pX500Name"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a GeneralName Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_DirectoryName_Create(
+ CERTGeneralName *nssAltName,
+ PKIX_PL_X500Name **pX500Name,
+ void *plContext)
+{
+ PKIX_PL_X500Name *pkixDN = NULL;
+ CERTName *dirName = NULL;
+ PKIX_PL_String *pkixDNString = NULL;
+ char *utf8String = NULL;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_DirectoryName_Create");
+ PKIX_NULLCHECK_TWO(nssAltName, pX500Name);
+
+ dirName = &nssAltName->name.directoryName;
+
+ PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName(NULL, dirName,
+ &pkixDN, plContext),
+ PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
+
+ *pX500Name = pkixDN;
+
+cleanup:
+
+ PR_Free(utf8String);
+ PKIX_DECREF(pkixDNString);
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_Create
+ * DESCRIPTION:
+ *
+ * Creates new GeneralName which represents the CERTGeneralName pointed to by
+ * "nssAltName" and stores it at "pGenName".
+ *
+ * PARAMETERS:
+ * "nssAltName"
+ * Address of CERTGeneralName. Must be non-NULL.
+ * "pGenName"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a GeneralName Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_GeneralName_Create(
+ CERTGeneralName *nssAltName,
+ PKIX_PL_GeneralName **pGenName,
+ void *plContext)
+{
+ PKIX_PL_GeneralName *genName = NULL;
+ PKIX_PL_X500Name *pkixDN = NULL;
+ PKIX_PL_OID *pkixOID = NULL;
+ OtherName *otherName = NULL;
+ CERTGeneralNameList *nssGenNameList = NULL;
+ CERTGeneralNameType nameType;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Create");
+ PKIX_NULLCHECK_TWO(nssAltName, pGenName);
+
+ /* create a PKIX_PL_GeneralName object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_GENERALNAME_TYPE,
+ sizeof (PKIX_PL_GeneralName),
+ (PKIX_PL_Object **)&genName,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ nameType = nssAltName->type;
+
+ /*
+ * We use CERT_CreateGeneralNameList to create just one CERTGeneralName
+ * item for memory allocation reason. If we want to just create one
+ * item, we have to use the calling path CERT_NewGeneralName, then
+ * CERT_CopyOneGeneralName. With this calling path, if we pass
+ * the arena argument as NULL, in CERT_CopyOneGeneralName's subsequent
+ * call to CERT_CopyName, it assumes arena should be valid, hence
+ * segmentation error (not sure this is a NSS bug, certainly it is
+ * not consistent). But on the other hand, we don't want to keep an
+ * arena record here explicitely for every PKIX_PL_GeneralName.
+ * So I concluded it is better to use CERT_CreateGeneralNameList,
+ * which keeps an arena pointer in its data structure and also masks
+ * out details calls from this libpkix level.
+ */
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_CreateGeneralNameList).\n");
+ nssGenNameList = CERT_CreateGeneralNameList(nssAltName);
+
+ if (nssGenNameList == NULL) {
+ PKIX_ERROR(PKIX_CERTCREATEGENERALNAMELISTFAILED);
+ }
+
+ genName->nssGeneralNameList = nssGenNameList;
+
+ /* initialize fields */
+ genName->type = nameType;
+ genName->directoryName = NULL;
+ genName->OthName = NULL;
+ genName->other = NULL;
+ genName->oid = NULL;
+
+ switch (nameType){
+ case certOtherName:
+
+ PKIX_CHECK(pkix_pl_OtherName_Create
+ (nssAltName, &otherName, plContext),
+ PKIX_OTHERNAMECREATEFAILED);
+
+ genName->OthName = otherName;
+ break;
+
+ case certDirectoryName:
+
+ PKIX_CHECK(pkix_pl_DirectoryName_Create
+ (nssAltName, &pkixDN, plContext),
+ PKIX_DIRECTORYNAMECREATEFAILED);
+
+ genName->directoryName = pkixDN;
+ break;
+ case certRegisterID:
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem(&nssAltName->name.other,
+ &pkixOID, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ genName->oid = pkixOID;
+ break;
+ case certDNSName:
+ case certEDIPartyName:
+ case certIPAddress:
+ case certRFC822Name:
+ case certX400Address:
+ case certURI:
+ genName->other = SECITEM_DupItem(&nssAltName->name.other);
+ if (!genName->other) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ break;
+ default:
+ PKIX_ERROR(PKIX_NAMETYPENOTSUPPORTED);
+ }
+
+ *pGenName = genName;
+ genName = NULL;
+
+cleanup:
+ PKIX_DECREF(genName);
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the GeneralName
+ * pointed to by "name" and stores it at "pString" Different mechanisms are
+ * used to create the string, depending on the type of the GeneralName.
+ *
+ * PARAMETERS
+ * "name"
+ * Address of GeneralName whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a GeneralName Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_GeneralName_ToString_Helper(
+ PKIX_PL_GeneralName *name,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_X500Name *pkixDN = NULL;
+ PKIX_PL_OID *pkixOID = NULL;
+ char *x400AsciiName = NULL;
+ char *ediPartyName = NULL;
+ char *asciiName = NULL;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_ToString_Helper");
+ PKIX_NULLCHECK_TWO(name, pString);
+
+ switch (name->type) {
+ case certRFC822Name:
+ case certDNSName:
+ case certURI:
+ /*
+ * Note that we can't use PKIX_ESCASCII here because
+ * name->other->data is not guaranteed to be null-terminated.
+ */
+
+ PKIX_NULLCHECK_ONE(name->other);
+
+ PKIX_CHECK(PKIX_PL_String_Create(PKIX_UTF8,
+ (name->other)->data,
+ (name->other)->len,
+ pString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ break;
+ case certEDIPartyName:
+ /* XXX print out the actual bytes */
+ ediPartyName = "EDIPartyName: <DER-encoded value>";
+ PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
+ ediPartyName,
+ 0,
+ pString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ break;
+ case certX400Address:
+ /* XXX print out the actual bytes */
+ x400AsciiName = "X400Address: <DER-encoded value>";
+ PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
+ x400AsciiName,
+ 0,
+ pString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ break;
+ case certIPAddress:
+ PKIX_CHECK(pkix_pl_ipAddrBytes2Ascii
+ (name->other, &asciiName, plContext),
+ PKIX_IPADDRBYTES2ASCIIFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
+ asciiName,
+ 0,
+ pString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ break;
+ case certOtherName:
+ PKIX_NULLCHECK_ONE(name->OthName);
+
+ /* we only print type-id - don't know how to print value */
+ /* XXX print out the bytes of the value */
+ PKIX_CHECK(pkix_pl_oidBytes2Ascii
+ (&name->OthName->oid, &asciiName, plContext),
+ PKIX_OIDBYTES2ASCIIFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiName,
+ 0,
+ pString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+ break;
+ case certRegisterID:
+ pkixOID = name->oid;
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)pkixOID, pString, plContext),
+ PKIX_OIDTOSTRINGFAILED);
+ break;
+ case certDirectoryName:
+ pkixDN = name->directoryName;
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)pkixDN, pString, plContext),
+ PKIX_X500NAMETOSTRINGFAILED);
+ break;
+ default:
+ PKIX_ERROR
+ (PKIX_TOSTRINGFORTHISGENERALNAMETYPENOTSUPPORTED);
+ }
+
+cleanup:
+
+ PKIX_FREE(asciiName);
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_GeneralName_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_GeneralName *name = NULL;
+ SECItem secItemName;
+ SECItem secItemOID;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext),
+ PKIX_OBJECTNOTGENERALNAME);
+
+ name = (PKIX_PL_GeneralName *)object;
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(name->other, PR_TRUE);
+ name->other = NULL;
+
+ if (name->OthName){
+ secItemName = name->OthName->name;
+ secItemOID = name->OthName->oid;
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(&secItemName, PR_FALSE);
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(&secItemOID, PR_FALSE);
+
+ PKIX_FREE(name->OthName);
+ name->OthName = NULL;
+ }
+
+ if (name->nssGeneralNameList != NULL) {
+ PKIX_GENERALNAME_DEBUG
+ ("\t\tCalling CERT_DestroyGeneralNameList).\n");
+ CERT_DestroyGeneralNameList(name->nssGeneralNameList);
+ }
+
+ PKIX_DECREF(name->directoryName);
+ PKIX_DECREF(name->oid);
+
+cleanup:
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_GeneralName_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *nameString = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext),
+ PKIX_OBJECTNOTGENERALNAME);
+
+ name = (PKIX_PL_GeneralName *)object;
+
+ PKIX_CHECK(pkix_pl_GeneralName_ToString_Helper
+ (name, &nameString, plContext),
+ PKIX_GENERALNAMETOSTRINGHELPERFAILED);
+
+ *pString = nameString;
+
+cleanup:
+
+
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_GeneralName_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_GeneralName *name = NULL;
+ PKIX_UInt32 firstHash, secondHash, nameHash;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext),
+ PKIX_OBJECTNOTGENERALNAME);
+
+ name = (PKIX_PL_GeneralName *)object;
+
+ switch (name->type) {
+ case certRFC822Name:
+ case certDNSName:
+ case certX400Address:
+ case certEDIPartyName:
+ case certURI:
+ case certIPAddress:
+ PKIX_NULLCHECK_ONE(name->other);
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)
+ name->other->data,
+ name->other->len,
+ &nameHash,
+ plContext),
+ PKIX_HASHFAILED);
+ break;
+ case certRegisterID:
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)name->oid,
+ &nameHash,
+ plContext),
+ PKIX_OIDHASHCODEFAILED);
+ break;
+ case certOtherName:
+ PKIX_NULLCHECK_ONE(name->OthName);
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)
+ name->OthName->oid.data,
+ name->OthName->oid.len,
+ &firstHash,
+ plContext),
+ PKIX_HASHFAILED);
+
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)
+ name->OthName->name.data,
+ name->OthName->name.len,
+ &secondHash,
+ plContext),
+ PKIX_HASHFAILED);
+
+ nameHash = firstHash + secondHash;
+ break;
+ case certDirectoryName:
+ PKIX_CHECK(PKIX_PL_Object_Hashcode
+ ((PKIX_PL_Object *)
+ name->directoryName,
+ &nameHash,
+ plContext),
+ PKIX_X500NAMEHASHCODEFAILED);
+ break;
+ }
+
+ *pHashcode = nameHash;
+
+cleanup:
+
+ PKIX_RETURN(GENERALNAME);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_GeneralName_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_GeneralName *firstName = NULL;
+ PKIX_PL_GeneralName *secondName = NULL;
+ PKIX_UInt32 secondType;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a GeneralName */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_GENERALNAME_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTGENERALNAME);
+
+ /*
+ * Since we know firstObject is a GeneralName, if both references are
+ * identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a GeneralName, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_GENERALNAME_TYPE){
+ goto cleanup;
+ }
+
+ firstName = (PKIX_PL_GeneralName *)firstObject;
+ secondName = (PKIX_PL_GeneralName *)secondObject;
+
+ if (firstName->type != secondName->type){
+ goto cleanup;
+ }
+
+ switch (firstName->type) {
+ case certRFC822Name:
+ case certDNSName:
+ case certX400Address:
+ case certEDIPartyName:
+ case certURI:
+ case certIPAddress:
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CompareItem).\n");
+ if (SECITEM_CompareItem(firstName->other,
+ secondName->other) != SECEqual) {
+ goto cleanup;
+ }
+ break;
+ case certRegisterID:
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstName->oid,
+ (PKIX_PL_Object *)secondName->oid,
+ pResult,
+ plContext),
+ PKIX_OIDEQUALSFAILED);
+ goto cleanup;
+ case certOtherName:
+ PKIX_NULLCHECK_TWO(firstName->OthName, secondName->OthName);
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CompareItem).\n");
+ if (SECITEM_CompareItem(&firstName->OthName->oid,
+ &secondName->OthName->oid)
+ != SECEqual ||
+ SECITEM_CompareItem(&firstName->OthName->name,
+ &secondName->OthName->name)
+ != SECEqual) {
+ goto cleanup;
+ }
+ break;
+ case certDirectoryName:
+ PKIX_CHECK(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)firstName->directoryName,
+ (PKIX_PL_Object *)secondName->directoryName,
+ pResult,
+ plContext),
+ PKIX_X500NAMEEQUALSFAILED);
+ goto cleanup;
+ }
+
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_GeneralName_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_GENERALNAME_TYPE and related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_GeneralName_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_RegisterSelf");
+
+ entry.description = "GeneralName";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_GeneralName);
+ entry.destructor = pkix_pl_GeneralName_Destroy;
+ entry.equalsFunction = pkix_pl_GeneralName_Equals;
+ entry.hashcodeFunction = pkix_pl_GeneralName_Hashcode;
+ entry.toStringFunction = pkix_pl_GeneralName_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_GENERALNAME_TYPE] = entry;
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+#ifdef BUILD_LIBPKIX_TESTS
+/*
+ * FUNCTION: PKIX_PL_GeneralName_Create (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_GeneralName_Create(
+ PKIX_UInt32 nameType,
+ PKIX_PL_String *stringRep,
+ PKIX_PL_GeneralName **pGName,
+ void *plContext)
+{
+ PKIX_PL_X500Name *pkixDN = NULL;
+ PKIX_PL_OID *pkixOID = NULL;
+ SECItem *secItem = NULL;
+ char *asciiString = NULL;
+ PKIX_UInt32 length = 0;
+ PKIX_PL_GeneralName *genName = NULL;
+ CERTGeneralName *nssGenName = NULL;
+ CERTGeneralNameList *nssGenNameList = NULL;
+ CERTName *nssCertName = NULL;
+ PLArenaPool *arena = NULL;
+
+ PKIX_ENTER(GENERALNAME, "PKIX_PL_GeneralName_Create");
+ PKIX_NULLCHECK_TWO(pGName, stringRep);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stringRep,
+ PKIX_ESCASCII,
+ (void **)&asciiString,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ /* Create a temporary CERTGeneralName */
+ PKIX_GENERALNAME_DEBUG("\t\tCalling PL_strlen).\n");
+ length = PL_strlen(asciiString);
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_AllocItem).\n");
+ secItem = SECITEM_AllocItem(NULL, NULL, length);
+ PKIX_GENERALNAME_DEBUG("\t\tCalling PORT_Memcpy).\n");
+ (void) PORT_Memcpy(secItem->data, asciiString, length);
+ PKIX_CERT_DEBUG("\t\tCalling PORT_NewArena).\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_NewGeneralName).\n");
+ nssGenName = CERT_NewGeneralName(arena, nameType);
+ if (nssGenName == NULL) {
+ PKIX_ERROR(PKIX_ALLOCATENEWCERTGENERALNAMEFAILED);
+ }
+
+ switch (nameType) {
+ case certRFC822Name:
+ case certDNSName:
+ case certURI:
+ nssGenName->name.other = *secItem;
+ break;
+
+ case certDirectoryName:
+
+ PKIX_CHECK(PKIX_PL_X500Name_Create
+ (stringRep, &pkixDN, plContext),
+ PKIX_X500NAMECREATEFAILED);
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_AsciiToName).\n");
+ nssCertName = CERT_AsciiToName(asciiString);
+ nssGenName->name.directoryName = *nssCertName;
+ break;
+
+ case certRegisterID:
+ PKIX_CHECK(PKIX_PL_OID_Create
+ (asciiString, &pkixOID, plContext),
+ PKIX_OIDCREATEFAILED);
+ nssGenName->name.other = *secItem;
+ break;
+ default:
+ /* including IPAddress, EDIPartyName, OtherName, X400Address */
+ PKIX_ERROR(PKIX_UNABLETOCREATEGENERALNAMEOFTHISTYPE);
+ }
+
+ /* create a PKIX_PL_GeneralName object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_GENERALNAME_TYPE,
+ sizeof (PKIX_PL_GeneralName),
+ (PKIX_PL_Object **)&genName,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* create a CERTGeneralNameList */
+ nssGenName->type = nameType;
+ PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_CreateGeneralNameList).\n");
+ nssGenNameList = CERT_CreateGeneralNameList(nssGenName);
+ if (nssGenNameList == NULL) {
+ PKIX_ERROR(PKIX_CERTCREATEGENERALNAMELISTFAILED);
+ }
+ genName->nssGeneralNameList = nssGenNameList;
+
+ /* initialize fields */
+ genName->type = nameType;
+ genName->directoryName = pkixDN;
+ genName->OthName = NULL;
+ genName->other = secItem;
+ genName->oid = pkixOID;
+
+ *pGName = genName;
+cleanup:
+
+ PKIX_FREE(asciiString);
+
+ if (nssCertName != NULL) {
+ PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyName).\n");
+ CERT_DestroyName(nssCertName);
+ }
+
+ if (arena){ /* will free nssGenName */
+ PKIX_CERT_DEBUG("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(pkixDN);
+ PKIX_DECREF(pkixOID);
+
+ PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ if (secItem){
+ SECITEM_FreeItem(secItem, PR_TRUE);
+ secItem = NULL;
+ }
+ }
+
+ PKIX_RETURN(GENERALNAME);
+}
+
+#endif /* BUILD_LIBPKIX_TESTS */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.h
new file mode 100644
index 0000000000..3cb5264d51
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.h
@@ -0,0 +1,49 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_generalname.h
+ *
+ * GeneralName Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_GENERALNAME_H
+#define _PKIX_PL_GENERALNAME_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_GeneralNameStruct{
+ CERTGeneralNameList *nssGeneralNameList;
+ CERTGeneralNameType type;
+ PKIX_PL_X500Name *directoryName;
+ PKIX_PL_OID *oid;
+ OtherName *OthName;
+ SECItem *other;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_GeneralName_Create(
+ CERTGeneralName *nssAltName,
+ PKIX_PL_GeneralName **pGenName,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_GeneralName_GetNssGeneralName(
+ PKIX_PL_GeneralName *genName,
+ CERTGeneralName **pNssGenName,
+ void *plContext);
+
+PKIX_Error *pkix_pl_GeneralName_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_GENERALNAME_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c
new file mode 100644
index 0000000000..09b54a2be3
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.c
@@ -0,0 +1,874 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_infoaccess.c
+ *
+ * InfoAccess Object Definitions
+ *
+ */
+
+#include "pkix_pl_infoaccess.h"
+
+/* --Private-InfoAccess-Functions----------------------------------*/
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_Create
+ * DESCRIPTION:
+ *
+ * This function creates an InfoAccess from the method provided in "method" and
+ * the GeneralName provided in "generalName" and stores the result at
+ * "pInfoAccess".
+ *
+ * PARAMETERS
+ * "method"
+ * The UInt32 value to be stored as the method field of the InfoAccess.
+ * "gName"
+ * The GeneralName to be stored as the gName field of the InfoAccess.
+ * Must be non-NULL.
+ * "pInfoAccess"
+ * Address where the result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_InfoAccess_Create(
+ PKIX_UInt32 method,
+ PKIX_PL_GeneralName *gName,
+ PKIX_PL_InfoAccess **pInfoAccess,
+ void *plContext)
+{
+
+ PKIX_PL_InfoAccess *infoAccess = NULL;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Create");
+ PKIX_NULLCHECK_TWO(gName, pInfoAccess);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_INFOACCESS_TYPE,
+ sizeof (PKIX_PL_InfoAccess),
+ (PKIX_PL_Object **)&infoAccess,
+ plContext),
+ PKIX_COULDNOTCREATEINFOACCESSOBJECT);
+
+ infoAccess->method = method;
+
+ PKIX_INCREF(gName);
+ infoAccess->location = gName;
+
+ *pInfoAccess = infoAccess;
+ infoAccess = NULL;
+
+cleanup:
+ PKIX_DECREF(infoAccess);
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_pki.h)
+ */
+static PKIX_Error *
+pkix_pl_InfoAccess_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_InfoAccess *infoAccess = NULL;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_INFOACCESS_TYPE, plContext),
+ PKIX_OBJECTNOTANINFOACCESS);
+
+ infoAccess = (PKIX_PL_InfoAccess *)object;
+
+ PKIX_DECREF(infoAccess->location);
+
+cleanup:
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_pki.h)
+ */
+static PKIX_Error *
+pkix_pl_InfoAccess_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_InfoAccess *infoAccess;
+ PKIX_PL_String *infoAccessString = NULL;
+ char *asciiFormat = NULL;
+ char *asciiMethod = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *methodString = NULL;
+ PKIX_PL_String *locationString = NULL;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_INFOACCESS_TYPE, plContext),
+ PKIX_OBJECTNOTINFOACCESS);
+
+ infoAccess = (PKIX_PL_InfoAccess *)object;
+
+ asciiFormat =
+ "["
+ "method:%s, "
+ "location:%s"
+ "]";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ switch(infoAccess->method) {
+ case PKIX_INFOACCESS_CA_ISSUERS:
+ asciiMethod = "caIssuers";
+ break;
+ case PKIX_INFOACCESS_OCSP:
+ asciiMethod = "ocsp";
+ break;
+ case PKIX_INFOACCESS_TIMESTAMPING:
+ asciiMethod = "timestamping";
+ break;
+ case PKIX_INFOACCESS_CA_REPOSITORY:
+ asciiMethod = "caRepository";
+ break;
+ default:
+ asciiMethod = "unknown";
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiMethod,
+ 0,
+ &methodString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_TOSTRING(infoAccess->location, &locationString, plContext,
+ PKIX_GENERALNAMETOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&infoAccessString,
+ plContext,
+ formatString,
+ methodString,
+ locationString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = infoAccessString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(methodString);
+ PKIX_DECREF(locationString);
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_pki.h)
+ */
+static PKIX_Error *
+pkix_pl_InfoAccess_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_InfoAccess *infoAccess = NULL;
+ PKIX_UInt32 infoAccessHash;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_INFOACCESS_TYPE, plContext),
+ PKIX_OBJECTNOTINFOACCESS);
+
+ infoAccess = (PKIX_PL_InfoAccess *)object;
+
+ PKIX_HASHCODE(infoAccess->location, &infoAccessHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ infoAccessHash += (infoAccess->method << 7);
+
+ *pHashcode = infoAccessHash;
+
+cleanup:
+
+ PKIX_RETURN(INFOACCESS);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_pki.h)
+ */
+static PKIX_Error *
+pkix_pl_InfoAccess_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_InfoAccess *firstInfoAccess = NULL;
+ PKIX_PL_InfoAccess *secondInfoAccess = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a InfoAccess */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_INFOACCESS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTINFOACCESS);
+
+ /*
+ * Since we know firstObject is a InfoAccess, if both references are
+ * identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a InfoAccess, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_INFOACCESS_TYPE) goto cleanup;
+
+ firstInfoAccess = (PKIX_PL_InfoAccess *)firstObject;
+ secondInfoAccess = (PKIX_PL_InfoAccess *)secondObject;
+
+ *pResult = PKIX_FALSE;
+
+ if (firstInfoAccess->method != secondInfoAccess->method) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS(firstInfoAccess, secondInfoAccess, &cmpResult, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ *pResult = cmpResult;
+
+cleanup:
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_INFOACCESS_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_InfoAccess_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(INFOACCESS,
+ "pkix_pl_InfoAccess_RegisterSelf");
+
+ entry.description = "InfoAccess";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_InfoAccess);
+ entry.destructor = pkix_pl_InfoAccess_Destroy;
+ entry.equalsFunction = pkix_pl_InfoAccess_Equals;
+ entry.hashcodeFunction = pkix_pl_InfoAccess_Hashcode;
+ entry.toStringFunction = pkix_pl_InfoAccess_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_INFOACCESS_TYPE] = entry;
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_CreateList
+ * DESCRIPTION:
+ *
+ * Based on data in CERTAuthInfoAccess array "nssInfoAccess", this function
+ * creates and returns a PKIX_List of PKIX_PL_InfoAccess at "pInfoAccessList".
+ *
+ * PARAMETERS
+ * "nssInfoAccess"
+ * The pointer array of CERTAuthInfoAccess that contains access data.
+ * May be NULL.
+ * "pInfoAccessList"
+ * Address where a list of PKIX_PL_InfoAccess is returned.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_InfoAccess_CreateList(
+ CERTAuthInfoAccess **nssInfoAccess,
+ PKIX_List **pInfoAccessList, /* of PKIX_PL_InfoAccess */
+ void *plContext)
+{
+ PKIX_List *infoAccessList = NULL;
+ PKIX_PL_InfoAccess *infoAccess = NULL;
+ PKIX_PL_GeneralName *location = NULL;
+ PKIX_UInt32 method;
+ int i;
+
+ PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_CreateList");
+ PKIX_NULLCHECK_ONE(pInfoAccessList);
+
+ PKIX_CHECK(PKIX_List_Create(&infoAccessList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ if (nssInfoAccess == NULL) {
+ goto cleanup;
+ }
+
+ for (i = 0; nssInfoAccess[i] != NULL; i++) {
+
+ if (nssInfoAccess[i]->location == NULL) {
+ continue;
+ }
+
+ PKIX_CHECK(pkix_pl_GeneralName_Create
+ (nssInfoAccess[i]->location, &location, plContext),
+ PKIX_GENERALNAMECREATEFAILED);
+
+ PKIX_CERT_DEBUG("\t\tCalling SECOID_FindOIDTag).\n");
+ method = SECOID_FindOIDTag(&nssInfoAccess[i]->method);
+ /* Map NSS access method value into PKIX constant */
+ switch(method) {
+ case SEC_OID_PKIX_CA_ISSUERS:
+ method = PKIX_INFOACCESS_CA_ISSUERS;
+ break;
+ case SEC_OID_PKIX_OCSP:
+ method = PKIX_INFOACCESS_OCSP;
+ break;
+ case SEC_OID_PKIX_TIMESTAMPING:
+ method = PKIX_INFOACCESS_TIMESTAMPING;
+ break;
+ case SEC_OID_PKIX_CA_REPOSITORY:
+ method = PKIX_INFOACCESS_CA_REPOSITORY;
+ break;
+ default:
+ PKIX_ERROR(PKIX_UNKNOWNINFOACCESSMETHOD);
+ }
+
+ PKIX_CHECK(pkix_pl_InfoAccess_Create
+ (method, location, &infoAccess, plContext),
+ PKIX_INFOACCESSCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (infoAccessList,
+ (PKIX_PL_Object *)infoAccess,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(infoAccess);
+ PKIX_DECREF(location);
+ }
+
+ *pInfoAccessList = infoAccessList;
+ infoAccessList = NULL;
+
+cleanup:
+
+ PKIX_DECREF(infoAccessList);
+ PKIX_DECREF(infoAccess);
+ PKIX_DECREF(location);
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_InfoAccess_GetMethod (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_InfoAccess_GetMethod(
+ PKIX_PL_InfoAccess *infoAccess,
+ PKIX_UInt32 *pMethod,
+ void *plContext)
+{
+ PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_GetMethod");
+ PKIX_NULLCHECK_TWO(infoAccess, pMethod);
+
+ *pMethod = infoAccess->method;
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: PKIX_PL_InfoAccess_GetLocation (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_InfoAccess_GetLocation(
+ PKIX_PL_InfoAccess *infoAccess,
+ PKIX_PL_GeneralName **pLocation,
+ void *plContext)
+{
+ PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_GetLocation");
+ PKIX_NULLCHECK_TWO(infoAccess, pLocation);
+
+ PKIX_INCREF(infoAccess->location);
+
+ *pLocation = infoAccess->location;
+
+cleanup:
+ PKIX_RETURN(INFOACCESS);
+}
+
+/*
+ * FUNCTION: PKIX_PL_InfoAccess_GetLocationType (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_InfoAccess_GetLocationType(
+ PKIX_PL_InfoAccess *infoAccess,
+ PKIX_UInt32 *pType,
+ void *plContext)
+{
+ PKIX_PL_String *locationString = NULL;
+ PKIX_UInt32 type = PKIX_INFOACCESS_LOCATION_UNKNOWN;
+ PKIX_UInt32 len = 0;
+ void *location = NULL;
+
+ PKIX_ENTER(INFOACCESS, "PKIX_PL_InfoAccess_GetLocationType");
+ PKIX_NULLCHECK_TWO(infoAccess, pType);
+
+ if (infoAccess->location != NULL) {
+
+ PKIX_TOSTRING(infoAccess->location, &locationString, plContext,
+ PKIX_GENERALNAMETOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (locationString, PKIX_ESCASCII, &location, &len, plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_OID_DEBUG("\tCalling PORT_Strcmp).\n");
+#ifndef NSS_PKIX_NO_LDAP
+ if (PORT_Strncmp(location, "ldap:", 5) == 0){
+ type = PKIX_INFOACCESS_LOCATION_LDAP;
+ } else
+#endif
+ if (PORT_Strncmp(location, "http:", 5) == 0){
+ type = PKIX_INFOACCESS_LOCATION_HTTP;
+ }
+ }
+
+ *pType = type;
+
+cleanup:
+
+ PKIX_PL_Free(location, plContext);
+ PKIX_DECREF(locationString);
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+#ifndef NSS_PKIX_NO_LDAP
+/*
+ * FUNCTION: pkix_pl_InfoAccess_ParseTokens
+ * DESCRIPTION:
+ *
+ * This function parses the string beginning at "startPos" into tokens using
+ * the separator contained in "separator" and the terminator contained in
+ * "terminator", copying the tokens into space allocated from the arena
+ * pointed to by "arena". It stores in "tokens" a null-terminated array of
+ * pointers to those tokens.
+ *
+ * PARAMETERS
+ * "arena"
+ * Address of a PLArenaPool to be used in populating the LDAPLocation.
+ * Must be non-NULL.
+ * "startPos"
+ * The address of char string that contains a subset of ldap location.
+ * "tokens"
+ * The address of an array of char string for storing returned tokens.
+ * Must be non-NULL.
+ * "separator"
+ * The character that is taken as token separator. Must be non-NULL.
+ * "terminator"
+ * The character that is taken as parsing terminator. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an InfoAccess Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_InfoAccess_ParseTokens(
+ PLArenaPool *arena,
+ char **startPos, /* return update */
+ char ***tokens,
+ char separator,
+ char terminator,
+ void *plContext)
+{
+ PKIX_UInt32 numFilters = 0;
+ char *endPos = NULL;
+ char **filterP = NULL;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ParseTokens");
+ PKIX_NULLCHECK_THREE(arena, startPos, tokens);
+
+ endPos = *startPos;
+
+ /* First pass: parse to <terminator> to count number of components */
+ numFilters = 0;
+ while (*endPos != terminator && *endPos != '\0') {
+ endPos++;
+ if (*endPos == separator) {
+ numFilters++;
+ }
+ }
+
+ if (*endPos != terminator) {
+ PKIX_ERROR(PKIX_LOCATIONSTRINGNOTPROPERLYTERMINATED);
+ }
+
+ /* Last component doesn't need a separator, although we allow it */
+ if (endPos > *startPos && *(endPos-1) != separator) {
+ numFilters++;
+ }
+
+ /*
+ * If string is a=xx, b=yy, c=zz, etc., use a=xx for filter,
+ * and everything else for the base
+ */
+ if (numFilters > 2) numFilters = 2;
+
+ filterP = PORT_ArenaZNewArray(arena, char*, numFilters+1);
+ if (filterP == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ /* Second pass: parse to fill in components in token array */
+ *tokens = filterP;
+ endPos = *startPos;
+
+ while (numFilters) {
+ if (*endPos == separator || *endPos == terminator) {
+ PKIX_UInt32 len = endPos - *startPos;
+ char *p = PORT_ArenaZAlloc(arena, len+1);
+ if (p == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ PORT_Memcpy(p, *startPos, len);
+ p[len] = '\0';
+
+ *filterP = p;
+ filterP++;
+ numFilters--;
+
+ separator = terminator;
+
+ if (*endPos == '\0') {
+ *startPos = endPos;
+ break;
+ } else {
+ endPos++;
+ *startPos = endPos;
+ continue;
+ }
+ }
+ endPos++;
+ }
+
+ *filterP = NULL;
+
+cleanup:
+
+ PKIX_RETURN(INFOACCESS);
+}
+
+static int
+pkix_pl_HexDigitToInt(
+ int ch)
+{
+ if (isdigit(ch)) {
+ ch = ch - '0';
+ } else if (isupper(ch)) {
+ ch = ch - 'A' + 10;
+ } else {
+ ch = ch - 'a' + 10;
+ }
+ return ch;
+}
+
+/*
+ * Convert the "%" hex hex escape sequences in the URL 'location' in place.
+ */
+static void
+pkix_pl_UnescapeURL(
+ char *location)
+{
+ const char *src;
+ char *dst;
+
+ for (src = dst = location; *src != '\0'; src++, dst++) {
+ if (*src == '%' && isxdigit((unsigned char)*(src+1)) &&
+ isxdigit((unsigned char)*(src+2))) {
+ *dst = pkix_pl_HexDigitToInt((unsigned char)*(src+1));
+ *dst *= 16;
+ *dst += pkix_pl_HexDigitToInt((unsigned char)*(src+2));
+ src += 2;
+ } else {
+ *dst = *src;
+ }
+ }
+ *dst = *src; /* the terminating null */
+}
+
+/*
+ * FUNCTION: pkix_pl_InfoAccess_ParseLocation
+ * DESCRIPTION:
+ *
+ * This function parses the GeneralName pointed to by "generalName" into the
+ * fields of the LDAPRequestParams pointed to by "request" and a domainName
+ * pointed to by "pDomainName", using the PLArenaPool pointed to by "arena" to
+ * allocate storage for the request components and for the domainName string.
+ *
+ * The expected GeneralName string should be in the format described by the
+ * following BNF:
+ *
+ * ldap://<ldap-server-site>/[cn=<cname>][,o=<org>][,c=<country>]?
+ * [caCertificate|crossCertificatPair|certificateRevocationList];
+ * [binary|<other-type>]
+ * [[,caCertificate|crossCertificatPair|certificateRevocationList]
+ * [binary|<other-type>]]*
+ *
+ * PARAMETERS
+ * "gName"
+ * Address of the GeneralName whose LDAPLocation is to be parsed. Must be
+ * non-NULL.
+ * "arena"
+ * Address of PLArenaPool to be used for the domainName and for components
+ * of the LDAPRequest. Must be non-NULL.
+ * "request"
+ * Address of the LDAPRequestParams into which request components are
+ * stored. Must be non-NULL.
+ * *pDomainName"
+ * Address at which the domainName is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an InfoAccess Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_InfoAccess_ParseLocation(
+ PKIX_PL_GeneralName *gName,
+ PLArenaPool *arena,
+ LDAPRequestParams *request,
+ char **pDomainName,
+ void *plContext)
+{
+ PKIX_PL_String *locationString = NULL;
+ PKIX_UInt32 len = 0;
+ PKIX_UInt32 ncIndex = 0;
+ char *domainName = NULL;
+ char **avaArray = NULL;
+ char **attrArray = NULL;
+ char *attr = NULL;
+ char *locationAscii = NULL;
+ char *startPos = NULL;
+ char *endPos = NULL;
+ char *avaPtr = NULL;
+ LdapAttrMask attrBit = 0;
+ LDAPNameComponent **setOfNameComponent = NULL;
+ LDAPNameComponent *nameComponent = NULL;
+
+ PKIX_ENTER(INFOACCESS, "pkix_pl_InfoAccess_ParseLocation");
+ PKIX_NULLCHECK_FOUR(gName, arena, request, pDomainName);
+
+ PKIX_TOSTRING(gName, &locationString, plContext,
+ PKIX_GENERALNAMETOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (locationString,
+ PKIX_ESCASCII,
+ (void **)&locationAscii,
+ &len,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ pkix_pl_UnescapeURL(locationAscii);
+
+ /* Skip "ldap:" */
+ endPos = locationAscii;
+ while (*endPos != ':' && *endPos != '\0') {
+ endPos++;
+ }
+ if (*endPos == '\0') {
+ PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGLOCATIONTYPE);
+ }
+
+ /* Skip "//" */
+ endPos++;
+ if (*endPos != '\0' && *(endPos+1) != '0' &&
+ *endPos == '/' && *(endPos+1) == '/') {
+ endPos += 2;
+ } else {
+ PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGDOUBLESLASH);
+ }
+
+ /* Get the server-site */
+ startPos = endPos;
+ while(*endPos != '/' && *(endPos) != '\0') {
+ endPos++;
+ }
+ if (*endPos == '\0') {
+ PKIX_ERROR(PKIX_GENERALNAMESTRINGMISSINGSERVERSITE);
+ }
+
+ len = endPos - startPos;
+ endPos++;
+
+ domainName = PORT_ArenaZAlloc(arena, len + 1);
+ if (!domainName) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ PORT_Memcpy(domainName, startPos, len);
+
+ domainName[len] = '\0';
+
+ *pDomainName = domainName;
+
+ /*
+ * Get a list of AttrValueAssertions (such as
+ * "cn=CommonName, o=Organization, c=US" into a null-terminated array
+ */
+ startPos = endPos;
+ PKIX_CHECK(pkix_pl_InfoAccess_ParseTokens
+ (arena,
+ &startPos,
+ (char ***) &avaArray,
+ ',',
+ '?',
+ plContext),
+ PKIX_INFOACCESSPARSETOKENSFAILED);
+
+ /* Count how many AVAs we have */
+ for (len = 0; avaArray[len] != NULL; len++) {}
+
+ if (len < 2) {
+ PKIX_ERROR(PKIX_NOTENOUGHNAMECOMPONENTSINGENERALNAME);
+ }
+
+ /* Use last name component for baseObject */
+ request->baseObject = avaArray[len - 1];
+
+ /* Use only one component for filter. LDAP servers aren't too smart. */
+ len = 2; /* Eliminate this when servers get smarter. */
+
+ avaArray[len - 1] = NULL;
+
+ /* Get room for null-terminated array of (LdapNameComponent *) */
+ setOfNameComponent = PORT_ArenaZNewArray(arena, LDAPNameComponent *, len);
+ if (setOfNameComponent == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ /* Get room for the remaining LdapNameComponents */
+ nameComponent = PORT_ArenaZNewArray(arena, LDAPNameComponent, --len);
+ if (nameComponent == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ /* Convert remaining AVAs to LDAPNameComponents */
+ for (ncIndex = 0; ncIndex < len; ncIndex ++) {
+ setOfNameComponent[ncIndex] = nameComponent;
+ avaPtr = avaArray[ncIndex];
+ nameComponent->attrType = (unsigned char *)avaPtr;
+ while ((*avaPtr != '=') && (*avaPtr != '\0')) {
+ avaPtr++;
+ if (*avaPtr == '\0') {
+ PKIX_ERROR(PKIX_NAMECOMPONENTWITHNOEQ);
+ }
+ }
+ *(avaPtr++) = '\0';
+ nameComponent->attrValue = (unsigned char *)avaPtr;
+ nameComponent++;
+ }
+
+ setOfNameComponent[len] = NULL;
+ request->nc = setOfNameComponent;
+
+ /*
+ * Get a list of AttrTypes (such as
+ * "caCertificate;binary, crossCertificatePair;binary") into
+ * a null-terminated array
+ */
+
+ PKIX_CHECK(pkix_pl_InfoAccess_ParseTokens
+ (arena,
+ (char **) &startPos,
+ (char ***) &attrArray,
+ ',',
+ '\0',
+ plContext),
+ PKIX_INFOACCESSPARSETOKENSFAILED);
+
+ /* Convert array of Attr Types into a bit mask */
+ request->attributes = 0;
+ attr = attrArray[0];
+ while (attr != NULL) {
+ PKIX_CHECK(pkix_pl_LdapRequest_AttrStringToBit
+ (attr, &attrBit, plContext),
+ PKIX_LDAPREQUESTATTRSTRINGTOBITFAILED);
+ request->attributes |= attrBit;
+ attr = *(++attrArray);
+ }
+
+cleanup:
+
+ PKIX_PL_Free(locationAscii, plContext);
+ PKIX_DECREF(locationString);
+
+ PKIX_RETURN(INFOACCESS);
+}
+#endif /* !NSS_PKIX_NO_LDAP */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.h
new file mode 100644
index 0000000000..e69d7b4139
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_infoaccess.h
@@ -0,0 +1,49 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_infoaccess.h
+ *
+ * InfoAccess Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_INFOACCESS_H
+#define _PKIX_PL_INFOACCESS_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_InfoAccessStruct{
+ PKIX_UInt32 method;
+ PKIX_PL_GeneralName *location;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_InfoAccess_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_InfoAccess_CreateList(
+ CERTAuthInfoAccess **authInfoAccess,
+ PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */
+ void *plContext);
+
+#ifndef NSS_PKIX_NO_LDAP
+PKIX_Error *
+pkix_pl_InfoAccess_ParseLocation(
+ PKIX_PL_GeneralName *generalName,
+ PLArenaPool *arena,
+ LDAPRequestParams *request,
+ char **pDomainName,
+ void *plContext);
+#endif /* !NSS_PKIX_NO_LDAP */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_INFOACCESS_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.c
new file mode 100644
index 0000000000..1d0b61bb44
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.c
@@ -0,0 +1,1279 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_nameconstraints.c
+ *
+ * Name Constraints Object Functions Definitions
+ *
+ */
+
+#include "pkix_pl_nameconstraints.h"
+
+
+/* --Private-NameConstraints-Functions----------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_GetPermitted
+ * DESCRIPTION:
+ *
+ * This function retrieve name constraints permitted list from NSS
+ * data in "nameConstraints" and returns a PKIX_PL_GeneralName list
+ * in "pPermittedList".
+ *
+ * PARAMETERS
+ * "nameConstraints"
+ * Address of CertNameConstraints which has a pointer to
+ * CERTNameConstraints data. Must be non-NULL.
+ * "pPermittedList"
+ * Address where returned permitted name list is stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_GetPermitted(
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_List **pPermittedList,
+ void *plContext)
+{
+ CERTNameConstraints *nssNameConstraints = NULL;
+ CERTNameConstraints **nssNameConstraintsList = NULL;
+ CERTNameConstraint *nssPermitted = NULL;
+ CERTNameConstraint *firstPermitted = NULL;
+ PKIX_List *permittedList = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_GetPermitted");
+ PKIX_NULLCHECK_TWO(nameConstraints, pPermittedList);
+
+ /*
+ * nssNameConstraints is an array of CERTNameConstraints
+ * pointers where CERTNameConstraints keep its permitted and excluded
+ * lists as pointer array of CERTNameConstraint.
+ */
+
+ if (nameConstraints->permittedList == NULL) {
+
+ PKIX_OBJECT_LOCK(nameConstraints);
+
+ if (nameConstraints->permittedList == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&permittedList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ numItems = nameConstraints->numNssNameConstraints;
+ nssNameConstraintsList =
+ nameConstraints->nssNameConstraintsList;
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_NULLCHECK_ONE(nssNameConstraintsList);
+ nssNameConstraints = *(nssNameConstraintsList + i);
+ PKIX_NULLCHECK_ONE(nssNameConstraints);
+
+ if (nssNameConstraints->permited != NULL) {
+
+ nssPermitted = nssNameConstraints->permited;
+ firstPermitted = nssPermitted;
+
+ do {
+
+ PKIX_CHECK(pkix_pl_GeneralName_Create
+ (&nssPermitted->name, &name, plContext),
+ PKIX_GENERALNAMECREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (permittedList,
+ (PKIX_PL_Object *)name,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(name);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_GetNextNameConstraint\n");
+ nssPermitted = CERT_GetNextNameConstraint
+ (nssPermitted);
+
+ } while (nssPermitted != firstPermitted);
+
+ }
+ }
+
+ PKIX_CHECK(PKIX_List_SetImmutable(permittedList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ nameConstraints->permittedList = permittedList;
+
+ }
+
+ PKIX_OBJECT_UNLOCK(nameConstraints);
+
+ }
+
+ PKIX_INCREF(nameConstraints->permittedList);
+
+ *pPermittedList = nameConstraints->permittedList;
+
+cleanup:
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_GetExcluded
+ * DESCRIPTION:
+ *
+ * This function retrieve name constraints excluded list from NSS
+ * data in "nameConstraints" and returns a PKIX_PL_GeneralName list
+ * in "pExcludedList".
+ *
+ * PARAMETERS
+ * "nameConstraints"
+ * Address of CertNameConstraints which has a pointer to NSS data.
+ * Must be non-NULL.
+ * "pPermittedList"
+ * Address where returned excluded name list is stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_GetExcluded(
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_List **pExcludedList,
+ void *plContext)
+{
+ CERTNameConstraints *nssNameConstraints = NULL;
+ CERTNameConstraints **nssNameConstraintsList = NULL;
+ CERTNameConstraint *nssExcluded = NULL;
+ CERTNameConstraint *firstExcluded = NULL;
+ PKIX_List *excludedList = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_GetExcluded");
+ PKIX_NULLCHECK_TWO(nameConstraints, pExcludedList);
+
+ if (nameConstraints->excludedList == NULL) {
+
+ PKIX_OBJECT_LOCK(nameConstraints);
+
+ if (nameConstraints->excludedList == NULL) {
+
+ PKIX_CHECK(PKIX_List_Create(&excludedList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ numItems = nameConstraints->numNssNameConstraints;
+ nssNameConstraintsList =
+ nameConstraints->nssNameConstraintsList;
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_NULLCHECK_ONE(nssNameConstraintsList);
+ nssNameConstraints = *(nssNameConstraintsList + i);
+ PKIX_NULLCHECK_ONE(nssNameConstraints);
+
+ if (nssNameConstraints->excluded != NULL) {
+
+ nssExcluded = nssNameConstraints->excluded;
+ firstExcluded = nssExcluded;
+
+ do {
+
+ PKIX_CHECK(pkix_pl_GeneralName_Create
+ (&nssExcluded->name, &name, plContext),
+ PKIX_GENERALNAMECREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_AppendItem
+ (excludedList,
+ (PKIX_PL_Object *)name,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+
+ PKIX_DECREF(name);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_GetNextNameConstraint\n");
+ nssExcluded = CERT_GetNextNameConstraint
+ (nssExcluded);
+
+ } while (nssExcluded != firstExcluded);
+
+ }
+
+ }
+ PKIX_CHECK(PKIX_List_SetImmutable(excludedList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ nameConstraints->excludedList = excludedList;
+
+ }
+
+ PKIX_OBJECT_UNLOCK(nameConstraints);
+ }
+
+ PKIX_INCREF(nameConstraints->excludedList);
+
+ *pExcludedList = nameConstraints->excludedList;
+
+cleanup:
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_CheckNameSpaceNssNames
+ * DESCRIPTION:
+ *
+ * This function checks if CERTGeneralNames in "nssSubjectNames" comply
+ * with the permitted and excluded names in "nameConstraints". It returns
+ * PKIX_TRUE in "pCheckPass", if the Names satify the name space of the
+ * permitted list and if the Names are not in the excluded list. Otherwise,
+ * it returns PKIX_FALSE.
+ *
+ * PARAMETERS
+ * "nssSubjectNames"
+ * List of CERTGeneralName that nameConstraints verification is based on.
+ * "nameConstraints"
+ * Address of CertNameConstraints that provides lists of permitted
+ * and excluded names. Must be non-NULL.
+ * "pCheckPass"
+ * Address where PKIX_TRUE is returned if the all names in "nameList" are
+ * valid.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertNameConstraints_CheckNameSpaceNssNames(
+ CERTGeneralName *nssSubjectNames,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean *pCheckPass,
+ void *plContext)
+{
+ CERTNameConstraints **nssNameConstraintsList = NULL;
+ CERTNameConstraints *nssNameConstraints = NULL;
+ CERTGeneralName *nssMatchName = NULL;
+ PLArenaPool *arena = NULL;
+ PKIX_UInt32 numItems = 0;
+ PKIX_UInt32 i;
+ SECStatus status = SECSuccess;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_CheckNameSpaceNssNames");
+ PKIX_NULLCHECK_THREE(nssSubjectNames, nameConstraints, pCheckPass);
+
+ *pCheckPass = PKIX_TRUE;
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ nssMatchName = nssSubjectNames;
+ nssNameConstraintsList = nameConstraints->nssNameConstraintsList;
+
+ /*
+ * CERTNameConstraint items in each permitted or excluded list
+ * is verified as OR condition. That means, if one item matched,
+ * then the checking on the remaining items on the list is skipped.
+ * (see NSS cert_CompareNameWithConstraints(...)).
+ * Items on PKIX_PL_NameConstraint's nssNameConstraints are verified
+ * as AND condition. PKIX_PL_NameConstraint keeps an array of pointers
+ * of CERTNameConstraints resulting from merging multiple
+ * PKIX_PL_NameConstraints. Since each CERTNameConstraint are created
+ * for different entity, a union condition of these entities then is
+ * performed.
+ */
+
+ do {
+
+ numItems = nameConstraints->numNssNameConstraints;
+
+ for (i = 0; i < numItems; i++) {
+
+ PKIX_NULLCHECK_ONE(nssNameConstraintsList);
+ nssNameConstraints = *(nssNameConstraintsList + i);
+ PKIX_NULLCHECK_ONE(nssNameConstraints);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_CheckNameSpace\n");
+ status = CERT_CheckNameSpace
+ (arena, nssNameConstraints, nssMatchName);
+ if (status != SECSuccess) {
+ break;
+ }
+
+ }
+
+ if (status != SECSuccess) {
+ break;
+ }
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_GetNextGeneralName\n");
+ nssMatchName = CERT_GetNextGeneralName(nssMatchName);
+
+ } while (nssMatchName != nssSubjectNames);
+
+ if (status == SECFailure) {
+
+ *pCheckPass = PKIX_FALSE;
+ }
+
+cleanup:
+
+ if (arena){
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_NameConstraints_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext),
+ PKIX_OBJECTNOTCERTNAMECONSTRAINTS);
+
+ nameConstraints = (PKIX_PL_CertNameConstraints *)object;
+
+ PKIX_CHECK(PKIX_PL_Free
+ (nameConstraints->nssNameConstraintsList, plContext),
+ PKIX_FREEFAILED);
+
+ if (nameConstraints->arena){
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(nameConstraints->arena, PR_FALSE);
+ nameConstraints->arena = NULL;
+ }
+
+ PKIX_DECREF(nameConstraints->permittedList);
+ PKIX_DECREF(nameConstraints->excludedList);
+
+cleanup:
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the object
+ * NameConstraints and stores it at "pString".
+ *
+ * PARAMETERS
+ * "nameConstraints"
+ * Address of CertNameConstraints whose string representation is
+ * desired. Must be non-NULL.
+ * "pString"
+ * Address where string object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a
+ * non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_ToString_Helper(
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ char *asciiFormat = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_List *permittedList = NULL;
+ PKIX_List *excludedList = NULL;
+ PKIX_PL_String *permittedListString = NULL;
+ PKIX_PL_String *excludedListString = NULL;
+ PKIX_PL_String *nameConstraintsString = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_ToString_Helper");
+ PKIX_NULLCHECK_TWO(nameConstraints, pString);
+
+ asciiFormat =
+ "[\n"
+ "\t\tPermitted Name: %s\n"
+ "\t\tExcluded Name: %s\n"
+ "\t]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted
+ (nameConstraints, &permittedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED);
+
+ PKIX_TOSTRING(permittedList, &permittedListString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded
+ (nameConstraints, &excludedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED);
+
+ PKIX_TOSTRING(excludedList, &excludedListString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&nameConstraintsString,
+ plContext,
+ formatString,
+ permittedListString,
+ excludedListString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = nameConstraintsString;
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(permittedList);
+ PKIX_DECREF(excludedList);
+ PKIX_DECREF(permittedListString);
+ PKIX_DECREF(excludedListString);
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *nameConstraintsString = NULL;
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(
+ object, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext),
+ PKIX_OBJECTNOTCERTNAMECONSTRAINTS);
+
+ nameConstraints = (PKIX_PL_CertNameConstraints *)object;
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_ToString_Helper
+ (nameConstraints, &nameConstraintsString, plContext),
+ PKIX_CERTNAMECONSTRAINTSTOSTRINGHELPERFAILED);
+
+ *pString = nameConstraintsString;
+
+cleanup:
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ PKIX_List *permittedList = NULL;
+ PKIX_List *excludedList = NULL;
+ PKIX_UInt32 permitHash = 0;
+ PKIX_UInt32 excludeHash = 0;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType
+ (object, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext),
+ PKIX_OBJECTNOTCERTNAMECONSTRAINTS);
+
+ nameConstraints = (PKIX_PL_CertNameConstraints *)object;
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted
+ (nameConstraints, &permittedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED);
+
+ PKIX_HASHCODE(permittedList, &permitHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded
+ (nameConstraints, &excludedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED);
+
+ PKIX_HASHCODE(excludedList, &excludeHash, plContext,
+ PKIX_OBJECTHASHCODEFAILED);
+
+ *pHashcode = (((permitHash << 7) + excludeHash) << 7) +
+ nameConstraints->numNssNameConstraints;
+
+cleanup:
+
+ PKIX_DECREF(permittedList);
+ PKIX_DECREF(excludedList);
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *firstNC = NULL;
+ PKIX_PL_CertNameConstraints *secondNC = NULL;
+ PKIX_List *firstPermittedList = NULL;
+ PKIX_List *secondPermittedList = NULL;
+ PKIX_List *firstExcludedList = NULL;
+ PKIX_List *secondExcludedList = NULL;
+ PKIX_UInt32 secondType;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CertNameConstraints */
+ PKIX_CHECK(pkix_CheckType
+ (firstObject, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCERTNAMECONSTRAINTS);
+
+ firstNC = (PKIX_PL_CertNameConstraints *)firstObject;
+ secondNC = (PKIX_PL_CertNameConstraints *)secondObject;
+
+ /*
+ * Since we know firstObject is a CertNameConstraints, if both
+ * references are identical, they must be equal
+ */
+ if (firstNC == secondNC){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondNC isn't a CertNameConstraints, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ ((PKIX_PL_Object *)secondNC, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ if (secondType != PKIX_CERTNAMECONSTRAINTS_TYPE) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted
+ (firstNC, &firstPermittedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted
+ (secondNC, &secondPermittedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED);
+
+ PKIX_EQUALS
+ (firstPermittedList, secondPermittedList, &cmpResult, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE) {
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded
+ (firstNC, &firstExcludedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded
+ (secondNC, &secondExcludedList, plContext),
+ PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED);
+
+ PKIX_EQUALS
+ (firstExcludedList, secondExcludedList, &cmpResult, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+
+ if (cmpResult != PKIX_TRUE) {
+ goto cleanup;
+ }
+
+ /*
+ * numNssNameConstraints is not checked because it is basically a
+ * merge count, it cannot determine the data equality.
+ */
+
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_DECREF(firstPermittedList);
+ PKIX_DECREF(secondPermittedList);
+ PKIX_DECREF(firstExcludedList);
+ PKIX_DECREF(secondExcludedList);
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_CERTNAMECONSTRAINTS_TYPE and its related functions with
+ * systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CertNameConstraints_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_RegisterSelf");
+
+ entry.description = "CertNameConstraints";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_CertNameConstraints);
+ entry.destructor = pkix_pl_CertNameConstraints_Destroy;
+ entry.equalsFunction = pkix_pl_CertNameConstraints_Equals;
+ entry.hashcodeFunction = pkix_pl_CertNameConstraints_Hashcode;
+ entry.toStringFunction = pkix_pl_CertNameConstraints_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_CERTNAMECONSTRAINTS_TYPE] = entry;
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_Create_Helper
+ *
+ * DESCRIPTION:
+ * This function retrieves name constraints in "nssNameConstraints",
+ * converts and stores the result in a PKIX_PL_CertNameConstraints object.
+ *
+ * PARAMETERS
+ * "nssNameConstraints"
+ * Address of CERTNameConstraints that contains this object's data.
+ * Must be non-NULL.
+ * "pNameConstraints"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * A NULL value will be returned if there is no Name Constraints extension.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_Create_Helper(
+ CERTNameConstraints *nssNameConstraints,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ CERTNameConstraints **nssNameConstraintPtr = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_Create_Helper");
+ PKIX_NULLCHECK_TWO(nssNameConstraints, pNameConstraints);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CERTNAMECONSTRAINTS_TYPE,
+ sizeof (PKIX_PL_CertNameConstraints),
+ (PKIX_PL_Object **)&nameConstraints,
+ plContext),
+ PKIX_COULDNOTCREATECERTNAMECONSTRAINTSOBJECT);
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (sizeof (CERTNameConstraint *),
+ (void *)&nssNameConstraintPtr,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ nameConstraints->numNssNameConstraints = 1;
+ nameConstraints->nssNameConstraintsList = nssNameConstraintPtr;
+ *nssNameConstraintPtr = nssNameConstraints;
+
+ nameConstraints->permittedList = NULL;
+ nameConstraints->excludedList = NULL;
+ nameConstraints->arena = NULL;
+
+ *pNameConstraints = nameConstraints;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(nameConstraints);
+ }
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_Create
+ *
+ * DESCRIPTION:
+ * function that allocates and initialize the object CertNameConstraints.
+ *
+ * PARAMETERS
+ * "nssCert"
+ * Address of CERT that contains this object's data.
+ * Must be non-NULL.
+ * "pNameConstraints"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * A NULL value will be returned if there is no Name Constraints extension.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertNameConstraints_Create(
+ CERTCertificate *nssCert,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ CERTNameConstraints *nssNameConstraints = NULL;
+ PLArenaPool *arena = NULL;
+ SECStatus status;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Create");
+ PKIX_NULLCHECK_THREE(nssCert, pNameConstraints, nssCert->arena);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena).\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_FindNameConstraintsExten\n");
+ status = CERT_FindNameConstraintsExten
+ (arena, nssCert, &nssNameConstraints);
+
+ if (status != SECSuccess) {
+ PKIX_ERROR(PKIX_DECODINGCERTNAMECONSTRAINTSFAILED);
+ }
+
+ if (nssNameConstraints == NULL) {
+ *pNameConstraints = NULL;
+ /* we free the arnea here because PKIX_ERROR_RECEIVED
+ * may not be set. Setting arena to NULL makes sure
+ * we don't try to free it again (and makes scanners
+ * happy). */
+ if (arena){
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ arena = NULL;
+ }
+ goto cleanup;
+ }
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_Create_Helper
+ (nssNameConstraints, &nameConstraints, plContext),
+ PKIX_CERTNAMECONSTRAINTSCREATEHELPERFAILED);
+
+ nameConstraints->arena = arena;
+
+ *pNameConstraints = nameConstraints;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ if (arena){
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ }
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_CreateByMerge
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates and creates a PKIX_PL_NameConstraint object
+ * for merging. It also allocates CERTNameConstraints data space for the
+ * merged NSS NameConstraints data.
+ *
+ * PARAMETERS
+ * "pNameConstraints"
+ * Address where object pointer will be stored and returned.
+ * Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_CreateByMerge(
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ CERTNameConstraints *nssNameConstraints = NULL;
+ PLArenaPool *arena = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_CreateByMerge");
+ PKIX_NULLCHECK_ONE(pNameConstraints);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena).\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_ArenaZNew).\n");
+ nssNameConstraints = PORT_ArenaZNew(arena, CERTNameConstraints);
+ if (nssNameConstraints == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ nssNameConstraints->permited = NULL;
+ nssNameConstraints->excluded = NULL;
+ nssNameConstraints->DERPermited = NULL;
+ nssNameConstraints->DERExcluded = NULL;
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_Create_Helper
+ (nssNameConstraints, &nameConstraints, plContext),
+ PKIX_CERTNAMECONSTRAINTSCREATEHELPERFAILED);
+
+ nameConstraints->arena = arena;
+
+ *pNameConstraints = nameConstraints;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ if (arena){
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ }
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_CopyNssNameConstraints
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates and copies data to a NSS CERTNameConstraints from
+ * the NameConstraints given by "srcNC" and stores the result at "pDestNC". It
+ * copies items on both the permitted and excluded lists, but not the
+ * DERPermited and DERExcluded.
+ *
+ * PARAMETERS
+ * "arena"
+ * Memory pool where object data is allocated from. Must be non-NULL.
+ * "srcNC"
+ * Address of the NameConstraints to copy from. Must be non-NULL.
+ * "pDestNC"
+ * Address where new copied object is stored and returned.
+ * Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CertNameConstraints_CopyNssNameConstraints(
+ PLArenaPool *arena,
+ CERTNameConstraints *srcNC,
+ CERTNameConstraints **pDestNC,
+ void *plContext)
+{
+ CERTNameConstraints *nssNameConstraints = NULL;
+ CERTNameConstraint *nssNameConstraintHead = NULL;
+ CERTNameConstraint *nssCurrent = NULL;
+ CERTNameConstraint *nssCopyTo = NULL;
+ CERTNameConstraint *nssCopyFrom = NULL;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "pkix_pl_CertNameConstraints_CopyNssNameConstraints");
+ PKIX_NULLCHECK_THREE(arena, srcNC, pDestNC);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_ArenaZNew).\n");
+ nssNameConstraints = PORT_ArenaZNew(arena, CERTNameConstraints);
+ if (nssNameConstraints == NULL) {
+ PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
+ }
+
+ if (srcNC->permited) {
+
+ nssCopyFrom = srcNC->permited;
+
+ do {
+
+ nssCopyTo = NULL;
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_CopyNameConstraint).\n");
+ nssCopyTo = CERT_CopyNameConstraint
+ (arena, nssCopyTo, nssCopyFrom);
+ if (nssCopyTo == NULL) {
+ PKIX_ERROR(PKIX_CERTCOPYNAMECONSTRAINTFAILED);
+ }
+ if (nssCurrent == NULL) {
+ nssCurrent = nssNameConstraintHead = nssCopyTo;
+ } else {
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_AddNameConstraint).\n");
+ nssCurrent = CERT_AddNameConstraint
+ (nssCurrent, nssCopyTo);
+ }
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_GetNextNameConstrain).\n");
+ nssCopyFrom = CERT_GetNextNameConstraint(nssCopyFrom);
+
+ } while (nssCopyFrom != srcNC->permited);
+
+ nssNameConstraints->permited = nssNameConstraintHead;
+ }
+
+ if (srcNC->excluded) {
+
+ nssCurrent = NULL;
+ nssCopyFrom = srcNC->excluded;
+
+ do {
+
+ /*
+ * Cannot use CERT_DupGeneralNameList, which just increments
+ * refcount. We need our own copy since arena is for each
+ * PKIX_PL_NameConstraints. Perhaps contribute this code
+ * as CERT_CopyGeneralNameList (in the future).
+ */
+ nssCopyTo = NULL;
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_CopyNameConstraint).\n");
+ nssCopyTo = CERT_CopyNameConstraint
+ (arena, nssCopyTo, nssCopyFrom);
+ if (nssCopyTo == NULL) {
+ PKIX_ERROR(PKIX_CERTCOPYNAMECONSTRAINTFAILED);
+ }
+ if (nssCurrent == NULL) {
+ nssCurrent = nssNameConstraintHead = nssCopyTo;
+ } else {
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_AddNameConstraint).\n");
+ nssCurrent = CERT_AddNameConstraint
+ (nssCurrent, nssCopyTo);
+ }
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_GetNextNameConstrain).\n");
+ nssCopyFrom = CERT_GetNextNameConstraint(nssCopyFrom);
+
+ } while (nssCopyFrom != srcNC->excluded);
+
+ nssNameConstraints->excluded = nssNameConstraintHead;
+ }
+
+ *pDestNC = nssNameConstraints;
+
+cleanup:
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/*
+ * FUNCTION: pkix_pl_CertNameConstraints_Merge
+ *
+ * DESCRIPTION:
+ *
+ * This function merges two NameConstraints pointed to by "firstNC" and
+ * "secondNC" and stores the result in "pMergedNC".
+ *
+ * PARAMETERS
+ * "firstNC"
+ * Address of the first NameConstraints to be merged. Must be non-NULL.
+ * "secondNC"
+ * Address of the second NameConstraints to be merged. Must be non-NULL.
+ * "pMergedNC"
+ * Address where the merge result is stored and returned. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a NameConstraints Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CertNameConstraints_Merge(
+ PKIX_PL_CertNameConstraints *firstNC,
+ PKIX_PL_CertNameConstraints *secondNC,
+ PKIX_PL_CertNameConstraints **pMergedNC,
+ void *plContext)
+{
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+ CERTNameConstraints **nssNCto = NULL;
+ CERTNameConstraints **nssNCfrom = NULL;
+ CERTNameConstraints *nssNameConstraints = NULL;
+ PKIX_UInt32 numNssItems = 0;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Merge");
+ PKIX_NULLCHECK_THREE(firstNC, secondNC, pMergedNC);
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_CreateByMerge
+ (&nameConstraints, plContext),
+ PKIX_CERTNAMECONSTRAINTSCREATEBYMERGEFAILED);
+
+ /* Merge NSSCertConstraint lists */
+
+ numNssItems = firstNC->numNssNameConstraints +
+ secondNC->numNssNameConstraints;
+
+ /* Free the default space (only one entry) allocated by create */
+ PKIX_CHECK(PKIX_PL_Free
+ (nameConstraints->nssNameConstraintsList, plContext),
+ PKIX_FREEFAILED);
+
+ /* Reallocate the size we need */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (numNssItems * sizeof (CERTNameConstraint *),
+ (void *)&nssNCto,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ nameConstraints->nssNameConstraintsList = nssNCto;
+
+ nssNCfrom = firstNC->nssNameConstraintsList;
+
+ for (i = 0; i < firstNC->numNssNameConstraints; i++) {
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_CopyNssNameConstraints
+ (nameConstraints->arena,
+ *nssNCfrom,
+ &nssNameConstraints,
+ plContext),
+ PKIX_CERTNAMECONSTRAINTSCOPYNSSNAMECONSTRAINTSFAILED);
+
+ *nssNCto = nssNameConstraints;
+
+ nssNCto++;
+ nssNCfrom++;
+ }
+
+ nssNCfrom = secondNC->nssNameConstraintsList;
+
+ for (i = 0; i < secondNC->numNssNameConstraints; i++) {
+
+ PKIX_CHECK(pkix_pl_CertNameConstraints_CopyNssNameConstraints
+ (nameConstraints->arena,
+ *nssNCfrom,
+ &nssNameConstraints,
+ plContext),
+ PKIX_CERTNAMECONSTRAINTSCOPYNSSNAMECONSTRAINTSFAILED);
+
+ *nssNCto = nssNameConstraints;
+
+ nssNCto++;
+ nssNCfrom++;
+ }
+
+ nameConstraints->numNssNameConstraints = numNssItems;
+ nameConstraints->permittedList = NULL;
+ nameConstraints->excludedList = NULL;
+
+ *pMergedNC = nameConstraints;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(nameConstraints);
+ }
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
+
+/* --Public-NameConstraints-Functions-------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_CertNameConstraints_CheckNamesInNameSpace
+ * (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_CertNameConstraints_CheckNamesInNameSpace(
+ PKIX_List *nameList, /* List of PKIX_PL_GeneralName */
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean *pCheckPass,
+ void *plContext)
+{
+ CERTNameConstraints **nssNameConstraintsList = NULL;
+ CERTNameConstraints *nssNameConstraints = NULL;
+ CERTGeneralName *nssMatchName = NULL;
+ PLArenaPool *arena = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+ PKIX_UInt32 numNameItems = 0;
+ PKIX_UInt32 numNCItems = 0;
+ PKIX_UInt32 i, j;
+ SECStatus status = SECSuccess;
+
+ PKIX_ENTER(CERTNAMECONSTRAINTS,
+ "PKIX_PL_CertNameConstraints_CheckNamesInNameSpace");
+ PKIX_NULLCHECK_TWO(nameConstraints, pCheckPass);
+
+ *pCheckPass = PKIX_TRUE;
+
+ if (nameList != NULL) {
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ nssNameConstraintsList =
+ nameConstraints->nssNameConstraintsList;
+ PKIX_NULLCHECK_ONE(nssNameConstraintsList);
+ numNCItems = nameConstraints->numNssNameConstraints;
+
+ PKIX_CHECK(PKIX_List_GetLength
+ (nameList, &numNameItems, plContext),
+ PKIX_LISTGETLENGTHFAILED);
+
+ for (i = 0; i < numNameItems; i++) {
+
+ PKIX_CHECK(PKIX_List_GetItem
+ (nameList,
+ i,
+ (PKIX_PL_Object **) &name,
+ plContext),
+ PKIX_LISTGETITEMFAILED);
+
+ PKIX_CHECK(pkix_pl_GeneralName_GetNssGeneralName
+ (name, &nssMatchName, plContext),
+ PKIX_GENERALNAMEGETNSSGENERALNAMEFAILED);
+
+ PKIX_DECREF(name);
+
+ for (j = 0; j < numNCItems; j++) {
+
+ nssNameConstraints = *(nssNameConstraintsList + j);
+ PKIX_NULLCHECK_ONE(nssNameConstraints);
+
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling CERT_CheckNameSpace\n");
+ status = CERT_CheckNameSpace
+ (arena, nssNameConstraints, nssMatchName);
+ if (status != SECSuccess) {
+ break;
+ }
+
+ }
+
+ if (status != SECSuccess) {
+ break;
+ }
+
+ }
+ }
+
+ if (status == SECFailure) {
+ *pCheckPass = PKIX_FALSE;
+ }
+
+cleanup:
+
+ if (arena){
+ PKIX_CERTNAMECONSTRAINTS_DEBUG
+ ("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ PKIX_RETURN(CERTNAMECONSTRAINTS);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.h
new file mode 100644
index 0000000000..2f305ac10a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_nameconstraints.h
@@ -0,0 +1,68 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_nameconstraints.h
+ *
+ * Name Constraints Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_NAMECONSTRAINTS_H
+#define _PKIX_PL_NAMECONSTRAINTS_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_CertNameConstraintsStruct {
+ PLArenaPool *arena;
+ CERTNameConstraints **nssNameConstraintsList;
+ PKIX_UInt32 numNssNameConstraints;
+ PKIX_List *permittedList; /* list of PKIX_PL_GeneralName */
+ PKIX_List *excludedList; /* list of PKIX_PL_GeneralName */
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_CertNameConstraints_RegisterSelf(void *plContext);
+
+PKIX_Error *pkix_pl_CertNameConstraints_Create(
+ CERTCertificate *nssCert,
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertNameConstraints_CreateWithNames(
+ PKIX_List *names, /* List of PKIX_PL_GeneralName */
+ PKIX_PL_CertNameConstraints **pNameConstraints,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertNameConstraints_CheckNameSpaceNssNames(
+ CERTGeneralName *nssSubjectNames,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean *pCheckPass,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_CertNameConstraints_CheckNameSpacePkixNames(
+ PKIX_List *nameList,
+ PKIX_PL_CertNameConstraints *nameConstraints,
+ PKIX_Boolean *pCheckPass,
+ void *plContext);
+
+
+PKIX_Error *pkix_pl_CertNameConstraints_Merge(
+ PKIX_PL_CertNameConstraints *firstNC,
+ PKIX_PL_CertNameConstraints *secondNC,
+ PKIX_PL_CertNameConstraints **pMergedNC,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_NAMECONSTRAINTS_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.c
new file mode 100644
index 0000000000..679811dec1
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.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/. */
+/*
+ * pkix_pl_ocspcertid.c
+ *
+ * Certificate ID Object for OCSP
+ *
+ */
+
+#include "pkix_pl_ocspcertid.h"
+
+/* --Private-Cert-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_OcspCertID_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspCertID_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_OcspCertID *certID = NULL;
+
+ PKIX_ENTER(OCSPCERTID, "pkix_pl_OcspCertID_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPCERTID_TYPE, plContext),
+ PKIX_OBJECTNOTOCSPCERTID);
+
+ certID = (PKIX_PL_OcspCertID *)object;
+
+ if (certID->certID) {
+ CERT_DestroyOCSPCertID(certID->certID);
+ }
+
+cleanup:
+
+ PKIX_RETURN(OCSPCERTID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspCertID_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_PUBLICKEY_TYPE and its related functions
+ * with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_OcspCertID_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(OCSPCERTID, "pkix_pl_OcspCertID_RegisterSelf");
+
+ entry.description = "OcspCertID";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_OcspCertID);
+ entry.destructor = pkix_pl_OcspCertID_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+ systemClasses[PKIX_OCSPCERTID_TYPE] = entry;
+
+ PKIX_RETURN(OCSPCERTID);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_OcspCertID_Create
+ * DESCRIPTION:
+ *
+ * This function creates an OcspCertID for a given certificate,
+ * to be used with OCSP transactions.
+ *
+ * If a Date is provided in "validity" it may be used in the search for the
+ * issuer of "cert" but has no effect on the request itself.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of the Cert for which an OcspCertID is to be created. Must be
+ * non-NULL.
+ * "validity"
+ * Address of the Date for which the Cert's validity is to be determined.
+ * May be NULL.
+ * "object"
+ * Address at which the result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspCertID Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_OcspCertID_Create(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Date *validity,
+ PKIX_PL_OcspCertID **object,
+ void *plContext)
+{
+ PKIX_PL_OcspCertID *cid = NULL;
+ PRTime time = 0;
+
+ PKIX_ENTER(DATE, "PKIX_PL_OcspCertID_Create");
+ PKIX_NULLCHECK_TWO(cert, object);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_OCSPCERTID_TYPE,
+ sizeof (PKIX_PL_OcspCertID),
+ (PKIX_PL_Object **)&cid,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ if (validity != NULL) {
+ PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext),
+ PKIX_DATEGETPRTIMEFAILED);
+ } else {
+ time = PR_Now();
+ }
+
+ cid->certID = CERT_CreateOCSPCertID(cert->nssCert, time);
+ if (!cid->certID) {
+ PKIX_ERROR(PKIX_COULDNOTCREATEOBJECT);
+ }
+
+ *object = cid;
+ cid = NULL;
+cleanup:
+ PKIX_DECREF(cid);
+ PKIX_RETURN(OCSPCERTID);
+}
+
+/*
+ * FUNCTION: PKIX_PL_OcspCertID_GetFreshCacheStatus
+ * DESCRIPTION:
+ *
+ * This function may return cached OCSP results for the provided
+ * certificate, but only if stored information is still considered to be
+ * fresh.
+ *
+ * PARAMETERS
+ * "cid"
+ * A certificate ID as used by OCSP
+ * "validity"
+ * Optional date parameter to request validity for a specifc time.
+ * "hasFreshStatus"
+ * Output parameter, if the function successed to find fresh cached
+ * information, this will be set to true. Must be non-NULL.
+ * "statusIsGood"
+ * The good/bad result stored in the cache. Must be non-NULL.
+ * "missingResponseError"
+ * If OCSP status is "bad", this variable may indicate the exact
+ * reason why the previous OCSP request had failed.
+ * "plContext"
+ * Platform-specific context pointer.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspCertID Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_OcspCertID_GetFreshCacheStatus(
+ PKIX_PL_OcspCertID *cid,
+ PKIX_PL_Date *validity,
+ PKIX_Boolean *hasFreshStatus,
+ PKIX_Boolean *statusIsGood,
+ SECErrorCodes *missingResponseError,
+ void *plContext)
+{
+ PRTime time = 0;
+ SECStatus rv;
+ SECStatus rvOcsp;
+ OCSPFreshness freshness;
+
+ PKIX_ENTER(DATE, "PKIX_PL_OcspCertID_GetFreshCacheStatus");
+ PKIX_NULLCHECK_THREE(cid, hasFreshStatus, statusIsGood);
+
+ if (validity != NULL) {
+ PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext),
+ PKIX_DATEGETPRTIMEFAILED);
+ } else {
+ time = PR_Now();
+ }
+
+ rv = ocsp_GetCachedOCSPResponseStatus(
+ cid->certID, time, PR_TRUE, /*ignoreGlobalOcspFailureSetting*/
+ &rvOcsp, missingResponseError, &freshness);
+
+ *hasFreshStatus = (rv == SECSuccess && freshness == ocspFresh);
+ if (*hasFreshStatus) {
+ *statusIsGood = (rvOcsp == SECSuccess);
+ }
+cleanup:
+ PKIX_RETURN(OCSPCERTID);
+}
+
+/*
+ * FUNCTION: PKIX_PL_OcspCertID_RememberOCSPProcessingFailure
+ * DESCRIPTION:
+ *
+ * Information about the current failure associated to the given certID
+ * will be remembered in the cache, potentially allowing future calls
+ * to prevent repetitive OCSP requests.
+ * After this function got called, it may no longer be safe to
+ * use the provided cid parameter, because ownership might have been
+ * transfered to the cache. This status will be recorded inside the
+ * cid object.
+ *
+ * PARAMETERS
+ * "cid"
+ * The certificate ID associated to a failed OCSP processing.
+ * "plContext"
+ * Platform-specific context pointer.
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspCertID Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+PKIX_PL_OcspCertID_RememberOCSPProcessingFailure(
+ PKIX_PL_OcspCertID *cid,
+ void *plContext)
+{
+ PRBool certIDWasConsumed = PR_FALSE;
+
+ PKIX_ENTER(DATE, "PKIX_PL_OcspCertID_RememberOCSPProcessingFailure");
+ PKIX_NULLCHECK_TWO(cid, cid->certID);
+
+ cert_RememberOCSPProcessingFailure(cid->certID, &certIDWasConsumed);
+
+ if (certIDWasConsumed) {
+ cid->certID = NULL;
+ }
+
+ PKIX_RETURN(OCSPCERTID);
+}
+
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.h
new file mode 100644
index 0000000000..772a12b25f
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspcertid.h
@@ -0,0 +1,53 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_ocspcertid.h
+ *
+ * Public Key Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_OCSPCERTID_H
+#define _PKIX_PL_OCSPCERTID_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_OcspCertIDStruct {
+ CERTOCSPCertID *certID;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_OcspCertID_RegisterSelf(void *plContext);
+
+PKIX_Error *
+PKIX_PL_OcspCertID_Create(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_Date *validity,
+ PKIX_PL_OcspCertID **object,
+ void *plContext);
+
+PKIX_Error *
+PKIX_PL_OcspCertID_GetFreshCacheStatus(
+ PKIX_PL_OcspCertID *cid,
+ PKIX_PL_Date *validity,
+ PKIX_Boolean *hasFreshStatus,
+ PKIX_Boolean *statusIsGood,
+ SECErrorCodes *missingResponseError,
+ void *plContext);
+
+PKIX_Error *
+PKIX_PL_OcspCertID_RememberOCSPProcessingFailure(
+ PKIX_PL_OcspCertID *cid,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_OCSPCERTID_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.c
new file mode 100644
index 0000000000..28b6953a76
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.c
@@ -0,0 +1,441 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_ocsprequest.c
+ *
+ */
+
+#include "pkix_pl_ocsprequest.h"
+
+/* --Private-OcspRequest-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspRequest_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_OcspRequest *ocspReq = NULL;
+
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPREQUEST_TYPE, plContext),
+ PKIX_OBJECTNOTOCSPREQUEST);
+
+ ocspReq = (PKIX_PL_OcspRequest *)object;
+
+ if (ocspReq->decoded != NULL) {
+ CERT_DestroyOCSPRequest(ocspReq->decoded);
+ }
+
+ if (ocspReq->encoded != NULL) {
+ SECITEM_FreeItem(ocspReq->encoded, PR_TRUE);
+ }
+
+ if (ocspReq->location != NULL) {
+ PORT_Free(ocspReq->location);
+ }
+
+ PKIX_DECREF(ocspReq->cert);
+ PKIX_DECREF(ocspReq->validity);
+ PKIX_DECREF(ocspReq->signerCert);
+
+cleanup:
+
+ PKIX_RETURN(OCSPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspRequest_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_UInt32 certHash = 0;
+ PKIX_UInt32 dateHash = 0;
+ PKIX_UInt32 extensionHash = 0;
+ PKIX_UInt32 signerHash = 0;
+ PKIX_PL_OcspRequest *ocspRq = NULL;
+
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPREQUEST_TYPE, plContext),
+ PKIX_OBJECTNOTOCSPREQUEST);
+
+ ocspRq = (PKIX_PL_OcspRequest *)object;
+
+ *pHashcode = 0;
+
+ PKIX_HASHCODE(ocspRq->cert, &certHash, plContext,
+ PKIX_CERTHASHCODEFAILED);
+
+ PKIX_HASHCODE(ocspRq->validity, &dateHash, plContext,
+ PKIX_DATEHASHCODEFAILED);
+
+ if (ocspRq->addServiceLocator == PKIX_TRUE) {
+ extensionHash = 0xff;
+ }
+
+ PKIX_HASHCODE(ocspRq->signerCert, &signerHash, plContext,
+ PKIX_CERTHASHCODEFAILED);
+
+ *pHashcode = (((((extensionHash << 8) | certHash) << 8) |
+ dateHash) << 8) | signerHash;
+
+cleanup:
+
+ PKIX_RETURN(OCSPREQUEST);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspRequest_Equals(
+ PKIX_PL_Object *firstObj,
+ PKIX_PL_Object *secondObj,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_Boolean match = PKIX_FALSE;
+ PKIX_UInt32 secondType = 0;
+ PKIX_PL_OcspRequest *firstReq = NULL;
+ PKIX_PL_OcspRequest *secondReq = NULL;
+
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Equals");
+ PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
+
+ /* test that firstObj is a OcspRequest */
+ PKIX_CHECK(pkix_CheckType(firstObj, PKIX_OCSPREQUEST_TYPE, plContext),
+ PKIX_FIRSTOBJARGUMENTNOTOCSPREQUEST);
+
+ /*
+ * Since we know firstObj is a OcspRequest, if both references are
+ * identical, they must be equal
+ */
+ if (firstObj == secondObj){
+ match = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObj isn't a OcspRequest, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObj, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_OCSPREQUEST_TYPE) {
+ goto cleanup;
+ }
+
+ firstReq = (PKIX_PL_OcspRequest *)firstObj;
+ secondReq = (PKIX_PL_OcspRequest *)secondObj;
+
+ if (firstReq->addServiceLocator != secondReq->addServiceLocator) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS(firstReq->cert, secondReq->cert, &match, plContext,
+ PKIX_CERTEQUALSFAILED);
+
+ if (match == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS(firstReq->validity, secondReq->validity, &match, plContext,
+ PKIX_DATEEQUALSFAILED);
+
+ if (match == PKIX_FALSE) {
+ goto cleanup;
+ }
+
+ PKIX_EQUALS
+ (firstReq->signerCert, secondReq->signerCert, &match, plContext,
+ PKIX_CERTEQUALSFAILED);
+
+cleanup:
+
+ *pResult = match;
+
+ PKIX_RETURN(OCSPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_OCSPREQUEST_TYPE and its related functions with
+ * systemClasses[]
+ * PARAMETERS:
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_OcspRequest_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_RegisterSelf");
+
+ entry.description = "OcspRequest";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_OcspRequest);
+ entry.destructor = pkix_pl_OcspRequest_Destroy;
+ entry.equalsFunction = pkix_pl_OcspRequest_Equals;
+ entry.hashcodeFunction = pkix_pl_OcspRequest_Hashcode;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_OCSPREQUEST_TYPE] = entry;
+
+ PKIX_RETURN(OCSPREQUEST);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_Create
+ * DESCRIPTION:
+ *
+ * This function creates an OcspRequest to be used in validating the Cert
+ * pointed to by "cert" and storing the result at "pRequest". If a URI
+ * is found for an OCSP responder, PKIX_TRUE is stored at "pURIFound". If no
+ * URI is found, PKIX_FALSE is stored.
+ *
+ * If a Date is provided in "validity" it may be used in the search for the
+ * issuer of "cert" but has no effect on the request itself. If
+ * "addServiceLocator" is TRUE, the AddServiceLocator extension will be
+ * included in the Request. If "signerCert" is provided it will be used to sign
+ * the Request. (Note: this signed request feature is not currently supported.)
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of the Cert for which an OcspRequest is to be created. Must be
+ * non-NULL.
+ * "validity"
+ * Address of the Date for which the Cert's validity is to be determined.
+ * May be NULL.
+ * "signerCert"
+ * Address of the Cert to be used, if present, in signing the request.
+ * May be NULL.
+ * "pRequest"
+ * Address at which the result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspRequest Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_OcspRequest_Create(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_OcspCertID *cid,
+ PKIX_PL_Date *validity,
+ PKIX_PL_Cert *signerCert,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean *pURIFound,
+ PKIX_PL_OcspRequest **pRequest,
+ void *plContext)
+{
+ PKIX_PL_OcspRequest *ocspRequest = NULL;
+
+ CERTCertDBHandle *handle = NULL;
+ SECStatus rv = SECFailure;
+ SECItem *encoding = NULL;
+ CERTOCSPRequest *certRequest = NULL;
+ PRTime time = 0;
+ PRBool addServiceLocatorExtension = PR_FALSE;
+ CERTCertificate *nssCert = NULL;
+ CERTCertificate *nssSignerCert = NULL;
+ char *location = NULL;
+ PRErrorCode locError = 0;
+ PKIX_Boolean canUseDefaultSource = PKIX_FALSE;
+
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Create");
+ PKIX_NULLCHECK_TWO(cert, pRequest);
+
+ /* create a PKIX_PL_OcspRequest object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_OCSPREQUEST_TYPE,
+ sizeof (PKIX_PL_OcspRequest),
+ (PKIX_PL_Object **)&ocspRequest,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ PKIX_INCREF(cert);
+ ocspRequest->cert = cert;
+
+ PKIX_INCREF(validity);
+ ocspRequest->validity = validity;
+
+ PKIX_INCREF(signerCert);
+ ocspRequest->signerCert = signerCert;
+
+ ocspRequest->decoded = NULL;
+ ocspRequest->encoded = NULL;
+
+ ocspRequest->location = NULL;
+
+ nssCert = cert->nssCert;
+
+ /*
+ * Does this Cert have an Authority Information Access extension with
+ * the URI of an OCSP responder?
+ */
+ handle = CERT_GetDefaultCertDB();
+
+ if (!(methodFlags & PKIX_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE)) {
+ canUseDefaultSource = PKIX_TRUE;
+ }
+ location = ocsp_GetResponderLocation(handle, nssCert,
+ canUseDefaultSource,
+ &addServiceLocatorExtension);
+ if (location == NULL) {
+ locError = PORT_GetError();
+ if (locError == SEC_ERROR_EXTENSION_NOT_FOUND ||
+ locError == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) {
+ PORT_SetError(0);
+ *pURIFound = PKIX_FALSE;
+ goto cleanup;
+ }
+ PKIX_ERROR(PKIX_ERRORFINDINGORPROCESSINGURI);
+ }
+
+ ocspRequest->location = location;
+ *pURIFound = PKIX_TRUE;
+
+ if (signerCert != NULL) {
+ nssSignerCert = signerCert->nssCert;
+ }
+
+ if (validity != NULL) {
+ PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext),
+ PKIX_DATEGETPRTIMEFAILED);
+ } else {
+ time = PR_Now();
+ }
+
+ certRequest = cert_CreateSingleCertOCSPRequest(
+ cid->certID, cert->nssCert, time,
+ addServiceLocatorExtension, nssSignerCert);
+
+ ocspRequest->decoded = certRequest;
+
+ if (certRequest == NULL) {
+ PKIX_ERROR(PKIX_UNABLETOCREATECERTOCSPREQUEST);
+ }
+
+ rv = CERT_AddOCSPAcceptableResponses(
+ certRequest, SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
+
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_UNABLETOADDACCEPTABLERESPONSESTOREQUEST);
+ }
+
+ encoding = CERT_EncodeOCSPRequest(NULL, certRequest, NULL);
+
+ ocspRequest->encoded = encoding;
+
+ *pRequest = ocspRequest;
+ ocspRequest = NULL;
+
+cleanup:
+ PKIX_DECREF(ocspRequest);
+
+ PKIX_RETURN(OCSPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_GetEncoded
+ * DESCRIPTION:
+ *
+ * This function obtains the encoded message from the OcspRequest pointed to
+ * by "request", storing the result at "pRequest".
+ *
+ * PARAMETERS
+ * "request"
+ * The address of the OcspRequest whose encoded message is to be
+ * retrieved. Must be non-NULL.
+ * "pRequest"
+ * The address at which is stored the address of the encoded message. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_OcspRequest_GetEncoded(
+ PKIX_PL_OcspRequest *request,
+ SECItem **pRequest,
+ void *plContext)
+{
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_GetEncoded");
+ PKIX_NULLCHECK_TWO(request, pRequest);
+
+ *pRequest = request->encoded;
+
+ PKIX_RETURN(OCSPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspRequest_GetLocation
+ * DESCRIPTION:
+ *
+ * This function obtains the location from the OcspRequest pointed to
+ * by "request", storing the result at "pLocation".
+ *
+ * PARAMETERS
+ * "request"
+ * The address of the OcspRequest whose encoded message is to be
+ * retrieved. Must be non-NULL.
+ * "pLocation"
+ * The address at which is stored the address of the location. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_OcspRequest_GetLocation(
+ PKIX_PL_OcspRequest *request,
+ char **pLocation,
+ void *plContext)
+{
+ PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_GetLocation");
+ PKIX_NULLCHECK_TWO(request, pLocation);
+
+ *pLocation = request->location;
+
+ PKIX_RETURN(OCSPREQUEST);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.h
new file mode 100644
index 0000000000..fa79266eec
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocsprequest.h
@@ -0,0 +1,61 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_ocsprequest.h
+ *
+ * OcspRequest Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_OCSPREQUEST_H
+#define _PKIX_PL_OCSPREQUEST_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_OcspRequestStruct{
+ PKIX_PL_Cert *cert;
+ PKIX_PL_Date *validity;
+ PKIX_Boolean addServiceLocator;
+ PKIX_PL_Cert *signerCert;
+ CERTOCSPRequest *decoded;
+ SECItem *encoded;
+ char *location;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_OcspRequest_Create(
+ PKIX_PL_Cert *cert,
+ PKIX_PL_OcspCertID *cid,
+ PKIX_PL_Date *validity,
+ PKIX_PL_Cert *signerCert,
+ PKIX_UInt32 methodFlags,
+ PKIX_Boolean *pURIFound,
+ PKIX_PL_OcspRequest **pRequest,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspRequest_GetEncoded(
+ PKIX_PL_OcspRequest *request,
+ SECItem **pRequest,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspRequest_GetLocation(
+ PKIX_PL_OcspRequest *request,
+ char **pLocation,
+ void *plContext);
+
+PKIX_Error *pkix_pl_OcspRequest_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_OCSPREQUEST_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c
new file mode 100644
index 0000000000..fa41f8102e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.c
@@ -0,0 +1,1069 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_ocspresponse.c
+ *
+ */
+
+#include "pkix_pl_ocspresponse.h"
+
+/* ----Public functions------------------------------------- */
+/*
+ * This is the libpkix replacement for CERT_VerifyOCSPResponseSignature.
+ * It is used if it has been set as the verifyFcn member of ocspChecker.
+ */
+PKIX_Error *
+PKIX_PL_OcspResponse_UseBuildChain(
+ PKIX_PL_Cert *signerCert,
+ PKIX_PL_Date *producedAt,
+ PKIX_ProcessingParams *procParams,
+ void **pNBIOContext,
+ void **pState,
+ PKIX_BuildResult **pBuildResult,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext)
+{
+ PKIX_ProcessingParams *caProcParams = NULL;
+ PKIX_PL_Date *date = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ void *nbioContext = NULL;
+ PKIX_Error *buildError = NULL;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_OcspResponse_UseBuildChain");
+ PKIX_NULLCHECK_THREE(signerCert, producedAt, procParams);
+ PKIX_NULLCHECK_THREE(pNBIOContext, pState, pBuildResult);
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ /* Are we resuming after a WOULDBLOCK return, or starting anew ? */
+ if (nbioContext == NULL) {
+ /* Starting anew */
+ PKIX_CHECK(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)procParams,
+ (PKIX_PL_Object **)&caProcParams,
+ plContext),
+ PKIX_OBJECTDUPLICATEFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_SetDate(procParams, date, plContext),
+ PKIX_PROCESSINGPARAMSSETDATEFAILED);
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_CHECK(PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext),
+ PKIX_CERTSELECTORCREATEFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_Create
+ (&certSelParams, plContext),
+ PKIX_COMCERTSELPARAMSCREATEFAILED);
+
+ PKIX_CHECK(PKIX_ComCertSelParams_SetCertificate
+ (certSelParams, signerCert, plContext),
+ PKIX_COMCERTSELPARAMSSETCERTIFICATEFAILED);
+
+ PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, certSelParams, plContext),
+ PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
+
+ PKIX_CHECK(PKIX_ProcessingParams_SetTargetCertConstraints
+ (caProcParams, certSelector, plContext),
+ PKIX_PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED);
+ }
+
+ buildError = PKIX_BuildChain
+ (caProcParams,
+ &nbioContext,
+ pState,
+ pBuildResult,
+ pVerifyTree,
+ plContext);
+
+ /* non-null nbioContext means the build would block */
+ if (nbioContext != NULL) {
+
+ *pNBIOContext = nbioContext;
+
+ /* no buildResult means the build has failed */
+ } else if (buildError) {
+ pkixErrorResult = buildError;
+ buildError = NULL;
+ } else {
+ PKIX_DECREF(*pState);
+ }
+
+cleanup:
+
+ PKIX_DECREF(caProcParams);
+ PKIX_DECREF(date);
+ PKIX_DECREF(certSelParams);
+ PKIX_DECREF(certSelector);
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/* --Private-OcspResponse-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspResponse_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_OcspResponse *ocspRsp = NULL;
+ const SEC_HttpClientFcn *httpClient = NULL;
+ const SEC_HttpClientFcnV1 *hcv1 = NULL;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPRESPONSE_TYPE, plContext),
+ PKIX_OBJECTNOTANOCSPRESPONSE);
+
+ ocspRsp = (PKIX_PL_OcspResponse *)object;
+
+ if (ocspRsp->nssOCSPResponse != NULL) {
+ CERT_DestroyOCSPResponse(ocspRsp->nssOCSPResponse);
+ ocspRsp->nssOCSPResponse = NULL;
+ }
+
+ if (ocspRsp->signerCert != NULL) {
+ CERT_DestroyCertificate(ocspRsp->signerCert);
+ ocspRsp->signerCert = NULL;
+ }
+
+ httpClient = (const SEC_HttpClientFcn *)(ocspRsp->httpClient);
+
+ if (httpClient && (httpClient->version == 1)) {
+
+ hcv1 = &(httpClient->fcnTable.ftable1);
+
+ if (ocspRsp->sessionRequest != NULL) {
+ (*hcv1->freeFcn)(ocspRsp->sessionRequest);
+ ocspRsp->sessionRequest = NULL;
+ }
+
+ if (ocspRsp->serverSession != NULL) {
+ (*hcv1->freeSessionFcn)(ocspRsp->serverSession);
+ ocspRsp->serverSession = NULL;
+ }
+ }
+
+ if (ocspRsp->arena != NULL) {
+ PORT_FreeArena(ocspRsp->arena, PR_FALSE);
+ ocspRsp->arena = NULL;
+ }
+
+ PKIX_DECREF(ocspRsp->producedAtDate);
+ PKIX_DECREF(ocspRsp->pkixSignerCert);
+ PKIX_DECREF(ocspRsp->request);
+
+cleanup:
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspResponse_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_OcspResponse *ocspRsp = NULL;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPRESPONSE_TYPE, plContext),
+ PKIX_OBJECTNOTANOCSPRESPONSE);
+
+ ocspRsp = (PKIX_PL_OcspResponse *)object;
+
+ if (ocspRsp->encodedResponse->data == NULL) {
+ *pHashcode = 0;
+ } else {
+ PKIX_CHECK(pkix_hash
+ (ocspRsp->encodedResponse->data,
+ ocspRsp->encodedResponse->len,
+ pHashcode,
+ plContext),
+ PKIX_HASHFAILED);
+ }
+
+cleanup:
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OcspResponse_Equals(
+ PKIX_PL_Object *firstObj,
+ PKIX_PL_Object *secondObj,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType = 0;
+ PKIX_UInt32 firstLen = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_PL_OcspResponse *rsp1 = NULL;
+ PKIX_PL_OcspResponse *rsp2 = NULL;
+ const unsigned char *firstData = NULL;
+ const unsigned char *secondData = NULL;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Equals");
+ PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
+
+ /* test that firstObj is a OcspResponse */
+ PKIX_CHECK(pkix_CheckType(firstObj, PKIX_OCSPRESPONSE_TYPE, plContext),
+ PKIX_FIRSTOBJARGUMENTNOTANOCSPRESPONSE);
+
+ /*
+ * Since we know firstObj is a OcspResponse, if both references are
+ * identical, they must be equal
+ */
+ if (firstObj == secondObj){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObj isn't a OcspResponse, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType(secondObj, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_OCSPRESPONSE_TYPE) {
+ goto cleanup;
+ }
+
+ rsp1 = (PKIX_PL_OcspResponse *)firstObj;
+ rsp2 = (PKIX_PL_OcspResponse *)secondObj;
+
+ /* If either lacks an encoded string, they cannot be compared */
+ firstData = (const unsigned char *)rsp1->encodedResponse->data;
+ secondData = (const unsigned char *)rsp2->encodedResponse->data;
+ if ((firstData == NULL) || (secondData == NULL)) {
+ goto cleanup;
+ }
+
+ firstLen = rsp1->encodedResponse->len;
+
+ if (firstLen != rsp2->encodedResponse->len) {
+ goto cleanup;
+ }
+
+ for (i = 0; i < firstLen; i++) {
+ if (*firstData++ != *secondData++) {
+ goto cleanup;
+ }
+ }
+
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_OCSPRESPONSE_TYPE and its related functions with
+ * systemClasses[]
+ * PARAMETERS:
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_OcspResponse_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry *entry = &systemClasses[PKIX_OCSPRESPONSE_TYPE];
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_RegisterSelf");
+
+ entry->description = "OcspResponse";
+ entry->typeObjectSize = sizeof(PKIX_PL_OcspResponse);
+ entry->destructor = pkix_pl_OcspResponse_Destroy;
+ entry->equalsFunction = pkix_pl_OcspResponse_Equals;
+ entry->hashcodeFunction = pkix_pl_OcspResponse_Hashcode;
+ entry->duplicateFunction = pkix_duplicateImmutable;
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_Create
+ * DESCRIPTION:
+ *
+ * This function transmits the OcspRequest pointed to by "request" and obtains
+ * an OcspResponse, which it stores at "pOcspResponse". If the HTTPClient
+ * supports non-blocking I/O this function may store a non-NULL value at
+ * "pNBIOContext" (the WOULDBLOCK condition). In that case the caller should
+ * make a subsequent call with the same value in "pNBIOContext" and
+ * "pOcspResponse" to resume the operation. Additional WOULDBLOCK returns may
+ * occur; the caller should persist until a return occurs with NULL stored at
+ * "pNBIOContext".
+ *
+ * If a SEC_HttpClientFcn "responder" is supplied, it is used as the client
+ * to which the OCSP query is sent. If none is supplied, the default responder
+ * is used.
+ *
+ * If an OcspResponse_VerifyCallback "verifyFcn" is supplied, it is used to
+ * verify the Cert received from the responder as the signer. If none is
+ * supplied, the default verification function is used.
+ *
+ * The contents of "request" are ignored on calls subsequent to a WOULDBLOCK
+ * return, and the caller is permitted to supply NULL.
+ *
+ * PARAMETERS
+ * "request"
+ * Address of the OcspRequest for which a response is desired.
+ * "httpMethod"
+ * GET or POST
+ * "responder"
+ * Address, if non-NULL, of the SEC_HttpClientFcn to be sent the OCSP
+ * query.
+ * "verifyFcn"
+ * Address, if non-NULL, of the OcspResponse_VerifyCallback function to be
+ * used to verify the Cert of the OCSP responder.
+ * "pNBIOContext"
+ * Address at which platform-dependent information is stored for handling
+ * of non-blocking I/O. Must be non-NULL.
+ * "pOcspResponse"
+ * The address where the created OcspResponse is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_OcspResponse_Create(
+ PKIX_PL_OcspRequest *request,
+ const char *httpMethod,
+ void *responder,
+ PKIX_PL_VerifyCallback verifyFcn,
+ void **pNBIOContext,
+ PKIX_PL_OcspResponse **pResponse,
+ void *plContext)
+{
+ void *nbioContext = NULL;
+ PKIX_PL_OcspResponse *ocspResponse = NULL;
+ const SEC_HttpClientFcn *httpClient = NULL;
+ const SEC_HttpClientFcnV1 *hcv1 = NULL;
+ SECStatus rv = SECFailure;
+ char *location = NULL;
+ char *hostname = NULL;
+ char *path = NULL;
+ char *responseContentType = NULL;
+ PRUint16 port = 0;
+ SEC_HTTP_SERVER_SESSION serverSession = NULL;
+ SEC_HTTP_REQUEST_SESSION sessionRequest = NULL;
+ SECItem *encodedRequest = NULL;
+ PRUint16 responseCode = 0;
+ char *responseData = NULL;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_Create");
+ PKIX_NULLCHECK_TWO(pNBIOContext, pResponse);
+
+ if (!strcmp(httpMethod, "GET") && !strcmp(httpMethod, "POST")) {
+ PKIX_ERROR(PKIX_INVALIDOCSPHTTPMETHOD);
+ }
+
+ nbioContext = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ if (nbioContext != NULL) {
+
+ ocspResponse = *pResponse;
+ PKIX_NULLCHECK_ONE(ocspResponse);
+
+ httpClient = ocspResponse->httpClient;
+ serverSession = ocspResponse->serverSession;
+ sessionRequest = ocspResponse->sessionRequest;
+ PKIX_NULLCHECK_THREE(httpClient, serverSession, sessionRequest);
+
+ } else {
+ PKIX_UInt32 timeout =
+ ((PKIX_PL_NssContext*)plContext)->timeoutSeconds;
+
+ PKIX_NULLCHECK_ONE(request);
+
+ PKIX_CHECK(pkix_pl_OcspRequest_GetEncoded
+ (request, &encodedRequest, plContext),
+ PKIX_OCSPREQUESTGETENCODEDFAILED);
+
+ /* prepare initial message to HTTPClient */
+
+ /* Is there a default responder and is it enabled? */
+ if (responder) {
+ httpClient = (const SEC_HttpClientFcn *)responder;
+ } else {
+ httpClient = SEC_GetRegisteredHttpClient();
+ }
+
+ if (httpClient && (httpClient->version == 1)) {
+ char *fullGetPath = NULL;
+ const char *sessionPath = NULL;
+ PRBool usePOST = !strcmp(httpMethod, "POST");
+
+ hcv1 = &(httpClient->fcnTable.ftable1);
+
+ PKIX_CHECK(pkix_pl_OcspRequest_GetLocation
+ (request, &location, plContext),
+ PKIX_OCSPREQUESTGETLOCATIONFAILED);
+
+ /* parse location -> hostname, port, path */
+ rv = CERT_ParseURL(location, &hostname, &port, &path);
+ if (rv == SECFailure || hostname == NULL || path == NULL) {
+ PKIX_ERROR(PKIX_URLPARSINGFAILED);
+ }
+
+ rv = (*hcv1->createSessionFcn)(hostname, port,
+ &serverSession);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OCSPSERVERERROR);
+ }
+
+ if (usePOST) {
+ sessionPath = path;
+ } else {
+ /* calculate, are we allowed to use GET? */
+ enum { max_get_request_size = 255 }; /* defined by RFC2560 */
+ char b64ReqBuf[max_get_request_size+1];
+ size_t base64size;
+ size_t slashLengthIfNeeded = 0;
+ size_t pathLength;
+ PRInt32 urlEncodedBufLength;
+ size_t getURLLength;
+ char *walkOutput = NULL;
+
+ pathLength = strlen(path);
+ if (path[pathLength-1] != '/') {
+ slashLengthIfNeeded = 1;
+ }
+ base64size = (((encodedRequest->len +2)/3) * 4);
+ if (base64size > max_get_request_size) {
+ PKIX_ERROR(PKIX_OCSPGETREQUESTTOOBIG);
+ }
+ memset(b64ReqBuf, 0, sizeof(b64ReqBuf));
+ PL_Base64Encode((const char *)encodedRequest->data, encodedRequest->len, b64ReqBuf);
+ urlEncodedBufLength = ocsp_UrlEncodeBase64Buf(b64ReqBuf, NULL);
+ getURLLength = pathLength + urlEncodedBufLength + slashLengthIfNeeded;
+ fullGetPath = (char*)PORT_Alloc(getURLLength);
+ if (!fullGetPath) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ strcpy(fullGetPath, path);
+ walkOutput = fullGetPath + pathLength;
+ if (walkOutput > fullGetPath && slashLengthIfNeeded) {
+ strcpy(walkOutput, "/");
+ ++walkOutput;
+ }
+ ocsp_UrlEncodeBase64Buf(b64ReqBuf, walkOutput);
+ sessionPath = fullGetPath;
+ }
+
+ rv = (*hcv1->createFcn)(serverSession, "http",
+ sessionPath, httpMethod,
+ PR_SecondsToInterval(timeout),
+ &sessionRequest);
+ sessionPath = NULL;
+ if (fullGetPath) {
+ PORT_Free(fullGetPath);
+ fullGetPath = NULL;
+ }
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OCSPSERVERERROR);
+ }
+
+ if (usePOST) {
+ rv = (*hcv1->setPostDataFcn)(sessionRequest,
+ (char *)encodedRequest->data,
+ encodedRequest->len,
+ "application/ocsp-request");
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OCSPSERVERERROR);
+ }
+ }
+
+ /* create a PKIX_PL_OcspResponse object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_OCSPRESPONSE_TYPE,
+ sizeof (PKIX_PL_OcspResponse),
+ (PKIX_PL_Object **)&ocspResponse,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ PKIX_INCREF(request);
+ ocspResponse->request = request;
+ ocspResponse->httpClient = httpClient;
+ ocspResponse->serverSession = serverSession;
+ serverSession = NULL;
+ ocspResponse->sessionRequest = sessionRequest;
+ sessionRequest = NULL;
+ ocspResponse->verifyFcn = verifyFcn;
+ ocspResponse->handle = CERT_GetDefaultCertDB();
+ ocspResponse->encodedResponse = NULL;
+ ocspResponse->arena = NULL;
+ ocspResponse->producedAt = 0;
+ ocspResponse->producedAtDate = NULL;
+ ocspResponse->pkixSignerCert = NULL;
+ ocspResponse->nssOCSPResponse = NULL;
+ ocspResponse->signerCert = NULL;
+ }
+ }
+
+ /* begin or resume IO to HTTPClient */
+ if (httpClient && (httpClient->version == 1)) {
+ PRUint32 responseDataLen =
+ ((PKIX_PL_NssContext*)plContext)->maxResponseLength;
+
+ hcv1 = &(httpClient->fcnTable.ftable1);
+
+ rv = (*hcv1->trySendAndReceiveFcn)(ocspResponse->sessionRequest,
+ (PRPollDesc **)&nbioContext,
+ &responseCode,
+ (const char **)&responseContentType,
+ NULL, /* responseHeaders */
+ (const char **)&responseData,
+ &responseDataLen);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OCSPSERVERERROR);
+ }
+ /* responseContentType is a pointer to the null-terminated
+ * string returned by httpclient. Memory allocated for context
+ * type will be freed with freeing of the HttpClient struct. */
+ if (PORT_Strcasecmp(responseContentType,
+ "application/ocsp-response")) {
+ PKIX_ERROR(PKIX_OCSPSERVERERROR);
+ }
+ if (nbioContext != NULL) {
+ *pNBIOContext = nbioContext;
+ goto cleanup;
+ }
+ if (responseCode != 200) {
+ PKIX_ERROR(PKIX_OCSPBADHTTPRESPONSE);
+ }
+ ocspResponse->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (ocspResponse->arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ ocspResponse->encodedResponse = SECITEM_AllocItem
+ (ocspResponse->arena, NULL, responseDataLen);
+ if (ocspResponse->encodedResponse == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ PORT_Memcpy(ocspResponse->encodedResponse->data,
+ responseData, responseDataLen);
+ }
+ *pResponse = ocspResponse;
+ ocspResponse = NULL;
+
+cleanup:
+
+ if (path != NULL) {
+ PORT_Free(path);
+ }
+ if (hostname != NULL) {
+ PORT_Free(hostname);
+ }
+ if (ocspResponse) {
+ PKIX_DECREF(ocspResponse);
+ }
+ if (serverSession) {
+ hcv1->freeSessionFcn(serverSession);
+ }
+ if (sessionRequest) {
+ hcv1->freeFcn(sessionRequest);
+ }
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_Decode
+ * DESCRIPTION:
+ *
+ * This function decodes the DER data contained in the OcspResponse pointed to
+ * by "response", storing PKIX_TRUE at "pPassed" if the decoding was
+ * successful, and PKIX_FALSE otherwise.
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the OcspResponse whose DER data is to be decoded. Must
+ * be non-NULL.
+ * "pPassed"
+ * Address at which the Boolean result is stored. Must be non-NULL.
+ * "pReturnCode"
+ * Address at which the SECErrorCodes result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+
+PKIX_Error *
+pkix_pl_OcspResponse_Decode(
+ PKIX_PL_OcspResponse *response,
+ PKIX_Boolean *pPassed,
+ SECErrorCodes *pReturnCode,
+ void *plContext)
+{
+
+ PKIX_ENTER(OCSPRESPONSE, "PKIX_PL_OcspResponse_Decode");
+ PKIX_NULLCHECK_TWO(response, response->encodedResponse);
+
+ response->nssOCSPResponse =
+ CERT_DecodeOCSPResponse(response->encodedResponse);
+
+ if (response->nssOCSPResponse != NULL) {
+ *pPassed = PKIX_TRUE;
+ *pReturnCode = 0;
+ } else {
+ *pPassed = PKIX_FALSE;
+ *pReturnCode = PORT_GetError();
+ }
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_GetStatus
+ * DESCRIPTION:
+ *
+ * This function checks the response status of the OcspResponse pointed to
+ * by "response", storing PKIX_TRUE at "pPassed" if the responder understood
+ * the request and considered it valid, and PKIX_FALSE otherwise.
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the OcspResponse whose status is to be retrieved. Must
+ * be non-NULL.
+ * "pPassed"
+ * Address at which the Boolean result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+
+PKIX_Error *
+pkix_pl_OcspResponse_GetStatus(
+ PKIX_PL_OcspResponse *response,
+ PKIX_Boolean *pPassed,
+ SECErrorCodes *pReturnCode,
+ void *plContext)
+{
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(OCSPRESPONSE, "PKIX_PL_OcspResponse_GetStatus");
+ PKIX_NULLCHECK_FOUR(response, response->nssOCSPResponse, pPassed, pReturnCode);
+
+ rv = CERT_GetOCSPResponseStatus(response->nssOCSPResponse);
+
+ if (rv == SECSuccess) {
+ *pPassed = PKIX_TRUE;
+ *pReturnCode = 0;
+ } else {
+ *pPassed = PKIX_FALSE;
+ *pReturnCode = PORT_GetError();
+ }
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+
+static PKIX_Error*
+pkix_pl_OcspResponse_VerifyResponse(
+ PKIX_PL_OcspResponse *response,
+ PKIX_ProcessingParams *procParams,
+ SECCertUsage certUsage,
+ void **state,
+ PKIX_BuildResult **buildResult,
+ void **pNBIOContext,
+ void *plContext)
+{
+ SECStatus rv = SECFailure;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_VerifyResponse");
+
+ if (response->verifyFcn != NULL) {
+ void *lplContext = NULL;
+
+ PKIX_CHECK(
+ PKIX_PL_NssContext_Create(((SECCertificateUsage)1) << certUsage,
+ PKIX_FALSE, NULL, &lplContext),
+ PKIX_NSSCONTEXTCREATEFAILED);
+
+ PKIX_CHECK(
+ (response->verifyFcn)((PKIX_PL_Object*)response->pkixSignerCert,
+ NULL, response->producedAtDate,
+ procParams, pNBIOContext,
+ state, buildResult,
+ NULL, lplContext),
+ PKIX_CERTVERIFYKEYUSAGEFAILED);
+ rv = SECSuccess;
+ } else {
+ /* checkSig is !isRoot */
+ PRBool checkSig = response->signerCert->isRoot ? PR_FALSE : PR_TRUE;
+ rv = CERT_VerifyCert(response->handle, response->signerCert, checkSig,
+ certUsage, response->producedAt, NULL, NULL);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_CERTVERIFYKEYUSAGEFAILED);
+ }
+ }
+
+cleanup:
+ if (rv != SECSuccess) {
+ PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
+ }
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_VerifySignature
+ * DESCRIPTION:
+ *
+ * This function verifies the ocspResponse signature field in the OcspResponse
+ * pointed to by "response", storing PKIX_TRUE at "pPassed" if verification
+ * is successful and PKIX_FALSE otherwise. If verification is unsuccessful an
+ * error code (an enumeration of type SECErrorCodes) is stored at *pReturnCode.
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the OcspResponse whose signature field is to be
+ * retrieved. Must be non-NULL.
+ * "cert"
+ * The address of the Cert for which the OCSP query was made. Must be
+ * non-NULL.
+ * "procParams"
+ * Address of ProcessingParams used to initialize the ExpirationChecker
+ * and TargetCertChecker. Must be non-NULL.
+ * "pPassed"
+ * Address at which the Boolean result is stored. Must be non-NULL.
+ * "pNBIOContext"
+ * Address at which the NBIOContext is stored indicating whether the
+ * checking is complete. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_OcspResponse_VerifySignature(
+ PKIX_PL_OcspResponse *response,
+ PKIX_PL_Cert *cert,
+ PKIX_ProcessingParams *procParams,
+ PKIX_Boolean *pPassed,
+ void **pNBIOContext,
+ void *plContext)
+{
+ SECStatus rv = SECFailure;
+ CERTOCSPResponse *nssOCSPResponse = NULL;
+ CERTCertificate *issuerCert = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ void *nbio = NULL;
+ void *state = NULL;
+
+ ocspSignature *signature = NULL;
+ ocspResponseData *tbsData = NULL;
+ SECItem *tbsResponseDataDER = NULL;
+
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_VerifySignature");
+ PKIX_NULLCHECK_FOUR(response, cert, pPassed, pNBIOContext);
+
+ nbio = *pNBIOContext;
+ *pNBIOContext = NULL;
+
+ nssOCSPResponse = response->nssOCSPResponse;
+ if (nssOCSPResponse == NULL) {
+ PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
+ goto cleanup;
+ }
+
+ tbsData =
+ ocsp_GetResponseData(nssOCSPResponse, &tbsResponseDataDER);
+
+ signature = ocsp_GetResponseSignature(nssOCSPResponse);
+
+
+ /* Are we resuming after a WOULDBLOCK response? */
+ if (nbio == NULL) {
+ /* No, this is a new query */
+
+ issuerCert = CERT_FindCertIssuer(cert->nssCert, PR_Now(),
+ certUsageAnyCA);
+
+ /*
+ * If this signature has already gone through verification,
+ * just return the cached result.
+ */
+ if (signature->wasChecked) {
+ if (signature->status == SECSuccess) {
+ response->signerCert =
+ CERT_DupCertificate(signature->cert);
+ } else {
+ PORT_SetError(signature->failureReason);
+ goto cleanup;
+ }
+ }
+
+ response->signerCert =
+ ocsp_GetSignerCertificate(response->handle, tbsData,
+ signature, issuerCert);
+
+ if (response->signerCert == NULL) {
+ if (PORT_GetError() == SEC_ERROR_UNKNOWN_CERT) {
+ /* Make the error a little more specific. */
+ PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
+ }
+ goto cleanup;
+ }
+ PKIX_CHECK(
+ PKIX_PL_Cert_CreateFromCERTCertificate(response->signerCert,
+ &(response->pkixSignerCert),
+ plContext),
+ PKIX_CERTCREATEWITHNSSCERTFAILED);
+
+ /*
+ * We could mark this true at the top of this function, or
+ * always below at "finish", but if the problem was just that
+ * we could not find the signer's cert, leave that as if the
+ * signature hasn't been checked. Maybe a subsequent call will
+ * have better luck.
+ */
+ signature->wasChecked = PR_TRUE;
+
+ /*
+ * We are about to verify the signer certificate; we need to
+ * specify *when* that certificate must be valid -- for our
+ * purposes we expect it to be valid when the response was
+ * signed. The value of "producedAt" is the signing time.
+ */
+ rv = DER_GeneralizedTimeToTime(&response->producedAt,
+ &tbsData->producedAt);
+ if (rv != SECSuccess) {
+ PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
+ goto cleanup;
+ }
+
+ /*
+ * We need producedAtDate and pkixSignerCert if we are calling a
+ * user-supplied verification function. Let's put their
+ * creation before the code that gets repeated when
+ * non-blocking I/O is used.
+ */
+
+ PKIX_CHECK(
+ pkix_pl_Date_CreateFromPRTime((PRTime)response->producedAt,
+ &(response->producedAtDate),
+ plContext),
+ PKIX_DATECREATEFROMPRTIMEFAILED);
+
+ }
+
+ /*
+ * Just because we have a cert does not mean it is any good; check
+ * it for validity, trust and usage. Use the caller-supplied
+ * verification function, if one was supplied.
+ */
+ if (ocsp_CertIsOCSPDefaultResponder(response->handle,
+ response->signerCert)) {
+ rv = SECSuccess;
+ } else {
+ SECCertUsage certUsage;
+ if (CERT_IsCACert(response->signerCert, NULL)) {
+ certUsage = certUsageAnyCA;
+ } else {
+ certUsage = certUsageStatusResponder;
+ }
+ PKIX_CHECK_ONLY_FATAL(
+ pkix_pl_OcspResponse_VerifyResponse(response, procParams,
+ certUsage, &state,
+ &buildResult, &nbio,
+ plContext),
+ PKIX_CERTVERIFYKEYUSAGEFAILED);
+ if (pkixTempErrorReceived) {
+ rv = SECFailure;
+ goto cleanup;
+ }
+ if (nbio != NULL) {
+ *pNBIOContext = nbio;
+ goto cleanup;
+ }
+ }
+
+ rv = ocsp_VerifyResponseSignature(response->signerCert, signature,
+ tbsResponseDataDER, NULL);
+
+cleanup:
+ if (rv == SECSuccess) {
+ *pPassed = PKIX_TRUE;
+ } else {
+ *pPassed = PKIX_FALSE;
+ }
+
+ if (signature) {
+ if (signature->wasChecked) {
+ signature->status = rv;
+ }
+
+ if (rv != SECSuccess) {
+ signature->failureReason = PORT_GetError();
+ if (response->signerCert != NULL) {
+ CERT_DestroyCertificate(response->signerCert);
+ response->signerCert = NULL;
+ }
+ } else {
+ /* Save signer's certificate in signature. */
+ signature->cert = CERT_DupCertificate(response->signerCert);
+ }
+ }
+
+ if (issuerCert)
+ CERT_DestroyCertificate(issuerCert);
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_OcspResponse_GetStatusForCert
+ * DESCRIPTION:
+ *
+ * This function checks the revocation status of the Cert for which the
+ * OcspResponse was obtained, storing PKIX_TRUE at "pPassed" if the Cert has
+ * not been revoked and PKIX_FALSE otherwise.
+ *
+ * PARAMETERS
+ * "response"
+ * The address of the OcspResponse whose certificate status is to be
+ * retrieved. Must be non-NULL.
+ * "pPassed"
+ * Address at which the Boolean result is stored. Must be non-NULL.
+ * "pReturnCode"
+ * Address at which the SECErrorCodes result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OcspResponse Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_OcspResponse_GetStatusForCert(
+ PKIX_PL_OcspCertID *cid,
+ PKIX_PL_OcspResponse *response,
+ PKIX_Boolean allowCachingOfFailures,
+ PKIX_PL_Date *validity,
+ PKIX_Boolean *pPassed,
+ SECErrorCodes *pReturnCode,
+ void *plContext)
+{
+ PRTime time = 0;
+ SECStatus rv = SECFailure;
+ CERTOCSPSingleResponse *single = NULL;
+
+ PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_GetStatusForCert");
+ PKIX_NULLCHECK_THREE(response, pPassed, pReturnCode);
+
+ /*
+ * It is an error to call this function except following a successful
+ * return from pkix_pl_OcspResponse_VerifySignature, which would have
+ * set response->signerCert.
+ */
+ PKIX_NULLCHECK_TWO(response->signerCert, response->request);
+ PKIX_NULLCHECK_TWO(cid, cid->certID);
+
+ if (validity != NULL) {
+ PKIX_Error *er = pkix_pl_Date_GetPRTime(validity, &time, plContext);
+ PKIX_DECREF(er);
+ }
+ if (!time) {
+ time = PR_Now();
+ }
+
+ rv = ocsp_GetVerifiedSingleResponseForCertID(response->handle,
+ response->nssOCSPResponse,
+ cid->certID,
+ response->signerCert,
+ time, &single);
+ if (rv == SECSuccess) {
+ /*
+ * Check whether the status says revoked, and if so
+ * how that compares to the time value passed into this routine.
+ */
+ rv = ocsp_CertHasGoodStatus(single->certStatus, time);
+ }
+
+ if (rv == SECSuccess || allowCachingOfFailures) {
+ /* allowed to update the cache */
+ PRBool certIDWasConsumed = PR_FALSE;
+
+ if (single) {
+ ocsp_CacheSingleResponse(cid->certID,single,
+ &certIDWasConsumed);
+ } else {
+ cert_RememberOCSPProcessingFailure(cid->certID,
+ &certIDWasConsumed);
+ }
+
+ if (certIDWasConsumed) {
+ cid->certID = NULL;
+ }
+ }
+
+ if (rv == SECSuccess) {
+ *pPassed = PKIX_TRUE;
+ *pReturnCode = 0;
+ } else {
+ *pPassed = PKIX_FALSE;
+ *pReturnCode = PORT_GetError();
+ }
+
+ PKIX_RETURN(OCSPRESPONSE);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.h
new file mode 100644
index 0000000000..dcf88c9603
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_ocspresponse.h
@@ -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/. */
+/*
+ * pkix_pl_ocspresponse.h
+ *
+ * OcspResponse Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_OCSPRESPONSE_H
+#define _PKIX_PL_OCSPRESPONSE_H
+
+#include "pkix_pl_common.h"
+#include "pkix_pl_ocspcertid.h"
+#include "hasht.h"
+#include "cryptohi.h"
+#include "ocspti.h"
+#include "ocspi.h"
+#include "plbase64.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_OCSP_RESPONSE_LEN (64*1024)
+
+struct PKIX_PL_OcspResponseStruct{
+ PLArenaPool *arena;
+ const PKIX_PL_OcspRequest *request;
+ const SEC_HttpClientFcn *httpClient;
+ SEC_HTTP_SERVER_SESSION serverSession;
+ SEC_HTTP_REQUEST_SESSION sessionRequest;
+ PKIX_PL_VerifyCallback verifyFcn;
+ SECItem *encodedResponse;
+ CERTCertDBHandle *handle;
+ PRTime producedAt;
+ PKIX_PL_Date *producedAtDate;
+ PKIX_PL_Cert *pkixSignerCert;
+ CERTOCSPResponse *nssOCSPResponse;
+ CERTCertificate *signerCert;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_OcspResponse_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspResponse_Create(
+ PKIX_PL_OcspRequest *request,
+ const char *httpMechanism,
+ void *responder,
+ PKIX_PL_VerifyCallback verifyFcn,
+ void **pNBIOContext,
+ PKIX_PL_OcspResponse **pResponse,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspResponse_Decode(
+ PKIX_PL_OcspResponse *response,
+ PKIX_Boolean *passed,
+ SECErrorCodes *pReturnCode,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspResponse_GetStatus(
+ PKIX_PL_OcspResponse *response,
+ PKIX_Boolean *passed,
+ SECErrorCodes *pReturnCode,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspResponse_VerifySignature(
+ PKIX_PL_OcspResponse *response,
+ PKIX_PL_Cert *cert,
+ PKIX_ProcessingParams *procParams,
+ PKIX_Boolean *pPassed,
+ void **pNBIOContext,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_OcspResponse_GetStatusForCert(
+ PKIX_PL_OcspCertID *cid,
+ PKIX_PL_OcspResponse *response,
+ PKIX_Boolean allowCachingOfFailures,
+ PKIX_PL_Date *validity,
+ PKIX_Boolean *pPassed,
+ SECErrorCodes *pReturnCode,
+ void *plContext);
+
+PKIX_Error *
+PKIX_PL_OcspResponse_UseBuildChain(
+ PKIX_PL_Cert *signerCert,
+ PKIX_PL_Date *producedAt,
+ PKIX_ProcessingParams *procParams,
+ void **pNBIOContext,
+ void **pState,
+ PKIX_BuildResult **pBuildResult,
+ PKIX_VerifyNode **pVerifyTree,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_OCSPRESPONSE_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c
new file mode 100644
index 0000000000..2dfe9a9c2c
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.c
@@ -0,0 +1,489 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_publickey.c
+ *
+ * Certificate Object Functions
+ *
+ */
+
+#include "pkix_pl_publickey.h"
+
+/* --Private-Cert-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_PublicKey_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the PublicKey
+ * pointed to by "pkixPubKey" and stores it at "pString".
+ *
+ * PARAMETERS
+ * "pkixPubKey"
+ * Address of PublicKey whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a PublicKey Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_PublicKey_ToString_Helper(
+ PKIX_PL_PublicKey *pkixPubKey,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ SECAlgorithmID algorithm;
+ SECOidTag pubKeyTag;
+ char *asciiOID = NULL;
+ PKIX_Boolean freeAsciiOID = PKIX_FALSE;
+ SECItem oidBytes;
+
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_ToString_Helper");
+ PKIX_NULLCHECK_THREE(pkixPubKey, pkixPubKey->nssSPKI, pString);
+
+ /*
+ * XXX for now, we print out public key algorithm's
+ * description - add params and bytes later
+ */
+
+ /*
+ * If the algorithm OID is known to NSS,
+ * we print out the ASCII description that is
+ * registered with NSS. Otherwise, if unknown,
+ * we print out the OID numbers (eg. "1.2.840.3")
+ */
+
+ algorithm = pkixPubKey->nssSPKI->algorithm;
+
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_GetAlgorithmTag).\n");
+ pubKeyTag = SECOID_GetAlgorithmTag(&algorithm);
+ if (pubKeyTag != SEC_OID_UNKNOWN){
+ PKIX_PUBLICKEY_DEBUG
+ ("\t\tCalling SECOID_FindOIDTagDescription).\n");
+ asciiOID = (char *)SECOID_FindOIDTagDescription(pubKeyTag);
+ if (!asciiOID){
+ PKIX_ERROR(PKIX_SECOIDFINDOIDTAGDESCRIPTIONFAILED);
+ }
+ } else { /* pubKeyTag == SEC_OID_UNKNOWN */
+ oidBytes = algorithm.algorithm;
+ PKIX_CHECK(pkix_pl_oidBytes2Ascii
+ (&oidBytes, &asciiOID, plContext),
+ PKIX_OIDBYTES2ASCIIFAILED);
+ freeAsciiOID = PKIX_TRUE;
+ }
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, (void *)asciiOID, 0, pString, plContext),
+ PKIX_UNABLETOCREATEPSTRING);
+
+cleanup:
+
+ /*
+ * we only free asciiOID if it was malloc'ed by pkix_pl_oidBytes2Ascii
+ */
+ if (freeAsciiOID){
+ PKIX_FREE(asciiOID);
+ }
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/*
+ * FUNCTION: pkix_pl_DestroySPKI
+ * DESCRIPTION:
+ * Frees all memory associated with the CERTSubjectPublicKeyInfo pointed to
+ * by "nssSPKI".
+ * PARAMETERS
+ * "nssSPKI"
+ * Address of CERTSubjectPublicKeyInfo. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_DestroySPKI(
+ CERTSubjectPublicKeyInfo *nssSPKI,
+ void *plContext)
+{
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_DestroySPKI");
+
+ PKIX_NULLCHECK_ONE(nssSPKI);
+
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_DestroyAlgorithmID).\n");
+ SECOID_DestroyAlgorithmID(&nssSPKI->algorithm, PKIX_FALSE);
+
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
+ SECITEM_FreeItem(&nssSPKI->subjectPublicKey, PKIX_FALSE);
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/*
+ * FUNCTION: pkix_pl_PublicKey_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_PublicKey_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *pubKey = NULL;
+
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Destroy");
+
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext),
+ PKIX_OBJECTNOTPUBLICKEY);
+
+ pubKey = (PKIX_PL_PublicKey *)object;
+
+ if (pubKey->nssSPKI) {
+
+ PKIX_CHECK(pkix_pl_DestroySPKI(pubKey->nssSPKI, plContext),
+ PKIX_DESTROYSPKIFAILED);
+
+ PKIX_FREE(pubKey->nssSPKI);
+ }
+
+cleanup:
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/*
+ * FUNCTION: pkix_pl_PublicKey_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_PublicKey_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *pkixPubKey = NULL;
+ PKIX_PL_String *pubKeyString = NULL;
+
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext),
+ PKIX_OBJECTNOTPUBLICKEY);
+
+ pkixPubKey = (PKIX_PL_PublicKey *)object;
+
+ PKIX_CHECK(pkix_pl_PublicKey_ToString_Helper
+ (pkixPubKey, &pubKeyString, plContext),
+ PKIX_PUBLICKEYTOSTRINGHELPERFAILED);
+
+ *pString = pubKeyString;
+
+cleanup:
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/*
+ * FUNCTION: pkix_pl_PublicKey_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_PublicKey_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *pkixPubKey = NULL;
+ SECItem algOID;
+ SECItem algParams;
+ SECItem nssPubKey;
+ PKIX_UInt32 algOIDHash;
+ PKIX_UInt32 algParamsHash;
+ PKIX_UInt32 pubKeyHash;
+
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext),
+ PKIX_OBJECTNOTPUBLICKEY);
+
+ pkixPubKey = (PKIX_PL_PublicKey *)object;
+
+ PKIX_NULLCHECK_ONE(pkixPubKey->nssSPKI);
+
+ algOID = pkixPubKey->nssSPKI->algorithm.algorithm;
+ algParams = pkixPubKey->nssSPKI->algorithm.parameters;
+ nssPubKey = pkixPubKey->nssSPKI->subjectPublicKey;
+
+ PKIX_CHECK(pkix_hash
+ (algOID.data, algOID.len, &algOIDHash, plContext),
+ PKIX_HASHFAILED);
+
+ PKIX_CHECK(pkix_hash
+ (algParams.data, algParams.len, &algParamsHash, plContext),
+ PKIX_HASHFAILED);
+
+ PKIX_CHECK(pkix_hash
+ (nssPubKey.data, nssPubKey.len, &pubKeyHash, plContext),
+ PKIX_HASHFAILED);
+
+ *pHashcode = pubKeyHash;
+
+cleanup:
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_PublicKey_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_PublicKey_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_PublicKey *firstPKIXPubKey = NULL;
+ PKIX_PL_PublicKey *secondPKIXPubKey = NULL;
+ CERTSubjectPublicKeyInfo *firstSPKI = NULL;
+ CERTSubjectPublicKeyInfo *secondSPKI = NULL;
+ SECComparison cmpResult;
+ PKIX_UInt32 secondType;
+
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a PublicKey */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_PUBLICKEY_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTPUBLICKEY);
+
+ /*
+ * Since we know firstObject is a PublicKey, if both references are
+ * identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't a PublicKey, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_PUBLICKEY_TYPE) goto cleanup;
+
+ firstPKIXPubKey = ((PKIX_PL_PublicKey *)firstObject);
+ secondPKIXPubKey = (PKIX_PL_PublicKey *)secondObject;
+
+ firstSPKI = firstPKIXPubKey->nssSPKI;
+ secondSPKI = secondPKIXPubKey->nssSPKI;
+
+ PKIX_NULLCHECK_TWO(firstSPKI, secondSPKI);
+
+ PKIX_PL_NSSCALLRV(PUBLICKEY, cmpResult, SECOID_CompareAlgorithmID,
+ (&firstSPKI->algorithm, &secondSPKI->algorithm));
+
+ if (cmpResult == SECEqual){
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_CompareItem).\n");
+ cmpResult = SECITEM_CompareItem
+ (&firstSPKI->subjectPublicKey,
+ &secondSPKI->subjectPublicKey);
+ }
+
+ *pResult = (cmpResult == SECEqual)?PKIX_TRUE:PKIX_FALSE;
+
+cleanup:
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/*
+ * FUNCTION: pkix_pl_PublicKey_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_PUBLICKEY_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_PublicKey_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_RegisterSelf");
+
+ entry.description = "PublicKey";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_PublicKey);
+ entry.destructor = pkix_pl_PublicKey_Destroy;
+ entry.equalsFunction = pkix_pl_PublicKey_Equals;
+ entry.hashcodeFunction = pkix_pl_PublicKey_Hashcode;
+ entry.toStringFunction = pkix_pl_PublicKey_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+ systemClasses[PKIX_PUBLICKEY_TYPE] = entry;
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_PublicKey_NeedsDSAParameters
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_PublicKey_NeedsDSAParameters(
+ PKIX_PL_PublicKey *pubKey,
+ PKIX_Boolean *pNeedsParams,
+ void *plContext)
+{
+ CERTSubjectPublicKeyInfo *nssSPKI = NULL;
+ KeyType pubKeyType;
+ PKIX_Boolean needsParams = PKIX_FALSE;
+
+ PKIX_ENTER(PUBLICKEY, "PKIX_PL_PublicKey_NeedsDSAParameters");
+ PKIX_NULLCHECK_TWO(pubKey, pNeedsParams);
+
+ nssSPKI = pubKey->nssSPKI;
+
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n");
+ pubKeyType = CERT_GetCertKeyType(nssSPKI);
+ if (!pubKeyType){
+ PKIX_ERROR(PKIX_PUBKEYTYPENULLKEY);
+ }
+
+ if ((pubKeyType == dsaKey) &&
+ (nssSPKI->algorithm.parameters.len == 0)){
+ needsParams = PKIX_TRUE;
+ }
+
+ *pNeedsParams = needsParams;
+
+cleanup:
+
+ PKIX_RETURN(PUBLICKEY);
+}
+
+/*
+ * FUNCTION: PKIX_PL_PublicKey_MakeInheritedDSAPublicKey
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_PublicKey_MakeInheritedDSAPublicKey(
+ PKIX_PL_PublicKey *firstKey,
+ PKIX_PL_PublicKey *secondKey,
+ PKIX_PL_PublicKey **pResultKey,
+ void *plContext)
+{
+ CERTSubjectPublicKeyInfo *firstSPKI = NULL;
+ CERTSubjectPublicKeyInfo *secondSPKI = NULL;
+ CERTSubjectPublicKeyInfo *thirdSPKI = NULL;
+ PKIX_PL_PublicKey *resultKey = NULL;
+ KeyType firstPubKeyType;
+ KeyType secondPubKeyType;
+ SECStatus rv;
+
+ PKIX_ENTER(PUBLICKEY, "PKIX_PL_PublicKey_MakeInheritedDSAPublicKey");
+ PKIX_NULLCHECK_THREE(firstKey, secondKey, pResultKey);
+ PKIX_NULLCHECK_TWO(firstKey->nssSPKI, secondKey->nssSPKI);
+
+ firstSPKI = firstKey->nssSPKI;
+ secondSPKI = secondKey->nssSPKI;
+
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n");
+ firstPubKeyType = CERT_GetCertKeyType(firstSPKI);
+ if (!firstPubKeyType){
+ PKIX_ERROR(PKIX_FIRSTPUBKEYTYPENULLKEY);
+ }
+
+ PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n");
+ secondPubKeyType = CERT_GetCertKeyType(secondSPKI);
+ if (!secondPubKeyType){
+ PKIX_ERROR(PKIX_SECONDPUBKEYTYPENULLKEY);
+ }
+
+ if ((firstPubKeyType == dsaKey) &&
+ (firstSPKI->algorithm.parameters.len == 0)){
+ if (secondPubKeyType != dsaKey) {
+ PKIX_ERROR(PKIX_SECONDKEYNOTDSAPUBLICKEY);
+ } else if (secondSPKI->algorithm.parameters.len == 0) {
+ PKIX_ERROR
+ (PKIX_SECONDKEYDSAPUBLICKEY);
+ } else {
+ PKIX_CHECK(PKIX_PL_Calloc
+ (1,
+ sizeof (CERTSubjectPublicKeyInfo),
+ (void **)&thirdSPKI,
+ plContext),
+ PKIX_CALLOCFAILED);
+
+ PKIX_PUBLICKEY_DEBUG
+ ("\t\tCalling"
+ "SECKEY_CopySubjectPublicKeyInfo).\n");
+ rv = SECKEY_CopySubjectPublicKeyInfo
+ (NULL, thirdSPKI, firstSPKI);
+ if (rv != SECSuccess) {
+ PKIX_ERROR
+ (PKIX_SECKEYCOPYSUBJECTPUBLICKEYINFOFAILED);
+ }
+
+ PKIX_PUBLICKEY_DEBUG
+ ("\t\tCalling SECITEM_CopyItem).\n");
+ rv = SECITEM_CopyItem(NULL,
+ &thirdSPKI->algorithm.parameters,
+ &secondSPKI->algorithm.parameters);
+
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ /* create a PKIX_PL_PublicKey object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_PUBLICKEY_TYPE,
+ sizeof (PKIX_PL_PublicKey),
+ (PKIX_PL_Object **)&resultKey,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* populate the SPKI field */
+ resultKey->nssSPKI = thirdSPKI;
+ *pResultKey = resultKey;
+ }
+ } else {
+ *pResultKey = NULL;
+ }
+
+cleanup:
+
+ if (thirdSPKI && PKIX_ERROR_RECEIVED){
+ PKIX_CHECK(pkix_pl_DestroySPKI(thirdSPKI, plContext),
+ PKIX_DESTROYSPKIFAILED);
+ PKIX_FREE(thirdSPKI);
+ }
+
+ PKIX_RETURN(PUBLICKEY);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.h
new file mode 100644
index 0000000000..8918859d2d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_publickey.h
@@ -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_pl_publickey.h
+ *
+ * Public Key Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_PUBLICKEY_H
+#define _PKIX_PL_PUBLICKEY_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_PublicKeyStruct {
+ CERTSubjectPublicKeyInfo *nssSPKI;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_PublicKey_RegisterSelf(void *plContext);
+
+PKIX_Error *
+PKIX_PL_PublicKey_NeedsDSAParameters(
+ PKIX_PL_PublicKey *pubKey,
+ PKIX_Boolean *pNeedsParams,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_PUBLICKEY_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c
new file mode 100644
index 0000000000..e37439cf01
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.c
@@ -0,0 +1,667 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_x500name.c
+ *
+ * X500Name Object Functions
+ *
+ */
+
+#include "pkix_pl_x500name.h"
+
+/* --Private-X500Name-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_X500Name_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_X500Name_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_X500Name *name = NULL;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext),
+ PKIX_OBJECTNOTANX500NAME);
+
+ name = (PKIX_PL_X500Name *)object;
+
+ /* PORT_FreeArena will destroy arena, and, allocated on it, CERTName
+ * and SECItem */
+ if (name->arena) {
+ PORT_FreeArena(name->arena, PR_FALSE);
+ name->arena = NULL;
+ }
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_X500Name_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_X500Name *name = NULL;
+ char *string = NULL;
+ PKIX_UInt32 strLength = 0;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext),
+ PKIX_OBJECTNOTANX500NAME);
+
+ name = (PKIX_PL_X500Name *)object;
+ string = CERT_NameToAscii(&name->nssDN);
+ if (!string){
+ PKIX_ERROR(PKIX_CERTNAMETOASCIIFAILED);
+ }
+ strLength = PL_strlen(string);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, string, strLength, pString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_X500Name_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_X500Name *name = NULL;
+ SECItem *derBytes = NULL;
+ PKIX_UInt32 nameHash;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext),
+ PKIX_OBJECTNOTANX500NAME);
+
+ name = (PKIX_PL_X500Name *)object;
+
+ /* we hash over the bytes in the DER encoding */
+
+ derBytes = &name->derName;
+
+ PKIX_CHECK(pkix_hash
+ (derBytes->data, derBytes->len, &nameHash, plContext),
+ PKIX_HASHFAILED);
+
+ *pHashcode = nameHash;
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_X500Name_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_X500Name_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is an X500Name */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_X500NAME_TYPE, plContext),
+ PKIX_FIRSTOBJECTARGUMENTNOTANX500NAME);
+
+ /*
+ * Since we know firstObject is an X500Name, if both references are
+ * identical, they must be equal
+ */
+ if (firstObject == secondObject){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObject isn't an X500Name, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_X500NAME_TYPE) goto cleanup;
+
+ PKIX_CHECK(
+ PKIX_PL_X500Name_Match((PKIX_PL_X500Name *)firstObject,
+ (PKIX_PL_X500Name *)secondObject,
+ pResult, plContext),
+ PKIX_X500NAMEMATCHFAILED);
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_X500NAME_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_X500Name_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_RegisterSelf");
+
+ entry.description = "X500Name";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_X500Name);
+ entry.destructor = pkix_pl_X500Name_Destroy;
+ entry.equalsFunction = pkix_pl_X500Name_Equals;
+ entry.hashcodeFunction = pkix_pl_X500Name_Hashcode;
+ entry.toStringFunction = pkix_pl_X500Name_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_X500NAME_TYPE] = entry;
+
+ PKIX_RETURN(X500NAME);
+}
+
+#ifdef BUILD_LIBPKIX_TESTS
+/*
+ * FUNCTION: pkix_pl_X500Name_CreateFromUtf8
+ *
+ * DESCRIPTION:
+ * Creates an X500Name object from the RFC1485 string representation pointed
+ * to by "stringRep", and stores the result at "pName". If the string cannot
+ * be successfully converted, a non-fatal error is returned.
+ *
+ * NOTE: ifdefed BUILD_LIBPKIX_TESTS function: this function is allowed to be
+ * called only by pkix tests programs.
+ *
+ * PARAMETERS:
+ * "stringRep"
+ * Address of the RFC1485 string to be converted. Must be non-NULL.
+ * "pName"
+ * Address where the X500Name result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an X500NAME Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_CreateFromUtf8(
+ char *stringRep,
+ PKIX_PL_X500Name **pName,
+ void *plContext)
+{
+ PKIX_PL_X500Name *x500Name = NULL;
+ PLArenaPool *arena = NULL;
+ CERTName *nssDN = NULL;
+ SECItem *resultSecItem = NULL;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_CreateFromUtf8");
+ PKIX_NULLCHECK_TWO(pName, stringRep);
+
+ nssDN = CERT_AsciiToName(stringRep);
+ if (nssDN == NULL) {
+ PKIX_ERROR(PKIX_COULDNOTCREATENSSDN);
+ }
+
+ arena = nssDN->arena;
+
+ /* create a PKIX_PL_X500Name object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_X500NAME_TYPE,
+ sizeof (PKIX_PL_X500Name),
+ (PKIX_PL_Object **)&x500Name,
+ plContext),
+ PKIX_COULDNOTCREATEX500NAMEOBJECT);
+
+ /* populate the nssDN field */
+ x500Name->arena = arena;
+ x500Name->nssDN.arena = arena;
+ x500Name->nssDN.rdns = nssDN->rdns;
+
+ resultSecItem =
+ SEC_ASN1EncodeItem(arena, &x500Name->derName, nssDN,
+ CERT_NameTemplate);
+
+ if (resultSecItem == NULL){
+ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
+ }
+
+ *pName = x500Name;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ if (x500Name) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)x500Name,
+ plContext);
+ } else if (nssDN) {
+ CERT_DestroyName(nssDN);
+ }
+ }
+
+ PKIX_RETURN(X500NAME);
+}
+#endif /* BUILD_LIBPKIX_TESTS */
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetCERTName
+ *
+ * DESCRIPTION:
+ *
+ * Returns the pointer to CERTName member of X500Name structure.
+ *
+ * Returned pointed should not be freed.2
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose OrganizationName is to be extracted. Must be
+ * non-NULL.
+ * "pCERTName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetCERTName(
+ PKIX_PL_X500Name *xname,
+ CERTName **pCERTName,
+ void *plContext)
+{
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCERTName");
+ PKIX_NULLCHECK_TWO(xname, pCERTName);
+
+ *pCERTName = &xname->nssDN;
+
+ PKIX_RETURN(X500NAME);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_X500Name_CreateFromCERTName (see comments in pkix_pl_pki.h)
+ */
+
+PKIX_Error *
+PKIX_PL_X500Name_CreateFromCERTName(
+ SECItem *derName,
+ CERTName *name,
+ PKIX_PL_X500Name **pName,
+ void *plContext)
+{
+ PLArenaPool *arena = NULL;
+ SECStatus rv = SECFailure;
+ PKIX_PL_X500Name *x500Name = NULL;
+
+ PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_CreateFromCERTName");
+ PKIX_NULLCHECK_ONE(pName);
+ if (derName == NULL && name == NULL) {
+ PKIX_ERROR(PKIX_NULLARGUMENT);
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_X500NAME_TYPE,
+ sizeof (PKIX_PL_X500Name),
+ (PKIX_PL_Object **)&x500Name,
+ plContext),
+ PKIX_COULDNOTCREATEX500NAMEOBJECT);
+
+ x500Name->arena = arena;
+ x500Name->nssDN.arena = NULL;
+
+ if (derName != NULL) {
+ rv = SECITEM_CopyItem(arena, &x500Name->derName, derName);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ }
+
+ if (name != NULL) {
+ rv = CERT_CopyName(arena, &x500Name->nssDN, name);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_CERTCOPYNAMEFAILED);
+ }
+ } else {
+ rv = SEC_QuickDERDecodeItem(arena, &x500Name->nssDN,
+ CERT_NameTemplate,
+ &x500Name->derName);
+ if (rv == SECFailure) {
+ PKIX_ERROR(PKIX_SECQUICKDERDECODERFAILED);
+ }
+ }
+
+ *pName = x500Name;
+
+cleanup:
+ if (PKIX_ERROR_RECEIVED) {
+ if (x500Name) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object*)x500Name,
+ plContext);
+ } else if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ }
+
+ PKIX_RETURN(X500NAME);
+}
+
+#ifdef BUILD_LIBPKIX_TESTS
+/*
+ * FUNCTION: PKIX_PL_X500Name_Create (see comments in pkix_pl_pki.h)
+ *
+ * NOTE: ifdefed BUILD_LIBPKIX_TESTS function: this function is allowed
+ * to be called only by pkix tests programs.
+ */
+PKIX_Error *
+PKIX_PL_X500Name_Create(
+ PKIX_PL_String *stringRep,
+ PKIX_PL_X500Name **pName,
+ void *plContext)
+{
+ char *utf8String = NULL;
+ PKIX_UInt32 utf8Length = 0;
+
+ PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_Create");
+ PKIX_NULLCHECK_TWO(pName, stringRep);
+
+ /*
+ * convert the input PKIX_PL_String to PKIX_UTF8_NULL_TERM.
+ * we need to use this format specifier because
+ * CERT_AsciiToName expects a NULL-terminated UTF8 string.
+ * Since UTF8 allow NUL characters in the middle of the
+ * string, this is buggy. However, as a workaround, using
+ * PKIX_UTF8_NULL_TERM gives us a NULL-terminated UTF8 string.
+ */
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stringRep,
+ PKIX_UTF8_NULL_TERM,
+ (void **)&utf8String,
+ &utf8Length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_CHECK(
+ pkix_pl_X500Name_CreateFromUtf8(utf8String,
+ pName, plContext),
+ PKIX_X500NAMECREATEFROMUTF8FAILED);
+
+cleanup:
+ PKIX_FREE(utf8String);
+
+ PKIX_RETURN(X500NAME);
+}
+#endif /* BUILD_LIBPKIX_TESTS */
+
+/*
+ * FUNCTION: PKIX_PL_X500Name_Match (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_X500Name_Match(
+ PKIX_PL_X500Name *firstX500Name,
+ PKIX_PL_X500Name *secondX500Name,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ SECItem *firstDerName = NULL;
+ SECItem *secondDerName = NULL;
+ SECComparison cmpResult;
+
+ PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_Match");
+ PKIX_NULLCHECK_THREE(firstX500Name, secondX500Name, pResult);
+
+ if (firstX500Name == secondX500Name){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ firstDerName = &firstX500Name->derName;
+ secondDerName = &secondX500Name->derName;
+
+ PKIX_NULLCHECK_TWO(firstDerName->data, secondDerName->data);
+
+ cmpResult = SECITEM_CompareItem(firstDerName, secondDerName);
+ if (cmpResult != SECEqual) {
+ cmpResult = CERT_CompareName(&firstX500Name->nssDN,
+ &secondX500Name->nssDN);
+ }
+
+ *pResult = (cmpResult == SECEqual);
+
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetSECName
+ *
+ * DESCRIPTION:
+ * Returns a copy of CERTName DER representation allocated on passed in arena.
+ * If allocation on arena can not be done, NULL is stored at "pSECName".
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose CERTName flag is to be encoded. Must be
+ * non-NULL.
+ * "arena"
+ * Address of the PLArenaPool to be used in the encoding, and in which
+ * "pSECName" will be allocated. Must be non-NULL.
+ * "pSECName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetDERName(
+ PKIX_PL_X500Name *xname,
+ PLArenaPool *arena,
+ SECItem **pDERName,
+ void *plContext)
+{
+ SECItem *derName = NULL;
+
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetDERName");
+
+ PKIX_NULLCHECK_THREE(xname, arena, pDERName);
+
+ /* Return NULL is X500Name was not created from DER */
+ if (xname->derName.data == NULL) {
+ *pDERName = NULL;
+ goto cleanup;
+ }
+
+ derName = SECITEM_ArenaDupItem(arena, &xname->derName);
+ if (derName == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ *pDERName = derName;
+cleanup:
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetCommonName
+ *
+ * DESCRIPTION:
+ * Extracts the CommonName component of the X500Name object pointed to by
+ * "xname", and stores the result at "pCommonName". If the CommonName cannot
+ * be successfully extracted, NULL is stored at "pCommonName".
+ *
+ * The returned string must be freed with PORT_Free.
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose CommonName is to be extracted. Must be
+ * non-NULL.
+ * "pCommonName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetCommonName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pCommonName,
+ void *plContext)
+{
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCommonName");
+ PKIX_NULLCHECK_TWO(xname, pCommonName);
+
+ *pCommonName = (unsigned char *)CERT_GetCommonName(&xname->nssDN);
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetCountryName
+ *
+ * DESCRIPTION:
+ * Extracts the CountryName component of the X500Name object pointed to by
+ * "xname", and stores the result at "pCountryName". If the CountryName cannot
+ * be successfully extracted, NULL is stored at "pCountryName".
+ *
+ * The returned string must be freed with PORT_Free.
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose CountryName is to be extracted. Must be
+ * non-NULL.
+ * "pCountryName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetCountryName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pCountryName,
+ void *plContext)
+{
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCountryName");
+ PKIX_NULLCHECK_TWO(xname, pCountryName);
+
+ *pCountryName = (unsigned char*)CERT_GetCountryName(&xname->nssDN);
+
+ PKIX_RETURN(X500NAME);
+}
+
+/*
+ * FUNCTION: pkix_pl_X500Name_GetOrgName
+ *
+ * DESCRIPTION:
+ * Extracts the OrganizationName component of the X500Name object pointed to by
+ * "xname", and stores the result at "pOrgName". If the OrganizationName cannot
+ * be successfully extracted, NULL is stored at "pOrgName".
+ *
+ * The returned string must be freed with PORT_Free.
+ *
+ * PARAMETERS:
+ * "xname"
+ * Address of X500Name whose OrganizationName is to be extracted. Must be
+ * non-NULL.
+ * "pOrgName"
+ * Address where result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ *
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ *
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_X500Name_GetOrgName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pOrgName,
+ void *plContext)
+{
+ PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetOrgName");
+ PKIX_NULLCHECK_TWO(xname, pOrgName);
+
+ *pOrgName = (unsigned char*)CERT_GetOrgName(&xname->nssDN);
+
+ PKIX_RETURN(X500NAME);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.h b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.h
new file mode 100644
index 0000000000..a62bdb82d5
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_x500name.h
@@ -0,0 +1,74 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_x500name.h
+ *
+ * X500Name Object Type Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_X500NAME_H
+#define _PKIX_PL_X500NAME_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct PKIX_PL_X500NameStruct{
+ PLArenaPool *arena; /* X500Name arena. Shared arena with nssDN
+ * and derName */
+ CERTName nssDN;
+ SECItem derName; /* adding DER encoded CERTName to the structure
+ * to avoid unnecessary name encoding when pass
+ * der name to cert finder */
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *pkix_pl_X500Name_RegisterSelf(void *plContext);
+
+PKIX_Error *pkix_pl_X500Name_GetDERName(
+ PKIX_PL_X500Name *xname,
+ PLArenaPool *arena,
+ SECItem **pSECName,
+ void *plContext);
+
+#ifdef BUILD_LIBPKIX_TESTS
+PKIX_Error * pkix_pl_X500Name_CreateFromUtf8(
+ char *stringRep,
+ PKIX_PL_X500Name **pName,
+ void *plContext);
+#endif /* BUILD_LIBPKIX_TESTS */
+
+PKIX_Error *pkix_pl_X500Name_GetCommonName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pCommonName,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_X500Name_GetCountryName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pCountryName,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_X500Name_GetOrgName(
+ PKIX_PL_X500Name *xname,
+ unsigned char **pOrgName,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_X500Name_GetCERTName(
+ PKIX_PL_X500Name *xname,
+ CERTName **pCERTName,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_X500NAME_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/Makefile b/security/nss/lib/libpkix/pkix_pl_nss/system/Makefile
new file mode 100644
index 0000000000..2b4b1574ab
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+
+#######################################################################
+# (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/lib/libpkix/pkix_pl_nss/system/exports.gyp b/security/nss/lib/libpkix/pkix_pl_nss/system/exports.gyp
new file mode 100644
index 0000000000..a2f759441e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/exports.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': 'lib_libpkix_pkix_pl_nss_system_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'pkix_pl_bigint.h',
+ 'pkix_pl_bytearray.h',
+ 'pkix_pl_common.h',
+ 'pkix_pl_hashtable.h',
+ 'pkix_pl_lifecycle.h',
+ 'pkix_pl_mem.h',
+ 'pkix_pl_monitorlock.h',
+ 'pkix_pl_mutex.h',
+ 'pkix_pl_object.h',
+ 'pkix_pl_oid.h',
+ 'pkix_pl_primhash.h',
+ 'pkix_pl_rwlock.h',
+ 'pkix_pl_string.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/manifest.mn b/security/nss/lib/libpkix/pkix_pl_nss/system/manifest.mn
new file mode 100644
index 0000000000..a143a03eed
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/manifest.mn
@@ -0,0 +1,43 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.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 = ../../../..
+
+PRIVATE_EXPORTS = \
+ pkix_pl_common.h \
+ pkix_pl_mem.h \
+ pkix_pl_object.h \
+ pkix_pl_string.h \
+ pkix_pl_primhash.h \
+ pkix_pl_bigint.h \
+ pkix_pl_mutex.h \
+ pkix_pl_bytearray.h \
+ pkix_pl_lifecycle.h \
+ pkix_pl_oid.h \
+ pkix_pl_hashtable.h \
+ pkix_pl_rwlock.h \
+ pkix_pl_monitorlock.h \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ pkix_pl_bigint.c \
+ pkix_pl_bytearray.c \
+ pkix_pl_common.c \
+ pkix_pl_error.c \
+ pkix_pl_hashtable.c \
+ pkix_pl_lifecycle.c \
+ pkix_pl_mem.c \
+ pkix_pl_monitorlock.c \
+ pkix_pl_mutex.c \
+ pkix_pl_object.c \
+ pkix_pl_oid.c \
+ pkix_pl_primhash.c \
+ pkix_pl_rwlock.c \
+ pkix_pl_string.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixsystem
+SHARED_LIBRARY = $(NULL)
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c
new file mode 100644
index 0000000000..cd8e15ee4b
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.c
@@ -0,0 +1,398 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_bigint.c
+ *
+ * BigInt Object Functions
+ *
+ */
+
+#include "pkix_pl_bigint.h"
+
+/* --Private-Big-Int-Functions------------------------------------ */
+
+/*
+ * FUNCTION: pkix_pl_BigInt_Comparator
+ * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_BigInt_Comparator(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_PL_BigInt *firstBigInt = NULL;
+ PKIX_PL_BigInt *secondBigInt = NULL;
+ char *firstPtr = NULL;
+ char *secondPtr = NULL;
+ PKIX_UInt32 firstLen, secondLen;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Comparator");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ PKIX_CHECK(pkix_CheckTypes
+ (firstObject, secondObject, PKIX_BIGINT_TYPE, plContext),
+ PKIX_ARGUMENTSNOTBIGINTS);
+
+ /* It's safe to cast */
+ firstBigInt = (PKIX_PL_BigInt*)firstObject;
+ secondBigInt = (PKIX_PL_BigInt*)secondObject;
+
+ *pResult = 0;
+ firstPtr = firstBigInt->dataRep;
+ secondPtr = secondBigInt->dataRep;
+ firstLen = firstBigInt->length;
+ secondLen = secondBigInt->length;
+
+ if (firstLen < secondLen) {
+ *pResult = -1;
+ } else if (firstLen > secondLen) {
+ *pResult = 1;
+ } else if (firstLen == secondLen) {
+ PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcmp).\n");
+ *pResult = PORT_Memcmp(firstPtr, secondPtr, firstLen);
+ }
+
+cleanup:
+
+ PKIX_RETURN(BIGINT);
+}
+
+/*
+ * FUNCTION: pkix_pl_BigInt_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_BigInt_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_BigInt *bigInt = NULL;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
+ PKIX_OBJECTNOTBIGINT);
+
+ bigInt = (PKIX_PL_BigInt*)object;
+
+ PKIX_FREE(bigInt->dataRep);
+ bigInt->dataRep = NULL;
+ bigInt->length = 0;
+
+cleanup:
+
+ PKIX_RETURN(BIGINT);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_BigInt_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_BigInt_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_BigInt *bigInt = NULL;
+ char *outputText = NULL;
+ PKIX_UInt32 i, j, lengthChars;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
+ PKIX_OBJECTNOTBIGINT);
+
+ bigInt = (PKIX_PL_BigInt*)object;
+
+ /* number of chars = 2 * (number of bytes) + null terminator */
+ lengthChars = (bigInt->length * 2) + 1;
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (lengthChars, (void **)&outputText, plContext),
+ PKIX_MALLOCFAILED);
+
+ for (i = 0, j = 0; i < bigInt->length; i += 1, j += 2){
+ outputText[j] = pkix_i2hex
+ ((char) ((*(bigInt->dataRep+i) & 0xf0) >> 4));
+ outputText[j+1] = pkix_i2hex
+ ((char) (*(bigInt->dataRep+i) & 0x0f));
+ }
+
+ outputText[lengthChars-1] = '\0';
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ outputText,
+ 0,
+ pString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+cleanup:
+
+ PKIX_FREE(outputText);
+
+ PKIX_RETURN(BIGINT);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_BigInt_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_BigInt_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_BigInt *bigInt = NULL;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BIGINT_TYPE, plContext),
+ PKIX_OBJECTNOTBIGINT);
+
+ bigInt = (PKIX_PL_BigInt*)object;
+
+ PKIX_CHECK(pkix_hash
+ ((void *)bigInt->dataRep,
+ bigInt->length,
+ pHashcode,
+ plContext),
+ PKIX_HASHFAILED);
+
+cleanup:
+
+ PKIX_RETURN(BIGINT);
+}
+
+/*
+ * FUNCTION: pkix_pl_BigInt_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_BigInt_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Int32 cmpResult = 0;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_CheckType(first, PKIX_BIGINT_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTBIGINT);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_BIGINT_TYPE) goto cleanup;
+
+ PKIX_CHECK(pkix_pl_BigInt_Comparator
+ (first, second, &cmpResult, plContext),
+ PKIX_BIGINTCOMPARATORFAILED);
+
+ *pResult = (cmpResult == 0);
+
+cleanup:
+
+ PKIX_RETURN(BIGINT);
+}
+
+/*
+ * FUNCTION: pkix_pl_BigInt_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_BIGINT_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_BigInt_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_RegisterSelf");
+
+ entry.description = "BigInt";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_BigInt);
+ entry.destructor = pkix_pl_BigInt_Destroy;
+ entry.equalsFunction = pkix_pl_BigInt_Equals;
+ entry.hashcodeFunction = pkix_pl_BigInt_Hashcode;
+ entry.toStringFunction = pkix_pl_BigInt_ToString;
+ entry.comparator = pkix_pl_BigInt_Comparator;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_BIGINT_TYPE] = entry;
+
+ PKIX_RETURN(BIGINT);
+}
+
+/*
+ * FUNCTION: pkix_pl_BigInt_CreateWithBytes
+ * DESCRIPTION:
+ *
+ * Creates a new BigInt of size "length" representing the array of bytes
+ * pointed to by "bytes" and stores it at "pBigInt". The caller should make
+ * sure that the first byte is not 0x00 (unless it is the the only byte).
+ * This function does not do that checking.
+ *
+ * Once created, a PKIX_PL_BigInt object is immutable.
+ *
+ * PARAMETERS:
+ * "bytes"
+ * Address of array of bytes. Must be non-NULL.
+ * "length"
+ * Length of the array. Must be non-zero.
+ * "pBigInt"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext" - Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_BigInt_CreateWithBytes(
+ char *bytes,
+ PKIX_UInt32 length,
+ PKIX_PL_BigInt **pBigInt,
+ void *plContext)
+{
+ PKIX_PL_BigInt *bigInt = NULL;
+
+ PKIX_ENTER(BIGINT, "pkix_pl_BigInt_CreateWithBytes");
+ PKIX_NULLCHECK_TWO(pBigInt, bytes);
+
+ if (length == 0) {
+ PKIX_ERROR(PKIX_BIGINTLENGTH0INVALID)
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_BIGINT_TYPE,
+ sizeof (PKIX_PL_BigInt),
+ (PKIX_PL_Object **)&bigInt,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (length, (void **)&(bigInt->dataRep), plContext),
+ PKIX_MALLOCFAILED);
+
+ PKIX_BIGINT_DEBUG("\t\tCalling PORT_Memcpy).\n");
+ (void) PORT_Memcpy(bigInt->dataRep, bytes, length);
+
+ bigInt->length = length;
+
+ *pBigInt = bigInt;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(bigInt);
+ }
+
+ PKIX_RETURN(BIGINT);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_BigInt_Create (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_BigInt_Create(
+ PKIX_PL_String *stringRep,
+ PKIX_PL_BigInt **pBigInt,
+ void *plContext)
+{
+ PKIX_PL_BigInt *bigInt = NULL;
+ char *asciiString = NULL;
+ PKIX_UInt32 lengthBytes;
+ PKIX_UInt32 lengthString;
+ PKIX_UInt32 i;
+ char currChar;
+
+ PKIX_ENTER(BIGINT, "PKIX_PL_BigInt_Create");
+ PKIX_NULLCHECK_TWO(pBigInt, stringRep);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (stringRep,
+ PKIX_ESCASCII,
+ (void **)&asciiString,
+ &lengthString,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ if ((lengthString == 0) || ((lengthString % 2) != 0)){
+ PKIX_ERROR(PKIX_SOURCESTRINGHASINVALIDLENGTH);
+ }
+
+ if (lengthString != 2){
+ if ((asciiString[0] == '0') && (asciiString[1] == '0')){
+ PKIX_ERROR(PKIX_FIRSTDOUBLEHEXMUSTNOTBE00);
+ }
+ }
+
+ for (i = 0; i < lengthString; i++) {
+ currChar = asciiString[i];
+ if (!PKIX_ISXDIGIT(currChar)){
+ PKIX_ERROR(PKIX_INVALIDCHARACTERINBIGINT);
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_BIGINT_TYPE,
+ sizeof (PKIX_PL_BigInt),
+ (PKIX_PL_Object **)&bigInt,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ /* number of bytes = 0.5 * (number of chars) */
+ lengthBytes = lengthString/2;
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (lengthBytes, (void **)&(bigInt->dataRep), plContext),
+ PKIX_MALLOCFAILED);
+
+ for (i = 0; i < lengthString; i += 2){
+ (bigInt->dataRep)[i/2] =
+ (pkix_hex2i(asciiString[i])<<4) |
+ pkix_hex2i(asciiString[i+1]);
+ }
+
+ bigInt->length = lengthBytes;
+
+ *pBigInt = bigInt;
+
+cleanup:
+
+ PKIX_FREE(asciiString);
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(bigInt);
+ }
+
+ PKIX_RETURN(BIGINT);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.h
new file mode 100644
index 0000000000..b3df808a8d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bigint.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/. */
+/*
+ * pkix_pl_bigint.h
+ *
+ * Bigint Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_BIGINT_H
+#define _PKIX_PL_BIGINT_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_BigIntStruct {
+ char *dataRep;
+ PKIX_UInt32 length;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_BigInt_CreateWithBytes(
+ char *bytes,
+ PKIX_UInt32 length,
+ PKIX_PL_BigInt **pBigInt,
+ void *plContext);
+
+PKIX_Error *pkix_pl_BigInt_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_BIGINT_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c
new file mode 100644
index 0000000000..0a2e9c08f3
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.c
@@ -0,0 +1,504 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_bytearray.c
+ *
+ * ByteArray Object Functions
+ *
+ */
+
+#include "pkix_pl_bytearray.h"
+
+/* --Private-ByteArray-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_ToHexString
+ * DESCRIPTION:
+ *
+ * Creates a hex-String representation of the ByteArray pointed to by "array"
+ * and stores the result at "pString". The hex-String consists of hex-digit
+ * pairs separated by spaces, and the entire string enclosed within square
+ * brackets, e.g. [43 61 6E 20 79 6F 75 20 72 65 61 64 20 74 68 69 73 3F].
+ * A zero-length ByteArray is represented as [].
+ * PARAMETERS
+ * "array"
+ * ByteArray to be represented by the hex-String; must be non-NULL
+ * "pString"
+ * Address where String will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Cert Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_ByteArray_ToHexString(
+ PKIX_PL_ByteArray *array,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ char *tempText = NULL;
+ char *stringText = NULL; /* "[XX XX XX ...]" */
+ PKIX_UInt32 i, outputLen, bufferSize;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_ToHexString");
+ PKIX_NULLCHECK_TWO(array, pString);
+
+ if ((array->length) == 0) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "[]", 0, pString, plContext),
+ PKIX_COULDNOTCREATESTRING);
+ } else {
+ /*
+ * Allocate space for format string
+ * '[' + "XX" + (n-1)*" XX" + ']' + '\0'
+ */
+ bufferSize = 2 + (3*(array->length));
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (bufferSize, (void **)&stringText, plContext),
+ PKIX_COULDNOTALLOCATEMEMORY);
+
+ stringText[0] = 0;
+ outputLen = 0;
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
+ tempText = PR_smprintf
+ ("[%02X", (0x0FF&((char *)(array->array))[0]));
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
+ outputLen += PL_strlen(tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
+ stringText = PL_strcat(stringText, tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
+ PR_smprintf_free(tempText);
+
+ for (i = 1; i < array->length; i++) {
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
+ tempText = PR_smprintf
+ (" %02X", (0x0FF&((char *)(array->array))[i]));
+
+ if (tempText == NULL){
+ PKIX_ERROR(PKIX_PRSMPRINTFFAILED);
+ }
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
+ outputLen += PL_strlen(tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
+ stringText = PL_strcat(stringText, tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
+ PR_smprintf_free(tempText);
+ tempText = NULL;
+ }
+
+ stringText[outputLen++] = ']';
+ stringText[outputLen] = 0;
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ stringText,
+ 0,
+ pString,
+ plContext),
+ PKIX_COULDNOTCREATESTRING);
+ }
+
+cleanup:
+
+ PKIX_FREE(stringText);
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_Comparator
+ * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
+ *
+ * NOTE:
+ * It is not clear that this definition of comparing byte arrays makes
+ * sense. It does allow you to tell whether two blocks of memory are
+ * identical, so we only use it for the Equals function (i.e. we don't
+ * register it as a Compare function for ByteArray).
+ */
+static PKIX_Error *
+pkix_pl_ByteArray_Comparator(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *firstByteArray = NULL;
+ PKIX_PL_ByteArray *secondByteArray = NULL;
+ unsigned char *firstData = NULL;
+ unsigned char *secondData = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Comparator");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ PKIX_CHECK(pkix_CheckTypes
+ (firstObject, secondObject, PKIX_BYTEARRAY_TYPE, plContext),
+ PKIX_ARGUMENTSNOTBYTEARRAYS);
+
+ /* It's safe to cast */
+ firstByteArray = (PKIX_PL_ByteArray *)firstObject;
+ secondByteArray = (PKIX_PL_ByteArray *)secondObject;
+
+ *pResult = 0;
+ firstData = (unsigned char *)firstByteArray->array;
+ secondData = (unsigned char *)secondByteArray->array;
+
+ if (firstByteArray->length < secondByteArray->length) {
+ *pResult = -1;
+ } else if (firstByteArray->length > secondByteArray->length) {
+ *pResult = 1;
+ } else if (firstByteArray->length == secondByteArray->length) {
+ /* Check if both array contents are identical */
+ for (i = 0;
+ (i < firstByteArray->length) && (*pResult == 0);
+ i++) {
+ if (firstData[i] < secondData[i]) {
+ *pResult = -1;
+ } else if (firstData[i] > secondData[i]) {
+ *pResult = 1;
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_ByteArray_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *array = NULL;
+ char *tempText = NULL;
+ char *stringText = NULL; /* "[OOO, OOO, ... OOO]" */
+ PKIX_UInt32 i, outputLen, bufferSize;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext),
+ PKIX_OBJECTNOTBYTEARRAY);
+
+ array = (PKIX_PL_ByteArray *)object;
+
+ if ((array->length) == 0) {
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "[]", 0, pString, plContext),
+ PKIX_COULDNOTCREATESTRING);
+ } else {
+ /* Allocate space for "XXX, ". */
+ bufferSize = 2+5*array->length;
+
+ /* Allocate space for format string */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (bufferSize, (void **)&stringText, plContext),
+ PKIX_MALLOCFAILED);
+
+ stringText[0] = 0;
+ outputLen = 0;
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
+ tempText =
+ PR_smprintf
+ ("[%03u", (0x0FF&((char *)(array->array))[0]));
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
+ outputLen += PL_strlen(tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
+ stringText = PL_strcat(stringText, tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
+ PR_smprintf_free(tempText);
+
+ for (i = 1; i < array->length; i++) {
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf).\n");
+ tempText = PR_smprintf
+ (", %03u",
+ (0x0FF&((char *)(array->array))[i]));
+
+ if (tempText == NULL){
+ PKIX_ERROR(PKIX_PRSMPRINTFFAILED);
+ }
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strlen).\n");
+ outputLen += PL_strlen(tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PL_strcat).\n");
+ stringText = PL_strcat(stringText, tempText);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PR_smprintf_free).\n");
+ PR_smprintf_free(tempText);
+ tempText = NULL;
+ }
+
+ stringText[outputLen++] = ']';
+ stringText[outputLen] = 0;
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, stringText, 0, pString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ }
+
+cleanup:
+
+ PKIX_FREE(stringText);
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_ByteArray_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Int32 cmpResult = 0;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ /* Sanity check: Test that "first" is a ByteArray */
+ PKIX_CHECK(pkix_CheckType(first, PKIX_BYTEARRAY_TYPE, plContext),
+ PKIX_FIRSTARGUMENTNOTBYTEARRAY);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ /* If types differ, then we will return false */
+ *pResult = PKIX_FALSE;
+
+ /* Second type may not be a BA */
+ if (secondType != PKIX_BYTEARRAY_TYPE) goto cleanup;
+
+ /* It's safe to cast here */
+ PKIX_CHECK(pkix_pl_ByteArray_Comparator
+ (first, second, &cmpResult, plContext),
+ PKIX_BYTEARRAYCOMPARATORFAILED);
+
+ /* ByteArrays are equal iff Comparator Result is 0 */
+ *pResult = (cmpResult == 0);
+
+cleanup:
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_ByteArray_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *array = NULL;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext),
+ PKIX_OBJECTNOTBYTEARRAY);
+
+ array = (PKIX_PL_ByteArray*)object;
+
+ PKIX_FREE(array->array);
+ array->array = NULL;
+ array->length = 0;
+
+cleanup:
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_ByteArray_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *array = NULL;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_BYTEARRAY_TYPE, plContext),
+ PKIX_OBJECTNOTBYTEARRAY);
+
+ array = (PKIX_PL_ByteArray*)object;
+
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)array->array,
+ array->length,
+ pHashcode,
+ plContext),
+ PKIX_HASHFAILED);
+
+cleanup:
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: pkix_pl_ByteArray_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_BYTEARRAY_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_ByteArray_RegisterSelf(void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(BYTEARRAY, "pkix_pl_ByteArray_RegisterSelf");
+
+ entry.description = "ByteArray";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_ByteArray);
+ entry.destructor = pkix_pl_ByteArray_Destroy;
+ entry.equalsFunction = pkix_pl_ByteArray_Equals;
+ entry.hashcodeFunction = pkix_pl_ByteArray_Hashcode;
+ entry.toStringFunction = pkix_pl_ByteArray_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_BYTEARRAY_TYPE] = entry;
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_ByteArray_Create (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_ByteArray_Create(
+ void *array,
+ PKIX_UInt32 length,
+ PKIX_PL_ByteArray **pByteArray,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+
+ PKIX_ENTER(BYTEARRAY, "PKIX_PL_ByteArray_Create");
+ PKIX_NULLCHECK_ONE(pByteArray);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_BYTEARRAY_TYPE,
+ sizeof (PKIX_PL_ByteArray),
+ (PKIX_PL_Object **)&byteArray,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECTSTORAGE);
+
+ byteArray->length = length;
+ byteArray->array = NULL;
+
+ if (length != 0){
+ /* Alloc space for array */
+ PKIX_NULLCHECK_ONE(array);
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (length, (void**)&(byteArray->array), plContext),
+ PKIX_MALLOCFAILED);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PORT_Memcpy).\n");
+ (void) PORT_Memcpy(byteArray->array, array, length);
+ }
+
+ *pByteArray = byteArray;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(byteArray);
+ }
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: PKIX_PL_ByteArray_GetPointer (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_ByteArray_GetPointer(
+ PKIX_PL_ByteArray *byteArray,
+ void **pArray,
+ void *plContext)
+{
+ void *bytes = NULL;
+ PKIX_ENTER(BYTEARRAY, "PKIX_PL_ByteArray_GetPointer");
+ PKIX_NULLCHECK_TWO(byteArray, pArray);
+
+ if (byteArray->length != 0){
+ PKIX_CHECK(PKIX_PL_Malloc
+ (byteArray->length, &bytes, plContext),
+ PKIX_MALLOCFAILED);
+
+ PKIX_BYTEARRAY_DEBUG("\tCalling PORT_Memcpy).\n");
+ (void) PORT_Memcpy
+ (bytes, byteArray->array, byteArray->length);
+ }
+
+ *pArray = bytes;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_FREE(bytes);
+ }
+
+ PKIX_RETURN(BYTEARRAY);
+}
+
+/*
+ * FUNCTION: PKIX_PL_ByteArray_GetLength (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_ByteArray_GetLength(
+ PKIX_PL_ByteArray *byteArray,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ PKIX_ENTER(BYTEARRAY, "PKIX_PL_ByteArray_GetLength");
+ PKIX_NULLCHECK_TWO(byteArray, pLength);
+
+ *pLength = byteArray->length;
+
+ PKIX_RETURN(BYTEARRAY);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.h
new file mode 100644
index 0000000000..4ba18eed74
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_bytearray.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/. */
+/*
+ * pkix_pl_bytearray.h
+ *
+ * ByteArray Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_BYTEARRAY_H
+#define _PKIX_PL_BYTEARRAY_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_ByteArrayStruct {
+ void *array;
+ PKIX_UInt32 length;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_ByteArray_ToHexString(
+ PKIX_PL_ByteArray *array,
+ PKIX_PL_String **pString,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_ByteArray_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_BYTEARRAY_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c
new file mode 100644
index 0000000000..831ce538d3
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.c
@@ -0,0 +1,1073 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_common.c
+ *
+ * Common utility functions used by various PKIX_PL functions
+ *
+ */
+
+#include "pkix_pl_common.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_LockObject
+ * DESCRIPTION:
+ *
+ * Locks the object pointed to by "object".
+ *
+ * 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 NULL if the function succeeds
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_LockObject(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader;
+
+ PKIX_ENTER(OBJECT, "pkix_LockObject");
+ PKIX_NULLCHECK_ONE(object);
+
+ if (object == (PKIX_PL_Object *)PKIX_ALLOC_ERROR()) {
+ goto cleanup;
+ }
+
+ PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
+ /* The header is sizeof(PKIX_PL_Object) before the object pointer */
+
+ objectHeader = object-1;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(objectHeader->lock);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_UnlockObject
+ * DESCRIPTION:
+ *
+ * Unlocks the object pointed to by "object".
+ *
+ * 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 NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_UnlockObject(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader;
+ PRStatus result;
+
+ PKIX_ENTER(OBJECT, "pkix_UnlockObject");
+ PKIX_NULLCHECK_ONE(object);
+
+ if (object == (PKIX_PL_Object *)PKIX_ALLOC_ERROR()) {
+ goto cleanup;
+ }
+
+ PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
+ /* The header is sizeof(PKIX_PL_Object) before the object pointer */
+
+ objectHeader = object-1;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ result = PR_Unlock(objectHeader->lock);
+
+ if (result == PR_FAILURE) {
+ PKIX_OBJECT_DEBUG("\tPR_Unlock failed.).\n");
+ PKIX_ERROR_FATAL(PKIX_ERRORUNLOCKINGOBJECT);
+ }
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_pl_UInt32_Overflows
+ * DESCRIPTION:
+ *
+ * Returns a PKIX_Boolean indicating whether the unsigned integer
+ * represented by "string" is too large to fit in 32-bits (i.e.
+ * whether it overflows). With the exception of the string "0",
+ * all other strings are stripped of any leading zeros. It is assumed
+ * that every character in "string" is from the set {'0' - '9'}.
+ *
+ * PARAMETERS
+ * "string"
+ * Address of array of bytes representing PKIX_UInt32 that's being tested
+ * for 32-bit overflow
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * PKIX_TRUE if PKIX_UInt32 represented by "string" overflows;
+ * PKIX_FALSE otherwise
+ */
+PKIX_Boolean
+pkix_pl_UInt32_Overflows(char *string){
+ char *firstNonZero = NULL;
+ PKIX_UInt32 length, i;
+ char *MAX_UINT32_STRING = "4294967295";
+
+ PKIX_DEBUG_ENTER(OID);
+
+ PKIX_OID_DEBUG("\tCalling PL_strlen).\n");
+ length = PL_strlen(string);
+
+ if (length < MAX_DIGITS_32){
+ return (PKIX_FALSE);
+ }
+
+ firstNonZero = string;
+ for (i = 0; i < length; i++){
+ if (*string == '0'){
+ firstNonZero++;
+ }
+ }
+
+ PKIX_OID_DEBUG("\tCalling PL_strlen).\n");
+ length = PL_strlen(firstNonZero);
+
+ if (length > MAX_DIGITS_32){
+ return (PKIX_TRUE);
+ }
+
+ PKIX_OID_DEBUG("\tCalling PL_strlen).\n");
+ if (length == MAX_DIGITS_32){
+ PKIX_OID_DEBUG("\tCalling PORT_Strcmp).\n");
+ if (PORT_Strcmp(firstNonZero, MAX_UINT32_STRING) > 0){
+ return (PKIX_TRUE);
+ }
+ }
+
+ return (PKIX_FALSE);
+}
+
+/*
+ * FUNCTION: pkix_pl_getOIDToken
+ * DESCRIPTION:
+ *
+ * Takes the array of DER-encoded bytes pointed to by "derBytes"
+ * (representing an OID) and the value of "index" representing the index into
+ * the array, and decodes the bytes until an integer token is retrieved. If
+ * successful, this function stores the integer component at "pToken" and
+ * stores the index representing the next byte in the array at "pIndex"
+ * (following the last byte that was used in the decoding). This new output
+ * index can be used in subsequent calls as an input index, allowing each
+ * token of the OID to be retrieved consecutively. Note that there is a
+ * special case for the first byte, in that it encodes two separate integer
+ * tokens. For example, the byte {2a} represents the integer tokens {1,2}.
+ * This special case is not handled here and must be handled by the caller.
+ *
+ * PARAMETERS
+ * "derBytes"
+ * Address of array of bytes representing a DER-encoded OID.
+ * Must be non-NULL.
+ * "index"
+ * Index into the array that this function will begin decoding at.
+ * "pToken"
+ * Destination for decoded OID token. Must be non-NULL.
+ * "pIndex"
+ * Destination for index of next byte following last byte used.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_getOIDToken(
+ char *derBytes,
+ PKIX_UInt32 index,
+ PKIX_UInt32 *pToken,
+ PKIX_UInt32 *pIndex,
+ void *plContext)
+{
+ PKIX_UInt32 retval, i, tmp;
+
+ PKIX_ENTER(OID, "pkix_pl_getOIDToken");
+ PKIX_NULLCHECK_THREE(derBytes, pToken, pIndex);
+
+ /*
+ * We should only need to parse a maximum of four bytes, because
+ * RFC 3280 "mandates support for OIDs which have arc elements
+ * with values that are less than 2^28, that is, they MUST be between
+ * 0 and 268,435,455, inclusive. This allows each arc element to be
+ * represented within a single 32 bit word."
+ */
+
+ for (i = 0, retval = 0; i < 4; i++) {
+ retval <<= 7;
+ tmp = derBytes[index];
+ index++;
+ retval |= (tmp & 0x07f);
+ if ((tmp & 0x080) == 0){
+ *pToken = retval;
+ *pIndex = index;
+ goto cleanup;
+ }
+ }
+
+ PKIX_ERROR(PKIX_INVALIDENCODINGOIDTOKENVALUETOOBIG);
+
+cleanup:
+
+ PKIX_RETURN(OID);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_helperBytes2Ascii
+ * DESCRIPTION:
+ *
+ * Converts an array of integers pointed to by "tokens" with a length of
+ * "numTokens", to an ASCII string consisting of those integers with dots in
+ * between them and stores the result at "pAscii". The ASCII representation is
+ * guaranteed to end with a NUL character. This is particularly useful for
+ * OID's and IP Addresses.
+ *
+ * The return value "pAscii" is not reference-counted and will need to
+ * be freed with PKIX_PL_Free.
+ *
+ * PARAMETERS
+ * "tokens"
+ * Address of array of integers. Must be non-NULL.
+ * "numTokens"
+ * Length of array of integers. Must be non-zero.
+ * "pAscii"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_helperBytes2Ascii(
+ PKIX_UInt32 *tokens,
+ PKIX_UInt32 numTokens,
+ char **pAscii,
+ void *plContext)
+{
+ char *tempString = NULL;
+ char *outputString = NULL;
+ char *format = "%d";
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 outputLen = 0;
+ PKIX_Int32 error;
+
+ PKIX_ENTER(OBJECT, "pkix_pl_helperBytes2Ascii");
+ PKIX_NULLCHECK_TWO(tokens, pAscii);
+
+ if (numTokens == 0) {
+ PKIX_ERROR_FATAL(PKIX_HELPERBYTES2ASCIINUMTOKENSZERO);
+ }
+
+ /*
+ * tempString will hold the string representation of a PKIX_UInt32 type
+ * The maximum value that can be held by an unsigned 32-bit integer
+ * is (2^32 - 1) = 4294967295 (which is ten digits long)
+ * Since tempString will hold the string representation of a
+ * PKIX_UInt32, we allocate 11 bytes for it (1 byte for '\0')
+ */
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (MAX_DIGITS_32 + 1, (void **)&tempString, plContext),
+ PKIX_MALLOCFAILED);
+
+ for (i = 0; i < numTokens; i++){
+ PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n");
+ error = PR_snprintf(tempString,
+ MAX_DIGITS_32 + 1,
+ format,
+ tokens[i]);
+ if (error == -1){
+ PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
+ }
+
+ PKIX_OBJECT_DEBUG("\tCalling PL_strlen).\n");
+ outputLen += PL_strlen(tempString);
+
+ /* Include a dot to separate each number */
+ outputLen++;
+ }
+
+ /* Allocate space for the destination string */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (outputLen, (void **)&outputString, plContext),
+ PKIX_MALLOCFAILED);
+
+ *outputString = '\0';
+
+ /* Concatenate all strings together */
+ for (i = 0; i < numTokens; i++){
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n");
+ error = PR_snprintf(tempString,
+ MAX_DIGITS_32 + 1,
+ format,
+ tokens[i]);
+ if (error == -1){
+ PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
+ }
+
+ PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n");
+ (void) PL_strcat(outputString, tempString);
+
+ /* we don't want to put a "." at the very end */
+ if (i < (numTokens - 1)){
+ PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n");
+ (void) PL_strcat(outputString, ".");
+ }
+ }
+
+ /* Ensure output string ends with terminating null */
+ outputString[outputLen-1] = '\0';
+
+ *pAscii = outputString;
+ outputString = NULL;
+
+cleanup:
+
+ PKIX_FREE(outputString);
+ PKIX_FREE(tempString);
+
+ PKIX_RETURN(OBJECT);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_ipAddrBytes2Ascii
+ * DESCRIPTION:
+ *
+ * Converts the DER encoding of an IPAddress pointed to by "secItem" to an
+ * ASCII representation and stores the result at "pAscii". The ASCII
+ * representation is guaranteed to end with a NUL character. The input
+ * SECItem must contain non-NULL data and must have a positive length.
+ *
+ * The return value "pAscii" is not reference-counted and will need to
+ * be freed with PKIX_PL_Free.
+ * XXX this function assumes that IPv4 addresses are being used
+ * XXX what about IPv6? can NSS tell the difference
+ *
+ * PARAMETERS
+ * "secItem"
+ * Address of SECItem which contains bytes and length of DER encoding.
+ * Must be non-NULL.
+ * "pAscii"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_ipAddrBytes2Ascii(
+ SECItem *secItem,
+ char **pAscii,
+ void *plContext)
+{
+ char *data = NULL;
+ PKIX_UInt32 *tokens = NULL;
+ PKIX_UInt32 numTokens = 0;
+ PKIX_UInt32 i = 0;
+ char *asciiString = NULL;
+
+ PKIX_ENTER(OBJECT, "pkix_pl_ipAddrBytes2Ascii");
+ PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data);
+
+ if (secItem->len == 0) {
+ PKIX_ERROR_FATAL(PKIX_IPADDRBYTES2ASCIIDATALENGTHZERO);
+ }
+
+ data = (char *)(secItem->data);
+ numTokens = secItem->len;
+
+ /* allocate space for array of integers */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (numTokens * sizeof (PKIX_UInt32),
+ (void **)&tokens,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ /* populate array of integers */
+ for (i = 0; i < numTokens; i++){
+ tokens[i] = data[i];
+ }
+
+ /* convert array of integers to ASCII */
+ PKIX_CHECK(pkix_pl_helperBytes2Ascii
+ (tokens, numTokens, &asciiString, plContext),
+ PKIX_HELPERBYTES2ASCIIFAILED);
+
+ *pAscii = asciiString;
+
+cleanup:
+
+ PKIX_FREE(tokens);
+
+ PKIX_RETURN(OBJECT);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_oidBytes2Ascii
+ * DESCRIPTION:
+ *
+ * Converts the DER encoding of an OID pointed to by "secItem" to an ASCII
+ * representation and stores it at "pAscii". The ASCII representation is
+ * guaranteed to end with a NUL character. The input SECItem must contain
+ * non-NULL data and must have a positive length.
+ *
+ * Example: the six bytes {2a 86 48 86 f7 0d} represent the
+ * four integer tokens {1, 2, 840, 113549}, which we will convert
+ * into ASCII yielding "1.2.840.113549"
+ *
+ * The return value "pAscii" is not reference-counted and will need to
+ * be freed with PKIX_PL_Free.
+ *
+ * PARAMETERS
+ * "secItem"
+ * Address of SECItem which contains bytes and length of DER encoding.
+ * Must be non-NULL.
+ * "pAscii"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an OID Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_oidBytes2Ascii(
+ SECItem *secItem,
+ char **pAscii,
+ void *plContext)
+{
+ char *data = NULL;
+ PKIX_UInt32 *tokens = NULL;
+ PKIX_UInt32 token = 0;
+ PKIX_UInt32 numBytes = 0;
+ PKIX_UInt32 numTokens = 0;
+ PKIX_UInt32 i = 0, x = 0, y = 0;
+ PKIX_UInt32 index = 0;
+ char *asciiString = NULL;
+
+ PKIX_ENTER(OID, "pkix_pl_oidBytes2Ascii");
+ PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data);
+
+ if (secItem->len == 0) {
+ PKIX_ERROR_FATAL(PKIX_OIDBYTES2ASCIIDATALENGTHZERO);
+ }
+
+ data = (char *)(secItem->data);
+ numBytes = secItem->len;
+ numTokens = 0;
+
+ /* calculate how many integer tokens are represented by the bytes. */
+ for (i = 0; i < numBytes; i++){
+ if ((data[i] & 0x080) == 0){
+ numTokens++;
+ }
+ }
+
+ /* if we are unable to retrieve any tokens at all, we throw an error */
+ if (numTokens == 0){
+ PKIX_ERROR(PKIX_INVALIDDERENCODINGFOROID);
+ }
+
+ /* add one more token b/c the first byte always contains two tokens */
+ numTokens++;
+
+ /* allocate space for array of integers */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (numTokens * sizeof (PKIX_UInt32),
+ (void **)&tokens,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ /* populate array of integers */
+ for (i = 0; i < numTokens; i++){
+
+ /* retrieve integer token */
+ PKIX_CHECK(pkix_pl_getOIDToken
+ (data, index, &token, &index, plContext),
+ PKIX_GETOIDTOKENFAILED);
+
+ if (i == 0){
+
+ /*
+ * special case: the first DER-encoded byte represents
+ * two tokens. We take advantage of fact that first
+ * token must be 0, 1, or 2; and second token must be
+ * between {0, 39} inclusive if first token is 0 or 1.
+ */
+
+ if (token < 40)
+ x = 0;
+ else if (token < 80)
+ x = 1;
+ else
+ x = 2;
+ y = token - (x * 40);
+
+ tokens[0] = x;
+ tokens[1] = y;
+ i++;
+ } else {
+ tokens[i] = token;
+ }
+ }
+
+ /* convert array of integers to ASCII */
+ PKIX_CHECK(pkix_pl_helperBytes2Ascii
+ (tokens, numTokens, &asciiString, plContext),
+ PKIX_HELPERBYTES2ASCIIFAILED);
+
+ *pAscii = asciiString;
+
+cleanup:
+
+ PKIX_FREE(tokens);
+ PKIX_RETURN(OID);
+
+}
+
+/*
+ * FUNCTION: pkix_UTF16_to_EscASCII
+ * DESCRIPTION:
+ *
+ * Converts array of bytes pointed to by "utf16String" with length of
+ * "utf16Length" (which must be even) into a freshly allocated Escaped ASCII
+ * string and stores a pointer to that string at "pDest" and stores the
+ * string's length at "pLength". The Escaped ASCII string's length does not
+ * include the final NUL character. The caller is responsible for freeing
+ * "pDest" using PKIX_PL_Free. If "debug" is set, uses EscASCII_Debug
+ * encoding.
+ *
+ * PARAMETERS:
+ * "utf16String"
+ * Address of array of bytes representing data source. Must be non-NULL.
+ * "utf16Length"
+ * Length of data source. Must be even.
+ * "debug"
+ * Boolean value indicating whether debug mode is desired.
+ * "pDest"
+ * Address where data will be stored. Must be non-NULL.
+ * "pLength"
+ * Address where data length will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a String Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_UTF16_to_EscASCII(
+ const void *utf16String,
+ PKIX_UInt32 utf16Length,
+ PKIX_Boolean debug,
+ char **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ char *destPtr = NULL;
+ PKIX_UInt32 i, charLen;
+ PKIX_UInt32 x = 0, y = 0, z = 0;
+ unsigned char *utf16Char = (unsigned char *)utf16String;
+
+ PKIX_ENTER(STRING, "pkix_UTF16_to_EscASCII");
+ PKIX_NULLCHECK_THREE(utf16String, pDest, pLength);
+
+ /* Assume every pair of bytes becomes &#xNNNN; */
+ charLen = 4*utf16Length;
+
+ /* utf16Lenght must be even */
+ if ((utf16Length % 2) != 0){
+ PKIX_ERROR(PKIX_UTF16ALIGNMENTERROR);
+ }
+
+ /* Count how many bytes we need */
+ for (i = 0; i < utf16Length; i += 2) {
+ if ((utf16Char[i] == 0x00)&&
+ pkix_isPlaintext(utf16Char[i+1], debug)) {
+ if (utf16Char[i+1] == '&') {
+ /* Need to convert this to &amp; */
+ charLen -= 3;
+ } else {
+ /* We can fit this into one char */
+ charLen -= 7;
+ }
+ } else if ((utf16Char[i] >= 0xD8) && (utf16Char[i] <= 0xDB)) {
+ if ((i+3) >= utf16Length) {
+ PKIX_ERROR(PKIX_UTF16HIGHZONEALIGNMENTERROR);
+ } else if ((utf16Char[i+2] >= 0xDC)&&
+ (utf16Char[i+2] <= 0xDF)) {
+ /* Quartet of bytes will become &#xNNNNNNNN; */
+ charLen -= 4;
+ /* Quartet of bytes will produce 12 chars */
+ i += 2;
+ } else {
+ /* Second pair should be DC00-DFFF */
+ PKIX_ERROR(PKIX_UTF16LOWZONEERROR);
+ }
+ }
+ }
+
+ *pLength = charLen;
+
+ /* Ensure this string is null terminated */
+ charLen++;
+
+ /* Allocate space for character array */
+ PKIX_CHECK(PKIX_PL_Malloc(charLen, (void **)pDest, plContext),
+ PKIX_MALLOCFAILED);
+
+ destPtr = *pDest;
+ for (i = 0; i < utf16Length; i += 2) {
+ if ((utf16Char[i] == 0x00)&&
+ pkix_isPlaintext(utf16Char[i+1], debug)) {
+ /* Write a single character */
+ *destPtr++ = utf16Char[i+1];
+ } else if ((utf16Char[i+1] == '&') && (utf16Char[i] == 0x00)){
+ *destPtr++ = '&';
+ *destPtr++ = 'a';
+ *destPtr++ = 'm';
+ *destPtr++ = 'p';
+ *destPtr++ = ';';
+ } else if ((utf16Char[i] >= 0xD8)&&
+ (utf16Char[i] <= 0xDB)&&
+ (utf16Char[i+2] >= 0xDC)&&
+ (utf16Char[i+2] <= 0xDF)) {
+ /*
+ * Special UTF pairs are of the form:
+ * x = D800..DBFF; y = DC00..DFFF;
+ * The result is of the form:
+ * ((x - D800) * 400 + (y - DC00)) + 0001 0000
+ */
+ x = 0x0FFFF & ((utf16Char[i]<<8) | utf16Char[i+1]);
+ y = 0x0FFFF & ((utf16Char[i+2]<<8) | utf16Char[i+3]);
+ z = ((x - 0xD800) * 0x400 + (y - 0xDC00)) + 0x00010000;
+
+ /* Sprintf &#xNNNNNNNN; */
+ PKIX_STRING_DEBUG("\tCalling PR_snprintf).\n");
+ if (PR_snprintf(destPtr, 13, "&#x%08X;", z) ==
+ (PKIX_UInt32)(-1)) {
+ PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
+ }
+ i += 2;
+ destPtr += 12;
+ } else {
+ /* Sprintf &#xNNNN; */
+ PKIX_STRING_DEBUG("\tCalling PR_snprintf).\n");
+ if (PR_snprintf
+ (destPtr,
+ 9,
+ "&#x%02X%02X;",
+ utf16Char[i],
+ utf16Char[i+1]) ==
+ (PKIX_UInt32)(-1)) {
+ PKIX_ERROR(PKIX_PRSNPRINTFFAILED);
+ }
+ destPtr += 8;
+ }
+ }
+ *destPtr = '\0';
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_FREE(*pDest);
+ }
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_EscASCII_to_UTF16
+ * DESCRIPTION:
+ *
+ * Converts array of bytes pointed to by "escAsciiString" with length of
+ * "escAsciiLength" into a freshly allocated UTF-16 string and stores a
+ * pointer to that string at "pDest" and stores the string's length at
+ * "pLength". The caller is responsible for freeing "pDest" using
+ * PKIX_PL_Free. If "debug" is set, uses EscASCII_Debug encoding.
+ *
+ * PARAMETERS:
+ * "escAsciiString"
+ * Address of array of bytes representing data source. Must be non-NULL.
+ * "escAsciiLength"
+ * Length of data source. Must be even.
+ * "debug"
+ * Boolean value indicating whether debug mode is desired.
+ * "pDest"
+ * Address where data will be stored. Must be non-NULL.
+ * "pLength"
+ * Address where data length will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a String Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_EscASCII_to_UTF16(
+ const char *escAsciiString,
+ PKIX_UInt32 escAsciiLen,
+ PKIX_Boolean debug,
+ void **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ PKIX_UInt32 newLen, i, j, charSize;
+ PKIX_UInt32 x = 0, y = 0, z = 0;
+ unsigned char *destPtr = NULL;
+ unsigned char testChar, testChar2;
+ unsigned char *stringData = (unsigned char *)escAsciiString;
+
+ PKIX_ENTER(STRING, "pkix_EscASCII_to_UTF16");
+ PKIX_NULLCHECK_THREE(escAsciiString, pDest, pLength);
+
+ if (escAsciiLen == 0) {
+ PKIX_CHECK(PKIX_PL_Malloc(escAsciiLen, pDest, plContext),
+ PKIX_MALLOCFAILED);
+ goto cleanup;
+ }
+
+ /* Assume each unicode character takes two bytes */
+ newLen = escAsciiLen*2;
+
+ /* Count up number of unicode encoded characters */
+ for (i = 0; i < escAsciiLen; i++) {
+ if (!pkix_isPlaintext(stringData[i], debug)&&
+ (stringData[i] != '&')) {
+ PKIX_ERROR(PKIX_ILLEGALCHARACTERINESCAPEDASCII);
+ } else if (PL_strstr(escAsciiString+i, "&amp;") ==
+ escAsciiString+i) {
+ /* Convert EscAscii "&amp;" to two bytes */
+ newLen -= 8;
+ i += 4;
+ } else if ((PL_strstr(escAsciiString+i, "&#x") ==
+ escAsciiString+i)||
+ (PL_strstr(escAsciiString+i, "&#X") ==
+ escAsciiString+i)) {
+ if (((i+7) <= escAsciiLen)&&
+ (escAsciiString[i+7] == ';')) {
+ /* Convert &#xNNNN; to two bytes */
+ newLen -= 14;
+ i += 7;
+ } else if (((i+11) <= escAsciiLen)&&
+ (escAsciiString[i+11] == ';')) {
+ /* Convert &#xNNNNNNNN; to four bytes */
+ newLen -= 20;
+ i += 11;
+ } else {
+ PKIX_ERROR(PKIX_ILLEGALUSEOFAMP);
+ }
+ }
+ }
+
+ PKIX_CHECK(PKIX_PL_Malloc(newLen, pDest, plContext),
+ PKIX_MALLOCFAILED);
+
+ /* Copy into newly allocated space */
+ destPtr = (unsigned char *)*pDest;
+
+ i = 0;
+ while (i < escAsciiLen) {
+ /* Copy each byte until you hit a &amp; */
+ if (pkix_isPlaintext(escAsciiString[i], debug)) {
+ *destPtr++ = 0x00;
+ *destPtr++ = escAsciiString[i++];
+ } else if (PL_strstr(escAsciiString+i, "&amp;") ==
+ escAsciiString+i) {
+ /* Convert EscAscii "&amp;" to two bytes */
+ *destPtr++ = 0x00;
+ *destPtr++ = '&';
+ i += 5;
+ } else if (((PL_strstr(escAsciiString+i, "&#x") ==
+ escAsciiString+i)||
+ (PL_strstr(escAsciiString+i, "&#X") ==
+ escAsciiString+i))&&
+ ((i+7) <= escAsciiLen)) {
+
+ /* We're either looking at &#xNNNN; or &#xNNNNNNNN; */
+ charSize = (escAsciiString[i+7] == ';')?4:8;
+
+ /* Skip past the &#x */
+ i += 3;
+
+ /* Make sure there is a terminating semi-colon */
+ if (((i+charSize) > escAsciiLen)||
+ (escAsciiString[i+charSize] != ';')) {
+ PKIX_ERROR(PKIX_TRUNCATEDUNICODEINESCAPEDASCII);
+ }
+
+ for (j = 0; j < charSize; j++) {
+ if (!PKIX_ISXDIGIT
+ (escAsciiString[i+j])) {
+ PKIX_ERROR(PKIX_ILLEGALUNICODECHARACTER);
+ } else if (charSize == 8) {
+ x |= (pkix_hex2i
+ (escAsciiString[i+j]))
+ <<(4*(7-j));
+ }
+ }
+
+ testChar =
+ (pkix_hex2i(escAsciiString[i])<<4)|
+ pkix_hex2i(escAsciiString[i+1]);
+ testChar2 =
+ (pkix_hex2i(escAsciiString[i+2])<<4)|
+ pkix_hex2i(escAsciiString[i+3]);
+
+ if (charSize == 4) {
+ if ((testChar >= 0xD8)&&
+ (testChar <= 0xDF)) {
+ PKIX_ERROR(PKIX_ILLEGALSURROGATEPAIR);
+ } else if ((testChar == 0x00)&&
+ pkix_isPlaintext(testChar2, debug)) {
+ PKIX_ERROR(
+ PKIX_ILLEGALCHARACTERINESCAPEDASCII);
+ }
+ *destPtr++ = testChar;
+ *destPtr++ = testChar2;
+ } else if (charSize == 8) {
+ /* First two chars must be 0001-0010 */
+ if (!((testChar == 0x00)&&
+ ((testChar2 >= 0x01)&&
+ (testChar2 <= 0x10)))) {
+ PKIX_ERROR(
+ PKIX_ILLEGALCHARACTERINESCAPEDASCII);
+ }
+ /*
+ * Unicode Strings of the form:
+ * x = 0001 0000..0010 FFFF
+ * Encoded as pairs of UTF-16 where
+ * y = ((x - 0001 0000) / 400) + D800
+ * z = ((x - 0001 0000) % 400) + DC00
+ */
+ x -= 0x00010000;
+ y = (x/0x400)+ 0xD800;
+ z = (x%0x400)+ 0xDC00;
+
+ /* Copy four bytes */
+ *destPtr++ = (y&0xFF00)>>8;
+ *destPtr++ = (y&0x00FF);
+ *destPtr++ = (z&0xFF00)>>8;
+ *destPtr++ = (z&0x00FF);
+ }
+ /* Move past the Hex digits and the semi-colon */
+ i += charSize+1;
+ } else {
+ /* Do not allow any other non-plaintext character */
+ PKIX_ERROR(PKIX_ILLEGALCHARACTERINESCAPEDASCII);
+ }
+ }
+
+ *pLength = newLen;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_FREE(*pDest);
+ }
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_UTF16_to_UTF8
+ * DESCRIPTION:
+ *
+ * Converts array of bytes pointed to by "utf16String" with length of
+ * "utf16Length" into a freshly allocated UTF-8 string and stores a pointer
+ * to that string at "pDest" and stores the string's length at "pLength" (not
+ * counting the null terminator, if requested. The caller is responsible for
+ * freeing "pDest" using PKIX_PL_Free.
+ *
+ * PARAMETERS:
+ * "utf16String"
+ * Address of array of bytes representing data source. Must be non-NULL.
+ * "utf16Length"
+ * Length of data source. Must be even.
+ * "null-term"
+ * Boolean value indicating whether output should be null-terminated.
+ * "pDest"
+ * Address where data will be stored. Must be non-NULL.
+ * "pLength"
+ * Address where data length will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a String Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_UTF16_to_UTF8(
+ const void *utf16String,
+ PKIX_UInt32 utf16Length,
+ PKIX_Boolean null_term,
+ void **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ PKIX_Boolean result;
+ PKIX_UInt32 reallocLen;
+ char *endPtr = NULL;
+
+ PKIX_ENTER(STRING, "pkix_UTF16_to_UTF8");
+ PKIX_NULLCHECK_THREE(utf16String, pDest, pLength);
+
+ /* XXX How big can a UTF8 string be compared to a UTF16? */
+ PKIX_CHECK(PKIX_PL_Calloc(1, utf16Length*2, pDest, plContext),
+ PKIX_CALLOCFAILED);
+
+ PKIX_STRING_DEBUG("\tCalling PORT_UCS2_UTF8Conversion).\n");
+ result = PORT_UCS2_UTF8Conversion
+ (PKIX_FALSE, /* False = From UCS2 */
+ (unsigned char *)utf16String,
+ utf16Length,
+ (unsigned char *)*pDest,
+ utf16Length*2, /* Max Size */
+ pLength);
+ if (result == PR_FALSE){
+ PKIX_ERROR(PKIX_PORTUCS2UTF8CONVERSIONFAILED);
+ }
+
+ reallocLen = *pLength;
+
+ if (null_term){
+ reallocLen++;
+ }
+
+ PKIX_CHECK(PKIX_PL_Realloc(*pDest, reallocLen, pDest, plContext),
+ PKIX_REALLOCFAILED);
+
+ if (null_term){
+ endPtr = (char*)*pDest + reallocLen - 1;
+ *endPtr = '\0';
+ }
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_FREE(*pDest);
+ }
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_UTF8_to_UTF16
+ * DESCRIPTION:
+ *
+ * Converts array of bytes pointed to by "utf8String" with length of
+ * "utf8Length" into a freshly allocated UTF-16 string and stores a pointer
+ * to that string at "pDest" and stores the string's length at "pLength". The
+ * caller is responsible for freeing "pDest" using PKIX_PL_Free.
+ *
+ * PARAMETERS:
+ * "utf8String"
+ * Address of array of bytes representing data source. Must be non-NULL.
+ * "utf8Length"
+ * Length of data source. Must be even.
+ * "pDest"
+ * Address where data will be stored. Must be non-NULL.
+ * "pLength"
+ * Address where data length will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a String Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_UTF8_to_UTF16(
+ const void *utf8String,
+ PKIX_UInt32 utf8Length,
+ void **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ PKIX_Boolean result;
+
+ PKIX_ENTER(STRING, "pkix_UTF8_to_UTF16");
+ PKIX_NULLCHECK_THREE(utf8String, pDest, pLength);
+
+ /* XXX How big can a UTF8 string be compared to a UTF16? */
+ PKIX_CHECK(PKIX_PL_Calloc(1, utf8Length*2, pDest, plContext),
+ PKIX_MALLOCFAILED);
+
+ PKIX_STRING_DEBUG("\tCalling PORT_UCS2_UTF8Conversion).\n");
+ result = PORT_UCS2_UTF8Conversion
+ (PKIX_TRUE, /* True = From UTF8 */
+ (unsigned char *)utf8String,
+ utf8Length,
+ (unsigned char *)*pDest,
+ utf8Length*2, /* Max Size */
+ pLength);
+ if (result == PR_FALSE){
+ PKIX_ERROR(PKIX_PORTUCS2UTF8CONVERSIONFAILED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Realloc(*pDest, *pLength, pDest, plContext),
+ PKIX_REALLOCFAILED);
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_FREE(*pDest);
+ }
+
+ PKIX_RETURN(STRING);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h
new file mode 100644
index 0000000000..2946e07a67
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_common.h
@@ -0,0 +1,159 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_common.h
+ *
+ * Common central header file included by all PL source files
+ *
+ */
+
+#ifndef _PKIX_PL_COMMON_H
+#define _PKIX_PL_COMMON_H
+
+/* PKIX HEADERS */
+#include "pkix_tools.h"
+
+/* NSS headers */
+#include "nss.h"
+#include "secport.h"
+#include "secasn1.h"
+#include "secerr.h"
+#include "base64.h"
+#include "cert.h"
+#include "certdb.h"
+#include "genname.h"
+#include "xconst.h"
+#include "keyhi.h"
+#include "ocsp.h"
+#include "ocspt.h"
+#include "pk11pub.h"
+#include "pkcs11.h"
+#include "pkcs11t.h"
+#include "prio.h"
+
+/* NSPR headers */
+#include "nspr.h"
+
+/* private PKIX_PL_NSS system headers */
+#include "pkix_pl_object.h"
+#include "pkix_pl_string.h"
+#ifndef NSS_PKIX_NO_LDAP
+#include "pkix_pl_ldapt.h"
+#endif /* !NSS_PKIX_NO_LDAP */
+#include "pkix_pl_aiamgr.h"
+#include "pkix_pl_bigint.h"
+#include "pkix_pl_oid.h"
+#include "pkix_pl_x500name.h"
+#include "pkix_pl_generalname.h"
+#include "pkix_pl_publickey.h"
+#include "pkix_pl_bytearray.h"
+#include "pkix_pl_date.h"
+#include "pkix_pl_primhash.h"
+#include "pkix_pl_basicconstraints.h"
+#include "pkix_pl_bytearray.h"
+#include "pkix_pl_cert.h"
+#include "pkix_pl_certpolicyinfo.h"
+#include "pkix_pl_certpolicymap.h"
+#include "pkix_pl_certpolicyqualifier.h"
+#include "pkix_pl_crldp.h"
+#include "pkix_pl_crl.h"
+#include "pkix_pl_crlentry.h"
+#include "pkix_pl_nameconstraints.h"
+#include "pkix_pl_ocsprequest.h"
+#include "pkix_pl_ocspresponse.h"
+#include "pkix_pl_pk11certstore.h"
+#include "pkix_pl_socket.h"
+#ifndef NSS_PKIX_NO_LDAP
+#include "pkix_pl_ldapcertstore.h"
+#include "pkix_pl_ldaprequest.h"
+#include "pkix_pl_ldapresponse.h"
+#endif /* !NSS_PKIX_NO_LDAP */
+#include "pkix_pl_nsscontext.h"
+#include "pkix_pl_httpcertstore.h"
+#include "pkix_pl_httpdefaultclient.h"
+#include "pkix_pl_infoaccess.h"
+#include "pkix_sample_modules.h"
+
+#define MAX_DIGITS_32 (PKIX_UInt32) 10
+
+#define PKIX_PL_NSSCALL(type, func, args) \
+ PKIX_ ## type ## _DEBUG_ARG("( Calling %s).\n", #func); \
+ (func args)
+
+#define PKIX_PL_NSSCALLRV(type, lvalue, func, args) \
+ PKIX_ ## type ## _DEBUG_ARG("( Calling %s).\n", #func); \
+ lvalue = (func args)
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_LockObject(
+ PKIX_PL_Object *object,
+ void *plContext);
+
+PKIX_Error *
+pkix_UnlockObject(
+ PKIX_PL_Object *object,
+ void *plContext);
+
+PKIX_Boolean
+pkix_pl_UInt32_Overflows(char *string);
+
+PKIX_Error *
+pkix_pl_helperBytes2Ascii(
+ PKIX_UInt32 *tokens,
+ PKIX_UInt32 numTokens,
+ char **pAscii,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_ipAddrBytes2Ascii(
+ SECItem *secItem,
+ char **pAscii,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_oidBytes2Ascii(
+ SECItem *secItem,
+ char **pAscii,
+ void *plContext);
+
+/* --String-Encoding-Conversion-Functions------------------------ */
+
+PKIX_Error *
+pkix_UTF16_to_EscASCII(
+ const void *utf16String,
+ PKIX_UInt32 utf16Length,
+ PKIX_Boolean debug,
+ char **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext);
+
+PKIX_Error *
+pkix_EscASCII_to_UTF16(
+ const char *escAsciiString,
+ PKIX_UInt32 escAsciiLen,
+ PKIX_Boolean debug,
+ void **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext);
+
+PKIX_Error *
+pkix_UTF16_to_UTF8(
+ const void *utf16String,
+ PKIX_UInt32 utf16Length,
+ PKIX_Boolean null_Term,
+ void **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext);
+
+PKIX_Error *
+pkix_UTF8_to_UTF16(
+ const void *utf8Source,
+ PKIX_UInt32 utf8Length,
+ void **pDest,
+ PKIX_UInt32 *pLength,
+ void *plContext);
+
+#endif /* _PKIX_PL_COMMON_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c
new file mode 100644
index 0000000000..2631aed031
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_error.c
@@ -0,0 +1,26 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_error.c
+ *
+ * PL error functions
+ *
+ */
+
+#include "pkix_pl_common.h"
+
+#undef PKIX_ERRORENTRY
+
+#define PKIX_ERRORENTRY(name,desc,plerr) plerr
+
+const PKIX_Int32 PKIX_PLErrorIndex[] =
+{
+#include "pkix_errorstrings.h"
+};
+
+int
+PKIX_PL_GetPLErrorCode()
+{
+ return PORT_GetError();
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c
new file mode 100644
index 0000000000..260365375e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.c
@@ -0,0 +1,383 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_hashtable.c
+ *
+ * Hashtable Object Functions
+ *
+ */
+
+#include "pkix_pl_hashtable.h"
+
+/* --Private-Structure-------------------------------------------- */
+
+struct PKIX_PL_HashTableStruct {
+ pkix_pl_PrimHashTable *primHash;
+ PKIX_PL_Mutex *tableLock;
+ PKIX_UInt32 maxEntriesPerBucket;
+};
+
+/* --Private-Functions-------------------------------------------- */
+
+#define PKIX_MUTEX_UNLOCK(mutex) \
+ do { \
+ if (mutex && lockedMutex == (PKIX_PL_Mutex *)(mutex)) { \
+ pkixTempResult = \
+ PKIX_PL_Mutex_Unlock((mutex), plContext); \
+ PORT_Assert(pkixTempResult == NULL); \
+ if (pkixTempResult) { \
+ PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \
+ pkixTempResult = NULL; \
+ } \
+ lockedMutex = NULL; \
+ } else { \
+ PORT_Assert(lockedMutex == NULL); \
+ }\
+ } while (0)
+
+
+#define PKIX_MUTEX_LOCK(mutex) \
+ do { \
+ if (mutex){ \
+ PORT_Assert(lockedMutex == NULL); \
+ PKIX_CHECK(PKIX_PL_Mutex_Lock((mutex), plContext), \
+ PKIX_MUTEXLOCKFAILED); \
+ lockedMutex = (mutex); \
+ } \
+ } while (0)
+
+/*
+ * FUNCTION: pkix_pl_HashTable_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_HashTable_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_HashTable *ht = NULL;
+ pkix_pl_HT_Elem *item = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_HashTable_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_HASHTABLE_TYPE, plContext),
+ PKIX_OBJECTNOTHASHTABLE);
+
+ ht = (PKIX_PL_HashTable*) object;
+
+ /* DecRef every object in the primitive hash table */
+ for (i = 0; i < ht->primHash->size; i++) {
+ for (item = ht->primHash->buckets[i];
+ item != NULL;
+ item = item->next) {
+ PKIX_DECREF(item->key);
+ PKIX_DECREF(item->value);
+ }
+ }
+
+ PKIX_CHECK(pkix_pl_PrimHashTable_Destroy(ht->primHash, plContext),
+ PKIX_PRIMHASHTABLEDESTROYFAILED);
+
+ PKIX_DECREF(ht->tableLock);
+
+cleanup:
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: pkix_pl_HashTable_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_HASHTABLE_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_HashTable_RegisterSelf(
+ void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_HashTable_RegisterSelf");
+
+ entry.description = "HashTable";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_HashTable);
+ entry.destructor = pkix_pl_HashTable_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_HASHTABLE_TYPE] = entry;
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_HashTable_Create (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_HashTable_Create(
+ PKIX_UInt32 numBuckets,
+ PKIX_UInt32 maxEntriesPerBucket,
+ PKIX_PL_HashTable **pResult,
+ void *plContext)
+{
+ PKIX_PL_HashTable *hashTable = NULL;
+
+ PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Create");
+ PKIX_NULLCHECK_ONE(pResult);
+
+ if (numBuckets == 0) {
+ PKIX_ERROR(PKIX_NUMBUCKETSEQUALSZERO);
+ }
+
+ /* Allocate a new hashtable */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_HASHTABLE_TYPE,
+ sizeof (PKIX_PL_HashTable),
+ (PKIX_PL_Object **)&hashTable,
+ plContext),
+ PKIX_COULDNOTCREATEHASHTABLEOBJECT);
+
+ /* Create the underlying primitive hash table type */
+ PKIX_CHECK(pkix_pl_PrimHashTable_Create
+ (numBuckets, &hashTable->primHash, plContext),
+ PKIX_PRIMHASHTABLECREATEFAILED);
+
+ /* Create a lock for this table */
+ PKIX_CHECK(PKIX_PL_Mutex_Create(&hashTable->tableLock, plContext),
+ PKIX_ERRORCREATINGTABLELOCK);
+
+ hashTable->maxEntriesPerBucket = maxEntriesPerBucket;
+
+ *pResult = hashTable;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(hashTable);
+ }
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: PKIX_PL_HashTable_Add (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_HashTable_Add(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_Object *key,
+ PKIX_PL_Object *value,
+ void *plContext)
+{
+ PKIX_PL_Mutex *lockedMutex = NULL;
+ PKIX_PL_Object *deletedKey = NULL;
+ PKIX_PL_Object *deletedValue = NULL;
+ PKIX_UInt32 hashCode;
+ PKIX_PL_EqualsCallback keyComp;
+ PKIX_UInt32 bucketSize = 0;
+
+ PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Add");
+
+#if !defined(PKIX_OBJECT_LEAK_TEST)
+ PKIX_NULLCHECK_THREE(ht, key, value);
+#else
+ PKIX_NULLCHECK_TWO(key, value);
+
+ if (ht == NULL) {
+ PKIX_RETURN(HASHTABLE);
+ }
+#endif
+ /* Insert into primitive hashtable */
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(pkix_pl_Object_RetrieveEqualsCallback
+ (key, &keyComp, plContext),
+ PKIX_OBJECTRETRIEVEEQUALSCALLBACKFAILED);
+
+ PKIX_MUTEX_LOCK(ht->tableLock);
+
+ PKIX_CHECK(pkix_pl_PrimHashTable_GetBucketSize
+ (ht->primHash,
+ hashCode,
+ &bucketSize,
+ plContext),
+ PKIX_PRIMHASHTABLEGETBUCKETSIZEFAILED);
+
+ if (ht->maxEntriesPerBucket != 0 &&
+ bucketSize >= ht->maxEntriesPerBucket) {
+ /* drop the last one in the bucket */
+ PKIX_CHECK(pkix_pl_PrimHashTable_RemoveFIFO
+ (ht->primHash,
+ hashCode,
+ (void **) &deletedKey,
+ (void **) &deletedValue,
+ plContext),
+ PKIX_PRIMHASHTABLEGETBUCKETSIZEFAILED);
+ PKIX_DECREF(deletedKey);
+ PKIX_DECREF(deletedValue);
+ }
+
+ PKIX_CHECK(pkix_pl_PrimHashTable_Add
+ (ht->primHash,
+ (void *)key,
+ (void *)value,
+ hashCode,
+ keyComp,
+ plContext),
+ PKIX_PRIMHASHTABLEADDFAILED);
+
+ PKIX_INCREF(key);
+ PKIX_INCREF(value);
+ PKIX_MUTEX_UNLOCK(ht->tableLock);
+
+ /*
+ * we don't call PKIX_PL_InvalidateCache here b/c we have
+ * not implemented toString or hashcode for this Object
+ */
+
+cleanup:
+
+ PKIX_MUTEX_UNLOCK(ht->tableLock);
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: PKIX_PL_HashTable_Remove (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_HashTable_Remove(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_Object *key,
+ void *plContext)
+{
+ PKIX_PL_Mutex *lockedMutex = NULL;
+ PKIX_PL_Object *origKey = NULL;
+ PKIX_PL_Object *value = NULL;
+ PKIX_UInt32 hashCode;
+ PKIX_PL_EqualsCallback keyComp;
+
+ PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Remove");
+
+#if !defined(PKIX_OBJECT_LEAK_TEST)
+ PKIX_NULLCHECK_TWO(ht, key);
+#else
+ PKIX_NULLCHECK_ONE(key);
+
+ if (ht == NULL) {
+ PKIX_RETURN(HASHTABLE);
+ }
+#endif
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(pkix_pl_Object_RetrieveEqualsCallback
+ (key, &keyComp, plContext),
+ PKIX_OBJECTRETRIEVEEQUALSCALLBACKFAILED);
+
+ PKIX_MUTEX_LOCK(ht->tableLock);
+
+ /* Remove from primitive hashtable */
+ PKIX_CHECK(pkix_pl_PrimHashTable_Remove
+ (ht->primHash,
+ (void *)key,
+ hashCode,
+ keyComp,
+ (void **)&origKey,
+ (void **)&value,
+ plContext),
+ PKIX_PRIMHASHTABLEREMOVEFAILED);
+
+ PKIX_MUTEX_UNLOCK(ht->tableLock);
+
+ PKIX_DECREF(origKey);
+ PKIX_DECREF(value);
+
+ /*
+ * we don't call PKIX_PL_InvalidateCache here b/c we have
+ * not implemented toString or hashcode for this Object
+ */
+
+cleanup:
+
+ PKIX_MUTEX_UNLOCK(ht->tableLock);
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: PKIX_PL_HashTable_Lookup (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_HashTable_Lookup(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_Object *key,
+ PKIX_PL_Object **pResult,
+ void *plContext)
+{
+ PKIX_PL_Mutex *lockedMutex = NULL;
+ PKIX_UInt32 hashCode;
+ PKIX_PL_EqualsCallback keyComp;
+ PKIX_PL_Object *result = NULL;
+
+ PKIX_ENTER(HASHTABLE, "PKIX_PL_HashTable_Lookup");
+
+#if !defined(PKIX_OBJECT_LEAK_TEST)
+ PKIX_NULLCHECK_THREE(ht, key, pResult);
+#else
+ PKIX_NULLCHECK_TWO(key, pResult);
+
+ if (ht == NULL) {
+ PKIX_RETURN(HASHTABLE);
+ }
+#endif
+
+ PKIX_CHECK(PKIX_PL_Object_Hashcode(key, &hashCode, plContext),
+ PKIX_OBJECTHASHCODEFAILED);
+
+ PKIX_CHECK(pkix_pl_Object_RetrieveEqualsCallback
+ (key, &keyComp, plContext),
+ PKIX_OBJECTRETRIEVEEQUALSCALLBACKFAILED);
+
+ PKIX_MUTEX_LOCK(ht->tableLock);
+
+ /* Lookup in primitive hashtable */
+ PKIX_CHECK(pkix_pl_PrimHashTable_Lookup
+ (ht->primHash,
+ (void *)key,
+ hashCode,
+ keyComp,
+ (void **)&result,
+ plContext),
+ PKIX_PRIMHASHTABLELOOKUPFAILED);
+
+ PKIX_INCREF(result);
+ PKIX_MUTEX_UNLOCK(ht->tableLock);
+
+ *pResult = result;
+
+cleanup:
+
+ PKIX_MUTEX_UNLOCK(ht->tableLock);
+
+ PKIX_RETURN(HASHTABLE);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h
new file mode 100644
index 0000000000..479c623733
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_hashtable.h
@@ -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_pl_hashtable.h
+ *
+ * Hashtable Object Definition
+ *
+ */
+
+#ifndef _PKIX_PL_HASHTABLE_H
+#define _PKIX_PL_HASHTABLE_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_HashTable_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_HASHTABLE_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c
new file mode 100644
index 0000000000..70ed25d729
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.c
@@ -0,0 +1,279 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_lifecycle.c
+ *
+ * Lifecycle Functions for the PKIX PL library.
+ *
+ */
+
+#include "pkix_pl_lifecycle.h"
+
+PKIX_Boolean pkix_pl_initialized = PKIX_FALSE;
+pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+PRLock *classTableLock;
+PRLogModuleInfo *pkixLog = NULL;
+
+/*
+ * PKIX_ALLOC_ERROR is a special error object hard-coded into the
+ * pkix_error.o object file. It is thrown if system memory cannot be
+ * allocated. PKIX_ALLOC_ERROR is immutable.
+ * IncRef, DecRef, and Settor functions cannot be called.
+ */
+
+/* Keep this structure definition here for its is used only once here */
+struct PKIX_Alloc_Error_ObjectStruct {
+ PKIX_PL_Object header;
+ PKIX_Error error;
+};
+typedef struct PKIX_Alloc_Error_ObjectStruct PKIX_Alloc_Error_Object;
+
+static const PKIX_Alloc_Error_Object pkix_Alloc_Error_Data = {
+ {
+ PKIX_MAGIC_HEADER, /* PRUint64 magicHeader */
+ (PKIX_UInt32)PKIX_ERROR_TYPE, /* PKIX_UInt32 type */
+ (PKIX_UInt32)1, /* PKIX_UInt32 references */
+ /* Warning! Cannot Ref Count with NULL lock */
+ (void *)0, /* PRLock *lock */
+ (PKIX_PL_String *)0, /* PKIX_PL_String *stringRep */
+ (PKIX_UInt32)0, /* PKIX_UInt32 hashcode */
+ (PKIX_Boolean)PKIX_FALSE, /* PKIX_Boolean hashcodeCached */
+ }, {
+ (PKIX_ERRORCODE)0, /* PKIX_ERRORCODE errCode; */
+ (PKIX_ERRORCLASS)PKIX_FATAL_ERROR,/* PKIX_ERRORCLASS errClass */
+ (PKIX_UInt32)SEC_ERROR_LIBPKIX_INTERNAL, /* default PL Error Code */
+ (PKIX_Error *)0, /* PKIX_Error *cause */
+ (PKIX_PL_Object *)0, /* PKIX_PL_Object *info */
+ }
+};
+
+PKIX_Error* PKIX_ALLOC_ERROR(void)
+{
+ return (PKIX_Error *)&pkix_Alloc_Error_Data.error;
+}
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+SECStatus
+pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable)
+{
+ int typeCounter = 0;
+
+ for (; typeCounter < PKIX_NUMTYPES; typeCounter++) {
+ pkix_ClassTable_Entry *entry = &systemClasses[typeCounter];
+
+ objCountTable[typeCounter] = entry->objCounter;
+ }
+
+ return SECSuccess;
+}
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+
+PKIX_UInt32
+pkix_pl_lifecycle_ObjectLeakCheck(int *initObjCountTable)
+{
+ unsigned int typeCounter = 0;
+ PKIX_UInt32 numObjects = 0;
+ char classNameBuff[128];
+ char *className = NULL;
+
+ for (; typeCounter < PKIX_NUMTYPES; typeCounter++) {
+ pkix_ClassTable_Entry *entry = &systemClasses[typeCounter];
+ PKIX_UInt32 objCountDiff = entry->objCounter;
+
+ if (initObjCountTable) {
+ PKIX_UInt32 initialCount = initObjCountTable[typeCounter];
+ objCountDiff = (entry->objCounter > initialCount) ?
+ entry->objCounter - initialCount : 0;
+ }
+
+ numObjects += objCountDiff;
+
+ if (!pkixLog || !objCountDiff) {
+ continue;
+ }
+ className = entry->description;
+ if (!className) {
+ className = classNameBuff;
+ PR_snprintf(className, 128, "Unknown(ref %d)",
+ entry->objCounter);
+ }
+
+ PR_LOG(pkixLog, 1, ("Class %s leaked %d objects of "
+ "size %d bytes, total = %d bytes\n", className,
+ objCountDiff, entry->typeObjectSize,
+ objCountDiff * entry->typeObjectSize));
+ }
+
+ return numObjects;
+}
+
+/*
+ * PKIX_PL_Initialize (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Initialize(
+ PKIX_Boolean platformInitNeeded,
+ PKIX_Boolean useArenas,
+ void **pPlContext)
+{
+ void *plContext = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Initialize");
+
+ /*
+ * This function can only be called once. If it has already been
+ * called, we return a positive status.
+ */
+ if (pkix_pl_initialized) {
+ PKIX_RETURN(OBJECT);
+ }
+
+ classTableLock = PR_NewLock();
+ if (classTableLock == NULL) {
+ return PKIX_ALLOC_ERROR();
+ }
+
+ if (PR_GetEnvSecure("NSS_STRICT_SHUTDOWN")) {
+ pkixLog = PR_NewLogModule("pkix");
+ }
+ /*
+ * Register Object, it is the base object of all other objects.
+ */
+ pkix_pl_Object_RegisterSelf(plContext);
+
+ /*
+ * Register Error and String, since they will be needed if
+ * there is a problem in registering any other type.
+ */
+ pkix_Error_RegisterSelf(plContext);
+ pkix_pl_String_RegisterSelf(plContext);
+
+
+ /*
+ * We register all other system types
+ * (They don't need to be in order, but it's
+ * easier to keep track of what types are registered
+ * if we register them in the same order as their
+ * numbers, defined in pkixt.h.
+ */
+ pkix_pl_BigInt_RegisterSelf(plContext); /* 1-10 */
+ pkix_pl_ByteArray_RegisterSelf(plContext);
+ pkix_pl_HashTable_RegisterSelf(plContext);
+ pkix_List_RegisterSelf(plContext);
+ pkix_Logger_RegisterSelf(plContext);
+ pkix_pl_Mutex_RegisterSelf(plContext);
+ pkix_pl_OID_RegisterSelf(plContext);
+ pkix_pl_RWLock_RegisterSelf(plContext);
+
+ pkix_pl_CertBasicConstraints_RegisterSelf(plContext); /* 11-20 */
+ pkix_pl_Cert_RegisterSelf(plContext);
+ pkix_pl_CRL_RegisterSelf(plContext);
+ pkix_pl_CRLEntry_RegisterSelf(plContext);
+ pkix_pl_Date_RegisterSelf(plContext);
+ pkix_pl_GeneralName_RegisterSelf(plContext);
+ pkix_pl_CertNameConstraints_RegisterSelf(plContext);
+ pkix_pl_PublicKey_RegisterSelf(plContext);
+ pkix_TrustAnchor_RegisterSelf(plContext);
+
+ pkix_pl_X500Name_RegisterSelf(plContext); /* 21-30 */
+ pkix_pl_HttpCertStoreContext_RegisterSelf(plContext);
+ pkix_BuildResult_RegisterSelf(plContext);
+ pkix_ProcessingParams_RegisterSelf(plContext);
+ pkix_ValidateParams_RegisterSelf(plContext);
+ pkix_ValidateResult_RegisterSelf(plContext);
+ pkix_CertStore_RegisterSelf(plContext);
+ pkix_CertChainChecker_RegisterSelf(plContext);
+ pkix_RevocationChecker_RegisterSelf(plContext);
+ pkix_CertSelector_RegisterSelf(plContext);
+
+ pkix_ComCertSelParams_RegisterSelf(plContext); /* 31-40 */
+ pkix_CRLSelector_RegisterSelf(plContext);
+ pkix_ComCRLSelParams_RegisterSelf(plContext);
+ pkix_pl_CertPolicyInfo_RegisterSelf(plContext);
+ pkix_pl_CertPolicyQualifier_RegisterSelf(plContext);
+ pkix_pl_CertPolicyMap_RegisterSelf(plContext);
+ pkix_PolicyNode_RegisterSelf(plContext);
+ pkix_TargetCertCheckerState_RegisterSelf(plContext);
+ pkix_BasicConstraintsCheckerState_RegisterSelf(plContext);
+ pkix_PolicyCheckerState_RegisterSelf(plContext);
+
+ pkix_pl_CollectionCertStoreContext_RegisterSelf(plContext); /* 41-50 */
+ pkix_CrlChecker_RegisterSelf(plContext);
+ pkix_ForwardBuilderState_RegisterSelf(plContext);
+ pkix_SignatureCheckerState_RegisterSelf(plContext);
+ pkix_NameConstraintsCheckerState_RegisterSelf(plContext);
+#ifndef NSS_PKIX_NO_LDAP
+ pkix_pl_LdapRequest_RegisterSelf(plContext);
+ pkix_pl_LdapResponse_RegisterSelf(plContext);
+ pkix_pl_LdapDefaultClient_RegisterSelf(plContext);
+#endif
+ pkix_pl_Socket_RegisterSelf(plContext);
+
+ pkix_ResourceLimits_RegisterSelf(plContext); /* 51-59 */
+ pkix_pl_MonitorLock_RegisterSelf(plContext);
+ pkix_pl_InfoAccess_RegisterSelf(plContext);
+ pkix_pl_AIAMgr_RegisterSelf(plContext);
+ pkix_OcspChecker_RegisterSelf(plContext);
+ pkix_pl_OcspCertID_RegisterSelf(plContext);
+ pkix_pl_OcspRequest_RegisterSelf(plContext);
+ pkix_pl_OcspResponse_RegisterSelf(plContext);
+ pkix_pl_HttpDefaultClient_RegisterSelf(plContext);
+ pkix_VerifyNode_RegisterSelf(plContext);
+ pkix_EkuChecker_RegisterSelf(plContext);
+ pkix_pl_CrlDp_RegisterSelf(plContext);
+
+ if (pPlContext) {
+ PKIX_CHECK(PKIX_PL_NssContext_Create
+ (0, useArenas, NULL, &plContext),
+ PKIX_NSSCONTEXTCREATEFAILED);
+
+ *pPlContext = plContext;
+ }
+
+ pkix_pl_initialized = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * PKIX_PL_Shutdown (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Shutdown(void *plContext)
+{
+#ifdef DEBUG
+ PKIX_UInt32 numLeakedObjects = 0;
+#endif
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Shutdown");
+
+ if (!pkix_pl_initialized) {
+ /* The library was not initilized */
+ PKIX_RETURN(OBJECT);
+ }
+
+ PR_DestroyLock(classTableLock);
+
+ pkix_pl_HttpCertStore_Shutdown(plContext);
+
+#ifdef DEBUG
+ numLeakedObjects = pkix_pl_lifecycle_ObjectLeakCheck(NULL);
+ if (PR_GetEnvSecure("NSS_STRICT_SHUTDOWN")) {
+ PORT_Assert(numLeakedObjects == 0);
+ }
+#else
+ pkix_pl_lifecycle_ObjectLeakCheck(NULL);
+#endif
+
+ if (plContext != NULL) {
+ PKIX_PL_NssContext_Destroy(plContext);
+ }
+
+ pkix_pl_initialized = PKIX_FALSE;
+
+ PKIX_RETURN(OBJECT);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h
new file mode 100644
index 0000000000..9660af123d
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_lifecycle.h
@@ -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/. */
+/*
+ * pkix_pl_lifecycle.h
+ *
+ * Lifecycle Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_LIFECYCLE_H
+#define _PKIX_PL_LIFECYCLE_H
+
+#include "pkix_pl_common.h"
+#include "pkix_pl_oid.h"
+#include "pkix_pl_aiamgr.h"
+#include "pkix_pl_bigint.h"
+#include "pkix_pl_bytearray.h"
+#include "pkix_pl_hashtable.h"
+#include "pkix_pl_mutex.h"
+#include "pkix_pl_rwlock.h"
+#include "pkix_pl_monitorlock.h"
+#include "pkix_pl_string.h"
+#include "pkix_pl_cert.h"
+#include "pkix_pl_x500name.h"
+#include "pkix_pl_generalname.h"
+#include "pkix_pl_publickey.h"
+#include "pkix_pl_date.h"
+#include "pkix_pl_basicconstraints.h"
+#include "pkix_pl_certpolicyinfo.h"
+#include "pkix_pl_certpolicymap.h"
+#include "pkix_pl_certpolicyqualifier.h"
+#include "pkix_pl_crlentry.h"
+#include "pkix_pl_crl.h"
+#include "pkix_pl_colcertstore.h"
+#ifndef NSS_PKIX_NO_LDAP
+#include "pkix_pl_ldapcertstore.h"
+#include "pkix_pl_ldapdefaultclient.h"
+#include "pkix_pl_ldaprequest.h"
+#include "pkix_pl_ldapresponse.h"
+#endif /* !NSS_PKIX_NO_LDAP */
+#include "pkix_pl_socket.h"
+#include "pkix_pl_infoaccess.h"
+#include "pkix_store.h"
+#include "pkix_error.h"
+#include "pkix_logger.h"
+#include "pkix_list.h"
+#include "pkix_trustanchor.h"
+#include "pkix_procparams.h"
+#include "pkix_valparams.h"
+#include "pkix_valresult.h"
+#include "pkix_verifynode.h"
+#include "pkix_resourcelimits.h"
+#include "pkix_certchainchecker.h"
+#include "pkix_revocationchecker.h"
+#include "pkix_certselector.h"
+#include "pkix_comcertselparams.h"
+#include "pkix_crlselector.h"
+#include "pkix_comcrlselparams.h"
+#include "pkix_targetcertchecker.h"
+#include "pkix_basicconstraintschecker.h"
+#include "pkix_policynode.h"
+#include "pkix_policychecker.h"
+#include "pkix_crlchecker.h"
+#include "pkix_signaturechecker.h"
+#include "pkix_buildresult.h"
+#include "pkix_build.h"
+#include "pkix_pl_nameconstraints.h"
+#include "pkix_nameconstraintschecker.h"
+#include "pkix_ocspchecker.h"
+#include "pkix_pl_ocspcertid.h"
+#include "pkix_pl_ocsprequest.h"
+#include "pkix_pl_ocspresponse.h"
+#include "pkix_pl_httpdefaultclient.h"
+#include "pkix_pl_httpcertstore.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_InitializeParamsStruct {
+ PKIX_List *loggers;
+ PKIX_UInt32 majorVersion;
+ PKIX_UInt32 minorVersion;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_LIFECYCLE_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.c
new file mode 100644
index 0000000000..d75c0be26e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.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/. */
+/*
+ * pkix_pl_mem.c
+ *
+ * Memory Management Functions
+ *
+ */
+
+#include "pkix_pl_mem.h"
+
+/*
+ * FUNCTION: PKIX_PL_Malloc (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Malloc(
+ PKIX_UInt32 size,
+ void **pMemory,
+ void *plContext)
+{
+ PKIX_PL_NssContext *nssContext = NULL;
+ void *result = NULL;
+
+ PKIX_ENTER(MEM, "PKIX_PL_Malloc");
+ PKIX_NULLCHECK_ONE(pMemory);
+
+ if (size == 0){
+ *pMemory = NULL;
+ } else {
+
+ nssContext = (PKIX_PL_NssContext *)plContext;
+
+ if (nssContext != NULL && nssContext->arena != NULL) {
+ PKIX_MEM_DEBUG("\tCalling PORT_ArenaAlloc.\n");
+ *pMemory = PORT_ArenaAlloc(nssContext->arena, size);
+ } else {
+ PKIX_MEM_DEBUG("\tCalling PR_Malloc.\n");
+ result = (void *) PR_Malloc(size);
+
+ if (result == NULL) {
+ PKIX_MEM_DEBUG("Fatal Error Occurred: "
+ "PR_Malloc failed.\n");
+ PKIX_ERROR_ALLOC_ERROR();
+ } else {
+ *pMemory = result;
+ }
+ }
+ }
+
+cleanup:
+ PKIX_RETURN(MEM);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Calloc (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Calloc(
+ PKIX_UInt32 nElem,
+ PKIX_UInt32 elSize,
+ void **pMemory,
+ void *plContext)
+{
+ PKIX_PL_NssContext *nssContext = NULL;
+ void *result = NULL;
+
+ PKIX_ENTER(MEM, "PKIX_PL_Calloc");
+ PKIX_NULLCHECK_ONE(pMemory);
+
+ if ((nElem == 0) || (elSize == 0)){
+ *pMemory = NULL;
+ } else {
+
+ nssContext = (PKIX_PL_NssContext *)plContext;
+
+ if (nssContext != NULL && nssContext->arena != NULL) {
+ PKIX_MEM_DEBUG("\tCalling PORT_ArenaAlloc.\n");
+ *pMemory = PORT_ArenaAlloc(nssContext->arena, elSize);
+ } else {
+ PKIX_MEM_DEBUG("\tCalling PR_Calloc.\n");
+ result = (void *) PR_Calloc(nElem, elSize);
+
+ if (result == NULL) {
+ PKIX_MEM_DEBUG("Fatal Error Occurred: "
+ "PR_Calloc failed.\n");
+ PKIX_ERROR_ALLOC_ERROR();
+ } else {
+ *pMemory = result;
+ }
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(MEM);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Realloc (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Realloc(
+ void *ptr,
+ PKIX_UInt32 size,
+ void **pMemory,
+ void *plContext)
+{
+ PKIX_PL_NssContext *nssContext = NULL;
+ void *result = NULL;
+
+ PKIX_ENTER(MEM, "PKIX_PL_Realloc");
+ PKIX_NULLCHECK_ONE(pMemory);
+
+ nssContext = (PKIX_PL_NssContext *)plContext;
+
+ if (nssContext != NULL && nssContext->arena != NULL) {
+ PKIX_MEM_DEBUG("\tCalling PORT_ArenaAlloc.\n");
+ result = PORT_ArenaAlloc(nssContext->arena, size);
+
+ if (result){
+ PKIX_MEM_DEBUG("\tCalling PORT_Memcpy.\n");
+ PORT_Memcpy(result, ptr, size);
+ }
+ *pMemory = result;
+ } else {
+ PKIX_MEM_DEBUG("\tCalling PR_Realloc.\n");
+ result = (void *) PR_Realloc(ptr, size);
+
+ if (result == NULL) {
+ if (size == 0){
+ *pMemory = NULL;
+ } else {
+ PKIX_MEM_DEBUG
+ ("Fatal Error Occurred: "
+ "PR_Realloc failed.\n");
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+ } else {
+ *pMemory = result;
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(MEM);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Free (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Free(
+ void *ptr,
+ /* ARGSUSED */ void *plContext)
+{
+ PKIX_PL_NssContext *context = NULL;
+
+ PKIX_ENTER(MEM, "PKIX_PL_Free");
+
+ context = (PKIX_PL_NssContext *) plContext;
+ if (context == NULL || context->arena == NULL) {
+ PKIX_MEM_DEBUG("\tCalling PR_Free.\n");
+ (void) PR_Free(ptr);
+ }
+
+ PKIX_RETURN(MEM);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h
new file mode 100644
index 0000000000..eaec6246c9
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mem.h
@@ -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_pl_mem.h
+ *
+ * Memory Management Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_MEM_H
+#define _PKIX_PL_MEM_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_MEM_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.c
new file mode 100644
index 0000000000..a5d2fc9621
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.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/. */
+/*
+ * pkix_pl_monitorlock.c
+ *
+ * Read/Write Lock Functions
+ *
+ */
+
+#include "pkix_pl_monitorlock.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+static PKIX_Error *
+pkix_pl_MonitorLock_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_MonitorLock* monitorLock = NULL;
+
+ PKIX_ENTER(MONITORLOCK, "pkix_pl_MonitorLock_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_MONITORLOCK_TYPE, plContext),
+ PKIX_OBJECTNOTMONITORLOCK);
+
+ monitorLock = (PKIX_PL_MonitorLock*) object;
+
+ PKIX_MONITORLOCK_DEBUG("Calling PR_DestroyMonitor)\n");
+ PR_DestroyMonitor(monitorLock->lock);
+ monitorLock->lock = NULL;
+
+cleanup:
+
+ PKIX_RETURN(MONITORLOCK);
+}
+
+/*
+ * FUNCTION: pkix_pl_MonitorLock_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_MONITORLOCK_TYPE and its related functions with
+ * systemClasses[].
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_MonitorLock_RegisterSelf(
+ void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(MONITORLOCK, "pkix_pl_MonitorLock_RegisterSelf");
+
+ entry.description = "MonitorLock";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_MonitorLock);
+ entry.destructor = pkix_pl_MonitorLock_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_MONITORLOCK_TYPE] = entry;
+
+ PKIX_RETURN(MONITORLOCK);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+PKIX_Error *
+PKIX_PL_MonitorLock_Create(
+ PKIX_PL_MonitorLock **pNewLock,
+ void *plContext)
+{
+ PKIX_PL_MonitorLock *monitorLock = NULL;
+
+ PKIX_ENTER(MONITORLOCK, "PKIX_PL_MonitorLock_Create");
+ PKIX_NULLCHECK_ONE(pNewLock);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_MONITORLOCK_TYPE,
+ sizeof (PKIX_PL_MonitorLock),
+ (PKIX_PL_Object **)&monitorLock,
+ plContext),
+ PKIX_ERRORALLOCATINGMONITORLOCK);
+
+ PKIX_MONITORLOCK_DEBUG("\tCalling PR_NewMonitor)\n");
+ monitorLock->lock = PR_NewMonitor();
+
+ if (monitorLock->lock == NULL) {
+ PKIX_DECREF(monitorLock);
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ *pNewLock = monitorLock;
+
+cleanup:
+
+ PKIX_RETURN(MONITORLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_MonitorLock_Enter(
+ PKIX_PL_MonitorLock *monitorLock,
+ void *plContext)
+{
+ PKIX_ENTER_NO_LOGGER(MONITORLOCK, "PKIX_PL_MonitorLock_Enter");
+ PKIX_NULLCHECK_ONE(monitorLock);
+
+ PKIX_MONITORLOCK_DEBUG("\tCalling PR_EnterMonitor)\n");
+ (void) PR_EnterMonitor(monitorLock->lock);
+
+ PKIX_RETURN_NO_LOGGER(MONITORLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_MonitorLock_Exit(
+ PKIX_PL_MonitorLock *monitorLock,
+ void *plContext)
+{
+ PKIX_ENTER_NO_LOGGER(MONITORLOCK, "PKIX_PL_MonitorLock_Exit");
+ PKIX_NULLCHECK_ONE(monitorLock);
+
+ PKIX_MONITORLOCK_DEBUG("\tCalling PR_ExitMonitor)\n");
+ PR_ExitMonitor(monitorLock->lock);
+
+ PKIX_RETURN_NO_LOGGER(MONITORLOCK);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.h
new file mode 100644
index 0000000000..76ac539ad8
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_monitorlock.h
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_monitorlock.h
+ *
+ * Read/Write Lock Definition
+ *
+ */
+
+#ifndef _PKIX_PL_MONITORLOCK_H
+#define _PKIX_PL_MONITORLOCK_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_MonitorLockStruct {
+ PRMonitor* lock;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_MonitorLock_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_MONITORLOCK_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.c
new file mode 100644
index 0000000000..07d13695b5
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.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/. */
+/*
+ * pkix_pl_mutex.c
+ *
+ * Mutual Exclusion (Lock) Object Functions
+ *
+ */
+
+#include "pkix_pl_mutex.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_Mutex_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_Mutex_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Mutex *mutex = NULL;
+
+ PKIX_ENTER(MUTEX, "pkix_pl_Mutex_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Sanity check: Test that "object" is a mutex */
+ PKIX_CHECK(pkix_CheckType(object, PKIX_MUTEX_TYPE, plContext),
+ PKIX_OBJECTNOTMUTEX);
+
+ mutex = (PKIX_PL_Mutex*) object;
+
+ PKIX_MUTEX_DEBUG("\tCalling PR_DestroyLock).\n");
+ PR_DestroyLock(mutex->lock);
+ mutex->lock = NULL;
+
+cleanup:
+
+ PKIX_RETURN(MUTEX);
+}
+
+/*
+ * FUNCTION: pkix_pl_Mutex_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_MUTEX_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_Mutex_RegisterSelf(
+ /* ARGSUSED */ void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(MUTEX, "pkix_pl_Mutex_RegisterSelf");
+
+ entry.description = "Mutex";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_Mutex);
+ entry.destructor = pkix_pl_Mutex_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_MUTEX_TYPE] = entry;
+
+ PKIX_RETURN(MUTEX);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_Mutex_Create (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Mutex_Create(
+ PKIX_PL_Mutex **pNewLock,
+ void *plContext)
+{
+ PKIX_PL_Mutex *mutex = NULL;
+
+ PKIX_ENTER(MUTEX, "PKIX_PL_Mutex_Create");
+ PKIX_NULLCHECK_ONE(pNewLock);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_MUTEX_TYPE,
+ sizeof (PKIX_PL_Mutex),
+ (PKIX_PL_Object **)&mutex,
+ plContext),
+ PKIX_COULDNOTCREATELOCKOBJECT);
+
+ PKIX_MUTEX_DEBUG("\tCalling PR_NewLock).\n");
+ mutex->lock = PR_NewLock();
+
+ /* If an error occurred in NSPR, report it here */
+ if (mutex->lock == NULL) {
+ PKIX_DECREF(mutex);
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+
+ *pNewLock = mutex;
+
+cleanup:
+
+ PKIX_RETURN(MUTEX);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Mutex_Lock (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Mutex_Lock(
+ PKIX_PL_Mutex *mutex,
+ void *plContext)
+{
+ PKIX_ENTER(MUTEX, "PKIX_PL_Mutex_Lock");
+ PKIX_NULLCHECK_ONE(mutex);
+
+ PKIX_MUTEX_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(mutex->lock);
+
+ PKIX_MUTEX_DEBUG_ARG("(Thread %u just acquired the lock)\n",
+ (PKIX_UInt32)PR_GetCurrentThread());
+
+ PKIX_RETURN(MUTEX);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Mutex_Unlock (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Mutex_Unlock(
+ PKIX_PL_Mutex *mutex,
+ void *plContext)
+{
+ PRStatus result;
+
+ PKIX_ENTER(MUTEX, "PKIX_PL_Mutex_Unlock");
+ PKIX_NULLCHECK_ONE(mutex);
+
+ PKIX_MUTEX_DEBUG("\tCalling PR_Unlock).\n");
+ result = PR_Unlock(mutex->lock);
+
+ PKIX_MUTEX_DEBUG_ARG("(Thread %u just released the lock)\n",
+ (PKIX_UInt32)PR_GetCurrentThread());
+
+ if (result == PR_FAILURE) {
+ PKIX_ERROR_FATAL(PKIX_ERRORUNLOCKINGMUTEX);
+ }
+
+cleanup:
+ PKIX_RETURN(MUTEX);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.h
new file mode 100644
index 0000000000..baf16fea92
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_mutex.h
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_mutex.h
+ *
+ * Mutual Exclusion (Lock) Object Type Definition
+ *
+ */
+
+#ifndef _PKIX_PL_MUTEX_H
+#define _PKIX_PL_MUTEX_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_MutexStruct {
+ PRLock* lock;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_Mutex_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_MUTEX_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c
new file mode 100644
index 0000000000..7dafa0b204
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.c
@@ -0,0 +1,1440 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_object.c
+ *
+ * Object Construction, Destruction and Callback Functions
+ *
+ */
+
+#include "pkix_pl_object.h"
+
+#ifdef PKIX_USER_OBJECT_TYPE
+/* --Class-Table-Initializers------------------------------------ */
+
+/*
+ * Create storage space for 20 Class Table buckets.
+ * These are only for user-defined types. System types are registered
+ * separately by PKIX_PL_Initialize.
+ */
+
+static pkix_pl_HT_Elem*
+pkix_Raw_ClassTable_Buckets[] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+/*
+ * Allocate static memory for a ClassTable.
+ * XXX This assumes the bucket pointer will fit into a PKIX_UInt32
+ */
+static pkix_pl_PrimHashTable pkix_Raw_ClassTable = {
+ (void *)pkix_Raw_ClassTable_Buckets, /* Buckets */
+ 20 /* Number of Buckets */
+};
+static pkix_pl_PrimHashTable * classTable = &pkix_Raw_ClassTable;
+#endif /* PKIX_USER_OBJECT_TYPE */
+
+/* --Private-Functions-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_Object_GetHeader
+ * DESCRIPTION:
+ *
+ * Shifts Object pointed to by "object" by the sizeof(PKIX_PL_Object) and
+ * stores the value at "pObjectHeader".
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object to shift. Must be non-NULL.
+ * "pObjectHeader"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Object_GetHeader(
+ PKIX_PL_Object *object,
+ PKIX_PL_Object **pObjectHeader,
+ void *plContext)
+{
+ PKIX_PL_Object *header = NULL;
+ PKIX_UInt32 objType;
+
+ PKIX_ENTER(OBJECT, "pkix_pl_Object_GetHeader");
+ PKIX_NULLCHECK_TWO(object, pObjectHeader);
+
+ PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
+
+ /* The header is sizeof(PKIX_PL_Object) before the object pointer */
+ header = (PKIX_PL_Object *)((char *)object - sizeof(PKIX_PL_Object));
+
+ objType = header->type;
+
+ if (objType >= PKIX_NUMTYPES) { /* if this is a user-defined type */
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+
+ PKIX_CHECK(pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext),
+ PKIX_ERRORGETTINGCLASSTABLEENTRY);
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+
+ if (ctEntry == NULL) {
+ PKIX_ERROR_FATAL(PKIX_UNKNOWNOBJECTTYPE);
+ }
+#else
+ PORT_Assert(objType < PKIX_NUMTYPES);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ }
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+ PORT_Assert(header && header->magicHeader == PKIX_MAGIC_HEADER);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+ if ((header == NULL)||
+ (header->magicHeader != PKIX_MAGIC_HEADER)) {
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+
+ *pObjectHeader = header;
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_Destroy_Object
+ * DESCRIPTION:
+ *
+ * Destroys and deallocates Object pointed to by "object". The caller is
+ * assumed to hold the Object's lock, which is acquired in
+ * PKIX_PL_Object_DecRef().
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object to destroy. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Object_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+
+ PKIX_ENTER(OBJECT, "pkix_pl_Object_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+ PKIX_CHECK_FATAL(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+#else
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+ /* Attempt to delete an object still being used */
+ if (objectHeader->references != 0) {
+ PKIX_ERROR_FATAL(PKIX_OBJECTSTILLREFERENCED);
+ }
+
+ PKIX_DECREF(objectHeader->stringRep);
+
+ /* Destroy this object's lock */
+ PKIX_OBJECT_DEBUG("\tCalling PR_DestroyLock).\n");
+ PR_DestroyLock(objectHeader->lock);
+ objectHeader->lock = NULL;
+ object = NULL;
+
+ objectHeader->magicHeader = PKIX_MAGIC_HEADER_DESTROYED;
+
+#ifdef PKIX_OBJECT_LEAK_TEST
+ memset(objectHeader, 0xbf, systemClasses[PKIX_OBJECT_TYPE].typeObjectSize);
+#endif
+
+ PKIX_FREE(objectHeader);
+
+cleanup:
+#ifdef PKIX_OBJECT_LEAK_TEST
+fatal:
+#endif
+
+ PKIX_RETURN(OBJECT);
+}
+
+/* --Default-Callbacks-------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_Object_Equals_Default
+ * DESCRIPTION:
+ *
+ * Default Object_Equals callback: Compares the address of the Object pointed
+ * to by "firstObject" with the address of the Object pointed to by
+ * "secondObject" and stores the Boolean result at "pResult".
+ *
+ * PARAMETERS:
+ * "firstObject"
+ * Address of first Object to compare. Must be non-NULL.
+ * "secondObject"
+ * Address of second Object to compare. Must be non-NULL.
+ * "pResult"
+ * Address where Boolean result will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Object_Equals_Default(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_ENTER(OBJECT, "pkix_pl_Object_Equals_Default");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* Just compare pointer values */
+ *pResult = (firstObject == secondObject)?PKIX_TRUE:PKIX_FALSE;
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Object_ToString_Default
+ * DESCRIPTION:
+ *
+ * Default Object_ToString callback: Creates a string consisting of the
+ * typename and address of the Object pointed to by "object" and stores
+ * the result at "pString". The format for the string is
+ * "TypeName@Address: <address>", where the default typename is "Object".
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object to convert to a string. Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Object_ToString_Default(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *descString = NULL;
+ char *format = "%s@Address: %x";
+ char *description = NULL;
+ PKIX_UInt32 objType;
+
+ PKIX_ENTER(OBJECT, "pkix_pl_Object_ToString_Default");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(PKIX_PL_Object_GetType(object, &objType, plContext),
+ PKIX_OBJECTGETTYPEFAILED);
+
+ if (objType >= PKIX_NUMTYPES){
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if (ctEntry == NULL){
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDCLASSTABLEENTRY);
+ } else {
+ description = ctEntry->description;
+ if (description == NULL) {
+ description = "User Type Object";
+ }
+ }
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ description = systemClasses[objType].description;
+ }
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (void *)format,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ (void *)description,
+ 0,
+ &descString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (pString,
+ plContext,
+ formatString,
+ descString,
+ object),
+ PKIX_SPRINTFFAILED);
+
+cleanup:
+
+ PKIX_DECREF(formatString);
+ PKIX_DECREF(descString);
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Object_Hashcode_Default
+ * DESCRIPTION:
+ *
+ * Default Object_Hashcode callback. Creates the a hashcode value using the
+ * address of the Object pointed to by "object" and stores the result at
+ * "pValue".
+ *
+ * XXX This isn't great since addresses are not uniformly distributed.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object to compute hashcode for. Must be non-NULL.
+ * "pValue"
+ * Address where PKIX_UInt32 will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_Object_Hashcode_Default(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pValue,
+ void *plContext)
+{
+ PKIX_ENTER(OBJECT, "pkix_pl_Object_Hashcode_Default");
+ PKIX_NULLCHECK_TWO(object, pValue);
+
+ *pValue = (PKIX_UInt32)((char *)object - (char *)NULL);
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Object_RetrieveEqualsCallback
+ * DESCRIPTION:
+ *
+ * Retrieves Equals callback function of Object pointed to by "object and
+ * stores it at "pEqualsCallback". If the object's type is one of the system
+ * types, its callback function is retrieved from the systemClasses array;
+ * otherwise, its callback function is retrieve from the classTable hash
+ * table where user-defined types are stored.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object whose equals callback is desired. Must be non-NULL.
+ * "pEqualsCallback"
+ * Address where EqualsCallback function pointer will be stored.
+ * Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an Object Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_Object_RetrieveEqualsCallback(
+ PKIX_PL_Object *object,
+ PKIX_PL_EqualsCallback *pEqualsCallback,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+ PKIX_PL_EqualsCallback func = NULL;
+ pkix_ClassTable_Entry entry;
+ PKIX_UInt32 objType;
+
+ PKIX_ENTER(OBJECT, "pkix_pl_Object_RetrieveEqualsCallback");
+ PKIX_NULLCHECK_TWO(object, pEqualsCallback);
+
+ PKIX_CHECK(pkix_pl_Object_GetHeader
+ (object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ objType = objectHeader->type;
+
+ if (objType >= PKIX_NUMTYPES){
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+ if (pkixErrorResult){
+ PKIX_ERROR(PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) {
+ PKIX_ERROR(PKIX_UNDEFINEDEQUALSCALLBACK);
+ } else {
+ *pEqualsCallback = ctEntry->equalsFunction;
+ }
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ entry = systemClasses[objType];
+ func = entry.equalsFunction;
+ if (func == NULL){
+ func = pkix_pl_Object_Equals_Default;
+ }
+ *pEqualsCallback = func;
+ }
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: pkix_pl_Object_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_OBJECT_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ *
+ * PKIX_PL_Object should have all function pointes to be to NULL: they
+ * work as proxy function to a real objects.
+ *
+ */
+PKIX_Error *
+pkix_pl_Object_RegisterSelf(void *plContext)
+{
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(ERROR, "pkix_pl_Object_RegisterSelf");
+
+ entry.description = "Object";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_Object);
+ entry.destructor = NULL;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_OBJECT_TYPE] = entry;
+
+ PKIX_RETURN(ERROR);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_Object_Alloc (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Alloc(
+ PKIX_TYPENUM objType,
+ PKIX_UInt32 size,
+ PKIX_PL_Object **pObject,
+ void *plContext)
+{
+ PKIX_PL_Object *object = NULL;
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Alloc");
+ PKIX_NULLCHECK_ONE(pObject);
+
+ /*
+ * We need to ensure that user-defined types have been registered.
+ * All system types have already been registered by PKIX_PL_Initialize.
+ */
+
+ if (objType >= PKIX_NUMTYPES) { /* i.e. if this is a user-defined type */
+#ifdef PKIX_USER_OBJECT_TYPE
+ PKIX_Boolean typeRegistered;
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE);
+ }
+
+ typeRegistered = (ctEntry != NULL);
+
+ if (!typeRegistered) {
+ PKIX_ERROR_FATAL(PKIX_UNKNOWNTYPEARGUMENT);
+ }
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ ctEntry = &systemClasses[objType];
+ }
+
+ PORT_Assert(size == ctEntry->typeObjectSize);
+
+ /* Allocate space for the object header and the requested size */
+#ifdef PKIX_OBJECT_LEAK_TEST
+ PKIX_CHECK(PKIX_PL_Calloc
+ (1,
+ ((PKIX_UInt32)sizeof (PKIX_PL_Object))+size,
+ (void **)&object,
+ plContext),
+ PKIX_MALLOCFAILED);
+#else
+ PKIX_CHECK(PKIX_PL_Malloc
+ (((PKIX_UInt32)sizeof (PKIX_PL_Object))+size,
+ (void **)&object,
+ plContext),
+ PKIX_MALLOCFAILED);
+#endif /* PKIX_OBJECT_LEAK_TEST */
+
+ /* Initialize all object fields */
+ object->magicHeader = PKIX_MAGIC_HEADER;
+ object->type = objType;
+ object->references = 1; /* Default to a single reference */
+ object->stringRep = NULL;
+ object->hashcode = 0;
+ object->hashcodeCached = 0;
+
+ /* Cannot use PKIX_PL_Mutex because it depends on Object */
+ /* Using NSPR Locks instead */
+ PKIX_OBJECT_DEBUG("\tCalling PR_NewLock).\n");
+ object->lock = PR_NewLock();
+ if (object->lock == NULL) {
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+
+ PKIX_OBJECT_DEBUG("\tShifting object pointer).\n");
+
+
+ /* Return a pointer to the user data. Need to offset by object size */
+ *pObject = object + 1;
+ object = NULL;
+
+ /* Atomically increment object counter */
+ PR_ATOMIC_INCREMENT((PRInt32*)&ctEntry->objCounter);
+
+cleanup:
+
+ PKIX_FREE(object);
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_IsTypeRegistered (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_IsTypeRegistered(
+ PKIX_UInt32 objType,
+ PKIX_Boolean *pBool,
+ void *plContext)
+{
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+#endif
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_IsTypeRegistered");
+ PKIX_NULLCHECK_ONE(pBool);
+
+ /* first, we handle the system types */
+ if (objType < PKIX_NUMTYPES) {
+ *pBool = PKIX_TRUE;
+ goto cleanup;
+ }
+
+#ifndef PKIX_USER_OBJECT_TYPE
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+#else
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE);
+ }
+
+ *pBool = (ctEntry != NULL);
+#endif /* PKIX_USER_OBJECT_TYPE */
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+#ifdef PKIX_USER_OBJECT_TYPE
+/*
+ * FUNCTION: PKIX_PL_Object_RegisterType (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_RegisterType(
+ PKIX_UInt32 objType,
+ char *description,
+ PKIX_PL_DestructorCallback destructor,
+ PKIX_PL_EqualsCallback equalsFunction,
+ PKIX_PL_HashcodeCallback hashcodeFunction,
+ PKIX_PL_ToStringCallback toStringFunction,
+ PKIX_PL_ComparatorCallback comparator,
+ PKIX_PL_DuplicateCallback duplicateFunction,
+ void *plContext)
+{
+ pkix_ClassTable_Entry *ctEntry = NULL;
+ pkix_pl_Integer *key = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_RegisterType");
+
+ /*
+ * System types are registered on startup by PKIX_PL_Initialize.
+ * These can not be overwritten.
+ */
+
+ if (objType < PKIX_NUMTYPES) { /* if this is a system type */
+ PKIX_ERROR(PKIX_CANTREREGISTERSYSTEMTYPE);
+ }
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ PKIX_CHECK(pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext),
+ PKIX_PRIMHASHTABLELOOKUPFAILED);
+
+ /* If the type is already registered, throw an error */
+ if (ctEntry) {
+ PKIX_ERROR(PKIX_TYPEALREADYREGISTERED);
+ }
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (((PKIX_UInt32)sizeof (pkix_ClassTable_Entry)),
+ (void **)&ctEntry,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ /* Set Default Values if none specified */
+
+ if (description == NULL){
+ description = "Object";
+ }
+
+ if (equalsFunction == NULL) {
+ equalsFunction = pkix_pl_Object_Equals_Default;
+ }
+
+ if (toStringFunction == NULL) {
+ toStringFunction = pkix_pl_Object_ToString_Default;
+ }
+
+ if (hashcodeFunction == NULL) {
+ hashcodeFunction = pkix_pl_Object_Hashcode_Default;
+ }
+
+ ctEntry->destructor = destructor;
+ ctEntry->equalsFunction = equalsFunction;
+ ctEntry->toStringFunction = toStringFunction;
+ ctEntry->hashcodeFunction = hashcodeFunction;
+ ctEntry->comparator = comparator;
+ ctEntry->duplicateFunction = duplicateFunction;
+ ctEntry->description = description;
+
+ PKIX_CHECK(PKIX_PL_Malloc
+ (((PKIX_UInt32)sizeof (pkix_pl_Integer)),
+ (void **)&key,
+ plContext),
+ PKIX_COULDNOTMALLOCNEWKEY);
+
+ key->ht_int = objType;
+
+ PKIX_CHECK(pkix_pl_PrimHashTable_Add
+ (classTable,
+ (void *)key,
+ (void *)ctEntry,
+ objType,
+ NULL,
+ plContext),
+ PKIX_PRIMHASHTABLEADDFAILED);
+
+cleanup:
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+
+ PKIX_RETURN(OBJECT);
+}
+#endif /* PKIX_USER_OBJECT_TYPE */
+
+/*
+ * FUNCTION: PKIX_PL_Object_IncRef (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_IncRef(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+ PKIX_PL_NssContext *context = NULL;
+ PKIX_Int32 refCount = 0;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_IncRef");
+ PKIX_NULLCHECK_ONE(object);
+
+ if (plContext){
+ /*
+ * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't
+ * have a header therefore we cannot verify its type before
+ * casting.
+ */
+ context = (PKIX_PL_NssContext *) plContext;
+ if (context->arena != NULL) {
+ goto cleanup;
+ }
+ }
+
+ if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) {
+ goto cleanup;
+ }
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ /* This object should never have zero references */
+ refCount = PR_ATOMIC_INCREMENT(&objectHeader->references);
+
+ if (refCount <= 1) {
+ PKIX_THROW(FATAL, PKIX_OBJECTWITHNONPOSITIVEREFERENCES);
+ }
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_DecRef (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_DecRef(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_Int32 refCount = 0;
+ PKIX_PL_Object *objectHeader = NULL;
+ PKIX_PL_NssContext *context = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_DecRef");
+ PKIX_NULLCHECK_ONE(object);
+
+ if (plContext){
+ /*
+ * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't
+ * have a header therefore we cannot verify its type before
+ * casting.
+ */
+ context = (PKIX_PL_NssContext *) plContext;
+ if (context->arena != NULL) {
+ goto cleanup;
+ }
+ }
+
+ if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) {
+ goto cleanup;
+ }
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ refCount = PR_ATOMIC_DECREMENT(&objectHeader->references);
+
+ if (refCount == 0) {
+ PKIX_PL_DestructorCallback destructor = NULL;
+ pkix_ClassTable_Entry *ctEntry = NULL;
+ PKIX_UInt32 objType = objectHeader->type;
+
+ /* first, special handling for system types */
+ if (objType >= PKIX_NUMTYPES){
+#ifdef PKIX_USER_OBJECT_TYPE
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG
+ ("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL
+ (PKIX_ERRORINGETTINGDESTRUCTOR);
+ }
+
+ if (ctEntry != NULL){
+ destructor = ctEntry->destructor;
+ }
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ ctEntry = &systemClasses[objType];
+ destructor = ctEntry->destructor;
+ }
+
+ if (destructor != NULL){
+ /* Call destructor on user data if necessary */
+ pkixErrorResult = destructor(object, plContext);
+ if (pkixErrorResult) {
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ PKIX_DoAddError(stdVarsPtr, pkixErrorResult, plContext);
+ pkixErrorResult = NULL;
+ }
+ }
+
+ /* Atomically decrement object counter */
+ PR_ATOMIC_DECREMENT((PRInt32*)&ctEntry->objCounter);
+
+ /* pkix_pl_Object_Destroy assumes the lock is held */
+ /* It will call unlock and destroy the object */
+ pkixErrorResult = pkix_pl_Object_Destroy(object, plContext);
+ goto cleanup;
+ }
+
+ if (refCount < 0) {
+ PKIX_ERROR_ALLOC_ERROR();
+ }
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+
+
+/*
+ * FUNCTION: PKIX_PL_Object_Equals (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_Object *firstObjectHeader = NULL;
+ PKIX_PL_Object *secondObjectHeader = NULL;
+ PKIX_PL_EqualsCallback func = NULL;
+ pkix_ClassTable_Entry entry;
+ PKIX_UInt32 objType;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ PKIX_CHECK(pkix_pl_Object_GetHeader
+ (firstObject, &firstObjectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ PKIX_CHECK(pkix_pl_Object_GetHeader
+ (secondObject, &secondObjectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ /* if hashcodes are cached but not equal, objects can't be equal */
+ if (firstObjectHeader->hashcodeCached &&
+ secondObjectHeader->hashcodeCached){
+ if (firstObjectHeader->hashcode !=
+ secondObjectHeader->hashcode){
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+ }
+
+ objType = firstObjectHeader->type;
+
+ if (objType >= PKIX_NUMTYPES) {
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&firstObjectHeader->type,
+ firstObjectHeader->type,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) {
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
+ } else {
+ func = ctEntry->equalsFunction;
+ }
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ entry = systemClasses[objType];
+ func = entry.equalsFunction;
+ if (func == NULL){
+ func = pkix_pl_Object_Equals_Default;
+ }
+ }
+
+ PKIX_CHECK(func(firstObject, secondObject, pResult, plContext),
+ PKIX_OBJECTSPECIFICFUNCTIONFAILED);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_Duplicate (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Duplicate(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object **pNewObject,
+ void *plContext)
+{
+ PKIX_PL_Object *firstObjectHeader = NULL;
+ PKIX_PL_DuplicateCallback func = NULL;
+ pkix_ClassTable_Entry entry;
+ PKIX_UInt32 objType;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Duplicate");
+ PKIX_NULLCHECK_TWO(firstObject, pNewObject);
+
+ PKIX_CHECK(pkix_pl_Object_GetHeader
+ (firstObject, &firstObjectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ objType = firstObjectHeader->type;
+
+ if (objType >= PKIX_NUMTYPES) {
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if ((ctEntry == NULL) || (ctEntry->duplicateFunction == NULL)) {
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
+ } else {
+ func = ctEntry->duplicateFunction;
+ }
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ entry = systemClasses[objType];
+ func = entry.duplicateFunction;
+ if (!func){
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDDUPLICATEFUNCTION);
+ }
+ }
+
+ PKIX_CHECK(func(firstObject, pNewObject, plContext),
+ PKIX_OBJECTSPECIFICFUNCTIONFAILED);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_Hashcode (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pValue,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+ PKIX_PL_HashcodeCallback func = NULL;
+ pkix_ClassTable_Entry entry;
+ PKIX_UInt32 objectHash;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pValue);
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (!objectHeader->hashcodeCached){
+
+ PKIX_UInt32 objType = objectHeader->type;
+
+ /* first, special handling for system types */
+ if (objType >= PKIX_NUMTYPES){
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL
+ (PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if ((ctEntry == NULL) ||
+ (ctEntry->hashcodeFunction == NULL)) {
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
+ }
+
+ func = ctEntry->hashcodeFunction;
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ entry = systemClasses[objType];
+ func = entry.hashcodeFunction;
+ if (func == NULL){
+ func = pkix_pl_Object_Hashcode_Default;
+ }
+ }
+
+ PKIX_CHECK(func(object, &objectHash, plContext),
+ PKIX_OBJECTSPECIFICFUNCTIONFAILED);
+
+ if (!objectHeader->hashcodeCached){
+
+ PKIX_CHECK(pkix_LockObject(object, plContext),
+ PKIX_ERRORLOCKINGOBJECT);
+
+ if (!objectHeader->hashcodeCached){
+ /* save cached copy in case we need it again */
+ objectHeader->hashcode = objectHash;
+ objectHeader->hashcodeCached = PKIX_TRUE;
+ }
+
+ PKIX_CHECK(pkix_UnlockObject(object, plContext),
+ PKIX_ERRORUNLOCKINGOBJECT);
+ }
+ }
+
+ *pValue = objectHeader->hashcode;
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_ToString (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+ PKIX_PL_ToStringCallback func = NULL;
+ pkix_ClassTable_Entry entry;
+ PKIX_PL_String *objectString = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (!objectHeader->stringRep){
+
+ PKIX_UInt32 objType = objectHeader->type;
+
+ if (objType >= PKIX_NUMTYPES){
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL
+ (PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if ((ctEntry == NULL) ||
+ (ctEntry->toStringFunction == NULL)) {
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK);
+ }
+
+ func = ctEntry->toStringFunction;
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ entry = systemClasses[objType];
+ func = entry.toStringFunction;
+ if (func == NULL){
+ func = pkix_pl_Object_ToString_Default;
+ }
+ }
+
+ PKIX_CHECK(func(object, &objectString, plContext),
+ PKIX_OBJECTSPECIFICFUNCTIONFAILED);
+
+ if (!objectHeader->stringRep){
+
+ PKIX_CHECK(pkix_LockObject(object, plContext),
+ PKIX_ERRORLOCKINGOBJECT);
+
+ if (!objectHeader->stringRep){
+ /* save a cached copy */
+ objectHeader->stringRep = objectString;
+ objectString = NULL;
+ }
+
+ PKIX_CHECK(pkix_UnlockObject(object, plContext),
+ PKIX_ERRORUNLOCKINGOBJECT);
+ }
+ }
+
+
+ *pString = objectHeader->stringRep;
+ objectHeader->stringRep = NULL;
+
+cleanup:
+ if (objectHeader) {
+ PKIX_DECREF(objectHeader->stringRep);
+ }
+ PKIX_DECREF(objectString);
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_InvalidateCache (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_InvalidateCache(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_InvalidateCache");
+ PKIX_NULLCHECK_ONE(object);
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ PKIX_CHECK(pkix_LockObject(object, plContext),
+ PKIX_ERRORLOCKINGOBJECT);
+
+ /* invalidate hashcode */
+ objectHeader->hashcode = 0;
+ objectHeader->hashcodeCached = PKIX_FALSE;
+
+ PKIX_DECREF(objectHeader->stringRep);
+
+ PKIX_CHECK(pkix_UnlockObject(object, plContext),
+ PKIX_ERRORUNLOCKINGOBJECT);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_Compare (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Compare(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_PL_Object *firstObjectHeader = NULL;
+ PKIX_PL_Object *secondObjectHeader = NULL;
+ PKIX_PL_ComparatorCallback func = NULL;
+ pkix_ClassTable_Entry entry;
+ PKIX_UInt32 objType;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Compare");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader
+ (firstObject, &firstObjectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader
+ (secondObject, &secondObjectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ objType = firstObjectHeader->type;
+
+ if (objType >= PKIX_NUMTYPES){
+#ifdef PKIX_USER_OBJECT_TYPE
+ pkix_ClassTable_Entry *ctEntry = NULL;
+
+ PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n");
+ PR_Lock(classTableLock);
+ pkixErrorResult = pkix_pl_PrimHashTable_Lookup
+ (classTable,
+ (void *)&objType,
+ objType,
+ NULL,
+ (void **)&ctEntry,
+ plContext);
+ PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n");
+ PR_Unlock(classTableLock);
+ if (pkixErrorResult){
+ PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY);
+ }
+
+ if ((ctEntry == NULL) || (ctEntry->comparator == NULL)) {
+ PKIX_ERROR_FATAL(PKIX_UNDEFINEDCOMPARATOR);
+ }
+
+ func = ctEntry->comparator;
+#else
+ PORT_Assert (0);
+ pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE;
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ goto cleanup;
+#endif /* PKIX_USER_OBJECT_TYPE */
+ } else {
+ /* special handling for system types */
+ entry = systemClasses[objType];
+ func = entry.comparator;
+ if (!func){
+ PKIX_ERROR(PKIX_UNDEFINEDCOMPARATOR);
+ }
+ }
+
+ PKIX_CHECK(func(firstObject, secondObject, pResult, plContext),
+ PKIX_OBJECTSPECIFICFUNCTIONFAILED);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_Lock (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Lock(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Lock");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_LockObject(object, plContext),
+ PKIX_LOCKOBJECTFAILED);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Object_Unlock (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_Unlock(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_Unlock");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_UnlockObject(object, plContext),
+ PKIX_UNLOCKOBJECTFAILED);
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
+
+
+/*
+ * FUNCTION: PKIX_PL_Object_GetType (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Object_GetType(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pType,
+ void *plContext)
+{
+ PKIX_PL_Object *objectHeader = NULL;
+
+ PKIX_ENTER(OBJECT, "PKIX_PL_Object_GetType");
+ PKIX_NULLCHECK_TWO(object, pType);
+
+ /* Shift pointer from user data to object header */
+ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext),
+ PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT);
+
+ *pType = objectHeader->type;
+
+cleanup:
+
+ PKIX_RETURN(OBJECT);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.h
new file mode 100644
index 0000000000..0133c43eeb
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_object.h
@@ -0,0 +1,76 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_object.h
+ *
+ * Object Construction, Destruction and Callback Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_OBJECT_H
+#define _PKIX_PL_OBJECT_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Object Implementation Notes:
+ *
+ * Allocating a new object creates an object header and a block of
+ * uninitialized user data. A pointer to this uninitialized data is
+ * returned to the user. The structure looks as follows:
+ *
+ * +--------------------+
+ * | MAGIC HEADER |
+ * | (object header) |
+ * +--------------------+
+ * | user data | -- pointer returned from PKIX_PL_Object_Alloc
+ * +--------------------+
+ *
+ * Object operations receive a pointer to raw user data as an argument.
+ * The macro HEADER(object) returns a pointer to the object header.
+ * An assertion then verifies that the first field is the MAGIC_HEADER.
+ */
+
+/* PKIX_PL_Object Structure Definition */
+struct PKIX_PL_ObjectStruct {
+ PRUint64 magicHeader;
+ PKIX_UInt32 type;
+ PKIX_Int32 references;
+ PRLock *lock;
+ PKIX_PL_String *stringRep;
+ PKIX_UInt32 hashcode;
+ PKIX_Boolean hashcodeCached;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_Object_RetrieveEqualsCallback(
+ PKIX_PL_Object *object,
+ PKIX_PL_EqualsCallback *equalsCallback,
+ void *plContext);
+
+extern PKIX_Boolean initializing;
+extern PKIX_Boolean initialized;
+
+#ifdef PKIX_USER_OBJECT_TYPE
+
+extern PRLock *classTableLock;
+
+#endif
+
+extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+
+PKIX_Error *
+pkix_pl_Object_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_OBJECT_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c
new file mode 100644
index 0000000000..a6e0503850
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.c
@@ -0,0 +1,316 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_oid.c
+ *
+ * OID Object Functions
+ *
+ */
+
+#include "pkix_pl_oid.h"
+
+/* --Private-OID-Functions---------------------------------------- */
+
+ /*
+ * FUNCTION: pkix_pl_OID_Comparator
+ * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OID_Comparator(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Int32 *pRes,
+ void *plContext)
+{
+ PKIX_PL_OID *firstOID = NULL;
+ PKIX_PL_OID *secondOID = NULL;
+
+ PKIX_ENTER(OID, "pkix_pl_OID_Comparator");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pRes);
+
+ PKIX_CHECK(pkix_CheckTypes
+ (firstObject, secondObject, PKIX_OID_TYPE, plContext),
+ PKIX_ARGUMENTSNOTOIDS);
+
+ firstOID = (PKIX_PL_OID*)firstObject;
+ secondOID = (PKIX_PL_OID*)secondObject;
+
+ *pRes = (PKIX_Int32)SECITEM_CompareItem(&firstOID->derOid,
+ &secondOID->derOid);
+cleanup:
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OID_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OID_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_OID *oid = NULL;
+
+ PKIX_ENTER(OID, "pkix_pl_OID_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OID_TYPE, plContext),
+ PKIX_OBJECTNOTANOID);
+ oid = (PKIX_PL_OID*)object;
+ SECITEM_FreeItem(&oid->derOid, PR_FALSE);
+
+cleanup:
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OID_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OID_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_OID *oid = NULL;
+
+ PKIX_ENTER(OID, "pkix_pl_OID_HashCode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OID_TYPE, plContext),
+ PKIX_OBJECTNOTANOID);
+
+ oid = (PKIX_PL_OID *)object;
+
+ PKIX_CHECK(pkix_hash
+ ((unsigned char *)oid->derOid.data,
+ oid->derOid.len * sizeof (char),
+ pHashcode,
+ plContext),
+ PKIX_HASHFAILED);
+cleanup:
+
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OID_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_OID_Equals(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_Int32 cmpResult;
+
+ PKIX_ENTER(OID, "pkix_pl_OID_Equals");
+ PKIX_NULLCHECK_THREE(first, second, pResult);
+
+ PKIX_CHECK(pkix_pl_OID_Comparator
+ (first, second, &cmpResult, plContext),
+ PKIX_OIDCOMPARATORFAILED);
+
+ *pResult = (cmpResult == 0);
+cleanup:
+
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OID_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ * Use this function only for printing OIDs and not to make any
+ * critical security decision.
+ */
+static PKIX_Error *
+pkix_pl_OID_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_OID *oid = NULL;
+ char *oidString = NULL;
+
+ PKIX_ENTER(OID, "pkix_pl_OID_toString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_OID_TYPE, plContext),
+ PKIX_OBJECTNOTANOID);
+ oid = (PKIX_PL_OID*)object;
+ oidString = CERT_GetOidString(&oid->derOid);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, oidString , 0, pString, plContext),
+ PKIX_STRINGCREATEFAILED);
+cleanup:
+ PR_smprintf_free(oidString);
+
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OID_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_OID_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_OID_RegisterSelf(
+ void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry *entry = &systemClasses[PKIX_OID_TYPE];
+
+ PKIX_ENTER(OID, "pkix_pl_OID_RegisterSelf");
+
+ entry->description = "OID";
+ entry->typeObjectSize = sizeof(PKIX_PL_OID);
+ entry->destructor = pkix_pl_OID_Destroy;
+ entry->equalsFunction = pkix_pl_OID_Equals;
+ entry->hashcodeFunction = pkix_pl_OID_Hashcode;
+ entry->toStringFunction = pkix_pl_OID_ToString;
+ entry->comparator = pkix_pl_OID_Comparator;
+ entry->duplicateFunction = pkix_duplicateImmutable;
+
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: pkix_pl_OID_GetCriticalExtensionOIDs
+ * DESCRIPTION:
+ *
+ * Converts the extensions in "extensions" array that are critical to
+ * PKIX_PL_OID and returns the result as a PKIX_List in "pPidList".
+ * If there is no critical extension, an empty list is returned.
+ *
+ * PARAMETERS
+ * "extension"
+ * an array of extension pointers. May be NULL.
+ * "pOidsList"
+ * Address where the list of OIDs is returned. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_OID_GetCriticalExtensionOIDs(
+ CERTCertExtension **extensions,
+ PKIX_List **pOidsList,
+ void *plContext)
+{
+ PKIX_List *oidsList = NULL;
+ PKIX_PL_OID *pkixOID = NULL;
+
+ PKIX_ENTER(OID, "pkix_pl_OID_GetCriticalExtensionOIDs");
+ PKIX_NULLCHECK_ONE(pOidsList);
+
+ PKIX_CHECK(PKIX_List_Create(&oidsList, plContext),
+ PKIX_LISTCREATEFAILED);
+
+ if (extensions) {
+ while (*extensions) {
+ CERTCertExtension *extension = NULL;
+ SECItem *critical = NULL;
+ SECItem *oid = NULL;
+
+ extension = *extensions++;
+ /* extension is critical ? */
+ critical = &extension->critical;
+ if (critical->len == 0 || critical->data[0] == 0) {
+ continue;
+ }
+ oid = &extension->id;
+ PKIX_CHECK(
+ PKIX_PL_OID_CreateBySECItem(oid, &pkixOID, plContext),
+ PKIX_OIDCREATEFAILED);
+ PKIX_CHECK(
+ PKIX_List_AppendItem(oidsList, (PKIX_PL_Object *)pkixOID,
+ plContext),
+ PKIX_LISTAPPENDITEMFAILED);
+ PKIX_DECREF(pkixOID);
+ }
+ }
+
+ *pOidsList = oidsList;
+ oidsList = NULL;
+
+cleanup:
+ PKIX_DECREF(oidsList);
+ PKIX_DECREF(pkixOID);
+ PKIX_RETURN(OID);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_OID_CreateBySECItem (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_OID_CreateBySECItem(
+ SECItem *derOid,
+ PKIX_PL_OID **pOID,
+ void *plContext)
+{
+ PKIX_PL_OID *oid = NULL;
+ SECStatus rv;
+
+ PKIX_ENTER(OID, "PKIX_PL_OID_CreateBySECItem");
+ PKIX_NULLCHECK_TWO(pOID, derOid);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_OID_TYPE,
+ sizeof (PKIX_PL_OID),
+ (PKIX_PL_Object **)&oid,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+ rv = SECITEM_CopyItem(NULL, &oid->derOid, derOid);
+ if (rv != SECSuccess) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+ *pOID = oid;
+ oid = NULL;
+
+cleanup:
+ PKIX_DECREF(oid);
+
+ PKIX_RETURN(OID);
+}
+
+/*
+ * FUNCTION: PKIX_PL_OID_Create (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_OID_Create(
+ SECOidTag idtag,
+ PKIX_PL_OID **pOID,
+ void *plContext)
+{
+ SECOidData *oidData = NULL;
+
+ PKIX_ENTER(OID, "PKIX_PL_OID_Create");
+ PKIX_NULLCHECK_ONE(pOID);
+
+ oidData = SECOID_FindOIDByTag((SECOidTag)idtag);
+ if (!oidData) {
+ PKIX_ERROR(PKIX_SECOIDFINDOIDTAGDESCRIPTIONFAILED);
+ }
+
+ pkixErrorResult =
+ PKIX_PL_OID_CreateBySECItem(&oidData->oid, pOID, plContext);
+cleanup:
+ PKIX_RETURN(OID);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h
new file mode 100644
index 0000000000..0229194d84
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_oid.h
@@ -0,0 +1,39 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_oid.h
+ *
+ * OID Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_OID_H
+#define _PKIX_PL_OID_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_OIDStruct {
+ SECItem derOid;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_OID_RegisterSelf(void *plContext);
+
+PKIX_Error *
+pkix_pl_OID_GetCriticalExtensionOIDs(
+ CERTCertExtension **extensions,
+ PKIX_List **pOidsList,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_OID_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c
new file mode 100644
index 0000000000..c920533d37
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.c
@@ -0,0 +1,584 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_primhash.c
+ *
+ * Primitive (non-object) Hashtable Functions
+ *
+ */
+
+#include "pkix_pl_primhash.h"
+
+/* --Private-Functions---------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_KeyComparator_Default
+ * DESCRIPTION:
+ *
+ * Compares the integer pointed to by "firstKey" with the integer pointed to
+ * by "secondKey" for equality and stores the Boolean result at "pResult".
+ * This default key comparator assumes each key is a PKIX_UInt32, and it
+ * simply tests them for equality.
+ *
+ * PARAMETERS:
+ * "firstKey"
+ * Address of the first integer key to compare. Must be non-NULL.
+ * The EqualsCallback for this Object will be called.
+ * "secondKey"
+ * Address of the second integer key to compare. Must be non-NULL.
+ * "pResult"
+ * Address where Boolean will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_KeyComparator_Default(
+ PKIX_UInt32 *firstKey,
+ PKIX_UInt32 *secondKey,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ /* Assume both keys are pointers to PKIX_UInt32 */
+ PKIX_UInt32 firstInt, secondInt;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_KeyComparator_Default");
+ PKIX_NULLCHECK_THREE(firstKey, secondKey, pResult);
+
+ firstInt = *firstKey;
+ secondInt = *secondKey;
+
+ *pResult = (firstInt == secondInt)?PKIX_TRUE:PKIX_FALSE;
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_PrimHashTable_Create
+ * DESCRIPTION:
+ *
+ * Creates a new PrimHashtable object with a number of buckets equal to
+ * "numBuckets" and stores the result at "pResult".
+ *
+ * PARAMETERS:
+ * "numBuckets"
+ * The number of hash table buckets. Must be non-zero.
+ * "pResult"
+ * Address where PrimHashTable pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_PrimHashTable_Create(
+ PKIX_UInt32 numBuckets,
+ pkix_pl_PrimHashTable **pResult,
+ void *plContext)
+{
+ pkix_pl_PrimHashTable *primHashTable = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Create");
+ PKIX_NULLCHECK_ONE(pResult);
+
+ if (numBuckets == 0) {
+ PKIX_ERROR(PKIX_NUMBUCKETSEQUALSZERO);
+ }
+
+ /* Allocate a new hashtable */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (sizeof (pkix_pl_PrimHashTable),
+ (void **)&primHashTable,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ primHashTable->size = numBuckets;
+
+ /* Allocate space for the buckets */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (numBuckets * sizeof (pkix_pl_HT_Elem*),
+ (void **)&primHashTable->buckets,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ for (i = 0; i < numBuckets; i++) {
+ primHashTable->buckets[i] = NULL;
+ }
+
+ *pResult = primHashTable;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_FREE(primHashTable);
+ }
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: pkix_pl_PrimHashTable_Add
+ * DESCRIPTION:
+ *
+ * Adds the value pointed to by "value" to the PrimHashTable pointed to by
+ * "ht" using the key pointed to by "key" and the hashCode value equal to
+ * "hashCode", using the function pointed to by "keyComp" to compare keys.
+ * Assumes the key is either a PKIX_UInt32 or a PKIX_PL_Object. If the value
+ * already exists in the hashtable, this function returns a non-fatal error.
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of PrimHashtable to insert into. Must be non-NULL.
+ * "key"
+ * Address of key. Typically a PKIX_UInt32 or PKIX_PL_Object.
+ * Must be non-NULL.
+ * "value"
+ * Address of Object to be added to PrimHashtable. Must be non-NULL.
+ * "hashCode"
+ * Hashcode value of the key.
+ * "keyComp"
+ * Address of function used to determine if two keys are equal.
+ * If NULL, pkix_pl_KeyComparator_Default is used.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "ht"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HashTable Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_PrimHashTable_Add(
+ pkix_pl_PrimHashTable *ht,
+ void *key,
+ void *value,
+ PKIX_UInt32 hashCode,
+ PKIX_PL_EqualsCallback keyComp,
+ void *plContext)
+{
+ pkix_pl_HT_Elem **elemPtr = NULL;
+ pkix_pl_HT_Elem *element = NULL;
+ PKIX_Boolean compResult = PKIX_FALSE;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Add");
+ PKIX_NULLCHECK_THREE(ht, key, value);
+
+ for (elemPtr = &((ht->buckets)[hashCode%ht->size]), element = *elemPtr;
+ element != NULL; elemPtr = &(element->next), element = *elemPtr) {
+
+ if (element->hashCode != hashCode){
+ /* no possibility of a match */
+ continue;
+ }
+
+ if (keyComp == NULL){
+ PKIX_CHECK(pkix_pl_KeyComparator_Default
+ ((PKIX_UInt32 *)key,
+ (PKIX_UInt32 *)(element->key),
+ &compResult,
+ plContext),
+ PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
+ } else {
+ PKIX_CHECK(keyComp
+ ((PKIX_PL_Object *)key,
+ (PKIX_PL_Object *)(element->key),
+ &compResult,
+ plContext),
+ PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
+ }
+
+ if ((element->hashCode == hashCode) &&
+ (compResult == PKIX_TRUE)){
+ /* Same key already exists in the table */
+ PKIX_ERROR(PKIX_ATTEMPTTOADDDUPLICATEKEY);
+ }
+ }
+
+ /* Next Element should be NULL at this point */
+ if (element != NULL) {
+ PKIX_ERROR(PKIX_ERRORTRAVERSINGBUCKET);
+ }
+
+ /* Create a new HT_Elem */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (sizeof (pkix_pl_HT_Elem), (void **)elemPtr, plContext),
+ PKIX_MALLOCFAILED);
+
+ element = *elemPtr;
+
+ element->key = key;
+ element->value = value;
+ element->hashCode = hashCode;
+ element->next = NULL;
+
+cleanup:
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: pkix_pl_PrimHashTable_Remove
+ * DESCRIPTION:
+ *
+ * Removes any objects with the key pointed to by "key" and hashCode value
+ * equal to "hashCode" from the PrimHashtable pointed to by "ht", using the
+ * function pointed to by "keyComp" to compare keys, and stores the object's
+ * value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object.
+ * This function sets "pResult" to NULL if the key is not in the hashtable.
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of PrimHashtable to remove object. Must be non-NULL.
+ * "key"
+ * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object.
+ * Must be non-NULL.
+ * "value"
+ * Address of Object to be added to PrimHashtable. Must be non-NULL.
+ * "hashCode"
+ * Hashcode value of the key.
+ * "keyComp"
+ * Address of function used to determine if two keys are equal.
+ * If NULL, pkix_pl_KeyComparator_Default is used.
+ * "pResult"
+ * Address where value will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "ht"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HashTable Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_PrimHashTable_Remove(
+ pkix_pl_PrimHashTable *ht,
+ void *key,
+ PKIX_UInt32 hashCode,
+ PKIX_PL_EqualsCallback keyComp,
+ void **pKey,
+ void **pValue,
+ void *plContext)
+{
+ pkix_pl_HT_Elem *element = NULL;
+ pkix_pl_HT_Elem *prior = NULL;
+ PKIX_Boolean compResult;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Remove");
+ PKIX_NULLCHECK_FOUR(ht, key, pKey, pValue);
+
+ *pKey = NULL;
+ *pValue = NULL;
+
+ for (element = ht->buckets[hashCode%ht->size], prior = element;
+ (element != NULL);
+ prior = element, element = element->next) {
+
+ if (element->hashCode != hashCode){
+ /* no possibility of a match */
+ continue;
+ }
+
+ if (keyComp == NULL){
+ PKIX_CHECK(pkix_pl_KeyComparator_Default
+ ((PKIX_UInt32 *)key,
+ (PKIX_UInt32 *)(element->key),
+ &compResult,
+ plContext),
+ PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
+ } else {
+ PKIX_CHECK(keyComp
+ ((PKIX_PL_Object *)key,
+ (PKIX_PL_Object *)(element->key),
+ &compResult,
+ plContext),
+ PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
+ }
+
+ if ((element->hashCode == hashCode) &&
+ (compResult == PKIX_TRUE)){
+ if (element != prior) {
+ prior->next = element->next;
+ } else {
+ ht->buckets[hashCode%ht->size] = element->next;
+ }
+ *pKey = element->key;
+ *pValue = element->value;
+ element->key = NULL;
+ element->value = NULL;
+ element->next = NULL;
+ PKIX_FREE(element);
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+
+/*
+ * FUNCTION: pkix_pl_HashTableLookup
+ * DESCRIPTION:
+ *
+ * Looks up object using the key pointed to by "key" and hashCode value
+ * equal to "hashCode" from the PrimHashtable pointed to by "ht", using the
+ * function pointed to by "keyComp" to compare keys, and stores the object's
+ * value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object.
+ * This function sets "pResult" to NULL if the key is not in the hashtable.
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of PrimHashtable to lookup object from. Must be non-NULL.
+ * "key"
+ * Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object.
+ * Must be non-NULL.
+ * "keyComp"
+ * Address of function used to determine if two keys are equal.
+ * If NULL, pkix_pl_KeyComparator_Default is used.
+ * "hashCode"
+ * Hashcode value of the key.
+ * "pResult"
+ * Address where value will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Conditionally Thread Safe
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_PrimHashTable_Lookup(
+ pkix_pl_PrimHashTable *ht,
+ void *key,
+ PKIX_UInt32 hashCode,
+ PKIX_PL_EqualsCallback keyComp,
+ void **pResult,
+ void *plContext)
+{
+ pkix_pl_HT_Elem *element = NULL;
+ PKIX_Boolean compResult = PKIX_FALSE;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Lookup");
+ PKIX_NULLCHECK_THREE(ht, key, pResult);
+
+ *pResult = NULL;
+
+ for (element = (ht->buckets)[hashCode%ht->size];
+ (element != NULL) && (*pResult == NULL);
+ element = element->next) {
+
+ if (element->hashCode != hashCode){
+ /* no possibility of a match */
+ continue;
+ }
+
+ if (keyComp == NULL){
+ PKIX_CHECK(pkix_pl_KeyComparator_Default
+ ((PKIX_UInt32 *)key,
+ (PKIX_UInt32 *)(element->key),
+ &compResult,
+ plContext),
+ PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
+ } else {
+ pkixErrorResult =
+ keyComp((PKIX_PL_Object *)key,
+ (PKIX_PL_Object *)(element->key),
+ &compResult,
+ plContext);
+ if (pkixErrorResult) {
+ pkixErrorClass = PKIX_FATAL_ERROR;
+ pkixErrorCode = PKIX_COULDNOTTESTWHETHERKEYSEQUAL;
+ goto cleanup;
+ }
+ }
+
+ if ((element->hashCode == hashCode) &&
+ (compResult == PKIX_TRUE)){
+ *pResult = element->value;
+ goto cleanup;
+ }
+ }
+
+ /* if we've reached here, specified key doesn't exist in hashtable */
+ *pResult = NULL;
+
+cleanup:
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: pkix_pl_PrimHashTable_Destroy
+ *
+ * Destroys PrimHashTable pointed to by "ht".
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of PrimHashtable to free. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "ht"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS
+ * Returns NULL if the function succeeds.
+ * Returns a HashTable Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_PrimHashTable_Destroy(
+ pkix_pl_PrimHashTable *ht,
+ void *plContext)
+{
+ pkix_pl_HT_Elem *element = NULL;
+ pkix_pl_HT_Elem *temp = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Destroy");
+ PKIX_NULLCHECK_ONE(ht);
+
+ /* Free each element (list) */
+ for (i = 0; i < ht->size; i++) {
+ for (element = ht->buckets[i];
+ element != NULL;
+ element = temp) {
+ temp = element->next;
+ element->value = NULL;
+ element->key = NULL;
+ element->hashCode = 0;
+ element->next = NULL;
+ PKIX_FREE(element);
+ }
+ }
+
+ /* Free the pointer to the list array */
+ PKIX_FREE(ht->buckets);
+ ht->size = 0;
+
+ /* Free the table itself */
+ PKIX_FREE(ht);
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: pkix_pl_PrimHashTable_GetBucketSize
+ * DESCRIPTION:
+ *
+ * Retruns number of entries in the bucket the "hashCode" is designated in
+ * the hashtable "ht" in the address "pBucketSize".
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of PrimHashtable to get entries count. Must be non-NULL.
+ * "hashCode"
+ * Hashcode value of the key.
+ * "pBucketSize"
+ * Address that an PKIX_UInt32 is returned for number of entries in the
+ * bucket associated with the hashCode. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "ht"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HashTable Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_PrimHashTable_GetBucketSize(
+ pkix_pl_PrimHashTable *ht,
+ PKIX_UInt32 hashCode,
+ PKIX_UInt32 *pBucketSize,
+ void *plContext)
+{
+ pkix_pl_HT_Elem **elemPtr = NULL;
+ pkix_pl_HT_Elem *element = NULL;
+ PKIX_UInt32 bucketSize = 0;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_GetBucketSize");
+ PKIX_NULLCHECK_TWO(ht, pBucketSize);
+
+ for (elemPtr = &((ht->buckets)[hashCode%ht->size]), element = *elemPtr;
+ element != NULL; elemPtr = &(element->next), element = *elemPtr) {
+ bucketSize++;
+ }
+
+ *pBucketSize = bucketSize;
+
+ PKIX_RETURN(HASHTABLE);
+}
+
+/*
+ * FUNCTION: pkix_pl_PrimHashTable_RemoveFIFO
+ * DESCRIPTION:
+ *
+ * Remove the first entry in the bucket the "hashCode" is designated in
+ * the hashtable "ht". Since new entry is added at end of the link list
+ * the first one is the oldest (FI) therefore removed first (FO).
+ *
+ * PARAMETERS:
+ * "ht"
+ * Address of PrimHashtable to get entries count. Must be non-NULL.
+ * "hashCode"
+ * Hashcode value of the key.
+ * "pKey"
+ * Address of key of the entry deleted. Must be non-NULL.
+ * "pValue"
+ * Address of Value of the entry deleted. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "ht"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a HashTable Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_PrimHashTable_RemoveFIFO(
+ pkix_pl_PrimHashTable *ht,
+ PKIX_UInt32 hashCode,
+ void **pKey,
+ void **pValue,
+ void *plContext)
+{
+ pkix_pl_HT_Elem *element = NULL;
+
+ PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Remove");
+ PKIX_NULLCHECK_THREE(ht, pKey, pValue);
+
+ element = (ht->buckets)[hashCode%ht->size];
+
+ if (element != NULL) {
+
+ *pKey = element->key;
+ *pValue = element->value;
+ ht->buckets[hashCode%ht->size] = element->next;
+ element->key = NULL;
+ element->value = NULL;
+ element->next = NULL;
+ PKIX_FREE(element);
+ }
+
+ PKIX_RETURN(HASHTABLE);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.h
new file mode 100644
index 0000000000..b889e2e91e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_primhash.h
@@ -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/. */
+/*
+ * pkix_pl_primhash.h
+ *
+ * Primitive Hashtable Definition
+ *
+ */
+
+#ifndef _PKIX_PL_PRIMHASH_H
+#define _PKIX_PL_PRIMHASH_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pkix_pl_HT_Elem pkix_pl_HT_Elem;
+
+typedef struct pkix_pl_PrimHashTable pkix_pl_PrimHashTable;
+
+typedef struct pkix_pl_Integer pkix_pl_Integer;
+
+struct pkix_pl_Integer{
+ PKIX_UInt32 ht_int;
+};
+
+struct pkix_pl_HT_Elem {
+ void *key;
+ void *value;
+ PKIX_UInt32 hashCode;
+ pkix_pl_HT_Elem *next;
+};
+
+struct pkix_pl_PrimHashTable {
+ pkix_pl_HT_Elem **buckets;
+ PKIX_UInt32 size;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_PrimHashTable_Create(
+ PKIX_UInt32 numBuckets,
+ pkix_pl_PrimHashTable **pResult,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_PrimHashTable_Add(
+ pkix_pl_PrimHashTable *ht,
+ void *key,
+ void *value,
+ PKIX_UInt32 hashCode,
+ PKIX_PL_EqualsCallback keyComp,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_PrimHashTable_Remove(
+ pkix_pl_PrimHashTable *ht,
+ void *key,
+ PKIX_UInt32 hashCode,
+ PKIX_PL_EqualsCallback keyComp,
+ void **pKey,
+ void **pValue,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_PrimHashTable_Lookup(
+ pkix_pl_PrimHashTable *ht,
+ void *key,
+ PKIX_UInt32 hashCode,
+ PKIX_PL_EqualsCallback keyComp,
+ void **pResult,
+ void *plContext);
+
+PKIX_Error*
+pkix_pl_PrimHashTable_Destroy(
+ pkix_pl_PrimHashTable *ht,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_PrimHashTable_GetBucketSize(
+ pkix_pl_PrimHashTable *ht,
+ PKIX_UInt32 hashCode,
+ PKIX_UInt32 *pBucketSize,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_PrimHashTable_RemoveFIFO(
+ pkix_pl_PrimHashTable *ht,
+ PKIX_UInt32 hashCode,
+ void **pKey,
+ void **pValue,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_PRIMHASH_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c
new file mode 100644
index 0000000000..662931e981
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.c
@@ -0,0 +1,217 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_rwlock.c
+ *
+ * Read/Write Lock Functions
+ *
+ */
+
+#include "pkix_pl_rwlock.h"
+
+/* --Private-Functions-------------------------------------------- */
+
+static PKIX_Error *
+pkix_pl_RWLock_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_RWLock* rwlock = NULL;
+
+ PKIX_ENTER(RWLOCK, "pkix_pl_RWLock_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_RWLOCK_TYPE, plContext),
+ PKIX_OBJECTNOTRWLOCK);
+
+ rwlock = (PKIX_PL_RWLock*) object;
+
+ PKIX_RWLOCK_DEBUG("Calling PR_DestroyRWLock)\n");
+ PR_DestroyRWLock(rwlock->lock);
+ rwlock->lock = NULL;
+
+cleanup:
+
+ PKIX_RETURN(RWLOCK);
+}
+
+/*
+ * FUNCTION: pkix_pl_RWLock_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_RWLOCK_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_RWLock_RegisterSelf(
+ void *plContext)
+{
+
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(RWLOCK, "pkix_pl_RWLock_RegisterSelf");
+
+ entry.description = "RWLock";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_RWLock);
+ entry.destructor = pkix_pl_RWLock_Destroy;
+ entry.equalsFunction = NULL;
+ entry.hashcodeFunction = NULL;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = NULL;
+
+ systemClasses[PKIX_RWLOCK_TYPE] = entry;
+
+ PKIX_RETURN(RWLOCK);
+}
+
+/* --Public-Functions--------------------------------------------- */
+
+PKIX_Error *
+PKIX_PL_RWLock_Create(
+ PKIX_PL_RWLock **pNewLock,
+ void *plContext)
+{
+ PKIX_PL_RWLock *rwLock = NULL;
+
+ PKIX_ENTER(RWLOCK, "PKIX_PL_RWLock_Create");
+ PKIX_NULLCHECK_ONE(pNewLock);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_RWLOCK_TYPE,
+ sizeof (PKIX_PL_RWLock),
+ (PKIX_PL_Object **)&rwLock,
+ plContext),
+ PKIX_ERRORALLOCATINGRWLOCK);
+
+ PKIX_RWLOCK_DEBUG("\tCalling PR_NewRWLock)\n");
+ rwLock->lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "PKIX RWLock");
+
+ if (rwLock->lock == NULL) {
+ PKIX_DECREF(rwLock);
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ rwLock->readCount = 0;
+ rwLock->writeLocked = PKIX_FALSE;
+
+ *pNewLock = rwLock;
+
+cleanup:
+
+ PKIX_RETURN(RWLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_AcquireReaderLock(
+ PKIX_PL_RWLock *lock,
+ void *plContext)
+{
+ PKIX_ENTER(RWLOCK, "PKIX_PL_AcquireReaderLock");
+ PKIX_NULLCHECK_ONE(lock);
+
+ PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Rlock)\n");
+ (void) PR_RWLock_Rlock(lock->lock);
+
+ lock->readCount++;
+
+ PKIX_RETURN(RWLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_ReleaseReaderLock(
+ PKIX_PL_RWLock *lock,
+ void *plContext)
+{
+ PKIX_ENTER(RWLOCK, "PKIX_PL_ReleaseReaderLock");
+ PKIX_NULLCHECK_ONE(lock);
+
+ PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Unlock)\n");
+ (void) PR_RWLock_Unlock(lock->lock);
+
+ lock->readCount--;
+
+ PKIX_RETURN(RWLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_IsReaderLockHeld(
+ PKIX_PL_RWLock *lock,
+ PKIX_Boolean *pIsHeld,
+ void *plContext)
+{
+ PKIX_ENTER(RWLOCK, "PKIX_PL_IsReaderLockHeld");
+ PKIX_NULLCHECK_TWO(lock, pIsHeld);
+
+ *pIsHeld = (lock->readCount > 0)?PKIX_TRUE:PKIX_FALSE;
+
+ PKIX_RETURN(RWLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_AcquireWriterLock(
+ PKIX_PL_RWLock *lock,
+ void *plContext)
+{
+ PKIX_ENTER(RWLOCK, "PKIX_PL_AcquireWriterLock");
+ PKIX_NULLCHECK_ONE(lock);
+
+ PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Wlock\n");
+ (void) PR_RWLock_Wlock(lock->lock);
+
+ if (lock->readCount > 0) {
+ PKIX_ERROR(PKIX_LOCKHASNONZEROREADCOUNT);
+ }
+
+ /* We should never acquire a write lock if the lock is held */
+ lock->writeLocked = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(RWLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_ReleaseWriterLock(
+ PKIX_PL_RWLock *lock,
+ void *plContext)
+{
+ PKIX_ENTER(RWLOCK, "PKIX_PL_ReleaseWriterLock");
+ PKIX_NULLCHECK_ONE(lock);
+
+ if (lock->readCount > 0) {
+ PKIX_ERROR(PKIX_LOCKHASNONZEROREADCOUNT);
+ }
+
+ PKIX_RWLOCK_DEBUG("\tCalling PR_RWLock_Unlock)\n");
+ (void) PR_RWLock_Unlock(lock->lock);
+
+ /* XXX Need to think about thread safety here */
+ /* There should be a single lock holder */
+ lock->writeLocked = PKIX_FALSE;
+
+cleanup:
+
+ PKIX_RETURN(RWLOCK);
+}
+
+PKIX_Error *
+PKIX_PL_IsWriterLockHeld(
+ PKIX_PL_RWLock *lock,
+ PKIX_Boolean *pIsHeld,
+ void *plContext)
+{
+ PKIX_ENTER(RWLOCK, "PKIX_PL_IsWriterLockHeld");
+ PKIX_NULLCHECK_TWO(lock, pIsHeld);
+
+ *pIsHeld = lock->writeLocked;
+
+ PKIX_RETURN(RWLOCK);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.h
new file mode 100644
index 0000000000..fd64659506
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_rwlock.h
@@ -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/. */
+/*
+ * pkix_pl_rwlock.h
+ *
+ * Read/Write Lock Definition
+ *
+ */
+
+#ifndef _PKIX_PL_RWLOCK_H
+#define _PKIX_PL_RWLOCK_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_RWLockStruct {
+ PRRWLock* lock;
+ PKIX_UInt32 readCount;
+ PKIX_Boolean writeLocked;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_RWLock_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_RWLOCK_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.c b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.c
new file mode 100644
index 0000000000..167382466e
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.c
@@ -0,0 +1,628 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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_pl_string.c
+ *
+ * String Object Functions
+ *
+ */
+
+#include "pkix_pl_string.h"
+
+/* --Private-String-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_String_Comparator
+ * (see comments for PKIX_PL_ComparatorCallback in pkix_pl_system.h)
+ *
+ * NOTE:
+ * This function is a utility function called by pkix_pl_String_Equals().
+ * It is not officially registered as a comparator.
+ */
+static PKIX_Error *
+pkix_pl_String_Comparator(
+ PKIX_PL_String *firstString,
+ PKIX_PL_String *secondString,
+ PKIX_Int32 *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 i;
+ PKIX_Int32 result;
+ unsigned char *p1 = NULL;
+ unsigned char *p2 = NULL;
+
+ PKIX_ENTER(STRING, "pkix_pl_String_Comparator");
+ PKIX_NULLCHECK_THREE(firstString, secondString, pResult);
+
+ result = 0;
+
+ p1 = (unsigned char*) firstString->utf16String;
+ p2 = (unsigned char*) secondString->utf16String;
+
+ /* Compare characters until you find a difference */
+ for (i = 0; ((i < firstString->utf16Length) &&
+ (i < secondString->utf16Length) &&
+ result == 0); i++, p1++, p2++) {
+ if (*p1 < *p2){
+ result = -1;
+ } else if (*p1 > *p2){
+ result = 1;
+ }
+ }
+
+ /* If two arrays are identical so far, the longer one is greater */
+ if (result == 0) {
+ if (firstString->utf16Length < secondString->utf16Length) {
+ result = -1;
+ } else if (firstString->utf16Length >
+ secondString->utf16Length) {
+ result = 1;
+ }
+ }
+
+ *pResult = result;
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_pl_String_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_String_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_String *string = NULL;
+
+ PKIX_ENTER(STRING, "pkix_pl_String_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_STRING_TYPE, plContext),
+ PKIX_ARGUMENTNOTSTRING);
+
+ string = (PKIX_PL_String*)object;
+
+ /* XXX For debugging Destroy EscASCII String */
+ if (string->escAsciiString != NULL) {
+ PKIX_FREE(string->escAsciiString);
+ string->escAsciiString = NULL;
+ string->escAsciiLength = 0;
+ }
+
+ /* Destroy UTF16 String */
+ if (string->utf16String != NULL) {
+ PKIX_FREE(string->utf16String);
+ string->utf16String = NULL;
+ string->utf16Length = 0;
+ }
+
+cleanup:
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_pl_String_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_String_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *string = NULL;
+ char *ascii = NULL;
+ PKIX_UInt32 length;
+
+ PKIX_ENTER(STRING, "pkix_pl_String_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_STRING_TYPE, plContext),
+ PKIX_ARGUMENTNOTSTRING);
+
+ string = (PKIX_PL_String*)object;
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ (string, PKIX_ESCASCII, (void **)&ascii, &length, plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, ascii, 0, pString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ goto cleanup;
+
+cleanup:
+
+ PKIX_FREE(ascii);
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_pl_String_Equals
+ * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_String_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 secondType;
+ PKIX_Int32 cmpResult = 0;
+
+ PKIX_ENTER(STRING, "pkix_pl_String_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* Sanity check: Test that "firstObject" is a Strings */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_STRING_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTSTRING);
+
+ /* "SecondObject" doesn't have to be a string */
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObject, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+
+ /* If types differ, then we will return false */
+ *pResult = PKIX_FALSE;
+
+ if (secondType != PKIX_STRING_TYPE) goto cleanup;
+
+ /* It's safe to cast here */
+ PKIX_CHECK(pkix_pl_String_Comparator
+ ((PKIX_PL_String*)firstObject,
+ (PKIX_PL_String*)secondObject,
+ &cmpResult,
+ plContext),
+ PKIX_STRINGCOMPARATORFAILED);
+
+ /* Strings are equal iff Comparator Result is 0 */
+ *pResult = (cmpResult == 0);
+
+cleanup:
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_pl_String_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_String_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_String *string = NULL;
+
+ PKIX_ENTER(STRING, "pkix_pl_String_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_STRING_TYPE, plContext),
+ PKIX_OBJECTNOTSTRING);
+
+ string = (PKIX_PL_String*)object;
+
+ PKIX_CHECK(pkix_hash
+ ((const unsigned char *)string->utf16String,
+ string->utf16Length,
+ pHashcode,
+ plContext),
+ PKIX_HASHFAILED);
+
+cleanup:
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: pkix_pl_String_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_STRING_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_String_RegisterSelf(
+ void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(STRING, "pkix_pl_String_RegisterSelf");
+
+ entry.description = "String";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_String);
+ entry.destructor = pkix_pl_String_Destroy;
+ entry.equalsFunction = pkix_pl_String_Equals;
+ entry.hashcodeFunction = pkix_pl_String_Hashcode;
+ entry.toStringFunction = pkix_pl_String_ToString;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_STRING_TYPE] = entry;
+
+ PKIX_RETURN(STRING);
+}
+
+
+/* --Public-String-Functions----------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_String_Create (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_String_Create(
+ PKIX_UInt32 fmtIndicator,
+ const void *stringRep,
+ PKIX_UInt32 stringLen,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *string = NULL;
+ unsigned char *utf16Char = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_ENTER(STRING, "PKIX_PL_String_Create");
+ PKIX_NULLCHECK_TWO(pString, stringRep);
+
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_STRING_TYPE,
+ sizeof (PKIX_PL_String),
+ (PKIX_PL_Object **)&string,
+ plContext),
+ PKIX_COULDNOTALLOCATENEWSTRINGOBJECT);
+
+ string->utf16String = NULL;
+ string->utf16Length = 0;
+
+ /* XXX For Debugging */
+ string->escAsciiString = NULL;
+ string->escAsciiLength = 0;
+
+ switch (fmtIndicator) {
+ case PKIX_ESCASCII: case PKIX_ESCASCII_DEBUG:
+ PKIX_STRING_DEBUG("\tCalling PL_strlen).\n");
+ string->escAsciiLength = PL_strlen(stringRep);
+
+ /* XXX Cache for Debugging */
+ PKIX_CHECK(PKIX_PL_Malloc
+ ((string->escAsciiLength)+1,
+ (void **)&string->escAsciiString,
+ plContext),
+ PKIX_MALLOCFAILED);
+
+ (void) PORT_Memcpy
+ (string->escAsciiString,
+ (void *)((char *)stringRep),
+ (string->escAsciiLength)+1);
+
+ /* Convert the EscASCII string to UTF16 */
+ PKIX_CHECK(pkix_EscASCII_to_UTF16
+ (string->escAsciiString,
+ string->escAsciiLength,
+ (fmtIndicator == PKIX_ESCASCII_DEBUG),
+ &string->utf16String,
+ &string->utf16Length,
+ plContext),
+ PKIX_ESCASCIITOUTF16FAILED);
+ break;
+ case PKIX_UTF8:
+ /* Convert the UTF8 string to UTF16 */
+ PKIX_CHECK(pkix_UTF8_to_UTF16
+ (stringRep,
+ stringLen,
+ &string->utf16String,
+ &string->utf16Length,
+ plContext),
+ PKIX_UTF8TOUTF16FAILED);
+ break;
+ case PKIX_UTF16:
+ /* UTF16 Strings must be even in length */
+ if (stringLen%2 == 1) {
+ PKIX_DECREF(string);
+ PKIX_ERROR(PKIX_UTF16ALIGNMENTERROR);
+ }
+
+ utf16Char = (unsigned char *)stringRep;
+
+ /* Make sure this is a valid UTF-16 String */
+ for (i = 0; \
+ (i < stringLen) && (pkixErrorResult == NULL); \
+ i += 2) {
+ /* Check that surrogate pairs are valid */
+ if ((utf16Char[i] >= 0xD8)&&
+ (utf16Char[i] <= 0xDB)) {
+ if ((i+2) >= stringLen) {
+ PKIX_ERROR(PKIX_UTF16HIGHZONEALIGNMENTERROR);
+ /* Second pair should be DC00-DFFF */
+ } else if (!((utf16Char[i+2] >= 0xDC)&&
+ (utf16Char[i+2] <= 0xDF))) {
+ PKIX_ERROR(PKIX_UTF16LOWZONEERROR);
+ } else {
+ /* Surrogate quartet is valid. */
+ i += 2;
+ }
+ }
+ }
+
+ /* Create UTF16 String */
+ string->utf16Length = stringLen;
+
+ /* Alloc space for string */
+ PKIX_CHECK(PKIX_PL_Malloc
+ (stringLen, &string->utf16String, plContext),
+ PKIX_MALLOCFAILED);
+
+ PKIX_STRING_DEBUG("\tCalling PORT_Memcpy).\n");
+ (void) PORT_Memcpy
+ (string->utf16String, stringRep, stringLen);
+ break;
+
+ default:
+ PKIX_ERROR(PKIX_UNKNOWNFORMAT);
+ }
+
+ *pString = string;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(string);
+ }
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: PKIX_PL_Sprintf (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_Sprintf(
+ PKIX_PL_String **pOut,
+ void *plContext,
+ const PKIX_PL_String *fmt,
+ ...)
+{
+ PKIX_PL_String *tempString = NULL;
+ PKIX_UInt32 tempUInt = 0;
+ void *pArg = NULL;
+ char *asciiText = NULL;
+ char *asciiFormat = NULL;
+ char *convertedAsciiFormat = NULL;
+ char *convertedAsciiFormatBase = NULL;
+ va_list args;
+ PKIX_UInt32 length, i, j, dummyLen;
+
+ PKIX_ENTER(STRING, "PKIX_PL_Sprintf");
+ PKIX_NULLCHECK_TWO(pOut, fmt);
+
+ PKIX_CHECK(PKIX_PL_String_GetEncoded
+ ((PKIX_PL_String *)fmt,
+ PKIX_ESCASCII,
+ (void **)&asciiFormat,
+ &length,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+
+ PKIX_STRING_DEBUG("\tCalling PR_Malloc).\n");
+ convertedAsciiFormat = PR_Malloc(length + 1);
+ if (convertedAsciiFormat == NULL)
+ PKIX_ERROR_ALLOC_ERROR();
+
+ convertedAsciiFormatBase = convertedAsciiFormat;
+
+ PKIX_STRING_DEBUG("\tCalling va_start).\n");
+ va_start(args, fmt);
+
+ i = 0;
+ j = 0;
+ while (i < length) {
+ if ((asciiFormat[i] == '%')&&((i+1) < length)) {
+ switch (asciiFormat[i+1]) {
+ case 's':
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ convertedAsciiFormat[j] = '\0';
+
+ tempString = va_arg(args, PKIX_PL_String *);
+ if (tempString != NULL) {
+ PKIX_CHECK_NO_GOTO(
+ PKIX_PL_String_GetEncoded
+ ((PKIX_PL_String*)
+ tempString,
+ PKIX_ESCASCII,
+ &pArg,
+ &dummyLen,
+ plContext),
+ PKIX_STRINGGETENCODEDFAILED);
+ /* need to cleanup var args before
+ * we ditch out to cleanup. */
+ if (pkixErrorResult) {
+ va_end(args);
+ goto cleanup;
+ }
+ } else {
+ /* there may be a NULL in var_args */
+ pArg = NULL;
+ }
+ if (asciiText != NULL) {
+ asciiText = PR_sprintf_append(asciiText,
+ (const char *)convertedAsciiFormat,
+ pArg);
+ } else {
+ asciiText = PR_smprintf
+ ((const char *)convertedAsciiFormat,
+ pArg);
+ }
+ if (pArg != NULL) {
+ PKIX_PL_Free(pArg, plContext);
+ pArg = NULL;
+ }
+ convertedAsciiFormat += j;
+ j = 0;
+ break;
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ convertedAsciiFormat[j] = '\0';
+
+ tempUInt = va_arg(args, PKIX_UInt32);
+ if (asciiText != NULL) {
+ asciiText = PR_sprintf_append(asciiText,
+ (const char *)convertedAsciiFormat,
+ tempUInt);
+ } else {
+ asciiText = PR_smprintf
+ ((const char *)convertedAsciiFormat,
+ tempUInt);
+ }
+ convertedAsciiFormat += j;
+ j = 0;
+ break;
+ default:
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ break;
+ }
+ } else {
+ convertedAsciiFormat[j++] = asciiFormat[i++];
+ }
+ }
+
+ /* for constant string value at end of fmt */
+ if (j > 0) {
+ convertedAsciiFormat[j] = '\0';
+ if (asciiText != NULL) {
+ asciiText = PR_sprintf_append(asciiText,
+ (const char *)convertedAsciiFormat);
+ } else {
+ asciiText = PR_smprintf((const char *)convertedAsciiFormat);
+ }
+ }
+
+ va_end(args);
+
+ /* Copy temporary char * into a string object */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, (void *)asciiText, 0, pOut, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+cleanup:
+
+ PKIX_FREE(asciiFormat);
+
+ if (convertedAsciiFormatBase){
+ PR_Free(convertedAsciiFormatBase);
+ }
+
+ if (asciiText){
+ PKIX_STRING_DEBUG("\tCalling PR_smprintf_free).\n");
+ PR_smprintf_free(asciiText);
+ }
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: PKIX_PL_GetString (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_GetString(
+ /* ARGSUSED */ PKIX_UInt32 stringID,
+ char *defaultString,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_ENTER(STRING, "PKIX_PL_GetString");
+ PKIX_NULLCHECK_TWO(pString, defaultString);
+
+ /* XXX Optimization - use stringID for caching */
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII, defaultString, 0, pString, plContext),
+ PKIX_STRINGCREATEFAILED);
+
+cleanup:
+
+ PKIX_RETURN(STRING);
+}
+
+/*
+ * FUNCTION: PKIX_PL_String_GetEncoded (see comments in pkix_pl_system.h)
+ */
+PKIX_Error *
+PKIX_PL_String_GetEncoded(
+ PKIX_PL_String *string,
+ PKIX_UInt32 fmtIndicator,
+ void **pStringRep,
+ PKIX_UInt32 *pLength,
+ void *plContext)
+{
+ PKIX_ENTER(STRING, "PKIX_PL_String_GetEncoded");
+ PKIX_NULLCHECK_THREE(string, pStringRep, pLength);
+
+ switch (fmtIndicator) {
+ case PKIX_ESCASCII: case PKIX_ESCASCII_DEBUG:
+ PKIX_CHECK(pkix_UTF16_to_EscASCII
+ (string->utf16String,
+ string->utf16Length,
+ (fmtIndicator == PKIX_ESCASCII_DEBUG),
+ (char **)pStringRep,
+ pLength,
+ plContext),
+ PKIX_UTF16TOESCASCIIFAILED);
+ break;
+ case PKIX_UTF8:
+ PKIX_CHECK(pkix_UTF16_to_UTF8
+ (string->utf16String,
+ string->utf16Length,
+ PKIX_FALSE,
+ pStringRep,
+ pLength,
+ plContext),
+ PKIX_UTF16TOUTF8FAILED);
+ break;
+ case PKIX_UTF8_NULL_TERM:
+ PKIX_CHECK(pkix_UTF16_to_UTF8
+ (string->utf16String,
+ string->utf16Length,
+ PKIX_TRUE,
+ pStringRep,
+ pLength,
+ plContext),
+ PKIX_UTF16TOUTF8FAILED);
+ break;
+ case PKIX_UTF16:
+ *pLength = string->utf16Length;
+
+ PKIX_CHECK(PKIX_PL_Malloc(*pLength, pStringRep, plContext),
+ PKIX_MALLOCFAILED);
+
+ PKIX_STRING_DEBUG("\tCalling PORT_Memcpy).\n");
+ (void) PORT_Memcpy(*pStringRep, string->utf16String, *pLength);
+ break;
+ default:
+ PKIX_ERROR(PKIX_UNKNOWNFORMAT);
+ }
+
+cleanup:
+
+ PKIX_RETURN(STRING);
+}
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.h b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.h
new file mode 100644
index 0000000000..9270e4c567
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/pkix_pl_string.h
@@ -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/. */
+/*
+ * pkix_pl_string.h
+ *
+ * String Object Definitions
+ *
+ */
+
+#ifndef _PKIX_PL_STRING_H
+#define _PKIX_PL_STRING_H
+
+#include "pkix_pl_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct PKIX_PL_StringStruct {
+ void* utf16String;
+ PKIX_UInt32 utf16Length;
+ /* XXX For Debugging */
+ char* escAsciiString;
+ PKIX_UInt32 escAsciiLength;
+};
+
+/* see source file for function documentation */
+
+PKIX_Error *
+pkix_pl_String_RegisterSelf(void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PKIX_PL_STRING_H */
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/system/system.gyp b/security/nss/lib/libpkix/pkix_pl_nss/system/system.gyp
new file mode 100644
index 0000000000..32daec93d6
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/system.gyp
@@ -0,0 +1,36 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+{
+ 'includes': [
+ '../../../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pkixsystem',
+ 'type': 'static_library',
+ 'sources': [
+ 'pkix_pl_bigint.c',
+ 'pkix_pl_bytearray.c',
+ 'pkix_pl_common.c',
+ 'pkix_pl_error.c',
+ 'pkix_pl_hashtable.c',
+ 'pkix_pl_lifecycle.c',
+ 'pkix_pl_mem.c',
+ 'pkix_pl_monitorlock.c',
+ 'pkix_pl_mutex.c',
+ 'pkix_pl_object.c',
+ 'pkix_pl_oid.c',
+ 'pkix_pl_primhash.c',
+ 'pkix_pl_rwlock.c',
+ 'pkix_pl_string.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file