summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/util
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /security/nss/lib/util
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/nss/lib/util')
-rw-r--r--security/nss/lib/util/Makefile47
-rw-r--r--security/nss/lib/util/SECerrs.h569
-rw-r--r--security/nss/lib/util/base64.h41
-rw-r--r--security/nss/lib/util/ciferfam.h62
-rw-r--r--security/nss/lib/util/config.mk38
-rw-r--r--security/nss/lib/util/derdec.c189
-rw-r--r--security/nss/lib/util/derenc.c460
-rw-r--r--security/nss/lib/util/dersubr.c249
-rw-r--r--security/nss/lib/util/dertime.c310
-rw-r--r--security/nss/lib/util/eccutil.h17
-rw-r--r--security/nss/lib/util/errstrs.c41
-rw-r--r--security/nss/lib/util/exports.gyp69
-rw-r--r--security/nss/lib/util/hasht.h71
-rw-r--r--security/nss/lib/util/kyber.h32
-rw-r--r--security/nss/lib/util/manifest.mn91
-rw-r--r--security/nss/lib/util/nssb64.h94
-rw-r--r--security/nss/lib/util/nssb64d.c852
-rw-r--r--security/nss/lib/util/nssb64e.c734
-rw-r--r--security/nss/lib/util/nssb64t.h15
-rw-r--r--security/nss/lib/util/nssilckt.h191
-rw-r--r--security/nss/lib/util/nssilock.c479
-rw-r--r--security/nss/lib/util/nssilock.h267
-rw-r--r--security/nss/lib/util/nsslocks.h10
-rw-r--r--security/nss/lib/util/nssrwlk.c450
-rw-r--r--security/nss/lib/util/nssrwlk.h133
-rw-r--r--security/nss/lib/util/nssrwlkt.h19
-rw-r--r--security/nss/lib/util/nssutil.def362
-rw-r--r--security/nss/lib/util/nssutil.h41
-rw-r--r--security/nss/lib/util/nssutil.rc68
-rw-r--r--security/nss/lib/util/oidstring.c114
-rw-r--r--security/nss/lib/util/pkcs11.h274
-rw-r--r--security/nss/lib/util/pkcs11f.h1044
-rw-r--r--security/nss/lib/util/pkcs11n.h745
-rw-r--r--security/nss/lib/util/pkcs11p.h24
-rw-r--r--security/nss/lib/util/pkcs11t.h2591
-rw-r--r--security/nss/lib/util/pkcs11u.h22
-rw-r--r--security/nss/lib/util/pkcs11uri.c867
-rw-r--r--security/nss/lib/util/pkcs11uri.h80
-rw-r--r--security/nss/lib/util/pkcs1sig.c158
-rw-r--r--security/nss/lib/util/pkcs1sig.h30
-rw-r--r--security/nss/lib/util/portreg.c375
-rw-r--r--security/nss/lib/util/portreg.h81
-rw-r--r--security/nss/lib/util/quickder.c837
-rw-r--r--security/nss/lib/util/secalgid.c129
-rw-r--r--security/nss/lib/util/secasn1.h303
-rw-r--r--security/nss/lib/util/secasn1d.c3443
-rw-r--r--security/nss/lib/util/secasn1e.c1572
-rw-r--r--security/nss/lib/util/secasn1t.h267
-rw-r--r--security/nss/lib/util/secasn1u.c94
-rw-r--r--security/nss/lib/util/seccomon.h91
-rw-r--r--security/nss/lib/util/secder.h175
-rw-r--r--security/nss/lib/util/secdert.h129
-rw-r--r--security/nss/lib/util/secdig.c182
-rw-r--r--security/nss/lib/util/secdig.h100
-rw-r--r--security/nss/lib/util/secdigt.h26
-rw-r--r--security/nss/lib/util/secerr.h226
-rw-r--r--security/nss/lib/util/secitem.c496
-rw-r--r--security/nss/lib/util/secitem.h126
-rw-r--r--security/nss/lib/util/secload.c182
-rw-r--r--security/nss/lib/util/secoid.c2402
-rw-r--r--security/nss/lib/util/secoid.h149
-rw-r--r--security/nss/lib/util/secoidt.h578
-rw-r--r--security/nss/lib/util/secplcy.c83
-rw-r--r--security/nss/lib/util/secplcy.h104
-rw-r--r--security/nss/lib/util/secport.c925
-rw-r--r--security/nss/lib/util/secport.h378
-rw-r--r--security/nss/lib/util/sectime.c163
-rw-r--r--security/nss/lib/util/templates.c136
-rw-r--r--security/nss/lib/util/utf8.c445
-rw-r--r--security/nss/lib/util/util.gyp60
-rw-r--r--security/nss/lib/util/utilmod.c946
-rw-r--r--security/nss/lib/util/utilmodt.h43
-rw-r--r--security/nss/lib/util/utilpars.c1314
-rw-r--r--security/nss/lib/util/utilpars.h70
-rw-r--r--security/nss/lib/util/utilparst.h78
-rw-r--r--security/nss/lib/util/utilrename.h164
-rw-r--r--security/nss/lib/util/verref.h43
77 files changed, 28865 insertions, 0 deletions
diff --git a/security/nss/lib/util/Makefile b/security/nss/lib/util/Makefile
new file mode 100644
index 0000000000..c3cb5ef8be
--- /dev/null
+++ b/security/nss/lib/util/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include config.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
diff --git a/security/nss/lib/util/SECerrs.h b/security/nss/lib/util/SECerrs.h
new file mode 100644
index 0000000000..e05d365c0a
--- /dev/null
+++ b/security/nss/lib/util/SECerrs.h
@@ -0,0 +1,569 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* General security error codes */
+/* Caller must #include "secerr.h" */
+
+ER3(SEC_ERROR_IO, SEC_ERROR_BASE + 0,
+ "An I/O error occurred during security authorization.")
+
+ER3(SEC_ERROR_LIBRARY_FAILURE, SEC_ERROR_BASE + 1,
+ "security library failure.")
+
+ER3(SEC_ERROR_BAD_DATA, SEC_ERROR_BASE + 2,
+ "security library: received bad data.")
+
+ER3(SEC_ERROR_OUTPUT_LEN, SEC_ERROR_BASE + 3,
+ "security library: output length error.")
+
+ER3(SEC_ERROR_INPUT_LEN, SEC_ERROR_BASE + 4,
+ "security library has experienced an input length error.")
+
+ER3(SEC_ERROR_INVALID_ARGS, SEC_ERROR_BASE + 5,
+ "security library: invalid arguments.")
+
+ER3(SEC_ERROR_INVALID_ALGORITHM, SEC_ERROR_BASE + 6,
+ "security library: invalid algorithm.")
+
+ER3(SEC_ERROR_INVALID_AVA, SEC_ERROR_BASE + 7,
+ "security library: invalid AVA.")
+
+ER3(SEC_ERROR_INVALID_TIME, SEC_ERROR_BASE + 8,
+ "Improperly formatted time string.")
+
+ER3(SEC_ERROR_BAD_DER, SEC_ERROR_BASE + 9,
+ "security library: improperly formatted DER-encoded message.")
+
+ER3(SEC_ERROR_BAD_SIGNATURE, SEC_ERROR_BASE + 10,
+ "Peer's certificate has an invalid signature.")
+
+ER3(SEC_ERROR_EXPIRED_CERTIFICATE, SEC_ERROR_BASE + 11,
+ "Peer's Certificate has expired.")
+
+ER3(SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_BASE + 12,
+ "Peer's Certificate has been revoked.")
+
+ER3(SEC_ERROR_UNKNOWN_ISSUER, SEC_ERROR_BASE + 13,
+ "Peer's Certificate issuer is not recognized.")
+
+ER3(SEC_ERROR_BAD_KEY, SEC_ERROR_BASE + 14,
+ "Peer's public key is invalid.")
+
+ER3(SEC_ERROR_BAD_PASSWORD, SEC_ERROR_BASE + 15,
+ "The security password entered is incorrect.")
+
+ER3(SEC_ERROR_RETRY_PASSWORD, SEC_ERROR_BASE + 16,
+ "New password entered incorrectly. Please try again.")
+
+ER3(SEC_ERROR_NO_NODELOCK, SEC_ERROR_BASE + 17,
+ "security library: no nodelock.")
+
+ER3(SEC_ERROR_BAD_DATABASE, SEC_ERROR_BASE + 18,
+ "security library: bad database.")
+
+ER3(SEC_ERROR_NO_MEMORY, SEC_ERROR_BASE + 19,
+ "security library: memory allocation failure.")
+
+ER3(SEC_ERROR_UNTRUSTED_ISSUER, SEC_ERROR_BASE + 20,
+ "Peer's certificate issuer has been marked as not trusted by the user.")
+
+ER3(SEC_ERROR_UNTRUSTED_CERT, SEC_ERROR_BASE + 21,
+ "Peer's certificate has been marked as not trusted by the user.")
+
+ER3(SEC_ERROR_DUPLICATE_CERT, (SEC_ERROR_BASE + 22),
+ "Certificate already exists in your database.")
+
+ER3(SEC_ERROR_DUPLICATE_CERT_NAME, (SEC_ERROR_BASE + 23),
+ "Downloaded certificate's name duplicates one already in your database.")
+
+ER3(SEC_ERROR_ADDING_CERT, (SEC_ERROR_BASE + 24),
+ "Error adding certificate to database.")
+
+ER3(SEC_ERROR_FILING_KEY, (SEC_ERROR_BASE + 25),
+ "Error refiling the key for this certificate.")
+
+ER3(SEC_ERROR_NO_KEY, (SEC_ERROR_BASE + 26),
+ "The private key for this certificate cannot be found in key database")
+
+ER3(SEC_ERROR_CERT_VALID, (SEC_ERROR_BASE + 27),
+ "This certificate is valid.")
+
+ER3(SEC_ERROR_CERT_NOT_VALID, (SEC_ERROR_BASE + 28),
+ "This certificate is not valid.")
+
+ER3(SEC_ERROR_CERT_NO_RESPONSE, (SEC_ERROR_BASE + 29),
+ "Cert Library: No Response")
+
+ER3(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, (SEC_ERROR_BASE + 30),
+ "The certificate issuer's certificate has expired. Check your system date and time.")
+
+ER3(SEC_ERROR_CRL_EXPIRED, (SEC_ERROR_BASE + 31),
+ "The CRL for the certificate's issuer has expired. Update it or check your system date and time.")
+
+ER3(SEC_ERROR_CRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 32),
+ "The CRL for the certificate's issuer has an invalid signature.")
+
+ER3(SEC_ERROR_CRL_INVALID, (SEC_ERROR_BASE + 33),
+ "New CRL has an invalid format.")
+
+ER3(SEC_ERROR_EXTENSION_VALUE_INVALID, (SEC_ERROR_BASE + 34),
+ "Certificate extension value is invalid.")
+
+ER3(SEC_ERROR_EXTENSION_NOT_FOUND, (SEC_ERROR_BASE + 35),
+ "Certificate extension not found.")
+
+ER3(SEC_ERROR_CA_CERT_INVALID, (SEC_ERROR_BASE + 36),
+ "Issuer certificate is invalid.")
+
+ER3(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, (SEC_ERROR_BASE + 37),
+ "Certificate path length constraint is invalid.")
+
+ER3(SEC_ERROR_CERT_USAGES_INVALID, (SEC_ERROR_BASE + 38),
+ "Certificate usages field is invalid.")
+
+ER3(SEC_INTERNAL_ONLY, (SEC_ERROR_BASE + 39),
+ "**Internal ONLY module**")
+
+ER3(SEC_ERROR_INVALID_KEY, (SEC_ERROR_BASE + 40),
+ "The key does not support the requested operation.")
+
+ER3(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 41),
+ "Certificate contains unknown critical extension.")
+
+ER3(SEC_ERROR_OLD_CRL, (SEC_ERROR_BASE + 42),
+ "New CRL is not later than the current one.")
+
+ER3(SEC_ERROR_NO_EMAIL_CERT, (SEC_ERROR_BASE + 43),
+ "Not encrypted or signed: you do not yet have an email certificate.")
+
+ER3(SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, (SEC_ERROR_BASE + 44),
+ "Not encrypted: you do not have certificates for each of the recipients.")
+
+ER3(SEC_ERROR_NOT_A_RECIPIENT, (SEC_ERROR_BASE + 45),
+ "Cannot decrypt: you are not a recipient, or matching certificate and \
+private key not found.")
+
+ER3(SEC_ERROR_PKCS7_KEYALG_MISMATCH, (SEC_ERROR_BASE + 46),
+ "Cannot decrypt: key encryption algorithm does not match your certificate.")
+
+ER3(SEC_ERROR_PKCS7_BAD_SIGNATURE, (SEC_ERROR_BASE + 47),
+ "Signature verification failed: no signer found, too many signers found, \
+or improper or corrupted data.")
+
+ER3(SEC_ERROR_UNSUPPORTED_KEYALG, (SEC_ERROR_BASE + 48),
+ "Unsupported or unknown key algorithm.")
+
+ER3(SEC_ERROR_DECRYPTION_DISALLOWED, (SEC_ERROR_BASE + 49),
+ "Cannot decrypt: encrypted using a disallowed algorithm or key size.")
+
+/* Fortezza Alerts */
+ER3(XP_SEC_FORTEZZA_BAD_CARD, (SEC_ERROR_BASE + 50),
+ "Fortezza card has not been properly initialized. \
+Please remove it and return it to your issuer.")
+
+ER3(XP_SEC_FORTEZZA_NO_CARD, (SEC_ERROR_BASE + 51),
+ "No Fortezza cards Found")
+
+ER3(XP_SEC_FORTEZZA_NONE_SELECTED, (SEC_ERROR_BASE + 52),
+ "No Fortezza card selected")
+
+ER3(XP_SEC_FORTEZZA_MORE_INFO, (SEC_ERROR_BASE + 53),
+ "Please select a personality to get more info on")
+
+ER3(XP_SEC_FORTEZZA_PERSON_NOT_FOUND, (SEC_ERROR_BASE + 54),
+ "Personality not found")
+
+ER3(XP_SEC_FORTEZZA_NO_MORE_INFO, (SEC_ERROR_BASE + 55),
+ "No more information on that Personality")
+
+ER3(XP_SEC_FORTEZZA_BAD_PIN, (SEC_ERROR_BASE + 56),
+ "Invalid Pin")
+
+ER3(XP_SEC_FORTEZZA_PERSON_ERROR, (SEC_ERROR_BASE + 57),
+ "Couldn't initialize Fortezza personalities.")
+/* end fortezza alerts. */
+
+ER3(SEC_ERROR_NO_KRL, (SEC_ERROR_BASE + 58),
+ "No KRL for this site's certificate has been found.")
+
+ER3(SEC_ERROR_KRL_EXPIRED, (SEC_ERROR_BASE + 59),
+ "The KRL for this site's certificate has expired.")
+
+ER3(SEC_ERROR_KRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 60),
+ "The KRL for this site's certificate has an invalid signature.")
+
+ER3(SEC_ERROR_REVOKED_KEY, (SEC_ERROR_BASE + 61),
+ "The key for this site's certificate has been revoked.")
+
+ER3(SEC_ERROR_KRL_INVALID, (SEC_ERROR_BASE + 62),
+ "New KRL has an invalid format.")
+
+ER3(SEC_ERROR_NEED_RANDOM, (SEC_ERROR_BASE + 63),
+ "security library: need random data.")
+
+ER3(SEC_ERROR_NO_MODULE, (SEC_ERROR_BASE + 64),
+ "security library: no security module can perform the requested operation.")
+
+ER3(SEC_ERROR_NO_TOKEN, (SEC_ERROR_BASE + 65),
+ "The security card or token does not exist, needs to be initialized, or has been removed.")
+
+ER3(SEC_ERROR_READ_ONLY, (SEC_ERROR_BASE + 66),
+ "security library: read-only database.")
+
+ER3(SEC_ERROR_NO_SLOT_SELECTED, (SEC_ERROR_BASE + 67),
+ "No slot or token was selected.")
+
+ER3(SEC_ERROR_CERT_NICKNAME_COLLISION, (SEC_ERROR_BASE + 68),
+ "A certificate with the same nickname already exists.")
+
+ER3(SEC_ERROR_KEY_NICKNAME_COLLISION, (SEC_ERROR_BASE + 69),
+ "A key with the same nickname already exists.")
+
+ER3(SEC_ERROR_SAFE_NOT_CREATED, (SEC_ERROR_BASE + 70),
+ "error while creating safe object")
+
+ER3(SEC_ERROR_BAGGAGE_NOT_CREATED, (SEC_ERROR_BASE + 71),
+ "error while creating baggage object")
+
+ER3(XP_JAVA_REMOVE_PRINCIPAL_ERROR, (SEC_ERROR_BASE + 72),
+ "Couldn't remove the principal")
+
+ER3(XP_JAVA_DELETE_PRIVILEGE_ERROR, (SEC_ERROR_BASE + 73),
+ "Couldn't delete the privilege")
+
+ER3(XP_JAVA_CERT_NOT_EXISTS_ERROR, (SEC_ERROR_BASE + 74),
+ "This principal doesn't have a certificate")
+
+ER3(SEC_ERROR_BAD_EXPORT_ALGORITHM, (SEC_ERROR_BASE + 75),
+ "Required algorithm is not allowed.")
+
+ER3(SEC_ERROR_EXPORTING_CERTIFICATES, (SEC_ERROR_BASE + 76),
+ "Error attempting to export certificates.")
+
+ER3(SEC_ERROR_IMPORTING_CERTIFICATES, (SEC_ERROR_BASE + 77),
+ "Error attempting to import certificates.")
+
+ER3(SEC_ERROR_PKCS12_DECODING_PFX, (SEC_ERROR_BASE + 78),
+ "Unable to import. Decoding error. File not valid.")
+
+ER3(SEC_ERROR_PKCS12_INVALID_MAC, (SEC_ERROR_BASE + 79),
+ "Unable to import. Invalid MAC. Incorrect password or corrupt file.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, (SEC_ERROR_BASE + 80),
+ "Unable to import. MAC algorithm not supported.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE, (SEC_ERROR_BASE + 81),
+ "Unable to import. Only password integrity and privacy modes supported.")
+
+ER3(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, (SEC_ERROR_BASE + 82),
+ "Unable to import. File structure is corrupt.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, (SEC_ERROR_BASE + 83),
+ "Unable to import. Encryption algorithm not supported.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, (SEC_ERROR_BASE + 84),
+ "Unable to import. File version not supported.")
+
+ER3(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT, (SEC_ERROR_BASE + 85),
+ "Unable to import. Incorrect privacy password.")
+
+ER3(SEC_ERROR_PKCS12_CERT_COLLISION, (SEC_ERROR_BASE + 86),
+ "Unable to import. Same nickname already exists in database.")
+
+ER3(SEC_ERROR_USER_CANCELLED, (SEC_ERROR_BASE + 87),
+ "The user pressed cancel.")
+
+ER3(SEC_ERROR_PKCS12_DUPLICATE_DATA, (SEC_ERROR_BASE + 88),
+ "Not imported, already in database.")
+
+ER3(SEC_ERROR_MESSAGE_SEND_ABORTED, (SEC_ERROR_BASE + 89),
+ "Message not sent.")
+
+ER3(SEC_ERROR_INADEQUATE_KEY_USAGE, (SEC_ERROR_BASE + 90),
+ "Certificate key usage inadequate for attempted operation.")
+
+ER3(SEC_ERROR_INADEQUATE_CERT_TYPE, (SEC_ERROR_BASE + 91),
+ "Certificate type not approved for application.")
+
+ER3(SEC_ERROR_CERT_ADDR_MISMATCH, (SEC_ERROR_BASE + 92),
+ "Address in signing certificate does not match address in message headers.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, (SEC_ERROR_BASE + 93),
+ "Unable to import. Error attempting to import private key.")
+
+ER3(SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, (SEC_ERROR_BASE + 94),
+ "Unable to import. Error attempting to import certificate chain.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, (SEC_ERROR_BASE + 95),
+ "Unable to export. Unable to locate certificate or key by nickname.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, (SEC_ERROR_BASE + 96),
+ "Unable to export. Private Key could not be located and exported.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_WRITE, (SEC_ERROR_BASE + 97),
+ "Unable to export. Unable to write the export file.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_READ, (SEC_ERROR_BASE + 98),
+ "Unable to import. Unable to read the import file.")
+
+ER3(SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, (SEC_ERROR_BASE + 99),
+ "Unable to export. Key database corrupt or deleted.")
+
+ER3(SEC_ERROR_KEYGEN_FAIL, (SEC_ERROR_BASE + 100),
+ "Unable to generate public/private key pair.")
+
+ER3(SEC_ERROR_INVALID_PASSWORD, (SEC_ERROR_BASE + 101),
+ "Password entered is invalid. Please pick a different one.")
+
+ER3(SEC_ERROR_RETRY_OLD_PASSWORD, (SEC_ERROR_BASE + 102),
+ "Old password entered incorrectly. Please try again.")
+
+ER3(SEC_ERROR_BAD_NICKNAME, (SEC_ERROR_BASE + 103),
+ "Certificate nickname already in use.")
+
+ER3(SEC_ERROR_NOT_FORTEZZA_ISSUER, (SEC_ERROR_BASE + 104),
+ "Peer FORTEZZA chain has a non-FORTEZZA Certificate.")
+
+ER3(SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY, (SEC_ERROR_BASE + 105),
+ "A sensitive key cannot be moved to the slot where it is needed.")
+
+ER3(SEC_ERROR_JS_INVALID_MODULE_NAME, (SEC_ERROR_BASE + 106),
+ "Invalid module name.")
+
+ER3(SEC_ERROR_JS_INVALID_DLL, (SEC_ERROR_BASE + 107),
+ "Invalid module path/filename")
+
+ER3(SEC_ERROR_JS_ADD_MOD_FAILURE, (SEC_ERROR_BASE + 108),
+ "Unable to add module")
+
+ER3(SEC_ERROR_JS_DEL_MOD_FAILURE, (SEC_ERROR_BASE + 109),
+ "Unable to delete module")
+
+ER3(SEC_ERROR_OLD_KRL, (SEC_ERROR_BASE + 110),
+ "New KRL is not later than the current one.")
+
+ER3(SEC_ERROR_CKL_CONFLICT, (SEC_ERROR_BASE + 111),
+ "New CKL has different issuer than current CKL. Delete current CKL.")
+
+ER3(SEC_ERROR_CERT_NOT_IN_NAME_SPACE, (SEC_ERROR_BASE + 112),
+ "The Certifying Authority for this certificate is not permitted to issue a \
+certificate with this name.")
+
+ER3(SEC_ERROR_KRL_NOT_YET_VALID, (SEC_ERROR_BASE + 113),
+ "The key revocation list for this certificate is not yet valid.")
+
+ER3(SEC_ERROR_CRL_NOT_YET_VALID, (SEC_ERROR_BASE + 114),
+ "The certificate revocation list for this certificate is not yet valid.")
+
+ER3(SEC_ERROR_UNKNOWN_CERT, (SEC_ERROR_BASE + 115),
+ "The requested certificate could not be found.")
+
+ER3(SEC_ERROR_UNKNOWN_SIGNER, (SEC_ERROR_BASE + 116),
+ "The signer's certificate could not be found.")
+
+ER3(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, (SEC_ERROR_BASE + 117),
+ "The location for the certificate status server has invalid format.")
+
+ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, (SEC_ERROR_BASE + 118),
+ "The OCSP response cannot be fully decoded; it is of an unknown type.")
+
+ER3(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, (SEC_ERROR_BASE + 119),
+ "The OCSP server returned unexpected/invalid HTTP data.")
+
+ER3(SEC_ERROR_OCSP_MALFORMED_REQUEST, (SEC_ERROR_BASE + 120),
+ "The OCSP server found the request to be corrupted or improperly formed.")
+
+ER3(SEC_ERROR_OCSP_SERVER_ERROR, (SEC_ERROR_BASE + 121),
+ "The OCSP server experienced an internal error.")
+
+ER3(SEC_ERROR_OCSP_TRY_SERVER_LATER, (SEC_ERROR_BASE + 122),
+ "The OCSP server suggests trying again later.")
+
+ER3(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, (SEC_ERROR_BASE + 123),
+ "The OCSP server requires a signature on this request.")
+
+ER3(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, (SEC_ERROR_BASE + 124),
+ "The OCSP server has refused this request as unauthorized.")
+
+ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, (SEC_ERROR_BASE + 125),
+ "The OCSP server returned an unrecognizable status.")
+
+ER3(SEC_ERROR_OCSP_UNKNOWN_CERT, (SEC_ERROR_BASE + 126),
+ "The OCSP server has no status for the certificate.")
+
+ER3(SEC_ERROR_OCSP_NOT_ENABLED, (SEC_ERROR_BASE + 127),
+ "You must enable OCSP before performing this operation.")
+
+ER3(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, (SEC_ERROR_BASE + 128),
+ "You must set the OCSP default responder before performing this operation.")
+
+ER3(SEC_ERROR_OCSP_MALFORMED_RESPONSE, (SEC_ERROR_BASE + 129),
+ "The response from the OCSP server was corrupted or improperly formed.")
+
+ER3(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, (SEC_ERROR_BASE + 130),
+ "The signer of the OCSP response is not authorized to give status for \
+this certificate.")
+
+ER3(SEC_ERROR_OCSP_FUTURE_RESPONSE, (SEC_ERROR_BASE + 131),
+ "The OCSP response is not yet valid (contains a date in the future).")
+
+ER3(SEC_ERROR_OCSP_OLD_RESPONSE, (SEC_ERROR_BASE + 132),
+ "The OCSP response contains out-of-date information.")
+
+ER3(SEC_ERROR_DIGEST_NOT_FOUND, (SEC_ERROR_BASE + 133),
+ "The CMS or PKCS #7 Digest was not found in signed message.")
+
+ER3(SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE, (SEC_ERROR_BASE + 134),
+ "The CMS or PKCS #7 Message type is unsupported.")
+
+ER3(SEC_ERROR_MODULE_STUCK, (SEC_ERROR_BASE + 135),
+ "PKCS #11 module could not be removed because it is still in use.")
+
+ER3(SEC_ERROR_BAD_TEMPLATE, (SEC_ERROR_BASE + 136),
+ "Could not decode ASN.1 data. Specified template was invalid.")
+
+ER3(SEC_ERROR_CRL_NOT_FOUND, (SEC_ERROR_BASE + 137),
+ "No matching CRL was found.")
+
+ER3(SEC_ERROR_REUSED_ISSUER_AND_SERIAL, (SEC_ERROR_BASE + 138),
+ "You are attempting to import a cert with the same issuer/serial as \
+an existing cert, but that is not the same cert.")
+
+ER3(SEC_ERROR_BUSY, (SEC_ERROR_BASE + 139),
+ "NSS could not shutdown. Objects are still in use.")
+
+ER3(SEC_ERROR_EXTRA_INPUT, (SEC_ERROR_BASE + 140),
+ "DER-encoded message contained extra unused data.")
+
+ER3(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE, (SEC_ERROR_BASE + 141),
+ "Unsupported elliptic curve.")
+
+ER3(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM, (SEC_ERROR_BASE + 142),
+ "Unsupported elliptic curve point form.")
+
+ER3(SEC_ERROR_UNRECOGNIZED_OID, (SEC_ERROR_BASE + 143),
+ "Unrecognized Object Identifier.")
+
+ER3(SEC_ERROR_OCSP_INVALID_SIGNING_CERT, (SEC_ERROR_BASE + 144),
+ "Invalid OCSP signing certificate in OCSP response.")
+
+ER3(SEC_ERROR_REVOKED_CERTIFICATE_CRL, (SEC_ERROR_BASE + 145),
+ "Certificate is revoked in issuer's certificate revocation list.")
+
+ER3(SEC_ERROR_REVOKED_CERTIFICATE_OCSP, (SEC_ERROR_BASE + 146),
+ "Issuer's OCSP responder reports certificate is revoked.")
+
+ER3(SEC_ERROR_CRL_INVALID_VERSION, (SEC_ERROR_BASE + 147),
+ "Issuer's Certificate Revocation List has an unknown version number.")
+
+ER3(SEC_ERROR_CRL_V1_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 148),
+ "Issuer's V1 Certificate Revocation List has a critical extension.")
+
+ER3(SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 149),
+ "Issuer's V2 Certificate Revocation List has an unknown critical extension.")
+
+ER3(SEC_ERROR_UNKNOWN_OBJECT_TYPE, (SEC_ERROR_BASE + 150),
+ "Unknown object type specified.")
+
+ER3(SEC_ERROR_INCOMPATIBLE_PKCS11, (SEC_ERROR_BASE + 151),
+ "PKCS #11 driver violates the spec in an incompatible way.")
+
+ER3(SEC_ERROR_NO_EVENT, (SEC_ERROR_BASE + 152),
+ "No new slot event is available at this time.")
+
+ER3(SEC_ERROR_CRL_ALREADY_EXISTS, (SEC_ERROR_BASE + 153),
+ "CRL already exists.")
+
+ER3(SEC_ERROR_NOT_INITIALIZED, (SEC_ERROR_BASE + 154),
+ "NSS is not initialized.")
+
+ER3(SEC_ERROR_TOKEN_NOT_LOGGED_IN, (SEC_ERROR_BASE + 155),
+ "The operation failed because the PKCS#11 token is not logged in.")
+
+ER3(SEC_ERROR_OCSP_RESPONDER_CERT_INVALID, (SEC_ERROR_BASE + 156),
+ "Configured OCSP responder's certificate is invalid.")
+
+ER3(SEC_ERROR_OCSP_BAD_SIGNATURE, (SEC_ERROR_BASE + 157),
+ "OCSP response has an invalid signature.")
+
+ER3(SEC_ERROR_OUT_OF_SEARCH_LIMITS, (SEC_ERROR_BASE + 158),
+ "Cert validation search is out of search limits")
+
+ER3(SEC_ERROR_INVALID_POLICY_MAPPING, (SEC_ERROR_BASE + 159),
+ "Policy mapping contains anypolicy")
+
+ER3(SEC_ERROR_POLICY_VALIDATION_FAILED, (SEC_ERROR_BASE + 160),
+ "Cert chain fails policy validation")
+
+ER3(SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE, (SEC_ERROR_BASE + 161),
+ "Unknown location type in cert AIA extension")
+
+ER3(SEC_ERROR_BAD_HTTP_RESPONSE, (SEC_ERROR_BASE + 162),
+ "Server returned bad HTTP response")
+
+ER3(SEC_ERROR_BAD_LDAP_RESPONSE, (SEC_ERROR_BASE + 163),
+ "Server returned bad LDAP response")
+
+ER3(SEC_ERROR_FAILED_TO_ENCODE_DATA, (SEC_ERROR_BASE + 164),
+ "Failed to encode data with ASN1 encoder")
+
+ER3(SEC_ERROR_BAD_INFO_ACCESS_LOCATION, (SEC_ERROR_BASE + 165),
+ "Bad information access location in cert extension")
+
+ER3(SEC_ERROR_LIBPKIX_INTERNAL, (SEC_ERROR_BASE + 166),
+ "Libpkix internal error occurred during cert validation.")
+
+ER3(SEC_ERROR_PKCS11_GENERAL_ERROR, (SEC_ERROR_BASE + 167),
+ "A PKCS #11 module returned CKR_GENERAL_ERROR, indicating that an unrecoverable error has occurred.")
+
+ER3(SEC_ERROR_PKCS11_FUNCTION_FAILED, (SEC_ERROR_BASE + 168),
+ "A PKCS #11 module returned CKR_FUNCTION_FAILED, indicating that the requested function could not be performed. Trying the same operation again might succeed.")
+
+ER3(SEC_ERROR_PKCS11_DEVICE_ERROR, (SEC_ERROR_BASE + 169),
+ "A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot.")
+
+ER3(SEC_ERROR_BAD_INFO_ACCESS_METHOD, (SEC_ERROR_BASE + 170),
+ "Unknown information access method in certificate extension.")
+
+ER3(SEC_ERROR_CRL_IMPORT_FAILED, (SEC_ERROR_BASE + 171),
+ "Error attempting to import a CRL.")
+
+ER3(SEC_ERROR_EXPIRED_PASSWORD, (SEC_ERROR_BASE + 172),
+ "The password expired.")
+
+ER3(SEC_ERROR_LOCKED_PASSWORD, (SEC_ERROR_BASE + 173),
+ "The password is locked.")
+
+ER3(SEC_ERROR_UNKNOWN_PKCS11_ERROR, (SEC_ERROR_BASE + 174),
+ "Unknown PKCS #11 error.")
+
+ER3(SEC_ERROR_BAD_CRL_DP_URL, (SEC_ERROR_BASE + 175),
+ "Invalid or unsupported URL in CRL distribution point name.")
+
+ER3(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED, (SEC_ERROR_BASE + 176),
+ "The certificate was signed using a signature algorithm that is disabled because it is not secure.")
+
+ER3(SEC_ERROR_LEGACY_DATABASE, (SEC_ERROR_BASE + 177),
+ "The certificate/key database is in an old, unsupported format.")
+
+ER3(SEC_ERROR_APPLICATION_CALLBACK_ERROR, (SEC_ERROR_BASE + 178),
+ "The certificate was rejected by extra checks in the application.")
+
+ER3(SEC_ERROR_INVALID_STATE, (SEC_ERROR_BASE + 179),
+ "The attempted operation is invalid for the current state.")
+
+ER3(SEC_ERROR_POLICY_LOCKED, (SEC_ERROR_BASE + 180),
+ "Could not change the policy because the policy is now locked.")
+
+ER3(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED, (SEC_ERROR_BASE + 181),
+ "Could not create or verify a signature using a signature algorithm that is disabled because it is not secure.")
+
+ER3(SEC_ERROR_ALGORITHM_MISMATCH, (SEC_ERROR_BASE + 182),
+ "The signature algorithm in the signature field of the certificate does not match the algorithm in its signatureAlgorithm field.")
+
+ER3(SEC_ERROR_CERTIFICATE_COMPRESSION_ALGORITHM_NOT_SUPPORTED, (SEC_ERROR_BASE + 183),
+ "The certificate was encoded using an unsupported certificate compression algorithm.")
+
+ER3(SEC_ERROR_UNEXPECTED_COMPRESSED_CERTIFICATE, (SEC_ERROR_BASE + 184),
+ "Received unexpected compressed certificate.")
diff --git a/security/nss/lib/util/base64.h b/security/nss/lib/util/base64.h
new file mode 100644
index 0000000000..ddc2db600b
--- /dev/null
+++ b/security/nss/lib/util/base64.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/. */
+
+/*
+ * base64.h - prototypes for base64 encoding/decoding
+ * Note: These functions are deprecated; see nssb64.h for new routines.
+ */
+#ifndef _BASE64_H_
+#define _BASE64_H_
+
+#include "utilrename.h"
+#include "seccomon.h"
+
+SEC_BEGIN_PROTOS
+
+/*
+** Return an PORT_Alloc'd ascii string which is the base64 encoded
+** version of the input string.
+*/
+extern char *BTOA_DataToAscii(const unsigned char *data, unsigned int len);
+
+/*
+** Return an PORT_Alloc'd string which is the base64 decoded version
+** of the input string; set *lenp to the length of the returned data.
+*/
+extern unsigned char *ATOB_AsciiToData(const char *string, unsigned int *lenp);
+
+/*
+** Convert from ascii to binary encoding of an item.
+*/
+extern SECStatus ATOB_ConvertAsciiToItem(SECItem *binary_item, const char *ascii);
+
+/*
+** Convert from binary encoding of an item to ascii.
+*/
+extern char *BTOA_ConvertItemToAscii(SECItem *binary_item);
+
+SEC_END_PROTOS
+
+#endif /* _BASE64_H_ */
diff --git a/security/nss/lib/util/ciferfam.h b/security/nss/lib/util/ciferfam.h
new file mode 100644
index 0000000000..68caa4f8bb
--- /dev/null
+++ b/security/nss/lib/util/ciferfam.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/. */
+
+/*
+ * ciferfam.h - cipher familie IDs used for configuring ciphers for export
+ * control
+ */
+
+#ifndef _CIFERFAM_H_
+#define _CIFERFAM_H_
+
+#include "utilrename.h"
+/* Cipher Suite "Families" */
+#define CIPHER_FAMILY_PKCS12 "PKCS12"
+#define CIPHER_FAMILY_SMIME "SMIME"
+#define CIPHER_FAMILY_SSL2 "SSLv2" /* deprecated */
+#define CIPHER_FAMILY_SSL3 "SSLv3"
+#define CIPHER_FAMILY_SSL "SSL"
+#define CIPHER_FAMILY_ALL ""
+#define CIPHER_FAMILY_UNKNOWN "UNKNOWN"
+
+#define CIPHER_FAMILYID_MASK 0xFFFF0000L
+#define CIPHER_FAMILYID_SSL 0x00000000L
+#define CIPHER_FAMILYID_SMIME 0x00010000L
+#define CIPHER_FAMILYID_PKCS12 0x00020000L
+
+/* SMIME "Cipher Suites" */
+/*
+ * Note that it is assumed that the cipher number itself can be used
+ * as a bit position in a mask, and that mask is currently 32 bits wide.
+ * So, if you want to add a cipher that is greater than 0037, secmime.c
+ * needs to be made smarter at the same time.
+ */
+#define SMIME_RC2_CBC_40 (CIPHER_FAMILYID_SMIME | 0001)
+#define SMIME_RC2_CBC_64 (CIPHER_FAMILYID_SMIME | 0002)
+#define SMIME_RC2_CBC_128 (CIPHER_FAMILYID_SMIME | 0003)
+#define SMIME_DES_CBC_56 (CIPHER_FAMILYID_SMIME | 0011)
+#define SMIME_DES_EDE3_168 (CIPHER_FAMILYID_SMIME | 0012)
+#define SMIME_AES_CBC_128 (CIPHER_FAMILYID_SMIME | 0013)
+#define SMIME_AES_CBC_256 (CIPHER_FAMILYID_SMIME | 0014)
+#define SMIME_RC5PAD_64_16_40 (CIPHER_FAMILYID_SMIME | 0021)
+#define SMIME_RC5PAD_64_16_64 (CIPHER_FAMILYID_SMIME | 0022)
+#define SMIME_RC5PAD_64_16_128 (CIPHER_FAMILYID_SMIME | 0023)
+#define SMIME_FORTEZZA (CIPHER_FAMILYID_SMIME | 0031)
+
+/* PKCS12 "Cipher Suites" */
+
+#define PKCS12_RC2_CBC_40 (CIPHER_FAMILYID_PKCS12 | 0001)
+#define PKCS12_RC2_CBC_128 (CIPHER_FAMILYID_PKCS12 | 0002)
+#define PKCS12_RC4_40 (CIPHER_FAMILYID_PKCS12 | 0011)
+#define PKCS12_RC4_128 (CIPHER_FAMILYID_PKCS12 | 0012)
+#define PKCS12_DES_56 (CIPHER_FAMILYID_PKCS12 | 0021)
+#define PKCS12_DES_EDE3_168 (CIPHER_FAMILYID_PKCS12 | 0022)
+#define PKCS12_AES_CBC_128 (CIPHER_FAMILYID_PKCS12 | 0031)
+#define PKCS12_AES_CBC_192 (CIPHER_FAMILYID_PKCS12 | 0032)
+#define PKCS12_AES_CBC_256 (CIPHER_FAMILYID_PKCS12 | 0033)
+
+/* SMIME version numbers are negative, to avoid colliding with SSL versions */
+#define SMIME_LIBRARY_VERSION_1_0 -0x0100
+
+#endif /* _CIFERFAM_H_ */
diff --git a/security/nss/lib/util/config.mk b/security/nss/lib/util/config.mk
new file mode 100644
index 0000000000..af42a2ee9e
--- /dev/null
+++ b/security/nss/lib/util/config.mk
@@ -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/.
+
+# can't do this in manifest.mn because OS_TARGET isn't defined there.
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+
+ifdef NS_USE_GCC
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib \
+ -L$(NSPR_LIB_DIR) \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4\
+ $(NULL)
+else # ! NS_USE_GCC
+EXTRA_SHARED_LIBS += \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
+ $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
+ $(NULL)
+endif # NS_USE_GCC
+
+else
+
+# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
+# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib \
+ -L$(NSPR_LIB_DIR) \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+
+endif
+
diff --git a/security/nss/lib/util/derdec.c b/security/nss/lib/util/derdec.c
new file mode 100644
index 0000000000..2e3312b231
--- /dev/null
+++ b/security/nss/lib/util/derdec.c
@@ -0,0 +1,189 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secder.h"
+#include "secerr.h"
+
+static PRUint32
+der_indefinite_length(unsigned char *buf, unsigned char *end)
+{
+ PRUint32 len, ret, dataLen;
+ unsigned char tag, lenCode;
+ int dataLenLen;
+
+ len = 0;
+ while (1) {
+ if ((buf + 2) > end) {
+ return (0);
+ }
+
+ tag = *buf++;
+ lenCode = *buf++;
+ len += 2;
+
+ if ((tag == 0) && (lenCode == 0)) {
+ return (len);
+ }
+
+ if (lenCode == 0x80) { /* indefinite length */
+ ret = der_indefinite_length(buf, end); /* recurse to find length */
+ if (ret == 0)
+ return 0;
+ len += ret;
+ buf += ret;
+ } else { /* definite length */
+ if (lenCode & 0x80) {
+ /* Length of data is in multibyte format */
+ dataLenLen = lenCode & 0x7f;
+ switch (dataLenLen) {
+ case 1:
+ dataLen = buf[0];
+ break;
+ case 2:
+ dataLen = (buf[0] << 8) | buf[1];
+ break;
+ case 3:
+ dataLen = ((unsigned long)buf[0] << 16) | (buf[1] << 8) | buf[2];
+ break;
+ case 4:
+ dataLen = ((unsigned long)buf[0] << 24) |
+ ((unsigned long)buf[1] << 16) | (buf[2] << 8) | buf[3];
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ } else {
+ /* Length of data is in single byte */
+ dataLen = lenCode;
+ dataLenLen = 0;
+ }
+
+ /* skip this item */
+ buf = buf + dataLenLen + dataLen;
+ len = len + dataLenLen + dataLen;
+ }
+ }
+}
+
+/*
+** Capture the next thing in the buffer.
+** Returns the length of the header and the length of the contents.
+*/
+static SECStatus
+der_capture(unsigned char *buf, unsigned char *end,
+ int *header_len_p, PRUint32 *contents_len_p)
+{
+ unsigned char *bp;
+ unsigned char whole_tag;
+ PRUint32 contents_len;
+ int tag_number;
+
+ if ((buf + 2) > end) {
+ *header_len_p = 0;
+ *contents_len_p = 0;
+ if (buf == end)
+ return SECSuccess;
+ return SECFailure;
+ }
+
+ bp = buf;
+
+ /* Get tag and verify that it is ok. */
+ whole_tag = *bp++;
+ tag_number = whole_tag & DER_TAGNUM_MASK;
+
+ /*
+ * XXX This code does not (yet) handle the high-tag-number form!
+ */
+ if (tag_number == DER_HIGH_TAG_NUMBER) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ if ((whole_tag & DER_CLASS_MASK) == DER_UNIVERSAL) {
+ /* Check that the universal tag number is one we implement. */
+ switch (tag_number) {
+ case DER_BOOLEAN:
+ case DER_INTEGER:
+ case DER_BIT_STRING:
+ case DER_OCTET_STRING:
+ case DER_NULL:
+ case DER_OBJECT_ID:
+ case DER_SEQUENCE:
+ case DER_SET:
+ case DER_PRINTABLE_STRING:
+ case DER_T61_STRING:
+ case DER_IA5_STRING:
+ case DER_VISIBLE_STRING:
+ case DER_UTC_TIME:
+ case 0: /* end-of-contents tag */
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ }
+
+ /*
+ * Get first byte of length code (might contain entire length, might not).
+ */
+ contents_len = *bp++;
+
+ /*
+ * If the high bit is set, then the length is in multibyte format,
+ * or the thing has an indefinite-length.
+ */
+ if (contents_len & 0x80) {
+ int bytes_of_encoded_len;
+
+ bytes_of_encoded_len = contents_len & 0x7f;
+ contents_len = 0;
+
+ switch (bytes_of_encoded_len) {
+ case 4:
+ contents_len |= *bp++;
+ contents_len <<= 8;
+ /* fallthru */
+ case 3:
+ contents_len |= *bp++;
+ contents_len <<= 8;
+ /* fallthru */
+ case 2:
+ contents_len |= *bp++;
+ contents_len <<= 8;
+ /* fallthru */
+ case 1:
+ contents_len |= *bp++;
+ break;
+
+ case 0:
+ contents_len = der_indefinite_length(bp, end);
+ if (contents_len)
+ break;
+ /* fallthru */
+ default:
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ }
+
+ if ((bp + contents_len) > end) {
+ /* Ran past end of buffer */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ *header_len_p = (int)(bp - buf);
+ *contents_len_p = contents_len;
+
+ return SECSuccess;
+}
+
+SECStatus
+DER_Lengths(SECItem *item, int *header_len_p, PRUint32 *contents_len_p)
+{
+ return (der_capture(item->data, &item->data[item->len], header_len_p,
+ contents_len_p));
+}
diff --git a/security/nss/lib/util/derenc.c b/security/nss/lib/util/derenc.c
new file mode 100644
index 0000000000..da9fc4e649
--- /dev/null
+++ b/security/nss/lib/util/derenc.c
@@ -0,0 +1,460 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secder.h"
+#include "secerr.h"
+
+#if 0
+/*
+ * Generic templates for individual/simple items.
+ */
+
+DERTemplate SECAnyTemplate[] = {
+ { DER_ANY,
+ 0, NULL, sizeof(SECItem) }
+};
+
+DERTemplate SECBitStringTemplate[] = {
+ { DER_BIT_STRING,
+ 0, NULL, sizeof(SECItem) }
+};
+
+DERTemplate SECBooleanTemplate[] = {
+ { DER_BOOLEAN,
+ 0, NULL, sizeof(SECItem) }
+};
+
+DERTemplate SECIA5StringTemplate[] = {
+ { DER_IA5_STRING,
+ 0, NULL, sizeof(SECItem) }
+};
+
+DERTemplate SECIntegerTemplate[] = {
+ { DER_INTEGER,
+ 0, NULL, sizeof(SECItem) }
+};
+
+DERTemplate SECNullTemplate[] = {
+ { DER_NULL,
+ 0, NULL, sizeof(SECItem) }
+};
+
+DERTemplate SECObjectIDTemplate[] = {
+ { DER_OBJECT_ID,
+ 0, NULL, sizeof(SECItem) }
+};
+
+DERTemplate SECOctetStringTemplate[] = {
+ { DER_OCTET_STRING,
+ 0, NULL, sizeof(SECItem) }
+};
+
+DERTemplate SECPrintableStringTemplate[] = {
+ { DER_PRINTABLE_STRING,
+ 0, NULL, sizeof(SECItem) }
+};
+
+DERTemplate SECT61StringTemplate[] = {
+ { DER_T61_STRING,
+ 0, NULL, sizeof(SECItem) }
+};
+
+DERTemplate SECUTCTimeTemplate[] = {
+ { DER_UTC_TIME,
+ 0, NULL, sizeof(SECItem) }
+};
+
+#endif
+
+static int
+header_length(DERTemplate *dtemplate, PRUint32 contents_len)
+{
+ PRUint32 len;
+ unsigned long encode_kind, under_kind;
+ PRBool explicit, optional, universal;
+
+ encode_kind = dtemplate->kind;
+
+ explicit = (encode_kind & DER_EXPLICIT) ? PR_TRUE : PR_FALSE;
+ optional = (encode_kind & DER_OPTIONAL) ? PR_TRUE : PR_FALSE;
+ universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL)
+ ? PR_TRUE
+ : PR_FALSE;
+
+ PORT_Assert(!(explicit && universal)); /* bad templates */
+
+ if (encode_kind & DER_POINTER) {
+ if (dtemplate->sub != NULL) {
+ under_kind = dtemplate->sub->kind;
+ if (universal) {
+ encode_kind = under_kind;
+ }
+ } else if (universal) {
+ under_kind = encode_kind & ~DER_POINTER;
+ } else {
+ under_kind = dtemplate->arg;
+ }
+ } else if (encode_kind & DER_INLINE) {
+ PORT_Assert(dtemplate->sub != NULL);
+ under_kind = dtemplate->sub->kind;
+ if (universal) {
+ encode_kind = under_kind;
+ }
+ } else if (universal) {
+ under_kind = encode_kind;
+ } else {
+ under_kind = dtemplate->arg;
+ }
+
+ /* This is only used in decoding; it plays no part in encoding. */
+ if (under_kind & DER_DERPTR)
+ return 0;
+
+ /* No header at all for an "empty" optional. */
+ if ((contents_len == 0) && optional)
+ return 0;
+
+ /* And no header for a full DER_ANY. */
+ if (encode_kind & DER_ANY)
+ return 0;
+
+ /*
+ * The common case: one octet for identifier and as many octets
+ * as necessary to hold the content length.
+ */
+ len = 1 + DER_LengthLength(contents_len);
+
+ /* Account for the explicit wrapper, if necessary. */
+ if (explicit) {
+#if 0 /* \
+ * Well, I was trying to do something useful, but these \
+ * assertions are too restrictive on valid templates. \
+ * I wanted to make sure that the top-level "kind" of \
+ * a template does not also specify DER_EXPLICIT, which \
+ * should only modify a component field. Maybe later \
+ * I can figure out a better way to detect such a problem, \
+ * but for now I must remove these checks altogether. \
+ */
+ /*
+ * This modifier applies only to components of a set or sequence;
+ * it should never be used on a set/sequence itself -- confirm.
+ */
+ PORT_Assert (under_kind != DER_SEQUENCE);
+ PORT_Assert (under_kind != DER_SET);
+#endif
+
+ len += 1 + DER_LengthLength(len + contents_len);
+ }
+
+ return len;
+}
+
+static PRUint32
+contents_length(DERTemplate *dtemplate, void *src)
+{
+ PRUint32 len;
+ unsigned long encode_kind, under_kind;
+ PRBool universal;
+
+ PORT_Assert(src != NULL);
+
+ encode_kind = dtemplate->kind;
+
+ universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL)
+ ? PR_TRUE
+ : PR_FALSE;
+ encode_kind &= ~DER_OPTIONAL;
+
+ if (encode_kind & DER_POINTER) {
+ src = *(void **)src;
+ if (src == NULL) {
+ return 0;
+ }
+ if (dtemplate->sub != NULL) {
+ dtemplate = dtemplate->sub;
+ under_kind = dtemplate->kind;
+ src = (void *)((char *)src + dtemplate->offset);
+ } else if (universal) {
+ under_kind = encode_kind & ~DER_POINTER;
+ } else {
+ under_kind = dtemplate->arg;
+ }
+ } else if (encode_kind & DER_INLINE) {
+ PORT_Assert(dtemplate->sub != NULL);
+ dtemplate = dtemplate->sub;
+ under_kind = dtemplate->kind;
+ src = (void *)((char *)src + dtemplate->offset);
+ } else if (universal) {
+ under_kind = encode_kind;
+ } else {
+ under_kind = dtemplate->arg;
+ }
+
+ /* Having any of these bits is not expected here... */
+ PORT_Assert((under_kind & (DER_EXPLICIT | DER_INLINE | DER_OPTIONAL | DER_POINTER | DER_SKIP)) == 0);
+
+ /* This is only used in decoding; it plays no part in encoding. */
+ if (under_kind & DER_DERPTR)
+ return 0;
+
+ if (under_kind & DER_INDEFINITE) {
+ PRUint32 sub_len;
+ void **indp = *(void ***)src;
+
+ if (indp == NULL)
+ return 0;
+
+ len = 0;
+ under_kind &= ~DER_INDEFINITE;
+
+ if (under_kind == DER_SET || under_kind == DER_SEQUENCE) {
+ DERTemplate *tmpt = dtemplate->sub;
+ PORT_Assert(tmpt != NULL);
+
+ for (; *indp != NULL; indp++) {
+ void *sub_src = (void *)((char *)(*indp) + tmpt->offset);
+ sub_len = contents_length(tmpt, sub_src);
+ len += sub_len + header_length(tmpt, sub_len);
+ }
+ } else {
+ /*
+ * XXX Lisa is not sure this code (for handling, for example,
+ * DER_INDEFINITE | DER_OCTET_STRING) is right.
+ */
+ for (; *indp != NULL; indp++) {
+ SECItem *item = (SECItem *)(*indp);
+ sub_len = item->len;
+ if (under_kind == DER_BIT_STRING) {
+ sub_len = (sub_len + 7) >> 3;
+ /* bit string contents involve an extra octet */
+ if (sub_len)
+ sub_len++;
+ }
+ if (under_kind != DER_ANY)
+ len += 1 + DER_LengthLength(sub_len);
+ }
+ }
+
+ return len;
+ }
+
+ switch (under_kind) {
+ case DER_SEQUENCE:
+ case DER_SET: {
+ DERTemplate *tmpt;
+ void *sub_src;
+ PRUint32 sub_len;
+
+ len = 0;
+ for (tmpt = dtemplate + 1; tmpt->kind; tmpt++) {
+ sub_src = (void *)((char *)src + tmpt->offset);
+ sub_len = contents_length(tmpt, sub_src);
+ len += sub_len + header_length(tmpt, sub_len);
+ }
+ } break;
+
+ case DER_BIT_STRING:
+ len = (((SECItem *)src)->len + 7) >> 3;
+ /* bit string contents involve an extra octet */
+ if (len)
+ len++;
+ break;
+
+ default:
+ len = ((SECItem *)src)->len;
+ break;
+ }
+
+ return len;
+}
+
+static unsigned char *
+der_encode(unsigned char *buf, DERTemplate *dtemplate, void *src)
+{
+ int header_len;
+ PRUint32 contents_len;
+ unsigned long encode_kind, under_kind;
+ PRBool explicit, universal;
+
+ /*
+ * First figure out how long the encoding will be. Do this by
+ * traversing the template from top to bottom and accumulating
+ * the length of each leaf item.
+ */
+ contents_len = contents_length(dtemplate, src);
+ header_len = header_length(dtemplate, contents_len);
+
+ /*
+ * Enough smarts was involved already, so that if both the
+ * header and the contents have a length of zero, then we
+ * are not doing any encoding for this element.
+ */
+ if (header_len == 0 && contents_len == 0)
+ return buf;
+
+ encode_kind = dtemplate->kind;
+
+ explicit = (encode_kind & DER_EXPLICIT) ? PR_TRUE : PR_FALSE;
+ encode_kind &= ~DER_OPTIONAL;
+ universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL)
+ ? PR_TRUE
+ : PR_FALSE;
+
+ if (encode_kind & DER_POINTER) {
+ if (contents_len) {
+ src = *(void **)src;
+ PORT_Assert(src != NULL);
+ }
+ if (dtemplate->sub != NULL) {
+ dtemplate = dtemplate->sub;
+ under_kind = dtemplate->kind;
+ if (universal) {
+ encode_kind = under_kind;
+ }
+ src = (void *)((char *)src + dtemplate->offset);
+ } else if (universal) {
+ under_kind = encode_kind & ~DER_POINTER;
+ } else {
+ under_kind = dtemplate->arg;
+ }
+ } else if (encode_kind & DER_INLINE) {
+ dtemplate = dtemplate->sub;
+ under_kind = dtemplate->kind;
+ if (universal) {
+ encode_kind = under_kind;
+ }
+ src = (void *)((char *)src + dtemplate->offset);
+ } else if (universal) {
+ under_kind = encode_kind;
+ } else {
+ under_kind = dtemplate->arg;
+ }
+
+ if (explicit) {
+ buf = DER_StoreHeader(buf, encode_kind,
+ (1 + DER_LengthLength(contents_len) + contents_len));
+ encode_kind = under_kind;
+ }
+
+ if ((encode_kind & DER_ANY) == 0) { /* DER_ANY already contains header */
+ buf = DER_StoreHeader(buf, encode_kind, contents_len);
+ }
+
+ /* If no real contents to encode, then we are done. */
+ if (contents_len == 0)
+ return buf;
+
+ if (under_kind & DER_INDEFINITE) {
+ void **indp;
+
+ indp = *(void ***)src;
+ PORT_Assert(indp != NULL);
+
+ under_kind &= ~DER_INDEFINITE;
+ if (under_kind == DER_SET || under_kind == DER_SEQUENCE) {
+ DERTemplate *tmpt = dtemplate->sub;
+ PORT_Assert(tmpt != NULL);
+ for (; *indp != NULL; indp++) {
+ void *sub_src = (void *)((char *)(*indp) + tmpt->offset);
+ buf = der_encode(buf, tmpt, sub_src);
+ }
+ } else {
+ for (; *indp != NULL; indp++) {
+ SECItem *item;
+ int sub_len;
+
+ item = (SECItem *)(*indp);
+ sub_len = item->len;
+ if (under_kind == DER_BIT_STRING) {
+ if (sub_len) {
+ int rem;
+
+ sub_len = (sub_len + 7) >> 3;
+ buf = DER_StoreHeader(buf, under_kind, sub_len + 1);
+ rem = (sub_len << 3) - item->len;
+ *buf++ = rem; /* remaining bits */
+ } else {
+ buf = DER_StoreHeader(buf, under_kind, 0);
+ }
+ } else if (under_kind != DER_ANY) {
+ buf = DER_StoreHeader(buf, under_kind, sub_len);
+ }
+ PORT_Memcpy(buf, item->data, sub_len);
+ buf += sub_len;
+ }
+ }
+ return buf;
+ }
+
+ switch (under_kind) {
+ case DER_SEQUENCE:
+ case DER_SET: {
+ DERTemplate *tmpt;
+ void *sub_src;
+
+ for (tmpt = dtemplate + 1; tmpt->kind; tmpt++) {
+ sub_src = (void *)((char *)src + tmpt->offset);
+ buf = der_encode(buf, tmpt, sub_src);
+ }
+ } break;
+
+ case DER_BIT_STRING: {
+ SECItem *item;
+ int rem;
+
+ /*
+ * The contents length includes our extra octet; subtract
+ * it off so we just have the real string length there.
+ */
+ contents_len--;
+ item = (SECItem *)src;
+ PORT_Assert(contents_len == ((item->len + 7) >> 3));
+ rem = (contents_len << 3) - item->len;
+ *buf++ = rem; /* remaining bits */
+ PORT_Memcpy(buf, item->data, contents_len);
+ buf += contents_len;
+ } break;
+
+ default: {
+ SECItem *item;
+
+ item = (SECItem *)src;
+ PORT_Assert(contents_len == item->len);
+ PORT_Memcpy(buf, item->data, contents_len);
+ buf += contents_len;
+ } break;
+ }
+
+ return buf;
+}
+
+SECStatus
+DER_Encode(PLArenaPool *arena, SECItem *dest, DERTemplate *dtemplate, void *src)
+{
+ unsigned int contents_len, header_len;
+
+ src = (void **)((char *)src + dtemplate->offset);
+
+ /*
+ * First figure out how long the encoding will be. Do this by
+ * traversing the template from top to bottom and accumulating
+ * the length of each leaf item.
+ */
+ contents_len = contents_length(dtemplate, src);
+ header_len = header_length(dtemplate, contents_len);
+
+ dest->len = contents_len + header_len;
+
+ /* Allocate storage to hold the encoding */
+ dest->data = (unsigned char *)PORT_ArenaAlloc(arena, dest->len);
+ if (dest->data == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return SECFailure;
+ }
+
+ /* Now encode into the buffer */
+ (void)der_encode(dest->data, dtemplate, src);
+
+ return SECSuccess;
+}
diff --git a/security/nss/lib/util/dersubr.c b/security/nss/lib/util/dersubr.c
new file mode 100644
index 0000000000..03d070ab2f
--- /dev/null
+++ b/security/nss/lib/util/dersubr.c
@@ -0,0 +1,249 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 "secder.h"
+#include <limits.h>
+#include "secerr.h"
+
+int
+DER_LengthLength(PRUint32 len)
+{
+ if (len > 127) {
+ if (len > 255) {
+ if (len > 65535L) {
+ if (len > 16777215L) {
+ return 5;
+ } else {
+ return 4;
+ }
+ } else {
+ return 3;
+ }
+ } else {
+ return 2;
+ }
+ } else {
+ return 1;
+ }
+}
+
+unsigned char *
+DER_StoreHeader(unsigned char *buf, unsigned int code, PRUint32 len)
+{
+ unsigned char b[4];
+
+ b[0] = (unsigned char)(len >> 24);
+ b[1] = (unsigned char)(len >> 16);
+ b[2] = (unsigned char)(len >> 8);
+ b[3] = (unsigned char)len;
+ if ((code & DER_TAGNUM_MASK) == DER_SET || (code & DER_TAGNUM_MASK) == DER_SEQUENCE)
+ code |= DER_CONSTRUCTED;
+ *buf++ = code;
+ if (len > 127) {
+ if (len > 255) {
+ if (len > 65535) {
+ if (len > 16777215) {
+ *buf++ = 0x84;
+ *buf++ = b[0];
+ *buf++ = b[1];
+ *buf++ = b[2];
+ *buf++ = b[3];
+ } else {
+ *buf++ = 0x83;
+ *buf++ = b[1];
+ *buf++ = b[2];
+ *buf++ = b[3];
+ }
+ } else {
+ *buf++ = 0x82;
+ *buf++ = b[2];
+ *buf++ = b[3];
+ }
+ } else {
+ *buf++ = 0x81;
+ *buf++ = b[3];
+ }
+ } else {
+ *buf++ = b[3];
+ }
+ return buf;
+}
+
+/*
+ * XXX This should be rewritten, generalized, to take a long instead
+ * of a PRInt32.
+ */
+SECStatus
+DER_SetInteger(PLArenaPool *arena, SECItem *it, PRInt32 i)
+{
+ unsigned char bb[4];
+ unsigned len;
+
+ bb[0] = (unsigned char)(i >> 24);
+ bb[1] = (unsigned char)(i >> 16);
+ bb[2] = (unsigned char)(i >> 8);
+ bb[3] = (unsigned char)(i);
+
+ /*
+ ** Small integers are encoded in a single byte. Larger integers
+ ** require progressively more space.
+ */
+ if (i < -128) {
+ if (i < -32768L) {
+ if (i < -8388608L) {
+ len = 4;
+ } else {
+ len = 3;
+ }
+ } else {
+ len = 2;
+ }
+ } else if (i > 127) {
+ if (i > 32767L) {
+ if (i > 8388607L) {
+ len = 4;
+ } else {
+ len = 3;
+ }
+ } else {
+ len = 2;
+ }
+ } else {
+ len = 1;
+ }
+ it->data = (unsigned char *)PORT_ArenaAlloc(arena, len);
+ if (!it->data) {
+ return SECFailure;
+ }
+ it->len = len;
+ PORT_Memcpy(it->data, bb + (4 - len), len);
+ return SECSuccess;
+}
+
+/*
+ * XXX This should be rewritten, generalized, to take an unsigned long instead
+ * of a PRUint32.
+ */
+SECStatus
+DER_SetUInteger(PLArenaPool *arena, SECItem *it, PRUint32 ui)
+{
+ unsigned char bb[5];
+ int len;
+
+ bb[0] = 0;
+ bb[1] = (unsigned char)(ui >> 24);
+ bb[2] = (unsigned char)(ui >> 16);
+ bb[3] = (unsigned char)(ui >> 8);
+ bb[4] = (unsigned char)(ui);
+
+ /*
+ ** Small integers are encoded in a single byte. Larger integers
+ ** require progressively more space.
+ */
+ if (ui > 0x7f) {
+ if (ui > 0x7fff) {
+ if (ui > 0x7fffffL) {
+ if (ui >= 0x80000000L) {
+ len = 5;
+ } else {
+ len = 4;
+ }
+ } else {
+ len = 3;
+ }
+ } else {
+ len = 2;
+ }
+ } else {
+ len = 1;
+ }
+
+ it->data = (unsigned char *)PORT_ArenaAlloc(arena, len);
+ if (it->data == NULL) {
+ return SECFailure;
+ }
+
+ it->len = len;
+ PORT_Memcpy(it->data, bb + (sizeof(bb) - len), len);
+
+ return SECSuccess;
+}
+
+/*
+** Convert a der encoded *signed* integer into a machine integral value.
+** If an underflow/overflow occurs, sets error code and returns min/max.
+*/
+long
+DER_GetInteger(const SECItem *it)
+{
+ unsigned long ival;
+ PRBool negative;
+ unsigned int len = it->len;
+ unsigned char *cp = it->data;
+ size_t lsize = sizeof(ival);
+
+ PORT_Assert(len);
+ if (!len) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ return 0;
+ }
+
+ negative = (PRBool)(*cp & 0x80);
+ ival = negative ? ~0 : 0;
+
+ /* Ignore leading zeros/ones. */
+ while (len && *cp == (unsigned char)ival) {
+ len--;
+ cp++;
+ }
+
+ /* Check for overflow/underflow. */
+ if (len > lsize || (len == lsize && (*cp & 0x80) != negative)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return negative ? LONG_MIN : LONG_MAX;
+ }
+
+ while (len--) {
+ ival <<= 8;
+ ival |= *cp++;
+ }
+
+ return ival;
+}
+
+/*
+** Convert a der encoded *unsigned* integer into a machine integral value.
+** If an overflow occurs, sets error code and returns max.
+*/
+unsigned long
+DER_GetUInteger(SECItem *it)
+{
+ unsigned long ival = 0;
+ unsigned len = it->len;
+ unsigned char *cp = it->data;
+ unsigned long overflow = 0xffUL << ((sizeof(ival) - 1) * 8);
+
+ PORT_Assert(len);
+ if (!len) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ return 0;
+ }
+
+ /* Cannot put a negative value into an unsigned container. */
+ if (*cp & 0x80) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return 0;
+ }
+
+ while (len) {
+ if (ival & overflow) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return ULONG_MAX;
+ }
+ ival = ival << 8;
+ ival |= *cp++;
+ --len;
+ }
+ return ival;
+}
diff --git a/security/nss/lib/util/dertime.c b/security/nss/lib/util/dertime.c
new file mode 100644
index 0000000000..273ab345e5
--- /dev/null
+++ b/security/nss/lib/util/dertime.c
@@ -0,0 +1,310 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "prtypes.h"
+#include "prtime.h"
+#include "secder.h"
+#include "prlong.h"
+#include "secerr.h"
+
+#define HIDIGIT(v) (((v) / 10) + '0')
+#define LODIGIT(v) (((v) % 10) + '0')
+
+#define ISDIGIT(dig) (((dig) >= '0') && ((dig) <= '9'))
+#define CAPTURE(var, p, label) \
+ { \
+ if (!ISDIGIT((p)[0]) || !ISDIGIT((p)[1])) \
+ goto label; \
+ (var) = ((p)[0] - '0') * 10 + ((p)[1] - '0'); \
+ p += 2; \
+ }
+
+static const PRTime January1st1 = PR_INT64(0xff23400100d44000);
+static const PRTime January1st1950 = PR_INT64(0xfffdc1f8793da000);
+static const PRTime January1st2050 = PR_INT64(0x0008f81e1b098000);
+static const PRTime January1st10000 = PR_INT64(0x0384440ccc736000);
+
+/* gmttime must contains UTC time in micro-seconds unit */
+SECStatus
+DER_TimeToUTCTimeArena(PLArenaPool *arenaOpt, SECItem *dst, PRTime gmttime)
+{
+ PRExplodedTime printableTime;
+ unsigned char *d;
+
+ if ((gmttime < January1st1950) || (gmttime >= January1st2050)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ dst->len = 13;
+ if (arenaOpt) {
+ dst->data = d = (unsigned char *)PORT_ArenaAlloc(arenaOpt, dst->len);
+ } else {
+ dst->data = d = (unsigned char *)PORT_Alloc(dst->len);
+ }
+ dst->type = siUTCTime;
+ if (!d) {
+ return SECFailure;
+ }
+
+ /* Convert a PRTime to a printable format. */
+ PR_ExplodeTime(gmttime, PR_GMTParameters, &printableTime);
+
+ /* The month in UTC time is base one */
+ printableTime.tm_month++;
+
+ /* remove the century since it's added to the tm_year by the
+ PR_ExplodeTime routine, but is not needed for UTC time */
+ printableTime.tm_year %= 100;
+
+ d[0] = HIDIGIT(printableTime.tm_year);
+ d[1] = LODIGIT(printableTime.tm_year);
+ d[2] = HIDIGIT(printableTime.tm_month);
+ d[3] = LODIGIT(printableTime.tm_month);
+ d[4] = HIDIGIT(printableTime.tm_mday);
+ d[5] = LODIGIT(printableTime.tm_mday);
+ d[6] = HIDIGIT(printableTime.tm_hour);
+ d[7] = LODIGIT(printableTime.tm_hour);
+ d[8] = HIDIGIT(printableTime.tm_min);
+ d[9] = LODIGIT(printableTime.tm_min);
+ d[10] = HIDIGIT(printableTime.tm_sec);
+ d[11] = LODIGIT(printableTime.tm_sec);
+ d[12] = 'Z';
+ return SECSuccess;
+}
+
+SECStatus
+DER_TimeToUTCTime(SECItem *dst, PRTime gmttime)
+{
+ return DER_TimeToUTCTimeArena(NULL, dst, gmttime);
+}
+
+static SECStatus /* forward */
+der_TimeStringToTime(PRTime *dst, const char *string, int generalized,
+ const char **endptr);
+
+#define GEN_STRING 2 /* TimeString is a GeneralizedTime */
+#define UTC_STRING 0 /* TimeString is a UTCTime */
+
+/* The caller of DER_AsciiToItem MUST ENSURE that either
+** a) "string" points to a null-terminated ASCII string, or
+** b) "string" points to a buffer containing a valid UTCTime,
+** whether null terminated or not, or
+** c) "string" contains at least 19 characters, with or without null char.
+** otherwise, this function may UMR and/or crash.
+** It suffices to ensure that the input "string" is at least 17 bytes long.
+*/
+SECStatus
+DER_AsciiToTime(PRTime *dst, const char *string)
+{
+ return der_TimeStringToTime(dst, string, UTC_STRING, NULL);
+}
+
+SECStatus
+DER_UTCTimeToTime(PRTime *dst, const SECItem *time)
+{
+ /* Minimum valid UTCTime is yymmddhhmmZ which is 11 bytes.
+ ** Maximum valid UTCTime is yymmddhhmmss+0000 which is 17 bytes.
+ ** 20 should be large enough for all valid encoded times.
+ */
+ unsigned int i;
+ char localBuf[20];
+ const char *end = NULL;
+ SECStatus rv;
+
+ if (!time || !time->data || time->len < 11 || time->len > 17) {
+ PORT_SetError(SEC_ERROR_INVALID_TIME);
+ return SECFailure;
+ }
+
+ for (i = 0; i < time->len; i++) {
+ if (time->data[i] == '\0') {
+ PORT_SetError(SEC_ERROR_INVALID_TIME);
+ return SECFailure;
+ }
+ localBuf[i] = time->data[i];
+ }
+ localBuf[i] = '\0';
+
+ rv = der_TimeStringToTime(dst, localBuf, UTC_STRING, &end);
+ if (rv == SECSuccess && *end != '\0') {
+ PORT_SetError(SEC_ERROR_INVALID_TIME);
+ return SECFailure;
+ }
+ return rv;
+}
+
+/*
+ gmttime must contains UTC time in micro-seconds unit.
+ Note: the caller should make sure that Generalized time
+ should only be used for certifiate validities after the
+ year 2049. Otherwise, UTC time should be used. This routine
+ does not check this case, since it can be used to encode
+ certificate extension, which does not have this restriction.
+ */
+SECStatus
+DER_TimeToGeneralizedTimeArena(PLArenaPool *arenaOpt, SECItem *dst, PRTime gmttime)
+{
+ PRExplodedTime printableTime;
+ unsigned char *d;
+
+ if ((gmttime < January1st1) || (gmttime >= January1st10000)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ dst->len = 15;
+ if (arenaOpt) {
+ dst->data = d = (unsigned char *)PORT_ArenaAlloc(arenaOpt, dst->len);
+ } else {
+ dst->data = d = (unsigned char *)PORT_Alloc(dst->len);
+ }
+ dst->type = siGeneralizedTime;
+ if (!d) {
+ return SECFailure;
+ }
+
+ /* Convert a PRTime to a printable format. */
+ PR_ExplodeTime(gmttime, PR_GMTParameters, &printableTime);
+
+ /* The month in Generalized time is base one */
+ printableTime.tm_month++;
+
+ d[0] = (printableTime.tm_year / 1000) + '0';
+ d[1] = ((printableTime.tm_year % 1000) / 100) + '0';
+ d[2] = ((printableTime.tm_year % 100) / 10) + '0';
+ d[3] = (printableTime.tm_year % 10) + '0';
+ d[4] = HIDIGIT(printableTime.tm_month);
+ d[5] = LODIGIT(printableTime.tm_month);
+ d[6] = HIDIGIT(printableTime.tm_mday);
+ d[7] = LODIGIT(printableTime.tm_mday);
+ d[8] = HIDIGIT(printableTime.tm_hour);
+ d[9] = LODIGIT(printableTime.tm_hour);
+ d[10] = HIDIGIT(printableTime.tm_min);
+ d[11] = LODIGIT(printableTime.tm_min);
+ d[12] = HIDIGIT(printableTime.tm_sec);
+ d[13] = LODIGIT(printableTime.tm_sec);
+ d[14] = 'Z';
+ return SECSuccess;
+}
+
+SECStatus
+DER_TimeToGeneralizedTime(SECItem *dst, PRTime gmttime)
+{
+ return DER_TimeToGeneralizedTimeArena(NULL, dst, gmttime);
+}
+
+SECStatus
+DER_GeneralizedTimeToTime(PRTime *dst, const SECItem *time)
+{
+ /* Minimum valid GeneralizedTime is ccyymmddhhmmZ which is 13 bytes.
+ ** Maximum valid GeneralizedTime is ccyymmddhhmmss+0000 which is 19 bytes.
+ ** 20 should be large enough for all valid encoded times.
+ */
+ unsigned int i;
+ char localBuf[20];
+ const char *end = NULL;
+ SECStatus rv;
+
+ if (!time || !time->data || time->len < 13 || time->len > 19) {
+ PORT_SetError(SEC_ERROR_INVALID_TIME);
+ return SECFailure;
+ }
+
+ for (i = 0; i < time->len; i++) {
+ if (time->data[i] == '\0') {
+ PORT_SetError(SEC_ERROR_INVALID_TIME);
+ return SECFailure;
+ }
+ localBuf[i] = time->data[i];
+ }
+ localBuf[i] = '\0';
+
+ rv = der_TimeStringToTime(dst, localBuf, GEN_STRING, &end);
+ if (rv == SECSuccess && *end != '\0') {
+ PORT_SetError(SEC_ERROR_INVALID_TIME);
+ return SECFailure;
+ }
+ return rv;
+}
+
+static SECStatus
+der_TimeStringToTime(PRTime *dst, const char *string, int generalized,
+ const char **endptr)
+{
+ PRExplodedTime genTime;
+ long hourOff = 0, minOff = 0;
+ PRUint16 century;
+ char signum;
+
+ if (string == NULL || dst == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ /* Verify time is formatted properly and capture information */
+ memset(&genTime, 0, sizeof genTime);
+
+ if (generalized == UTC_STRING) {
+ CAPTURE(genTime.tm_year, string, loser);
+ century = (genTime.tm_year < 50) ? 20 : 19;
+ } else {
+ CAPTURE(century, string, loser);
+ CAPTURE(genTime.tm_year, string, loser);
+ }
+ genTime.tm_year += century * 100;
+
+ CAPTURE(genTime.tm_month, string, loser);
+ if ((genTime.tm_month == 0) || (genTime.tm_month > 12))
+ goto loser;
+
+ /* NSPR month base is 0 */
+ --genTime.tm_month;
+
+ CAPTURE(genTime.tm_mday, string, loser);
+ if ((genTime.tm_mday == 0) || (genTime.tm_mday > 31))
+ goto loser;
+
+ CAPTURE(genTime.tm_hour, string, loser);
+ if (genTime.tm_hour > 23)
+ goto loser;
+
+ CAPTURE(genTime.tm_min, string, loser);
+ if (genTime.tm_min > 59)
+ goto loser;
+
+ if (ISDIGIT(string[0])) {
+ CAPTURE(genTime.tm_sec, string, loser);
+ if (genTime.tm_sec > 59)
+ goto loser;
+ }
+ signum = *string++;
+ if (signum == '+' || signum == '-') {
+ CAPTURE(hourOff, string, loser);
+ if (hourOff > 23)
+ goto loser;
+ CAPTURE(minOff, string, loser);
+ if (minOff > 59)
+ goto loser;
+ if (signum == '-') {
+ hourOff = -hourOff;
+ minOff = -minOff;
+ }
+ } else if (signum != 'Z') {
+ goto loser;
+ }
+
+ if (endptr)
+ *endptr = string;
+
+ /* Convert the GMT offset to seconds and save it in genTime
+ * for the implode time call.
+ */
+ genTime.tm_params.tp_gmt_offset = (PRInt32)((hourOff * 60L + minOff) * 60L);
+ *dst = PR_ImplodeTime(&genTime);
+ return SECSuccess;
+
+loser:
+ PORT_SetError(SEC_ERROR_INVALID_TIME);
+ return SECFailure;
+}
diff --git a/security/nss/lib/util/eccutil.h b/security/nss/lib/util/eccutil.h
new file mode 100644
index 0000000000..7b52295b73
--- /dev/null
+++ b/security/nss/lib/util/eccutil.h
@@ -0,0 +1,17 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _FREEBL_H_
+#define _FREEBL_H_
+
+#define X25519_PUBLIC_KEY_BYTES 32U
+
+/* deprecated */
+typedef enum {
+ ECPoint_Uncompressed,
+ ECPoint_XOnly,
+ ECPoint_Undefined
+} ECPointEncoding;
+
+#endif /* _FREEBL_H_ */
diff --git a/security/nss/lib/util/errstrs.c b/security/nss/lib/util/errstrs.c
new file mode 100644
index 0000000000..138ee39589
--- /dev/null
+++ b/security/nss/lib/util/errstrs.c
@@ -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/. */
+#include "prerror.h"
+#include "secerr.h"
+#include "secport.h"
+#include "prinit.h"
+#include "prprf.h"
+#include "prtypes.h"
+#include "prlog.h"
+#include "plstr.h"
+#include "nssutil.h"
+#include <string.h>
+
+#define ER3(name, value, str) { #name, str },
+
+static const struct PRErrorMessage sectext[] = {
+#include "SECerrs.h"
+ { 0, 0 }
+};
+
+static const struct PRErrorTable sec_et = {
+ sectext, "secerrstrings", SEC_ERROR_BASE,
+ (sizeof sectext) / (sizeof sectext[0])
+};
+
+static PRStatus
+nss_InitializePRErrorTableOnce(void)
+{
+ return PR_ErrorInstallTable(&sec_et);
+}
+
+static PRCallOnceType once;
+
+SECStatus
+NSS_InitializePRErrorTable(void)
+{
+ return (PR_SUCCESS == PR_CallOnce(&once, nss_InitializePRErrorTableOnce))
+ ? SECSuccess
+ : SECFailure;
+}
diff --git a/security/nss/lib/util/exports.gyp b/security/nss/lib/util/exports.gyp
new file mode 100644
index 0000000000..7480d1b5ea
--- /dev/null
+++ b/security/nss/lib/util/exports.gyp
@@ -0,0 +1,69 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'lib_util_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'base64.h',
+ 'ciferfam.h',
+ 'eccutil.h',
+ 'hasht.h',
+ 'kyber.h',
+ 'nssb64.h',
+ 'nssb64t.h',
+ 'nssilckt.h',
+ 'nssilock.h',
+ 'nsslocks.h',
+ 'nssrwlk.h',
+ 'nssrwlkt.h',
+ 'nssutil.h',
+ 'pkcs11.h',
+ 'pkcs11f.h',
+ 'pkcs11n.h',
+ 'pkcs11p.h',
+ 'pkcs11t.h',
+ 'pkcs11u.h',
+ 'pkcs11uri.h',
+ 'pkcs1sig.h',
+ 'portreg.h',
+ 'secasn1.h',
+ 'secasn1t.h',
+ 'seccomon.h',
+ 'secder.h',
+ 'secdert.h',
+ 'secdig.h',
+ 'secdigt.h',
+ 'secerr.h',
+ 'secitem.h',
+ 'secoid.h',
+ 'secoidt.h',
+ 'secport.h',
+ 'utilmodt.h',
+ 'utilpars.h',
+ 'utilparst.h',
+ 'utilrename.h'
+ ],
+ 'destination': '<(nss_public_dist_dir)/<(module)'
+ },
+ {
+ 'files': [
+ 'templates.c',
+ 'verref.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/lib/util/hasht.h b/security/nss/lib/util/hasht.h
new file mode 100644
index 0000000000..b70b94fbfc
--- /dev/null
+++ b/security/nss/lib/util/hasht.h
@@ -0,0 +1,71 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 _HASHT_H_
+#define _HASHT_H_
+
+#include "prtypes.h"
+
+/* Opaque objects */
+typedef struct SECHashObjectStr SECHashObject;
+typedef struct HASHContextStr HASHContext;
+
+/*
+ * The hash functions the security library supports
+ * NOTE the order must match the definition of SECHashObjects[]!
+ */
+typedef enum {
+ HASH_AlgNULL = 0,
+ HASH_AlgMD2 = 1,
+ HASH_AlgMD5 = 2,
+ HASH_AlgSHA1 = 3,
+ HASH_AlgSHA256 = 4,
+ HASH_AlgSHA384 = 5,
+ HASH_AlgSHA512 = 6,
+ HASH_AlgSHA224 = 7,
+ HASH_AlgSHA3_224 = 8,
+ HASH_AlgSHA3_256 = 9,
+ HASH_AlgSHA3_384 = 10,
+ HASH_AlgSHA3_512 = 11,
+ HASH_AlgTOTAL
+} HASH_HashType;
+
+/*
+ * Number of bytes each hash algorithm produces
+ */
+#define MD2_LENGTH 16
+#define MD5_LENGTH 16
+#define SHA1_LENGTH 20
+#define SHA224_LENGTH 28
+#define SHA256_LENGTH 32
+#define SHA384_LENGTH 48
+#define SHA512_LENGTH 64
+#define SHA3_224_LENGTH 28
+#define SHA3_256_LENGTH 32
+#define SHA3_384_LENGTH 48
+#define SHA3_512_LENGTH 64
+#define HASH_LENGTH_MAX SHA512_LENGTH
+
+/*
+ * Structure to hold hash computation info and routines
+ */
+struct SECHashObjectStr {
+ unsigned int length; /* hash output length (in bytes) */
+ void *(*create)(void);
+ void *(*clone)(void *);
+ void (*destroy)(void *, PRBool);
+ void (*begin)(void *);
+ void (*update)(void *, const unsigned char *, unsigned int);
+ void (*end)(void *, unsigned char *, unsigned int *, unsigned int);
+ unsigned int blocklength; /* hash input block size (in bytes) */
+ HASH_HashType type;
+ void (*end_raw)(void *, unsigned char *, unsigned int *, unsigned int);
+};
+
+struct HASHContextStr {
+ const struct SECHashObjectStr *hashobj;
+ void *hash_context;
+};
+
+#endif /* _HASHT_H_ */
diff --git a/security/nss/lib/util/kyber.h b/security/nss/lib/util/kyber.h
new file mode 100644
index 0000000000..0b78225159
--- /dev/null
+++ b/security/nss/lib/util/kyber.h
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef KYBER_UTIL_H
+#define KYBER_UTIL_H
+
+#define KYBER768_PUBLIC_KEY_BYTES 1184U
+#define KYBER768_PRIVATE_KEY_BYTES 2400U
+#define KYBER768_CIPHERTEXT_BYTES 1088U
+
+#define KYBER_SHARED_SECRET_BYTES 32U
+#define KYBER_KEYPAIR_COIN_BYTES 64U
+#define KYBER_ENC_COIN_BYTES 32U
+
+typedef enum {
+ params_kyber_invalid,
+
+ /*
+ * The Kyber768 parameters specified in version 3.02 of the NIST submission
+ * https://pq-crystals.org/kyber/data/kyber-specification-round3-20210804.pdf
+ */
+ params_kyber768_round3,
+
+ /*
+ * Identical to params_kyber768_round3 except that this parameter set allows
+ * the use of a seed in `Kyber_Encapsulate` for testing.
+ */
+ params_kyber768_round3_test_mode,
+} KyberParams;
+
+#endif /* KYBER_UTIL_H */
diff --git a/security/nss/lib/util/manifest.mn b/security/nss/lib/util/manifest.mn
new file mode 100644
index 0000000000..acff3793df
--- /dev/null
+++ b/security/nss/lib/util/manifest.mn
@@ -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/.
+CORE_DEPTH = ../..
+
+EXPORTS = \
+ base64.h \
+ ciferfam.h \
+ eccutil.h \
+ hasht.h \
+ kyber.h \
+ nssb64.h \
+ nssb64t.h \
+ nsslocks.h \
+ nssilock.h \
+ nssilckt.h \
+ nssrwlk.h \
+ nssrwlkt.h \
+ nssutil.h \
+ pkcs11.h \
+ pkcs11f.h \
+ pkcs11p.h \
+ pkcs11t.h \
+ pkcs11n.h \
+ pkcs11u.h \
+ pkcs1sig.h \
+ portreg.h \
+ secasn1.h \
+ secasn1t.h \
+ seccomon.h \
+ secder.h \
+ secdert.h \
+ secdig.h \
+ secdigt.h \
+ secitem.h \
+ secoid.h \
+ secoidt.h \
+ secport.h \
+ secerr.h \
+ utilmodt.h \
+ utilrename.h \
+ utilpars.h \
+ utilparst.h \
+ pkcs11uri.h \
+ $(NULL)
+
+PRIVATE_EXPORTS = \
+ verref.h \
+ templates.c \
+ $(NULL)
+
+CSRCS = \
+ quickder.c \
+ secdig.c \
+ derdec.c \
+ derenc.c \
+ dersubr.c \
+ dertime.c \
+ errstrs.c \
+ nssb64d.c \
+ nssb64e.c \
+ nssrwlk.c \
+ nssilock.c \
+ oidstring.c \
+ pkcs1sig.c \
+ portreg.c \
+ secalgid.c \
+ secasn1d.c \
+ secasn1e.c \
+ secasn1u.c \
+ secitem.c \
+ secload.c \
+ secoid.c \
+ sectime.c \
+ secport.c \
+ templates.c \
+ utf8.c \
+ utilmod.c \
+ utilpars.c \
+ pkcs11uri.c \
+ $(NULL)
+
+MODULE = nss
+
+LIBRARY_NAME = nssutil
+LIBRARY_VERSION = 3
+MAPFILE = $(OBJDIR)/$(LIBRARY_NAME).def
+
+# 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/util/nssb64.h b/security/nss/lib/util/nssb64.h
new file mode 100644
index 0000000000..7882c3b2d9
--- /dev/null
+++ b/security/nss/lib/util/nssb64.h
@@ -0,0 +1,94 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Public prototypes for base64 encoding/decoding.
+ */
+#ifndef _NSSB64_H_
+#define _NSSB64_H_
+
+#include "utilrename.h"
+#include "seccomon.h"
+#include "nssb64t.h"
+
+SEC_BEGIN_PROTOS
+
+/*
+ * Functions to start a base64 decoding/encoding context.
+ */
+
+extern NSSBase64Decoder *
+NSSBase64Decoder_Create(PRInt32 (*output_fn)(void *, const unsigned char *,
+ PRInt32),
+ void *output_arg);
+
+extern NSSBase64Encoder *
+NSSBase64Encoder_Create(PRInt32 (*output_fn)(void *, const char *, PRInt32),
+ void *output_arg);
+
+/*
+ * Push data through the decoder/encoder, causing the output_fn (provided
+ * to Create) to be called with the decoded/encoded data.
+ */
+
+extern SECStatus
+NSSBase64Decoder_Update(NSSBase64Decoder *data, const char *buffer,
+ PRUint32 size);
+
+extern SECStatus
+NSSBase64Encoder_Update(NSSBase64Encoder *data, const unsigned char *buffer,
+ PRUint32 size);
+
+/*
+ * When you're done processing, call this to close the context.
+ * If "abort_p" is false, then calling this may cause the output_fn
+ * to be called one last time (as the last buffered data is flushed out).
+ */
+
+extern SECStatus
+NSSBase64Decoder_Destroy(NSSBase64Decoder *data, PRBool abort_p);
+
+extern SECStatus
+NSSBase64Encoder_Destroy(NSSBase64Encoder *data, PRBool abort_p);
+
+/*
+ * Perform base64 decoding from an ascii string "inStr" to an Item.
+ * The length of the input must be provided as "inLen". The Item
+ * may be provided (as "outItemOpt"); you can also pass in a NULL
+ * and the Item will be allocated for you.
+ *
+ * In any case, the data within the Item will be allocated for you.
+ * All allocation will happen out of the passed-in "arenaOpt", if non-NULL.
+ * If "arenaOpt" is NULL, standard allocation (heap) will be used and
+ * you will want to free the result via SECITEM_FreeItem.
+ *
+ * Return value is NULL on error, the Item (allocated or provided) otherwise.
+ */
+extern SECItem *
+NSSBase64_DecodeBuffer(PLArenaPool *arenaOpt, SECItem *outItemOpt,
+ const char *inStr, unsigned int inLen);
+
+/*
+ * Perform base64 encoding of binary data "inItem" to an ascii string.
+ * The output buffer may be provided (as "outStrOpt"); you can also pass
+ * in a NULL and the buffer will be allocated for you. The result will
+ * be null-terminated, and if the buffer is provided, "maxOutLen" must
+ * specify the maximum length of the buffer and will be checked to
+ * supply sufficient space space for the encoded result. (If "outStrOpt"
+ * is NULL, "maxOutLen" is ignored.)
+ *
+ * If "outStrOpt" is NULL, allocation will happen out of the passed-in
+ * "arenaOpt", if *it* is non-NULL, otherwise standard allocation (heap)
+ * will be used.
+ *
+ * Return value is NULL on error, the output buffer (allocated or provided)
+ * otherwise.
+ */
+extern char *
+NSSBase64_EncodeItem(PLArenaPool *arenaOpt, char *outStrOpt,
+ unsigned int maxOutLen, SECItem *inItem);
+
+SEC_END_PROTOS
+
+#endif /* _NSSB64_H_ */
diff --git a/security/nss/lib/util/nssb64d.c b/security/nss/lib/util/nssb64d.c
new file mode 100644
index 0000000000..ebfb154f90
--- /dev/null
+++ b/security/nss/lib/util/nssb64d.c
@@ -0,0 +1,852 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Base64 decoding (ascii to binary).
+ */
+
+#include "nssb64.h"
+#include "nspr.h"
+#include "secitem.h"
+#include "secerr.h"
+
+/*
+ * XXX We want this basic support to go into NSPR (the PL part).
+ * Until that can happen, the PL interface is going to be kept entirely
+ * internal here -- all static functions and opaque data structures.
+ * When someone can get it moved over into NSPR, that should be done:
+ * - giving everything names that are accepted by the NSPR module owners
+ * (though I tried to choose ones that would work without modification)
+ * - exporting the functions (remove static declarations and add
+ * to nssutil.def as necessary)
+ * - put prototypes into appropriate header file (probably replacing
+ * the entire current lib/libc/include/plbase64.h in NSPR)
+ * along with a typedef for the context structure (which should be
+ * kept opaque -- definition in the source file only, but typedef
+ * ala "typedef struct PLBase64FooStr PLBase64Foo;" in header file)
+ * - modify anything else as necessary to conform to NSPR required style
+ * (I looked but found no formatting guide to follow)
+ *
+ * You will want to move over everything from here down to the comment
+ * which says "XXX End of base64 decoding code to be moved into NSPR",
+ * into a new file in NSPR.
+ */
+
+/*
+ **************************************************************
+ * XXX Beginning of base64 decoding code to be moved into NSPR.
+ */
+
+/*
+ * This typedef would belong in the NSPR header file (i.e. plbase64.h).
+ */
+typedef struct PLBase64DecoderStr PLBase64Decoder;
+
+/*
+ * The following implementation of base64 decoding was based on code
+ * found in libmime (specifically, in mimeenc.c). It has been adapted to
+ * use PR types and naming as well as to provide other necessary semantics
+ * (like buffer-in/buffer-out in addition to "streaming" without undue
+ * performance hit of extra copying if you made the buffer versions
+ * use the output_fn). It also incorporates some aspects of the current
+ * NSPR base64 decoding code. As such, you may find similarities to
+ * both of those implementations. I tried to use names that reflected
+ * the original code when possible. For this reason you may find some
+ * inconsistencies -- libmime used lots of "in" and "out" whereas the
+ * NSPR version uses "src" and "dest"; sometimes I changed one to the other
+ * and sometimes I left them when I thought the subroutines were at least
+ * self-consistent.
+ */
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * Opaque object used by the decoder to store state.
+ */
+struct PLBase64DecoderStr {
+ /* Current token (or portion, if token_size < 4) being decoded. */
+ unsigned char token[4];
+ int token_size;
+
+ /*
+ * Where to write the decoded data (used when streaming, not when
+ * doing all in-memory (buffer) operations).
+ *
+ * Note that this definition is chosen to be compatible with PR_Write.
+ */
+ PRInt32 (*output_fn)(void *output_arg, const unsigned char *buf,
+ PRInt32 size);
+ void *output_arg;
+
+ /*
+ * Where the decoded output goes -- either temporarily (in the streaming
+ * case, staged here before it goes to the output function) or what will
+ * be the entire buffered result for users of the buffer version.
+ */
+ unsigned char *output_buffer;
+ PRUint32 output_buflen; /* the total length of allocated buffer */
+ PRUint32 output_length; /* the length that is currently populated */
+};
+
+PR_END_EXTERN_C
+
+/* A constant time range check for unsigned chars.
+ * Returns 255 if a <= x <= b and 0 otherwise.
+ */
+static inline unsigned char
+ct_u8_in_range(unsigned char x, unsigned char a, unsigned char b)
+{
+ /* Let x, a, b be ints in {0, 1, ... 255}.
+ * The value (a - x - 1) is in {-256, ..., 254}, so the low
+ * 8 bits of
+ * (a - x - 1) >> 8
+ * are all 1 if a <= x and all 0 if a > x.
+ *
+ * Likewise the low 8 bits of
+ * ((a - x - 1) >> 8) & ((x - c - 1) >> 8)
+ * are all 1 if a <= x <= c and all 0 otherwise.
+ *
+ * The same is true if we perform the shift after the AND
+ * ((a - x - 1) & (x - b - 1)) >> 8.
+ */
+ return (unsigned char)(((a - x - 1) & (x - b - 1)) >> 8);
+}
+
+/* Convert a base64 code [A-Za-z0-9+/] to its value in {1, 2, ..., 64}.
+ * The use of 1-64 instead of 0-63 is so that the special value of zero can
+ * denote an invalid mapping; that was much easier than trying to fill in the
+ * other values with some value other than zero, and to check for it.
+ * Just remember to SUBTRACT ONE when using the value retrieved.
+ */
+static unsigned char
+pl_base64_codetovaluep1(unsigned char code)
+{
+ unsigned char mask;
+ unsigned char res = 0;
+
+ /* The range 'A' to 'Z' is mapped to 1 to 26 */
+ mask = ct_u8_in_range(code, 'A', 'Z');
+ res |= mask & (code - 'A' + 1);
+
+ /* The range 'a' to 'z' is mapped to 27 to 52 */
+ mask = ct_u8_in_range(code, 'a', 'z');
+ res |= mask & (code - 'a' + 27);
+
+ /* The range '0' to '9' is mapped to 53 to 62 */
+ mask = ct_u8_in_range(code, '0', '9');
+ res |= mask & (code - '0' + 53);
+
+ /* The code '+' is mapped to 63 */
+ mask = ct_u8_in_range(code, '+', '+');
+ res |= mask & 63;
+
+ /* The code '/' is mapped to 64 */
+ mask = ct_u8_in_range(code, '/', '/');
+ res |= mask & 64;
+
+ /* All other characters, including '=' are mapped to 0. */
+ return res;
+}
+
+#define B64_PAD '='
+
+/*
+ * Reads 4; writes 3 (known, or expected, to have no trailing padding).
+ * Returns bytes written; -1 on error (unexpected character).
+ */
+static int
+pl_base64_decode_4to3(const unsigned char *in, unsigned char *out)
+{
+ int j;
+ PRUint32 num = 0;
+ unsigned char bits;
+
+ for (j = 0; j < 4; j++) {
+ bits = pl_base64_codetovaluep1(in[j]);
+ if (bits == 0)
+ return -1;
+ num = (num << 6) | (bits - 1);
+ }
+
+ out[0] = (unsigned char)(num >> 16);
+ out[1] = (unsigned char)((num >> 8) & 0xFF);
+ out[2] = (unsigned char)(num & 0xFF);
+
+ return 3;
+}
+
+/*
+ * Reads 3; writes 2 (caller already confirmed EOF or trailing padding).
+ * Returns bytes written; -1 on error (unexpected character).
+ */
+static int
+pl_base64_decode_3to2(const unsigned char *in, unsigned char *out)
+{
+ PRUint32 num = 0;
+ unsigned char bits1, bits2, bits3;
+
+ bits1 = pl_base64_codetovaluep1(in[0]);
+ bits2 = pl_base64_codetovaluep1(in[1]);
+ bits3 = pl_base64_codetovaluep1(in[2]);
+
+ if ((bits1 == 0) || (bits2 == 0) || (bits3 == 0))
+ return -1;
+
+ num = ((PRUint32)(bits1 - 1)) << 10;
+ num |= ((PRUint32)(bits2 - 1)) << 4;
+ num |= ((PRUint32)(bits3 - 1)) >> 2;
+
+ out[0] = (unsigned char)(num >> 8);
+ out[1] = (unsigned char)(num & 0xFF);
+
+ return 2;
+}
+
+/*
+ * Reads 2; writes 1 (caller already confirmed EOF or trailing padding).
+ * Returns bytes written; -1 on error (unexpected character).
+ */
+static int
+pl_base64_decode_2to1(const unsigned char *in, unsigned char *out)
+{
+ PRUint32 num = 0;
+ unsigned char bits1, bits2;
+
+ bits1 = pl_base64_codetovaluep1(in[0]);
+ bits2 = pl_base64_codetovaluep1(in[1]);
+
+ if ((bits1 == 0) || (bits2 == 0))
+ return -1;
+
+ num = ((PRUint32)(bits1 - 1)) << 2;
+ num |= ((PRUint32)(bits2 - 1)) >> 4;
+
+ out[0] = (unsigned char)num;
+
+ return 1;
+}
+
+/*
+ * Reads 4; writes 0-3. Returns bytes written or -1 on error.
+ * (Writes less than 3 only at (presumed) EOF.)
+ */
+static int
+pl_base64_decode_token(const unsigned char *in, unsigned char *out)
+{
+ if (in[3] != B64_PAD)
+ return pl_base64_decode_4to3(in, out);
+
+ if (in[2] == B64_PAD)
+ return pl_base64_decode_2to1(in, out);
+
+ return pl_base64_decode_3to2(in, out);
+}
+
+static PRStatus
+pl_base64_decode_buffer(PLBase64Decoder *data, const unsigned char *in,
+ PRUint32 length)
+{
+ unsigned char *out = data->output_buffer;
+ unsigned char *token = data->token;
+ int i, n = 0;
+
+ i = data->token_size;
+ data->token_size = 0;
+
+ while (length > 0) {
+ while (i < 4 && length > 0) {
+ /*
+ * XXX Note that the following simply ignores any unexpected
+ * characters. This is exactly what the original code in
+ * libmime did, and I am leaving it. We certainly want to skip
+ * over whitespace (we must); this does much more than that.
+ * I am not confident changing it, and I don't want to slow
+ * the processing down doing more complicated checking, but
+ * someone else might have different ideas in the future.
+ */
+ if (pl_base64_codetovaluep1(*in) > 0 || *in == B64_PAD)
+ token[i++] = *in;
+ in++;
+ length--;
+ }
+
+ if (i < 4) {
+ /* Didn't get enough for a complete token. */
+ data->token_size = i;
+ break;
+ }
+ i = 0;
+
+ PR_ASSERT((PRUint32)(out - data->output_buffer + 3) <= data->output_buflen);
+
+ /*
+ * Assume we are not at the end; the following function only works
+ * for an internal token (no trailing padding characters) but is
+ * faster that way. If it hits an invalid character (padding) it
+ * will return an error; we break out of the loop and try again
+ * calling the routine that will handle a final token.
+ * Note that we intentionally do it this way rather than explicitly
+ * add a check for padding here (because that would just slow down
+ * the normal case) nor do we rely on checking whether we have more
+ * input to process (because that would also slow it down but also
+ * because we want to allow trailing garbage, especially white space
+ * and cannot tell that without read-ahead, also a slow proposition).
+ * Whew. Understand?
+ */
+ n = pl_base64_decode_4to3(token, out);
+ if (n < 0)
+ break;
+
+ /* Advance "out" by the number of bytes just written to it. */
+ out += n;
+ n = 0;
+ }
+
+ /*
+ * See big comment above, before call to pl_base64_decode_4to3.
+ * Here we check if we error'd out of loop, and allow for the case
+ * that we are processing the last interesting token. If the routine
+ * which should handle padding characters also fails, then we just
+ * have bad input and give up.
+ */
+ if (n < 0) {
+ n = pl_base64_decode_token(token, out);
+ if (n < 0)
+ return PR_FAILURE;
+
+ out += n;
+ }
+
+ /*
+ * As explained above, we can get here with more input remaining, but
+ * it should be all characters we do not care about (i.e. would be
+ * ignored when transferring from "in" to "token" in loop above,
+ * except here we choose to ignore extraneous pad characters, too).
+ * Swallow it, performing that check. If we find more characters that
+ * we would expect to decode, something is wrong.
+ */
+ while (length > 0) {
+ if (pl_base64_codetovaluep1(*in) > 0)
+ return PR_FAILURE;
+ in++;
+ length--;
+ }
+
+ /* Record the length of decoded data we have left in output_buffer. */
+ data->output_length = (PRUint32)(out - data->output_buffer);
+ return PR_SUCCESS;
+}
+
+/*
+ * Flush any remaining buffered characters. Given well-formed input,
+ * this will have nothing to do. If the input was missing the padding
+ * characters at the end, though, there could be 1-3 characters left
+ * behind -- we will tolerate that by adding the padding for them.
+ */
+static PRStatus
+pl_base64_decode_flush(PLBase64Decoder *data)
+{
+ int count;
+
+ /*
+ * If no remaining characters, or all are padding (also not well-formed
+ * input, but again, be tolerant), then nothing more to do. (And, that
+ * is considered successful.)
+ */
+ if (data->token_size == 0 || data->token[0] == B64_PAD)
+ return PR_SUCCESS;
+
+ /*
+ * Assume we have all the interesting input except for some expected
+ * padding characters. Add them and decode the resulting token.
+ */
+ while (data->token_size < 4)
+ data->token[data->token_size++] = B64_PAD;
+
+ data->token_size = 0; /* so a subsequent flush call is a no-op */
+
+ count = pl_base64_decode_token(data->token,
+ data->output_buffer + data->output_length);
+ if (count < 0)
+ return PR_FAILURE;
+
+ /*
+ * If there is an output function, call it with this last bit of data.
+ * Otherwise we are doing all buffered output, and the decoded bytes
+ * are now there, we just need to reflect that in the length.
+ */
+ if (data->output_fn != NULL) {
+ PRInt32 output_result;
+
+ PR_ASSERT(data->output_length == 0);
+ output_result = data->output_fn(data->output_arg,
+ data->output_buffer,
+ (PRInt32)count);
+ if (output_result < 0)
+ return PR_FAILURE;
+ } else {
+ data->output_length += count;
+ }
+
+ return PR_SUCCESS;
+}
+
+/*
+ * The maximum space needed to hold the output of the decoder given
+ * input data of length "size".
+ */
+static PRUint32
+PL_Base64MaxDecodedLength(PRUint32 size)
+{
+ return size * 0.75;
+}
+
+/*
+ * A distinct internal creation function for the buffer version to use.
+ * (It does not want to specify an output_fn, and we want the normal
+ * Create function to require that.) If more common initialization
+ * of the decoding context needs to be done, it should be done *here*.
+ */
+static PLBase64Decoder *
+pl_base64_create_decoder(void)
+{
+ return PR_NEWZAP(PLBase64Decoder);
+}
+
+/*
+ * Function to start a base64 decoding context.
+ * An "output_fn" is required; the "output_arg" parameter to that is optional.
+ */
+static PLBase64Decoder *
+PL_CreateBase64Decoder(PRInt32 (*output_fn)(void *, const unsigned char *,
+ PRInt32),
+ void *output_arg)
+{
+ PLBase64Decoder *data;
+
+ if (output_fn == NULL) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+
+ data = pl_base64_create_decoder();
+ if (data != NULL) {
+ data->output_fn = output_fn;
+ data->output_arg = output_arg;
+ }
+ return data;
+}
+
+/*
+ * Push data through the decoder, causing the output_fn (provided to Create)
+ * to be called with the decoded data.
+ */
+static PRStatus
+PL_UpdateBase64Decoder(PLBase64Decoder *data, const char *buffer,
+ PRUint32 size)
+{
+ PRUint32 need_length;
+ PRStatus status;
+
+ /* XXX Should we do argument checking only in debug build? */
+ if (data == NULL || buffer == NULL || size == 0) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ /*
+ * How much space could this update need for decoding?
+ */
+ need_length = PL_Base64MaxDecodedLength(size + data->token_size);
+
+ /*
+ * Make sure we have at least that much. If not, (re-)allocate.
+ */
+ if (need_length > data->output_buflen) {
+ unsigned char *output_buffer = data->output_buffer;
+
+ if (output_buffer != NULL)
+ output_buffer = (unsigned char *)PR_Realloc(output_buffer,
+ need_length);
+ else
+ output_buffer = (unsigned char *)PR_Malloc(need_length);
+
+ if (output_buffer == NULL)
+ return PR_FAILURE;
+
+ data->output_buffer = output_buffer;
+ data->output_buflen = need_length;
+ }
+
+ /* There should not have been any leftover output data in the buffer. */
+ PR_ASSERT(data->output_length == 0);
+ data->output_length = 0;
+
+ status = pl_base64_decode_buffer(data, (const unsigned char *)buffer,
+ size);
+
+ /* Now that we have some decoded data, write it. */
+ if (status == PR_SUCCESS && data->output_length > 0) {
+ PRInt32 output_result;
+
+ PR_ASSERT(data->output_fn != NULL);
+ output_result = data->output_fn(data->output_arg,
+ data->output_buffer,
+ (PRInt32)data->output_length);
+ if (output_result < 0)
+ status = PR_FAILURE;
+ }
+
+ data->output_length = 0;
+ return status;
+}
+
+/*
+ * When you're done decoding, call this to free the data. If "abort_p"
+ * is false, then calling this may cause the output_fn to be called
+ * one last time (as the last buffered data is flushed out).
+ */
+static PRStatus
+PL_DestroyBase64Decoder(PLBase64Decoder *data, PRBool abort_p)
+{
+ PRStatus status = PR_SUCCESS;
+
+ /* XXX Should we do argument checking only in debug build? */
+ if (data == NULL) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ /* Flush out the last few buffered characters. */
+ if (!abort_p)
+ status = pl_base64_decode_flush(data);
+
+ if (data->output_buffer != NULL)
+ PR_Free(data->output_buffer);
+ PR_Free(data);
+
+ return status;
+}
+
+/*
+ * Perform base64 decoding from an input buffer to an output buffer.
+ * The output buffer can be provided (as "dest"); you can also pass in
+ * a NULL and this function will allocate a buffer large enough for you,
+ * and return it. If you do provide the output buffer, you must also
+ * provide the maximum length of that buffer (as "maxdestlen").
+ * The actual decoded length of output will be returned to you in
+ * "output_destlen".
+ *
+ * Return value is NULL on error, the output buffer (allocated or provided)
+ * otherwise.
+ */
+static unsigned char *
+PL_Base64DecodeBuffer(const char *src, PRUint32 srclen, unsigned char *dest,
+ PRUint32 maxdestlen, PRUint32 *output_destlen)
+{
+ PRUint32 need_length;
+ unsigned char *output_buffer = NULL;
+ PLBase64Decoder *data = NULL;
+ PRStatus status;
+
+ PR_ASSERT(srclen > 0);
+ if (srclen == 0) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+
+ /*
+ * How much space could we possibly need for decoding this input?
+ */
+ need_length = PL_Base64MaxDecodedLength(srclen);
+
+ /*
+ * Make sure we have at least that much, if output buffer provided.
+ * If no output buffer provided, then we allocate that much.
+ */
+ if (dest != NULL) {
+ PR_ASSERT(maxdestlen >= need_length);
+ if (maxdestlen < need_length) {
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
+ goto loser;
+ }
+ output_buffer = dest;
+ } else {
+ output_buffer = (unsigned char *)PR_Malloc(need_length);
+ if (output_buffer == NULL)
+ goto loser;
+ maxdestlen = need_length;
+ }
+
+ data = pl_base64_create_decoder();
+ if (data == NULL)
+ goto loser;
+
+ data->output_buflen = maxdestlen;
+ data->output_buffer = output_buffer;
+
+ status = pl_base64_decode_buffer(data, (const unsigned char *)src,
+ srclen);
+
+ /*
+ * We do not wait for Destroy to flush, because Destroy will also
+ * get rid of our decoder context, which we need to look at first!
+ */
+ if (status == PR_SUCCESS)
+ status = pl_base64_decode_flush(data);
+
+ /* Must clear this or Destroy will free it. */
+ data->output_buffer = NULL;
+
+ if (status == PR_SUCCESS) {
+ *output_destlen = data->output_length;
+ status = PL_DestroyBase64Decoder(data, PR_FALSE);
+ data = NULL;
+ if (status == PR_FAILURE)
+ goto loser;
+ return output_buffer;
+ }
+
+loser:
+ if (dest == NULL && output_buffer != NULL)
+ PR_Free(output_buffer);
+ if (data != NULL)
+ (void)PL_DestroyBase64Decoder(data, PR_TRUE);
+ return NULL;
+}
+
+/*
+ * XXX End of base64 decoding code to be moved into NSPR.
+ ********************************************************
+ */
+
+/*
+ * This is the beginning of the NSS cover functions. These will
+ * provide the interface we want to expose as NSS-ish. For example,
+ * they will operate on our Items, do any special handling or checking
+ * we want to do, etc.
+ */
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * A boring cover structure for now. Perhaps someday it will include
+ * some more interesting fields.
+ */
+struct NSSBase64DecoderStr {
+ PLBase64Decoder *pl_data;
+};
+
+PR_END_EXTERN_C
+
+/*
+ * Function to start a base64 decoding context.
+ */
+NSSBase64Decoder *
+NSSBase64Decoder_Create(PRInt32 (*output_fn)(void *, const unsigned char *,
+ PRInt32),
+ void *output_arg)
+{
+ PLBase64Decoder *pl_data;
+ NSSBase64Decoder *nss_data;
+
+ nss_data = PORT_ZNew(NSSBase64Decoder);
+ if (nss_data == NULL)
+ return NULL;
+
+ pl_data = PL_CreateBase64Decoder(output_fn, output_arg);
+ if (pl_data == NULL) {
+ PORT_Free(nss_data);
+ return NULL;
+ }
+
+ nss_data->pl_data = pl_data;
+ return nss_data;
+}
+
+/*
+ * Push data through the decoder, causing the output_fn (provided to Create)
+ * to be called with the decoded data.
+ */
+SECStatus
+NSSBase64Decoder_Update(NSSBase64Decoder *data, const char *buffer,
+ PRUint32 size)
+{
+ PRStatus pr_status;
+
+ /* XXX Should we do argument checking only in debug build? */
+ if (data == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ pr_status = PL_UpdateBase64Decoder(data->pl_data, buffer, size);
+ if (pr_status == PR_FAILURE)
+ return SECFailure;
+
+ return SECSuccess;
+}
+
+/*
+ * When you're done decoding, call this to free the data. If "abort_p"
+ * is false, then calling this may cause the output_fn to be called
+ * one last time (as the last buffered data is flushed out).
+ */
+SECStatus
+NSSBase64Decoder_Destroy(NSSBase64Decoder *data, PRBool abort_p)
+{
+ PRStatus pr_status;
+
+ /* XXX Should we do argument checking only in debug build? */
+ if (data == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ pr_status = PL_DestroyBase64Decoder(data->pl_data, abort_p);
+
+ PORT_Free(data);
+
+ if (pr_status == PR_FAILURE)
+ return SECFailure;
+
+ return SECSuccess;
+}
+
+/*
+ * Perform base64 decoding from an ascii string "inStr" to an Item.
+ * The length of the input must be provided as "inLen". The Item
+ * may be provided (as "outItemOpt"); you can also pass in a NULL
+ * and the Item will be allocated for you.
+ *
+ * In any case, the data within the Item will be allocated for you.
+ * All allocation will happen out of the passed-in "arenaOpt", if non-NULL.
+ * If "arenaOpt" is NULL, standard allocation (heap) will be used and
+ * you will want to free the result via SECITEM_FreeItem.
+ *
+ * Return value is NULL on error, the Item (allocated or provided) otherwise.
+ */
+SECItem *
+NSSBase64_DecodeBuffer(PLArenaPool *arenaOpt, SECItem *outItemOpt,
+ const char *inStr, unsigned int inLen)
+{
+ SECItem *out_item = NULL;
+ PRUint32 max_out_len = 0;
+ void *mark = NULL;
+ unsigned char *dummy = NULL;
+
+ if ((outItemOpt != NULL && outItemOpt->data != NULL) || inLen == 0) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ if (arenaOpt != NULL)
+ mark = PORT_ArenaMark(arenaOpt);
+
+ max_out_len = PL_Base64MaxDecodedLength(inLen);
+ if (max_out_len == 0) {
+ goto loser;
+ }
+ out_item = SECITEM_AllocItem(arenaOpt, outItemOpt, max_out_len);
+ if (out_item == NULL) {
+ goto loser;
+ }
+
+ dummy = PL_Base64DecodeBuffer(inStr, inLen, out_item->data,
+ max_out_len, &out_item->len);
+ if (dummy == NULL) {
+ goto loser;
+ }
+ if (arenaOpt != NULL) {
+ PORT_ArenaUnmark(arenaOpt, mark);
+ }
+ return out_item;
+
+loser:
+ if (arenaOpt != NULL) {
+ PORT_ArenaRelease(arenaOpt, mark);
+ if (outItemOpt != NULL) {
+ outItemOpt->data = NULL;
+ outItemOpt->len = 0;
+ }
+ } else if (dummy == NULL) {
+ SECITEM_FreeItem(out_item, (PRBool)(outItemOpt == NULL));
+ }
+ return NULL;
+}
+
+/*
+ * XXX Everything below is deprecated. If you add new stuff, put it
+ * *above*, not below.
+ */
+
+/*
+ * XXX The following "ATOB" functions are provided for backward compatibility
+ * with current code. They should be considered strongly deprecated.
+ * When we can convert all our code over to using the new NSSBase64Decoder_
+ * functions defined above, we should get rid of these altogether. (Remove
+ * protoypes from base64.h as well -- actually, remove that file completely).
+ * If someone thinks either of these functions provides such a very useful
+ * interface (though, as shown, the same functionality can already be
+ * obtained by calling NSSBase64_DecodeBuffer directly), fine -- but then
+ * that API should be provided with a nice new NSSFoo name and using
+ * appropriate types, etc.
+ */
+
+#include "base64.h"
+
+/*
+** Return an PORT_Alloc'd string which is the base64 decoded version
+** of the input string; set *lenp to the length of the returned data.
+*/
+unsigned char *
+ATOB_AsciiToData(const char *string, unsigned int *lenp)
+{
+ SECItem binary_item, *dummy;
+
+ binary_item.data = NULL;
+ binary_item.len = 0;
+
+ dummy = NSSBase64_DecodeBuffer(NULL, &binary_item, string,
+ (PRUint32)PORT_Strlen(string));
+ if (dummy == NULL)
+ return NULL;
+
+ PORT_Assert(dummy == &binary_item);
+
+ *lenp = dummy->len;
+ return dummy->data;
+}
+
+/*
+** Convert from ascii to binary encoding of an item.
+*/
+SECStatus
+ATOB_ConvertAsciiToItem(SECItem *binary_item, const char *ascii)
+{
+ SECItem *dummy;
+
+ if (binary_item == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ /*
+ * XXX Would prefer to assert here if data is non-null (actually,
+ * don't need to, just let NSSBase64_DecodeBuffer do it), so as to
+ * to catch unintended memory leaks, but callers are not clean in
+ * this respect so we need to explicitly clear here to avoid the
+ * assert in NSSBase64_DecodeBuffer.
+ */
+ binary_item->data = NULL;
+ binary_item->len = 0;
+
+ dummy = NSSBase64_DecodeBuffer(NULL, binary_item, ascii,
+ (PRUint32)PORT_Strlen(ascii));
+
+ if (dummy == NULL)
+ return SECFailure;
+
+ return SECSuccess;
+}
diff --git a/security/nss/lib/util/nssb64e.c b/security/nss/lib/util/nssb64e.c
new file mode 100644
index 0000000000..18b01ddacb
--- /dev/null
+++ b/security/nss/lib/util/nssb64e.c
@@ -0,0 +1,734 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Base64 encoding (binary to ascii).
+ */
+
+#include "nssb64.h"
+#include "nspr.h"
+#include "secitem.h"
+#include "secerr.h"
+
+/*
+ * XXX See the big comment at the top of nssb64d.c about moving the
+ * bulk of this code over into NSPR (the PL part). It all applies
+ * here but I didn't want to duplicate it, to avoid divergence problems.
+ */
+
+/*
+ **************************************************************
+ * XXX Beginning of base64 encoding code to be moved into NSPR.
+ */
+
+struct PLBase64EncodeStateStr {
+ unsigned chunks;
+ unsigned saved;
+ unsigned char buf[3];
+};
+
+/*
+ * This typedef would belong in the NSPR header file (i.e. plbase64.h).
+ */
+typedef struct PLBase64EncoderStr PLBase64Encoder;
+
+/*
+ * The following implementation of base64 encoding was based on code
+ * found in libmime (specifically, in mimeenc.c). It has been adapted to
+ * use PR types and naming as well as to provide other necessary semantics
+ * (like buffer-in/buffer-out in addition to "streaming" without undue
+ * performance hit of extra copying if you made the buffer versions
+ * use the output_fn). It also incorporates some aspects of the current
+ * NSPR base64 encoding code. As such, you may find similarities to
+ * both of those implementations. I tried to use names that reflected
+ * the original code when possible. For this reason you may find some
+ * inconsistencies -- libmime used lots of "in" and "out" whereas the
+ * NSPR version uses "src" and "dest"; sometimes I changed one to the other
+ * and sometimes I left them when I thought the subroutines were at least
+ * self-consistent.
+ */
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * Opaque object used by the encoder to store state.
+ */
+struct PLBase64EncoderStr {
+ /*
+ * The one or two bytes pending. (We need 3 to create a "token",
+ * and hold the leftovers here. in_buffer_count is *only* ever
+ * 0, 1, or 2.
+ */
+ unsigned char in_buffer[2];
+ int in_buffer_count;
+
+ /*
+ * If the caller wants linebreaks added, line_length specifies
+ * where they come out. It must be a multiple of 4; if the caller
+ * provides one that isn't, we round it down to the nearest
+ * multiple of 4.
+ *
+ * The value of current_column counts how many characters have been
+ * added since the last linebreaks (or since the beginning, on the
+ * first line). It is also always a multiple of 4; it is unused when
+ * line_length is 0.
+ */
+ PRUint32 line_length;
+ PRUint32 current_column;
+
+ /*
+ * Where to write the encoded data (used when streaming, not when
+ * doing all in-memory (buffer) operations).
+ *
+ * Note that this definition is chosen to be compatible with PR_Write.
+ */
+ PRInt32 (*output_fn)(void *output_arg, const char *buf, PRInt32 size);
+ void *output_arg;
+
+ /*
+ * Where the encoded output goes -- either temporarily (in the streaming
+ * case, staged here before it goes to the output function) or what will
+ * be the entire buffered result for users of the buffer version.
+ */
+ char *output_buffer;
+ PRUint32 output_buflen; /* the total length of allocated buffer */
+ PRUint32 output_length; /* the length that is currently populated */
+};
+
+PR_END_EXTERN_C
+
+/*
+ * Table to convert a binary value to its corresponding ascii "code".
+ */
+static unsigned char base64_valuetocode[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+#define B64_PAD '='
+#define B64_CR '\r'
+#define B64_LF '\n'
+
+static PRStatus
+pl_base64_encode_buffer(PLBase64Encoder *data, const unsigned char *in,
+ PRUint32 size)
+{
+ const unsigned char *end = in + size;
+ char *out = data->output_buffer + data->output_length;
+ unsigned int i = data->in_buffer_count;
+ PRUint32 n = 0;
+ int off;
+ PRUint32 output_threshold;
+
+ /* If this input buffer is too small, wait until next time. */
+ if (size < (3 - i)) {
+ data->in_buffer[i++] = in[0];
+ if (size > 1)
+ data->in_buffer[i++] = in[1];
+ PR_ASSERT(i < 3);
+ data->in_buffer_count = i;
+ return PR_SUCCESS;
+ }
+
+ /* If there are bytes that were put back last time, take them now. */
+ if (i > 0) {
+ n = data->in_buffer[0];
+ if (i > 1)
+ n = (n << 8) | data->in_buffer[1];
+ data->in_buffer_count = 0;
+ }
+
+ /* If our total is not a multiple of three, put one or two bytes back. */
+ off = (size + i) % 3;
+ if (off > 0) {
+ size -= off;
+ data->in_buffer[0] = in[size];
+ if (off > 1)
+ data->in_buffer[1] = in[size + 1];
+ data->in_buffer_count = off;
+ end -= off;
+ }
+
+ output_threshold = data->output_buflen - 3;
+
+ /*
+ * Populate the output buffer with base64 data, one line (or buffer)
+ * at a time.
+ */
+ while (in < end) {
+ int j, k;
+
+ while (i < 3) {
+ n = (n << 8) | *in++;
+ i++;
+ }
+ i = 0;
+
+ if (data->line_length > 0) {
+ if (data->current_column >= data->line_length) {
+ data->current_column = 0;
+ *out++ = B64_CR;
+ *out++ = B64_LF;
+ data->output_length += 2;
+ }
+ data->current_column += 4; /* the bytes we are about to add */
+ }
+
+ for (j = 18; j >= 0; j -= 6) {
+ k = (n >> j) & 0x3F;
+ *out++ = base64_valuetocode[k];
+ }
+ n = 0;
+ data->output_length += 4;
+
+ if (data->output_length >= output_threshold) {
+ PR_ASSERT(data->output_length <= data->output_buflen);
+ if (data->output_fn != NULL) {
+ PRInt32 output_result;
+
+ output_result = data->output_fn(data->output_arg,
+ data->output_buffer,
+ (PRInt32)data->output_length);
+ if (output_result < 0)
+ return PR_FAILURE;
+
+ out = data->output_buffer;
+ data->output_length = 0;
+ } else {
+ /*
+ * Check that we are about to exit the loop. (Since we
+ * are over the threshold, there isn't enough room in the
+ * output buffer for another trip around.)
+ */
+ PR_ASSERT(in == end);
+ if (in < end) {
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
+ return PR_FAILURE;
+ }
+ }
+ }
+ }
+
+ return PR_SUCCESS;
+}
+
+static PRStatus
+pl_base64_encode_flush(PLBase64Encoder *data)
+{
+ int i = data->in_buffer_count;
+
+ if (i == 0 && data->output_length == 0)
+ return PR_SUCCESS;
+
+ if (i > 0) {
+ char *out = data->output_buffer + data->output_length;
+ PRUint32 n;
+ int j, k;
+
+ n = ((PRUint32)data->in_buffer[0]) << 16;
+ if (i > 1)
+ n |= ((PRUint32)data->in_buffer[1] << 8);
+
+ data->in_buffer_count = 0;
+
+ if (data->line_length > 0) {
+ if (data->current_column >= data->line_length) {
+ data->current_column = 0;
+ *out++ = B64_CR;
+ *out++ = B64_LF;
+ data->output_length += 2;
+ }
+ }
+
+ /*
+ * This will fill in more than we really have data for, but the
+ * valid parts will end up in the correct position and the extras
+ * will be over-written with pad characters below.
+ */
+ for (j = 18; j >= 0; j -= 6) {
+ k = (n >> j) & 0x3F;
+ *out++ = base64_valuetocode[k];
+ }
+
+ /* Pad with equal-signs. */
+ if (i == 1)
+ out[-2] = B64_PAD;
+ out[-1] = B64_PAD;
+
+ data->output_length += 4;
+ }
+
+ if (data->output_fn != NULL) {
+ PRInt32 output_result;
+
+ output_result = data->output_fn(data->output_arg, data->output_buffer,
+ (PRInt32)data->output_length);
+ data->output_length = 0;
+
+ if (output_result < 0)
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+/*
+ * The maximum space needed to hold the output of the encoder given input
+ * data of length "size", and allowing for CRLF added at least every
+ * line_length bytes (we will add it at nearest lower multiple of 4).
+ * There is no trailing CRLF.
+ */
+static PRUint32
+PL_Base64MaxEncodedLength(PRUint32 size, PRUint32 line_length)
+{
+ PRUint32 tokens, tokens_per_line, full_lines, line_break_chars, remainder;
+
+ /* This is the maximum length we support. */
+ if (size > 0x3fffffff) {
+ return 0;
+ }
+
+ tokens = (size + 2) / 3;
+
+ if (line_length == 0) {
+ return tokens * 4;
+ }
+
+ if (line_length < 4) { /* too small! */
+ line_length = 4;
+ }
+
+ tokens_per_line = line_length / 4;
+ full_lines = tokens / tokens_per_line;
+ remainder = (tokens - (full_lines * tokens_per_line)) * 4;
+ line_break_chars = full_lines * 2;
+ if (remainder == 0) {
+ line_break_chars -= 2;
+ }
+
+ return (full_lines * tokens_per_line * 4) + line_break_chars + remainder;
+}
+
+/*
+ * A distinct internal creation function for the buffer version to use.
+ * (It does not want to specify an output_fn, and we want the normal
+ * Create function to require that.) All common initialization of the
+ * encoding context should be done *here*.
+ *
+ * Save "line_length", rounded down to nearest multiple of 4 (if not
+ * already even multiple). Allocate output_buffer, if not provided --
+ * based on given size if specified, otherwise based on line_length.
+ */
+static PLBase64Encoder *
+pl_base64_create_encoder(PRUint32 line_length, char *output_buffer,
+ PRUint32 output_buflen)
+{
+ PLBase64Encoder *data;
+ PRUint32 line_tokens;
+
+ data = PR_NEWZAP(PLBase64Encoder);
+ if (data == NULL)
+ return NULL;
+
+ if (line_length > 0 && line_length < 4) /* too small! */
+ line_length = 4;
+
+ line_tokens = line_length / 4;
+ data->line_length = line_tokens * 4;
+
+ if (output_buffer == NULL) {
+ if (output_buflen == 0) {
+ if (data->line_length > 0) /* need to include room for CRLF */
+ output_buflen = data->line_length + 2;
+ else
+ output_buflen = 64; /* XXX what is a good size? */
+ }
+
+ output_buffer = (char *)PR_Malloc(output_buflen);
+ if (output_buffer == NULL) {
+ PR_Free(data);
+ return NULL;
+ }
+ }
+
+ data->output_buffer = output_buffer;
+ data->output_buflen = output_buflen;
+ return data;
+}
+
+/*
+ * Function to start a base64 encoding context.
+ * An "output_fn" is required; the "output_arg" parameter to that is optional.
+ * If linebreaks in the encoded output are desired, "line_length" specifies
+ * where to place them -- it will be rounded down to the nearest multiple of 4
+ * (if it is not already an even multiple of 4). If it is zero, no linebreaks
+ * will be added. (FYI, a linebreak is CRLF -- two characters.)
+ */
+static PLBase64Encoder *
+PL_CreateBase64Encoder(PRInt32 (*output_fn)(void *, const char *, PRInt32),
+ void *output_arg, PRUint32 line_length)
+{
+ PLBase64Encoder *data;
+
+ if (output_fn == NULL) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+
+ data = pl_base64_create_encoder(line_length, NULL, 0);
+ if (data == NULL)
+ return NULL;
+
+ data->output_fn = output_fn;
+ data->output_arg = output_arg;
+
+ return data;
+}
+
+/*
+ * Push data through the encoder, causing the output_fn (provided to Create)
+ * to be called with the encoded data.
+ */
+static PRStatus
+PL_UpdateBase64Encoder(PLBase64Encoder *data, const unsigned char *buffer,
+ PRUint32 size)
+{
+ /* XXX Should we do argument checking only in debug build? */
+ if (data == NULL || buffer == NULL || size == 0) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ return pl_base64_encode_buffer(data, buffer, size);
+}
+
+/*
+ * When you're done encoding, call this to free the data. If "abort_p"
+ * is false, then calling this may cause the output_fn to be called
+ * one last time (as the last buffered data is flushed out).
+ */
+static PRStatus
+PL_DestroyBase64Encoder(PLBase64Encoder *data, PRBool abort_p)
+{
+ PRStatus status = PR_SUCCESS;
+
+ /* XXX Should we do argument checking only in debug build? */
+ if (data == NULL) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return PR_FAILURE;
+ }
+
+ /* Flush out the last few buffered characters. */
+ if (!abort_p)
+ status = pl_base64_encode_flush(data);
+
+ if (data->output_buffer != NULL)
+ PR_Free(data->output_buffer);
+ PR_Free(data);
+
+ return status;
+}
+
+/*
+ * Perform base64 encoding from an input buffer to an output buffer.
+ * The output buffer can be provided (as "dest"); you can also pass in
+ * a NULL and this function will allocate a buffer large enough for you,
+ * and return it. If you do provide the output buffer, you must also
+ * provide the maximum length of that buffer (as "maxdestlen").
+ * The actual encoded length of output will be returned to you in
+ * "output_destlen".
+ *
+ * If linebreaks in the encoded output are desired, "line_length" specifies
+ * where to place them -- it will be rounded down to the nearest multiple of 4
+ * (if it is not already an even multiple of 4). If it is zero, no linebreaks
+ * will be added. (FYI, a linebreak is CRLF -- two characters.)
+ *
+ * Return value is NULL on error, the output buffer (allocated or provided)
+ * otherwise.
+ */
+static char *
+PL_Base64EncodeBuffer(const unsigned char *src, PRUint32 srclen,
+ PRUint32 line_length, char *dest, PRUint32 maxdestlen,
+ PRUint32 *output_destlen)
+{
+ PRUint32 need_length;
+ PLBase64Encoder *data = NULL;
+ PRStatus status;
+
+ PR_ASSERT(srclen > 0);
+ if (srclen == 0) {
+ return dest;
+ }
+
+ /*
+ * How much space could we possibly need for encoding this input?
+ */
+ need_length = PL_Base64MaxEncodedLength(srclen, line_length);
+ if (need_length == 0) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ /*
+ * Make sure we have at least that much, if output buffer provided.
+ */
+ if (dest != NULL) {
+ PR_ASSERT(maxdestlen >= need_length);
+ if (maxdestlen < need_length) {
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
+ return NULL;
+ }
+ } else {
+ maxdestlen = need_length;
+ }
+
+ data = pl_base64_create_encoder(line_length, dest, maxdestlen);
+ if (data == NULL)
+ return NULL;
+
+ status = pl_base64_encode_buffer(data, src, srclen);
+
+ /*
+ * We do not wait for Destroy to flush, because Destroy will also
+ * get rid of our encoder context, which we need to look at first!
+ */
+ if (status == PR_SUCCESS)
+ status = pl_base64_encode_flush(data);
+
+ if (status != PR_SUCCESS) {
+ (void)PL_DestroyBase64Encoder(data, PR_TRUE);
+ return NULL;
+ }
+
+ dest = data->output_buffer;
+
+ /* Must clear this or Destroy will free it. */
+ data->output_buffer = NULL;
+
+ *output_destlen = data->output_length;
+ status = PL_DestroyBase64Encoder(data, PR_FALSE);
+ if (status == PR_FAILURE) {
+ PR_Free(dest);
+ return NULL;
+ }
+
+ return dest;
+}
+
+/*
+ * XXX End of base64 encoding code to be moved into NSPR.
+ ********************************************************
+ */
+
+/*
+ * This is the beginning of the NSS cover functions. These will
+ * provide the interface we want to expose as NSS-ish. For example,
+ * they will operate on our Items, do any special handling or checking
+ * we want to do, etc.
+ */
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * A boring cover structure for now. Perhaps someday it will include
+ * some more interesting fields.
+ */
+struct NSSBase64EncoderStr {
+ PLBase64Encoder *pl_data;
+};
+
+PR_END_EXTERN_C
+
+/*
+ * Function to start a base64 encoding context.
+ */
+NSSBase64Encoder *
+NSSBase64Encoder_Create(PRInt32 (*output_fn)(void *, const char *, PRInt32),
+ void *output_arg)
+{
+ PLBase64Encoder *pl_data;
+ NSSBase64Encoder *nss_data;
+
+ nss_data = PORT_ZNew(NSSBase64Encoder);
+ if (nss_data == NULL)
+ return NULL;
+
+ pl_data = PL_CreateBase64Encoder(output_fn, output_arg, 64);
+ if (pl_data == NULL) {
+ PORT_Free(nss_data);
+ return NULL;
+ }
+
+ nss_data->pl_data = pl_data;
+ return nss_data;
+}
+
+/*
+ * Push data through the encoder, causing the output_fn (provided to Create)
+ * to be called with the encoded data.
+ */
+SECStatus
+NSSBase64Encoder_Update(NSSBase64Encoder *data, const unsigned char *buffer,
+ PRUint32 size)
+{
+ PRStatus pr_status;
+
+ /* XXX Should we do argument checking only in debug build? */
+ if (data == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ pr_status = PL_UpdateBase64Encoder(data->pl_data, buffer, size);
+ if (pr_status == PR_FAILURE)
+ return SECFailure;
+
+ return SECSuccess;
+}
+
+/*
+ * When you're done encoding, call this to free the data. If "abort_p"
+ * is false, then calling this may cause the output_fn to be called
+ * one last time (as the last buffered data is flushed out).
+ */
+SECStatus
+NSSBase64Encoder_Destroy(NSSBase64Encoder *data, PRBool abort_p)
+{
+ PRStatus pr_status;
+
+ /* XXX Should we do argument checking only in debug build? */
+ if (data == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ pr_status = PL_DestroyBase64Encoder(data->pl_data, abort_p);
+
+ PORT_Free(data);
+
+ if (pr_status == PR_FAILURE)
+ return SECFailure;
+
+ return SECSuccess;
+}
+
+/*
+ * Perform base64 encoding of binary data "inItem" to an ascii string.
+ * The output buffer may be provided (as "outStrOpt"); you can also pass
+ * in a NULL and the buffer will be allocated for you. The result will
+ * be null-terminated, and if the buffer is provided, "maxOutLen" must
+ * specify the maximum length of the buffer and will be checked to
+ * supply sufficient space space for the encoded result. (If "outStrOpt"
+ * is NULL, "maxOutLen" is ignored.)
+ *
+ * If "outStrOpt" is NULL, allocation will happen out of the passed-in
+ * "arenaOpt", if *it* is non-NULL, otherwise standard allocation (heap)
+ * will be used.
+ *
+ * Return value is NULL on error, the output buffer (allocated or provided)
+ * otherwise.
+ */
+char *
+NSSBase64_EncodeItem(PLArenaPool *arenaOpt, char *outStrOpt,
+ unsigned int maxOutLen, SECItem *inItem)
+{
+ char *out_string = outStrOpt;
+ PRUint32 max_out_len;
+ PRUint32 out_len = 0;
+ void *mark = NULL;
+ char *dummy;
+
+ PORT_Assert(inItem != NULL && inItem->data != NULL && inItem->len != 0);
+ if (inItem == NULL || inItem->data == NULL || inItem->len == 0) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ max_out_len = PL_Base64MaxEncodedLength(inItem->len, 64);
+ if (max_out_len == 0) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ if (arenaOpt != NULL)
+ mark = PORT_ArenaMark(arenaOpt);
+
+ if (out_string == NULL) {
+ if (arenaOpt != NULL)
+ out_string = PORT_ArenaAlloc(arenaOpt, max_out_len + 1);
+ else
+ out_string = PORT_Alloc(max_out_len + 1);
+
+ if (out_string == NULL) {
+ if (arenaOpt != NULL)
+ PORT_ArenaRelease(arenaOpt, mark);
+ return NULL;
+ }
+ } else {
+ if ((max_out_len + 1) > maxOutLen) {
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ return NULL;
+ }
+ max_out_len = maxOutLen;
+ }
+
+ dummy = PL_Base64EncodeBuffer(inItem->data, inItem->len, 64,
+ out_string, max_out_len, &out_len);
+ if (dummy == NULL) {
+ if (arenaOpt != NULL) {
+ PORT_ArenaRelease(arenaOpt, mark);
+ } else {
+ PORT_Free(out_string);
+ }
+ return NULL;
+ }
+
+ if (arenaOpt != NULL)
+ PORT_ArenaUnmark(arenaOpt, mark);
+
+ out_string[out_len] = '\0';
+ return out_string;
+}
+
+/*
+ * XXX Everything below is deprecated. If you add new stuff, put it
+ * *above*, not below.
+ */
+
+/*
+ * XXX The following "BTOA" functions are provided for backward compatibility
+ * with current code. They should be considered strongly deprecated.
+ * When we can convert all our code over to using the new NSSBase64Encoder_
+ * functions defined above, we should get rid of these altogether. (Remove
+ * protoypes from base64.h as well -- actually, remove that file completely).
+ * If someone thinks either of these functions provides such a very useful
+ * interface (though, as shown, the same functionality can already be
+ * obtained by calling NSSBase64_EncodeItem directly), fine -- but then
+ * that API should be provided with a nice new NSSFoo name and using
+ * appropriate types, etc.
+ */
+
+#include "base64.h"
+
+/*
+** Return an PORT_Alloc'd ascii string which is the base64 encoded
+** version of the input string.
+*/
+char *
+BTOA_DataToAscii(const unsigned char *data, unsigned int len)
+{
+ SECItem binary_item;
+
+ binary_item.data = (unsigned char *)data;
+ binary_item.len = len;
+
+ return NSSBase64_EncodeItem(NULL, NULL, 0, &binary_item);
+}
+
+/*
+** Convert from binary encoding of an item to ascii.
+*/
+char *
+BTOA_ConvertItemToAscii(SECItem *binary_item)
+{
+ return NSSBase64_EncodeItem(NULL, NULL, 0, binary_item);
+}
diff --git a/security/nss/lib/util/nssb64t.h b/security/nss/lib/util/nssb64t.h
new file mode 100644
index 0000000000..75e7877bc3
--- /dev/null
+++ b/security/nss/lib/util/nssb64t.h
@@ -0,0 +1,15 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Public data structures for base64 encoding/decoding.
+ */
+#ifndef _NSSB64T_H_
+#define _NSSB64T_H_
+
+#include "utilrename.h"
+typedef struct NSSBase64DecoderStr NSSBase64Decoder;
+typedef struct NSSBase64EncoderStr NSSBase64Encoder;
+
+#endif /* _NSSB64T_H_ */
diff --git a/security/nss/lib/util/nssilckt.h b/security/nss/lib/util/nssilckt.h
new file mode 100644
index 0000000000..417f96f67a
--- /dev/null
+++ b/security/nss/lib/util/nssilckt.h
@@ -0,0 +1,191 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+** nssilock.h - Instrumented locking functions for NSS
+**
+** Description:
+** nssilock provides instrumentation for locks and monitors in
+** the NSS libraries. The instrumentation, when enabled, causes
+** each call to the instrumented function to record data about
+** the call to an external file. The external file
+** subsequently used to extract performance data and other
+** statistical information about the operation of locks used in
+** the nss library.
+**
+** To enable compilation with instrumentation, build NSS with
+** the compile time switch NEED_NSS_ILOCK defined.
+**
+** say: "gmake OS_CFLAGS+=-DNEED_NSS_ILOCK" at make time.
+**
+** At runtime, to enable recording from nssilock, one or more
+** environment variables must be set. For each nssILockType to
+** be recorded, an environment variable of the form NSS_ILOCK_x
+** must be set to 1. For example:
+**
+** set NSS_ILOCK_Cert=1
+**
+** nssilock uses PRLOG is used to record to trace data. The
+** PRLogModule name associated with nssilock data is: "nssilock".
+** To enable recording of nssilock data you will need to set the
+** environment variable NSPR_LOG_MODULES to enable
+** recording for the nssilock log module. Similarly, you will
+** need to set the environment variable NSPR_LOG_FILE to specify
+** the filename to receive the recorded data. See prlog.h for usage.
+** Example:
+**
+** export NSPR_LOG_MODULES=nssilock:6
+** export NSPR_LOG_FILE=xxxLogfile
+**
+** Operation:
+** nssilock wraps calls to NSPR's PZLock and PZMonitor functions
+** with similarly named functions: PZ_NewLock(), etc. When NSS is
+** built with lock instrumentation enabled, the PZ* functions are
+** compiled into NSS; when lock instrumentation is disabled,
+** calls to PZ* functions are directly mapped to PR* functions
+** and the instrumentation arguments to the PZ* functions are
+** compiled away.
+**
+**
+** File Format:
+** The format of the external file is implementation
+** dependent. Where NSPR's PR_LOG() function is used, the file
+** contains data defined for PR_LOG() plus the data written by
+** the wrapped function. On some platforms and under some
+** circumstances, platform dependent logging or
+** instrumentation probes may be used. In any case, the
+** relevant data provided by the lock instrumentation is:
+**
+** lockType, func, address, duration, line, file [heldTime]
+**
+** where:
+**
+** lockType: a character representation of nssILockType for the
+** call. e.g. ... "cert"
+**
+** func: the function doing the tracing. e.g. "NewLock"
+**
+** address: address of the instrumented lock or monitor
+**
+** duration: is how long was spent in the instrumented function,
+** in PRIntervalTime "ticks".
+**
+** line: the line number within the calling function
+**
+** file: the file from which the call was made
+**
+** heldTime: how long the lock/monitor was held. field
+** present only for PZ_Unlock() and PZ_ExitMonitor().
+**
+** Design Notes:
+** The design for lock instrumentation was influenced by the
+** need to gather performance data on NSS 3.x. It is intended
+** that the effort to modify NSS to use lock instrumentation
+** be minimized. Existing calls to locking functions need only
+** have their names changed to the instrumentation function
+** names.
+**
+** Private NSS Interface:
+** nssilock.h defines a private interface for use by NSS.
+** nssilock.h is experimental in nature and is subject to
+** change or revocation without notice. ... Don't mess with
+** it.
+**
+*/
+
+/*
+ * $Id:
+ */
+
+#ifndef _NSSILCKT_H_
+#define _NSSILCKT_H_
+
+#include "utilrename.h"
+#include "prtypes.h"
+#include "prmon.h"
+#include "prlock.h"
+#include "prcvar.h"
+
+typedef enum {
+ nssILockArena = 0,
+ nssILockSession = 1,
+ nssILockObject = 2,
+ nssILockRefLock = 3,
+ nssILockCert = 4,
+ nssILockCertDB = 5,
+ nssILockDBM = 6,
+ nssILockCache = 7,
+ nssILockSSL = 8,
+ nssILockList = 9,
+ nssILockSlot = 10,
+ nssILockFreelist = 11,
+ nssILockOID = 12,
+ nssILockAttribute = 13,
+ nssILockPK11cxt = 14, /* pk11context */
+ nssILockRWLock = 15,
+ nssILockOther = 16,
+ nssILockSelfServ = 17,
+ nssILockKeyDB = 18,
+ nssILockLast /* don't use this one! */
+} nssILockType;
+
+/*
+** conditionally compile in nssilock features
+*/
+#if defined(NEED_NSS_ILOCK)
+
+/*
+** Declare operation type enumerator
+** enumerations identify the function being performed
+*/
+typedef enum {
+ FlushTT = 0,
+ NewLock = 1,
+ Lock = 2,
+ Unlock = 3,
+ DestroyLock = 4,
+ NewCondVar = 5,
+ WaitCondVar = 6,
+ NotifyCondVar = 7,
+ NotifyAllCondVar = 8,
+ DestroyCondVar = 9,
+ NewMonitor = 10,
+ EnterMonitor = 11,
+ ExitMonitor = 12,
+ Notify = 13,
+ NotifyAll = 14,
+ Wait = 15,
+ DestroyMonitor = 16
+} nssILockOp;
+
+/*
+** Declare the trace record
+*/
+struct pzTrace_s {
+ PRUint32 threadID; /* PR_GetThreadID() */
+ nssILockOp op; /* operation being performed */
+ nssILockType ltype; /* lock type identifier */
+ PRIntervalTime callTime; /* time spent in function */
+ PRIntervalTime heldTime; /* lock held time, or -1 */
+ void *lock; /* address of lock structure */
+ PRIntn line; /* line number */
+ char file[24]; /* filename */
+};
+
+/*
+** declare opaque types. See: nssilock.c
+*/
+typedef struct pzlock_s PZLock;
+typedef struct pzcondvar_s PZCondVar;
+typedef struct pzmonitor_s PZMonitor;
+
+#else /* NEED_NSS_ILOCK */
+
+#define PZLock PRLock
+#define PZCondVar PRCondVar
+#define PZMonitor PRMonitor
+
+#endif /* NEED_NSS_ILOCK */
+
+#endif /* _NSSILCKT_H_ */
diff --git a/security/nss/lib/util/nssilock.c b/security/nss/lib/util/nssilock.c
new file mode 100644
index 0000000000..d767209429
--- /dev/null
+++ b/security/nss/lib/util/nssilock.c
@@ -0,0 +1,479 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * nssilock.c - NSS lock instrumentation wrapper functions
+ *
+ * NOTE - These are not public interfaces
+ *
+ * Implementation Notes:
+ * I've tried to make the instrumentation relatively non-intrusive.
+ * To do this, I have used a single PR_LOG() call in each
+ * instrumented function. There's room for improvement.
+ *
+ *
+ */
+
+#include "prinit.h"
+#include "prerror.h"
+#include "prlock.h"
+#include "prmem.h"
+#include "prenv.h"
+#include "prcvar.h"
+#include "prio.h"
+
+#if defined(NEED_NSS_ILOCK)
+#include "prlog.h"
+#include "nssilock.h"
+
+/*
+** Declare the instrumented PZLock
+*/
+struct pzlock_s {
+ PRLock *lock; /* the PZLock to be instrumented */
+ PRIntervalTime time; /* timestamp when the lock was aquired */
+ nssILockType ltype;
+};
+
+/*
+** Declare the instrumented PZMonitor
+*/
+struct pzmonitor_s {
+ PRMonitor *mon; /* the PZMonitor to be instrumented */
+ PRIntervalTime time; /* timestamp when the monitor was aquired */
+ nssILockType ltype;
+};
+
+/*
+** Declare the instrumented PZCondVar
+*/
+struct pzcondvar_s {
+ PRCondVar *cvar; /* the PZCondVar to be instrumented */
+ nssILockType ltype;
+};
+
+/*
+** Define a CallOnce type to ensure serialized self-initialization
+*/
+static PRCallOnceType coNssILock; /* CallOnce type */
+static PRIntn nssILockInitialized; /* initialization done when 1 */
+static PRLogModuleInfo *nssILog; /* Log instrumentation to this handle */
+
+#define NUM_TT_ENTRIES 6000000
+static PRInt32 traceIndex = -1; /* index into trace table */
+static struct pzTrace_s *tt; /* pointer to trace table */
+static PRInt32 ttBufSize = (NUM_TT_ENTRIES * sizeof(struct pzTrace_s));
+static PRCondVar *ttCVar;
+static PRLock *ttLock;
+static PRFileDesc *ttfd; /* trace table file */
+
+/*
+** Vtrace() -- Trace events, write events to external media
+**
+** Vtrace() records traced events in an in-memory trace table
+** when the trace table fills, Vtrace writes the entire table
+** to a file.
+**
+** data can be lost!
+**
+*/
+static void
+Vtrace(
+ nssILockOp op,
+ nssILockType ltype,
+ PRIntervalTime callTime,
+ PRIntervalTime heldTime,
+ void *lock,
+ PRIntn line,
+ char *file)
+{
+ PRInt32 idx;
+ struct pzTrace_s *tp;
+
+RetryTrace:
+ idx = PR_ATOMIC_INCREMENT(&traceIndex);
+ while (NUM_TT_ENTRIES <= idx || op == FlushTT) {
+ if (NUM_TT_ENTRIES == idx || op == FlushTT) {
+ int writeSize = idx * sizeof(struct pzTrace_s);
+ PR_Lock(ttLock);
+ PR_Write(ttfd, tt, writeSize);
+ traceIndex = -1;
+ PR_NotifyAllCondVar(ttCVar);
+ PR_Unlock(ttLock);
+ goto RetryTrace;
+ } else {
+ PR_Lock(ttLock);
+ while (NUM_TT_ENTRIES < idx)
+ PR_WaitCondVar(ttCVar, PR_INTERVAL_NO_WAIT);
+ PR_Unlock(ttLock);
+ goto RetryTrace;
+ }
+ } /* end while() */
+
+ /* create the trace entry */
+ tp = tt + idx;
+ tp->threadID = PR_GetThreadID(PR_GetCurrentThread());
+ tp->op = op;
+ tp->ltype = ltype;
+ tp->callTime = callTime;
+ tp->heldTime = heldTime;
+ tp->lock = lock;
+ tp->line = line;
+ strcpy(tp->file, file);
+ return;
+} /* --- end Vtrace() --- */
+
+/*
+** pz_TraceFlush() -- Force trace table write to file
+**
+*/
+extern void
+pz_TraceFlush(void)
+{
+ Vtrace(FlushTT, nssILockSelfServ, 0, 0, NULL, 0, "");
+ return;
+} /* --- end pz_TraceFlush() --- */
+
+/*
+** nssILockInit() -- Initialization for nssilock
+**
+** This function is called from the CallOnce mechanism.
+*/
+static PRStatus
+nssILockInit(void)
+{
+ int i;
+ nssILockInitialized = 1;
+
+ /* new log module */
+ nssILog = PR_NewLogModule("nssilock");
+ if (NULL == nssILog) {
+ return (PR_FAILURE);
+ }
+
+ tt = PR_Calloc(NUM_TT_ENTRIES, sizeof(struct pzTrace_s));
+ if (NULL == tt) {
+ fprintf(stderr, "nssilock: can't allocate trace table\n");
+ exit(1);
+ }
+
+ ttfd = PR_Open("xxxTTLog", PR_CREATE_FILE | PR_WRONLY, 0666);
+ if (NULL == ttfd) {
+ fprintf(stderr, "Oh Drat! Can't open 'xxxTTLog'\n");
+ exit(1);
+ }
+
+ ttLock = PR_NewLock();
+ ttCVar = PR_NewCondVar(ttLock);
+
+ return (PR_SUCCESS);
+} /* --- end nssILockInit() --- */
+
+extern PZLock *
+pz_NewLock(
+ nssILockType ltype,
+ char *file,
+ PRIntn line)
+{
+ PRStatus rc;
+ PZLock *lock;
+
+ /* Self Initialize the nssILock feature */
+ if (!nssILockInitialized) {
+ rc = PR_CallOnce(&coNssILock, nssILockInit);
+ if (PR_FAILURE == rc) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return (NULL);
+ }
+ }
+
+ lock = PR_NEWZAP(PZLock);
+ if (NULL != lock) {
+ lock->ltype = ltype;
+ lock->lock = PR_NewLock();
+ if (NULL == lock->lock) {
+ PR_DELETE(lock);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ }
+ } else {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ }
+
+ Vtrace(NewLock, ltype, 0, 0, lock, line, file);
+ return (lock);
+} /* --- end pz_NewLock() --- */
+
+extern void
+pz_Lock(
+ PZLock *lock,
+ char *file,
+ PRIntn line)
+{
+ PRIntervalTime callTime;
+
+ callTime = PR_IntervalNow();
+ PR_Lock(lock->lock);
+ lock->time = PR_IntervalNow();
+ callTime = lock->time - callTime;
+
+ Vtrace(Lock, lock->ltype, callTime, 0, lock, line, file);
+ return;
+} /* --- end pz_Lock() --- */
+
+extern PRStatus
+pz_Unlock(
+ PZLock *lock,
+ char *file,
+ PRIntn line)
+{
+ PRStatus rc;
+ PRIntervalTime callTime, now, heldTime;
+
+ callTime = PR_IntervalNow();
+ rc = PR_Unlock(lock->lock);
+ now = PR_IntervalNow();
+ callTime = now - callTime;
+ heldTime = now - lock->time;
+ Vtrace(Unlock, lock->ltype, callTime, heldTime, lock, line, file);
+ return (rc);
+} /* --- end pz_Unlock() --- */
+
+extern void
+pz_DestroyLock(
+ PZLock *lock,
+ char *file,
+ PRIntn line)
+{
+ Vtrace(DestroyLock, lock->ltype, 0, 0, lock, line, file);
+ PR_DestroyLock(lock->lock);
+ PR_DELETE(lock);
+ return;
+} /* --- end pz_DestroyLock() --- */
+
+extern PZCondVar *
+pz_NewCondVar(
+ PZLock *lock,
+ char *file,
+ PRIntn line)
+{
+ PZCondVar *cvar;
+
+ cvar = PR_NEWZAP(PZCondVar);
+ if (NULL == cvar) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ } else {
+ cvar->ltype = lock->ltype;
+ cvar->cvar = PR_NewCondVar(lock->lock);
+ if (NULL == cvar->cvar) {
+ PR_DELETE(cvar);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ }
+ }
+ Vtrace(NewCondVar, lock->ltype, 0, 0, cvar, line, file);
+ return (cvar);
+} /* --- end pz_NewCondVar() --- */
+
+extern void
+pz_DestroyCondVar(
+ PZCondVar *cvar,
+ char *file,
+ PRIntn line)
+{
+ Vtrace(DestroyCondVar, cvar->ltype, 0, 0, cvar, line, file);
+ PR_DestroyCondVar(cvar->cvar);
+ PR_DELETE(cvar);
+} /* --- end pz_DestroyCondVar() --- */
+
+extern PRStatus
+pz_WaitCondVar(
+ PZCondVar *cvar,
+ PRIntervalTime timeout,
+ char *file,
+ PRIntn line)
+{
+ PRStatus rc;
+ PRIntervalTime callTime;
+
+ callTime = PR_IntervalNow();
+ rc = PR_WaitCondVar(cvar->cvar, timeout);
+ callTime = PR_IntervalNow() - callTime;
+
+ Vtrace(WaitCondVar, cvar->ltype, callTime, 0, cvar, line, file);
+ return (rc);
+} /* --- end pz_WaitCondVar() --- */
+
+extern PRStatus
+pz_NotifyCondVar(
+ PZCondVar *cvar,
+ char *file,
+ PRIntn line)
+{
+ PRStatus rc;
+
+ rc = PR_NotifyCondVar(cvar->cvar);
+
+ Vtrace(NotifyCondVar, cvar->ltype, 0, 0, cvar, line, file);
+ return (rc);
+} /* --- end pz_NotifyCondVar() --- */
+
+extern PRStatus
+pz_NotifyAllCondVar(
+ PZCondVar *cvar,
+ char *file,
+ PRIntn line)
+{
+ PRStatus rc;
+
+ rc = PR_NotifyAllCondVar(cvar->cvar);
+
+ Vtrace(NotifyAllCondVar, cvar->ltype, 0, 0, cvar, line, file);
+ return (rc);
+} /* --- end pz_NotifyAllCondVar() --- */
+
+extern PZMonitor *
+pz_NewMonitor(
+ nssILockType ltype,
+ char *file,
+ PRIntn line)
+{
+ PRStatus rc;
+ PZMonitor *mon;
+
+ /* Self Initialize the nssILock feature */
+ if (!nssILockInitialized) {
+ rc = PR_CallOnce(&coNssILock, nssILockInit);
+ if (PR_FAILURE == rc) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ return (NULL);
+ }
+ }
+
+ mon = PR_NEWZAP(PZMonitor);
+ if (NULL != mon) {
+ mon->ltype = ltype;
+ mon->mon = PR_NewMonitor();
+ if (NULL == mon->mon) {
+ PR_DELETE(mon);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ }
+ } else {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ }
+
+ Vtrace(NewMonitor, ltype, 0, 0, mon, line, file);
+ return (mon);
+} /* --- end pz_NewMonitor() --- */
+
+extern void
+pz_DestroyMonitor(
+ PZMonitor *mon,
+ char *file,
+ PRIntn line)
+{
+ Vtrace(DestroyMonitor, mon->ltype, 0, 0, mon, line, file);
+ PR_DestroyMonitor(mon->mon);
+ PR_DELETE(mon);
+ return;
+} /* --- end pz_DestroyMonitor() --- */
+
+extern void
+pz_EnterMonitor(
+ PZMonitor *mon,
+ char *file,
+ PRIntn line)
+{
+ PRIntervalTime callTime, now;
+
+ callTime = PR_IntervalNow();
+ PR_EnterMonitor(mon->mon);
+ now = PR_IntervalNow();
+ callTime = now - callTime;
+ if (PR_GetMonitorEntryCount(mon->mon) == 1) {
+ mon->time = now;
+ }
+ Vtrace(EnterMonitor, mon->ltype, callTime, 0, mon, line, file);
+ return;
+} /* --- end pz_EnterMonitor() --- */
+
+extern PRStatus
+pz_ExitMonitor(
+ PZMonitor *mon,
+ char *file,
+ PRIntn line)
+{
+ PRStatus rc;
+ PRIntervalTime callTime, now, heldTime;
+ PRIntn mec = PR_GetMonitorEntryCount(mon->mon);
+
+ heldTime = (PRIntervalTime)-1;
+ callTime = PR_IntervalNow();
+ rc = PR_ExitMonitor(mon->mon);
+ now = PR_IntervalNow();
+ callTime = now - callTime;
+ if (mec == 1)
+ heldTime = now - mon->time;
+ Vtrace(ExitMonitor, mon->ltype, callTime, heldTime, mon, line, file);
+ return (rc);
+} /* --- end pz_ExitMonitor() --- */
+
+extern PRIntn
+pz_GetMonitorEntryCount(
+ PZMonitor *mon,
+ char *file,
+ PRIntn line)
+{
+ return (PR_GetMonitorEntryCount(mon->mon));
+} /* --- end pz_GetMonitorEntryCount() --- */
+
+extern PRStatus
+pz_Wait(
+ PZMonitor *mon,
+ PRIntervalTime ticks,
+ char *file,
+ PRIntn line)
+{
+ PRStatus rc;
+ PRIntervalTime callTime;
+
+ callTime = PR_IntervalNow();
+ rc = PR_Wait(mon->mon, ticks);
+ callTime = PR_IntervalNow() - callTime;
+ Vtrace(Wait, mon->ltype, callTime, 0, mon, line, file);
+ return (rc);
+} /* --- end pz_Wait() --- */
+
+extern PRStatus
+pz_Notify(
+ PZMonitor *mon,
+ char *file,
+ PRIntn line)
+{
+ PRStatus rc;
+ PRIntervalTime callTime;
+
+ callTime = PR_IntervalNow();
+ rc = PR_Notify(mon->mon);
+ callTime = PR_IntervalNow() - callTime;
+ Vtrace(Notify, mon->ltype, callTime, 0, mon, line, file);
+ return (rc);
+} /* --- end pz_Notify() --- */
+
+extern PRStatus
+pz_NotifyAll(
+ PZMonitor *mon,
+ char *file,
+ PRIntn line)
+{
+ PRStatus rc;
+ PRIntervalTime callTime;
+
+ callTime = PR_IntervalNow();
+ rc = PR_NotifyAll(mon->mon);
+ callTime = PR_IntervalNow() - callTime;
+ Vtrace(NotifyAll, mon->ltype, callTime, 0, mon, line, file);
+ return (rc);
+} /* --- end pz_NotifyAll() --- */
+
+#endif /* NEED_NSS_ILOCK */
+/* --- end nssilock.c --------------------------------- */
diff --git a/security/nss/lib/util/nssilock.h b/security/nss/lib/util/nssilock.h
new file mode 100644
index 0000000000..01f666a799
--- /dev/null
+++ b/security/nss/lib/util/nssilock.h
@@ -0,0 +1,267 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+** nssilock.h - Instrumented locking functions for NSS
+**
+** Description:
+** nssilock provides instrumentation for locks and monitors in
+** the NSS libraries. The instrumentation, when enabled, causes
+** each call to the instrumented function to record data about
+** the call to an external file. The external file
+** subsequently used to extract performance data and other
+** statistical information about the operation of locks used in
+** the nss library.
+**
+** To enable compilation with instrumentation, build NSS with
+** the compile time switch NEED_NSS_ILOCK defined.
+**
+** say: "gmake OS_CFLAGS+=-DNEED_NSS_ILOCK" at make time.
+**
+** At runtime, to enable recording from nssilock, one or more
+** environment variables must be set. For each nssILockType to
+** be recorded, an environment variable of the form NSS_ILOCK_x
+** must be set to 1. For example:
+**
+** set NSS_ILOCK_Cert=1
+**
+** nssilock uses PRLOG is used to record to trace data. The
+** PRLogModule name associated with nssilock data is: "nssilock".
+** To enable recording of nssilock data you will need to set the
+** environment variable NSPR_LOG_MODULES to enable
+** recording for the nssilock log module. Similarly, you will
+** need to set the environment variable NSPR_LOG_FILE to specify
+** the filename to receive the recorded data. See prlog.h for usage.
+** Example:
+**
+** export NSPR_LOG_MODULES=nssilock:6
+** export NSPR_LOG_FILE=xxxLogfile
+**
+** Operation:
+** nssilock wraps calls to NSPR's PZLock and PZMonitor functions
+** with similarly named functions: PZ_NewLock(), etc. When NSS is
+** built with lock instrumentation enabled, the PZ* functions are
+** compiled into NSS; when lock instrumentation is disabled,
+** calls to PZ* functions are directly mapped to PR* functions
+** and the instrumentation arguments to the PZ* functions are
+** compiled away.
+**
+**
+** File Format:
+** The format of the external file is implementation
+** dependent. Where NSPR's PR_LOG() function is used, the file
+** contains data defined for PR_LOG() plus the data written by
+** the wrapped function. On some platforms and under some
+** circumstances, platform dependent logging or
+** instrumentation probes may be used. In any case, the
+** relevant data provided by the lock instrumentation is:
+**
+** lockType, func, address, duration, line, file [heldTime]
+**
+** where:
+**
+** lockType: a character representation of nssILockType for the
+** call. e.g. ... "cert"
+**
+** func: the function doing the tracing. e.g. "NewLock"
+**
+** address: address of the instrumented lock or monitor
+**
+** duration: is how long was spent in the instrumented function,
+** in PRIntervalTime "ticks".
+**
+** line: the line number within the calling function
+**
+** file: the file from which the call was made
+**
+** heldTime: how long the lock/monitor was held. field
+** present only for PZ_Unlock() and PZ_ExitMonitor().
+**
+** Design Notes:
+** The design for lock instrumentation was influenced by the
+** need to gather performance data on NSS 3.x. It is intended
+** that the effort to modify NSS to use lock instrumentation
+** be minimized. Existing calls to locking functions need only
+** have their names changed to the instrumentation function
+** names.
+**
+** Private NSS Interface:
+** nssilock.h defines a private interface for use by NSS.
+** nssilock.h is experimental in nature and is subject to
+** change or revocation without notice. ... Don't mess with
+** it.
+**
+*/
+
+/*
+ * $Id:
+ */
+
+#ifndef _NSSILOCK_H_
+#define _NSSILOCK_H_
+
+#include "utilrename.h"
+#include "prtypes.h"
+#include "prmon.h"
+#include "prlock.h"
+#include "prcvar.h"
+
+#include "nssilckt.h"
+
+PR_BEGIN_EXTERN_C
+
+#if defined(NEED_NSS_ILOCK)
+
+#define PZ_NewLock(t) pz_NewLock((t), __FILE__, __LINE__)
+extern PZLock *
+pz_NewLock(
+ nssILockType ltype,
+ char *file,
+ PRIntn line);
+
+#define PZ_Lock(k) pz_Lock((k), __FILE__, __LINE__)
+extern void
+pz_Lock(
+ PZLock *lock,
+ char *file,
+ PRIntn line);
+
+#define PZ_Unlock(k) pz_Unlock((k), __FILE__, __LINE__)
+extern PRStatus
+pz_Unlock(
+ PZLock *lock,
+ char *file,
+ PRIntn line);
+
+#define PZ_DestroyLock(k) pz_DestroyLock((k), __FILE__, __LINE__)
+extern void
+pz_DestroyLock(
+ PZLock *lock,
+ char *file,
+ PRIntn line);
+
+#define PZ_NewCondVar(l) pz_NewCondVar((l), __FILE__, __LINE__)
+extern PZCondVar *
+pz_NewCondVar(
+ PZLock *lock,
+ char *file,
+ PRIntn line);
+
+#define PZ_DestroyCondVar(v) pz_DestroyCondVar((v), __FILE__, __LINE__)
+extern void
+pz_DestroyCondVar(
+ PZCondVar *cvar,
+ char *file,
+ PRIntn line);
+
+#define PZ_WaitCondVar(v, t) pz_WaitCondVar((v), (t), __FILE__, __LINE__)
+extern PRStatus
+pz_WaitCondVar(
+ PZCondVar *cvar,
+ PRIntervalTime timeout,
+ char *file,
+ PRIntn line);
+
+#define PZ_NotifyCondVar(v) pz_NotifyCondVar((v), __FILE__, __LINE__)
+extern PRStatus
+pz_NotifyCondVar(
+ PZCondVar *cvar,
+ char *file,
+ PRIntn line);
+
+#define PZ_NotifyAllCondVar(v) pz_NotifyAllCondVar((v), __FILE__, __LINE__)
+extern PRStatus
+pz_NotifyAllCondVar(
+ PZCondVar *cvar,
+ char *file,
+ PRIntn line);
+
+#define PZ_NewMonitor(t) pz_NewMonitor((t), __FILE__, __LINE__)
+extern PZMonitor *
+pz_NewMonitor(
+ nssILockType ltype,
+ char *file,
+ PRIntn line);
+
+#define PZ_DestroyMonitor(m) pz_DestroyMonitor((m), __FILE__, __LINE__)
+extern void
+pz_DestroyMonitor(
+ PZMonitor *mon,
+ char *file,
+ PRIntn line);
+
+#define PZ_EnterMonitor(m) pz_EnterMonitor((m), __FILE__, __LINE__)
+extern void
+pz_EnterMonitor(
+ PZMonitor *mon,
+ char *file,
+ PRIntn line);
+
+#define PZ_ExitMonitor(m) pz_ExitMonitor((m), __FILE__, __LINE__)
+extern PRStatus
+pz_ExitMonitor(
+ PZMonitor *mon,
+ char *file,
+ PRIntn line);
+
+#define PZ_InMonitor(m) (PZ_GetMonitorEntryCount(m) > 0)
+#define PZ_GetMonitorEntryCount(m) pz_GetMonitorEntryCount((m), __FILE__, __LINE__)
+extern PRIntn
+pz_GetMonitorEntryCount(
+ PZMonitor *mon,
+ char *file,
+ PRIntn line);
+
+#define PZ_Wait(m, i) pz_Wait((m), ((i)), __FILE__, __LINE__)
+extern PRStatus
+pz_Wait(
+ PZMonitor *mon,
+ PRIntervalTime ticks,
+ char *file,
+ PRIntn line);
+
+#define PZ_Notify(m) pz_Notify((m), __FILE__, __LINE__)
+extern PRStatus
+pz_Notify(
+ PZMonitor *mon,
+ char *file,
+ PRIntn line);
+
+#define PZ_NotifyAll(m) pz_NotifyAll((m), __FILE__, __LINE__)
+extern PRStatus
+pz_NotifyAll(
+ PZMonitor *mon,
+ char *file,
+ PRIntn line);
+
+#define PZ_TraceFlush() pz_TraceFlush()
+extern void pz_TraceFlush(void);
+
+#else /* NEED_NSS_ILOCK */
+
+#define PZ_NewLock(t) PR_NewLock()
+#define PZ_DestroyLock(k) PR_DestroyLock((k))
+#define PZ_Lock(k) PR_Lock((k))
+#define PZ_Unlock(k) PR_Unlock((k))
+
+#define PZ_NewCondVar(l) PR_NewCondVar((l))
+#define PZ_DestroyCondVar(v) PR_DestroyCondVar((v))
+#define PZ_WaitCondVar(v, t) PR_WaitCondVar((v), (t))
+#define PZ_NotifyCondVar(v) PR_NotifyCondVar((v))
+#define PZ_NotifyAllCondVar(v) PR_NotifyAllCondVar((v))
+
+#define PZ_NewMonitor(t) PR_NewMonitor()
+#define PZ_DestroyMonitor(m) PR_DestroyMonitor((m))
+#define PZ_EnterMonitor(m) PR_EnterMonitor((m))
+#define PZ_ExitMonitor(m) PR_ExitMonitor((m))
+#define PZ_InMonitor(m) PR_InMonitor((m))
+#define PZ_Wait(m, t) PR_Wait(((m)), ((t)))
+#define PZ_Notify(m) PR_Notify((m))
+#define PZ_NotifyAll(m) PR_Notify((m))
+#define PZ_TraceFlush() /* nothing */
+
+#endif /* NEED_NSS_ILOCK */
+
+PR_END_EXTERN_C
+#endif /* _NSSILOCK_H_ */
diff --git a/security/nss/lib/util/nsslocks.h b/security/nss/lib/util/nsslocks.h
new file mode 100644
index 0000000000..6098f56a44
--- /dev/null
+++ b/security/nss/lib/util/nsslocks.h
@@ -0,0 +1,10 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * nsslocks.h - threadsafe functions to initialize lock pointers.
+ *
+ * NOTE - The interfaces formerly in this header were private and are now all
+ * obsolete.
+ */
diff --git a/security/nss/lib/util/nssrwlk.c b/security/nss/lib/util/nssrwlk.c
new file mode 100644
index 0000000000..5af0217628
--- /dev/null
+++ b/security/nss/lib/util/nssrwlk.c
@@ -0,0 +1,450 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nssrwlk.h"
+#include "nspr.h"
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * Reader-writer lock
+ */
+struct nssRWLockStr {
+ PZLock *rw_lock;
+ char *rw_name; /* lock name */
+ PRUint32 rw_rank; /* rank of the lock */
+ PRInt32 rw_writer_locks; /* == 0, if unlocked */
+ PRInt32 rw_reader_locks; /* == 0, if unlocked */
+ /* > 0 , # of read locks */
+ PRUint32 rw_waiting_readers; /* number of waiting readers */
+ PRUint32 rw_waiting_writers; /* number of waiting writers */
+ PZCondVar *rw_reader_waitq; /* cvar for readers */
+ PZCondVar *rw_writer_waitq; /* cvar for writers */
+ PRThread *rw_owner; /* lock owner for write-lock */
+ /* Non-null if write lock held. */
+};
+
+PR_END_EXTERN_C
+
+#include <string.h>
+
+#ifdef DEBUG_RANK_ORDER
+#define NSS_RWLOCK_RANK_ORDER_DEBUG /* enable deadlock detection using \
+ rank-order for locks \
+ */
+#endif
+
+#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG
+
+static PRUintn nss_thread_rwlock_initialized;
+static PRUintn nss_thread_rwlock; /* TPD key for lock stack */
+static PRUintn nss_thread_rwlock_alloc_failed;
+
+#define _NSS_RWLOCK_RANK_ORDER_LIMIT 10
+
+typedef struct thread_rwlock_stack {
+ PRInt32 trs_index; /* top of stack */
+ NSSRWLock *trs_stack[_NSS_RWLOCK_RANK_ORDER_LIMIT]; /* stack of lock
+ pointers */
+} thread_rwlock_stack;
+
+/* forward static declarations. */
+static PRUint32 nssRWLock_GetThreadRank(PRThread *me);
+static void nssRWLock_SetThreadRank(PRThread *me, NSSRWLock *rwlock);
+static void nssRWLock_UnsetThreadRank(PRThread *me, NSSRWLock *rwlock);
+static void nssRWLock_ReleaseLockStack(void *lock_stack);
+
+#endif
+
+#define UNTIL(x) while (!(x))
+
+/*
+ * Reader/Writer Locks
+ */
+
+/*
+ * NSSRWLock_New
+ * Create a reader-writer lock, with the given lock rank and lock name
+ *
+ */
+
+NSSRWLock *
+NSSRWLock_New(PRUint32 lock_rank, const char *lock_name)
+{
+ NSSRWLock *rwlock;
+
+ rwlock = PR_NEWZAP(NSSRWLock);
+ if (rwlock == NULL)
+ return NULL;
+
+ rwlock->rw_lock = PZ_NewLock(nssILockRWLock);
+ if (rwlock->rw_lock == NULL) {
+ goto loser;
+ }
+ rwlock->rw_reader_waitq = PZ_NewCondVar(rwlock->rw_lock);
+ if (rwlock->rw_reader_waitq == NULL) {
+ goto loser;
+ }
+ rwlock->rw_writer_waitq = PZ_NewCondVar(rwlock->rw_lock);
+ if (rwlock->rw_writer_waitq == NULL) {
+ goto loser;
+ }
+ if (lock_name != NULL) {
+ rwlock->rw_name = (char *)PR_Malloc((PRUint32)strlen(lock_name) + 1);
+ if (rwlock->rw_name == NULL) {
+ goto loser;
+ }
+ strcpy(rwlock->rw_name, lock_name);
+ } else {
+ rwlock->rw_name = NULL;
+ }
+ rwlock->rw_rank = lock_rank;
+ rwlock->rw_waiting_readers = 0;
+ rwlock->rw_waiting_writers = 0;
+ rwlock->rw_reader_locks = 0;
+ rwlock->rw_writer_locks = 0;
+
+ return rwlock;
+
+loser:
+ NSSRWLock_Destroy(rwlock);
+ return (NULL);
+}
+
+/*
+** Destroy the given RWLock "lock".
+*/
+void
+NSSRWLock_Destroy(NSSRWLock *rwlock)
+{
+ PR_ASSERT(rwlock != NULL);
+ PR_ASSERT(rwlock->rw_waiting_readers == 0);
+ PR_ASSERT(rwlock->rw_writer_locks == 0);
+ PR_ASSERT(rwlock->rw_reader_locks == 0);
+
+ /* XXX Shouldn't we lock the PZLock before destroying this?? */
+
+ if (rwlock->rw_name)
+ PR_Free(rwlock->rw_name);
+ if (rwlock->rw_reader_waitq)
+ PZ_DestroyCondVar(rwlock->rw_reader_waitq);
+ if (rwlock->rw_writer_waitq)
+ PZ_DestroyCondVar(rwlock->rw_writer_waitq);
+ if (rwlock->rw_lock)
+ PZ_DestroyLock(rwlock->rw_lock);
+ PR_DELETE(rwlock);
+}
+
+/*
+** Read-lock the RWLock.
+*/
+void
+NSSRWLock_LockRead(NSSRWLock *rwlock)
+{
+ PRThread *me = PR_GetCurrentThread();
+
+ PZ_Lock(rwlock->rw_lock);
+#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG
+
+ /*
+ * assert that rank ordering is not violated; the rank of 'rwlock' should
+ * be equal to or greater than the highest rank of all the locks held by
+ * the thread.
+ */
+ PR_ASSERT((rwlock->rw_rank == NSS_RWLOCK_RANK_NONE) ||
+ (rwlock->rw_rank >= nssRWLock_GetThreadRank(me)));
+#endif
+ /*
+ * wait if write-locked or if a writer is waiting; preference for writers
+ */
+ UNTIL((rwlock->rw_owner == me) || /* I own it, or */
+ ((rwlock->rw_owner == NULL) && /* no-one owns it, and */
+ (rwlock->rw_waiting_writers == 0)))
+ { /* no-one is waiting to own */
+
+ rwlock->rw_waiting_readers++;
+ PZ_WaitCondVar(rwlock->rw_reader_waitq, PR_INTERVAL_NO_TIMEOUT);
+ rwlock->rw_waiting_readers--;
+ }
+ rwlock->rw_reader_locks++; /* Increment read-lock count */
+
+ PZ_Unlock(rwlock->rw_lock);
+
+#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG
+ nssRWLock_SetThreadRank(me, rwlock); /* update thread's lock rank */
+#endif
+}
+
+/* Unlock a Read lock held on this RW lock.
+*/
+void
+NSSRWLock_UnlockRead(NSSRWLock *rwlock)
+{
+ PZ_Lock(rwlock->rw_lock);
+
+ PR_ASSERT(rwlock->rw_reader_locks > 0); /* lock must be read locked */
+
+ if ((rwlock->rw_reader_locks > 0) && /* caller isn't screwey */
+ (--rwlock->rw_reader_locks == 0) && /* not read locked any more */
+ (rwlock->rw_owner == NULL) && /* not write locked */
+ (rwlock->rw_waiting_writers > 0)) { /* someone's waiting. */
+
+ PZ_NotifyCondVar(rwlock->rw_writer_waitq); /* wake him up. */
+ }
+
+ PZ_Unlock(rwlock->rw_lock);
+
+#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG
+ /*
+ * update thread's lock rank
+ */
+ nssRWLock_UnsetThreadRank(me, rwlock);
+#endif
+ return;
+}
+
+/*
+** Write-lock the RWLock.
+*/
+void
+NSSRWLock_LockWrite(NSSRWLock *rwlock)
+{
+ PRThread *me = PR_GetCurrentThread();
+
+ PZ_Lock(rwlock->rw_lock);
+#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG
+ /*
+ * assert that rank ordering is not violated; the rank of 'rwlock' should
+ * be equal to or greater than the highest rank of all the locks held by
+ * the thread.
+ */
+ PR_ASSERT((rwlock->rw_rank == NSS_RWLOCK_RANK_NONE) ||
+ (rwlock->rw_rank >= nssRWLock_GetThreadRank(me)));
+#endif
+ /*
+ * wait if read locked or write locked.
+ */
+ PR_ASSERT(rwlock->rw_reader_locks >= 0);
+ PR_ASSERT(me != NULL);
+
+ UNTIL((rwlock->rw_owner == me) || /* I own write lock, or */
+ ((rwlock->rw_owner == NULL) && /* no writer and */
+ (rwlock->rw_reader_locks == 0)))
+ { /* no readers, either. */
+
+ rwlock->rw_waiting_writers++;
+ PZ_WaitCondVar(rwlock->rw_writer_waitq, PR_INTERVAL_NO_TIMEOUT);
+ rwlock->rw_waiting_writers--;
+ PR_ASSERT(rwlock->rw_reader_locks >= 0);
+ }
+
+ PR_ASSERT(rwlock->rw_reader_locks == 0);
+ /*
+ * apply write lock
+ */
+ rwlock->rw_owner = me;
+ rwlock->rw_writer_locks++; /* Increment write-lock count */
+
+ PZ_Unlock(rwlock->rw_lock);
+
+#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG
+ /*
+ * update thread's lock rank
+ */
+ nssRWLock_SetThreadRank(me, rwlock);
+#endif
+}
+
+/* Unlock a Read lock held on this RW lock.
+*/
+void
+NSSRWLock_UnlockWrite(NSSRWLock *rwlock)
+{
+ PRThread *me = PR_GetCurrentThread();
+
+ PZ_Lock(rwlock->rw_lock);
+ PR_ASSERT(rwlock->rw_owner == me); /* lock must be write-locked by me. */
+ PR_ASSERT(rwlock->rw_writer_locks > 0); /* lock must be write locked */
+
+ if (rwlock->rw_owner == me && /* I own it, and */
+ rwlock->rw_writer_locks > 0 && /* I own it, and */
+ --rwlock->rw_writer_locks == 0) { /* I'm all done with it */
+
+ rwlock->rw_owner = NULL; /* I don't own it any more. */
+
+ /* Give preference to waiting writers. */
+ if (rwlock->rw_waiting_writers > 0) {
+ if (rwlock->rw_reader_locks == 0)
+ PZ_NotifyCondVar(rwlock->rw_writer_waitq);
+ } else if (rwlock->rw_waiting_readers > 0) {
+ PZ_NotifyAllCondVar(rwlock->rw_reader_waitq);
+ }
+ }
+ PZ_Unlock(rwlock->rw_lock);
+
+#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG
+ /*
+ * update thread's lock rank
+ */
+ nssRWLock_UnsetThreadRank(me, rwlock);
+#endif
+ return;
+}
+
+/* This is primarily for debugging, i.e. for inclusion in ASSERT calls. */
+PRBool
+NSSRWLock_HaveWriteLock(NSSRWLock *rwlock)
+{
+ PRBool ownWriteLock;
+ PRThread *me = PR_GetCurrentThread();
+
+/* This lock call isn't really necessary.
+ ** If this thread is the owner, that fact cannot change during this call,
+ ** because this thread is in this call.
+ ** If this thread is NOT the owner, the owner could change, but it
+ ** could not become this thread.
+ */
+#if UNNECESSARY
+ PZ_Lock(rwlock->rw_lock);
+#endif
+ ownWriteLock = (PRBool)(me == rwlock->rw_owner);
+#if UNNECESSARY
+ PZ_Unlock(rwlock->rw_lock);
+#endif
+ return ownWriteLock;
+}
+
+#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG
+
+/*
+ * nssRWLock_SetThreadRank
+ * Set a thread's lock rank, which is the highest of the ranks of all
+ * the locks held by the thread. Pointers to the locks are added to a
+ * per-thread list, which is anchored off a thread-private data key.
+ */
+
+static void
+nssRWLock_SetThreadRank(PRThread *me, NSSRWLock *rwlock)
+{
+ thread_rwlock_stack *lock_stack;
+ PRStatus rv;
+
+ /*
+ * allocated thread-private-data for rwlock list, if not already allocated
+ */
+ if (!nss_thread_rwlock_initialized) {
+ /*
+ * allocate tpd, only if not failed already
+ */
+ if (!nss_thread_rwlock_alloc_failed) {
+ if (PR_NewThreadPrivateIndex(&nss_thread_rwlock,
+ nssRWLock_ReleaseLockStack) == PR_FAILURE) {
+ nss_thread_rwlock_alloc_failed = 1;
+ return;
+ }
+ } else
+ return;
+ }
+ /*
+ * allocate a lock stack
+ */
+ if ((lock_stack = PR_GetThreadPrivate(nss_thread_rwlock)) == NULL) {
+ lock_stack = (thread_rwlock_stack *)
+ PR_CALLOC(1 * sizeof(thread_rwlock_stack));
+ if (lock_stack) {
+ rv = PR_SetThreadPrivate(nss_thread_rwlock, lock_stack);
+ if (rv == PR_FAILURE) {
+ PR_DELETE(lock_stack);
+ nss_thread_rwlock_alloc_failed = 1;
+ return;
+ }
+ } else {
+ nss_thread_rwlock_alloc_failed = 1;
+ return;
+ }
+ }
+ /*
+ * add rwlock to lock stack, if limit is not exceeded
+ */
+ if (lock_stack) {
+ if (lock_stack->trs_index < _NSS_RWLOCK_RANK_ORDER_LIMIT)
+ lock_stack->trs_stack[lock_stack->trs_index++] = rwlock;
+ }
+ nss_thread_rwlock_initialized = 1;
+}
+
+static void
+nssRWLock_ReleaseLockStack(void *lock_stack)
+{
+ PR_ASSERT(lock_stack);
+ PR_DELETE(lock_stack);
+}
+
+/*
+ * nssRWLock_GetThreadRank
+ *
+ * return thread's lock rank. If thread-private-data for the lock
+ * stack is not allocated, return NSS_RWLOCK_RANK_NONE.
+ */
+
+static PRUint32
+nssRWLock_GetThreadRank(PRThread *me)
+{
+ thread_rwlock_stack *lock_stack;
+
+ if (nss_thread_rwlock_initialized) {
+ if ((lock_stack = PR_GetThreadPrivate(nss_thread_rwlock)) == NULL)
+ return (NSS_RWLOCK_RANK_NONE);
+ else
+ return (lock_stack->trs_stack[lock_stack->trs_index - 1]->rw_rank);
+
+ } else
+ return (NSS_RWLOCK_RANK_NONE);
+}
+
+/*
+ * nssRWLock_UnsetThreadRank
+ *
+ * remove the rwlock from the lock stack. Since locks may not be
+ * unlocked in a FIFO order, the entire lock stack is searched.
+ */
+
+static void
+nssRWLock_UnsetThreadRank(PRThread *me, NSSRWLock *rwlock)
+{
+ thread_rwlock_stack *lock_stack;
+ int new_index = 0, index, done = 0;
+
+ if (!nss_thread_rwlock_initialized)
+ return;
+
+ lock_stack = PR_GetThreadPrivate(nss_thread_rwlock);
+
+ PR_ASSERT(lock_stack != NULL);
+
+ index = lock_stack->trs_index - 1;
+ while (index-- >= 0) {
+ if ((lock_stack->trs_stack[index] == rwlock) && !done) {
+ /*
+ * reset the slot for rwlock
+ */
+ lock_stack->trs_stack[index] = NULL;
+ done = 1;
+ }
+ /*
+ * search for the lowest-numbered empty slot, above which there are
+ * no non-empty slots
+ */
+ if ((lock_stack->trs_stack[index] != NULL) && !new_index)
+ new_index = index + 1;
+ if (done && new_index)
+ break;
+ }
+ /*
+ * set top of stack to highest numbered empty slot
+ */
+ lock_stack->trs_index = new_index;
+}
+
+#endif /* NSS_RWLOCK_RANK_ORDER_DEBUG */
diff --git a/security/nss/lib/util/nssrwlk.h b/security/nss/lib/util/nssrwlk.h
new file mode 100644
index 0000000000..8e1fa6fbe1
--- /dev/null
+++ b/security/nss/lib/util/nssrwlk.h
@@ -0,0 +1,133 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+** File: nsrwlock.h
+** Description: API to basic reader-writer lock functions of NSS.
+** These locks allow re-entry from writers but not readers. That is,
+** If I hold the write lock, I can ask for it and get it again.
+** If I hold the write lock, I can also ask for and get a read lock.
+** I can then release the locks in any order (read or write).
+** If I hold a read lock, I must not ask for another read lock or
+** the write lock.
+** I must release each lock type as many times as I acquired it.
+**
+** For deadlock detection, locks should be ranked, and no lock may be aquired
+** while I hold a lock of higher rank number.
+** If you don't want that feature, always use NSS_RWLOCK_RANK_NONE.
+** Lock name is for debugging, and is optional (may be NULL)
+**/
+
+#ifndef nssrwlk_h___
+#define nssrwlk_h___
+
+#include "utilrename.h"
+#include "prtypes.h"
+#include "nssrwlkt.h"
+
+#define NSS_RWLOCK_RANK_NONE 0
+
+/* SEC_BEGIN_PROTOS */
+PR_BEGIN_EXTERN_C
+
+/***********************************************************************
+** FUNCTION: NSSRWLock_New
+** DESCRIPTION:
+** Returns a pointer to a newly created reader-writer lock object.
+** INPUTS: Lock rank
+** Lock name
+** OUTPUTS: void
+** RETURN: NSSRWLock*
+** If the lock cannot be created because of resource constraints, NULL
+** is returned.
+**
+***********************************************************************/
+extern NSSRWLock *NSSRWLock_New(PRUint32 lock_rank, const char *lock_name);
+
+/***********************************************************************
+** FUNCTION: NSSRWLock_AtomicCreate
+** DESCRIPTION:
+** Given the address of a NULL pointer to a NSSRWLock,
+** atomically initializes that pointer to a newly created NSSRWLock.
+** Returns the value placed into that pointer, or NULL.
+**
+** INPUTS: address of NSRWLock pointer
+** Lock rank
+** Lock name
+** OUTPUTS: NSSRWLock*
+** RETURN: NSSRWLock*
+** If the lock cannot be created because of resource constraints,
+** the pointer will be left NULL.
+**
+***********************************************************************/
+extern NSSRWLock *
+nssRWLock_AtomicCreate(NSSRWLock **prwlock,
+ PRUint32 lock_rank,
+ const char *lock_name);
+
+/***********************************************************************
+** FUNCTION: NSSRWLock_Destroy
+** DESCRIPTION:
+** Destroys a given RW lock object.
+** INPUTS: NSSRWLock *lock - Lock to be freed.
+** OUTPUTS: void
+** RETURN: None
+***********************************************************************/
+extern void NSSRWLock_Destroy(NSSRWLock *lock);
+
+/***********************************************************************
+** FUNCTION: NSSRWLock_LockRead
+** DESCRIPTION:
+** Apply a read lock (non-exclusive) on a RWLock
+** INPUTS: NSSRWLock *lock - Lock to be read-locked.
+** OUTPUTS: void
+** RETURN: None
+***********************************************************************/
+extern void NSSRWLock_LockRead(NSSRWLock *lock);
+
+/***********************************************************************
+** FUNCTION: NSSRWLock_LockWrite
+** DESCRIPTION:
+** Apply a write lock (exclusive) on a RWLock
+** INPUTS: NSSRWLock *lock - Lock to write-locked.
+** OUTPUTS: void
+** RETURN: None
+***********************************************************************/
+extern void NSSRWLock_LockWrite(NSSRWLock *lock);
+
+/***********************************************************************
+** FUNCTION: NSSRWLock_UnlockRead
+** DESCRIPTION:
+** Release a Read lock. Unlocking an unlocked lock has undefined results.
+** INPUTS: NSSRWLock *lock - Lock to unlocked.
+** OUTPUTS: void
+** RETURN: void
+***********************************************************************/
+extern void NSSRWLock_UnlockRead(NSSRWLock *lock);
+
+/***********************************************************************
+** FUNCTION: NSSRWLock_UnlockWrite
+** DESCRIPTION:
+** Release a Write lock. Unlocking an unlocked lock has undefined results.
+** INPUTS: NSSRWLock *lock - Lock to unlocked.
+** OUTPUTS: void
+** RETURN: void
+***********************************************************************/
+extern void NSSRWLock_UnlockWrite(NSSRWLock *lock);
+
+/***********************************************************************
+** FUNCTION: NSSRWLock_HaveWriteLock
+** DESCRIPTION:
+** Tells caller whether the current thread holds the write lock, or not.
+** INPUTS: NSSRWLock *lock - Lock to test.
+** OUTPUTS: void
+** RETURN: PRBool PR_TRUE IFF the current thread holds the write lock.
+***********************************************************************/
+
+extern PRBool NSSRWLock_HaveWriteLock(NSSRWLock *rwlock);
+
+/* SEC_END_PROTOS */
+PR_END_EXTERN_C
+
+#endif /* nsrwlock_h___ */
diff --git a/security/nss/lib/util/nssrwlkt.h b/security/nss/lib/util/nssrwlkt.h
new file mode 100644
index 0000000000..50a4112edd
--- /dev/null
+++ b/security/nss/lib/util/nssrwlkt.h
@@ -0,0 +1,19 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nssrwlkt_h___
+#define nssrwlkt_h___
+
+#include "utilrename.h"
+#include "nssilock.h"
+/*
+ * NSSRWLock --
+ *
+ * The reader writer lock, NSSRWLock, is an opaque object to the clients
+ * of NSS. All routines operate on a pointer to this opaque entity.
+ */
+
+typedef struct nssRWLockStr NSSRWLock;
+
+#endif /* nsrwlock_h___ */
diff --git a/security/nss/lib/util/nssutil.def b/security/nss/lib/util/nssutil.def
new file mode 100644
index 0000000000..01f362c2a0
--- /dev/null
+++ b/security/nss/lib/util/nssutil.def
@@ -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/.
+;+#
+;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
+;+# 1. For all unix platforms, the string ";-" means "remove this line"
+;+# 2. For all unix platforms, the string " DATA " will be removed from any
+;+# line on which it occurs.
+;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
+;+# On AIX, lines containing ";+" will be removed.
+;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
+;+# 5. For all unix platforms, after the above processing has taken place,
+;+# all characters after the first ";" on the line will be removed.
+;+# And for AIX, the first ";" will also be removed.
+;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
+;+# directives are hidden behind ";", ";+", and ";-"
+;+NSSUTIL_3.12 { # NSS Utilities 3.12 release
+;+ global:
+LIBRARY nssutil3 ;-
+EXPORTS ;-
+ATOB_AsciiToData_Util;
+ATOB_ConvertAsciiToItem_Util;
+BTOA_ConvertItemToAscii_Util;
+BTOA_DataToAscii_Util;
+CERT_GenTime2FormattedAscii_Util;
+DER_AsciiToTime_Util;
+DER_DecodeTimeChoice_Util;
+DER_Encode_Util;
+DER_EncodeTimeChoice_Util;
+DER_GeneralizedDayToAscii_Util;
+DER_GeneralizedTimeToTime_Util;
+DER_GetInteger_Util;
+DER_GetUInteger;
+DER_LengthLength;
+DER_Lengths_Util;
+DER_SetUInteger;
+DER_StoreHeader;
+DER_TimeChoiceDayToAscii_Util;
+DER_TimeToGeneralizedTime_Util;
+DER_TimeToGeneralizedTimeArena_Util;
+DER_TimeToUTCTime_Util;
+DER_UTCDayToAscii_Util;
+DER_UTCTimeToAscii_Util;
+DER_UTCTimeToTime_Util;
+NSS_PutEnv_Util;
+NSSBase64_DecodeBuffer_Util;
+NSSBase64_EncodeItem_Util;
+NSSBase64Decoder_Create_Util;
+NSSBase64Decoder_Destroy_Util;
+NSSBase64Decoder_Update_Util;
+NSSBase64Encoder_Create_Util;
+NSSBase64Encoder_Destroy_Util;
+NSSBase64Encoder_Update_Util;
+NSSRWLock_Destroy_Util;
+NSSRWLock_HaveWriteLock_Util;
+NSSRWLock_LockRead_Util;
+NSSRWLock_LockWrite_Util;
+NSSRWLock_New_Util;
+NSSRWLock_UnlockRead_Util;
+NSSRWLock_UnlockWrite_Util;
+PORT_Alloc_Util;
+PORT_ArenaAlloc_Util;
+PORT_ArenaGrow_Util;
+PORT_ArenaMark_Util;
+PORT_ArenaRelease_Util;
+PORT_ArenaStrdup_Util;
+PORT_ArenaUnmark_Util;
+PORT_ArenaZAlloc_Util;
+PORT_Free_Util;
+PORT_FreeArena_Util;
+PORT_GetError_Util;
+PORT_ISO88591_UTF8Conversion;
+PORT_NewArena_Util;
+PORT_Realloc_Util;
+PORT_RegExpCaseSearch;
+PORT_RegExpValid;
+PORT_SetError_Util;
+PORT_SetUCS2_ASCIIConversionFunction_Util;
+PORT_SetUCS2_UTF8ConversionFunction_Util;
+PORT_SetUCS4_UTF8ConversionFunction_Util;
+PORT_Strdup_Util;
+PORT_UCS2_ASCIIConversion_Util;
+PORT_UCS2_UTF8Conversion_Util;
+PORT_UCS4_UTF8Conversion;
+PORT_ZAlloc_Util;
+PORT_ZFree_Util;
+SEC_ASN1Decode_Util;
+SEC_ASN1DecodeInteger_Util;
+SEC_ASN1DecodeItem_Util;
+SEC_ASN1DecoderAbort_Util;
+SEC_ASN1DecoderClearFilterProc_Util;
+SEC_ASN1DecoderClearNotifyProc_Util;
+SEC_ASN1DecoderFinish_Util;
+SEC_ASN1DecoderSetFilterProc_Util;
+SEC_ASN1DecoderSetNotifyProc_Util;
+SEC_ASN1DecoderStart_Util;
+SEC_ASN1DecoderUpdate_Util;
+SEC_ASN1Encode_Util;
+SEC_ASN1EncodeInteger_Util;
+SEC_ASN1EncodeItem_Util;
+SEC_ASN1EncoderAbort_Util;
+SEC_ASN1EncoderClearNotifyProc_Util;
+SEC_ASN1EncoderClearStreaming_Util;
+SEC_ASN1EncoderClearTakeFromBuf_Util;
+SEC_ASN1EncoderFinish_Util;
+SEC_ASN1EncoderSetNotifyProc_Util;
+SEC_ASN1EncoderSetStreaming_Util;
+SEC_ASN1EncoderSetTakeFromBuf_Util;
+SEC_ASN1EncoderStart_Util;
+SEC_ASN1EncoderUpdate_Util;
+SEC_ASN1EncodeUnsignedInteger_Util;
+SEC_ASN1LengthLength_Util;
+SEC_QuickDERDecodeItem_Util;
+SEC_StringToOID;
+SECITEM_AllocItem_Util;
+SECITEM_ArenaDupItem_Util;
+SECITEM_CompareItem_Util;
+SECITEM_CopyItem_Util;
+SECITEM_DupItem_Util;
+SECITEM_FreeItem_Util;
+SECITEM_Hash;
+SECITEM_HashCompare;
+SECITEM_ItemsAreEqual_Util;
+SECITEM_ZfreeItem_Util;
+SECOID_AddEntry_Util;
+SECOID_CompareAlgorithmID_Util;
+SECOID_CopyAlgorithmID_Util;
+SECOID_DestroyAlgorithmID_Util;
+SECOID_FindOID_Util;
+SECOID_FindOIDByMechanism;
+SECOID_FindOIDByTag_Util;
+SECOID_FindOIDTag_Util;
+SECOID_FindOIDTagDescription_Util;
+SECOID_GetAlgorithmTag_Util;
+SECOID_Init;
+SECOID_KnownCertExtenOID;
+SECOID_SetAlgorithmID_Util;
+SECOID_Shutdown;
+SGN_CompareDigestInfo_Util;
+SGN_CopyDigestInfo_Util;
+SGN_CreateDigestInfo_Util;
+SGN_DecodeDigestInfo;
+SGN_DestroyDigestInfo_Util;
+;+#
+;+# Data objects
+;+#
+;+# Don't export these DATA symbols on Windows because they don't work right.
+;+# Use the SEC_ASN1_GET / SEC_ASN1_SUB / SEC_ASN1_XTRN macros to access them.
+;;SEC_AnyTemplate_Util DATA ;
+;;SEC_BitStringTemplate_Util DATA ;
+;;SEC_BMPStringTemplate_Util DATA ;
+;;SEC_BooleanTemplate_Util DATA ;
+;;SEC_EnumeratedTemplate DATA ;
+;;SEC_GeneralizedTimeTemplate_Util DATA ;
+;;SEC_IA5StringTemplate_Util DATA ;
+;;SEC_IntegerTemplate_Util DATA ;
+;;SEC_NullTemplate_Util DATA ;
+;;SEC_ObjectIDTemplate_Util DATA ;
+;;SEC_OctetStringTemplate_Util DATA ;
+;;SEC_PointerToAnyTemplate_Util DATA ;
+;;SEC_PointerToEnumeratedTemplate DATA ;
+;;SEC_PointerToGeneralizedTimeTemplate DATA ;
+;;SEC_PointerToOctetStringTemplate_Util DATA ;
+;;SEC_PrintableStringTemplate DATA ;
+;;SEC_SequenceOfAnyTemplate DATA ;
+;;SEC_SequenceOfObjectIDTemplate DATA ;
+;;SEC_SetOfAnyTemplate_Util DATA ;
+;;SEC_SkipTemplate DATA ;
+;;SEC_T61StringTemplate DATA ;
+;;SEC_UniversalStringTemplate DATA ;
+;;SEC_UTF8StringTemplate_Util DATA ;
+;;SECOID_AlgorithmIDTemplate_Util DATA ;
+;;sgn_DigestInfoTemplate_Util DATA ;
+NSS_Get_SEC_AnyTemplate_Util;
+NSS_Get_SEC_BitStringTemplate_Util;
+NSS_Get_SEC_BMPStringTemplate_Util;
+NSS_Get_SEC_BooleanTemplate_Util;
+NSS_Get_SEC_EnumeratedTemplate;
+NSS_Get_SEC_GeneralizedTimeTemplate_Util;
+NSS_Get_SEC_IA5StringTemplate_Util;
+NSS_Get_SEC_IntegerTemplate_Util;
+NSS_Get_SEC_NullTemplate_Util;
+NSS_Get_SEC_ObjectIDTemplate_Util;
+NSS_Get_SEC_OctetStringTemplate_Util;
+NSS_Get_SEC_PointerToAnyTemplate_Util;
+NSS_Get_SEC_PointerToEnumeratedTemplate;
+NSS_Get_SEC_PointerToGeneralizedTimeTemplate;
+NSS_Get_SEC_PointerToOctetStringTemplate_Util;
+NSS_Get_SEC_PrintableStringTemplate;
+NSS_Get_SEC_SequenceOfAnyTemplate;
+NSS_Get_SEC_SequenceOfObjectIDTemplate;
+NSS_Get_SEC_SetOfAnyTemplate_Util;
+NSS_Get_SEC_SkipTemplate;
+NSS_Get_SEC_T61StringTemplate;
+NSS_Get_SEC_UniversalStringTemplate;
+NSS_Get_SEC_UTF8StringTemplate_Util;
+NSS_Get_SECOID_AlgorithmIDTemplate_Util;
+NSS_Get_sgn_DigestInfoTemplate_Util;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.12.3 { # NSS Utilities 3.12.3 release
+;+ global:
+NSS_GetAlgorithmPolicy;
+NSS_SetAlgorithmPolicy;
+SECITEM_ReallocItem;
+UTIL_SetForkState;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.12.5 { # NSS Utilities 3.12.5 release
+;+ global:
+NSS_SecureMemcmp;
+PORT_LoadLibraryFromOrigin;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.12.7 { # NSS Utilities 3.12.7 release
+;+ global:
+PORT_RegExpSearch;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.13 { # NSS Utilities 3.13 release
+;+ global:
+NSSUTIL_GetVersion;
+NSS_InitializePRErrorTable;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.14 { # NSS Utilities 3.14 release
+;+ global:
+;+# private exports for softoken
+_NSSUTIL_GetSecmodName;
+_NSSUTIL_EvaluateConfigDir;
+;+# public exports
+NSSUTIL_ArgDecodeNumber;
+NSSUTIL_ArgFetchValue;
+NSSUTIL_ArgGetParamValue;
+NSSUTIL_ArgGetLabel;
+NSSUTIL_ArgHasFlag;
+NSSUTIL_ArgIsBlank;
+NSSUTIL_ArgParseCipherFlags;
+NSSUTIL_ArgParseModuleSpec;
+NSSUTIL_ArgParseSlotFlags;
+NSSUTIL_ArgParseSlotInfo;
+NSSUTIL_ArgReadLong;
+NSSUTIL_ArgSkipParameter;
+NSSUTIL_ArgStrip;
+NSSUTIL_DoModuleDBFunction;
+NSSUTIL_DoubleEscape;
+NSSUTIL_DoubleEscapeSize;
+NSSUTIL_Escape;
+NSSUTIL_EscapeSize;
+NSSUTIL_MkModuleSpec;
+NSSUTIL_MkNSSString;
+NSSUTIL_MkSlotString;
+NSSUTIL_Quote;
+NSSUTIL_QuoteSize;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.15 { # NSS Utilities 3.15 release
+;+ global:
+SECITEM_AllocArray;
+SECITEM_DupArray;
+SECITEM_FreeArray;
+SECITEM_ReallocItemV2;
+SECITEM_ZfreeArray;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.17.1 { # NSS Utilities 3.17.1 release
+;+ global:
+_SGN_VerifyPKCS1DigestInfo;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.21 { # NSS Utilities 3.21 release
+;+ global:
+NSSUTIL_ArgParseModuleSpecEx;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.24 { # NSS Utilities 3.24 release
+;+ global:
+PORT_InitCheapArena;
+PORT_DestroyCheapArena;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.25 { # NSS Utilities 3.25 release
+;+ global:
+SEC_ASN1DecoderSetMaximumElementSize;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.31 { # NSS Utilities 3.31 release
+;+ global:
+PK11URI_CreateURI;
+PK11URI_ParseURI;
+PK11URI_FormatURI;
+PK11URI_DestroyURI;
+PK11URI_GetPathAttribute;
+PK11URI_GetQueryAttribute;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.33 { # NSS Utilities 3.33 release
+;+ global:
+PORT_ZAllocAligned_Util;
+PORT_ZAllocAlignedOffset_Util;
+NSS_SecureMemcmpZero;
+;+ local:
+;+ *;
+;+};
+;-NSSUTIL_3.35 { # NSS Utilities 3.35 release
+;- global:
+;-# private exports for softoken
+_NSSUTIL_UTF8ToWide;-
+_NSSUTIL_Access;-
+;- local:
+;- *;
+;+NSSUTIL_3.38 { # NSS Utilities 3.38 release
+;+ global:
+SECITEM_MakeItem;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.39 { # NSS Utilities 3.39 release
+;+ global:
+NSSUTIL_AddNSSFlagToModuleSpec;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.59 { # NSS Utilities 3.59 release
+;+ global:
+NSS_IsPolicyLocked;
+NSS_LockPolicy;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.82 { # NSS Utilities 3.82 release
+;+ global:
+PK11URI_GetPathAttributeItem;
+PK11URI_GetQueryAttributeItem;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.90 { # NSS Utilities 3.90 release
+;+ global:
+NSS_SecureSelect;
+;+ local:
+;+ *;
+;+};
+;+NSSUTIL_3.94 { # NSS Utilities 3.94 release
+;+ global:
+NSS_GetSystemFIPSEnabled;
+;+ local:
+;+ *;
+;+};
diff --git a/security/nss/lib/util/nssutil.h b/security/nss/lib/util/nssutil.h
new file mode 100644
index 0000000000..b1a7c5fc59
--- /dev/null
+++ b/security/nss/lib/util/nssutil.h
@@ -0,0 +1,41 @@
+/*
+ * NSS utility functions
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 __nssutil_h_
+#define __nssutil_h_
+
+#ifndef RC_INVOKED
+#include "seccomon.h"
+#endif
+
+/*
+ * NSS utilities's major version, minor version, patch level, build number,
+ * and whether this is a beta release.
+ *
+ * The format of the version string should be
+ * "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
+ */
+#define NSSUTIL_VERSION "3.98"
+#define NSSUTIL_VMAJOR 3
+#define NSSUTIL_VMINOR 98
+#define NSSUTIL_VPATCH 0
+#define NSSUTIL_VBUILD 0
+#define NSSUTIL_BETA PR_FALSE
+
+SEC_BEGIN_PROTOS
+
+/*
+ * Returns a const string of the UTIL library version.
+ */
+extern const char *NSSUTIL_GetVersion(void);
+
+extern SECStatus
+NSS_InitializePRErrorTable(void);
+
+SEC_END_PROTOS
+
+#endif /* __nssutil_h_ */
diff --git a/security/nss/lib/util/nssutil.rc b/security/nss/lib/util/nssutil.rc
new file mode 100644
index 0000000000..65d4e68b26
--- /dev/null
+++ b/security/nss/lib/util/nssutil.rc
@@ -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/. */
+
+#include "nssutil.h"
+#include <winver.h>
+
+#define MY_LIBNAME "nssutil"
+#define MY_FILEDESCRIPTION "NSS Utility Library"
+
+#define STRINGIZE(x) #x
+#define STRINGIZE2(x) STRINGIZE(x)
+#define NSSUTIL_VMAJOR_STR STRINGIZE2(NSSUTIL_VMAJOR)
+
+#ifdef _DEBUG
+#define MY_DEBUG_STR " (debug)"
+#define MY_FILEFLAGS_1 VS_FF_DEBUG
+#else
+#define MY_DEBUG_STR ""
+#define MY_FILEFLAGS_1 0x0L
+#endif
+#if NSSUTIL_BETA
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
+#else
+#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
+#endif
+
+#ifdef WINNT
+#define MY_FILEOS VOS_NT_WINDOWS32
+#else
+#define MY_FILEOS VOS__WINDOWS32
+#endif
+
+#define MY_INTERNAL_NAME MY_LIBNAME NSSUTIL_VMAJOR_STR
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version-information resource
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION NSSUTIL_VMAJOR,NSSUTIL_VMINOR,NSSUTIL_VPATCH,NSSUTIL_VBUILD
+ PRODUCTVERSION NSSUTIL_VMAJOR,NSSUTIL_VMINOR,NSSUTIL_VPATCH,NSSUTIL_VBUILD
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+ FILEFLAGS MY_FILEFLAGS_2
+ FILEOS MY_FILEOS
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L // not used
+
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0" // Lang=US English, CharSet=Unicode
+ BEGIN
+ VALUE "CompanyName", "Mozilla Foundation\0"
+ VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
+ VALUE "FileVersion", NSSUTIL_VERSION "\0"
+ VALUE "InternalName", MY_INTERNAL_NAME "\0"
+ VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
+ VALUE "ProductName", "Network Security Services\0"
+ VALUE "ProductVersion", NSSUTIL_VERSION "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/security/nss/lib/util/oidstring.c b/security/nss/lib/util/oidstring.c
new file mode 100644
index 0000000000..58c8be1c4b
--- /dev/null
+++ b/security/nss/lib/util/oidstring.c
@@ -0,0 +1,114 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 <string.h>
+#include "secitem.h"
+#include "secport.h"
+#include "secerr.h"
+
+/* if to->data is not NULL, and to->len is large enough to hold the result,
+ * then the resultant OID will be copyed into to->data, and to->len will be
+ * changed to show the actual OID length.
+ * Otherwise, memory for the OID will be allocated (from the caller's
+ * PLArenaPool, if pool is non-NULL) and to->data will receive the address
+ * of the allocated data, and to->len will receive the OID length.
+ * The original value of to->data is not freed when a new buffer is allocated.
+ *
+ * The input string may begin with "OID." and this still be ignored.
+ * The length of the input string is given in len. If len == 0, then
+ * len will be computed as strlen(from), meaning it must be NUL terminated.
+ * It is an error if from == NULL, or if *from == '\0'.
+ */
+
+SECStatus
+SEC_StringToOID(PLArenaPool *pool, SECItem *to, const char *from, PRUint32 len)
+{
+ PRUint32 decimal_numbers = 0;
+ PRUint32 result_bytes = 0;
+ SECStatus rv;
+ PRUint8 result[1024];
+
+ static const PRUint32 max_decimal = (0xffffffff / 10);
+ static const char OIDstring[] = { "OID." };
+
+ if (!from || !to) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ if (!len) {
+ len = PL_strlen(from);
+ }
+ if (len >= 4 && !PL_strncasecmp(from, OIDstring, 4)) {
+ from += 4; /* skip leading "OID." if present */
+ len -= 4;
+ }
+ if (!len) {
+ bad_data:
+ PORT_SetError(SEC_ERROR_BAD_DATA);
+ return SECFailure;
+ }
+ do {
+ PRUint32 decimal = 0;
+ while (len > 0 && isdigit(*from)) {
+ PRUint32 addend = (*from++ - '0');
+ --len;
+ if (decimal > max_decimal) /* overflow */
+ goto bad_data;
+ decimal = (decimal * 10) + addend;
+ if (decimal < addend) /* overflow */
+ goto bad_data;
+ }
+ if (len != 0 && *from != '.') {
+ goto bad_data;
+ }
+ if (decimal_numbers == 0) {
+ if (decimal > 2)
+ goto bad_data;
+ result[0] = decimal * 40;
+ result_bytes = 1;
+ } else if (decimal_numbers == 1) {
+ if (decimal > 40)
+ goto bad_data;
+ result[0] += decimal;
+ } else {
+ /* encode the decimal number, */
+ PRUint8 *rp;
+ PRUint32 num_bytes = 0;
+ PRUint32 tmp = decimal;
+ while (tmp) {
+ num_bytes++;
+ tmp >>= 7;
+ }
+ if (!num_bytes)
+ ++num_bytes; /* use one byte for a zero value */
+ if (num_bytes + result_bytes > sizeof result)
+ goto bad_data;
+ tmp = num_bytes;
+ rp = result + result_bytes - 1;
+ rp[tmp] = (PRUint8)(decimal & 0x7f);
+ decimal >>= 7;
+ while (--tmp > 0) {
+ rp[tmp] = (PRUint8)(decimal | 0x80);
+ decimal >>= 7;
+ }
+ result_bytes += num_bytes;
+ }
+ ++decimal_numbers;
+ if (len > 0) { /* skip trailing '.' */
+ ++from;
+ --len;
+ }
+ } while (len > 0);
+ /* now result contains result_bytes of data */
+ if (to->data && to->len >= result_bytes) {
+ PORT_Memcpy(to->data, result, to->len = result_bytes);
+ rv = SECSuccess;
+ } else {
+ SECItem result_item = { siBuffer, NULL, 0 };
+ result_item.data = result;
+ result_item.len = result_bytes;
+ rv = SECITEM_CopyItem(pool, to, &result_item);
+ }
+ return rv;
+}
diff --git a/security/nss/lib/util/pkcs11.h b/security/nss/lib/util/pkcs11.h
new file mode 100644
index 0000000000..9b03614341
--- /dev/null
+++ b/security/nss/lib/util/pkcs11.h
@@ -0,0 +1,274 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document
+ * is granted provided that it is identified as "RSA Security In.c Public-Key
+ * Cryptography Standards (PKCS)" in all material mentioning or referencing
+ * this document.
+ *
+ * The latest version of this header can be found at:
+ * http://www.rsalabs.com/pkcs/pkcs-11/index.html
+ */
+#ifndef _PKCS11_H_
+#define _PKCS11_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Before including this file (pkcs11.h) (or pkcs11t.h by
+ * itself), 6 platform-specific macros must be defined. These
+ * macros are described below, and typical definitions for them
+ * are also given. Be advised that these definitions can depend
+ * on both the platform and the compiler used (and possibly also
+ * on whether a PKCS #11 library is linked statically or
+ * dynamically).
+ *
+ * In addition to defining these 6 macros, the packing convention
+ * for PKCS #11 structures should be set. The PKCS #11
+ * convention on packing is that structures should be 1-byte
+ * aligned.
+ *
+ * In a Win32 environment, this might be done by using the
+ * following preprocessor directive before including pkcs11.h
+ * or pkcs11t.h:
+ *
+ * #pragma pack(push, cryptoki, 1)
+ *
+ * and using the following preprocessor directive after including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(pop, cryptoki)
+ *
+ * In a UNIX environment, you're on your own here. You might
+ * not need to do anything.
+ *
+ *
+ * Now for the macros:
+ *
+ *
+ * 1. CK_PTR: The indirection string for making a pointer to an
+ * object. It can be used like this:
+ *
+ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+ *
+ * In a Win32 environment, it might be defined by
+ *
+ * #define CK_PTR *
+ *
+ * In a UNIX environment, it might be defined by
+ *
+ * #define CK_PTR *
+ *
+ *
+ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
+ * an exportable PKCS #11 library function definition out of a
+ * return type and a function name. It should be used in the
+ * following fashion to define the exposed PKCS #11 functions in
+ * a PKCS #11 library:
+ *
+ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
+ * CK_VOID_PTR pReserved
+ * )
+ * {
+ * ...
+ * }
+ *
+ * For defining a function in a Win32 PKCS #11 .dll, it might be
+ * defined by
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType __declspec(dllexport) name
+ *
+ * In a UNIX environment, it might be defined by
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType name
+ *
+ *
+ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
+ * an importable PKCS #11 library function declaration out of a
+ * return type and a function name. It should be used in the
+ * following fashion:
+ *
+ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
+ * CK_VOID_PTR pReserved
+ * );
+ *
+ * For declaring a function in a Win32 PKCS #11 .dll, it might
+ * be defined by
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType __declspec(dllimport) name
+ *
+ * In a UNIX environment, it might be defined by
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType name
+ *
+ *
+ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
+ * which makes a PKCS #11 API function pointer declaration or
+ * function pointer type declaration out of a return type and a
+ * function name. It should be used in the following fashion:
+ *
+ * // Define funcPtr to be a pointer to a PKCS #11 API function
+ * // taking arguments args and returning CK_RV.
+ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
+ *
+ * or
+ *
+ * // Define funcPtrType to be the type of a pointer to a
+ * // PKCS #11 API function taking arguments args and returning
+ * // CK_RV, and then define funcPtr to be a variable of type
+ * // funcPtrType.
+ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
+ * funcPtrType funcPtr;
+ *
+ * For accessing functions in a Win32 PKCS #11 .dll, in might be
+ * defined by
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType __declspec(dllimport) (* name)
+ *
+ * In a UNIX environment, it might be defined by
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
+ * a function pointer type for an application callback out of
+ * a return type for the callback and a name for the callback.
+ * It should be used in the following fashion:
+ *
+ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
+ *
+ * to declare a function pointer, myCallback, to a callback
+ * which takes arguments args and returns a CK_RV. It can also
+ * be used like this:
+ *
+ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
+ * myCallbackType myCallback;
+ *
+ * In a Win32 environment, it might be defined by
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ * In a UNIX environment, it might be defined by
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 6. NULL_PTR: This macro is the value of a NULL pointer.
+ *
+ * In any ANSI/ISO C environment (and in many others as well),
+ * this should be defined by
+ *
+ * #ifndef NULL_PTR
+ * #define NULL_PTR 0
+ * #endif
+ */
+
+/* All the various PKCS #11 types and #define'd values are in the
+ * file pkcs11t.h. */
+#include "pkcs11t.h"
+
+#define __PASTE(x, y) x##y
+
+#ifndef CK_PKCS11_3_0
+/* remember that we set it so we can unset it at the end */
+#define __NSS_CK_PKCS11_3_IMPLICIT 1
+#define CK_PKCS11_3_0 1
+#endif
+
+/* ==============================================================
+ * Define the "extern" form of all the entry points.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ CK_DECLARE_FUNCTION(CK_RV, name)
+
+/* pkcs11f.h has all the information about the PKCS #11
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+/* ==============================================================
+ * Define the typedef form of all the entry points. That is, for
+ * each PKCS #11 function C_XXX, define a type CK_C_XXX which is
+ * a pointer to that kind of function.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_, name))
+
+/* pkcs11f.h has all the information about the PKCS #11
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+/* ==============================================================
+ * Define structed vector of entry points. A CK_FUNCTION_3_0_LIST
+ * contains a CK_VERSION indicating a library's PKCS #11 version
+ * and then a whole slew of function pointers to the routines in
+ * the library. This type was declared, but not defined, in
+ * pkcs11t.h.
+ * ==============================================================
+ */
+
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ __PASTE(CK_, name) \
+ name;
+
+#include "pkcs11p.h"
+struct CK_FUNCTION_LIST_3_0 {
+
+ CK_VERSION version; /* PKCS #11 version */
+
+/* Pile all the function pointers into the CK_FUNCTION_LIST_3_0. */
+/* pkcs11f.h has all the information about the PKCS #11
+ * function prototypes. */
+#include "pkcs11f.h"
+};
+
+#define CK_PKCS11_2_0_ONLY 1
+
+/* now define the 2.0 function list */
+struct CK_FUNCTION_LIST {
+
+ CK_VERSION version; /* PKCS #11 version */
+
+/* Pile all the function pointers into the CK_FUNCTION_LIST. */
+/* pkcs11f.h has all the information about the PKCS #11
+ * function prototypes. */
+#include "pkcs11f.h"
+};
+#include "pkcs11u.h"
+
+#undef CK_PKCS11_FUNCTION_INFO
+#undef CK_PKCS11_2_0_ONLY
+
+#ifdef __NSS_CK_PKCS11_3_IMPLICIT
+#undef CK_PKCS11_3_0
+#undef __NSS_CK_PKCS11_3_IMPLICIT
+#endif
+
+#undef __PASTE
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/security/nss/lib/util/pkcs11f.h b/security/nss/lib/util/pkcs11f.h
new file mode 100644
index 0000000000..97bb8daac3
--- /dev/null
+++ b/security/nss/lib/util/pkcs11f.h
@@ -0,0 +1,1044 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document
+ * is granted provided that it is identified as "RSA Security In.c Public-Key
+ * Cryptography Standards (PKCS)" in all material mentioning or referencing
+ * this document.
+ */
+/* This function contains pretty much everything about all the */
+/* PKCS #11 function prototypes. Because this information is */
+/* used for more than just declaring function prototypes, the */
+/* order of the functions appearing herein is important, and */
+/* should not be altered. */
+
+/* General-purpose */
+
+/* C_Initialize initializes the PKCS #11 library. */
+CK_PKCS11_FUNCTION_INFO(C_Initialize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
+ * cast to CK_C_INITIALIZE_ARGS_PTR
+ * and dereferenced */
+);
+#endif
+
+/* C_Finalize indicates that an application is done with the
+ * PKCS #11 library. */
+CK_PKCS11_FUNCTION_INFO(C_Finalize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
+);
+#endif
+
+/* C_GetInfo returns general information about PKCS #11. */
+CK_PKCS11_FUNCTION_INFO(C_GetInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_INFO_PTR pInfo /* location that receives information */
+);
+#endif
+
+/* C_GetFunctionList returns the function list. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
+ * function list */
+);
+#endif
+
+/* Slot and token management */
+
+/* C_GetSlotList obtains a list of slots in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_BBOOL tokenPresent, /* only slots with tokens? */
+ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
+ CK_ULONG_PTR pulCount /* receives number of slots */
+);
+#endif
+
+/* C_GetSlotInfo obtains information about a particular slot in
+ * the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the ID of the slot */
+ CK_SLOT_INFO_PTR pInfo /* receives the slot information */
+);
+#endif
+
+/* C_GetTokenInfo obtains information about a particular token
+ * in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_TOKEN_INFO_PTR pInfo /* receives the token information */
+);
+#endif
+
+/* C_GetMechanismList obtains a list of mechanism types
+ * supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of token's slot */
+ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
+ CK_ULONG_PTR pulCount /* gets # of mechs. */
+);
+#endif
+
+/* C_GetMechanismInfo obtains information about a particular
+ * mechanism possibly supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_MECHANISM_TYPE type, /* type of mechanism */
+ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
+);
+#endif
+
+/* C_InitToken initializes a token. */
+CK_PKCS11_FUNCTION_INFO(C_InitToken)
+#ifdef CK_NEED_ARG_LIST
+/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
+ CK_ULONG ulPinLen, /* length in bytes of the PIN */
+ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
+);
+#endif
+
+/* C_InitPIN initializes the normal user's PIN. */
+CK_PKCS11_FUNCTION_INFO(C_InitPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
+ CK_ULONG ulPinLen /* length in bytes of the PIN */
+);
+#endif
+
+/* C_SetPIN modifies the PIN of the user who is logged in. */
+CK_PKCS11_FUNCTION_INFO(C_SetPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
+ CK_ULONG ulOldLen, /* length of the old PIN */
+ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
+ CK_ULONG ulNewLen /* length of the new PIN */
+);
+#endif
+
+/* Session management */
+
+/* C_OpenSession opens a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_OpenSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the slot's ID */
+ CK_FLAGS flags, /* from CK_SESSION_INFO */
+ CK_VOID_PTR pApplication, /* passed to callback */
+ CK_NOTIFY Notify, /* callback function */
+ CK_SESSION_HANDLE_PTR phSession /* gets session handle */
+);
+#endif
+
+/* C_CloseSession closes a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+/* C_CloseAllSessions closes all sessions with a token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID /* the token's slot */
+);
+#endif
+
+/* C_GetSessionInfo obtains information about the session. */
+CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_SESSION_INFO_PTR pInfo /* receives session info */
+);
+#endif
+
+/* C_GetOperationState obtains the state of the cryptographic operation
+ * in a session. */
+CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* gets state */
+ CK_ULONG_PTR pulOperationStateLen /* gets state length */
+);
+#endif
+
+/* C_SetOperationState restores the state of the cryptographic
+ * operation in a session. */
+CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* holds state */
+ CK_ULONG ulOperationStateLen, /* holds state length */
+ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
+ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
+);
+#endif
+
+/* C_Login logs a user into a token. */
+CK_PKCS11_FUNCTION_INFO(C_Login)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_USER_TYPE userType, /* the user type */
+ CK_UTF8CHAR_PTR pPin, /* the user's PIN */
+ CK_ULONG ulPinLen /* the length of the PIN */
+);
+#endif
+
+/* C_Logout logs a user out from a token. */
+CK_PKCS11_FUNCTION_INFO(C_Logout)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+/* Object management */
+
+/* C_CreateObject creates a new object. */
+CK_PKCS11_FUNCTION_INFO(C_CreateObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
+);
+#endif
+
+/* C_CopyObject copies an object, creating a new object for the
+ * copy. */
+CK_PKCS11_FUNCTION_INFO(C_CopyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
+);
+#endif
+
+/* C_DestroyObject destroys an object. */
+CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject /* the object's handle */
+);
+#endif
+
+/* C_GetObjectSize gets the size of an object in bytes. */
+CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ULONG_PTR pulSize /* receives size of object */
+);
+#endif
+
+/* C_GetAttributeValue obtains the value of one or more object
+ * attributes. */
+CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+/* C_SetAttributeValue modifies the value of one or more object
+ * attributes */
+CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+/* C_FindObjectsInit initializes a search for token and session
+ * objects that match a template. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
+ CK_ULONG ulCount /* attrs in search template */
+);
+#endif
+
+/* C_FindObjects continues a search for token and session
+ * objects that match a template, obtaining additional object
+ * handles. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjects)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
+ CK_ULONG ulMaxObjectCount, /* max handles to get */
+ CK_ULONG_PTR pulObjectCount /* actual # returned */
+);
+#endif
+
+/* C_FindObjectsFinal finishes a search for token and session
+ * objects. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+/* Encryption and decryption */
+
+/* C_EncryptInit initializes an encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of encryption key */
+);
+#endif
+
+/* C_Encrypt encrypts single-part data. */
+CK_PKCS11_FUNCTION_INFO(C_Encrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pData, /* the plaintext data */
+ CK_ULONG ulDataLen, /* bytes of plaintext */
+ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
+);
+#endif
+
+/* C_EncryptUpdate continues a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext data len */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
+);
+#endif
+
+/* C_EncryptFinal finishes a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session handle */
+ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
+ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
+);
+#endif
+
+/* C_DecryptInit initializes a decryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of decryption key */
+);
+#endif
+
+/* C_Decrypt decrypts encrypted data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Decrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedData, /* ciphertext */
+ CK_ULONG ulEncryptedDataLen, /* ciphertext length */
+ CK_BYTE_PTR pData, /* gets plaintext */
+ CK_ULONG_PTR pulDataLen /* gets p-text size */
+);
+#endif
+
+/* C_DecryptUpdate continues a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* encrypted data */
+ CK_ULONG ulEncryptedPartLen, /* input length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* p-text size */
+);
+#endif
+
+/* C_DecryptFinal finishes a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pLastPart, /* gets plaintext */
+ CK_ULONG_PTR pulLastPartLen /* p-text size */
+);
+#endif
+
+/* Message digesting */
+
+/* C_DigestInit initializes a message-digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
+);
+#endif
+
+/* C_Digest digests data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Digest)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* data to be digested */
+ CK_ULONG ulDataLen, /* bytes of data to digest */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets digest length */
+);
+#endif
+
+/* C_DigestUpdate continues a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* data to be digested */
+ CK_ULONG ulPartLen /* bytes of data to be digested */
+);
+#endif
+
+/* C_DigestKey continues a multi-part message-digesting
+ * operation, by digesting the value of a secret key as part of
+ * the data already digested. */
+CK_PKCS11_FUNCTION_INFO(C_DigestKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hKey /* secret key to digest */
+);
+#endif
+
+/* C_DigestFinal finishes a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
+);
+#endif
+
+/* Signing and MACing */
+
+/* C_SignInit initializes a signature (private key encryption)
+ * operation, where the signature is (will be) an appendix to
+ * the data, and plaintext cannot be recovered from the
+ *signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of signature key */
+);
+#endif
+
+/* C_Sign signs (encrypts with private key) data in a single
+ * part, where the signature is (will be) an appendix to the
+ * data, and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Sign)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+/* C_SignUpdate continues a multiple-part signature operation,
+ * where the signature is (will be) an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* the data to sign */
+ CK_ULONG ulPartLen /* count of bytes to sign */
+);
+#endif
+
+/* C_SignFinal finishes a multiple-part signature operation,
+ * returning the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+/* C_SignRecoverInit initializes a signature operation, where
+ * the data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of the signature key */
+);
+#endif
+
+/* C_SignRecover signs data in a single operation, where the
+ * data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+/* Verifying signatures and MACs */
+
+/* C_VerifyInit initializes a verification operation, where the
+ * signature is an appendix to the data, and plaintext cannot
+ * cannot be recovered from the signature (e.g. DSA). */
+CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+/* C_Verify verifies a signature in a single-part operation,
+ * where the signature is an appendix to the data, and plaintext
+ * cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Verify)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* signed data */
+ CK_ULONG ulDataLen, /* length of signed data */
+ CK_BYTE_PTR pSignature, /* signature */
+ CK_ULONG ulSignatureLen /* signature length*/
+);
+#endif
+
+/* C_VerifyUpdate continues a multiple-part verification
+ * operation, where the signature is an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* signed data */
+ CK_ULONG ulPartLen /* length of signed data */
+);
+#endif
+
+/* C_VerifyFinal finishes a multiple-part verification
+ * operation, checking the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen /* signature length */
+);
+#endif
+
+/* C_VerifyRecoverInit initializes a signature verification
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+/* C_VerifyRecover verifies a signature in a single-part
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen, /* signature length */
+ CK_BYTE_PTR pData, /* gets signed data */
+ CK_ULONG_PTR pulDataLen /* gets signed data len */
+);
+#endif
+
+/* Dual-function cryptographic operations */
+
+/* C_DigestEncryptUpdate continues a multiple-part digesting
+ * and encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+/* C_DecryptDigestUpdate continues a multiple-part decryption and
+ * digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets plaintext len */
+);
+#endif
+
+/* C_SignEncryptUpdate continues a multiple-part signing and
+ * encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+/* C_DecryptVerifyUpdate continues a multiple-part decryption and
+ * verify operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets p-text length */
+);
+#endif
+
+/* Key management */
+
+/* C_GenerateKey generates a secret key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key generation mech. */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
+ CK_ULONG ulCount, /* # of attrs in template */
+ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
+);
+#endif
+
+/* C_GenerateKeyPair generates a public-key/private-key pair,
+ * creating new key objects. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session handle */
+ CK_MECHANISM_PTR pMechanism, /* key-gen mech. */
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template for pub. key */
+ CK_ULONG ulPublicKeyAttributeCount, /* # pub. attrs. */
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template for priv. key */
+ CK_ULONG ulPrivateKeyAttributeCount, /* # priv. attrs. */
+ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub. key handle */
+ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets priv. key handle */
+);
+#endif
+
+/* C_WrapKey wraps (i.e., encrypts) a key. */
+CK_PKCS11_FUNCTION_INFO(C_WrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
+ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
+ CK_OBJECT_HANDLE hKey, /* key to be wrapped */
+ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
+ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
+);
+#endif
+
+/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
+ * key object. */
+CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
+ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
+ CK_BYTE_PTR pWrappedKey, /* the wrapped key */
+ CK_ULONG ulWrappedKeyLen, /* wrapped key len */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+/* C_DeriveKey derives a key from a base key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
+ CK_OBJECT_HANDLE hBaseKey, /* base key */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+/* Random number generation */
+
+/* C_SeedRandom mixes additional seed material into the token's
+ * random number generator. */
+CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSeed, /* the seed material */
+ CK_ULONG ulSeedLen /* length of seed material */
+);
+#endif
+
+/* C_GenerateRandom generates random data. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR RandomData, /* receives the random data */
+ CK_ULONG ulRandomLen /* # of bytes to generate */
+);
+#endif
+
+/* Parallel function management */
+
+/* C_GetFunctionStatus is a legacy function; it obtains an
+ * updated status of a function running in parallel with an
+ * application. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+/* C_CancelFunction is a legacy function; it cancels a function
+ * running in parallel. */
+CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+/* Functions added in for PKCS #11 Version 2.01 or later */
+
+/* C_WaitForSlotEvent waits for a slot event (token insertion,
+ * removal, etc.) to occur. */
+CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FLAGS flags, /* blocking/nonblocking flag */
+ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
+ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
+);
+#endif
+
+#if defined(CK_PKCS11_3_0) && !defined(CK_PKCS11_2_0_ONLY)
+CK_PKCS11_FUNCTION_INFO(C_GetInterfaceList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_INTERFACE_PTR interfaces,
+ CK_ULONG_PTR pulCount);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_GetInterface)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_UTF8CHAR_PTR pInterfaceName,
+ CK_VERSION_PTR pVersion,
+ CK_INTERFACE_PTR_PTR ppInterface,
+ CK_FLAGS flags);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_LoginUser)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_USER_TYPE userType,
+ CK_CHAR_PTR pPin,
+ CK_ULONG ulPinLen,
+ CK_UTF8CHAR_PTR pUsername,
+ CK_ULONG ulUsernameLen);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_SessionCancel)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_FLAGS flags);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_MessageEncryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_EncryptMessage)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen,
+ CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen,
+ CK_BYTE_PTR pPlaintext,
+ CK_ULONG ulPlaintextLen,
+ CK_BYTE_PTR pCiphertext,
+ CK_ULONG_PTR pulCiphertextLen);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_EncryptMessageBegin)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen,
+ CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_EncryptMessageNext)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen,
+ CK_BYTE_PTR pPlaintextPart,
+ CK_ULONG ulPlaintextPartLen,
+ CK_BYTE_PTR pCiphertextPart,
+ CK_ULONG_PTR pulCiphertextPartLen,
+ CK_FLAGS flags);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_MessageEncryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_MessageDecryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_DecryptMessage)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen,
+ CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen,
+ CK_BYTE_PTR pCiphertext,
+ CK_ULONG ulCiphertextLen,
+ CK_BYTE_PTR pPlaintext,
+ CK_ULONG_PTR pulPlaintextLen);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_DecryptMessageBegin)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen,
+ CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_DecryptMessageNext)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen,
+ CK_BYTE_PTR pCiphertextPart,
+ CK_ULONG ulCiphertextPartLen,
+ CK_BYTE_PTR pPlaintextPart,
+ CK_ULONG_PTR pulPlaintextPartLen,
+ CK_FLAGS flags);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_MessageDecryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_MessageSignInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_SignMessage)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen,
+ CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen,
+
+ CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_SignMessageBegin)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_SignMessageNext)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen,
+ CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_MessageSignFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_MessageVerifyInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_VerifyMessage)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen,
+ CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_VerifyMessageBegin)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_VerifyMessageNext)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession,
+ CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen,
+ CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen);
+#endif
+
+CK_PKCS11_FUNCTION_INFO(C_MessageVerifyFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession);
+#endif
+
+#endif
diff --git a/security/nss/lib/util/pkcs11n.h b/security/nss/lib/util/pkcs11n.h
new file mode 100644
index 0000000000..8c33b8719b
--- /dev/null
+++ b/security/nss/lib/util/pkcs11n.h
@@ -0,0 +1,745 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 _PKCS11N_H_
+#define _PKCS11N_H_
+
+/*
+ * pkcs11n.h
+ *
+ * This file contains the NSS-specific type definitions for Cryptoki
+ * (PKCS#11).
+ */
+
+/*
+ * NSSCK_VENDOR_NSS
+ *
+ * Cryptoki reserves the high half of all the number spaces for
+ * vendor-defined use. I'd like to keep all of our NSS-
+ * specific values together, but not in the oh-so-obvious
+ * 0x80000001, 0x80000002, etc. area. So I've picked an offset,
+ * and constructed values for the beginnings of our spaces.
+ *
+ * Note that some "historical" Netscape values don't fall within
+ * this range.
+ */
+#define NSSCK_VENDOR_NSS 0x4E534350 /* NSCP */
+
+/*
+ * NSS-defined object classes
+ *
+ */
+#define CKO_NSS (CKO_VENDOR_DEFINED | NSSCK_VENDOR_NSS)
+
+#define CKO_NSS_CRL (CKO_NSS + 1)
+#define CKO_NSS_SMIME (CKO_NSS + 2)
+#define CKO_NSS_TRUST (CKO_NSS + 3)
+#define CKO_NSS_BUILTIN_ROOT_LIST (CKO_NSS + 4)
+#define CKO_NSS_NEWSLOT (CKO_NSS + 5)
+#define CKO_NSS_DELSLOT (CKO_NSS + 6)
+#define CKO_NSS_VALIDATION (CKO_NSS + 7)
+
+#define CKV_NSS_FIPS_140 (CKO_NSS + 1)
+
+/*
+ * NSS-defined key types
+ *
+ */
+#define CKK_NSS (CKK_VENDOR_DEFINED | NSSCK_VENDOR_NSS)
+
+#define CKK_NSS_PKCS8 (CKK_NSS + 1)
+
+#define CKK_NSS_JPAKE_ROUND1 (CKK_NSS + 2)
+#define CKK_NSS_JPAKE_ROUND2 (CKK_NSS + 3)
+
+#define CKK_NSS_CHACHA20 (CKK_NSS + 4)
+
+#define CKK_NSS_KYBER (CKK_NSS + 5)
+
+/*
+ * NSS-defined certificate types
+ *
+ */
+#define CKC_NSS (CKC_VENDOR_DEFINED | NSSCK_VENDOR_NSS)
+
+/* FAKE PKCS #11 defines */
+#define CKA_DIGEST 0x81000000L
+#define CKA_NSS_MESSAGE 0x82000000L
+#define CKA_NSS_MESSAGE_MASK 0xff000000L
+#define CKA_FLAGS_ONLY 0 /* CKA_CLASS */
+
+/*
+ * NSS-defined object attributes
+ *
+ */
+#define CKA_NSS (CKA_VENDOR_DEFINED | NSSCK_VENDOR_NSS)
+
+#define CKA_NSS_URL (CKA_NSS + 1)
+#define CKA_NSS_EMAIL (CKA_NSS + 2)
+#define CKA_NSS_SMIME_INFO (CKA_NSS + 3)
+#define CKA_NSS_SMIME_TIMESTAMP (CKA_NSS + 4)
+#define CKA_NSS_PKCS8_SALT (CKA_NSS + 5)
+#define CKA_NSS_PASSWORD_CHECK (CKA_NSS + 6)
+#define CKA_NSS_EXPIRES (CKA_NSS + 7)
+#define CKA_NSS_KRL (CKA_NSS + 8)
+
+#define CKA_NSS_PQG_COUNTER (CKA_NSS + 20)
+#define CKA_NSS_PQG_SEED (CKA_NSS + 21)
+#define CKA_NSS_PQG_H (CKA_NSS + 22)
+#define CKA_NSS_PQG_SEED_BITS (CKA_NSS + 23)
+#define CKA_NSS_MODULE_SPEC (CKA_NSS + 24)
+#define CKA_NSS_OVERRIDE_EXTENSIONS (CKA_NSS + 25)
+
+#define CKA_NSS_JPAKE_SIGNERID (CKA_NSS + 26)
+#define CKA_NSS_JPAKE_PEERID (CKA_NSS + 27)
+#define CKA_NSS_JPAKE_GX1 (CKA_NSS + 28)
+#define CKA_NSS_JPAKE_GX2 (CKA_NSS + 29)
+#define CKA_NSS_JPAKE_GX3 (CKA_NSS + 30)
+#define CKA_NSS_JPAKE_GX4 (CKA_NSS + 31)
+#define CKA_NSS_JPAKE_X2 (CKA_NSS + 32)
+#define CKA_NSS_JPAKE_X2S (CKA_NSS + 33)
+
+#define CKA_NSS_MOZILLA_CA_POLICY (CKA_NSS + 34)
+#define CKA_NSS_SERVER_DISTRUST_AFTER (CKA_NSS + 35)
+#define CKA_NSS_EMAIL_DISTRUST_AFTER (CKA_NSS + 36)
+
+#define CKA_NSS_VALIDATION_TYPE (CKA_NSS + 36)
+#define CKA_NSS_VALIDATION_VERSION (CKA_NSS + 37)
+#define CKA_NSS_VALIDATION_LEVEL (CKA_NSS + 38)
+#define CKA_NSS_VALIDATION_MODULE_ID (CKA_NSS + 39)
+
+#define CKA_NSS_PARAMETER_SET (CKA_NSS + 40)
+
+/*
+ * Trust attributes:
+ *
+ * If trust goes standard, these probably will too. So I'll
+ * put them all in one place.
+ */
+
+#define CKA_TRUST (CKA_NSS + 0x2000)
+
+/* "Usage" key information */
+#define CKA_TRUST_DIGITAL_SIGNATURE (CKA_TRUST + 1)
+#define CKA_TRUST_NON_REPUDIATION (CKA_TRUST + 2)
+#define CKA_TRUST_KEY_ENCIPHERMENT (CKA_TRUST + 3)
+#define CKA_TRUST_DATA_ENCIPHERMENT (CKA_TRUST + 4)
+#define CKA_TRUST_KEY_AGREEMENT (CKA_TRUST + 5)
+#define CKA_TRUST_KEY_CERT_SIGN (CKA_TRUST + 6)
+#define CKA_TRUST_CRL_SIGN (CKA_TRUST + 7)
+
+/* "Purpose" trust information */
+#define CKA_TRUST_SERVER_AUTH (CKA_TRUST + 8)
+#define CKA_TRUST_CLIENT_AUTH (CKA_TRUST + 9)
+#define CKA_TRUST_CODE_SIGNING (CKA_TRUST + 10)
+#define CKA_TRUST_EMAIL_PROTECTION (CKA_TRUST + 11)
+#define CKA_TRUST_IPSEC_END_SYSTEM (CKA_TRUST + 12)
+#define CKA_TRUST_IPSEC_TUNNEL (CKA_TRUST + 13)
+#define CKA_TRUST_IPSEC_USER (CKA_TRUST + 14)
+#define CKA_TRUST_TIME_STAMPING (CKA_TRUST + 15)
+#define CKA_TRUST_STEP_UP_APPROVED (CKA_TRUST + 16)
+
+#define CKA_CERT_SHA1_HASH (CKA_TRUST + 100)
+#define CKA_CERT_MD5_HASH (CKA_TRUST + 101)
+
+/* NSS trust stuff */
+
+/* HISTORICAL: define used to pass in the database key for DSA private keys */
+#define CKA_NSS_DB 0xD5A0DB00L
+#define CKA_NSS_TRUST 0x80000001L
+
+/* FAKE PKCS #11 defines */
+#define CKM_FAKE_RANDOM 0x80000efeUL
+#define CKM_INVALID_MECHANISM 0xffffffffUL
+#define CKT_INVALID_TYPE 0xffffffffUL
+
+/*
+ * NSS-defined crypto mechanisms
+ *
+ */
+#define CKM_NSS (CKM_VENDOR_DEFINED | NSSCK_VENDOR_NSS)
+
+#define CKM_NSS_AES_KEY_WRAP (CKM_NSS + 1)
+#define CKM_NSS_AES_KEY_WRAP_PAD (CKM_NSS + 2)
+
+/* HKDF key derivation mechanisms. See CK_NSS_HKDFParams for documentation. */
+#define CKM_NSS_HKDF_SHA1 (CKM_NSS + 3)
+#define CKM_NSS_HKDF_SHA256 (CKM_NSS + 4)
+#define CKM_NSS_HKDF_SHA384 (CKM_NSS + 5)
+#define CKM_NSS_HKDF_SHA512 (CKM_NSS + 6)
+
+/* J-PAKE round 1 key generation mechanisms.
+ *
+ * Required template attributes: CKA_PRIME, CKA_SUBPRIME, CKA_BASE,
+ * CKA_NSS_JPAKE_SIGNERID
+ * Output key type: CKK_NSS_JPAKE_ROUND1
+ * Output key class: CKO_PRIVATE_KEY
+ * Parameter type: CK_NSS_JPAKERound1Params
+ *
+ */
+#define CKM_NSS_JPAKE_ROUND1_SHA1 (CKM_NSS + 7)
+#define CKM_NSS_JPAKE_ROUND1_SHA256 (CKM_NSS + 8)
+#define CKM_NSS_JPAKE_ROUND1_SHA384 (CKM_NSS + 9)
+#define CKM_NSS_JPAKE_ROUND1_SHA512 (CKM_NSS + 10)
+
+/* J-PAKE round 2 key derivation mechanisms.
+ *
+ * Required template attributes: CKA_NSS_JPAKE_PEERID
+ * Input key type: CKK_NSS_JPAKE_ROUND1
+ * Output key type: CKK_NSS_JPAKE_ROUND2
+ * Output key class: CKO_PRIVATE_KEY
+ * Parameter type: CK_NSS_JPAKERound2Params
+ */
+#define CKM_NSS_JPAKE_ROUND2_SHA1 (CKM_NSS + 11)
+#define CKM_NSS_JPAKE_ROUND2_SHA256 (CKM_NSS + 12)
+#define CKM_NSS_JPAKE_ROUND2_SHA384 (CKM_NSS + 13)
+#define CKM_NSS_JPAKE_ROUND2_SHA512 (CKM_NSS + 14)
+
+/* J-PAKE final key material derivation mechanisms
+ *
+ * Input key type: CKK_NSS_JPAKE_ROUND2
+ * Output key type: CKK_GENERIC_SECRET
+ * Output key class: CKO_SECRET_KEY
+ * Parameter type: CK_NSS_JPAKEFinalParams
+ *
+ * You must apply a KDF (e.g. CKM_NSS_HKDF_*) to resultant keying material
+ * to get a key with uniformly distributed bits.
+ */
+#define CKM_NSS_JPAKE_FINAL_SHA1 (CKM_NSS + 15)
+#define CKM_NSS_JPAKE_FINAL_SHA256 (CKM_NSS + 16)
+#define CKM_NSS_JPAKE_FINAL_SHA384 (CKM_NSS + 17)
+#define CKM_NSS_JPAKE_FINAL_SHA512 (CKM_NSS + 18)
+
+/* Constant-time MAC mechanisms:
+ *
+ * These operations verify a padded, MAC-then-encrypt block of data in
+ * constant-time. Because of the order of operations, the padding bytes are not
+ * protected by the MAC. However, disclosing the value of the padding bytes
+ * gives an attacker the ability to decrypt ciphertexts. Such disclosure can be
+ * as subtle as taking slightly less time to perform the MAC when the padding
+ * is one byte longer. See https://www.isg.rhul.ac.uk/tls/
+ *
+ * CKM_NSS_HMAC_CONSTANT_TIME: performs an HMAC authentication.
+ * CKM_NSS_SSL3_MAC_CONSTANT_TIME: performs an authentication with SSLv3 MAC.
+ *
+ * Parameter type: CK_NSS_MAC_CONSTANT_TIME_PARAMS
+ */
+#define CKM_NSS_HMAC_CONSTANT_TIME (CKM_NSS + 19)
+#define CKM_NSS_SSL3_MAC_CONSTANT_TIME (CKM_NSS + 20)
+
+/* TLS 1.2 mechanisms */
+#define CKM_NSS_TLS_PRF_GENERAL_SHA256 (CKM_NSS + 21)
+#define CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256 (CKM_NSS + 22)
+#define CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256 (CKM_NSS + 23)
+#define CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 (CKM_NSS + 24)
+
+/* TLS extended master secret derivation */
+#define CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE (CKM_NSS + 25)
+#define CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH (CKM_NSS + 26)
+
+#define CKM_NSS_CHACHA20_KEY_GEN (CKM_NSS + 27)
+#define CKM_NSS_CHACHA20_POLY1305 (CKM_NSS + 28)
+
+/* Additional PKCS #12 PBE algorithms defined in v1.1 */
+#define CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN (CKM_NSS + 29)
+#define CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN (CKM_NSS + 30)
+#define CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN (CKM_NSS + 31)
+#define CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN (CKM_NSS + 32)
+
+#define CKM_NSS_CHACHA20_CTR (CKM_NSS + 33)
+
+/* IKE mechanism (to be proposed to PKCS #11 */
+#define CKM_NSS_IKE_PRF_PLUS_DERIVE (CKM_NSS + 34)
+#define CKM_NSS_IKE_PRF_DERIVE (CKM_NSS + 35)
+#define CKM_NSS_IKE1_PRF_DERIVE (CKM_NSS + 36)
+#define CKM_NSS_IKE1_APP_B_PRF_DERIVE (CKM_NSS + 37)
+
+#define CKM_NSS_PUB_FROM_PRIV (CKM_NSS + 40)
+
+/* SP800-108 NSS mechanism with support for data object derivation */
+#define CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA (CKM_NSS + 42)
+#define CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA (CKM_NSS + 43)
+#define CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA (CKM_NSS + 44)
+
+/* Kyber */
+#define CKM_NSS_KYBER_KEY_PAIR_GEN (CKM_NSS + 45)
+#define CKM_NSS_KYBER (CKM_NSS + 46)
+
+/*
+ * HISTORICAL:
+ * Do not attempt to use these. They are only used by NSS's internal
+ * PKCS #11 interface. Most of these are place holders for other mechanism
+ * and will change in the future.
+ */
+#define CKM_NSS_PBE_SHA1_DES_CBC 0x80000002UL
+#define CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC 0x80000003UL
+#define CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC 0x80000004UL
+#define CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC 0x80000005UL
+#define CKM_NSS_PBE_SHA1_40_BIT_RC4 0x80000006UL
+#define CKM_NSS_PBE_SHA1_128_BIT_RC4 0x80000007UL
+#define CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC 0x80000008UL
+#define CKM_NSS_PBE_SHA1_HMAC_KEY_GEN 0x80000009UL
+#define CKM_NSS_PBE_MD5_HMAC_KEY_GEN 0x8000000aUL
+#define CKM_NSS_PBE_MD2_HMAC_KEY_GEN 0x8000000bUL
+
+#define CKM_TLS_PRF_GENERAL 0x80000373UL
+
+/* Parameter set identifiers */
+#define CKP_NSS (CKM_VENDOR_DEFINED | NSSCK_VENDOR_NSS)
+#define CKP_NSS_KYBER_768_ROUND3 (CKP_NSS + 1)
+
+/* FIPS Indicator defines */
+#define CKS_NSS_UNINITIALIZED 0xffffffffUL
+#define CKS_NSS_FIPS_NOT_OK 0UL
+#define CKS_NSS_FIPS_OK 1UL
+
+#define CKT_NSS_SESSION_CHECK 1UL
+#define CKT_NSS_OBJECT_CHECK 2UL
+#define CKT_NSS_BOTH_CHECK 3UL
+#define CKT_NSS_SESSION_LAST_CHECK 4UL
+
+typedef struct CK_NSS_JPAKEPublicValue {
+ CK_BYTE *pGX;
+ CK_ULONG ulGXLen;
+ CK_BYTE *pGV;
+ CK_ULONG ulGVLen;
+ CK_BYTE *pR;
+ CK_ULONG ulRLen;
+} CK_NSS_JPAKEPublicValue;
+
+typedef struct CK_NSS_JPAKERound1Params {
+ CK_NSS_JPAKEPublicValue gx1; /* out */
+ CK_NSS_JPAKEPublicValue gx2; /* out */
+} CK_NSS_JPAKERound1Params;
+
+typedef struct CK_NSS_JPAKERound2Params {
+ CK_BYTE *pSharedKey; /* in */
+ CK_ULONG ulSharedKeyLen; /* in */
+ CK_NSS_JPAKEPublicValue gx3; /* in */
+ CK_NSS_JPAKEPublicValue gx4; /* in */
+ CK_NSS_JPAKEPublicValue A; /* out */
+} CK_NSS_JPAKERound2Params;
+
+typedef struct CK_NSS_JPAKEFinalParams {
+ CK_NSS_JPAKEPublicValue B; /* in */
+} CK_NSS_JPAKEFinalParams;
+
+/* macAlg: the MAC algorithm to use. This determines the hash function used in
+ * the HMAC/SSLv3 MAC calculations.
+ * ulBodyTotalLen: the total length of the data, including padding bytes and
+ * padding length.
+ * pHeader: points to a block of data that contains additional data to
+ * authenticate. For TLS this includes the sequence number etc. For SSLv3,
+ * this also includes the initial padding bytes.
+ *
+ * NOTE: the softoken's implementation of CKM_NSS_HMAC_CONSTANT_TIME and
+ * CKM_NSS_SSL3_MAC_CONSTANT_TIME requires that the sum of ulBodyTotalLen
+ * and ulHeaderLen be much smaller than 2^32 / 8 bytes because it uses an
+ * unsigned int variable to represent the length in bits. This should not
+ * be a problem because the SSL/TLS protocol limits the size of an SSL
+ * record to something considerably less than 2^32 bytes.
+ */
+typedef struct CK_NSS_MAC_CONSTANT_TIME_PARAMS {
+ CK_MECHANISM_TYPE macAlg; /* in */
+ CK_ULONG ulBodyTotalLen; /* in */
+ CK_BYTE *pHeader; /* in */
+ CK_ULONG ulHeaderLen; /* in */
+} CK_NSS_MAC_CONSTANT_TIME_PARAMS;
+
+typedef struct CK_NSS_AEAD_PARAMS {
+ CK_BYTE_PTR pNonce;
+ CK_ULONG ulNonceLen;
+ CK_BYTE_PTR pAAD;
+ CK_ULONG ulAADLen;
+ CK_ULONG ulTagLen;
+} CK_NSS_AEAD_PARAMS;
+
+/*
+ * NSS-defined return values
+ *
+ */
+#define CKR_NSS (CKM_VENDOR_DEFINED | NSSCK_VENDOR_NSS)
+
+#define CKR_NSS_CERTDB_FAILED (CKR_NSS + 1)
+#define CKR_NSS_KEYDB_FAILED (CKR_NSS + 2)
+
+/* NSS specific types */
+typedef CK_ULONG CK_NSS_VALIDATION_TYPE;
+
+typedef CK_ULONG CK_NSS_KEM_PARAMETER_SET_TYPE;
+
+/* Mandatory parameter for the CKM_NSS_HKDF_* key deriviation mechanisms.
+ See RFC 5869.
+
+ bExtract: If set, HKDF-Extract will be applied to the input key. If
+ the optional salt is given, it is used; otherwise, the salt is
+ set to a sequence of zeros equal in length to the HMAC output.
+ If bExpand is not set, then the key template given to
+ C_DeriveKey must indicate an output key size less than or equal
+ to the output size of the HMAC.
+
+ bExpand: If set, HKDF-Expand will be applied to the input key (if
+ bExtract is not set) or to the result of HKDF-Extract (if
+ bExtract is set). Any info given in the optional pInfo field will
+ be included in the calculation.
+
+ The size of the output key must be specified in the template passed to
+ C_DeriveKey.
+*/
+typedef struct CK_NSS_HKDFParams {
+ CK_BBOOL bExtract;
+ CK_BYTE_PTR pSalt;
+ CK_ULONG ulSaltLen;
+ CK_BBOOL bExpand;
+ CK_BYTE_PTR pInfo;
+ CK_ULONG ulInfoLen;
+} CK_NSS_HKDFParams;
+
+/*
+ * CK_NSS_IKE_PRF_PLUS_PARAMS is a structure that provides the parameters to
+ * the CKM_NSS_IKE_PRF_PLUS_DERIVE mechanism.
+ * The fields of the structure have the following meanings:
+ * prfMechanism underlying MAC mechanism used to generate the prf.
+ * bHasSeedKey hSeed key is present.
+ * hSeedKey optional seed from key
+ * pSeedData optional seed from data.
+ * ulSeedDataLen length of optional seed data.
+ * If no seed data is present this value is NULL.
+ */
+typedef struct CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS {
+ CK_MECHANISM_TYPE prfMechanism;
+ CK_BBOOL bHasSeedKey;
+ CK_OBJECT_HANDLE hSeedKey;
+ CK_BYTE_PTR pSeedData;
+ CK_ULONG ulSeedDataLen;
+} CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS;
+
+/* CK_NSS_IKE_PRF_DERIVE_PARAMS is a structure that provides the parameters to
+ * the CKM_NSS_IKE_PRF_DERIVE mechanism.
+ *
+ * The fields of the structure have the following meanings:
+ * prfMechanism underlying MAC mechanism used to generate the prf.
+ * bRekey hNewKey is present.
+ * pNi Ni value
+ * ulNiLen length of Ni
+ * pNr Nr value
+ * ulNrLen length of Nr
+ * hNewKey New key value to drive the rekey.
+ */
+typedef struct CK_NSS_IKE_PRF_DERIVE_PARAMS {
+ CK_MECHANISM_TYPE prfMechanism;
+ CK_BBOOL bDataAsKey;
+ CK_BBOOL bRekey;
+ CK_BYTE_PTR pNi;
+ CK_ULONG ulNiLen;
+ CK_BYTE_PTR pNr;
+ CK_ULONG ulNrLen;
+ CK_OBJECT_HANDLE hNewKey;
+} CK_NSS_IKE_PRF_DERIVE_PARAMS;
+
+/* CK_NSS_IKE1_PRF_DERIVE_PARAMS is a structure that provides the parameters
+ * to the CKM_NSS_IKE_PRF_DERIVE mechanism.
+ *
+ * The fields of the structure have the following meanings:
+ * prfMechanism underlying MAC mechanism used to generate the prf.
+ * bRekey hNewKey is present.
+ * pCKYi CKYi value
+ * ulCKYiLen length of CKYi
+ * pCKYr CKYr value
+ * ulCKYrLen length of CKYr
+ * hNewKey New key value to drive the rekey.
+ */
+typedef struct CK_NSS_IKE1_PRF_DERIVE_PARAMS {
+ CK_MECHANISM_TYPE prfMechanism;
+ CK_BBOOL bHasPrevKey;
+ CK_OBJECT_HANDLE hKeygxy;
+ CK_OBJECT_HANDLE hPrevKey;
+ CK_BYTE_PTR pCKYi;
+ CK_ULONG ulCKYiLen;
+ CK_BYTE_PTR pCKYr;
+ CK_ULONG ulCKYrLen;
+ CK_BYTE keyNumber;
+} CK_NSS_IKE1_PRF_DERIVE_PARAMS;
+
+/* CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS is a structure that provides the
+ * parameters to the CKM_NSS_IKE_APP_B_PRF_DERIVE mechanism.
+ *
+ * The fields of the structure have the following meanings:
+ * prfMechanism underlying MAC mechanism used to generate the prf.
+ * bHasKeygxy hKeygxy exists
+ * hKeygxy optional key to hash in the prf
+ * pExtraData optional extra data to hash in the prf
+ * ulExtraData length of the optional extra data.
+ *
+ * CK_NSS_IKE_APP_B_PRF_DERIVE can take wither CK_NSS_IKE1_APP_B_PRF_DRIVE_PARAMS
+ * or a single CK_MECHANISM_TYPE. In the latter cases bHashKeygx is assumed to
+ * be false and ulExtraDataLen is assumed to be '0'.
+ */
+typedef struct CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS {
+ CK_MECHANISM_TYPE prfMechanism;
+ CK_BBOOL bHasKeygxy;
+ CK_OBJECT_HANDLE hKeygxy;
+ CK_BYTE_PTR pExtraData;
+ CK_ULONG ulExtraDataLen;
+} CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS;
+
+/*
+ * Parameter for the TLS extended master secret key derivation mechanisms:
+ *
+ * * CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE
+ * * CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH
+ *
+ * For the TLS 1.2 PRF, the prfHashMechanism parameter determines the hash
+ * function used. For earlier versions of the PRF, set the prfHashMechanism
+ * value to CKM_TLS_PRF.
+ *
+ * The session hash input is expected to be the output of the same hash
+ * function as the PRF uses (as required by draft-ietf-tls-session-hash). So
+ * the ulSessionHashLen member must be equal the output length of the hash
+ * function specified by the prfHashMechanism member (or, for pre-TLS 1.2 PRF,
+ * the length of concatenated MD5 and SHA-1 digests).
+ *
+ */
+typedef struct CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS {
+ CK_MECHANISM_TYPE prfHashMechanism;
+ CK_BYTE_PTR pSessionHash;
+ CK_ULONG ulSessionHashLen;
+ CK_VERSION_PTR pVersion;
+} CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS;
+
+/*
+ * Trust info
+ *
+ * This isn't part of the Cryptoki standard (yet), so I'm putting
+ * all the definitions here. Some of this would move to nssckt.h
+ * if trust info were made part of the standard. In view of this
+ * possibility, I'm putting my (NSS) values in the NSS
+ * vendor space, like everything else.
+ */
+
+typedef CK_ULONG CK_TRUST;
+
+/* The following trust types are defined: */
+#define CKT_VENDOR_DEFINED 0x80000000
+
+#define CKT_NSS (CKT_VENDOR_DEFINED | NSSCK_VENDOR_NSS)
+
+/* If trust goes standard, these'll probably drop out of vendor space. */
+#define CKT_NSS_TRUSTED (CKT_NSS + 1)
+#define CKT_NSS_TRUSTED_DELEGATOR (CKT_NSS + 2)
+#define CKT_NSS_MUST_VERIFY_TRUST (CKT_NSS + 3)
+#define CKT_NSS_NOT_TRUSTED (CKT_NSS + 10)
+#define CKT_NSS_TRUST_UNKNOWN (CKT_NSS + 5) /* default */
+
+/*
+ * These may well remain NSS-specific; I'm only using them
+ * to cache resolution data.
+ */
+#define CKT_NSS_VALID_DELEGATOR (CKT_NSS + 11)
+
+/*
+ * old definitions. They still exist, but the plain meaning of the
+ * labels have never been accurate to what was really implemented.
+ * The new labels correctly reflect what the values effectively mean.
+ */
+#if defined(__GNUC__) && (__GNUC__ > 3)
+/* make GCC warn when we use these #defines */
+/*
+ * This is really painful because GCC doesn't allow us to mark random
+ * #defines as deprecated. We can only mark the following:
+ * functions, variables, and types.
+ * const variables will create extra storage for everyone including this
+ * header file, so it's undesirable.
+ * functions could be inlined to prevent storage creation, but will fail
+ * when constant values are expected (like switch statements).
+ * enum types do not seem to pay attention to the deprecated attribute.
+ *
+ * That leaves typedefs. We declare new types that we then deprecate, then
+ * cast the resulting value to the deprecated type in the #define, thus
+ * producting the warning when the #define is used.
+ */
+#if (__GNUC__ == 4) && (__GNUC_MINOR__ < 5)
+/* The mac doesn't like the friendlier deprecate messages. I'm assuming this
+ * is a gcc version issue rather than mac or ppc specific */
+typedef CK_TRUST __CKT_NSS_UNTRUSTED __attribute__((deprecated));
+typedef CK_TRUST __CKT_NSS_VALID __attribute__((deprecated));
+typedef CK_TRUST __CKT_NSS_MUST_VERIFY __attribute__((deprecated));
+#else
+/* when possible, get a full deprecation warning. This works on gcc 4.5
+ * it may work on earlier versions of gcc */
+typedef CK_TRUST __CKT_NSS_UNTRUSTED __attribute__((deprecated("CKT_NSS_UNTRUSTED really means CKT_NSS_MUST_VERIFY_TRUST")));
+typedef CK_TRUST __CKT_NSS_VALID __attribute__((deprecated("CKT_NSS_VALID really means CKT_NSS_NOT_TRUSTED")));
+typedef CK_TRUST __CKT_NSS_MUST_VERIFY __attribute__((deprecated("CKT_NSS_MUST_VERIFY really functions as CKT_NSS_TRUST_UNKNOWN")));
+#endif
+#define CKT_NSS_UNTRUSTED ((__CKT_NSS_UNTRUSTED)CKT_NSS_MUST_VERIFY_TRUST)
+#define CKT_NSS_VALID ((__CKT_NSS_VALID)CKT_NSS_NOT_TRUSTED)
+/* keep the old value for compatibility reasons*/
+#define CKT_NSS_MUST_VERIFY ((__CKT_NSS_MUST_VERIFY)(CKT_NSS + 4))
+#else
+#ifdef _WIN32
+/* This magic gets the windows compiler to give us a deprecation
+ * warning */
+#pragma deprecated(CKT_NSS_UNTRUSTED, CKT_NSS_MUST_VERIFY, CKT_NSS_VALID)
+#endif
+/* CKT_NSS_UNTRUSTED really means CKT_NSS_MUST_VERIFY_TRUST */
+#define CKT_NSS_UNTRUSTED CKT_NSS_MUST_VERIFY_TRUST
+/* CKT_NSS_VALID really means CKT_NSS_NOT_TRUSTED */
+#define CKT_NSS_VALID CKT_NSS_NOT_TRUSTED
+/* CKT_NSS_MUST_VERIFY was always treated as CKT_NSS_TRUST_UNKNOWN */
+#define CKT_NSS_MUST_VERIFY (CKT_NSS + 4) /*really means trust unknown*/
+#endif
+
+/*
+ * These are not really PKCS #11 values specifically. They are the 'loadable'
+ * module spec NSS uses. They are available for others to use as well, but not
+ * part of the formal PKCS #11 spec.
+ *
+ * The function 'FIND' returns an array of PKCS #11 initialization strings
+ * The function 'ADD' takes a PKCS #11 initialization string and stores it.
+ * The function 'DEL' takes a 'name= library=' value and deletes the associated
+ * string.
+ * The function 'RELEASE' frees the array returned by 'FIND'
+ */
+#define SECMOD_MODULE_DB_FUNCTION_FIND 0
+#define SECMOD_MODULE_DB_FUNCTION_ADD 1
+#define SECMOD_MODULE_DB_FUNCTION_DEL 2
+#define SECMOD_MODULE_DB_FUNCTION_RELEASE 3
+typedef char **(PR_CALLBACK *SECMODModuleDBFunc)(unsigned long function,
+ char *parameters, void *moduleSpec);
+
+/* softoken slot ID's */
+#define SFTK_MIN_USER_SLOT_ID 4
+#define SFTK_MAX_USER_SLOT_ID 100
+#define SFTK_MIN_FIPS_USER_SLOT_ID 101
+#define SFTK_MAX_FIPS_USER_SLOT_ID 127
+
+/* Module Interface. This is the old NSS private module interface, now exported
+ * as a PKCS #11 v3 interface. It's interface name is
+ * "Vendor NSS Module Interface" */
+typedef char **(*CK_NSS_ModuleDBFunc)(unsigned long function,
+ char *parameters, void *args);
+typedef struct CK_NSS_MODULE_FUNCTIONS {
+ CK_VERSION version;
+ CK_NSS_ModuleDBFunc NSC_ModuleDBFunc;
+} CK_NSS_MODULE_FUNCTIONS;
+
+/* FIPS Indicator Interface. This may move to the normal PKCS #11 table
+ * in the future. For now it's called "Vendor NSS FIPS Interface" */
+typedef CK_RV (*CK_NSS_GetFIPSStatus)(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject,
+ CK_ULONG ulOperationType,
+ CK_ULONG *pulFIPSStatus);
+
+typedef struct CK_NSS_FIPS_FUNCTIONS {
+ CK_VERSION version;
+ CK_NSS_GetFIPSStatus NSC_NSSGetFIPSStatus;
+} CK_NSS_FIPS_FUNCTIONS;
+
+/* KEM interface. This may move to the normal PKCS #11 table in the future. For
+ * now it's called "Vendor NSS KEM Interface" */
+typedef CK_RV (*CK_NSS_Encapsulate)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hPublicKey,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulAttributeCount,
+ CK_OBJECT_HANDLE_PTR phKey,
+ CK_BYTE_PTR pCiphertext,
+ CK_ULONG_PTR pulCiphertextLen);
+
+typedef CK_RV (*CK_NSS_Decapsulate)(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hPrivateKey,
+ CK_BYTE_PTR pCiphertext,
+ CK_ULONG ulCiphertextLen,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulAttributeCount,
+ CK_OBJECT_HANDLE_PTR phKey);
+
+typedef struct CK_NSS_KEM_FUNCTIONS {
+ CK_VERSION version;
+ CK_NSS_Encapsulate C_Encapsulate;
+ CK_NSS_Decapsulate C_Decapsulate;
+} CK_NSS_KEM_FUNCTIONS;
+
+/* There was an inconsistency between the spec and the header file in defining
+ * the CK_GCM_PARAMS structure. The authoritative reference is the header file,
+ * but NSS used the spec when adding it to its own header. In V3 we've
+ * corrected it, but we need to handle the old case for devices that followed
+ * us in using the incorrect specification. */
+typedef struct CK_NSS_GCM_PARAMS {
+ CK_BYTE_PTR pIv;
+ CK_ULONG ulIvLen;
+ CK_BYTE_PTR pAAD;
+ CK_ULONG ulAADLen;
+ CK_ULONG ulTagBits;
+} CK_NSS_GCM_PARAMS;
+
+typedef CK_NSS_GCM_PARAMS CK_PTR CK_NSS_GCM_PARAMS_PTR;
+
+/* deprecated #defines. Drop in future NSS releases */
+#ifdef NSS_PKCS11_2_0_COMPAT
+
+/* defines that were changed between NSS's PKCS #11 and the Oasis headers */
+#define CKF_EC_FP CKF_EC_F_P
+#define CKO_KG_PARAMETERS CKO_DOMAIN_PARAMETERS
+#define CK_INVALID_SESSION CK_INVALID_HANDLE
+#define CKR_KEY_PARAMS_INVALID 0x0000006B
+
+/* use the old wrong CK_GCM_PARAMS if NSS_PCKS11_2_0_COMPAT is defined */
+typedef struct CK_NSS_GCM_PARAMS CK_GCM_PARAMS;
+typedef CK_NSS_GCM_PARAMS CK_PTR CK_GCM_PARAMS_PTR;
+
+/* don't leave old programs in a lurch just yet, give them the old NETSCAPE
+ * synonym if NSS_PKCS11_2_0_COMPAT is defined*/
+#define CKO_NETSCAPE_CRL CKO_NSS_CRL
+#define CKO_NETSCAPE_SMIME CKO_NSS_SMIME
+#define CKO_NETSCAPE_TRUST CKO_NSS_TRUST
+#define CKO_NETSCAPE_BUILTIN_ROOT_LIST CKO_NSS_BUILTIN_ROOT_LIST
+#define CKO_NETSCAPE_NEWSLOT CKO_NSS_NEWSLOT
+#define CKO_NETSCAPE_DELSLOT CKO_NSS_DELSLOT
+#define CKK_NETSCAPE_PKCS8 CKK_NSS_PKCS8
+#define CKA_NETSCAPE_URL CKA_NSS_URL
+#define CKA_NETSCAPE_EMAIL CKA_NSS_EMAIL
+#define CKA_NETSCAPE_SMIME_INFO CKA_NSS_SMIME_INFO
+#define CKA_NETSCAPE_SMIME_TIMESTAMP CKA_NSS_SMIME_TIMESTAMP
+#define CKA_NETSCAPE_PKCS8_SALT CKA_NSS_PKCS8_SALT
+#define CKA_NETSCAPE_PASSWORD_CHECK CKA_NSS_PASSWORD_CHECK
+#define CKA_NETSCAPE_EXPIRES CKA_NSS_EXPIRES
+#define CKA_NETSCAPE_KRL CKA_NSS_KRL
+#define CKA_NETSCAPE_PQG_COUNTER CKA_NSS_PQG_COUNTER
+#define CKA_NETSCAPE_PQG_SEED CKA_NSS_PQG_SEED
+#define CKA_NETSCAPE_PQG_H CKA_NSS_PQG_H
+#define CKA_NETSCAPE_PQG_SEED_BITS CKA_NSS_PQG_SEED_BITS
+#define CKA_NETSCAPE_MODULE_SPEC CKA_NSS_MODULE_SPEC
+#define CKA_NETSCAPE_DB CKA_NSS_DB
+#define CKA_NETSCAPE_TRUST CKA_NSS_TRUST
+#define CKM_NETSCAPE_AES_KEY_WRAP CKM_NSS_AES_KEY_WRAP
+#define CKM_NETSCAPE_AES_KEY_WRAP_PAD CKM_NSS_AES_KEY_WRAP_PAD
+#define CKM_NETSCAPE_PBE_SHA1_DES_CBC CKM_NSS_PBE_SHA1_DES_CBC
+#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC
+#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC
+#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC
+#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 CKM_NSS_PBE_SHA1_40_BIT_RC4
+#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 CKM_NSS_PBE_SHA1_128_BIT_RC4
+#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC
+#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN CKM_NSS_PBE_SHA1_HMAC_KEY_GEN
+#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN CKM_NSS_PBE_MD5_HMAC_KEY_GEN
+#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN CKM_NSS_PBE_MD2_HMAC_KEY_GEN
+#define CKR_NETSCAPE_CERTDB_FAILED CKR_NSS_CERTDB_FAILED
+#define CKR_NETSCAPE_KEYDB_FAILED CKR_NSS_KEYDB_FAILED
+
+#define CKT_NETSCAPE_TRUSTED CKT_NSS_TRUSTED
+#define CKT_NETSCAPE_TRUSTED_DELEGATOR CKT_NSS_TRUSTED_DELEGATOR
+#define CKT_NETSCAPE_UNTRUSTED CKT_NSS_UNTRUSTED
+#define CKT_NETSCAPE_MUST_VERIFY CKT_NSS_MUST_VERIFY
+#define CKT_NETSCAPE_TRUST_UNKNOWN CKT_NSS_TRUST_UNKNOWN
+#define CKT_NETSCAPE_VALID CKT_NSS_VALID
+#define CKT_NETSCAPE_VALID_DELEGATOR CKT_NSS_VALID_DELEGATOR
+#else
+/* use the new CK_GCM_PARAMS if NSS_PKCS11_2_0_COMPAT is not defined */
+typedef struct CK_GCM_PARAMS_V3 CK_GCM_PARAMS;
+typedef CK_GCM_PARAMS_V3 CK_PTR CK_GCM_PARAMS_PTR;
+#endif
+
+#endif /* _PKCS11N_H_ */
diff --git a/security/nss/lib/util/pkcs11p.h b/security/nss/lib/util/pkcs11p.h
new file mode 100644
index 0000000000..1c9201350e
--- /dev/null
+++ b/security/nss/lib/util/pkcs11p.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/. */
+/*
+ * Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document
+ * is granted provided that it is identified as "RSA Security Inc. Public-Key
+ * Cryptography Standards (PKCS)" in all material mentioning or referencing
+ * this document.
+ */
+/* these data types are platform/implementation dependent. */
+/*
+ * Packing was removed from the shipped RSA header files, even
+ * though it's still needed. put in a central file to help merging..
+ */
+
+#if defined(_WIN32) || defined(_WINDOWS)
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wpragma-pack"
+#endif
+#ifdef _MSC_VER
+#pragma warning(disable : 4103)
+#endif
+#pragma pack(push, cryptoki, 1)
+#endif
diff --git a/security/nss/lib/util/pkcs11t.h b/security/nss/lib/util/pkcs11t.h
new file mode 100644
index 0000000000..b4a8b4ab6d
--- /dev/null
+++ b/security/nss/lib/util/pkcs11t.h
@@ -0,0 +1,2591 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+#ifndef _PKCS11T_H_
+#define _PKCS11T_H_ 1
+
+#define CK_TRUE 1
+#define CK_FALSE 0
+
+#include "prtypes.h"
+
+#define CK_PTR *
+#define CK_NULL_PTR 0
+#define CK_CALLBACK_FUNCTION(rtype, func) rtype(PR_CALLBACK *func)
+#define CK_DECLARE_FUNCTION(rtype, func) extern rtype func
+#define CK_DECLARE_FUNCTION_POINTER(rtype, func) rtype(PR_CALLBACK *func)
+
+#ifdef NSS_PCKS11_2_0_COMPAT
+#define prfHashMechanism prfMechanism
+#endif
+
+#define CRYPTOKI_VERSION_MAJOR 3
+#define CRYPTOKI_VERSION_MINOR 0
+#define CRYPTOKI_VERSION_AMENDMENT 0
+
+/* an unsigned 8-bit value */
+typedef unsigned char CK_BYTE;
+
+/* an unsigned 8-bit character */
+typedef CK_BYTE CK_CHAR;
+
+/* an 8-bit UTF-8 character */
+typedef CK_BYTE CK_UTF8CHAR;
+
+/* a BYTE-sized Boolean flag */
+typedef CK_BYTE CK_BBOOL;
+
+/* an unsigned value, at least 32 bits long */
+typedef unsigned long int CK_ULONG;
+
+/* a signed value, the same size as a CK_ULONG */
+/* CK_LONG is new for v2.0 */
+typedef long int CK_LONG;
+
+/* at least 32 bits; each bit is a Boolean flag */
+typedef CK_ULONG CK_FLAGS;
+
+/* some special values for certain CK_ULONG variables */
+#define CK_UNAVAILABLE_INFORMATION (~0UL)
+#define CK_EFFECTIVELY_INFINITE 0
+
+typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+typedef CK_CHAR CK_PTR CK_CHAR_PTR;
+typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
+typedef CK_ULONG CK_PTR CK_ULONG_PTR;
+typedef void CK_PTR CK_VOID_PTR;
+
+/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
+typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
+
+/* The following value is always invalid if used as a session */
+/* handle or object handle */
+#define CK_INVALID_HANDLE 0
+
+/* pack */
+#include "pkcs11p.h"
+
+typedef struct CK_VERSION {
+ CK_BYTE major; /* integer portion of version number */
+ CK_BYTE minor; /* 1/100ths portion of version number */
+} CK_VERSION;
+
+typedef CK_VERSION CK_PTR CK_VERSION_PTR;
+
+typedef struct CK_INFO {
+ /* manufacturerID and libraryDecription have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_VERSION cryptokiVersion; /* PKCS #11 interface ver */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags; /* must be zero */
+
+ /* libraryDescription and libraryVersion are new for v2.0 */
+ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
+ CK_VERSION libraryVersion; /* version of library */
+} CK_INFO;
+
+typedef CK_INFO CK_PTR CK_INFO_PTR;
+
+/* CK_NOTIFICATION enumerates the types of notifications that
+ * PKCS #11 provides to an application */
+/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_NOTIFICATION;
+#define CKN_SURRENDER 0
+
+typedef CK_ULONG CK_SLOT_ID;
+
+typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
+
+/* CK_SLOT_INFO provides information about a slot */
+typedef struct CK_SLOT_INFO {
+ /* slotDescription and manufacturerID have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR slotDescription[64]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags;
+
+ /* hardwareVersion and firmwareVersion are new for v2.0 */
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+} CK_SLOT_INFO;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_TOKEN_PRESENT 0x00000001UL /* a token is there */
+#define CKF_REMOVABLE_DEVICE 0x00000002UL /* removable devices*/
+#define CKF_HW_SLOT 0x00000004UL /* hardware slot */
+
+typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
+
+/* CK_TOKEN_INFO provides information about a token */
+typedef struct CK_TOKEN_INFO {
+ /* label, manufacturerID, and model have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR label[32]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_UTF8CHAR model[16]; /* blank padded */
+ CK_CHAR serialNumber[16]; /* blank padded */
+ CK_FLAGS flags; /* see below */
+
+ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
+ * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
+ * changed from CK_USHORT to CK_ULONG for v2.0 */
+ CK_ULONG ulMaxSessionCount; /* max open sessions */
+ CK_ULONG ulSessionCount; /* sess. now open */
+ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
+ CK_ULONG ulRwSessionCount; /* R/W sess. now open */
+ CK_ULONG ulMaxPinLen; /* in bytes */
+ CK_ULONG ulMinPinLen; /* in bytes */
+ CK_ULONG ulTotalPublicMemory; /* in bytes */
+ CK_ULONG ulFreePublicMemory; /* in bytes */
+ CK_ULONG ulTotalPrivateMemory; /* in bytes */
+ CK_ULONG ulFreePrivateMemory; /* in bytes */
+
+ /* hardwareVersion, firmwareVersion, and time are new for
+ * v2.0 */
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+ CK_CHAR utcTime[16]; /* time */
+} CK_TOKEN_INFO;
+
+/* The flags parameter is defined as follows:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RNG 0x00000001UL /* has random # \
+ * generator */
+#define CKF_WRITE_PROTECTED 0x00000002UL /* token is \
+ * write- \
+ * protected */
+#define CKF_LOGIN_REQUIRED 0x00000004UL /* user must \
+ * login */
+#define CKF_USER_PIN_INITIALIZED 0x00000008UL /* normal user's \
+ * PIN is set */
+
+/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set,
+ * that means that *every* time the state of cryptographic
+ * operations of a session is successfully saved, all keys
+ * needed to continue those operations are stored in the state */
+#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020UL
+
+/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means
+ * that the token has some sort of clock. The time on that
+ * clock is returned in the token info structure */
+#define CKF_CLOCK_ON_TOKEN 0x00000040UL
+
+/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is
+ * set, that means that there is some way for the user to login
+ * without sending a PIN through the PKCS #11 library itself */
+#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100UL
+
+/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true,
+ * that means that a single session with the token can perform
+ * dual simultaneous cryptographic operations (digest and
+ * encrypt; decrypt and digest; sign and encrypt; and decrypt
+ * and sign) */
+#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200UL
+
+/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
+ * token has been initialized using C_InitializeToken or an
+ * equivalent mechanism outside the scope of PKCS #11.
+ * Calling C_InitializeToken when this flag is set will cause
+ * the token to be reinitialized. */
+#define CKF_TOKEN_INITIALIZED 0x00000400UL
+
+/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
+ * true, the token supports secondary authentication for
+ * private key objects. This flag is deprecated in v2.11 and
+ onwards. */
+#define CKF_SECONDARY_AUTHENTICATION 0x00000800UL
+
+/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect user login PIN has been entered at least once
+ * since the last successful authentication. */
+#define CKF_USER_PIN_COUNT_LOW 0x00010000UL
+
+/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect user PIN will it to become locked. */
+#define CKF_USER_PIN_FINAL_TRY 0x00020000UL
+
+/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
+ * user PIN has been locked. User login to the token is not
+ * possible. */
+#define CKF_USER_PIN_LOCKED 0x00040000UL
+
+/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the user PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000UL
+
+/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect SO login PIN has been entered at least once since
+ * the last successful authentication. */
+#define CKF_SO_PIN_COUNT_LOW 0x00100000UL
+
+/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect SO PIN will it to become locked. */
+#define CKF_SO_PIN_FINAL_TRY 0x00200000UL
+
+/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
+ * PIN has been locked. SO login to the token is not possible.
+ */
+#define CKF_SO_PIN_LOCKED 0x00400000UL
+
+/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the SO PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000UL
+
+#define CKF_ERROR_STATE 0x01000000UL
+
+typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
+
+/* CK_SESSION_HANDLE is a PKCS #11-assigned value that
+ * identifies a session */
+typedef CK_ULONG CK_SESSION_HANDLE;
+
+typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
+
+/* CK_USER_TYPE enumerates the types of PKCS #11 users */
+/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_USER_TYPE;
+/* Security Officer */
+#define CKU_SO 0
+/* Normal user */
+#define CKU_USER 1
+/* Context specific (added in v2.20) */
+#define CKU_CONTEXT_SPECIFIC 2
+
+/* CK_STATE enumerates the session states */
+/* CK_STATE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_STATE;
+#define CKS_RO_PUBLIC_SESSION 0
+#define CKS_RO_USER_FUNCTIONS 1
+#define CKS_RW_PUBLIC_SESSION 2
+#define CKS_RW_USER_FUNCTIONS 3
+#define CKS_RW_SO_FUNCTIONS 4
+
+/* CK_SESSION_INFO provides information about a session */
+typedef struct CK_SESSION_INFO {
+ CK_SLOT_ID slotID;
+ CK_STATE state;
+ CK_FLAGS flags; /* see below */
+
+ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulDeviceError; /* device-dependent error code */
+} CK_SESSION_INFO;
+
+/* The flags are defined in the following table:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RW_SESSION 0x00000002UL /* session is r/w */
+#define CKF_SERIAL_SESSION 0x00000004UL /* no parallel */
+
+typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
+
+/* CK_OBJECT_HANDLE is a token-specific identifier for an
+ * object */
+typedef CK_ULONG CK_OBJECT_HANDLE;
+
+typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
+
+/* CK_OBJECT_CLASS is a value that identifies the classes (or
+ * types) of objects that PKCS #11 recognizes. It is defined
+ * as follows: */
+/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_OBJECT_CLASS;
+
+/* The following classes of objects are defined: */
+/* CKO_HW_FEATURE is new for v2.10 */
+/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
+/* CKO_MECHANISM is new for v2.20 */
+/* CKO_PROFILE is new for v3.00 */
+#define CKO_DATA 0x00000000UL
+#define CKO_CERTIFICATE 0x00000001UL
+#define CKO_PUBLIC_KEY 0x00000002UL
+#define CKO_PRIVATE_KEY 0x00000003UL
+#define CKO_SECRET_KEY 0x00000004UL
+#define CKO_HW_FEATURE 0x00000005UL
+#define CKO_DOMAIN_PARAMETERS 0x00000006UL
+#define CKO_MECHANISM 0x00000007UL
+#define CKO_PROFILE 0x00000009UL
+#define CKO_VENDOR_DEFINED 0x80000000UL
+
+typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
+
+/* CK_PROFILE_ID is new for v3.00. CK_PROFILE_ID is a value that
+ * identifies the profile that the token supports. */
+typedef CK_ULONG CK_PROFILE_ID;
+
+/* Profile ID's */
+#define CKP_INVALID_ID 0x00000000UL
+#define CKP_BASELINE_PROVIDER 0x00000001UL
+#define CKP_EXTENDED_PROVIDER 0x00000002UL
+#define CKP_AUTHENTICATION_TOKEN 0x00000003UL
+#define CKP_PUBLIC_CERTIFICATES_TOKEN 0x00000004UL
+#define CKP_VENDOR_DEFINED 0x80000000UL
+
+/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
+ * value that identifies the hardware feature type of an object
+ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
+typedef CK_ULONG CK_HW_FEATURE_TYPE;
+
+/* The following hardware feature types are defined */
+/* CKH_USER_INTERFACE is new for v2.20 */
+#define CKH_MONOTONIC_COUNTER 0x00000001UL
+#define CKH_CLOCK 0x00000002UL
+#define CKH_USER_INTERFACE 0x00000003UL
+#define CKH_VENDOR_DEFINED 0x80000000UL
+
+/* CK_KEY_TYPE is a value that identifies a key type */
+/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG CK_KEY_TYPE;
+
+/* the following key types are defined: */
+#define CKK_RSA 0x00000000UL
+#define CKK_DSA 0x00000001UL
+#define CKK_DH 0x00000002UL
+
+/* CKK_ECDSA and CKK_KEA are new for v2.0 */
+/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
+#define CKK_ECDSA 0x00000003UL
+#define CKK_EC 0x00000003UL
+#define CKK_X9_42_DH 0x00000004UL
+#define CKK_KEA 0x00000005UL
+
+#define CKK_GENERIC_SECRET 0x00000010UL
+#define CKK_RC2 0x00000011UL
+#define CKK_RC4 0x00000012UL
+#define CKK_DES 0x00000013UL
+#define CKK_DES2 0x00000014UL
+#define CKK_DES3 0x00000015UL
+
+/* all these key types are new for v2.0 */
+#define CKK_CAST 0x00000016UL
+#define CKK_CAST3 0x00000017UL
+/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
+#define CKK_CAST5 0x00000018UL
+#define CKK_CAST128 0x00000018UL
+#define CKK_RC5 0x00000019UL
+#define CKK_IDEA 0x0000001AUL
+#define CKK_SKIPJACK 0x0000001BUL
+#define CKK_BATON 0x0000001CUL
+#define CKK_JUNIPER 0x0000001DUL
+#define CKK_CDMF 0x0000001EUL
+#define CKK_AES 0x0000001FUL
+
+/* BlowFish and TwoFish are new for v2.20 */
+#define CKK_BLOWFISH 0x00000020UL
+#define CKK_TWOFISH 0x00000021UL
+
+/* Camellia is proposed for v2.20 Amendment 3 */
+#define CKK_CAMELLIA 0x00000025UL
+
+#define CKK_SEED 0x0000002FUL /* was 2A */
+
+/* added in v2.30 */
+#define CKK_ARIA 0x00000026UL
+
+/* added in 2.40 */
+#define CKK_MD5_HMAC 0x00000027UL
+#define CKK_SHA_1_HMAC 0x00000028UL
+#define CKK_RIPEMD128_HMAC 0x00000029UL
+#define CKK_RIPEMD160_HMAC 0x0000002AUL
+#define CKK_SHA256_HMAC 0x0000002BUL
+#define CKK_SHA384_HMAC 0x0000002CUL
+#define CKK_SHA512_HMAC 0x0000002DUL
+#define CKK_SHA224_HMAC 0x0000002EUL
+#define CKK_GOSTR3410 0x00000030UL
+#define CKK_GOSTR3411 0x00000031UL
+#define CKK_GOST28147 0x00000032UL
+#define CKK_CHACHA20 0x00000033UL
+#define CKK_POLY1305 0x00000034UL
+#define CKK_AES_XTS 0x00000035UL
+#define CKK_SHA3_224_HMAC 0x00000036UL
+#define CKK_SHA3_256_HMAC 0x00000037UL
+#define CKK_SHA3_384_HMAC 0x00000038UL
+#define CKK_SHA3_512_HMAC 0x00000039UL
+
+/* added in 3.0 */
+#define CKK_BLAKE2B_160_HMAC 0x0000003aUL
+#define CKK_BLAKE2B_256_HMAC 0x0000003bUL
+#define CKK_BLAKE2B_384_HMAC 0x0000003cUL
+#define CKK_BLAKE2B_512_HMAC 0x0000003dUL
+#define CKK_SALSA20 0x0000003eUL
+#define CKK_X2RATCHET 0x0000003fUL
+#define CKK_EC_EDWARDS 0x00000040UL
+#define CKK_EC_MONTGOMERY 0x00000041UL
+#define CKK_HKDF 0x00000042UL
+#define CKK_SHA512_224_HMAC 0x00000043UL
+#define CKK_SHA512_256_HMAC 0x00000044UL
+#define CKK_SHA512_T_HMAC 0x00000045UL
+
+#define CKK_VENDOR_DEFINED 0x80000000UL
+
+/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
+ * type */
+/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_CERTIFICATE_TYPE;
+
+/* The following certificate types are defined: */
+/* CKC_X_509_ATTR_CERT is new for v2.10 */
+/* CKC_WTLS is new for v2.20 */
+#define CKC_X_509 0x00000000UL
+#define CKC_X_509_ATTR_CERT 0x00000001UL
+#define CKC_WTLS 0x00000002UL
+#define CKC_VENDOR_DEFINED 0x80000000UL
+
+/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
+ * type */
+/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_ATTRIBUTE_TYPE;
+
+/* values for CKA_CERTIFICATE_CATEGORY v2.20 */
+typedef CK_ULONG CK_CERTIFICATE_CATEGORY;
+#define CK_CERTIFICATE_CATEGORY_UNSPECIFIED 0UL
+#define CK_CERTIFICATE_CATEGORY_TOKEN_USER 1UL
+#define CK_CERTIFICATE_CATEGORY_AUTHORITY 2UL
+#define CK_CERTIFICATE_CATEGORY_OTHER_ENTITY 3UL
+
+/* values for CKA_JAVA_MIDP_SECURITY_DOMAIN v2.20 */
+typedef CK_ULONG CK_JAVA_MIDP_SECURITY_DOMAIN;
+#define CK_SECURITY_DOMAIN_UNSPECIFIED 0UL
+#define CK_SECURITY_DOMAIN_MANUFACTURER 1UL
+#define CK_SECURITY_DOMAIN_OPERATOR 2UL
+#define CK_SECURITY_DOMAIN_THIRD_PARTY 3UL
+
+/* values for CKA_OTP_FORMAT */
+#define CK_OTP_FORMAT_DECIMAL 0UL
+#define CK_OTP_FORMAT_HEXADECIMAL 1UL
+#define CK_OTP_FORMAT_ALPHANUMERIC 2UL
+#define CK_OTP_FORMAT_BINARY 3UL
+
+/* values for CKA_OTP_CHALLENGE_REQUIREMENT, CKA_OTP_TIME_REQUIREMENT,
+ * CKA_OTP_COUNTER_REQUIREMENT, CKA_OTP_PIN_REQUIREMENT */
+#define CK_OTP_PARAM_IGNORED 0UL
+#define CK_OTP_PARAM_OPTIONAL 1UL
+#define CK_OTP_PARAM_MANDATORY 2UL
+
+/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
+ consists of an array of values. */
+#define CKF_ARRAY_ATTRIBUTE 0x40000000UL
+
+/* The following attribute types are defined: */
+#define CKA_CLASS 0x00000000UL
+#define CKA_TOKEN 0x00000001UL
+#define CKA_PRIVATE 0x00000002UL
+#define CKA_LABEL 0x00000003UL
+#define CKA_APPLICATION 0x00000010UL
+#define CKA_VALUE 0x00000011UL
+
+/* CKA_OBJECT_ID is new for v2.10 */
+#define CKA_OBJECT_ID 0x00000012UL
+
+#define CKA_CERTIFICATE_TYPE 0x00000080UL
+#define CKA_ISSUER 0x00000081UL
+#define CKA_SERIAL_NUMBER 0x00000082UL
+
+/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
+ * for v2.10 */
+#define CKA_AC_ISSUER 0x00000083UL
+#define CKA_OWNER 0x00000084UL
+#define CKA_ATTR_TYPES 0x00000085UL
+
+/* CKA_TRUSTED is new for v2.11 */
+#define CKA_TRUSTED 0x00000086UL
+
+/* CKA_CERTIFICATE_CATEGORY ...
+ * CKA_CHECK_VALUE are new for v2.20 */
+#define CKA_CERTIFICATE_CATEGORY 0x00000087UL
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088UL
+#define CKA_URL 0x00000089UL
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008AUL
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008BUL
+#define CKA_CHECK_VALUE 0x00000090UL
+
+#define CKA_KEY_TYPE 0x00000100UL
+#define CKA_SUBJECT 0x00000101UL
+#define CKA_ID 0x00000102UL
+#define CKA_SENSITIVE 0x00000103UL
+#define CKA_ENCRYPT 0x00000104UL
+#define CKA_DECRYPT 0x00000105UL
+#define CKA_WRAP 0x00000106UL
+#define CKA_UNWRAP 0x00000107UL
+#define CKA_SIGN 0x00000108UL
+#define CKA_SIGN_RECOVER 0x00000109UL
+#define CKA_VERIFY 0x0000010AUL
+#define CKA_VERIFY_RECOVER 0x0000010BUL
+#define CKA_DERIVE 0x0000010CUL
+#define CKA_START_DATE 0x00000110UL
+#define CKA_END_DATE 0x00000111UL
+#define CKA_MODULUS 0x00000120UL
+#define CKA_MODULUS_BITS 0x00000121UL
+#define CKA_PUBLIC_EXPONENT 0x00000122UL
+#define CKA_PRIVATE_EXPONENT 0x00000123UL
+#define CKA_PRIME_1 0x00000124UL
+#define CKA_PRIME_2 0x00000125UL
+#define CKA_EXPONENT_1 0x00000126UL
+#define CKA_EXPONENT_2 0x00000127UL
+#define CKA_COEFFICIENT 0x00000128UL
+/* CKA_PUBLIC_KEY_INFO is new for v2.40 */
+#define CKA_PUBLIC_KEY_INFO 0x00000129UL
+#define CKA_PRIME 0x00000130UL
+#define CKA_SUBPRIME 0x00000131UL
+#define CKA_BASE 0x00000132UL
+
+/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
+#define CKA_PRIME_BITS 0x00000133UL
+#define CKA_SUBPRIME_BITS 0x00000134UL
+#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS
+/* (To retain backwards-compatibility) */
+
+#define CKA_VALUE_BITS 0x00000160UL
+#define CKA_VALUE_LEN 0x00000161UL
+
+/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
+ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
+ * and CKA_EC_POINT are new for v2.0 */
+#define CKA_EXTRACTABLE 0x00000162UL
+#define CKA_LOCAL 0x00000163UL
+#define CKA_NEVER_EXTRACTABLE 0x00000164UL
+#define CKA_ALWAYS_SENSITIVE 0x00000165UL
+
+/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
+#define CKA_KEY_GEN_MECHANISM 0x00000166UL
+
+#define CKA_MODIFIABLE 0x00000170UL
+
+/* New for 2.40 */
+#define CKA_COPYABLE 0x00000171UL
+#define CKA_DESTROYABLE 0x00000172UL
+
+/* CKA_ECDSA_PARAMS is deprecated in v2.11,
+ * CKA_EC_PARAMS is preferred. */
+#define CKA_ECDSA_PARAMS 0x00000180UL
+#define CKA_EC_PARAMS 0x00000180UL
+
+#define CKA_EC_POINT 0x00000181UL
+
+/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
+ * are new for v2.10. Deprecated in v2.11 and onwards. */
+#define CKA_SECONDARY_AUTH 0x00000200UL
+#define CKA_AUTH_PIN_FLAGS 0x00000201UL
+
+/* CKA_ALWAYS_AUTHENTICATE ...
+ * CKA_UNWRAP_TEMPLATE are new for v2.20 */
+#define CKA_ALWAYS_AUTHENTICATE 0x00000202UL
+
+#define CKA_WRAP_WITH_TRUSTED 0x00000210UL
+#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x00000211UL)
+#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x00000212UL)
+
+/* new for 2.40 */
+#define CKA_DERIVE_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x00000213UL)
+#define CKA_OTP_FORMAT 0x00000220UL
+#define CKA_OTP_LENGTH 0x00000221UL
+#define CKA_OTP_TIME_INTERVAL 0x00000222UL
+#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223UL
+#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224UL
+#define CKA_OTP_TIME_REQUIREMENT 0x00000225UL
+#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226UL
+#define CKA_OTP_PIN_REQUIREMENT 0x00000227UL
+#define CKA_OTP_COUNTER 0x0000022EUL
+#define CKA_OTP_TIME 0x0000022FUL
+#define CKA_OTP_USER_IDENTIFIER 0x0000022AUL
+#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022BUL
+#define CKA_OTP_SERVICE_LOGO 0x0000022CUL
+#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022DUL
+#define CKA_GOSTR3410_PARAMS 0x00000250UL
+#define CKA_GOSTR3411_PARAMS 0x00000251UL
+#define CKA_GOST28147_PARAMS 0x00000252UL
+
+/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
+ * are new for v2.10 */
+#define CKA_HW_FEATURE_TYPE 0x00000300UL
+#define CKA_RESET_ON_INIT 0x00000301UL
+#define CKA_HAS_RESET 0x00000302UL
+
+/* The following attributes are new for v2.20 */
+#define CKA_PIXEL_X 0x00000400UL
+#define CKA_PIXEL_Y 0x00000401UL
+#define CKA_RESOLUTION 0x00000402UL
+#define CKA_CHAR_ROWS 0x00000403UL
+#define CKA_CHAR_COLUMNS 0x00000404UL
+#define CKA_COLOR 0x00000405UL
+#define CKA_BITS_PER_PIXEL 0x00000406UL
+#define CKA_CHAR_SETS 0x00000480UL
+#define CKA_ENCODING_METHODS 0x00000481UL
+#define CKA_MIME_TYPES 0x00000482UL
+#define CKA_MECHANISM_TYPE 0x00000500UL
+#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501UL
+#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502UL
+#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503UL
+#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x00000600UL)
+
+/* new for v3.0 */
+#define CKA_PROFILE_ID 0x00000601UL
+#define CKA_X2RATCHET_BAG 0x00000602UL
+#define CKA_X2RATCHET_BAGSIZE 0x00000603UL
+#define CKA_X2RATCHET_BOBS1STMSG 0x00000604UL
+#define CKA_X2RATCHET_CKR 0x00000605UL
+#define CKA_X2RATCHET_CKS 0x00000606UL
+#define CKA_X2RATCHET_DHP 0x00000607UL
+#define CKA_X2RATCHET_DHR 0x00000608UL
+#define CKA_X2RATCHET_DHS 0x00000609UL
+#define CKA_X2RATCHET_HKR 0x0000060aUL
+#define CKA_X2RATCHET_HKS 0x0000060bUL
+#define CKA_X2RATCHET_ISALICE 0x0000060cUL
+#define CKA_X2RATCHET_NHKR 0x0000060dUL
+#define CKA_X2RATCHET_NHKS 0x0000060eUL
+#define CKA_X2RATCHET_NR 0x0000060fUL
+#define CKA_X2RATCHET_NS 0x00000610UL
+#define CKA_X2RATCHET_PNS 0x00000611UL
+#define CKA_X2RATCHET_RK 0x00000612UL
+
+#define CKA_VENDOR_DEFINED 0x80000000UL
+
+/* CK_ATTRIBUTE is a structure that includes the type, length
+ * and value of an attribute */
+typedef struct CK_ATTRIBUTE {
+ CK_ATTRIBUTE_TYPE type;
+ CK_VOID_PTR pValue;
+
+ /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
+ CK_ULONG ulValueLen; /* in bytes */
+} CK_ATTRIBUTE;
+
+typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
+
+/* CK_DATE is a structure that defines a date */
+typedef struct CK_DATE {
+ CK_CHAR year[4]; /* the year ("1900" - "9999") */
+ CK_CHAR month[2]; /* the month ("01" - "12") */
+ CK_CHAR day[2]; /* the day ("01" - "31") */
+} CK_DATE;
+
+/* CK_MECHANISM_TYPE is a value that identifies a mechanism
+ * type */
+/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_MECHANISM_TYPE;
+
+/* the following mechanism types are defined: */
+#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000UL
+#define CKM_RSA_PKCS 0x00000001UL
+#define CKM_RSA_9796 0x00000002UL
+#define CKM_RSA_X_509 0x00000003UL
+
+/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
+ * are new for v2.0. They are mechanisms which hash and sign */
+#define CKM_MD2_RSA_PKCS 0x00000004UL
+#define CKM_MD5_RSA_PKCS 0x00000005UL
+#define CKM_SHA1_RSA_PKCS 0x00000006UL
+
+/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
+ * CKM_RSA_PKCS_OAEP are new for v2.10 */
+#define CKM_RIPEMD128_RSA_PKCS 0x00000007UL
+#define CKM_RIPEMD160_RSA_PKCS 0x00000008UL
+#define CKM_RSA_PKCS_OAEP 0x00000009UL
+
+/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
+ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
+#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000AUL
+#define CKM_RSA_X9_31 0x0000000BUL
+#define CKM_SHA1_RSA_X9_31 0x0000000CUL
+#define CKM_RSA_PKCS_PSS 0x0000000DUL
+#define CKM_SHA1_RSA_PKCS_PSS 0x0000000EUL
+
+#define CKM_DSA_KEY_PAIR_GEN 0x00000010UL
+#define CKM_DSA 0x00000011UL
+#define CKM_DSA_SHA1 0x00000012UL
+
+/* new for v2.40 */
+#define CKM_DSA_SHA224 0x00000013UL
+#define CKM_DSA_SHA256 0x00000014UL
+#define CKM_DSA_SHA384 0x00000015UL
+#define CKM_DSA_SHA512 0x00000016UL
+#define CKM_DSA_SHA3_224 0x00000018UL
+#define CKM_DSA_SHA3_256 0x00000019UL
+#define CKM_DSA_SHA3_384 0x0000001AUL
+#define CKM_DSA_SHA3_512 0x0000001BUL
+
+#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020UL
+#define CKM_DH_PKCS_DERIVE 0x00000021UL
+
+/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
+ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
+ * v2.11 */
+#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030UL
+#define CKM_X9_42_DH_DERIVE 0x00000031UL
+#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032UL
+#define CKM_X9_42_MQV_DERIVE 0x00000033UL
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256_RSA_PKCS 0x00000040UL
+#define CKM_SHA384_RSA_PKCS 0x00000041UL
+#define CKM_SHA512_RSA_PKCS 0x00000042UL
+#define CKM_SHA256_RSA_PKCS_PSS 0x00000043UL
+#define CKM_SHA384_RSA_PKCS_PSS 0x00000044UL
+#define CKM_SHA512_RSA_PKCS_PSS 0x00000045UL
+
+/* CKM_SHA224 new for v2.20 amendment 3 */
+#define CKM_SHA224_RSA_PKCS 0x00000046UL
+#define CKM_SHA224_RSA_PKCS_PSS 0x00000047UL
+
+/* new for v2.40 */
+#define CKM_SHA512_224 0x00000048UL
+#define CKM_SHA512_224_HMAC 0x00000049UL
+#define CKM_SHA512_224_HMAC_GENERAL 0x0000004AUL
+#define CKM_SHA512_224_KEY_DERIVATION 0x0000004BUL
+#define CKM_SHA512_256 0x0000004CUL
+#define CKM_SHA512_256_HMAC 0x0000004DUL
+#define CKM_SHA512_256_HMAC_GENERAL 0x0000004EUL
+#define CKM_SHA512_256_KEY_DERIVATION 0x0000004FUL
+#define CKM_SHA512_T 0x00000050UL
+#define CKM_SHA512_T_HMAC 0x00000051UL
+#define CKM_SHA512_T_HMAC_GENERAL 0x00000052UL
+#define CKM_SHA512_T_KEY_DERIVATION 0x00000053UL
+#define CKM_SHA3_256_RSA_PKCS 0x00000060UL
+#define CKM_SHA3_384_RSA_PKCS 0x00000061UL
+#define CKM_SHA3_512_RSA_PKCS 0x00000062UL
+#define CKM_SHA3_256_RSA_PKCS_PSS 0x00000063UL
+#define CKM_SHA3_384_RSA_PKCS_PSS 0x00000064UL
+#define CKM_SHA3_512_RSA_PKCS_PSS 0x00000065UL
+#define CKM_SHA3_224_RSA_PKCS 0x00000066UL
+#define CKM_SHA3_224_RSA_PKCS_PSS 0x00000067UL
+
+#define CKM_RC2_KEY_GEN 0x00000100UL
+#define CKM_RC2_ECB 0x00000101UL
+#define CKM_RC2_CBC 0x00000102UL
+#define CKM_RC2_MAC 0x00000103UL
+
+/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
+#define CKM_RC2_MAC_GENERAL 0x00000104UL
+#define CKM_RC2_CBC_PAD 0x00000105UL
+
+#define CKM_RC4_KEY_GEN 0x00000110UL
+#define CKM_RC4 0x00000111UL
+#define CKM_DES_KEY_GEN 0x00000120UL
+#define CKM_DES_ECB 0x00000121UL
+#define CKM_DES_CBC 0x00000122UL
+#define CKM_DES_MAC 0x00000123UL
+
+/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
+#define CKM_DES_MAC_GENERAL 0x00000124UL
+#define CKM_DES_CBC_PAD 0x00000125UL
+
+#define CKM_DES2_KEY_GEN 0x00000130UL
+#define CKM_DES3_KEY_GEN 0x00000131UL
+#define CKM_DES3_ECB 0x00000132UL
+#define CKM_DES3_CBC 0x00000133UL
+#define CKM_DES3_MAC 0x00000134UL
+
+/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
+ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
+ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
+#define CKM_DES3_MAC_GENERAL 0x00000135UL
+#define CKM_DES3_CBC_PAD 0x00000136UL
+#define CKM_CDMF_KEY_GEN 0x00000140UL
+#define CKM_CDMF_ECB 0x00000141UL
+#define CKM_CDMF_CBC 0x00000142UL
+#define CKM_CDMF_MAC 0x00000143UL
+#define CKM_CDMF_MAC_GENERAL 0x00000144UL
+#define CKM_CDMF_CBC_PAD 0x00000145UL
+
+/* the following four DES mechanisms are new for v2.20 */
+#define CKM_DES_OFB64 0x00000150UL
+#define CKM_DES_OFB8 0x00000151UL
+#define CKM_DES_CFB64 0x00000152UL
+#define CKM_DES_CFB8 0x00000153UL
+
+#define CKM_MD2 0x00000200UL
+
+/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD2_HMAC 0x00000201UL
+#define CKM_MD2_HMAC_GENERAL 0x00000202UL
+
+#define CKM_MD5 0x00000210UL
+
+/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD5_HMAC 0x00000211UL
+#define CKM_MD5_HMAC_GENERAL 0x00000212UL
+
+#define CKM_SHA_1 0x00000220UL
+
+/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
+#define CKM_SHA_1_HMAC 0x00000221UL
+#define CKM_SHA_1_HMAC_GENERAL 0x00000222UL
+
+/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
+ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
+ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
+#define CKM_RIPEMD128 0x00000230UL
+#define CKM_RIPEMD128_HMAC 0x00000231UL
+#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232UL
+#define CKM_RIPEMD160 0x00000240UL
+#define CKM_RIPEMD160_HMAC 0x00000241UL
+#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242UL
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256 0x00000250UL
+#define CKM_SHA256_HMAC 0x00000251UL
+#define CKM_SHA256_HMAC_GENERAL 0x00000252UL
+#define CKM_SHA384 0x00000260UL
+#define CKM_SHA384_HMAC 0x00000261UL
+#define CKM_SHA384_HMAC_GENERAL 0x00000262UL
+#define CKM_SHA512 0x00000270UL
+#define CKM_SHA512_HMAC 0x00000271UL
+#define CKM_SHA512_HMAC_GENERAL 0x00000272UL
+
+/* CKM_SHA224 new for v2.20 amendment 3 */
+#define CKM_SHA224 0x00000255UL
+#define CKM_SHA224_HMAC 0x00000256UL
+#define CKM_SHA224_HMAC_GENERAL 0x00000257UL
+
+/* new for v2.40 */
+#define CKM_SECURID_KEY_GEN 0x00000280UL
+#define CKM_SECURID 0x00000282UL
+#define CKM_HOTP_KEY_GEN 0x00000290UL
+#define CKM_HOTP 0x00000291UL
+#define CKM_ACTI 0x000002A0UL
+#define CKM_ACTI_KEY_GEN 0x000002A1UL
+#define CKM_SHA3_256 0x000002B0UL
+#define CKM_SHA3_256_HMAC 0x000002B1UL
+#define CKM_SHA3_256_HMAC_GENERAL 0x000002B2UL
+#define CKM_SHA3_256_KEY_GEN 0x000002B3UL
+#define CKM_SHA3_224 0x000002B5UL
+#define CKM_SHA3_224_HMAC 0x000002B6UL
+#define CKM_SHA3_224_HMAC_GENERAL 0x000002B7UL
+#define CKM_SHA3_224_KEY_GEN 0x000002B8UL
+#define CKM_SHA3_384 0x000002C0UL
+#define CKM_SHA3_384_HMAC 0x000002C1UL
+#define CKM_SHA3_384_HMAC_GENERAL 0x000002C2UL
+#define CKM_SHA3_384_KEY_GEN 0x000002C3UL
+#define CKM_SHA3_512 0x000002D0UL
+#define CKM_SHA3_512_HMAC 0x000002D1UL
+#define CKM_SHA3_512_HMAC_GENERAL 0x000002D2UL
+#define CKM_SHA3_512_KEY_GEN 0x000002D3UL
+
+/* All of the following mechanisms are new for v2.0 */
+/* Note that CAST128 and CAST5 are the same algorithm */
+#define CKM_CAST_KEY_GEN 0x00000300UL
+#define CKM_CAST_ECB 0x00000301UL
+#define CKM_CAST_CBC 0x00000302UL
+#define CKM_CAST_MAC 0x00000303UL
+#define CKM_CAST_MAC_GENERAL 0x00000304UL
+#define CKM_CAST_CBC_PAD 0x00000305UL
+#define CKM_CAST3_KEY_GEN 0x00000310UL
+#define CKM_CAST3_ECB 0x00000311UL
+#define CKM_CAST3_CBC 0x00000312UL
+#define CKM_CAST3_MAC 0x00000313UL
+#define CKM_CAST3_MAC_GENERAL 0x00000314UL
+#define CKM_CAST3_CBC_PAD 0x00000315UL
+#define CKM_CAST5_KEY_GEN 0x00000320UL
+#define CKM_CAST128_KEY_GEN 0x00000320UL
+#define CKM_CAST5_ECB 0x00000321UL
+#define CKM_CAST128_ECB 0x00000321UL
+#define CKM_CAST5_CBC 0x00000322UL
+#define CKM_CAST128_CBC 0x00000322UL
+#define CKM_CAST5_MAC 0x00000323UL
+#define CKM_CAST128_MAC 0x00000323UL
+#define CKM_CAST5_MAC_GENERAL 0x00000324UL
+#define CKM_CAST128_MAC_GENERAL 0x00000324UL
+#define CKM_CAST5_CBC_PAD 0x00000325UL
+#define CKM_CAST128_CBC_PAD 0x00000325UL
+#define CKM_RC5_KEY_GEN 0x00000330UL
+#define CKM_RC5_ECB 0x00000331UL
+#define CKM_RC5_CBC 0x00000332UL
+#define CKM_RC5_MAC 0x00000333UL
+#define CKM_RC5_MAC_GENERAL 0x00000334UL
+#define CKM_RC5_CBC_PAD 0x00000335UL
+#define CKM_IDEA_KEY_GEN 0x00000340UL
+#define CKM_IDEA_ECB 0x00000341UL
+#define CKM_IDEA_CBC 0x00000342UL
+#define CKM_IDEA_MAC 0x00000343UL
+#define CKM_IDEA_MAC_GENERAL 0x00000344UL
+#define CKM_IDEA_CBC_PAD 0x00000345UL
+#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350UL
+#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360UL
+#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362UL
+#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363UL
+#define CKM_XOR_BASE_AND_DATA 0x00000364UL
+#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365UL
+#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370UL
+#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371UL
+#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372UL
+
+/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
+ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
+ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373UL
+#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374UL
+#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375UL
+#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376UL
+#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377UL
+
+/* CKM_TLS_PRF is new for v2.20 */
+#define CKM_TLS_PRF 0x00000378UL
+
+#define CKM_SSL3_MD5_MAC 0x00000380UL
+#define CKM_SSL3_SHA1_MAC 0x00000381UL
+#define CKM_MD5_KEY_DERIVATION 0x00000390UL
+#define CKM_MD2_KEY_DERIVATION 0x00000391UL
+#define CKM_SHA1_KEY_DERIVATION 0x00000392UL
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256_KEY_DERIVATION 0x00000393UL
+#define CKM_SHA384_KEY_DERIVATION 0x00000394UL
+#define CKM_SHA512_KEY_DERIVATION 0x00000395UL
+
+/* CKM_SHA224 new for v2.20 amendment 3 */
+#define CKM_SHA224_KEY_DERIVATION 0x00000396UL
+
+/* new for v2.40 */
+#define CKM_SHA3_256_KEY_DERIVATION 0x00000397UL
+#define CKM_SHA3_224_KEY_DERIVATION 0x00000398UL
+#define CKM_SHA3_384_KEY_DERIVATION 0x00000399UL
+#define CKM_SHA3_512_KEY_DERIVATION 0x0000039AUL
+#define CKM_SHAKE_128_KEY_DERIVATION 0x0000039BUL
+#define CKM_SHAKE_256_KEY_DERIVATION 0x0000039CUL
+
+#define CKM_PBE_MD2_DES_CBC 0x000003A0UL
+#define CKM_PBE_MD5_DES_CBC 0x000003A1UL
+#define CKM_PBE_MD5_CAST_CBC 0x000003A2UL
+#define CKM_PBE_MD5_CAST3_CBC 0x000003A3UL
+#define CKM_PBE_MD5_CAST5_CBC 0x000003A4UL
+#define CKM_PBE_MD5_CAST128_CBC 0x000003A4UL
+#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5UL
+#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5UL
+#define CKM_PBE_SHA1_RC4_128 0x000003A6UL
+#define CKM_PBE_SHA1_RC4_40 0x000003A7UL
+#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8UL
+#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9UL
+#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AAUL
+#define CKM_PBE_SHA1_RC2_40_CBC 0x000003ABUL
+
+/* CKM_PKCS5_PBKD2 is new for v2.10 */
+#define CKM_PKCS5_PBKD2 0x000003B0UL
+
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0UL
+
+/* WTLS mechanisms are new for v2.20 */
+#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0UL
+#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1UL
+#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2UL
+#define CKM_WTLS_PRF 0x000003D3UL
+#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4UL
+#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5UL
+
+/* TLS 1.2 mechanisms are new for v2.40 */
+#define CKM_TLS12_MASTER_KEY_DERIVE 0x000003E0UL
+#define CKM_TLS12_KEY_AND_MAC_DERIVE 0x000003E1UL
+#define CKM_TLS12_MASTER_KEY_DERIVE_DH 0x000003E2UL
+#define CKM_TLS12_KEY_SAFE_DERIVE 0x000003E3UL
+#define CKM_TLS12_MAC 0x000003D8UL
+#define CKM_TLS12_KDF 0x000003D9UL
+#define CKM_TLS_MAC 0x000003E4UL
+#define CKM_TLS_KDF 0x000003E5UL
+
+#define CKM_KEY_WRAP_LYNKS 0x00000400UL
+#define CKM_KEY_WRAP_SET_OAEP 0x00000401UL
+
+/* CKM_CMS_SIG is new for v2.20 */
+#define CKM_CMS_SIG 0x00000500UL
+
+/* new for 2.40 */
+#define CKM_KIP_DERIVE 0x00000510UL
+#define CKM_KIP_WRAP 0x00000511UL
+#define CKM_KIP_MAC 0x00000512UL
+
+/* Fortezza mechanisms */
+#define CKM_SKIPJACK_KEY_GEN 0x00001000UL
+#define CKM_SKIPJACK_ECB64 0x00001001UL
+#define CKM_SKIPJACK_CBC64 0x00001002UL
+#define CKM_SKIPJACK_OFB64 0x00001003UL
+#define CKM_SKIPJACK_CFB64 0x00001004UL
+#define CKM_SKIPJACK_CFB32 0x00001005UL
+#define CKM_SKIPJACK_CFB16 0x00001006UL
+#define CKM_SKIPJACK_CFB8 0x00001007UL
+#define CKM_SKIPJACK_WRAP 0x00001008UL
+#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009UL
+#define CKM_SKIPJACK_RELAYX 0x0000100aUL
+#define CKM_KEA_KEY_PAIR_GEN 0x00001010UL
+#define CKM_KEA_KEY_DERIVE 0x00001011UL
+#define CKM_FORTEZZA_TIMESTAMP 0x00001020UL
+#define CKM_BATON_KEY_GEN 0x00001030UL
+#define CKM_BATON_ECB128 0x00001031UL
+#define CKM_BATON_ECB96 0x00001032UL
+#define CKM_BATON_CBC128 0x00001033UL
+#define CKM_BATON_COUNTER 0x00001034UL
+#define CKM_BATON_SHUFFLE 0x00001035UL
+#define CKM_BATON_WRAP 0x00001036UL
+
+/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
+ * CKM_EC_KEY_PAIR_GEN is preferred */
+#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040UL
+#define CKM_EC_KEY_PAIR_GEN 0x00001040UL
+
+#define CKM_ECDSA 0x00001041UL
+#define CKM_ECDSA_SHA1 0x00001042UL
+
+/* new for v2.40 */
+#define CKM_ECDSA_SHA224 0x00001043UL
+#define CKM_ECDSA_SHA256 0x00001044UL
+#define CKM_ECDSA_SHA384 0x00001045UL
+#define CKM_ECDSA_SHA512 0x00001046UL
+#define CKM_EC_KEY_PAIR_GEN_W_EXTRA_BITS 0x0000140BUL
+
+/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
+ * are new for v2.11 */
+#define CKM_ECDH1_DERIVE 0x00001050UL
+#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051UL
+#define CKM_ECMQV_DERIVE 0x00001052UL
+
+/* new for v2.40 */
+#define CKM_ECDH_AES_KEY_WRAP 0x00001053UL
+#define CKM_RSA_AES_KEY_WRAP 0x00001054UL
+
+#define CKM_JUNIPER_KEY_GEN 0x00001060UL
+#define CKM_JUNIPER_ECB128 0x00001061UL
+#define CKM_JUNIPER_CBC128 0x00001062UL
+#define CKM_JUNIPER_COUNTER 0x00001063UL
+#define CKM_JUNIPER_SHUFFLE 0x00001064UL
+#define CKM_JUNIPER_WRAP 0x00001065UL
+#define CKM_FASTHASH 0x00001070UL
+
+/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
+ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
+ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
+ * new for v2.11 */
+#define CKM_AES_KEY_GEN 0x00001080UL
+#define CKM_AES_ECB 0x00001081UL
+#define CKM_AES_CBC 0x00001082UL
+#define CKM_AES_MAC 0x00001083UL
+#define CKM_AES_MAC_GENERAL 0x00001084UL
+#define CKM_AES_CBC_PAD 0x00001085UL
+/* new for v2.20 amendment 3 */
+#define CKM_AES_CTR 0x00001086UL
+/* new for v2.30 */
+#define CKM_AES_GCM 0x00001087UL
+#define CKM_AES_CCM 0x00001088UL
+#define CKM_AES_CTS 0x00001089UL
+/* AES-CMAC values copied from v2.40 errata 1 header file */
+#define CKM_AES_CMAC 0x0000108AUL
+#define CKM_AES_CMAC_GENERAL 0x0000108BUL
+#define CKM_AES_XCBC_MAC 0x0000108CUL
+#define CKM_AES_XCBC_MAC_96 0x0000108DUL
+
+/* BlowFish and TwoFish are new for v2.20 */
+#define CKM_BLOWFISH_KEY_GEN 0x00001090UL
+#define CKM_BLOWFISH_CBC 0x00001091UL
+#define CKM_TWOFISH_KEY_GEN 0x00001092UL
+#define CKM_TWOFISH_CBC 0x00001093UL
+
+/* new for v2.40 */
+#define CKM_BLOWFISH_CBC_PAD 0x00001094UL
+#define CKM_TWOFISH_CBC_PAD 0x00001095UL
+
+/* Camellia is proposed for v2.20 Amendment 3 */
+#define CKM_CAMELLIA_KEY_GEN 0x00000550UL
+#define CKM_CAMELLIA_ECB 0x00000551UL
+#define CKM_CAMELLIA_CBC 0x00000552UL
+#define CKM_CAMELLIA_MAC 0x00000553UL
+#define CKM_CAMELLIA_MAC_GENERAL 0x00000554UL
+#define CKM_CAMELLIA_CBC_PAD 0x00000555UL
+#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556UL
+#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557UL
+
+/* new for v2.40 */
+#define CKM_ARIA_KEY_GEN 0x00000560UL
+#define CKM_ARIA_ECB 0x00000561UL
+#define CKM_ARIA_CBC 0x00000562UL
+#define CKM_ARIA_MAC 0x00000563UL
+#define CKM_ARIA_MAC_GENERAL 0x00000564UL
+#define CKM_ARIA_CBC_PAD 0x00000565UL
+#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566UL
+#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567UL
+
+#define CKM_SEED_KEY_GEN 0x00000650UL
+#define CKM_SEED_ECB 0x00000651UL
+#define CKM_SEED_CBC 0x00000652UL
+#define CKM_SEED_MAC 0x00000653UL
+#define CKM_SEED_MAC_GENERAL 0x00000654UL
+#define CKM_SEED_CBC_PAD 0x00000655UL
+#define CKM_SEED_ECB_ENCRYPT_DATA 0x00000656UL
+#define CKM_SEED_CBC_ENCRYPT_DATA 0x00000657UL
+
+/* new for v2.40 */
+#define CKM_ECDSA_SHA3_224 0x00001047UL
+#define CKM_ECDSA_SHA3_256 0x00001048UL
+#define CKM_ECDSA_SHA3_384 0x00001049UL
+#define CKM_ECDSA_SHA3_512 0x0000104aUL
+#define CKM_EC_EDWARDS_KEY_PAIR_GEN 0x00001055UL
+#define CKM_EC_MONTGOMERY_KEY_PAIR_GEN 0x00001056UL
+#define CKM_EDDSA 0x00001057UL
+
+/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
+#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100UL
+#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101UL
+#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102UL
+#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103UL
+#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104UL
+#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105UL
+
+#define CKM_GOSTR3410_KEY_PAIR_GEN 0x00001200UL
+#define CKM_GOSTR3410 0x00001201UL
+#define CKM_GOSTR3410_WITH_GOSTR3411 0x00001202UL
+#define CKM_GOSTR3410_KEY_WRAP 0x00001203UL
+#define CKM_GOSTR3410_DERIVE 0x00001204UL
+#define CKM_GOSTR3411 0x00001210UL
+#define CKM_GOSTR3411_HMAC 0x00001211UL
+#define CKM_GOST28147_KEY_GEN 0x00001220UL
+#define CKM_GOST28147_ECB 0x00001221UL
+#define CKM_GOST28147 0x00001222UL
+#define CKM_GOST28147_MAC 0x00001223UL
+#define CKM_GOST28147_KEY_WRAP 0x00001224UL
+
+/* new for v2.40 */
+#define CKM_CHACHA20_KEY_GEN 0x00001225UL
+#define CKM_CHACHA20 0x00001226UL
+#define CKM_POLY1305_KEY_GEN 0x00001227UL
+#define CKM_POLY1305 0x00001228UL
+
+#define CKM_DSA_PARAMETER_GEN 0x00002000UL
+#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001UL
+#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002UL
+
+/* new for v2.40 */
+#define CKM_DSA_PROBABILISTIC_PARAMETER_GEN 0x00002003UL
+#define CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN 0x00002004UL
+#define CKM_DSA_FIPS_G_GEN 0x00002005UL
+#define CKM_AES_CFB1 0x00002108UL
+#define CKM_AES_KEY_WRAP 0x00002109UL
+#define CKM_AES_KEY_WRAP_PAD 0x0000210AUL
+#define CKM_AES_KEY_WRAP_KWP 0x0000210BUL
+
+/* CKM_SP800_108_xxx_KDF are new for v3.0 */
+#define CKM_SP800_108_COUNTER_KDF 0x000003acUL
+#define CKM_SP800_108_FEEDBACK_KDF 0x000003adUL
+#define CKM_SP800_108_DOUBLE_PIPELINE_KDF 0x000003aeUL
+
+/* new for v2.4 */
+#define CKM_RSA_PKCS_TPM_1_1 0x00004001UL
+#define CKM_RSA_PKCS_OAEP_TPM_1_1 0x00004002UL
+#define CKM_SHA_1_KEY_GEN 0x00004003UL
+#define CKM_SHA224_KEY_GEN 0x00004004UL
+#define CKM_SHA256_KEY_GEN 0x00004005UL
+#define CKM_SHA384_KEY_GEN 0x00004006UL
+#define CKM_SHA512_KEY_GEN 0x00004007UL
+#define CKM_SHA512_224_KEY_GEN 0x00004008UL
+#define CKM_SHA512_256_KEY_GEN 0x00004009UL
+#define CKM_SHA512_T_KEY_GEN 0x0000400aUL
+
+/* new for v3.0 */
+#define CKM_NULL 0x0000400bUL
+#define CKM_BLAKE2B_160 0x0000400cUL
+#define CKM_BLAKE2B_160_HMAC 0x0000400dUL
+#define CKM_BLAKE2B_160_HMAC_GENERAL 0x0000400eUL
+#define CKM_BLAKE2B_160_KEY_DERIVE 0x0000400fUL
+#define CKM_BLAKE2B_160_KEY_GEN 0x00004010UL
+#define CKM_BLAKE2B_256 0x00004011UL
+#define CKM_BLAKE2B_256_HMAC 0x00004012UL
+#define CKM_BLAKE2B_256_HMAC_GENERAL 0x00004013UL
+#define CKM_BLAKE2B_256_KEY_DERIVE 0x00004014UL
+#define CKM_BLAKE2B_256_KEY_GEN 0x00004015UL
+#define CKM_BLAKE2B_384 0x00004016UL
+#define CKM_BLAKE2B_384_HMAC 0x00004017UL
+#define CKM_BLAKE2B_384_HMAC_GENERAL 0x00004018UL
+#define CKM_BLAKE2B_384_KEY_DERIVE 0x00004019UL
+#define CKM_BLAKE2B_384_KEY_GEN 0x0000401aUL
+#define CKM_BLAKE2B_512 0x0000401bUL
+#define CKM_BLAKE2B_512_HMAC 0x0000401cUL
+#define CKM_BLAKE2B_512_HMAC_GENERAL 0x0000401dUL
+#define CKM_BLAKE2B_512_KEY_DERIVE 0x0000401eUL
+#define CKM_BLAKE2B_512_KEY_GEN 0x0000401fUL
+#define CKM_SALSA20 0x00004020UL
+#define CKM_CHACHA20_POLY1305 0x00004021UL
+#define CKM_SALSA20_POLY1305 0x00004022UL
+#define CKM_X3DH_INITIALIZE 0x00004023UL
+#define CKM_X3DH_RESPOND 0x00004024UL
+#define CKM_X2RATCHET_INITIALIZE 0x00004025UL
+#define CKM_X2RATCHET_RESPOND 0x00004026UL
+#define CKM_X2RATCHET_ENCRYPT 0x00004027UL
+#define CKM_X2RATCHET_DECRYPT 0x00004028UL
+#define CKM_XEDDSA 0x00004029UL
+#define CKM_HKDF_DERIVE 0x0000402aUL
+#define CKM_HKDF_DATA 0x0000402bUL
+#define CKM_HKDF_KEY_GEN 0x0000402cUL
+#define CKM_SALSA20_KEY_GEN 0x0000402dUL
+
+#define CKM_VENDOR_DEFINED 0x80000000UL
+
+typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
+
+/* CK_MECHANISM is a structure that specifies a particular
+ * mechanism */
+typedef struct CK_MECHANISM {
+ CK_MECHANISM_TYPE mechanism;
+ CK_VOID_PTR pParameter;
+
+ /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulParameterLen; /* in bytes */
+} CK_MECHANISM;
+
+typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
+
+/* CK_MECHANISM_INFO provides information about a particular
+ * mechanism */
+typedef struct CK_MECHANISM_INFO {
+ CK_ULONG ulMinKeySize;
+ CK_ULONG ulMaxKeySize;
+ CK_FLAGS flags;
+} CK_MECHANISM_INFO;
+
+/* The flags are defined as follows:
+ * Bit Flag Mask Meaning */
+#define CKF_HW 0x00000001UL /* performed by HW */
+
+/* Message interface Flags, new for v3.0 */
+#define CKF_MESSAGE_ENCRYPT 0x00000002UL
+#define CKF_MESSAGE_DECRYPT 0x00000004UL
+#define CKF_MESSAGE_SIGN 0x00000008UL
+#define CKF_MESSAGE_VERIFY 0x00000010UL
+#define CKF_MULTI_MESSAGE 0x00000020UL
+
+/* FindObjects (not for CK_MECHANISM_INFO, but for C_CancelSession) v3.0 */
+#define CKF_FIND_OBJECTS 0x00000040UL
+
+/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
+ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
+ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
+ * and CKF_DERIVE are new for v2.0. They specify whether or not
+ * a mechanism can be used for a particular task */
+#define CKF_ENCRYPT 0x00000100UL
+#define CKF_DECRYPT 0x00000200UL
+#define CKF_DIGEST 0x00000400UL
+#define CKF_SIGN 0x00000800UL
+#define CKF_SIGN_RECOVER 0x00001000UL
+#define CKF_VERIFY 0x00002000
+#define CKF_VERIFY_RECOVER 0x00004000UL
+#define CKF_GENERATE 0x00008000UL
+#define CKF_GENERATE_KEY_PAIR 0x00010000UL
+#define CKF_WRAP 0x00020000UL
+#define CKF_UNWRAP 0x00040000UL
+#define CKF_DERIVE 0x00080000UL
+
+/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
+ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
+ * describe a token's EC capabilities not available in mechanism
+ * information. */
+#define CKF_EC_F_P 0x00100000UL
+#define CKF_EC_F_2M 0x00200000UL
+#define CKF_EC_ECPARAMETERS 0x00400000UL
+#define CKF_EC_OID 0x00800000UL
+#define CKF_EC_NAMEDCURVE CKF_EC_OID /* renamed in v3.0 */
+#define CKF_EC_UNCOMPRESS 0x01000000UL
+#define CKF_EC_COMPRESS 0x02000000UL
+
+#define CKF_EXTENSION 0x80000000UL /* FALSE for this version */
+
+typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
+
+/* CK_RV is a value that identifies the return value of a
+ * PKCS #11 function */
+/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG CK_RV;
+
+#define CKR_OK 0x00000000UL
+#define CKR_CANCEL 0x00000001UL
+#define CKR_HOST_MEMORY 0x00000002UL
+#define CKR_SLOT_ID_INVALID 0x00000003UL
+
+/* CKR_FLAGS_INVALID was removed for v2.0 */
+
+/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
+#define CKR_GENERAL_ERROR 0x00000005UL
+#define CKR_FUNCTION_FAILED 0x00000006UL
+
+/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
+ * and CKR_CANT_LOCK are new for v2.01 */
+#define CKR_ARGUMENTS_BAD 0x00000007UL
+#define CKR_NO_EVENT 0x00000008UL
+#define CKR_NEED_TO_CREATE_THREADS 0x00000009UL
+#define CKR_CANT_LOCK 0x0000000AUL
+
+#define CKR_ATTRIBUTE_READ_ONLY 0x00000010UL
+#define CKR_ATTRIBUTE_SENSITIVE 0x00000011UL
+#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012UL
+#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013UL
+
+/* new for v3.0 */
+#define CKR_ACTION_PROHIBITED 0x0000001BUL
+
+#define CKR_DATA_INVALID 0x00000020UL
+#define CKR_DATA_LEN_RANGE 0x00000021UL
+#define CKR_DEVICE_ERROR 0x00000030UL
+#define CKR_DEVICE_MEMORY 0x00000031UL
+#define CKR_DEVICE_REMOVED 0x00000032UL
+#define CKR_ENCRYPTED_DATA_INVALID 0x00000040UL
+#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041UL
+#define CKR_FUNCTION_CANCELED 0x00000050UL
+#define CKR_FUNCTION_NOT_PARALLEL 0x00000051UL
+
+/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
+#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054UL
+
+#define CKR_KEY_HANDLE_INVALID 0x00000060UL
+
+/* CKR_KEY_SENSITIVE was removed for v2.0 */
+
+#define CKR_KEY_SIZE_RANGE 0x00000062UL
+#define CKR_KEY_TYPE_INCONSISTENT 0x00000063UL
+
+/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
+ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
+ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
+ * v2.0 */
+#define CKR_KEY_NOT_NEEDED 0x00000064UL
+#define CKR_KEY_CHANGED 0x00000065UL
+#define CKR_KEY_NEEDED 0x00000066UL
+#define CKR_KEY_INDIGESTIBLE 0x00000067UL
+#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068UL
+#define CKR_KEY_NOT_WRAPPABLE 0x00000069UL
+#define CKR_KEY_UNEXTRACTABLE 0x0000006AUL
+
+#define CKR_MECHANISM_INVALID 0x00000070UL
+#define CKR_MECHANISM_PARAM_INVALID 0x00000071UL
+
+/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
+ * were removed for v2.0 */
+#define CKR_OBJECT_HANDLE_INVALID 0x00000082UL
+#define CKR_OPERATION_ACTIVE 0x00000090UL
+#define CKR_OPERATION_NOT_INITIALIZED 0x00000091UL
+#define CKR_PIN_INCORRECT 0x000000A0UL
+#define CKR_PIN_INVALID 0x000000A1UL
+#define CKR_PIN_LEN_RANGE 0x000000A2UL
+
+/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
+#define CKR_PIN_EXPIRED 0x000000A3UL
+#define CKR_PIN_LOCKED 0x000000A4UL
+
+#define CKR_SESSION_CLOSED 0x000000B0UL
+#define CKR_SESSION_COUNT 0x000000B1UL
+#define CKR_SESSION_HANDLE_INVALID 0x000000B3UL
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4UL
+#define CKR_SESSION_READ_ONLY 0x000000B5UL
+#define CKR_SESSION_EXISTS 0x000000B6UL
+
+/* CKR_SESSION_READ_ONLY_EXISTS and
+ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
+#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7UL
+#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8UL
+
+#define CKR_SIGNATURE_INVALID 0x000000C0UL
+#define CKR_SIGNATURE_LEN_RANGE 0x000000C1UL
+#define CKR_TEMPLATE_INCOMPLETE 0x000000D0UL
+#define CKR_TEMPLATE_INCONSISTENT 0x000000D1UL
+#define CKR_TOKEN_NOT_PRESENT 0x000000E0UL
+#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1UL
+#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2UL
+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0UL
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1UL
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2UL
+#define CKR_USER_ALREADY_LOGGED_IN 0x00000100UL
+#define CKR_USER_NOT_LOGGED_IN 0x00000101UL
+#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102UL
+#define CKR_USER_TYPE_INVALID 0x00000103UL
+
+/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
+ * are new to v2.01 */
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104UL
+#define CKR_USER_TOO_MANY_TYPES 0x00000105UL
+
+#define CKR_WRAPPED_KEY_INVALID 0x00000110UL
+#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112UL
+#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113UL
+#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114UL
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115UL
+#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120UL
+
+/* This is new to v2.0 */
+#define CKR_RANDOM_NO_RNG 0x00000121UL
+
+/* This is new to v2.11 */
+#define CKR_DOMAIN_PARAMS_INVALID 0x00000130UL
+
+/* This is new to v2.40 */
+#define CKR_CURVE_NOT_SUPPORTED 0x00000140UL
+
+/* These are new to v2.0 */
+#define CKR_BUFFER_TOO_SMALL 0x00000150UL
+#define CKR_SAVED_STATE_INVALID 0x00000160UL
+#define CKR_INFORMATION_SENSITIVE 0x00000170UL
+#define CKR_STATE_UNSAVEABLE 0x00000180UL
+
+/* These are new to v2.01 */
+#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190UL
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191UL
+#define CKR_MUTEX_BAD 0x000001A0UL
+#define CKR_MUTEX_NOT_LOCKED 0x000001A1UL
+
+/* These are new to v2.40 */
+#define CKR_NEW_PIN_MODE 0x000001B0UL
+#define CKR_NEXT_OTP 0x000001B1UL
+#define CKR_EXCEEDED_MAX_ITERATIONS 0x000001B5UL
+#define CKR_FIPS_SELF_TEST_FAILED 0x000001B6UL
+#define CKR_LIBRARY_LOAD_FAILED 0x000001B7UL
+#define CKR_PIN_TOO_WEAK 0x000001B8UL
+#define CKR_PUBLIC_KEY_INVALID 0x000001B9UL
+
+/* This is new to v2.20 */
+#define CKR_FUNCTION_REJECTED 0x00000200UL
+
+/* This is new to v3.0 */
+#define CKR_TOKEN_RESOURCE_EXCEEDED 0x00000201UL
+#define CKR_OPERATION_CANCEL_FAILED 0x00000202UL
+
+#define CKR_VENDOR_DEFINED 0x80000000UL
+
+/* CK_NOTIFY is an application callback that processes events */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_NOTIFICATION event,
+ CK_VOID_PTR pApplication /* passed to C_OpenSession */
+);
+
+/* CK_FUNCTION_LIST is a structure holding a PKCS #11 spec
+ * version and pointers of appropriate types to all the
+ * PKCS #11 functions */
+/* CK_FUNCTION_LIST is new for v2.0 */
+typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
+
+typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
+
+typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
+
+/* These are new for v3.0 */
+typedef struct CK_FUNCTION_LIST_3_0 CK_FUNCTION_LIST_3_0;
+typedef CK_FUNCTION_LIST_3_0 CK_PTR CK_FUNCTION_LIST_3_0_PTR;
+typedef CK_FUNCTION_LIST_3_0_PTR CK_PTR CK_FUNCTION_LIST_3_0_PTR_PTR;
+
+/* Interfaces are new in v3.0 */
+typedef struct CK_INTERFACE {
+ CK_CHAR *pInterfaceName;
+ CK_VOID_PTR pFunctionList;
+ CK_FLAGS flags;
+} CK_INTERFACE;
+
+typedef CK_INTERFACE CK_PTR CK_INTERFACE_PTR;
+typedef CK_INTERFACE_PTR CK_PTR CK_INTERFACE_PTR_PTR;
+
+#define CKF_END_OF_MESSAGE 0x00000001UL
+#define CKF_INTERFACE_FORK_SAFE 0x00000001UL
+
+/* CK_CREATEMUTEX is an application callback for creating a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
+ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
+);
+
+/* CK_DESTROYMUTEX is an application callback for destroying a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+/* CK_LOCKMUTEX is an application callback for locking a mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+/* CK_UNLOCKMUTEX is an application callback for unlocking a
+ * mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+/* CK_C_INITIALIZE_ARGS provides the optional arguments to
+ * C_Initialize */
+typedef struct CK_C_INITIALIZE_ARGS {
+ CK_CREATEMUTEX CreateMutex;
+ CK_DESTROYMUTEX DestroyMutex;
+ CK_LOCKMUTEX LockMutex;
+ CK_UNLOCKMUTEX UnlockMutex;
+ CK_FLAGS flags;
+ /* The official PKCS #11 spec does not have a 'LibraryParameters' field, but
+ * a reserved field. NSS needs a way to pass instance-specific information
+ * to the library (like where to find its config files, etc). This
+ * information is usually provided by the installer and passed uninterpreted
+ * by NSS to the library, though NSS does know the specifics of the softoken
+ * version of this parameter. Most compliant PKCS#11 modules expect this
+ * parameter to be NULL, and will return CKR_ARGUMENTS_BAD from
+ * C_Initialize if Library parameters is supplied. */
+ CK_CHAR_PTR *LibraryParameters;
+ /* This field is only present if the LibraryParameters is not NULL. It must
+ * be NULL in all cases */
+ CK_VOID_PTR pReserved;
+} CK_C_INITIALIZE_ARGS;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001UL
+#define CKF_OS_LOCKING_OK 0x00000002UL
+
+typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
+
+/* additional flags for parameters to functions */
+
+/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
+#define CKF_DONT_BLOCK 1
+
+/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
+ * Generation Function (MGF) applied to a message block when
+ * formatting a message block for the PKCS #1 OAEP encryption
+ * scheme. */
+typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
+
+typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
+
+/* The following MGFs are defined */
+/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
+ * are new for v2.20 */
+#define CKG_MGF1_SHA1 0x00000001UL
+#define CKG_MGF1_SHA256 0x00000002UL
+#define CKG_MGF1_SHA384 0x00000003UL
+#define CKG_MGF1_SHA512 0x00000004UL
+
+/* v2.20 amendment 3 */
+#define CKG_MGF1_SHA224 0x00000005UL
+
+/* v2.40 */
+#define CKG_MGF1_SHA3_224 0x00000006UL
+#define CKG_MGF1_SHA3_256 0x00000007UL
+#define CKG_MGF1_SHA3_384 0x00000008UL
+#define CKG_MGF1_SHA3_512 0x00000009UL
+
+/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
+ * of the encoding parameter when formatting a message block
+ * for the PKCS #1 OAEP encryption scheme. */
+typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
+
+typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
+
+/* The following encoding parameter sources are defined */
+#define CKZ_DATA_SPECIFIED 0x00000001UL
+
+/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
+ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_OAEP mechanism. */
+typedef struct CK_RSA_PKCS_OAEP_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
+ CK_VOID_PTR pSourceData;
+ CK_ULONG ulSourceDataLen;
+} CK_RSA_PKCS_OAEP_PARAMS;
+
+typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
+
+/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
+ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_PSS mechanism(s). */
+typedef struct CK_RSA_PKCS_PSS_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_ULONG sLen;
+} CK_RSA_PKCS_PSS_PARAMS;
+
+typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
+
+/* CK_EC_KDF_TYPE is new for v2.11. */
+typedef CK_ULONG CK_EC_KDF_TYPE;
+
+/* The following EC Key Derivation Functions are defined */
+#define CKD_NULL 0x00000001UL
+#define CKD_SHA1_KDF 0x00000002UL
+#define CKD_SHA224_KDF 0x00000005UL
+#define CKD_SHA256_KDF 0x00000006UL
+#define CKD_SHA384_KDF 0x00000007UL
+#define CKD_SHA512_KDF 0x00000008UL
+
+/* new for v2.40 */
+#define CKD_CPDIVERSIFY_KDF 0x00000009UL
+#define CKD_SHA3_224_KDF 0x0000000AUL
+#define CKD_SHA3_256_KDF 0x0000000BUL
+#define CKD_SHA3_384_KDF 0x0000000CUL
+#define CKD_SHA3_512_KDF 0x0000000DUL
+
+/* new for v3.0 */
+#define CKD_SHA1_KDF_SP800 0x0000000EUL
+#define CKD_SHA224_KDF_SP800 0x0000000FUL
+#define CKD_SHA256_KDF_SP800 0x00000010UL
+#define CKD_SHA384_KDF_SP800 0x00000011UL
+#define CKD_SHA512_KDF_SP800 0x00000012UL
+#define CKD_SHA3_224_KDF_SP800 0x00000013UL
+#define CKD_SHA3_256_KDF_SP800 0x00000014UL
+#define CKD_SHA3_384_KDF_SP800 0x00000015UL
+#define CKD_SHA3_512_KDF_SP800 0x00000016UL
+#define CKD_BLAKE2B_160_KDF 0x00000017UL
+#define CKD_BLAKE2B_256_KDF 0x00000018UL
+#define CKD_BLAKE2B_384_KDF 0x00000019UL
+#define CKD_BLAKE2B_512_KDF 0x0000001aUL
+
+/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
+ * where each party contributes one key pair.
+ */
+typedef struct CK_ECDH1_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_ECDH1_DERIVE_PARAMS;
+
+typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
+
+/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
+typedef struct CK_ECDH2_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+} CK_ECDH2_DERIVE_PARAMS;
+
+typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
+
+typedef struct CK_ECMQV_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+ CK_OBJECT_HANDLE publicKey;
+} CK_ECMQV_DERIVE_PARAMS;
+
+typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
+
+/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
+ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
+typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
+typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
+
+/* The following X9.42 DH key derivation functions are defined
+ (besides CKD_NULL already defined : */
+#define CKD_SHA1_KDF_ASN1 0x00000003UL
+#define CKD_SHA1_KDF_CONCATENATE 0x00000004UL
+
+/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
+ * contributes one key pair */
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_X9_42_DH1_DERIVE_PARAMS;
+
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
+
+/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
+ * mechanisms, where each party contributes two key pairs */
+typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+} CK_X9_42_DH2_DERIVE_PARAMS;
+
+typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
+
+typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+ CK_OBJECT_HANDLE publicKey;
+} CK_X9_42_MQV_DERIVE_PARAMS;
+
+typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
+
+/* CK_KEA_DERIVE_PARAMS provides the parameters to the
+ * CKM_KEA_DERIVE mechanism */
+/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
+typedef struct CK_KEA_DERIVE_PARAMS {
+ CK_BBOOL isSender;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pRandomB;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_KEA_DERIVE_PARAMS;
+
+typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
+
+/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
+ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
+ * holds the effective keysize */
+typedef CK_ULONG CK_RC2_PARAMS;
+
+typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
+
+/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
+ * mechanism */
+typedef struct CK_RC2_CBC_PARAMS {
+ /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+
+ CK_BYTE iv[8]; /* IV for CBC mode */
+} CK_RC2_CBC_PARAMS;
+
+typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
+
+/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC2_MAC_GENERAL mechanism */
+/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC2_MAC_GENERAL_PARAMS {
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC2_MAC_GENERAL_PARAMS;
+
+typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR
+ CK_RC2_MAC_GENERAL_PARAMS_PTR;
+
+/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
+ * CKM_RC5_MAC mechanisms */
+/* CK_RC5_PARAMS is new for v2.0 */
+typedef struct CK_RC5_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+} CK_RC5_PARAMS;
+
+typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
+
+/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
+ * mechanism */
+/* CK_RC5_CBC_PARAMS is new for v2.0 */
+typedef struct CK_RC5_CBC_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_BYTE_PTR pIv; /* pointer to IV */
+ CK_ULONG ulIvLen; /* length of IV in bytes */
+} CK_RC5_CBC_PARAMS;
+
+typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
+
+/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC5_MAC_GENERAL mechanism */
+/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC5_MAC_GENERAL_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC5_MAC_GENERAL_PARAMS;
+
+typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR
+ CK_RC5_MAC_GENERAL_PARAMS_PTR;
+
+/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
+ * ciphers' MAC_GENERAL mechanisms. Its value is the length of
+ * the MAC */
+/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
+
+typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
+
+/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */
+typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[8];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[16];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+/* CK_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */
+typedef struct CK_AES_CTR_PARAMS {
+ CK_ULONG ulCounterBits;
+ CK_BYTE cb[16];
+} CK_AES_CTR_PARAMS;
+
+typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR;
+
+/* CK_GCM_PARAMS is new for version 2.30 */
+/* There was a discrepency between the doc and the headers
+ * in PKCS #11 v2.40, NSS had the doc version, but the header
+ * was normative. In V3.0 they were reconsiled as the header
+ * version. In NSS the header version is called CK_GCM_PARAMS_V3
+ * and the v2.40 doc version is called CK_NSS_GCM_PARAMS.
+ * CK_GCM_PARMS is define as CK_NSS_GCM_PARAMS if
+ * NSS_PCKS11_2_0_COMPAT is defined and CK_GCM_PARAMS_V3 if it's not.
+ * Softoken accepts either version and internally uses CK_NSS_GCM_PARAMS */
+typedef struct CK_GCM_PARAMS_V3 {
+ CK_BYTE_PTR pIv;
+ CK_ULONG ulIvLen;
+ CK_ULONG ulIvBits;
+ CK_BYTE_PTR pAAD;
+ CK_ULONG ulAADLen;
+ CK_ULONG ulTagBits;
+} CK_GCM_PARAMS_V3;
+
+typedef CK_GCM_PARAMS_V3 CK_PTR CK_GCM_PARAMS_V3_PTR;
+
+/* CK_CCM_PARAMS is new for version 2.30 */
+typedef struct CK_CCM_PARAMS {
+ CK_ULONG ulDataLen;
+ CK_BYTE_PTR pNonce;
+ CK_ULONG ulNonceLen;
+ CK_BYTE_PTR pAAD;
+ CK_ULONG ulAADLen;
+ CK_ULONG ulMACLen;
+} CK_CCM_PARAMS;
+
+typedef CK_CCM_PARAMS CK_PTR CK_CCM_PARAMS_PTR;
+
+/* SALSA20_POLY1305 and CHACHA20_POLY1305 is AEAD is new in v3.0 */
+typedef struct CK_SALSA20_CHACHA20_POLY1305_PARAMS {
+ CK_BYTE_PTR pNonce;
+ CK_ULONG ulNonceLen;
+ CK_BYTE_PTR pAAD;
+ CK_ULONG ulAADLen;
+} CK_SALSA20_CHACHA20_POLY1305_PARAMS;
+
+typedef CK_SALSA20_CHACHA20_POLY1305_PARAMS
+ CK_PTR CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR;
+
+/* MESSAGE params are new for v3.0 */
+typedef CK_ULONG CK_GENERATOR_FUNCTION;
+#define CKG_NO_GENERATE 0x00000000UL
+#define CKG_GENERATE 0x00000001UL
+#define CKG_GENERATE_COUNTER 0x00000002UL
+#define CKG_GENERATE_RANDOM 0x00000003UL
+#define CKG_GENERATE_COUNTER_XOR 0x00000004UL
+
+typedef struct CK_GCM_MESSAGE_PARAMS {
+ CK_BYTE_PTR pIv;
+ CK_ULONG ulIvLen;
+ CK_ULONG ulIvFixedBits;
+ CK_GENERATOR_FUNCTION ivGenerator;
+ CK_BYTE_PTR pTag;
+ CK_ULONG ulTagBits;
+} CK_GCM_MESSAGE_PARAMS;
+
+typedef CK_GCM_MESSAGE_PARAMS CK_GCM_MESSAGE_PARAMS_PTR;
+
+typedef struct CK_CCM_MESSAGE_PARAMS {
+ CK_ULONG ulDataLen; /*plaintext or ciphertext*/
+ CK_BYTE_PTR pNonce;
+ CK_ULONG ulNonceLen;
+ CK_ULONG ulNonceFixedBits;
+ CK_GENERATOR_FUNCTION nonceGenerator;
+ CK_BYTE_PTR pMAC;
+ CK_ULONG ulMACLen;
+} CK_CCM_MESSAGE_PARAMS;
+
+typedef CK_CCM_MESSAGE_PARAMS CK_CCM_MESSAGE_PARAMS_PTR;
+
+/* SALSA20/CHACHA20 doe not define IV generators */
+typedef struct CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS {
+ CK_BYTE_PTR pNonce;
+ CK_ULONG ulNonceLen;
+ CK_BYTE_PTR pTag;
+} CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS;
+
+typedef CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS
+ CK_PTR CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS_PTR;
+
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pPassword;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPAndGLen;
+ CK_ULONG ulQLen;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pPrimeP;
+ CK_BYTE_PTR pBaseG;
+ CK_BYTE_PTR pSubprimeQ;
+} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
+
+typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR
+ CK_SKIPJACK_PRIVATE_WRAP_PTR;
+
+/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_RELAYX mechanism */
+/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_RELAYX_PARAMS {
+ CK_ULONG ulOldWrappedXLen;
+ CK_BYTE_PTR pOldWrappedX;
+ CK_ULONG ulOldPasswordLen;
+ CK_BYTE_PTR pOldPassword;
+ CK_ULONG ulOldPublicDataLen;
+ CK_BYTE_PTR pOldPublicData;
+ CK_ULONG ulOldRandomLen;
+ CK_BYTE_PTR pOldRandomA;
+ CK_ULONG ulNewPasswordLen;
+ CK_BYTE_PTR pNewPassword;
+ CK_ULONG ulNewPublicDataLen;
+ CK_BYTE_PTR pNewPublicData;
+ CK_ULONG ulNewRandomLen;
+ CK_BYTE_PTR pNewRandomA;
+} CK_SKIPJACK_RELAYX_PARAMS;
+
+typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR
+ CK_SKIPJACK_RELAYX_PARAMS_PTR;
+
+/* New for v2.40, CAMELLIA, ARIA, SEED */
+typedef struct CK_CAMELLIA_CTR_PARAMS {
+ CK_ULONG ulCounterBits;
+ CK_BYTE cb[16];
+} CK_CAMELLIA_CTR_PARAMS;
+
+typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR;
+
+typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[16];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR
+ CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[16];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR
+ CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+typedef struct CK_SEED_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[16];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_SEED_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_SEED_CBC_ENCRYPT_DATA_PARAMS CK_PTR
+ CK_SEED_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+/* ChaCha20/Salsa20 Counter support is new in v3.0*/
+typedef struct CK_CHACHA20_PARAMS {
+ CK_BYTE_PTR pBlockCounter;
+ CK_ULONG blockCounterBits;
+ CK_BYTE_PTR pNonce;
+ CK_ULONG ulNonceBits;
+} CK_CHACHA20_PARAMS;
+
+typedef CK_CHACHA20_PARAMS CK_PTR CK_CHACHA20_PARAMS_PTR;
+
+typedef struct CK_SALSA20_PARAMS {
+ CK_BYTE_PTR pBlockCounter;
+ CK_BYTE_PTR pNonce;
+ CK_ULONG ulNonceBits;
+} CK_SALSA20_PARAMS;
+typedef CK_SALSA20_PARAMS CK_PTR CK_SALSA20_PARAMS_PTR;
+
+typedef struct CK_PBE_PARAMS {
+ CK_BYTE_PTR pInitVector;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pSalt;
+ CK_ULONG ulSaltLen;
+ CK_ULONG ulIteration;
+} CK_PBE_PARAMS;
+
+typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
+
+/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
+ * CKM_KEY_WRAP_SET_OAEP mechanism */
+/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
+typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
+ CK_BYTE bBC; /* block contents byte */
+ CK_BYTE_PTR pX; /* extra data */
+ CK_ULONG ulXLen; /* length of extra data in bytes */
+} CK_KEY_WRAP_SET_OAEP_PARAMS;
+
+typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR
+ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
+
+typedef struct CK_SSL3_RANDOM_DATA {
+ CK_BYTE_PTR pClientRandom;
+ CK_ULONG ulClientRandomLen;
+ CK_BYTE_PTR pServerRandom;
+ CK_ULONG ulServerRandomLen;
+} CK_SSL3_RANDOM_DATA;
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_VERSION_PTR pVersion;
+} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR
+ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+typedef struct CK_SSL3_KEY_MAT_OUT {
+ CK_OBJECT_HANDLE hClientMacSecret;
+ CK_OBJECT_HANDLE hServerMacSecret;
+ CK_OBJECT_HANDLE hClientKey;
+ CK_OBJECT_HANDLE hServerKey;
+ CK_BYTE_PTR pIVClient;
+ CK_BYTE_PTR pIVServer;
+} CK_SSL3_KEY_MAT_OUT;
+
+typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
+
+typedef struct CK_SSL3_KEY_MAT_PARAMS {
+ CK_ULONG ulMacSizeInBits;
+ CK_ULONG ulKeySizeInBits;
+ CK_ULONG ulIVSizeInBits;
+ CK_BBOOL bIsExport; /* Unused. Must be set to CK_FALSE. */
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_SSL3_KEY_MAT_PARAMS;
+
+typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
+
+/* CK_TLS_PRF_PARAMS is new for version 2.20 */
+typedef struct CK_TLS_PRF_PARAMS {
+ CK_BYTE_PTR pSeed;
+ CK_ULONG ulSeedLen;
+ CK_BYTE_PTR pLabel;
+ CK_ULONG ulLabelLen;
+ CK_BYTE_PTR pOutput;
+ CK_ULONG_PTR pulOutputLen;
+} CK_TLS_PRF_PARAMS;
+
+typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
+
+/* TLS 1.2 is new for version 2.40 */
+typedef struct CK_TLS12_MASTER_KEY_DERIVE_PARAMS {
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_VERSION_PTR pVersion;
+ CK_MECHANISM_TYPE prfHashMechanism;
+} CK_TLS12_MASTER_KEY_DERIVE_PARAMS;
+
+typedef CK_TLS12_MASTER_KEY_DERIVE_PARAMS CK_PTR
+ CK_TLS12_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+typedef struct CK_TLS12_KEY_MAT_PARAMS {
+ CK_ULONG ulMacSizeInBits;
+ CK_ULONG ulKeySizeInBits;
+ CK_ULONG ulIVSizeInBits;
+ CK_BBOOL bIsExport; /* Unused. Must be set to CK_FALSE. */
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+ CK_MECHANISM_TYPE prfHashMechanism;
+} CK_TLS12_KEY_MAT_PARAMS;
+
+typedef CK_TLS12_KEY_MAT_PARAMS CK_PTR CK_TLS12_KEY_MAT_PARAMS_PTR;
+
+typedef struct CK_TLS_KDF_PARAMS {
+ CK_MECHANISM_TYPE prfMechanism;
+ CK_BYTE_PTR pLabel;
+ CK_ULONG ulLabelLength;
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_BYTE_PTR pContextData;
+ CK_ULONG ulContextDataLength;
+} CK_TLS_KDF_PARAMS;
+
+typedef struct CK_TLS_MAC_PARAMS {
+ CK_MECHANISM_TYPE prfHashMechanism;
+ CK_ULONG ulMacLength;
+ CK_ULONG ulServerOrClient;
+} CK_TLS_MAC_PARAMS;
+
+typedef CK_TLS_MAC_PARAMS CK_PTR CK_TLS_MAC_PARAMS_PTR;
+
+/* HKDF is new for v3.0 */
+typedef struct CK_HKDF_PARAMS {
+ CK_BBOOL bExtract;
+ CK_BBOOL bExpand;
+ CK_MECHANISM_TYPE prfHashMechanism;
+ CK_ULONG ulSaltType;
+ CK_BYTE_PTR pSalt;
+ CK_ULONG ulSaltLen;
+ CK_OBJECT_HANDLE hSaltKey;
+ CK_BYTE_PTR pInfo;
+ CK_ULONG ulInfoLen;
+} CK_HKDF_PARAMS;
+typedef CK_HKDF_PARAMS CK_PTR CK_HKDF_PARAMS_PTR;
+
+#define CKF_HKDF_SALT_NULL 0x00000001UL
+#define CKF_HKDF_SALT_DATA 0x00000002UL
+#define CKF_HKDF_SALT_KEY 0x00000004UL
+
+/* WTLS is new for version 2.20 */
+typedef struct CK_WTLS_RANDOM_DATA {
+ CK_BYTE_PTR pClientRandom;
+ CK_ULONG ulClientRandomLen;
+ CK_BYTE_PTR pServerRandom;
+ CK_ULONG ulServerRandomLen;
+} CK_WTLS_RANDOM_DATA;
+
+typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
+
+typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
+ CK_MECHANISM_TYPE DigestMechanism;
+ CK_WTLS_RANDOM_DATA RandomInfo;
+ CK_BYTE_PTR pVersion;
+} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
+
+typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR
+ CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+typedef struct CK_WTLS_PRF_PARAMS {
+ CK_MECHANISM_TYPE DigestMechanism;
+ CK_BYTE_PTR pSeed;
+ CK_ULONG ulSeedLen;
+ CK_BYTE_PTR pLabel;
+ CK_ULONG ulLabelLen;
+ CK_BYTE_PTR pOutput;
+ CK_ULONG_PTR pulOutputLen;
+} CK_WTLS_PRF_PARAMS;
+
+typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
+
+typedef struct CK_WTLS_KEY_MAT_OUT {
+ CK_OBJECT_HANDLE hMacSecret;
+ CK_OBJECT_HANDLE hKey;
+ CK_BYTE_PTR pIV;
+} CK_WTLS_KEY_MAT_OUT;
+
+typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
+
+typedef struct CK_WTLS_KEY_MAT_PARAMS {
+ CK_MECHANISM_TYPE DigestMechanism;
+ CK_ULONG ulMacSizeInBits;
+ CK_ULONG ulKeySizeInBits;
+ CK_ULONG ulIVSizeInBits;
+ CK_ULONG ulSequenceNumber;
+ CK_BBOOL bIsExport; /* Unused. Must be set to CK_FALSE. */
+ CK_WTLS_RANDOM_DATA RandomInfo;
+ CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_WTLS_KEY_MAT_PARAMS;
+
+typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
+
+/* The following types for NIST 800-108 KBKDF are defined in PKCS#11 v3.0 */
+typedef CK_MECHANISM_TYPE CK_SP800_108_PRF_TYPE;
+typedef CK_ULONG CK_PRF_DATA_TYPE;
+
+#define CK_SP800_108_ITERATION_VARIABLE 0x00000001UL
+#define CK_SP800_108_OPTIONAL_COUNTER 0x00000002UL
+#define CK_SP800_108_DKM_LENGTH 0x00000003UL
+#define CK_SP800_108_BYTE_ARRAY 0x00000004UL
+
+/* ERRATA: PKCS#11 v3.0 Cryptographic Token Interface Current Mechanisms
+ * specification specifies a CK_SP800_108_COUNTER, while the pkcs11t.h from
+ * PKCS#11 v3.0 Cryptographic Token Interface Base Specification specifies
+ * CK_SP800_108_OPTIONAL_COUNTER. */
+#define CK_SP800_108_COUNTER CK_SP800_108_OPTIONAL_COUNTER
+
+typedef struct CK_PRF_DATA_PARAM {
+ CK_PRF_DATA_TYPE type;
+ CK_VOID_PTR pValue;
+ CK_ULONG ulValueLen;
+} CK_PRF_DATA_PARAM;
+
+typedef CK_PRF_DATA_PARAM CK_PTR CK_PRF_DATA_PARAM_PTR;
+
+typedef struct CK_SP800_108_COUNTER_FORMAT {
+ CK_BBOOL bLittleEndian;
+ CK_ULONG ulWidthInBits;
+} CK_SP800_108_COUNTER_FORMAT;
+
+typedef CK_SP800_108_COUNTER_FORMAT CK_PTR CK_SP800_108_COUNTER_FORMAT_PTR;
+
+typedef CK_ULONG CK_SP800_108_DKM_LENGTH_METHOD;
+
+/* ERRATA: PKCS#11 v3.0 Cryptographic Token Interface Current Mechanisms
+ * defines that these constants exist, but doesn't specify values. pkcs11t.h
+ * from PKCS#11 v3.0 Cryptographic Token Interface Base Specification doesn't
+ * define these constants either. */
+#define CK_SP800_108_DKM_LENGTH_SUM_OF_KEYS 0x00000001UL
+#define CK_SP800_108_DKM_LENGTH_SUM_OF_SEGMENTS 0x00000002UL
+
+typedef struct CK_SP800_108_DKM_LENGTH_FORMAT {
+ CK_SP800_108_DKM_LENGTH_METHOD dkmLengthMethod;
+ CK_BBOOL bLittleEndian;
+ CK_ULONG ulWidthInBits;
+} CK_SP800_108_DKM_LENGTH_FORMAT;
+
+typedef CK_SP800_108_DKM_LENGTH_FORMAT CK_PTR CK_SP800_108_DKM_LENGTH_FORMAT_PTR;
+
+typedef struct CK_DERIVED_KEY {
+ CK_ATTRIBUTE_PTR pTemplate;
+ CK_ULONG ulAttributeCount;
+ CK_OBJECT_HANDLE_PTR phKey;
+} CK_DERIVED_KEY;
+
+typedef CK_DERIVED_KEY CK_PTR CK_DERIVED_KEY_PTR;
+
+/* UNFIXED ERRATA: NIST SP800-108 specifies that implementer can decide the
+ * number of bits to take from each PRF invocation. However, all three forms
+ * of the PKCS#11 v3.0 implementation lack a bitwidth for the PRF and only
+ * allow the full-width mechanism varieties. Additionally, outside of the
+ * base key (used as the key to the PRF), there is no way to pass any
+ * additional, PRF-mechanism specific data. */
+
+typedef struct CK_SP800_108_KDF_PARAMS {
+ CK_SP800_108_PRF_TYPE prfType;
+ CK_ULONG ulNumberOfDataParams;
+ CK_PRF_DATA_PARAM_PTR pDataParams;
+ CK_ULONG ulAdditionalDerivedKeys;
+ /* ERRATA: in PKCS#11 v3.0, pAdditionalDerivedKeys is typed as
+ * CK_DERVIED_KEY; it needs to be of type CK_DERIVED_KEY_PTR. */
+ CK_DERIVED_KEY_PTR pAdditionalDerivedKeys;
+} CK_SP800_108_KDF_PARAMS;
+
+typedef CK_SP800_108_KDF_PARAMS CK_PTR CK_SP800_108_KDF_PARAMS_PTR;
+
+typedef struct CK_SP800_108_FEEDBACK_KDF_PARAMS {
+ CK_SP800_108_PRF_TYPE prfType;
+ CK_ULONG ulNumberOfDataParams;
+ CK_PRF_DATA_PARAM_PTR pDataParams;
+ CK_ULONG ulIVLen;
+ CK_BYTE_PTR pIV;
+ CK_ULONG ulAdditionalDerivedKeys;
+ /* ERRATA: in PKCS#11 v3.0, pAdditionalDerivedKeys is typed as
+ * CK_DERVIED_KEY; it needs to be of type CK_DERIVED_KEY_PTR. */
+ CK_DERIVED_KEY_PTR pAdditionalDerivedKeys;
+} CK_SP800_108_FEEDBACK_KDF_PARAMS;
+
+typedef CK_SP800_108_FEEDBACK_KDF_PARAMS CK_PTR CK_SP800_108_FEEDBACK_KDF_PARAMS_PTR;
+
+/* CMS is new for version 2.20 */
+typedef struct CK_CMS_SIG_PARAMS {
+ CK_OBJECT_HANDLE certificateHandle;
+ CK_MECHANISM_PTR pSigningMechanism;
+ CK_MECHANISM_PTR pDigestMechanism;
+ CK_UTF8CHAR_PTR pContentType;
+ CK_BYTE_PTR pRequestedAttributes;
+ CK_ULONG ulRequestedAttributesLen;
+ CK_BYTE_PTR pRequiredAttributes;
+ CK_ULONG ulRequiredAttributesLen;
+} CK_CMS_SIG_PARAMS;
+
+typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
+
+typedef struct CK_KEY_DERIVATION_STRING_DATA {
+ CK_BYTE_PTR pData;
+ CK_ULONG ulLen;
+} CK_KEY_DERIVATION_STRING_DATA;
+
+typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR
+ CK_KEY_DERIVATION_STRING_DATA_PTR;
+
+/* The CK_EXTRACT_PARAMS is used for the
+ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
+ * of the base key should be used as the first bit of the
+ * derived key */
+/* CK_EXTRACT_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_EXTRACT_PARAMS;
+
+typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
+
+/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
+ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
+ * indicate the Pseudo-Random Function (PRF) used to generate
+ * key bits using PKCS #5 PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
+
+typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
+
+/* The following PRFs are defined in PKCS #5 v2.1. */
+#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001UL
+#define CKP_PKCS5_PBKD2_HMAC_GOSTR3411 0x00000002UL
+#define CKP_PKCS5_PBKD2_HMAC_SHA224 0x00000003UL
+#define CKP_PKCS5_PBKD2_HMAC_SHA256 0x00000004UL
+#define CKP_PKCS5_PBKD2_HMAC_SHA384 0x00000005UL
+#define CKP_PKCS5_PBKD2_HMAC_SHA512 0x00000006UL
+#define CKP_PKCS5_PBKD2_HMAC_SHA512_224 0x00000007UL
+#define CKP_PKCS5_PBKD2_HMAC_SHA512_256 0x00000008UL
+
+/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
+ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
+ * source of the salt value when deriving a key using PKCS #5
+ * PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
+
+typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
+
+/* The following salt value sources are defined in PKCS #5 v2.0. */
+#define CKZ_SALT_SPECIFIED 0x00000001UL
+
+/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
+ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
+ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
+/* this structure is kept for compatibility. use _PARAMS2. */
+typedef struct CK_PKCS5_PBKD2_PARAMS {
+ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
+ CK_VOID_PTR pSaltSourceData;
+ CK_ULONG ulSaltSourceDataLen;
+ CK_ULONG iterations;
+ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+ CK_VOID_PTR pPrfData;
+ CK_ULONG ulPrfDataLen;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG_PTR ulPasswordLen;
+} CK_PKCS5_PBKD2_PARAMS;
+
+typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
+
+typedef struct CK_PKCS5_PBKD2_PARAMS2 {
+ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
+ CK_VOID_PTR pSaltSourceData;
+ CK_ULONG ulSaltSourceDataLen;
+ CK_ULONG iterations;
+ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+ CK_VOID_PTR pPrfData;
+ CK_ULONG ulPrfDataLen;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG ulPasswordLen;
+} CK_PKCS5_PBKD2_PARAMS2;
+
+typedef CK_PKCS5_PBKD2_PARAMS2 CK_PTR CK_PKCS5_PBKD2_PARAMS2_PTR;
+
+/* OTP is new in v2.40 */
+typedef CK_ULONG CK_OTP_PARAM_TYPE;
+#define CK_OTP_VALUE 0UL
+#define CK_OTP_PIN 1UL
+#define CK_OTP_CHALLENGE 2UL
+#define CK_OTP_TIME 3UL
+#define CK_OTP_COUNTER 4UL
+#define CK_OTP_FLAGS 5UL
+#define CK_OTP_OUTPUT_LENGTH 6UL
+#define CK_OTP_OUTPUT_FORMAT 7UL
+
+typedef struct CK_OTP_PARAM {
+ CK_OTP_PARAM_TYPE type;
+ CK_VOID_PTR pValue;
+ CK_ULONG ulValueLen;
+} CK_OTP_PARAM;
+
+typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR;
+
+typedef struct CK_OTP_PARAMS {
+ CK_OTP_PARAM_PTR pParams;
+ CK_ULONG ulCount;
+} CK_OTP_PARAMS;
+
+typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR;
+
+typedef struct CK_OTP_SIGNATURE_INFO {
+ CK_OTP_PARAM_PTR pParams;
+ CK_ULONG ulCount;
+} CK_OTP_SIGNATURE_INFO;
+
+typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR;
+
+#define CKF_NEXT_OTP 0x00000001UL
+#define CKF_EXCLUDE_TIME 0x00000002UL
+#define CKF_EXCLUDE_COUNTER 0x00000004UL
+#define CKF_EXCLUDE_CHALLENGE 0x00000008UL
+#define CKF_EXCLUDE_PIN 0x00000010UL
+#define CKF_USER_FRIENDLY_OTP 0x00000020UL
+
+/* KIP is new in v2.40 */
+typedef struct CK_KIP_PARAMS {
+ CK_MECHANISM_PTR pMechanism;
+ CK_OBJECT_HANDLE hKey;
+ CK_BYTE_PTR pSeed;
+ CK_ULONG ulSeedLen;
+} CK_KIP_PARAMS;
+
+typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR;
+
+/* DSA Param Gen is new for v2.40 */
+typedef struct CK_DSA_PARAMETER_GEN_PARAM {
+ CK_MECHANISM_TYPE hash;
+ CK_BYTE_PTR pSeed;
+ CK_ULONG ulSeedLen;
+ CK_ULONG ulIndex;
+} CK_DSA_PARAMETER_GEN_PARAM;
+
+typedef CK_DSA_PARAMETER_GEN_PARAM CK_PTR CK_DSA_PARAMETER_GEN_PARAM_PTR;
+
+/* XXXX_AES_KEY_WRAP is new for v2.40 */
+typedef struct CK_ECDH_AES_KEY_WRAP_PARAMS {
+ CK_ULONG ulAESKeyBits;
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+} CK_ECDH_AES_KEY_WRAP_PARAMS;
+
+typedef CK_ECDH_AES_KEY_WRAP_PARAMS CK_PTR CK_ECDH_AES_KEY_WRAP_PARAMS_PTR;
+
+typedef struct CK_RSA_AES_KEY_WRAP_PARAMS {
+ CK_ULONG ulAESKeyBits;
+ CK_RSA_PKCS_OAEP_PARAMS_PTR pOAEPParams;
+} CK_RSA_AES_KEY_WRAP_PARAMS;
+
+typedef CK_RSA_AES_KEY_WRAP_PARAMS CK_PTR CK_RSA_AES_KEY_WRAP_PARAMS_PTR;
+
+/* GOSTR3410 is new for v2.40 */
+typedef struct CK_GOSTR3410_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pUKM;
+ CK_ULONG ulUKMLen;
+} CK_GOSTR3410_DERIVE_PARAMS;
+
+typedef CK_GOSTR3410_DERIVE_PARAMS CK_PTR CK_GOSTR3410_DERIVE_PARAMS_PTR;
+
+typedef struct CK_GOSTR3410_KEY_WRAP_PARAMS {
+ CK_BYTE_PTR pWrapOID;
+ CK_ULONG ulWrapOIDLen;
+ CK_BYTE_PTR pUKM;
+ CK_ULONG ulUKMLen;
+ CK_OBJECT_HANDLE hKey;
+} CK_GOSTR3410_KEY_WRAP_PARAMS;
+
+typedef CK_GOSTR3410_KEY_WRAP_PARAMS CK_PTR CK_GOSTR3410_KEY_WRAP_PARAMS_PTR;
+
+/* EDDSA and XEDDSA are new for v3.0 */
+typedef struct CK_EDDSA_PARAMS {
+ CK_BBOOL phFlag;
+ CK_ULONG ulContextDataLen;
+ CK_BYTE_PTR pContextData;
+} CK_EDDSA_PARAMS;
+typedef CK_ULONG CK_XEDDSA_HASH_TYPE;
+typedef CK_XEDDSA_HASH_TYPE CK_PTR CK_XEDDSA_HASH_TYPE_PTR;
+
+typedef struct CK_XEDDSA_PARAMS {
+ CK_XEDDSA_HASH_TYPE hash;
+} CK_XEDDSA_PARAMS;
+typedef CK_XEDDSA_PARAMS CK_PTR CK_XEDDSA_PARAMS_PTR;
+
+/* X3DH and Ratchet are new in v3.0 */
+typedef CK_ULONG CK_X3DH_KDF_TYPE;
+typedef CK_X3DH_KDF_TYPE CK_PTR CK_X3DH_KDF_TYPE_PTR;
+
+typedef struct CK_X3DH_INITIATE_PARAMS {
+ CK_X3DH_KDF_TYPE kdf;
+ CK_OBJECT_HANDLE pPeer_identity;
+ CK_OBJECT_HANDLE pPeer_prekey;
+ CK_BYTE_PTR pPrekey_signature;
+ CK_BYTE_PTR pOnetime_key;
+ CK_OBJECT_HANDLE pOwn_identity;
+ CK_OBJECT_HANDLE pOwn_ephemeral;
+} CK_X3DH_INITIATE_PARAMS;
+
+typedef struct CK_X3DH_RESPOND_PARAMS {
+ CK_X3DH_KDF_TYPE kdf;
+ CK_BYTE_PTR pIdentity_id;
+ CK_BYTE_PTR pPrekey_id;
+ CK_BYTE_PTR pOnetime_id;
+ CK_OBJECT_HANDLE pInitiator_identity;
+ CK_BYTE_PTR pInitiator_ephemeral;
+} CK_X3DH_RESPOND_PARAMS;
+
+typedef CK_ULONG CK_X2RATCHET_KDF_TYPE;
+typedef CK_X2RATCHET_KDF_TYPE CK_PTR CK_X2RATCHET_KDF_TYPE_PTR;
+
+typedef struct CK_X2RATCHET_INITIALIZE_PARAMS {
+ CK_BYTE_PTR sk;
+ CK_OBJECT_HANDLE peer_public_prekey;
+ CK_OBJECT_HANDLE peer_public_identity;
+ CK_OBJECT_HANDLE own_public_identity;
+ CK_BBOOL bEncryptedHeader;
+ CK_ULONG eCurve;
+ CK_MECHANISM_TYPE aeadMechanism;
+ CK_X2RATCHET_KDF_TYPE kdfMechanism;
+} CK_X2RATCHET_INITIALIZE_PARAMS;
+
+typedef CK_X2RATCHET_INITIALIZE_PARAMS
+ CK_PTR CK_X2RATCHET_INITIALIZE_PARAMS_PTR;
+
+typedef struct CK_X2RATCHET_RESPOND_PARAMS {
+ CK_BYTE_PTR sk;
+ CK_OBJECT_HANDLE own_prekey;
+ CK_OBJECT_HANDLE initiator_identity;
+ CK_OBJECT_HANDLE own_public_identity;
+ CK_BBOOL bEncryptedHeader;
+ CK_ULONG eCurve;
+ CK_MECHANISM_TYPE aeadMechanism;
+ CK_X2RATCHET_KDF_TYPE kdfMechanism;
+} CK_X2RATCHET_RESPOND_PARAMS;
+typedef CK_X2RATCHET_RESPOND_PARAMS
+ CK_PTR CK_X2RATCHET_RESPOND_PARAMS_PTR;
+
+/* NSS Specific defines */
+/* stuff that for historic reasons is in this header file but should have
+ * been in pkcs11n.h */
+#define CKK_INVALID_KEY_TYPE 0xffffffffUL
+
+#include "pkcs11n.h"
+
+/* undo packing */
+#include "pkcs11u.h"
+
+#endif
diff --git a/security/nss/lib/util/pkcs11u.h b/security/nss/lib/util/pkcs11u.h
new file mode 100644
index 0000000000..64ec2fdb5c
--- /dev/null
+++ b/security/nss/lib/util/pkcs11u.h
@@ -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/. */
+/*
+ * Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document
+ * is granted provided that it is identified as "RSA Security Inc. Public-Key
+ * Cryptography Standards (PKCS)" in all material mentioning or referencing
+ * this document.
+ */
+/*
+ * reset any packing set by pkcs11p.h
+ */
+
+#if defined(_WIN32) || defined(_WINDOWS)
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wpragma-pack"
+#endif
+#ifdef _MSC_VER
+#pragma warning(disable : 4103)
+#endif
+#pragma pack(pop, cryptoki)
+#endif
diff --git a/security/nss/lib/util/pkcs11uri.c b/security/nss/lib/util/pkcs11uri.c
new file mode 100644
index 0000000000..e0c4077a3d
--- /dev/null
+++ b/security/nss/lib/util/pkcs11uri.c
@@ -0,0 +1,867 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 "pkcs11.h"
+#include "pkcs11uri.h"
+#include "plarena.h"
+#include "prprf.h"
+#include "secport.h"
+
+/* Character sets used in the ABNF rules in RFC7512. */
+#define PK11URI_DIGIT "0123456789"
+#define PK11URI_ALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define PK11URI_HEXDIG PK11URI_DIGIT "abcdefABCDEF"
+#define PK11URI_UNRESERVED PK11URI_ALPHA PK11URI_DIGIT "-._~"
+#define PK11URI_RES_AVAIL ":[]@!$'()*+,="
+#define PK11URI_PATH_RES_AVAIL PK11URI_RES_AVAIL "&"
+#define PK11URI_QUERY_RES_AVAIL PK11URI_RES_AVAIL "/?|"
+#define PK11URI_ATTR_NM_CHAR PK11URI_ALPHA PK11URI_DIGIT "-_"
+#define PK11URI_PCHAR PK11URI_UNRESERVED PK11URI_PATH_RES_AVAIL
+#define PK11URI_QCHAR PK11URI_UNRESERVED PK11URI_QUERY_RES_AVAIL
+
+/* Path attributes defined in RFC7512. */
+static const char *pattr_names[] = {
+ PK11URI_PATTR_TOKEN,
+ PK11URI_PATTR_MANUFACTURER,
+ PK11URI_PATTR_SERIAL,
+ PK11URI_PATTR_MODEL,
+ PK11URI_PATTR_LIBRARY_MANUFACTURER,
+ PK11URI_PATTR_LIBRARY_DESCRIPTION,
+ PK11URI_PATTR_LIBRARY_VERSION,
+ PK11URI_PATTR_OBJECT,
+ PK11URI_PATTR_TYPE,
+ PK11URI_PATTR_ID,
+ PK11URI_PATTR_SLOT_MANUFACTURER,
+ PK11URI_PATTR_SLOT_DESCRIPTION,
+ PK11URI_PATTR_SLOT_ID
+};
+
+/* Query attributes defined in RFC7512. */
+static const char *qattr_names[] = {
+ PK11URI_QATTR_PIN_SOURCE,
+ PK11URI_QATTR_PIN_VALUE,
+ PK11URI_QATTR_MODULE_NAME,
+ PK11URI_QATTR_MODULE_PATH
+};
+
+struct PK11URIBufferStr {
+ PLArenaPool *arena;
+ unsigned char *data;
+ size_t size;
+ size_t allocated;
+};
+typedef struct PK11URIBufferStr PK11URIBuffer;
+
+struct PK11URIAttributeListEntryStr {
+ char *name;
+ SECItem value;
+};
+typedef struct PK11URIAttributeListEntryStr PK11URIAttributeListEntry;
+
+struct PK11URIAttributeListStr {
+ PLArenaPool *arena;
+ PK11URIAttributeListEntry *attrs;
+ size_t num_attrs;
+};
+typedef struct PK11URIAttributeListStr PK11URIAttributeList;
+
+struct PK11URIStr {
+ PLArenaPool *arena;
+
+ PK11URIAttributeList pattrs;
+ PK11URIAttributeList vpattrs;
+
+ PK11URIAttributeList qattrs;
+ PK11URIAttributeList vqattrs;
+};
+
+#define PK11URI_ARENA_SIZE 1024
+
+typedef int (*PK11URIAttributeCompareNameFunc)(const char *a, const char *b);
+
+/* This belongs in secport.h */
+#define PORT_ArenaGrowArray(poolp, oldptr, type, oldnum, newnum) \
+ (type *)PORT_ArenaGrow((poolp), (oldptr), \
+ (oldnum) * sizeof(type), (newnum) * sizeof(type))
+#define PORT_ReallocArray(oldptr, type, newnum) \
+ (type *)PORT_Realloc((oldptr), (newnum) * sizeof(type))
+
+/* Functions for resizable buffer. */
+static SECStatus
+pk11uri_AppendBuffer(PK11URIBuffer *buffer, const unsigned char *data,
+ size_t size)
+{
+ /* Check overflow. */
+ if (buffer->size + size < buffer->size)
+ return SECFailure;
+
+ if (buffer->size + size > buffer->allocated) {
+ size_t allocated = buffer->allocated * 2 + size;
+ if (allocated < buffer->allocated)
+ return SECFailure;
+ if (buffer->arena)
+ buffer->data = PORT_ArenaGrow(buffer->arena, buffer->data,
+ buffer->allocated, allocated);
+ else
+ buffer->data = PORT_Realloc(buffer->data, allocated);
+ if (buffer->data == NULL)
+ return SECFailure;
+ buffer->allocated = allocated;
+ }
+
+ memcpy(&buffer->data[buffer->size], data, size);
+ buffer->size += size;
+
+ return SECSuccess;
+}
+
+static void
+pk11uri_InitBuffer(PK11URIBuffer *buffer, PLArenaPool *arena)
+{
+ memset(buffer, 0, sizeof(PK11URIBuffer));
+ buffer->arena = arena;
+}
+
+static void
+pk11uri_DestroyBuffer(PK11URIBuffer *buffer)
+{
+ if (buffer->arena == NULL) {
+ PORT_Free(buffer->data);
+ }
+}
+
+/* URI encoding functions. */
+static char *
+pk11uri_Escape(PLArenaPool *arena, const unsigned char *value, size_t length,
+ const char *available)
+{
+ PK11URIBuffer buffer;
+ const unsigned char *p;
+ unsigned char buf[4];
+ char *result = NULL;
+ SECStatus ret;
+
+ pk11uri_InitBuffer(&buffer, arena);
+
+ for (p = value; p < value + length; p++) {
+ if (strchr(available, *p) == NULL) {
+ if (PR_snprintf((char *)buf, sizeof(buf), "%%%02X", *p) == (PRUint32)-1) {
+ goto fail;
+ }
+ ret = pk11uri_AppendBuffer(&buffer, buf, 3);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+ } else {
+ ret = pk11uri_AppendBuffer(&buffer, p, 1);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+ }
+ }
+ buf[0] = '\0';
+ ret = pk11uri_AppendBuffer(&buffer, buf, 1);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+
+ /* Steal the memory allocated in buffer. */
+ result = (char *)buffer.data;
+ buffer.data = NULL;
+
+fail:
+ pk11uri_DestroyBuffer(&buffer);
+
+ return result;
+}
+
+static unsigned char *
+pk11uri_Unescape(PLArenaPool *arena, const char *value, size_t *length)
+{
+ PK11URIBuffer buffer;
+ const char *p;
+ unsigned char buf[1];
+ unsigned char *result = NULL;
+ SECStatus ret;
+
+ pk11uri_InitBuffer(&buffer, arena);
+
+ for (p = value; p < value + *length; p++) {
+ if (*p == '%') {
+ int c;
+ size_t i;
+
+ p++;
+ for (c = 0, i = 0; i < 2; i++) {
+ int h = *(p + i);
+ if ('0' <= h && h <= '9') {
+ c = (c << 4) | (h - '0');
+ } else if ('a' <= h && h <= 'f') {
+ c = (c << 4) | (h - 'a' + 10);
+ } else if ('A' <= h && h <= 'F') {
+ c = (c << 4) | (h - 'A' + 10);
+ } else {
+ break;
+ }
+ }
+ if (i != 2) {
+ goto fail;
+ }
+ p++;
+ buf[0] = c;
+ } else {
+ buf[0] = *p;
+ }
+ ret = pk11uri_AppendBuffer(&buffer, buf, 1);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+ }
+ *length = buffer.size;
+ buf[0] = '\0';
+ ret = pk11uri_AppendBuffer(&buffer, buf, 1);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+
+ result = buffer.data;
+ buffer.data = NULL;
+
+fail:
+ pk11uri_DestroyBuffer(&buffer);
+
+ return result;
+}
+
+/* Functions for manipulating attributes array. */
+
+/* Compare two attribute names by the array index in attr_names. Both
+ * attribute names must be present in attr_names, otherwise it is a
+ * programming error. */
+static int
+pk11uri_CompareByPosition(const char *a, const char *b,
+ const char **attr_names, size_t num_attr_names)
+{
+ size_t i, j;
+
+ for (i = 0; i < num_attr_names; i++) {
+ if (strcmp(a, attr_names[i]) == 0) {
+ break;
+ }
+ }
+ PR_ASSERT(i < num_attr_names);
+
+ for (j = 0; j < num_attr_names; j++) {
+ if (strcmp(b, attr_names[j]) == 0) {
+ break;
+ }
+ }
+ PR_ASSERT(j < num_attr_names);
+
+ return i - j;
+}
+
+/* Those pk11uri_Compare{Path,Query}AttributeName functions are used
+ * to reorder attributes when inserting. */
+static int
+pk11uri_ComparePathAttributeName(const char *a, const char *b)
+{
+ return pk11uri_CompareByPosition(a, b, pattr_names, PR_ARRAY_SIZE(pattr_names));
+}
+
+static int
+pk11uri_CompareQueryAttributeName(const char *a, const char *b)
+{
+ return pk11uri_CompareByPosition(a, b, qattr_names, PR_ARRAY_SIZE(qattr_names));
+}
+
+static SECStatus
+pk11uri_InsertToAttributeList(PK11URIAttributeList *attrs,
+ char *name, unsigned char *value, size_t size,
+ PK11URIAttributeCompareNameFunc compare_name,
+ PRBool allow_duplicate)
+{
+ size_t i;
+
+ if (attrs->arena) {
+ attrs->attrs = PORT_ArenaGrowArray(attrs->arena, attrs->attrs,
+ PK11URIAttributeListEntry,
+ attrs->num_attrs,
+ attrs->num_attrs + 1);
+ } else {
+ attrs->attrs = PORT_ReallocArray(attrs->attrs,
+ PK11URIAttributeListEntry,
+ attrs->num_attrs + 1);
+ }
+ if (attrs->attrs == NULL) {
+ return SECFailure;
+ }
+
+ for (i = 0; i < attrs->num_attrs; i++) {
+ if (!allow_duplicate && strcmp(name, attrs->attrs[i].name) == 0) {
+ return SECFailure;
+ }
+ if (compare_name(name, attrs->attrs[i].name) < 0) {
+ memmove(&attrs->attrs[i + 1], &attrs->attrs[i],
+ sizeof(PK11URIAttributeListEntry) * (attrs->num_attrs - i));
+ break;
+ }
+ }
+
+ attrs->attrs[i].name = name;
+ attrs->attrs[i].value.type = siBuffer;
+ attrs->attrs[i].value.data = value;
+ attrs->attrs[i].value.len = size;
+
+ attrs->num_attrs++;
+
+ return SECSuccess;
+}
+
+static SECStatus
+pk11uri_InsertToAttributeListEscaped(PK11URIAttributeList *attrs,
+ const char *name, size_t name_size,
+ const char *value, size_t value_size,
+ PK11URIAttributeCompareNameFunc compare_name,
+ PRBool allow_duplicate)
+{
+ char *name_copy = NULL;
+ unsigned char *value_copy = NULL;
+ SECStatus ret;
+
+ if (attrs->arena) {
+ name_copy = PORT_ArenaNewArray(attrs->arena, char, name_size + 1);
+ } else {
+ name_copy = PORT_Alloc(name_size + 1);
+ }
+ if (name_copy == NULL) {
+ goto fail;
+ }
+ memcpy(name_copy, name, name_size);
+ name_copy[name_size] = '\0';
+
+ value_copy = pk11uri_Unescape(attrs->arena, value, &value_size);
+ if (value_copy == NULL) {
+ goto fail;
+ }
+
+ ret = pk11uri_InsertToAttributeList(attrs, name_copy, value_copy, value_size,
+ compare_name, allow_duplicate);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+
+ return ret;
+
+fail:
+ if (attrs->arena == NULL) {
+ PORT_Free(name_copy);
+ PORT_Free(value_copy);
+ }
+
+ return SECFailure;
+}
+
+static void
+pk11uri_InitAttributeList(PK11URIAttributeList *attrs, PLArenaPool *arena)
+{
+ memset(attrs, 0, sizeof(PK11URIAttributeList));
+ attrs->arena = arena;
+}
+
+static void
+pk11uri_DestroyAttributeList(PK11URIAttributeList *attrs)
+{
+ if (attrs->arena == NULL) {
+ size_t i;
+
+ for (i = 0; i < attrs->num_attrs; i++) {
+ PORT_Free(attrs->attrs[i].name);
+ PORT_Free(attrs->attrs[i].value.data);
+ }
+ PORT_Free(attrs->attrs);
+ }
+}
+
+static SECStatus
+pk11uri_AppendAttributeListToBuffer(PK11URIBuffer *buffer,
+ PK11URIAttributeList *attrs,
+ int separator,
+ const char *unescaped)
+{
+ size_t i;
+ SECStatus ret;
+
+ for (i = 0; i < attrs->num_attrs; i++) {
+ unsigned char sep[1];
+ char *escaped;
+ PK11URIAttributeListEntry *attr = &attrs->attrs[i];
+
+ if (i > 0) {
+ sep[0] = separator;
+ ret = pk11uri_AppendBuffer(buffer, sep, 1);
+ if (ret != SECSuccess) {
+ return ret;
+ }
+ }
+
+ ret = pk11uri_AppendBuffer(buffer, (unsigned char *)attr->name,
+ strlen(attr->name));
+ if (ret != SECSuccess) {
+ return ret;
+ }
+
+ sep[0] = '=';
+ ret = pk11uri_AppendBuffer(buffer, sep, 1);
+ if (ret != SECSuccess) {
+ return ret;
+ }
+
+ escaped = pk11uri_Escape(buffer->arena, attr->value.data, attr->value.len,
+ unescaped);
+ if (escaped == NULL) {
+ return ret;
+ }
+ ret = pk11uri_AppendBuffer(buffer, (unsigned char *)escaped,
+ strlen(escaped));
+ if (buffer->arena == NULL) {
+ PORT_Free(escaped);
+ }
+ if (ret != SECSuccess) {
+ return ret;
+ }
+ }
+
+ return SECSuccess;
+}
+
+/* Creation of PK11URI object. */
+static PK11URI *
+pk11uri_AllocURI(void)
+{
+ PLArenaPool *arena;
+ PK11URI *result;
+
+ arena = PORT_NewArena(PK11URI_ARENA_SIZE);
+ if (arena == NULL) {
+ return NULL;
+ }
+
+ result = PORT_ArenaZAlloc(arena, sizeof(PK11URI));
+ if (result == NULL) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return NULL;
+ }
+
+ result->arena = arena;
+ pk11uri_InitAttributeList(&result->pattrs, arena);
+ pk11uri_InitAttributeList(&result->vpattrs, arena);
+ pk11uri_InitAttributeList(&result->qattrs, arena);
+ pk11uri_InitAttributeList(&result->vqattrs, arena);
+
+ return result;
+}
+
+static SECStatus
+pk11uri_InsertAttributes(PK11URIAttributeList *dest_attrs,
+ PK11URIAttributeList *dest_vattrs,
+ const PK11URIAttribute *attrs,
+ size_t num_attrs,
+ const char **attr_names,
+ size_t num_attr_names,
+ PK11URIAttributeCompareNameFunc compare_name,
+ PRBool allow_duplicate,
+ PRBool vendor_allow_duplicate)
+{
+ SECStatus ret;
+ size_t i;
+
+ for (i = 0; i < num_attrs; i++) {
+ char *name, *value;
+ const char *p;
+ size_t j;
+
+ p = attrs[i].name;
+
+ /* The attribute must not be empty. */
+ if (*p == '\0') {
+ return SECFailure;
+ }
+
+ /* Check that the name doesn't contain invalid character. */
+ for (; *p != '\0'; p++) {
+ if (strchr(PK11URI_ATTR_NM_CHAR, *p) == NULL) {
+ return SECFailure;
+ }
+ }
+
+ name = PORT_ArenaStrdup(dest_attrs->arena, attrs[i].name);
+ if (name == NULL) {
+ return SECFailure;
+ }
+
+ value = PORT_ArenaStrdup(dest_attrs->arena, attrs[i].value);
+ if (value == NULL) {
+ return SECFailure;
+ }
+
+ for (j = 0; j < num_attr_names; j++) {
+ if (strcmp(name, attr_names[j]) == 0) {
+ break;
+ }
+ }
+ if (j < num_attr_names) {
+ /* Named attribute. */
+ ret = pk11uri_InsertToAttributeList(dest_attrs,
+ name,
+ (unsigned char *)value,
+ strlen(value),
+ compare_name,
+ allow_duplicate);
+ if (ret != SECSuccess) {
+ return ret;
+ }
+ } else {
+ /* Vendor attribute. */
+ ret = pk11uri_InsertToAttributeList(dest_vattrs,
+ name,
+ (unsigned char *)value,
+ strlen(value),
+ strcmp,
+ vendor_allow_duplicate);
+ if (ret != SECSuccess) {
+ return ret;
+ }
+ }
+ }
+
+ return SECSuccess;
+}
+
+PK11URI *
+PK11URI_CreateURI(const PK11URIAttribute *pattrs,
+ size_t num_pattrs,
+ const PK11URIAttribute *qattrs,
+ size_t num_qattrs)
+{
+ PK11URI *result;
+ SECStatus ret;
+
+ result = pk11uri_AllocURI();
+
+ ret = pk11uri_InsertAttributes(&result->pattrs, &result->vpattrs,
+ pattrs, num_pattrs,
+ pattr_names, PR_ARRAY_SIZE(pattr_names),
+ pk11uri_ComparePathAttributeName,
+ PR_FALSE, PR_FALSE);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+
+ ret = pk11uri_InsertAttributes(&result->qattrs, &result->vqattrs,
+ qattrs, num_qattrs,
+ qattr_names, PR_ARRAY_SIZE(qattr_names),
+ pk11uri_CompareQueryAttributeName,
+ PR_FALSE, PR_TRUE);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+
+ return result;
+
+fail:
+ PK11URI_DestroyURI(result);
+
+ return NULL;
+}
+
+/* Parsing. */
+static SECStatus
+pk11uri_ParseAttributes(const char **string,
+ const char *stop_chars,
+ int separator,
+ const char *accept_chars,
+ const char **attr_names, size_t num_attr_names,
+ PK11URIAttributeList *attrs,
+ PK11URIAttributeList *vattrs,
+ PK11URIAttributeCompareNameFunc compare_name,
+ PRBool allow_duplicate,
+ PRBool vendor_allow_duplicate)
+{
+ const char *p = *string;
+
+ for (; *p != '\0'; p++) {
+ const char *name_start, *name_end, *value_start, *value_end;
+ size_t name_length, value_length, i;
+ SECStatus ret;
+
+ if (strchr(stop_chars, *p) != NULL) {
+ break;
+ }
+ for (name_start = p; *p != '=' && *p != '\0'; p++) {
+ if (strchr(PK11URI_ATTR_NM_CHAR, *p) != NULL)
+ continue;
+
+ return SECFailure;
+ }
+ if (*p == '\0') {
+ return SECFailure;
+ }
+ name_end = p++;
+
+ /* The attribute name must not be empty. */
+ if (name_end == name_start) {
+ return SECFailure;
+ }
+
+ for (value_start = p; *p != separator && *p != '\0'; p++) {
+ if (strchr(stop_chars, *p) != NULL) {
+ break;
+ }
+ if (strchr(accept_chars, *p) != NULL) {
+ continue;
+ }
+ if (*p == '%') {
+ const char ch2 = *++p;
+ if (strchr(PK11URI_HEXDIG, ch2) != NULL) {
+ const char ch3 = *++p;
+ if (strchr(PK11URI_HEXDIG, ch3) != NULL)
+ continue;
+ }
+ }
+
+ return SECFailure;
+ }
+ value_end = p;
+
+ name_length = name_end - name_start;
+ value_length = value_end - value_start;
+
+ for (i = 0; i < num_attr_names; i++) {
+ if (name_length == strlen(attr_names[i]) &&
+ memcmp(name_start, attr_names[i], name_length) == 0) {
+ break;
+ }
+ }
+ if (i < num_attr_names) {
+ /* Named attribute. */
+ ret = pk11uri_InsertToAttributeListEscaped(attrs,
+ name_start, name_length,
+ value_start, value_length,
+ compare_name,
+ allow_duplicate);
+ if (ret != SECSuccess) {
+ return ret;
+ }
+ } else {
+ /* Vendor attribute. */
+ ret = pk11uri_InsertToAttributeListEscaped(vattrs,
+ name_start, name_length,
+ value_start, value_length,
+ strcmp,
+ vendor_allow_duplicate);
+ if (ret != SECSuccess) {
+ return ret;
+ }
+ }
+
+ if (*p == '?' || *p == '\0') {
+ break;
+ }
+ }
+
+ *string = p;
+ return SECSuccess;
+}
+
+PK11URI *
+PK11URI_ParseURI(const char *string)
+{
+ PK11URI *result;
+ const char *p = string;
+ SECStatus ret;
+
+ if (PORT_Strncasecmp("pkcs11:", p, 7) != 0) {
+ return NULL;
+ }
+ p += 7;
+
+ result = pk11uri_AllocURI();
+ if (result == NULL) {
+ return NULL;
+ }
+
+ /* Parse the path component and its attributes. */
+ ret = pk11uri_ParseAttributes(&p, "?", ';', PK11URI_PCHAR,
+ pattr_names, PR_ARRAY_SIZE(pattr_names),
+ &result->pattrs, &result->vpattrs,
+ pk11uri_ComparePathAttributeName,
+ PR_FALSE, PR_FALSE);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+
+ /* Parse the query component and its attributes. */
+ if (*p == '?') {
+ p++;
+ ret = pk11uri_ParseAttributes(&p, "", '&', PK11URI_QCHAR,
+ qattr_names, PR_ARRAY_SIZE(qattr_names),
+ &result->qattrs, &result->vqattrs,
+ pk11uri_CompareQueryAttributeName,
+ PR_FALSE, PR_TRUE);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+ }
+
+ return result;
+
+fail:
+ PK11URI_DestroyURI(result);
+
+ return NULL;
+}
+
+/* Formatting. */
+char *
+PK11URI_FormatURI(PLArenaPool *arena, PK11URI *uri)
+{
+ PK11URIBuffer buffer;
+ SECStatus ret;
+ char *result = NULL;
+
+ pk11uri_InitBuffer(&buffer, arena);
+
+ ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)"pkcs11:", 7);
+ if (ret != SECSuccess)
+ goto fail;
+
+ ret = pk11uri_AppendAttributeListToBuffer(&buffer, &uri->pattrs, ';', PK11URI_PCHAR);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+
+ if (uri->pattrs.num_attrs > 0 && uri->vpattrs.num_attrs > 0) {
+ ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)";", 1);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+ }
+
+ ret = pk11uri_AppendAttributeListToBuffer(&buffer, &uri->vpattrs, ';',
+ PK11URI_PCHAR);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+
+ if (uri->qattrs.num_attrs > 0 || uri->vqattrs.num_attrs > 0) {
+ ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)"?", 1);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+ }
+
+ ret = pk11uri_AppendAttributeListToBuffer(&buffer, &uri->qattrs, '&', PK11URI_QCHAR);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+
+ if (uri->qattrs.num_attrs > 0 && uri->vqattrs.num_attrs > 0) {
+ ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)"&", 1);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+ }
+
+ ret = pk11uri_AppendAttributeListToBuffer(&buffer, &uri->vqattrs, '&',
+ PK11URI_QCHAR);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+
+ ret = pk11uri_AppendBuffer(&buffer, (unsigned char *)"\0", 1);
+ if (ret != SECSuccess) {
+ goto fail;
+ }
+
+ result = (char *)buffer.data;
+ buffer.data = NULL;
+
+fail:
+ pk11uri_DestroyBuffer(&buffer);
+
+ return result;
+}
+
+/* Deallocating. */
+void
+PK11URI_DestroyURI(PK11URI *uri)
+{
+ pk11uri_DestroyAttributeList(&uri->pattrs);
+ pk11uri_DestroyAttributeList(&uri->vpattrs);
+ pk11uri_DestroyAttributeList(&uri->qattrs);
+ pk11uri_DestroyAttributeList(&uri->vqattrs);
+ PORT_FreeArena(uri->arena, PR_FALSE);
+}
+
+/* Accessors. */
+static const SECItem *
+pk11uri_GetAttribute(PK11URIAttributeList *attrs,
+ PK11URIAttributeList *vattrs,
+ const char *name)
+{
+ size_t i;
+
+ for (i = 0; i < attrs->num_attrs; i++) {
+ if (strcmp(name, attrs->attrs[i].name) == 0) {
+ return &attrs->attrs[i].value;
+ }
+ }
+
+ for (i = 0; i < vattrs->num_attrs; i++) {
+ if (strcmp(name, vattrs->attrs[i].name) == 0) {
+ return &vattrs->attrs[i].value;
+ }
+ }
+
+ return NULL;
+}
+
+const SECItem *
+PK11URI_GetPathAttributeItem(PK11URI *uri, const char *name)
+{
+ return pk11uri_GetAttribute(&uri->pattrs, &uri->vpattrs, name);
+}
+
+const char *
+PK11URI_GetPathAttribute(PK11URI *uri, const char *name)
+{
+ const SECItem *value;
+
+ value = PK11URI_GetPathAttributeItem(uri, name);
+ if (!value) {
+ return NULL;
+ }
+
+ return (const char *)value->data;
+}
+
+const SECItem *
+PK11URI_GetQueryAttributeItem(PK11URI *uri, const char *name)
+{
+ return pk11uri_GetAttribute(&uri->qattrs, &uri->vqattrs, name);
+}
+
+const char *
+PK11URI_GetQueryAttribute(PK11URI *uri, const char *name)
+{
+ const SECItem *value;
+
+ value = PK11URI_GetQueryAttributeItem(uri, name);
+ if (!value) {
+ return NULL;
+ }
+
+ return (const char *)value->data;
+}
diff --git a/security/nss/lib/util/pkcs11uri.h b/security/nss/lib/util/pkcs11uri.h
new file mode 100644
index 0000000000..84fb69f6fd
--- /dev/null
+++ b/security/nss/lib/util/pkcs11uri.h
@@ -0,0 +1,80 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 _PKCS11URI_H_
+#define _PKCS11URI_H_ 1
+
+#include "seccomon.h"
+
+/* Path attributes defined in RFC7512. */
+#define PK11URI_PATTR_TOKEN "token"
+#define PK11URI_PATTR_MANUFACTURER "manufacturer"
+#define PK11URI_PATTR_SERIAL "serial"
+#define PK11URI_PATTR_MODEL "model"
+#define PK11URI_PATTR_LIBRARY_MANUFACTURER "library-manufacturer"
+#define PK11URI_PATTR_LIBRARY_DESCRIPTION "library-description"
+#define PK11URI_PATTR_LIBRARY_VERSION "library-version"
+#define PK11URI_PATTR_OBJECT "object"
+#define PK11URI_PATTR_TYPE "type"
+#define PK11URI_PATTR_ID "id"
+#define PK11URI_PATTR_SLOT_MANUFACTURER "slot-manufacturer"
+#define PK11URI_PATTR_SLOT_DESCRIPTION "slot-description"
+#define PK11URI_PATTR_SLOT_ID "slot-id"
+
+/* Query attributes defined in RFC7512. */
+#define PK11URI_QATTR_PIN_SOURCE "pin-source"
+#define PK11URI_QATTR_PIN_VALUE "pin-value"
+#define PK11URI_QATTR_MODULE_NAME "module-name"
+#define PK11URI_QATTR_MODULE_PATH "module-path"
+
+SEC_BEGIN_PROTOS
+
+/* A PK11URI object is an immutable structure that holds path and
+ * query attributes of a PKCS#11 URI. */
+struct PK11URIStr;
+typedef struct PK11URIStr PK11URI;
+
+struct PK11URIAttributeStr {
+ const char *name;
+ const char *value;
+};
+typedef struct PK11URIAttributeStr PK11URIAttribute;
+
+/* Create a new PK11URI object from a set of attributes. */
+extern PK11URI *PK11URI_CreateURI(const PK11URIAttribute *pattrs,
+ size_t num_pattrs,
+ const PK11URIAttribute *qattrs,
+ size_t num_qattrs);
+
+/* Parse PKCS#11 URI and return a new PK11URI object. */
+extern PK11URI *PK11URI_ParseURI(const char *string);
+
+/* Format a PK11URI object to a string. */
+extern char *PK11URI_FormatURI(PLArenaPool *arena, PK11URI *uri);
+
+/* Destroy a PK11URI object. */
+extern void PK11URI_DestroyURI(PK11URI *uri);
+
+/* Retrieve a path attribute with the given name. This function can be used only
+ * when we can assume that the attribute value is a string (such as "label" or
+ * "type"). If it can be a binary blob (such as "id"), use
+ * PK11URI_GetPathAttributeItem.
+ */
+extern const char *PK11URI_GetPathAttribute(PK11URI *uri, const char *name);
+
+/* Retrieve a query attribute with the given name. This function can be used
+ * only when we can assume that the attribute value is a string (such as
+ * "module-name"). If it can be a binary blob, use
+ * PK11URI_GetQueryAttributeItem.*/
+extern const char *PK11URI_GetQueryAttribute(PK11URI *uri, const char *name);
+
+/* Retrieve a path attribute with the given name as a SECItem. */
+extern const SECItem *PK11URI_GetPathAttributeItem(PK11URI *uri, const char *name);
+
+/* Retrieve a query attribute with the given name as a SECItem. */
+extern const SECItem *PK11URI_GetQueryAttributeItem(PK11URI *uri, const char *name);
+
+SEC_END_PROTOS
+
+#endif /* _PKCS11URI_H_ */
diff --git a/security/nss/lib/util/pkcs1sig.c b/security/nss/lib/util/pkcs1sig.c
new file mode 100644
index 0000000000..68588c7f80
--- /dev/null
+++ b/security/nss/lib/util/pkcs1sig.c
@@ -0,0 +1,158 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "pkcs1sig.h"
+#include "hasht.h"
+#include "secerr.h"
+#include "secasn1t.h"
+#include "secoid.h"
+
+typedef struct pkcs1PrefixStr pkcs1Prefix;
+struct pkcs1PrefixStr {
+ unsigned int len;
+ PRUint8 *data;
+};
+
+/* The value for SGN_PKCS1_DIGESTINFO_MAX_PREFIX_LEN_EXCLUDING_OID is based on
+ * the possible prefix encodings as explained below.
+ */
+#define MAX_PREFIX_LEN_EXCLUDING_OID 10
+
+static SECStatus
+encodePrefix(const SECOidData *hashOid, unsigned int digestLen,
+ pkcs1Prefix *prefix, PRBool withParams)
+{
+ /* with params coding is:
+ * Sequence (2 bytes) {
+ * Sequence (2 bytes) {
+ * Oid (2 bytes) {
+ * Oid value (derOid->oid.len)
+ * }
+ * NULL (2 bytes)
+ * }
+ * OCTECT (2 bytes);
+ *
+ * without params coding is:
+ * Sequence (2 bytes) {
+ * Sequence (2 bytes) {
+ * Oid (2 bytes) {
+ * Oid value (derOid->oid.len)
+ * }
+ * }
+ * OCTECT (2 bytes);
+ */
+
+ unsigned int innerSeqLen = 2 + hashOid->oid.len;
+ unsigned int outerSeqLen = 2 + innerSeqLen + 2 + digestLen;
+ unsigned int extra = 0;
+
+ if (withParams) {
+ innerSeqLen += 2;
+ outerSeqLen += 2;
+ extra = 2;
+ }
+
+ if (innerSeqLen >= 128 ||
+ outerSeqLen >= 128 ||
+ (outerSeqLen + 2 - digestLen) >
+ (MAX_PREFIX_LEN_EXCLUDING_OID + hashOid->oid.len)) {
+ /* this is actually a library failure, It shouldn't happen */
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ prefix->len = 6 + hashOid->oid.len + extra + 2;
+ prefix->data = PORT_Alloc(prefix->len);
+ if (!prefix->data) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return SECFailure;
+ }
+
+ prefix->data[0] = SEC_ASN1_SEQUENCE | SEC_ASN1_CONSTRUCTED;
+ prefix->data[1] = outerSeqLen;
+ prefix->data[2] = SEC_ASN1_SEQUENCE | SEC_ASN1_CONSTRUCTED;
+ prefix->data[3] = innerSeqLen;
+ prefix->data[4] = SEC_ASN1_OBJECT_ID;
+ prefix->data[5] = hashOid->oid.len;
+ PORT_Memcpy(&prefix->data[6], hashOid->oid.data, hashOid->oid.len);
+ if (withParams) {
+ prefix->data[6 + hashOid->oid.len] = SEC_ASN1_NULL;
+ prefix->data[6 + hashOid->oid.len + 1] = 0;
+ }
+ prefix->data[6 + hashOid->oid.len + extra] = SEC_ASN1_OCTET_STRING;
+ prefix->data[6 + hashOid->oid.len + extra + 1] = digestLen;
+
+ return SECSuccess;
+}
+
+SECStatus
+_SGN_VerifyPKCS1DigestInfo(SECOidTag digestAlg,
+ const SECItem *digest,
+ const SECItem *dataRecoveredFromSignature,
+ PRBool unsafeAllowMissingParameters)
+{
+ SECOidData *hashOid;
+ pkcs1Prefix prefix;
+ SECStatus rv;
+
+ if (!digest || !digest->data ||
+ !dataRecoveredFromSignature || !dataRecoveredFromSignature->data) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ hashOid = SECOID_FindOIDByTag(digestAlg);
+ if (hashOid == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ prefix.data = NULL;
+
+ rv = encodePrefix(hashOid, digest->len, &prefix, PR_TRUE);
+
+ if (rv == SECSuccess) {
+ /* We don't attempt to avoid timing attacks on these comparisons because
+ * signature verification is a public key operation, not a private key
+ * operation.
+ */
+
+ if (dataRecoveredFromSignature->len != prefix.len + digest->len) {
+ PRBool lengthMismatch = PR_TRUE;
+#ifdef NSS_PKCS1_AllowMissingParameters
+ if (unsafeAllowMissingParameters) {
+ if (prefix.data) {
+ PORT_Free(prefix.data);
+ prefix.data = NULL;
+ }
+ rv = encodePrefix(hashOid, digest->len, &prefix, PR_FALSE);
+ if (rv != SECSuccess ||
+ dataRecoveredFromSignature->len == prefix.len + digest->len) {
+ lengthMismatch = PR_FALSE;
+ }
+ }
+#endif
+ if (lengthMismatch) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ rv = SECFailure;
+ }
+ }
+ }
+
+ if (rv == SECSuccess) {
+ if (memcmp(dataRecoveredFromSignature->data, prefix.data, prefix.len) ||
+ memcmp(dataRecoveredFromSignature->data + prefix.len, digest->data,
+ digest->len)) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ rv = SECFailure;
+ }
+ }
+
+ if (prefix.data) {
+ PORT_Free(prefix.data);
+ }
+
+ return rv;
+}
diff --git a/security/nss/lib/util/pkcs1sig.h b/security/nss/lib/util/pkcs1sig.h
new file mode 100644
index 0000000000..7c52b15758
--- /dev/null
+++ b/security/nss/lib/util/pkcs1sig.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/.
+ */
+
+#ifndef _PKCS1SIG_H_
+#define _PKCS1SIG_H_
+
+#include "hasht.h"
+#include "seccomon.h"
+#include "secoidt.h"
+
+/* SGN_VerifyPKCS1DigestInfo verifies that the length of the digest is correct
+ * for the given algorithm, then verifies that the recovered data from the
+ * PKCS#1 signature is a properly-formatted DigestInfo that identifies the
+ * given digest algorithm, then verifies that the digest in the DigestInfo
+ * matches the given digest.
+ *
+ * dataRecoveredFromSignature must be the result of calling PK11_VerifyRecover
+ * or equivalent.
+ *
+ * If unsafeAllowMissingParameters is true (not recommended), then a DigestInfo
+ * without the mandatory ASN.1 NULL parameter will also be accepted.
+ */
+SECStatus _SGN_VerifyPKCS1DigestInfo(SECOidTag digestAlg,
+ const SECItem* digest,
+ const SECItem* dataRecoveredFromSignature,
+ PRBool unsafeAllowMissingParameters);
+
+#endif /* _PKCS1SIG_H_ */
diff --git a/security/nss/lib/util/portreg.c b/security/nss/lib/util/portreg.c
new file mode 100644
index 0000000000..bf77672f00
--- /dev/null
+++ b/security/nss/lib/util/portreg.c
@@ -0,0 +1,375 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * shexp.c: shell-like wildcard match routines
+ *
+ * See shexp.h for public documentation.
+ */
+
+#include "seccomon.h"
+#include "portreg.h"
+
+/* ----------------------------- shexp_valid ------------------------------ */
+
+static int
+_valid_subexp(const char *exp, char stop1, char stop2)
+{
+ register int x;
+ int nsc = 0; /* Number of special characters */
+ int np; /* Number of pipe characters in union */
+ int tld = 0; /* Number of tilde characters */
+
+ for (x = 0; exp[x] && (exp[x] != stop1) && (exp[x] != stop2); ++x) {
+ switch (exp[x]) {
+ case '~':
+ if (tld) /* at most one exclusion */
+ return INVALID_SXP;
+ if (stop1) /* no exclusions within unions */
+ return INVALID_SXP;
+ if (!exp[x + 1]) /* exclusion cannot be last character */
+ return INVALID_SXP;
+ if (!x) /* exclusion cannot be first character */
+ return INVALID_SXP;
+ ++tld;
+ /* fall through */
+ case '*':
+ case '?':
+ case '$':
+ ++nsc;
+ break;
+ case '[':
+ ++nsc;
+ if ((!exp[++x]) || (exp[x] == ']'))
+ return INVALID_SXP;
+ for (; exp[x] && (exp[x] != ']'); ++x) {
+ if (exp[x] == '\\' && !exp[++x])
+ return INVALID_SXP;
+ }
+ if (!exp[x])
+ return INVALID_SXP;
+ break;
+ case '(':
+ ++nsc;
+ if (stop1) /* no nested unions */
+ return INVALID_SXP;
+ np = -1;
+ do {
+ int t = _valid_subexp(&exp[++x], ')', '|');
+ if (t == 0 || t == INVALID_SXP)
+ return INVALID_SXP;
+ x += t;
+ if (!exp[x])
+ return INVALID_SXP;
+ ++np;
+ } while (exp[x] == '|');
+ if (np < 1) /* must be at least one pipe */
+ return INVALID_SXP;
+ break;
+ case ')':
+ case '|':
+ case ']':
+ return INVALID_SXP;
+ case '\\':
+ ++nsc;
+ if (!exp[++x])
+ return INVALID_SXP;
+ break;
+ default:
+ break;
+ }
+ }
+ if ((!stop1) && (!nsc)) /* must be at least one special character */
+ return NON_SXP;
+ return ((exp[x] == stop1 || exp[x] == stop2) ? x : INVALID_SXP);
+}
+
+int
+PORT_RegExpValid(const char *exp)
+{
+ int x;
+
+ x = _valid_subexp(exp, '\0', '\0');
+ return (x < 0 ? x : VALID_SXP);
+}
+
+/* ----------------------------- shexp_match ----------------------------- */
+
+#define MATCH 0
+#define NOMATCH 1
+#define ABORTED -1
+
+static int
+_shexp_match(const char *str, const char *exp, PRBool case_insensitive,
+ unsigned int level);
+
+/* Count characters until we reach a NUL character or either of the
+ * two delimiter characters, stop1 or stop2. If we encounter a bracketed
+ * expression, look only for NUL or ']' inside it. Do not look for stop1
+ * or stop2 inside it. Return ABORTED if bracketed expression is unterminated.
+ * Handle all escaping.
+ * Return index in input string of first stop found, or ABORTED if not found.
+ * If "dest" is non-NULL, copy counted characters to it and NUL terminate.
+ */
+static int
+_scan_and_copy(const char *exp, char stop1, char stop2, char *dest)
+{
+ register int sx; /* source index */
+ register char cc;
+
+ for (sx = 0; (cc = exp[sx]) && cc != stop1 && cc != stop2; sx++) {
+ if (cc == '\\') {
+ if (!exp[++sx])
+ return ABORTED; /* should be impossible */
+ } else if (cc == '[') {
+ while ((cc = exp[++sx]) && cc != ']') {
+ if (cc == '\\' && !exp[++sx])
+ return ABORTED;
+ }
+ if (!cc)
+ return ABORTED; /* should be impossible */
+ }
+ }
+ if (dest && sx) {
+ /* Copy all but the closing delimiter. */
+ memcpy(dest, exp, sx);
+ dest[sx] = 0;
+ }
+ return cc ? sx : ABORTED; /* index of closing delimiter */
+}
+
+/* On input, exp[0] is the opening parenthesis of a union.
+ * See if any of the alternatives in the union matches as a pattern.
+ * The strategy is to take each of the alternatives, in turn, and append
+ * the rest of the expression (after the closing ')' that marks the end of
+ * this union) to that alternative, and then see if the resultant expression
+ * matches the input string. Repeat this until some alternative matches,
+ * or we have an abort.
+ */
+static int
+_handle_union(const char *str, const char *exp, PRBool case_insensitive,
+ unsigned int level)
+{
+ register int sx; /* source index */
+ int cp; /* source index of closing parenthesis */
+ int count;
+ int ret = NOMATCH;
+ char *e2;
+
+ /* Find the closing parenthesis that ends this union in the expression */
+ cp = _scan_and_copy(exp, ')', '\0', NULL);
+ if (cp == ABORTED || cp < 4) /* must be at least "(a|b" before ')' */
+ return ABORTED;
+ ++cp; /* now index of char after closing parenthesis */
+ e2 = (char *)PORT_Alloc(1 + strlen(exp));
+ if (!e2)
+ return ABORTED;
+ for (sx = 1;; ++sx) {
+ /* Here, exp[sx] is one character past the preceding '(' or '|'. */
+ /* Copy everything up to the next delimiter to e2 */
+ count = _scan_and_copy(exp + sx, ')', '|', e2);
+ if (count == ABORTED || !count) {
+ ret = ABORTED;
+ break;
+ }
+ sx += count;
+ /* Append everything after closing parenthesis to e2. This is safe. */
+ strcpy(e2 + count, exp + cp);
+ ret = _shexp_match(str, e2, case_insensitive, level + 1);
+ if (ret != NOMATCH || !exp[sx] || exp[sx] == ')')
+ break;
+ }
+ PORT_Free(e2);
+ if (sx < 2)
+ ret = ABORTED;
+ return ret;
+}
+
+/* returns 1 if val is in range from start..end, case insensitive. */
+static int
+_is_char_in_range(int start, int end, int val)
+{
+ char map[256];
+ memset(map, 0, sizeof map);
+ while (start <= end)
+ map[tolower(start++)] = 1;
+ return map[tolower(val)];
+}
+
+static int
+_shexp_match(const char *str, const char *exp, PRBool case_insensitive,
+ unsigned int level)
+{
+ register int x; /* input string index */
+ register int y; /* expression index */
+ int ret, neg;
+
+ if (level > 20) /* Don't let the stack get too deep. */
+ return ABORTED;
+ for (x = 0, y = 0; exp[y]; ++y, ++x) {
+ if ((!str[x]) && (exp[y] != '$') && (exp[y] != '*')) {
+ return NOMATCH;
+ }
+ switch (exp[y]) {
+ case '$':
+ if (str[x])
+ return NOMATCH;
+ --x; /* we don't want loop to increment x */
+ break;
+ case '*':
+ while (exp[++y] == '*') {
+ }
+ if (!exp[y])
+ return MATCH;
+ while (str[x]) {
+ ret = _shexp_match(&str[x++], &exp[y], case_insensitive,
+ level + 1);
+ switch (ret) {
+ case NOMATCH:
+ continue;
+ case ABORTED:
+ return ABORTED;
+ default:
+ return MATCH;
+ }
+ }
+ if ((exp[y] == '$') && (exp[y + 1] == '\0') && (!str[x]))
+ return MATCH;
+ else
+ return NOMATCH;
+ case '[': {
+ int start, end = 0, i;
+ neg = ((exp[++y] == '^') && (exp[y + 1] != ']'));
+ if (neg)
+ ++y;
+ i = y;
+ start = (unsigned char)(exp[i++]);
+ if (start == '\\')
+ start = (unsigned char)(exp[i++]);
+ if (isalnum(start) && exp[i++] == '-') {
+ end = (unsigned char)(exp[i++]);
+ if (end == '\\')
+ end = (unsigned char)(exp[i++]);
+ }
+ if (isalnum(end) && exp[i] == ']') {
+ /* This is a range form: a-b */
+ int val = (unsigned char)(str[x]);
+ if (end < start) { /* swap them */
+ start ^= end;
+ end ^= start;
+ start ^= end;
+ }
+ if (case_insensitive && isalpha(val)) {
+ val = _is_char_in_range(start, end, val);
+ if (neg == val)
+ return NOMATCH;
+ } else if (neg != ((val < start) || (val > end))) {
+ return NOMATCH;
+ }
+ y = i;
+ } else {
+ /* Not range form */
+ int matched = 0;
+ for (; exp[y] != ']'; y++) {
+ if (exp[y] == '\\')
+ ++y;
+ if (case_insensitive) {
+ matched |= (toupper(str[x]) == toupper(exp[y]));
+ } else {
+ matched |= (str[x] == exp[y]);
+ }
+ }
+ if (neg == matched)
+ return NOMATCH;
+ }
+ } break;
+ case '(':
+ if (!exp[y + 1])
+ return ABORTED;
+ return _handle_union(&str[x], &exp[y], case_insensitive, level);
+ case '?':
+ break;
+ case '|':
+ case ']':
+ case ')':
+ return ABORTED;
+ case '\\':
+ ++y;
+ /* fall through */
+ default:
+ if (case_insensitive) {
+ if (toupper(str[x]) != toupper(exp[y]))
+ return NOMATCH;
+ } else {
+ if (str[x] != exp[y])
+ return NOMATCH;
+ }
+ break;
+ }
+ }
+ return (str[x] ? NOMATCH : MATCH);
+}
+
+static int
+port_RegExpMatch(const char *str, const char *xp, PRBool case_insensitive)
+{
+ char *exp = 0;
+ int x, ret = MATCH;
+
+ if (!strchr(xp, '~'))
+ return _shexp_match(str, xp, case_insensitive, 0);
+
+ exp = PORT_Strdup(xp);
+ if (!exp)
+ return NOMATCH;
+
+ x = _scan_and_copy(exp, '~', '\0', NULL);
+ if (x != ABORTED && exp[x] == '~') {
+ exp[x++] = '\0';
+ ret = _shexp_match(str, &exp[x], case_insensitive, 0);
+ switch (ret) {
+ case NOMATCH:
+ ret = MATCH;
+ break;
+ case MATCH:
+ ret = NOMATCH;
+ break;
+ default:
+ break;
+ }
+ }
+ if (ret == MATCH)
+ ret = _shexp_match(str, exp, case_insensitive, 0);
+
+ PORT_Free(exp);
+ return ret;
+}
+
+/* ------------------------------ shexp_cmp ------------------------------- */
+
+int
+PORT_RegExpSearch(const char *str, const char *exp)
+{
+ switch (PORT_RegExpValid(exp)) {
+ case INVALID_SXP:
+ return -1;
+ case NON_SXP:
+ return (strcmp(exp, str) ? 1 : 0);
+ default:
+ return port_RegExpMatch(str, exp, PR_FALSE);
+ }
+}
+
+int
+PORT_RegExpCaseSearch(const char *str, const char *exp)
+{
+ switch (PORT_RegExpValid(exp)) {
+ case INVALID_SXP:
+ return -1;
+ case NON_SXP:
+ return (PORT_Strcasecmp(exp, str) ? 1 : 0);
+ default:
+ return port_RegExpMatch(str, exp, PR_TRUE);
+ }
+}
diff --git a/security/nss/lib/util/portreg.h b/security/nss/lib/util/portreg.h
new file mode 100644
index 0000000000..14bd9e7666
--- /dev/null
+++ b/security/nss/lib/util/portreg.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/. */
+
+/*
+ * shexp.h: Defines and prototypes for shell exp. match routines
+ *
+ * This routine will match a string with a shell expression. The expressions
+ * accepted are based loosely on the expressions accepted by zsh.
+ *
+ * o * matches anything
+ * o ? matches one character
+ * o \ will escape a special character
+ * o $ matches the end of the string
+ * Bracketed expressions:
+ * o [abc] matches one occurence of a, b, or c.
+ * o [^abc] matches any character except a, b, or c.
+ * To be matched between [ and ], these characters must be escaped: \ ]
+ * No other characters need be escaped between brackets.
+ * Unnecessary escaping is permitted.
+ * o [a-z] matches any character between a and z, inclusive.
+ * The two range-definition characters must be alphanumeric ASCII.
+ * If one is upper case and the other is lower case, then the ASCII
+ * non-alphanumeric characters between Z and a will also be in range.
+ * o [^a-z] matches any character except those between a and z, inclusive.
+ * These forms cannot be combined, e.g [a-gp-z] does not work.
+ * o Exclusions:
+ * As a top level, outter-most expression only, the expression
+ * foo~bar will match the expression foo, provided it does not also
+ * match the expression bar. Either expression or both may be a union.
+ * Except between brackets, any unescaped ~ is an exclusion.
+ * At most one exclusion is permitted.
+ * Exclusions cannot be nested (contain other exclusions).
+ * example: *~abc will match any string except abc
+ * o Unions:
+ * (foo|bar) will match either the expression foo, or the expression bar.
+ * At least one '|' separator is required. More are permitted.
+ * Expressions inside unions may not include unions or exclusions.
+ * Inside a union, to be matched and not treated as a special character,
+ * these characters must be escaped: \ ( | ) [ ~ except when they occur
+ * inside a bracketed expression, where only \ and ] require escaping.
+ *
+ * The public interface to these routines is documented below.
+ *
+ */
+
+#ifndef SHEXP_H
+#define SHEXP_H
+
+#include "utilrename.h"
+/*
+ * Requires that the macro MALLOC be set to a "safe" malloc that will
+ * exit if no memory is available.
+ */
+
+/* --------------------------- Public routines ---------------------------- */
+
+/*
+ * shexp_valid takes a shell expression exp as input. It returns:
+ *
+ * NON_SXP if exp is a standard string
+ * INVALID_SXP if exp is a shell expression, but invalid
+ * VALID_SXP if exp is a valid shell expression
+ */
+
+#define NON_SXP -1
+#define INVALID_SXP -2
+#define VALID_SXP 1
+
+SEC_BEGIN_PROTOS
+
+extern int PORT_RegExpValid(const char *exp);
+
+extern int PORT_RegExpSearch(const char *str, const char *exp);
+
+/* same as above but uses case insensitive search */
+extern int PORT_RegExpCaseSearch(const char *str, const char *exp);
+
+SEC_END_PROTOS
+
+#endif
diff --git a/security/nss/lib/util/quickder.c b/security/nss/lib/util/quickder.c
new file mode 100644
index 0000000000..86f0fae2dc
--- /dev/null
+++ b/security/nss/lib/util/quickder.c
@@ -0,0 +1,837 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ Optimized ASN.1 DER decoder
+*/
+
+#include "secerr.h"
+#include "secasn1.h" /* for SEC_ASN1GetSubtemplate */
+#include "secitem.h"
+
+/*
+ * simple definite-length ASN.1 decoder
+ */
+
+static unsigned char*
+definite_length_decoder(const unsigned char* buf,
+ const unsigned int buf_length,
+ unsigned int* out_data_length,
+ PRBool includeTag)
+{
+ unsigned char tag;
+ unsigned int used_length = 0;
+ unsigned int data_length = 0;
+ unsigned char length_field_len = 0;
+ unsigned char byte;
+ unsigned int i;
+
+ if (used_length >= buf_length) {
+ /* Tag field was not found! */
+ return NULL;
+ }
+ tag = buf[used_length++];
+
+ if (tag == 0) {
+ /* End-of-contents octects should not be present in DER because
+ DER doesn't use the indefinite length form. */
+ return NULL;
+ }
+
+ if ((tag & 0x1F) == 0x1F) {
+ /* High tag number (a tag number > 30) is not supported */
+ return NULL;
+ }
+
+ if (used_length >= buf_length) {
+ /* Length field was not found! */
+ return NULL;
+ }
+ byte = buf[used_length++];
+
+ if (!(byte & 0x80)) {
+ /* Short form: The high bit is not set. */
+ data_length = byte; /* clarity; we're returning a 32-bit int. */
+ } else {
+ /* Long form. Extract the field length */
+ length_field_len = byte & 0x7F;
+ if (length_field_len == 0) {
+ /* DER doesn't use the indefinite length form. */
+ return NULL;
+ }
+
+ if (length_field_len > sizeof(data_length)) {
+ /* We don't support an extended length field longer than
+ 4 bytes (2^32) */
+ return NULL;
+ }
+
+ if (length_field_len > (buf_length - used_length)) {
+ /* Extended length field was not found */
+ return NULL;
+ }
+
+ /* Iterate across the extended length field */
+ for (i = 0; i < length_field_len; i++) {
+ byte = buf[used_length++];
+ data_length = (data_length << 8) | byte;
+
+ if (i == 0) {
+ PRBool too_long = PR_FALSE;
+ if (length_field_len == 1) {
+ too_long = ((byte & 0x80) == 0); /* Short form suffices */
+ } else {
+ too_long = (byte == 0); /* This zero byte can be omitted */
+ }
+ if (too_long) {
+ /* The length is longer than needed. */
+ return NULL;
+ }
+ }
+ }
+ }
+
+ if ((tag & SEC_ASN1_TAGNUM_MASK) == SEC_ASN1_NULL && data_length != 0) {
+ /* The DER encoding of NULL has no contents octets */
+ return NULL;
+ }
+
+ if (data_length > (buf_length - used_length)) {
+ /* The decoded length exceeds the available buffer */
+ return NULL;
+ }
+
+ if (includeTag) {
+ data_length += used_length;
+ }
+
+ *out_data_length = data_length;
+ return ((unsigned char*)buf + (includeTag ? 0 : used_length));
+}
+
+static SECStatus
+GetItem(SECItem* src, SECItem* dest, PRBool includeTag)
+{
+ if ((!src) || (!dest) || (!src->data && src->len)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (!src->len) {
+ /* reaching the end of the buffer is not an error */
+ dest->data = NULL;
+ dest->len = 0;
+ return SECSuccess;
+ }
+
+ dest->data = definite_length_decoder(src->data, src->len, &dest->len,
+ includeTag);
+ if (dest->data == NULL) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ src->len -= (int)(dest->data - src->data) + dest->len;
+ src->data = dest->data + dest->len;
+ return SECSuccess;
+}
+
+/* check if the actual component's type matches the type in the template */
+
+static SECStatus
+MatchComponentType(const SEC_ASN1Template* templateEntry,
+ SECItem* item, PRBool* match, void* dest)
+{
+ unsigned long kind = 0;
+ unsigned char tag = 0;
+
+ if ((!item) || (!item->data && item->len) || (!templateEntry) || (!match)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (!item->len) {
+ *match = PR_FALSE;
+ return SECSuccess;
+ }
+
+ kind = templateEntry->kind;
+ tag = *(unsigned char*)item->data;
+
+ if (((kind & SEC_ASN1_INLINE) ||
+ (kind & SEC_ASN1_POINTER)) &&
+ (0 == (kind & SEC_ASN1_TAG_MASK))) {
+ /* These cases are special because the template's "kind" does not
+ give us the information for the ASN.1 tag of the next item. It can
+ only be figured out from the subtemplate. */
+ if (!(kind & SEC_ASN1_OPTIONAL)) {
+ /* This is a required component. If there is a type mismatch,
+ the decoding of the subtemplate will fail, so assume this
+ is a match at the parent level and let it fail later. This
+ avoids a redundant check in matching cases */
+ *match = PR_TRUE;
+ return SECSuccess;
+ } else {
+ /* optional component. This is the hard case. Now we need to
+ look at the subtemplate to get the expected kind */
+ const SEC_ASN1Template* subTemplate =
+ SEC_ASN1GetSubtemplate(templateEntry, dest, PR_FALSE);
+ if (!subTemplate) {
+ PORT_SetError(SEC_ERROR_BAD_TEMPLATE);
+ return SECFailure;
+ }
+ if ((subTemplate->kind & SEC_ASN1_INLINE) ||
+ (subTemplate->kind & SEC_ASN1_POINTER)) {
+ /* disallow nesting SEC_ASN1_POINTER and SEC_ASN1_INLINE,
+ otherwise you may get a false positive due to the recursion
+ optimization above that always matches the type if the
+ component is required . Nesting these should never be
+ required, so that no one should miss this ability */
+ PORT_SetError(SEC_ERROR_BAD_TEMPLATE);
+ return SECFailure;
+ }
+ return MatchComponentType(subTemplate, item, match,
+ (void*)((char*)dest + templateEntry->offset));
+ }
+ }
+
+ if (kind & SEC_ASN1_CHOICE) {
+ /* we need to check the component's tag against each choice's tag */
+ /* XXX it would be nice to save the index of the choice here so that
+ DecodeChoice wouldn't have to do this again. However, due to the
+ recursivity of MatchComponentType, we don't know if we are in a
+ required or optional component, so we can't write anywhere in
+ the destination within this function */
+ unsigned choiceIndex = 1;
+ const SEC_ASN1Template* choiceEntry;
+ while ((choiceEntry = &templateEntry[choiceIndex++]) && (choiceEntry->kind)) {
+ if ((SECSuccess == MatchComponentType(choiceEntry, item, match,
+ (void*)((char*)dest + choiceEntry->offset))) &&
+ (PR_TRUE == *match)) {
+ return SECSuccess;
+ }
+ }
+ /* no match, caller must decide if this is BAD DER, or not. */
+ *match = PR_FALSE;
+ return SECSuccess;
+ }
+
+ if (kind & SEC_ASN1_ANY) {
+ /* SEC_ASN1_ANY always matches */
+ *match = PR_TRUE;
+ return SECSuccess;
+ }
+
+ if ((0 == ((unsigned char)kind & SEC_ASN1_TAGNUM_MASK)) &&
+ (!(kind & SEC_ASN1_EXPLICIT)) &&
+ (((kind & SEC_ASN1_SAVE) ||
+ (kind & SEC_ASN1_SKIP)) &&
+ (!(kind & SEC_ASN1_OPTIONAL)))) {
+ /* when saving or skipping a required component, a type is not
+ required in the template. This is for legacy support of
+ SEC_ASN1_SAVE and SEC_ASN1_SKIP only. XXX I would like to
+ deprecate these usages and always require a type, as this
+ disables type checking, and effectively forbids us from
+ transparently ignoring optional components we aren't aware of */
+ *match = PR_TRUE;
+ return SECSuccess;
+ }
+
+ /* first, do a class check */
+ if ((tag & SEC_ASN1_CLASS_MASK) !=
+ (((unsigned char)kind) & SEC_ASN1_CLASS_MASK)) {
+ /* this is only to help debugging of the decoder in case of problems */
+ /* unsigned char tagclass = tag & SEC_ASN1_CLASS_MASK; */
+ /* unsigned char expectedclass = (unsigned char)kind & SEC_ASN1_CLASS_MASK; */
+ *match = PR_FALSE;
+ return SECSuccess;
+ }
+
+ /* now do a tag check */
+ if (((unsigned char)kind & SEC_ASN1_TAGNUM_MASK) !=
+ (tag & SEC_ASN1_TAGNUM_MASK)) {
+ *match = PR_FALSE;
+ return SECSuccess;
+ }
+
+ /* now, do a method check. This depends on the class */
+ switch (tag & SEC_ASN1_CLASS_MASK) {
+ case SEC_ASN1_UNIVERSAL:
+ /* For types of the SEC_ASN1_UNIVERSAL class, we know which must be
+ primitive or constructed based on the tag */
+ switch (tag & SEC_ASN1_TAGNUM_MASK) {
+ case SEC_ASN1_SEQUENCE:
+ case SEC_ASN1_SET:
+ case SEC_ASN1_EMBEDDED_PDV:
+ /* this component must be a constructed type */
+ /* XXX add any new universal constructed type here */
+ if (tag & SEC_ASN1_CONSTRUCTED) {
+ *match = PR_TRUE;
+ return SECSuccess;
+ }
+ break;
+
+ default:
+ /* this component must be a primitive type */
+ if (!(tag & SEC_ASN1_CONSTRUCTED)) {
+ *match = PR_TRUE;
+ return SECSuccess;
+ }
+ break;
+ }
+ break;
+
+ default:
+ /* for all other classes, we check the method based on the template */
+ if ((unsigned char)(kind & SEC_ASN1_METHOD_MASK) ==
+ (tag & SEC_ASN1_METHOD_MASK)) {
+ *match = PR_TRUE;
+ return SECSuccess;
+ }
+ /* method does not match between template and component */
+ break;
+ }
+
+ *match = PR_FALSE;
+ return SECSuccess;
+}
+
+#ifdef DEBUG
+
+static SECStatus
+CheckSequenceTemplate(const SEC_ASN1Template* sequenceTemplate)
+{
+ SECStatus rv = SECSuccess;
+ const SEC_ASN1Template* sequenceEntry = NULL;
+ unsigned long seqIndex = 0;
+ unsigned long lastEntryIndex = 0;
+ unsigned long ambiguityIndex = 0;
+ PRBool foundAmbiguity = PR_FALSE;
+
+ do {
+ sequenceEntry = &sequenceTemplate[seqIndex++];
+ if (sequenceEntry->kind) {
+ /* ensure that we don't have an optional component of SEC_ASN1_ANY
+ in the middle of the sequence, since we could not handle it */
+ /* XXX this function needs to dig into the subtemplates to find
+ the next tag */
+ if ((PR_FALSE == foundAmbiguity) &&
+ (sequenceEntry->kind & SEC_ASN1_OPTIONAL) &&
+ (sequenceEntry->kind & SEC_ASN1_ANY)) {
+ foundAmbiguity = PR_TRUE;
+ ambiguityIndex = seqIndex - 1;
+ }
+ }
+ } while (sequenceEntry->kind);
+
+ lastEntryIndex = seqIndex - 2;
+
+ if (PR_FALSE != foundAmbiguity) {
+ if (ambiguityIndex < lastEntryIndex) {
+ /* ambiguity can only be tolerated on the last entry */
+ PORT_SetError(SEC_ERROR_BAD_TEMPLATE);
+ rv = SECFailure;
+ }
+ }
+
+ /* XXX also enforce ASN.1 requirement that tags be
+ distinct for consecutive optional components */
+
+ return rv;
+}
+
+#endif
+
+static SECStatus DecodeItem(void* dest,
+ const SEC_ASN1Template* templateEntry,
+ SECItem* src, PLArenaPool* arena, PRBool checkTag);
+
+static SECStatus
+DecodeSequence(void* dest,
+ const SEC_ASN1Template* templateEntry,
+ SECItem* src, PLArenaPool* arena)
+{
+ SECStatus rv = SECSuccess;
+ SECItem source;
+ SECItem sequence;
+ const SEC_ASN1Template* sequenceTemplate = &(templateEntry[1]);
+ const SEC_ASN1Template* sequenceEntry = NULL;
+ unsigned long seqindex = 0;
+
+#ifdef DEBUG
+ /* for a sequence, we need to validate the template. */
+ rv = CheckSequenceTemplate(sequenceTemplate);
+#endif
+
+ source = *src;
+
+ /* get the sequence */
+ if (SECSuccess == rv) {
+ rv = GetItem(&source, &sequence, PR_FALSE);
+ }
+
+ /* process it */
+ if (SECSuccess == rv)
+ do {
+ sequenceEntry = &sequenceTemplate[seqindex++];
+ if ((sequenceEntry && sequenceEntry->kind) &&
+ (sequenceEntry->kind != SEC_ASN1_SKIP_REST)) {
+ rv = DecodeItem(dest, sequenceEntry, &sequence, arena, PR_TRUE);
+ }
+ } while ((SECSuccess == rv) &&
+ (sequenceEntry->kind &&
+ sequenceEntry->kind != SEC_ASN1_SKIP_REST));
+ /* we should have consumed all the bytes in the sequence by now
+ unless the caller doesn't care about the rest of the sequence */
+ if (SECSuccess == rv && sequence.len &&
+ sequenceEntry && sequenceEntry->kind != SEC_ASN1_SKIP_REST) {
+ /* it isn't 100% clear whether this is a bad DER or a bad template.
+ The problem is that logically, they don't match - there is extra
+ data in the DER that the template doesn't know about */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ rv = SECFailure;
+ }
+
+ return rv;
+}
+
+static SECStatus
+DecodeInline(void* dest,
+ const SEC_ASN1Template* templateEntry,
+ SECItem* src, PLArenaPool* arena, PRBool checkTag)
+{
+ const SEC_ASN1Template* inlineTemplate =
+ SEC_ASN1GetSubtemplate(templateEntry, dest, PR_FALSE);
+ return DecodeItem((void*)((char*)dest + templateEntry->offset),
+ inlineTemplate, src, arena, checkTag);
+}
+
+static SECStatus
+DecodePointer(void* dest,
+ const SEC_ASN1Template* templateEntry,
+ SECItem* src, PLArenaPool* arena, PRBool checkTag)
+{
+ const SEC_ASN1Template* ptrTemplate =
+ SEC_ASN1GetSubtemplate(templateEntry, dest, PR_FALSE);
+ if (!ptrTemplate) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ void* subdata = PORT_ArenaZAlloc(arena, ptrTemplate->size);
+ *(void**)((char*)dest + templateEntry->offset) = subdata;
+ if (subdata) {
+ return DecodeItem(subdata, ptrTemplate, src, arena, checkTag);
+ } else {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return SECFailure;
+ }
+}
+
+static SECStatus
+DecodeImplicit(void* dest,
+ const SEC_ASN1Template* templateEntry,
+ SECItem* src, PLArenaPool* arena)
+{
+ if (templateEntry->kind & SEC_ASN1_POINTER) {
+ return DecodePointer((void*)((char*)dest),
+ templateEntry, src, arena, PR_FALSE);
+ } else {
+ return DecodeInline((void*)((char*)dest),
+ templateEntry, src, arena, PR_FALSE);
+ }
+}
+
+static SECStatus
+DecodeChoice(void* dest,
+ const SEC_ASN1Template* templateEntry,
+ SECItem* src, PLArenaPool* arena)
+{
+ SECStatus rv = SECSuccess;
+ SECItem choice;
+ const SEC_ASN1Template* choiceTemplate = &(templateEntry[1]);
+ const SEC_ASN1Template* choiceEntry = NULL;
+ unsigned long choiceindex = 0;
+
+ /* XXX for a choice component, we should validate the template to make
+ sure the tags are distinct, in debug builds. This hasn't been
+ implemented yet */
+ /* rv = CheckChoiceTemplate(sequenceTemplate); */
+
+ /* process it */
+ do {
+ choice = *src;
+ choiceEntry = &choiceTemplate[choiceindex++];
+ if (choiceEntry->kind) {
+ rv = DecodeItem(dest, choiceEntry, &choice, arena, PR_TRUE);
+ }
+ } while ((SECFailure == rv) && (choiceEntry->kind));
+
+ if (SECFailure == rv) {
+ /* the component didn't match any of the choices */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ } else {
+ /* set the type in the union here */
+ int* which = (int*)((char*)dest + templateEntry->offset);
+ *which = (int)choiceEntry->size;
+ }
+
+ /* we should have consumed all the bytes by now */
+ /* fail if we have not */
+ if (SECSuccess == rv && choice.len) {
+ /* there is extra data that isn't listed in the template */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ rv = SECFailure;
+ }
+ return rv;
+}
+
+static SECStatus
+DecodeGroup(void* dest,
+ const SEC_ASN1Template* templateEntry,
+ SECItem* src, PLArenaPool* arena)
+{
+ SECStatus rv = SECSuccess;
+ SECItem source;
+ SECItem group;
+ PRUint32 totalEntries = 0;
+ PRUint32 entryIndex = 0;
+ void** entries = NULL;
+
+ const SEC_ASN1Template* subTemplate =
+ SEC_ASN1GetSubtemplate(templateEntry, dest, PR_FALSE);
+
+ source = *src;
+
+ /* get the group */
+ if (SECSuccess == rv) {
+ rv = GetItem(&source, &group, PR_FALSE);
+ }
+
+ /* XXX we should check the subtemplate in debug builds */
+ if (SECSuccess == rv) {
+ /* first, count the number of entries. Benchmarking showed that this
+ counting pass is more efficient than trying to allocate entries as
+ we read the DER, even if allocating many entries at a time
+ */
+ SECItem counter = group;
+ do {
+ SECItem anitem;
+ rv = GetItem(&counter, &anitem, PR_TRUE);
+ if (SECSuccess == rv && (anitem.len)) {
+ totalEntries++;
+ }
+ } while ((SECSuccess == rv) && (counter.len));
+
+ if (SECSuccess == rv) {
+ /* allocate room for pointer array and entries */
+ /* we want to allocate the array even if there is 0 entry */
+ entries = (void**)PORT_ArenaZAlloc(arena, sizeof(void*) * (totalEntries + 1) + /* the extra one is for NULL termination */
+ subTemplate->size * totalEntries);
+
+ if (entries) {
+ entries[totalEntries] = NULL; /* terminate the array */
+ } else {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ rv = SECFailure;
+ }
+ if (SECSuccess == rv) {
+ void* entriesData = (unsigned char*)entries + (unsigned long)(sizeof(void*) * (totalEntries + 1));
+ /* and fix the pointers in the array */
+ PRUint32 entriesIndex = 0;
+ for (entriesIndex = 0; entriesIndex < totalEntries; entriesIndex++) {
+ entries[entriesIndex] =
+ (char*)entriesData + (subTemplate->size * entriesIndex);
+ }
+ }
+ }
+ }
+
+ if (SECSuccess == rv && totalEntries)
+ do {
+ if (!(entryIndex < totalEntries)) {
+ rv = SECFailure;
+ break;
+ }
+ rv = DecodeItem(entries[entryIndex++], subTemplate, &group, arena, PR_TRUE);
+ } while ((SECSuccess == rv) && (group.len));
+ /* we should be at the end of the set by now */
+ /* save the entries where requested */
+ memcpy(((char*)dest + templateEntry->offset), &entries, sizeof(void**));
+
+ return rv;
+}
+
+static SECStatus
+DecodeExplicit(void* dest,
+ const SEC_ASN1Template* templateEntry,
+ SECItem* src, PLArenaPool* arena)
+{
+ SECStatus rv = SECSuccess;
+ SECItem subItem;
+ SECItem constructed = *src;
+
+ rv = GetItem(&constructed, &subItem, PR_FALSE);
+
+ if (SECSuccess == rv) {
+ if (templateEntry->kind & SEC_ASN1_POINTER) {
+ rv = DecodePointer(dest, templateEntry, &subItem, arena, PR_TRUE);
+ } else {
+ rv = DecodeInline(dest, templateEntry, &subItem, arena, PR_TRUE);
+ }
+ }
+
+ return rv;
+}
+
+/* new decoder implementation. This is a recursive function */
+
+static SECStatus
+DecodeItem(void* dest,
+ const SEC_ASN1Template* templateEntry,
+ SECItem* src, PLArenaPool* arena, PRBool checkTag)
+{
+ SECStatus rv = SECSuccess;
+ SECItem temp;
+ SECItem mark = { siBuffer, NULL, 0 };
+ PRBool pop = PR_FALSE;
+ PRBool decode = PR_TRUE;
+ PRBool save = PR_FALSE;
+ unsigned long kind;
+ PRBool match = PR_TRUE;
+
+ PR_ASSERT(src && dest && templateEntry && arena);
+#if 0
+ if (!src || !dest || !templateEntry || !arena)
+ {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+ }
+#endif
+
+ if (SECSuccess == rv) {
+ /* do the template validation */
+ kind = templateEntry->kind;
+ if (!kind) {
+ PORT_SetError(SEC_ERROR_BAD_TEMPLATE);
+ rv = SECFailure;
+ }
+ }
+
+ if (SECSuccess == rv) {
+#ifdef DEBUG
+ if (kind & SEC_ASN1_DEBUG_BREAK) {
+ /* when debugging the decoder or a template that fails to
+ decode, put SEC_ASN1_DEBUG in the component that gives you
+ trouble. The decoder will then get to this block and assert.
+ If you want to debug the rest of the code, you can set a
+ breakpoint and set dontassert to PR_TRUE, which will let
+ you skip over the assert and continue the debugging session
+ past it. */
+ PRBool dontassert = PR_FALSE;
+ PR_ASSERT(dontassert); /* set bkpoint here & set dontassert*/
+ }
+#endif
+
+ if ((kind & SEC_ASN1_SKIP) ||
+ (kind & SEC_ASN1_SAVE)) {
+ /* if skipping or saving this component, don't decode it */
+ decode = PR_FALSE;
+ }
+
+ if (kind & (SEC_ASN1_SAVE | SEC_ASN1_OPTIONAL)) {
+ /* if saving this component, or if it is optional, we may not want to
+ move past it, so save the position in case we have to rewind */
+ mark = *src;
+ if (kind & SEC_ASN1_SAVE) {
+ save = PR_TRUE;
+ if (0 == (kind & SEC_ASN1_SKIP)) {
+ /* we will for sure have to rewind when saving this
+ component and not skipping it. This is true for all
+ legacy uses of SEC_ASN1_SAVE where the following entry
+ in the template would causes the same component to be
+ processed again */
+ pop = PR_TRUE;
+ }
+ }
+ }
+
+ rv = GetItem(src, &temp, PR_TRUE);
+ }
+
+ if (SECSuccess == rv) {
+ /* now check if the component matches what we expect in the template */
+
+ if (PR_TRUE == checkTag)
+
+ {
+ rv = MatchComponentType(templateEntry, &temp, &match, dest);
+ }
+
+ if ((SECSuccess == rv) && (PR_TRUE != match)) {
+ if (kind & SEC_ASN1_OPTIONAL) {
+
+ /* the optional component is missing. This is not fatal. */
+ /* Rewind, don't decode, and don't save */
+ pop = PR_TRUE;
+ decode = PR_FALSE;
+ save = PR_FALSE;
+ } else {
+ /* a required component is missing. abort */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ rv = SECFailure;
+ }
+ }
+ }
+
+ if ((SECSuccess == rv) && (PR_TRUE == decode)) {
+ /* the order of processing here is is the tricky part */
+ /* we start with our special cases */
+ /* first, check the component class */
+ if (kind & SEC_ASN1_INLINE) {
+ /* decode inline template */
+ rv = DecodeInline(dest, templateEntry, &temp, arena, PR_TRUE);
+ }
+
+ else if (kind & SEC_ASN1_EXPLICIT) {
+ rv = DecodeExplicit(dest, templateEntry, &temp, arena);
+ } else if ((SEC_ASN1_UNIVERSAL != (kind & SEC_ASN1_CLASS_MASK)) &&
+
+ (!(kind & SEC_ASN1_EXPLICIT))) {
+
+ /* decode implicitly tagged components */
+ rv = DecodeImplicit(dest, templateEntry, &temp, arena);
+ } else if (kind & SEC_ASN1_POINTER) {
+ rv = DecodePointer(dest, templateEntry, &temp, arena, PR_TRUE);
+ } else if (kind & SEC_ASN1_CHOICE) {
+ rv = DecodeChoice(dest, templateEntry, &temp, arena);
+ } else if (kind & SEC_ASN1_ANY) {
+ /* catch-all ANY type, don't decode */
+ save = PR_TRUE;
+ if (kind & SEC_ASN1_INNER) {
+ /* skip the tag and length */
+ SECItem newtemp = temp;
+ rv = GetItem(&newtemp, &temp, PR_FALSE);
+ }
+ } else if (kind & SEC_ASN1_GROUP) {
+ if ((SEC_ASN1_SEQUENCE == (kind & SEC_ASN1_TAGNUM_MASK)) ||
+ (SEC_ASN1_SET == (kind & SEC_ASN1_TAGNUM_MASK))) {
+ rv = DecodeGroup(dest, templateEntry, &temp, arena);
+ } else {
+ /* a group can only be a SET OF or SEQUENCE OF */
+ PORT_SetError(SEC_ERROR_BAD_TEMPLATE);
+ rv = SECFailure;
+ }
+ } else if (SEC_ASN1_SEQUENCE == (kind & SEC_ASN1_TAGNUM_MASK)) {
+ /* plain SEQUENCE */
+ rv = DecodeSequence(dest, templateEntry, &temp, arena);
+ } else {
+ /* handle all other types as "save" */
+ /* we should only get here for primitive universal types */
+ SECItem newtemp = temp;
+ rv = GetItem(&newtemp, &temp, PR_FALSE);
+ save = PR_TRUE;
+ if ((SECSuccess == rv) &&
+ SEC_ASN1_UNIVERSAL == (kind & SEC_ASN1_CLASS_MASK)) {
+ unsigned long tagnum = kind & SEC_ASN1_TAGNUM_MASK;
+ if (temp.len == 0 && (tagnum == SEC_ASN1_BOOLEAN ||
+ tagnum == SEC_ASN1_INTEGER ||
+ tagnum == SEC_ASN1_BIT_STRING ||
+ tagnum == SEC_ASN1_OBJECT_ID ||
+ tagnum == SEC_ASN1_ENUMERATED ||
+ tagnum == SEC_ASN1_UTC_TIME ||
+ tagnum == SEC_ASN1_GENERALIZED_TIME)) {
+ /* these types MUST have at least one content octet */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ rv = SECFailure;
+ } else
+ switch (tagnum) {
+ /* special cases of primitive types */
+ case SEC_ASN1_INTEGER: {
+ SECItem* destItem = (SECItem*)((char*)dest +
+ templateEntry->offset);
+ if (destItem && (siUnsignedInteger == destItem->type)) {
+ /* A leading 0 is only allowed when a value
+ * would otherwise be interpreted as negative. */
+ if (temp.len > 1 && temp.data[0] == 0) {
+ temp.data++;
+ temp.len--;
+ if (!(temp.data[0] & 0x80)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ rv = SECFailure;
+ }
+ }
+ }
+ break;
+ }
+
+ case SEC_ASN1_BIT_STRING: {
+ /* Can't be 8 or more spare bits, or any spare bits
+ * if there are no octets. */
+ if (temp.data[0] >= 8 || (temp.data[0] > 0 && temp.len == 1)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ rv = SECFailure;
+ break;
+ }
+ /* change the length in the SECItem to be the number
+ of bits */
+ temp.len = (temp.len - 1) * 8 - (temp.data[0] & 0x7);
+ temp.data++;
+ break;
+ }
+
+ default: {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if ((SECSuccess == rv) && (PR_TRUE == save)) {
+ SECItem* destItem = (SECItem*)((char*)dest + templateEntry->offset);
+ if (destItem) {
+ /* we leave the type alone in the destination SECItem.
+ If part of the destination was allocated by the decoder, in
+ cases of POINTER, SET OF and SEQUENCE OF, then type is set to
+ siBuffer due to the use of PORT_ArenaZAlloc*/
+ destItem->data = temp.len ? temp.data : NULL;
+ destItem->len = temp.len;
+ } else {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+ }
+ }
+
+ if (PR_TRUE == pop) {
+ /* we don't want to move ahead, so restore the position */
+ *src = mark;
+ }
+ return rv;
+}
+
+/* the function below is the public one */
+
+SECStatus
+SEC_QuickDERDecodeItem(PLArenaPool* arena, void* dest,
+ const SEC_ASN1Template* templateEntry,
+ const SECItem* src)
+{
+ SECStatus rv = SECSuccess;
+ SECItem newsrc;
+
+ if (!arena || !templateEntry || !src) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+ }
+
+ if (SECSuccess == rv) {
+ newsrc = *src;
+ rv = DecodeItem(dest, templateEntry, &newsrc, arena, PR_TRUE);
+ if (SECSuccess == rv && newsrc.len) {
+ rv = SECFailure;
+ PORT_SetError(SEC_ERROR_EXTRA_INPUT);
+ }
+ }
+
+ return rv;
+}
diff --git a/security/nss/lib/util/secalgid.c b/security/nss/lib/util/secalgid.c
new file mode 100644
index 0000000000..b3e8e89db5
--- /dev/null
+++ b/security/nss/lib/util/secalgid.c
@@ -0,0 +1,129 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secoid.h"
+#include "secder.h" /* XXX remove this when remove the DERTemplate */
+#include "secasn1.h"
+#include "secitem.h"
+#include "secerr.h"
+
+SECOidTag
+SECOID_GetAlgorithmTag(const SECAlgorithmID *id)
+{
+ if (id == NULL || id->algorithm.data == NULL)
+ return SEC_OID_UNKNOWN;
+
+ return SECOID_FindOIDTag(&(id->algorithm));
+}
+
+SECStatus
+SECOID_SetAlgorithmID(PLArenaPool *arena, SECAlgorithmID *id, SECOidTag which,
+ SECItem *params)
+{
+ SECOidData *oiddata;
+ PRBool add_null_param;
+
+ oiddata = SECOID_FindOIDByTag(which);
+ if (!oiddata) {
+ PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+ return SECFailure;
+ }
+
+ if (SECITEM_CopyItem(arena, &id->algorithm, &oiddata->oid))
+ return SECFailure;
+
+ switch (which) {
+ case SEC_OID_MD2:
+ case SEC_OID_MD4:
+ case SEC_OID_MD5:
+ case SEC_OID_SHA1:
+ case SEC_OID_SHA224:
+ case SEC_OID_SHA256:
+ case SEC_OID_SHA384:
+ case SEC_OID_SHA512:
+ case SEC_OID_PKCS1_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
+ add_null_param = PR_TRUE;
+ break;
+ default:
+ add_null_param = PR_FALSE;
+ break;
+ }
+
+ if (params) {
+ /*
+ * I am specifically *not* enforcing the following assertion
+ * (by following it up with an error and a return of failure)
+ * because I do not want to introduce any change in the current
+ * behavior. But I do want for us to notice if the following is
+ * ever true, because I do not think it should be so and probably
+ * signifies an error/bug somewhere.
+ */
+ PORT_Assert(!add_null_param || (params->len == 2 && params->data[0] == SEC_ASN1_NULL && params->data[1] == 0));
+ if (SECITEM_CopyItem(arena, &id->parameters, params)) {
+ return SECFailure;
+ }
+ } else {
+ /*
+ * Again, this is not considered an error. But if we assume
+ * that nobody tries to set the parameters field themselves
+ * (but always uses this routine to do that), then we should
+ * not hit the following assertion. Unless they forgot to zero
+ * the structure, which could also be a bad (and wrong) thing.
+ */
+ PORT_Assert(id->parameters.data == NULL);
+
+ if (add_null_param) {
+ (void)SECITEM_AllocItem(arena, &id->parameters, 2);
+ if (id->parameters.data == NULL) {
+ return SECFailure;
+ }
+ id->parameters.data[0] = SEC_ASN1_NULL;
+ id->parameters.data[1] = 0;
+ }
+ }
+
+ return SECSuccess;
+}
+
+SECStatus
+SECOID_CopyAlgorithmID(PLArenaPool *arena, SECAlgorithmID *to,
+ const SECAlgorithmID *from)
+{
+ SECStatus rv;
+
+ rv = SECITEM_CopyItem(arena, &to->algorithm, &from->algorithm);
+ if (rv)
+ return rv;
+ rv = SECITEM_CopyItem(arena, &to->parameters, &from->parameters);
+ return rv;
+}
+
+void
+SECOID_DestroyAlgorithmID(SECAlgorithmID *algid, PRBool freeit)
+{
+ SECITEM_ZfreeItem(&algid->parameters, PR_FALSE);
+ SECITEM_FreeItem(&algid->algorithm, PR_FALSE);
+ if (freeit == PR_TRUE)
+ PORT_Free(algid);
+}
+
+SECComparison
+SECOID_CompareAlgorithmID(SECAlgorithmID *a, SECAlgorithmID *b)
+{
+ SECComparison rv;
+
+ rv = SECITEM_CompareItem(&a->algorithm, &b->algorithm);
+ if (rv)
+ return rv;
+ rv = SECITEM_CompareItem(&a->parameters, &b->parameters);
+ return rv;
+}
diff --git a/security/nss/lib/util/secasn1.h b/security/nss/lib/util/secasn1.h
new file mode 100644
index 0000000000..78cab0a26b
--- /dev/null
+++ b/security/nss/lib/util/secasn1.h
@@ -0,0 +1,303 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Support for encoding/decoding of ASN.1 using BER/DER (Basic/Distinguished
+ * Encoding Rules). The routines are found in and used extensively by the
+ * security library, but exported for other use.
+ */
+
+#ifndef _SECASN1_H_
+#define _SECASN1_H_
+
+#include "utilrename.h"
+#include "plarena.h"
+
+#include "seccomon.h"
+#include "secasn1t.h"
+
+/************************************************************************/
+SEC_BEGIN_PROTOS
+
+/*
+ * XXX These function prototypes need full, explanatory comments.
+ */
+
+/*
+** Decoding.
+*/
+
+extern SEC_ASN1DecoderContext *SEC_ASN1DecoderStart(PLArenaPool *pool,
+ void *dest,
+ const SEC_ASN1Template *t);
+
+/* XXX char or unsigned char? */
+extern SECStatus SEC_ASN1DecoderUpdate(SEC_ASN1DecoderContext *cx,
+ const char *buf,
+ unsigned long len);
+
+extern SECStatus SEC_ASN1DecoderFinish(SEC_ASN1DecoderContext *cx);
+
+/* Higher level code detected an error, abort the rest of the processing */
+extern void SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error);
+
+extern void SEC_ASN1DecoderSetFilterProc(SEC_ASN1DecoderContext *cx,
+ SEC_ASN1WriteProc fn,
+ void *arg, PRBool no_store);
+
+extern void SEC_ASN1DecoderClearFilterProc(SEC_ASN1DecoderContext *cx);
+
+extern void SEC_ASN1DecoderSetNotifyProc(SEC_ASN1DecoderContext *cx,
+ SEC_ASN1NotifyProc fn,
+ void *arg);
+
+extern void SEC_ASN1DecoderClearNotifyProc(SEC_ASN1DecoderContext *cx);
+
+/* Sets the maximum size that should be allocated for a single ASN.1
+ * element. Set to 0 to indicate there is no limit.
+ *
+ * Note: This does not set the maximum size overall that may be allocated
+ * while parsing, nor does it guarantee that the decoder won't allocate
+ * more than |max_size| while parsing an individual element; rather, it
+ * merely guarantees that any individual allocation for returned data
+ * should not exceed |max_size|.
+*/
+extern void SEC_ASN1DecoderSetMaximumElementSize(SEC_ASN1DecoderContext *cx,
+ unsigned long max_size);
+
+extern SECStatus SEC_ASN1Decode(PLArenaPool *pool, void *dest,
+ const SEC_ASN1Template *t,
+ const char *buf, long len);
+
+/* Both classic ASN.1 and QuickDER have a feature that removes leading zeroes
+ out of SEC_ASN1_INTEGER if the caller sets siUnsignedInteger in the type
+ field of the target SECItem prior to calling the decoder. Otherwise, the
+ type field is ignored and untouched. For SECItem that are dynamically
+ allocated (from POINTER, SET OF, SEQUENCE OF) the decoder sets the type
+ field to siBuffer. */
+
+extern SECStatus SEC_ASN1DecodeItem(PLArenaPool *pool, void *dest,
+ const SEC_ASN1Template *t,
+ const SECItem *src);
+
+extern SECStatus SEC_QuickDERDecodeItem(PLArenaPool *arena, void *dest,
+ const SEC_ASN1Template *templateEntry,
+ const SECItem *src);
+
+/*
+** Encoding.
+*/
+
+extern SEC_ASN1EncoderContext *SEC_ASN1EncoderStart(const void *src,
+ const SEC_ASN1Template *t,
+ SEC_ASN1WriteProc fn,
+ void *output_arg);
+
+/* XXX char or unsigned char? */
+extern SECStatus SEC_ASN1EncoderUpdate(SEC_ASN1EncoderContext *cx,
+ const char *buf,
+ unsigned long len);
+
+extern void SEC_ASN1EncoderFinish(SEC_ASN1EncoderContext *cx);
+
+/* Higher level code detected an error, abort the rest of the processing */
+extern void SEC_ASN1EncoderAbort(SEC_ASN1EncoderContext *cx, int error);
+
+extern void SEC_ASN1EncoderSetNotifyProc(SEC_ASN1EncoderContext *cx,
+ SEC_ASN1NotifyProc fn,
+ void *arg);
+
+extern void SEC_ASN1EncoderClearNotifyProc(SEC_ASN1EncoderContext *cx);
+
+extern void SEC_ASN1EncoderSetStreaming(SEC_ASN1EncoderContext *cx);
+
+extern void SEC_ASN1EncoderClearStreaming(SEC_ASN1EncoderContext *cx);
+
+extern void sec_ASN1EncoderSetDER(SEC_ASN1EncoderContext *cx);
+
+extern void sec_ASN1EncoderClearDER(SEC_ASN1EncoderContext *cx);
+
+extern void SEC_ASN1EncoderSetTakeFromBuf(SEC_ASN1EncoderContext *cx);
+
+extern void SEC_ASN1EncoderClearTakeFromBuf(SEC_ASN1EncoderContext *cx);
+
+extern SECStatus SEC_ASN1Encode(const void *src, const SEC_ASN1Template *t,
+ SEC_ASN1WriteProc output_proc,
+ void *output_arg);
+
+/*
+ * If both pool and dest are NULL, the caller should free the returned SECItem
+ * with a SECITEM_FreeItem(..., PR_TRUE) call. If pool is NULL but dest is
+ * not NULL, the caller should free the data buffer pointed to by dest with a
+ * SECITEM_FreeItem(dest, PR_FALSE) or PORT_Free(dest->data) call.
+ */
+extern SECItem *SEC_ASN1EncodeItem(PLArenaPool *pool, SECItem *dest,
+ const void *src, const SEC_ASN1Template *t);
+
+extern SECItem *SEC_ASN1EncodeInteger(PLArenaPool *pool,
+ SECItem *dest, long value);
+
+extern SECItem *SEC_ASN1EncodeUnsignedInteger(PLArenaPool *pool,
+ SECItem *dest,
+ unsigned long value);
+
+extern SECStatus SEC_ASN1DecodeInteger(SECItem *src,
+ unsigned long *value);
+
+/*
+** Utilities.
+*/
+
+/*
+ * We have a length that needs to be encoded; how many bytes will the
+ * encoding take?
+ */
+extern int SEC_ASN1LengthLength(unsigned long len);
+
+/* encode the length and return the number of bytes we encoded. Buffer
+ * must be pre allocated */
+extern int SEC_ASN1EncodeLength(unsigned char *buf, int value);
+
+/*
+ * Find the appropriate subtemplate for the given template.
+ * This may involve calling a "chooser" function, or it may just
+ * be right there. In either case, it is expected to *have* a
+ * subtemplate; this is asserted in debug builds (in non-debug
+ * builds, NULL will be returned).
+ *
+ * "thing" is a pointer to the structure being encoded/decoded
+ * "encoding", when true, means that we are in the process of encoding
+ * (as opposed to in the process of decoding)
+ */
+extern const SEC_ASN1Template *
+SEC_ASN1GetSubtemplate(const SEC_ASN1Template *inTemplate, void *thing,
+ PRBool encoding);
+
+/* whether the template is for a primitive type or a choice of
+ * primitive types
+ */
+extern PRBool SEC_ASN1IsTemplateSimple(const SEC_ASN1Template *theTemplate);
+
+/************************************************************************/
+
+/*
+ * Generic Templates
+ * One for each of the simple types, plus a special one for ANY, plus:
+ * - a pointer to each one of those
+ * - a set of each one of those
+ * - a sequence of each one of those
+ *
+ * Note that these are alphabetical (case insensitive); please add new
+ * ones in the appropriate place.
+ */
+
+extern const SEC_ASN1Template SEC_AnyTemplate[];
+extern const SEC_ASN1Template SEC_BitStringTemplate[];
+extern const SEC_ASN1Template SEC_BMPStringTemplate[];
+extern const SEC_ASN1Template SEC_BooleanTemplate[];
+extern const SEC_ASN1Template SEC_EnumeratedTemplate[];
+extern const SEC_ASN1Template SEC_GeneralizedTimeTemplate[];
+extern const SEC_ASN1Template SEC_IA5StringTemplate[];
+extern const SEC_ASN1Template SEC_IntegerTemplate[];
+extern const SEC_ASN1Template SEC_NullTemplate[];
+extern const SEC_ASN1Template SEC_ObjectIDTemplate[];
+extern const SEC_ASN1Template SEC_OctetStringTemplate[];
+extern const SEC_ASN1Template SEC_PrintableStringTemplate[];
+extern const SEC_ASN1Template SEC_T61StringTemplate[];
+extern const SEC_ASN1Template SEC_UniversalStringTemplate[];
+extern const SEC_ASN1Template SEC_UTCTimeTemplate[];
+extern const SEC_ASN1Template SEC_UTF8StringTemplate[];
+extern const SEC_ASN1Template SEC_VisibleStringTemplate[];
+
+extern const SEC_ASN1Template SEC_PointerToAnyTemplate[];
+extern const SEC_ASN1Template SEC_PointerToBitStringTemplate[];
+extern const SEC_ASN1Template SEC_PointerToBMPStringTemplate[];
+extern const SEC_ASN1Template SEC_PointerToBooleanTemplate[];
+extern const SEC_ASN1Template SEC_PointerToEnumeratedTemplate[];
+extern const SEC_ASN1Template SEC_PointerToGeneralizedTimeTemplate[];
+extern const SEC_ASN1Template SEC_PointerToIA5StringTemplate[];
+extern const SEC_ASN1Template SEC_PointerToIntegerTemplate[];
+extern const SEC_ASN1Template SEC_PointerToNullTemplate[];
+extern const SEC_ASN1Template SEC_PointerToObjectIDTemplate[];
+extern const SEC_ASN1Template SEC_PointerToOctetStringTemplate[];
+extern const SEC_ASN1Template SEC_PointerToPrintableStringTemplate[];
+extern const SEC_ASN1Template SEC_PointerToT61StringTemplate[];
+extern const SEC_ASN1Template SEC_PointerToUniversalStringTemplate[];
+extern const SEC_ASN1Template SEC_PointerToUTCTimeTemplate[];
+extern const SEC_ASN1Template SEC_PointerToUTF8StringTemplate[];
+extern const SEC_ASN1Template SEC_PointerToVisibleStringTemplate[];
+
+extern const SEC_ASN1Template SEC_SequenceOfAnyTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfBitStringTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfBMPStringTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfBooleanTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfEnumeratedTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfGeneralizedTimeTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfIA5StringTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfIntegerTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfNullTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfObjectIDTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfOctetStringTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfPrintableStringTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfT61StringTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfUniversalStringTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfUTCTimeTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfUTF8StringTemplate[];
+extern const SEC_ASN1Template SEC_SequenceOfVisibleStringTemplate[];
+
+extern const SEC_ASN1Template SEC_SetOfAnyTemplate[];
+extern const SEC_ASN1Template SEC_SetOfBitStringTemplate[];
+extern const SEC_ASN1Template SEC_SetOfBMPStringTemplate[];
+extern const SEC_ASN1Template SEC_SetOfBooleanTemplate[];
+extern const SEC_ASN1Template SEC_SetOfEnumeratedTemplate[];
+extern const SEC_ASN1Template SEC_SetOfGeneralizedTimeTemplate[];
+extern const SEC_ASN1Template SEC_SetOfIA5StringTemplate[];
+extern const SEC_ASN1Template SEC_SetOfIntegerTemplate[];
+extern const SEC_ASN1Template SEC_SetOfNullTemplate[];
+extern const SEC_ASN1Template SEC_SetOfObjectIDTemplate[];
+extern const SEC_ASN1Template SEC_SetOfOctetStringTemplate[];
+extern const SEC_ASN1Template SEC_SetOfPrintableStringTemplate[];
+extern const SEC_ASN1Template SEC_SetOfT61StringTemplate[];
+extern const SEC_ASN1Template SEC_SetOfUniversalStringTemplate[];
+extern const SEC_ASN1Template SEC_SetOfUTCTimeTemplate[];
+extern const SEC_ASN1Template SEC_SetOfUTF8StringTemplate[];
+extern const SEC_ASN1Template SEC_SetOfVisibleStringTemplate[];
+
+/*
+ * Template for skipping a subitem; this only makes sense when decoding.
+ */
+extern const SEC_ASN1Template SEC_SkipTemplate[];
+
+/* These functions simply return the address of the above-declared templates.
+** This is necessary for Windows DLLs. Sigh.
+*/
+SEC_ASN1_CHOOSER_DECLARE(SEC_AnyTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_BMPStringTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_BooleanTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_BitStringTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_GeneralizedTimeTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_IA5StringTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_IntegerTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_NullTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_ObjectIDTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_OctetStringTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_UTCTimeTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_UTF8StringTemplate)
+
+SEC_ASN1_CHOOSER_DECLARE(SEC_PointerToAnyTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_PointerToOctetStringTemplate)
+
+SEC_ASN1_CHOOSER_DECLARE(SEC_SetOfAnyTemplate)
+
+SEC_ASN1_CHOOSER_DECLARE(SEC_EnumeratedTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_PointerToEnumeratedTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_SequenceOfAnyTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_SequenceOfObjectIDTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_SkipTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_UniversalStringTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_PrintableStringTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_T61StringTemplate)
+SEC_ASN1_CHOOSER_DECLARE(SEC_PointerToGeneralizedTimeTemplate)
+SEC_END_PROTOS
+#endif /* _SECASN1_H_ */
diff --git a/security/nss/lib/util/secasn1d.c b/security/nss/lib/util/secasn1d.c
new file mode 100644
index 0000000000..e503c6b1ca
--- /dev/null
+++ b/security/nss/lib/util/secasn1d.c
@@ -0,0 +1,3443 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished
+ * Encoding Rules).
+ */
+
+/* #define DEBUG_ASN1D_STATES 1 */
+
+#ifdef DEBUG_ASN1D_STATES
+#include <stdio.h>
+#define PR_Assert sec_asn1d_Assert
+#endif
+
+#include <limits.h>
+
+#include "secasn1.h"
+#include "secerr.h"
+
+typedef enum {
+ beforeIdentifier,
+ duringIdentifier,
+ afterIdentifier,
+ beforeLength,
+ duringLength,
+ afterLength,
+ beforeBitString,
+ duringBitString,
+ duringConstructedString,
+ duringGroup,
+ duringLeaf,
+ duringSaveEncoding,
+ duringSequence,
+ afterConstructedString,
+ afterGroup,
+ afterExplicit,
+ afterImplicit,
+ afterInline,
+ afterPointer,
+ afterSaveEncoding,
+ beforeEndOfContents,
+ duringEndOfContents,
+ afterEndOfContents,
+ beforeChoice,
+ duringChoice,
+ afterChoice,
+ notInUse
+} sec_asn1d_parse_place;
+
+#ifdef DEBUG_ASN1D_STATES
+static const char *const place_names[] = {
+ "beforeIdentifier",
+ "duringIdentifier",
+ "afterIdentifier",
+ "beforeLength",
+ "duringLength",
+ "afterLength",
+ "beforeBitString",
+ "duringBitString",
+ "duringConstructedString",
+ "duringGroup",
+ "duringLeaf",
+ "duringSaveEncoding",
+ "duringSequence",
+ "afterConstructedString",
+ "afterGroup",
+ "afterExplicit",
+ "afterImplicit",
+ "afterInline",
+ "afterPointer",
+ "afterSaveEncoding",
+ "beforeEndOfContents",
+ "duringEndOfContents",
+ "afterEndOfContents",
+ "beforeChoice",
+ "duringChoice",
+ "afterChoice",
+ "notInUse"
+};
+
+static const char *const class_names[] = {
+ "UNIVERSAL",
+ "APPLICATION",
+ "CONTEXT_SPECIFIC",
+ "PRIVATE"
+};
+
+static const char *const method_names[] = { "PRIMITIVE", "CONSTRUCTED" };
+
+static const char *const type_names[] = {
+ "END_OF_CONTENTS",
+ "BOOLEAN",
+ "INTEGER",
+ "BIT_STRING",
+ "OCTET_STRING",
+ "NULL",
+ "OBJECT_ID",
+ "OBJECT_DESCRIPTOR",
+ "(type 08)",
+ "REAL",
+ "ENUMERATED",
+ "EMBEDDED",
+ "UTF8_STRING",
+ "(type 0d)",
+ "(type 0e)",
+ "(type 0f)",
+ "SEQUENCE",
+ "SET",
+ "NUMERIC_STRING",
+ "PRINTABLE_STRING",
+ "T61_STRING",
+ "VIDEOTEXT_STRING",
+ "IA5_STRING",
+ "UTC_TIME",
+ "GENERALIZED_TIME",
+ "GRAPHIC_STRING",
+ "VISIBLE_STRING",
+ "GENERAL_STRING",
+ "UNIVERSAL_STRING",
+ "(type 1d)",
+ "BMP_STRING",
+ "HIGH_TAG_VALUE"
+};
+
+static const char *const flag_names[] = {
+ /* flags, right to left */
+ "OPTIONAL",
+ "EXPLICIT",
+ "ANY",
+ "INLINE",
+ "POINTER",
+ "GROUP",
+ "DYNAMIC",
+ "SKIP",
+ "INNER",
+ "SAVE",
+ "", /* decoder ignores "MAY_STREAM", */
+ "SKIP_REST",
+ "CHOICE",
+ "NO_STREAM",
+ "DEBUG_BREAK",
+ "unknown 08",
+ "unknown 10",
+ "unknown 20",
+ "unknown 40",
+ "unknown 80"
+};
+
+static int /* bool */
+formatKind(unsigned long kind, char *buf, int space_in_buffer)
+{
+ int i;
+ unsigned long k = kind & SEC_ASN1_TAGNUM_MASK;
+ unsigned long notag = kind & (SEC_ASN1_CHOICE | SEC_ASN1_POINTER |
+ SEC_ASN1_INLINE | SEC_ASN1_ANY | SEC_ASN1_SAVE);
+
+ buf[0] = 0;
+ if ((kind & SEC_ASN1_CLASS_MASK) != SEC_ASN1_UNIVERSAL) {
+ space_in_buffer -= snprintf(buf, space_in_buffer, " %s", class_names[(kind & SEC_ASN1_CLASS_MASK) >> 6]);
+ buf += strlen(buf);
+ }
+ if (kind & SEC_ASN1_METHOD_MASK) {
+ space_in_buffer -= snprintf(buf, space_in_buffer, " %s", method_names[1]);
+ buf += strlen(buf);
+ }
+ if ((kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) {
+ if (k || !notag) {
+ space_in_buffer -= snprintf(buf, space_in_buffer, " %s", type_names[k]);
+ if ((k == SEC_ASN1_SET || k == SEC_ASN1_SEQUENCE) &&
+ (kind & SEC_ASN1_GROUP)) {
+ buf += strlen(buf);
+ space_in_buffer -= snprintf(buf, space_in_buffer, "_OF");
+ }
+ }
+ } else {
+ space_in_buffer -= snprintf(buf, space_in_buffer, " [%lu]", k);
+ }
+ buf += strlen(buf);
+
+ for (k = kind >> 8, i = 0; k; k >>= 1, ++i) {
+ if (k & 1) {
+ space_in_buffer -= snprintf(buf, space_in_buffer, " %s", flag_names[i]);
+ buf += strlen(buf);
+ }
+ }
+ return notag != 0;
+}
+
+#endif /* DEBUG_ASN1D_STATES */
+
+typedef enum {
+ allDone,
+ decodeError,
+ keepGoing,
+ needBytes
+} sec_asn1d_parse_status;
+
+struct subitem {
+ const void *data;
+ unsigned long len; /* only used for substrings */
+ struct subitem *next;
+};
+
+typedef struct sec_asn1d_state_struct {
+ SEC_ASN1DecoderContext *top;
+ const SEC_ASN1Template *theTemplate;
+ void *dest;
+
+ void *our_mark; /* free on completion */
+
+ struct sec_asn1d_state_struct *parent; /* aka prev */
+ struct sec_asn1d_state_struct *child; /* aka next */
+
+ sec_asn1d_parse_place place;
+
+ /*
+ * XXX explain the next fields as clearly as possible...
+ */
+ unsigned char found_tag_modifiers;
+ unsigned char expect_tag_modifiers;
+ unsigned long check_tag_mask;
+ unsigned long found_tag_number;
+ unsigned long expect_tag_number;
+ unsigned long underlying_kind;
+
+ unsigned long contents_length;
+ unsigned long pending;
+ unsigned long consumed;
+
+ int depth;
+
+ /*
+ * Bit strings have their length adjusted -- the first octet of the
+ * contents contains a value between 0 and 7 which says how many bits
+ * at the end of the octets are not actually part of the bit string;
+ * when parsing bit strings we put that value here because we need it
+ * later, for adjustment of the length (when the whole string is done).
+ */
+ unsigned int bit_string_unused_bits;
+
+ /*
+ * The following are used for indefinite-length constructed strings.
+ */
+ struct subitem *subitems_head;
+ struct subitem *subitems_tail;
+
+ PRPackedBool
+ allocate, /* when true, need to allocate the destination */
+ endofcontents, /* this state ended up parsing its parent's end-of-contents octets */
+ explicit, /* we are handling an explicit header */
+ indefinite, /* the current item has indefinite-length encoding */
+ missing, /* an optional field that was not present */
+ optional, /* the template says this field may be omitted */
+ substring; /* this is a substring of a constructed string */
+
+} sec_asn1d_state;
+
+#define IS_HIGH_TAG_NUMBER(n) ((n) == SEC_ASN1_HIGH_TAG_NUMBER)
+#define LAST_TAG_NUMBER_BYTE(b) (((b)&0x80) == 0)
+#define TAG_NUMBER_BITS 7
+#define TAG_NUMBER_MASK 0x7f
+
+#define LENGTH_IS_SHORT_FORM(b) (((b)&0x80) == 0)
+#define LONG_FORM_LENGTH(b) ((b)&0x7f)
+
+#define HIGH_BITS(field, cnt) ((field) >> ((sizeof(field) * 8) - (cnt)))
+
+/*
+ * An "outsider" will have an opaque pointer to this, created by calling
+ * SEC_ASN1DecoderStart(). It will be passed back in to all subsequent
+ * calls to SEC_ASN1DecoderUpdate(), and when done it is passed to
+ * SEC_ASN1DecoderFinish().
+ */
+struct sec_DecoderContext_struct {
+ PLArenaPool *our_pool; /* for our internal allocs */
+ PLArenaPool *their_pool; /* for destination structure allocs */
+#ifdef SEC_ASN1D_FREE_ON_ERROR /* \
+ * XXX see comment below (by same \
+ * ifdef) that explains why this \
+ * does not work (need more smarts \
+ * in order to free back to mark) \
+ */
+ /*
+ * XXX how to make their_mark work in the case where they do NOT
+ * give us a pool pointer?
+ */
+ void *their_mark; /* free on error */
+#endif
+
+ sec_asn1d_state *current;
+ sec_asn1d_parse_status status;
+
+ /* The maximum size the caller is willing to allow a single element
+ * to be before returning an error.
+ *
+ * In the case of an indefinite length element, this is the sum total
+ * of all child elements.
+ *
+ * In the case of a definite length element, this represents the maximum
+ * size of the top-level element.
+ */
+ unsigned long max_element_size;
+
+ SEC_ASN1NotifyProc notify_proc; /* call before/after handling field */
+ void *notify_arg; /* argument to notify_proc */
+ PRBool during_notify; /* true during call to notify_proc */
+
+ SEC_ASN1WriteProc filter_proc; /* pass field bytes to this */
+ void *filter_arg; /* argument to that function */
+ PRBool filter_only; /* do not allocate/store fields */
+};
+
+/*
+ * XXX this is a fairly generic function that may belong elsewhere
+ */
+static void *
+sec_asn1d_alloc(PLArenaPool *poolp, unsigned long len)
+{
+ void *thing;
+
+ if (poolp != NULL) {
+ /*
+ * Allocate from the pool.
+ */
+ thing = PORT_ArenaAlloc(poolp, len);
+ } else {
+ /*
+ * Allocate generically.
+ */
+ thing = PORT_Alloc(len);
+ }
+
+ return thing;
+}
+
+/*
+ * XXX this is a fairly generic function that may belong elsewhere
+ */
+static void *
+sec_asn1d_zalloc(PLArenaPool *poolp, unsigned long len)
+{
+ void *thing;
+
+ thing = sec_asn1d_alloc(poolp, len);
+ if (thing != NULL)
+ PORT_Memset(thing, 0, len);
+ return thing;
+}
+
+static sec_asn1d_state *
+sec_asn1d_push_state(SEC_ASN1DecoderContext *cx,
+ const SEC_ASN1Template *theTemplate,
+ void *dest, PRBool new_depth)
+{
+ sec_asn1d_state *state, *new_state;
+
+ state = cx->current;
+
+ PORT_Assert(state == NULL || state->child == NULL);
+
+ if (state != NULL) {
+ PORT_Assert(state->our_mark == NULL);
+ state->our_mark = PORT_ArenaMark(cx->our_pool);
+ }
+
+ if (theTemplate == NULL) {
+ PORT_SetError(SEC_ERROR_BAD_TEMPLATE);
+ goto loser;
+ }
+
+ new_state = (sec_asn1d_state *)sec_asn1d_zalloc(cx->our_pool,
+ sizeof(*new_state));
+ if (new_state == NULL) {
+ goto loser;
+ }
+
+ new_state->top = cx;
+ new_state->parent = state;
+ new_state->theTemplate = theTemplate;
+ new_state->place = notInUse;
+ if (dest != NULL)
+ new_state->dest = (char *)dest + theTemplate->offset;
+
+ if (state != NULL) {
+ new_state->depth = state->depth;
+ if (new_depth) {
+ if (++new_state->depth > SEC_ASN1D_MAX_DEPTH) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ goto loser;
+ }
+ }
+ state->child = new_state;
+ }
+
+ cx->current = new_state;
+ return new_state;
+
+loser:
+ cx->status = decodeError;
+ if (state != NULL) {
+ PORT_ArenaRelease(cx->our_pool, state->our_mark);
+ state->our_mark = NULL;
+ }
+ return NULL;
+}
+
+static void
+sec_asn1d_scrub_state(sec_asn1d_state *state)
+{
+ /*
+ * Some default "scrubbing".
+ * XXX right set of initializations?
+ */
+ state->place = beforeIdentifier;
+ state->endofcontents = PR_FALSE;
+ state->indefinite = PR_FALSE;
+ state->missing = PR_FALSE;
+ PORT_Assert(state->consumed == 0);
+}
+
+static void
+sec_asn1d_notify_before(SEC_ASN1DecoderContext *cx, void *dest, int depth)
+{
+ if (cx->notify_proc == NULL)
+ return;
+
+ cx->during_notify = PR_TRUE;
+ (*cx->notify_proc)(cx->notify_arg, PR_TRUE, dest, depth);
+ cx->during_notify = PR_FALSE;
+}
+
+static void
+sec_asn1d_notify_after(SEC_ASN1DecoderContext *cx, void *dest, int depth)
+{
+ if (cx->notify_proc == NULL)
+ return;
+
+ cx->during_notify = PR_TRUE;
+ (*cx->notify_proc)(cx->notify_arg, PR_FALSE, dest, depth);
+ cx->during_notify = PR_FALSE;
+}
+
+static sec_asn1d_state *
+sec_asn1d_init_state_based_on_template(sec_asn1d_state *state)
+{
+ PRBool explicit, optional, universal;
+ unsigned char expect_tag_modifiers;
+ unsigned long encode_kind, under_kind;
+ unsigned long check_tag_mask, expect_tag_number;
+
+ /* XXX Check that both of these tests are really needed/appropriate. */
+ if (state == NULL || state->top->status == decodeError)
+ return state;
+
+ encode_kind = state->theTemplate->kind;
+
+ if (encode_kind & SEC_ASN1_SAVE) {
+ /*
+ * This is a "magic" field that saves away all bytes, allowing
+ * the immediately following field to still be decoded from this
+ * same spot -- sort of a fork.
+ */
+ /* check that there are no extraneous bits */
+ PORT_Assert(encode_kind == SEC_ASN1_SAVE);
+ if (state->top->filter_only) {
+ /*
+ * If we are not storing, then we do not do the SAVE field
+ * at all. Just move ahead to the "real" field instead,
+ * doing the appropriate notify calls before and after.
+ */
+ sec_asn1d_notify_after(state->top, state->dest, state->depth);
+ /*
+ * Since we are not storing, allow for our current dest value
+ * to be NULL. (This might not actually occur, but right now I
+ * cannot convince myself one way or the other.) If it is NULL,
+ * assume that our parent dest can help us out.
+ */
+ if (state->dest == NULL)
+ state->dest = state->parent->dest;
+ else
+ state->dest = (char *)state->dest - state->theTemplate->offset;
+ state->theTemplate++;
+ if (state->dest != NULL)
+ state->dest = (char *)state->dest + state->theTemplate->offset;
+ sec_asn1d_notify_before(state->top, state->dest, state->depth);
+ encode_kind = state->theTemplate->kind;
+ PORT_Assert((encode_kind & SEC_ASN1_SAVE) == 0);
+ } else {
+ sec_asn1d_scrub_state(state);
+ state->place = duringSaveEncoding;
+ state = sec_asn1d_push_state(state->top, SEC_AnyTemplate,
+ state->dest, PR_FALSE);
+ if (state != NULL)
+ state = sec_asn1d_init_state_based_on_template(state);
+ return state;
+ }
+ }
+
+ universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL)
+ ? PR_TRUE
+ : PR_FALSE;
+
+ explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE;
+ encode_kind &= ~SEC_ASN1_EXPLICIT;
+
+ optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE;
+ encode_kind &= ~SEC_ASN1_OPTIONAL;
+
+ PORT_Assert(!(explicit && universal)); /* bad templates */
+
+ encode_kind &= ~SEC_ASN1_DYNAMIC;
+ encode_kind &= ~SEC_ASN1_MAY_STREAM;
+
+ if (encode_kind & SEC_ASN1_CHOICE) {
+#if 0 /* XXX remove? */
+ sec_asn1d_state *child = sec_asn1d_push_state(state->top, state->theTemplate, state->dest, PR_FALSE);
+ if ((sec_asn1d_state *)NULL == child) {
+ return (sec_asn1d_state *)NULL;
+ }
+
+ child->allocate = state->allocate;
+ child->place = beforeChoice;
+ return child;
+#else
+ state->place = beforeChoice;
+ return state;
+#endif
+ }
+
+ if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal && !explicit)) {
+ const SEC_ASN1Template *subt;
+ void *dest;
+ PRBool child_allocate;
+
+ PORT_Assert((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0);
+
+ sec_asn1d_scrub_state(state);
+ child_allocate = PR_FALSE;
+
+ if (encode_kind & SEC_ASN1_POINTER) {
+ /*
+ * A POINTER means we need to allocate the destination for
+ * this field. But, since it may also be an optional field,
+ * we defer the allocation until later; we just record that
+ * it needs to be done.
+ *
+ * There are two possible scenarios here -- one is just a
+ * plain POINTER (kind of like INLINE, except with allocation)
+ * and the other is an implicitly-tagged POINTER. We don't
+ * need to do anything special here for the two cases, but
+ * since the template definition can be tricky, we do check
+ * that there are no extraneous bits set in encode_kind.
+ *
+ * XXX The same conditions which assert should set an error.
+ */
+ if (universal) {
+ /*
+ * "universal" means this entry is a standalone POINTER;
+ * there should be no other bits set in encode_kind.
+ */
+ PORT_Assert(encode_kind == SEC_ASN1_POINTER);
+ } else {
+ /*
+ * If we get here we have an implicitly-tagged field
+ * that needs to be put into a POINTER. The subtemplate
+ * will determine how to decode the field, but encode_kind
+ * describes the (implicit) tag we are looking for.
+ * The non-tag bits of encode_kind will be ignored by
+ * the code below; none of them should be set, however,
+ * except for the POINTER bit itself -- so check that.
+ */
+ PORT_Assert((encode_kind & ~SEC_ASN1_TAG_MASK) == SEC_ASN1_POINTER);
+ }
+ if (!state->top->filter_only)
+ child_allocate = PR_TRUE;
+ dest = NULL;
+ state->place = afterPointer;
+ } else {
+ dest = state->dest;
+ if (encode_kind & SEC_ASN1_INLINE) {
+ /* check that there are no extraneous bits */
+ PORT_Assert(encode_kind == SEC_ASN1_INLINE && !optional);
+ state->place = afterInline;
+ } else {
+ state->place = afterImplicit;
+ }
+ }
+
+ state->optional = optional;
+ subt = SEC_ASN1GetSubtemplate(state->theTemplate, state->dest, PR_FALSE);
+ state = sec_asn1d_push_state(state->top, subt, dest, PR_FALSE);
+ if (state == NULL)
+ return NULL;
+
+ state->allocate = child_allocate;
+
+ if (universal) {
+ state = sec_asn1d_init_state_based_on_template(state);
+ if (state != NULL) {
+ /*
+ * If this field is optional, we need to record that on
+ * the pushed child so it won't fail if the field isn't
+ * found. I can't think of a way that this new state
+ * could already have optional set (which we would wipe
+ * out below if our local optional is not set) -- but
+ * just to be sure, assert that it isn't set.
+ */
+ PORT_Assert(!state->optional);
+ state->optional = optional;
+ }
+ return state;
+ }
+
+ under_kind = state->theTemplate->kind;
+ under_kind &= ~SEC_ASN1_MAY_STREAM;
+ } else if (explicit) {
+ /*
+ * For explicit, we only need to match the encoding tag next,
+ * then we will push another state to handle the entire inner
+ * part. In this case, there is no underlying kind which plays
+ * any part in the determination of the outer, explicit tag.
+ * So we just set under_kind to 0, which is not a valid tag,
+ * and the rest of the tag matching stuff should be okay.
+ */
+ under_kind = 0;
+ } else {
+ /*
+ * Nothing special; the underlying kind and the given encoding
+ * information are the same.
+ */
+ under_kind = encode_kind;
+ }
+
+ /* XXX is this the right set of bits to test here? */
+ PORT_Assert((under_kind & (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_MAY_STREAM | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0);
+
+ if (encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) {
+ PORT_Assert(encode_kind == under_kind);
+ if (encode_kind & SEC_ASN1_SKIP) {
+ PORT_Assert(!optional);
+ PORT_Assert(encode_kind == SEC_ASN1_SKIP);
+ state->dest = NULL;
+ }
+ check_tag_mask = 0;
+ expect_tag_modifiers = 0;
+ expect_tag_number = 0;
+ } else {
+ check_tag_mask = SEC_ASN1_TAG_MASK;
+ expect_tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK & ~SEC_ASN1_TAGNUM_MASK;
+ /*
+ * XXX This assumes only single-octet identifiers. To handle
+ * the HIGH TAG form we would need to do some more work, especially
+ * in how to specify them in the template, because right now we
+ * do not provide a way to specify more *tag* bits in encode_kind.
+ */
+ expect_tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK;
+
+ switch (under_kind & SEC_ASN1_TAGNUM_MASK) {
+ case SEC_ASN1_SET:
+ /*
+ * XXX A plain old SET (as opposed to a SET OF) is not implemented.
+ * If it ever is, remove this assert...
+ */
+ PORT_Assert((under_kind & SEC_ASN1_GROUP) != 0);
+ /* fallthru */
+ case SEC_ASN1_SEQUENCE:
+ expect_tag_modifiers |= SEC_ASN1_CONSTRUCTED;
+ break;
+ case SEC_ASN1_BIT_STRING:
+ case SEC_ASN1_BMP_STRING:
+ case SEC_ASN1_GENERALIZED_TIME:
+ case SEC_ASN1_IA5_STRING:
+ case SEC_ASN1_OCTET_STRING:
+ case SEC_ASN1_PRINTABLE_STRING:
+ case SEC_ASN1_T61_STRING:
+ case SEC_ASN1_UNIVERSAL_STRING:
+ case SEC_ASN1_UTC_TIME:
+ case SEC_ASN1_UTF8_STRING:
+ case SEC_ASN1_VISIBLE_STRING:
+ check_tag_mask &= ~SEC_ASN1_CONSTRUCTED;
+ break;
+ }
+ }
+
+ state->check_tag_mask = check_tag_mask;
+ state->expect_tag_modifiers = expect_tag_modifiers;
+ state->expect_tag_number = expect_tag_number;
+ state->underlying_kind = under_kind;
+ state->explicit = explicit;
+ state->optional = optional;
+
+ sec_asn1d_scrub_state(state);
+
+ return state;
+}
+
+static sec_asn1d_state *
+sec_asn1d_get_enclosing_construct(sec_asn1d_state *state)
+{
+ for (state = state->parent; state; state = state->parent) {
+ sec_asn1d_parse_place place = state->place;
+ if (place != afterImplicit &&
+ place != afterPointer &&
+ place != afterInline &&
+ place != afterSaveEncoding &&
+ place != duringSaveEncoding &&
+ place != duringChoice) {
+
+ /* we've walked up the stack to a state that represents
+ ** the enclosing construct.
+ */
+ break;
+ }
+ }
+ return state;
+}
+
+static PRBool
+sec_asn1d_parent_allows_EOC(sec_asn1d_state *state)
+{
+ /* get state of enclosing construct. */
+ state = sec_asn1d_get_enclosing_construct(state);
+ if (state) {
+ sec_asn1d_parse_place place = state->place;
+ /* Is it one of the types that permits an unexpected EOC? */
+ int eoc_permitted =
+ (place == duringGroup ||
+ place == duringConstructedString ||
+ state->child->optional);
+ return (state->indefinite && eoc_permitted) ? PR_TRUE : PR_FALSE;
+ }
+ return PR_FALSE;
+}
+
+static unsigned long
+sec_asn1d_parse_identifier(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
+{
+ unsigned char byte;
+ unsigned char tag_number;
+
+ PORT_Assert(state->place == beforeIdentifier);
+
+ if (len == 0) {
+ state->top->status = needBytes;
+ return 0;
+ }
+
+ byte = (unsigned char)*buf;
+#ifdef DEBUG_ASN1D_STATES
+ {
+ int bufsize = 256;
+ char kindBuf[bufsize];
+ formatKind(byte, kindBuf, bufsize);
+ printf("Found tag %02x %s\n", byte, kindBuf);
+ }
+#endif
+ tag_number = byte & SEC_ASN1_TAGNUM_MASK;
+
+ if (IS_HIGH_TAG_NUMBER(tag_number)) {
+ state->place = duringIdentifier;
+ state->found_tag_number = 0;
+ /*
+ * Actually, we have no idea how many bytes are pending, but we
+ * do know that it is at least 1. That is all we know; we have
+ * to look at each byte to know if there is another, etc.
+ */
+ state->pending = 1;
+ } else {
+ if (byte == 0 && sec_asn1d_parent_allows_EOC(state)) {
+ /*
+ * Our parent has indefinite-length encoding, and the
+ * entire tag found is 0, so it seems that we have hit the
+ * end-of-contents octets. To handle this, we just change
+ * our state to that which expects to get the bytes of the
+ * end-of-contents octets and let that code re-read this byte
+ * so that our categorization of field types is correct.
+ * After that, our parent will then deal with everything else.
+ */
+ state->place = duringEndOfContents;
+ state->pending = 2;
+ state->found_tag_number = 0;
+ state->found_tag_modifiers = 0;
+ /*
+ * We might be an optional field that is, as we now find out,
+ * missing. Give our parent a clue that this happened.
+ */
+ if (state->optional)
+ state->missing = PR_TRUE;
+ return 0;
+ }
+ state->place = afterIdentifier;
+ state->found_tag_number = tag_number;
+ }
+ state->found_tag_modifiers = byte & ~SEC_ASN1_TAGNUM_MASK;
+
+ return 1;
+}
+
+static unsigned long
+sec_asn1d_parse_more_identifier(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
+{
+ unsigned char byte;
+ int count;
+
+ PORT_Assert(state->pending == 1);
+ PORT_Assert(state->place == duringIdentifier);
+
+ if (len == 0) {
+ state->top->status = needBytes;
+ return 0;
+ }
+
+ count = 0;
+
+ while (len && state->pending) {
+ if (HIGH_BITS(state->found_tag_number, TAG_NUMBER_BITS) != 0) {
+ /*
+ * The given high tag number overflows our container;
+ * just give up. This is not likely to *ever* happen.
+ */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
+
+ state->found_tag_number <<= TAG_NUMBER_BITS;
+
+ byte = (unsigned char)buf[count++];
+ state->found_tag_number |= (byte & TAG_NUMBER_MASK);
+
+ len--;
+ if (LAST_TAG_NUMBER_BYTE(byte))
+ state->pending = 0;
+ }
+
+ if (state->pending == 0)
+ state->place = afterIdentifier;
+
+ return count;
+}
+
+static void
+sec_asn1d_confirm_identifier(sec_asn1d_state *state)
+{
+ PRBool match;
+
+ PORT_Assert(state->place == afterIdentifier);
+
+ match = (PRBool)(((state->found_tag_modifiers & state->check_tag_mask) == state->expect_tag_modifiers) && ((state->found_tag_number & state->check_tag_mask) == state->expect_tag_number));
+ if (match) {
+ state->place = beforeLength;
+ } else {
+ if (state->optional) {
+ state->missing = PR_TRUE;
+ state->place = afterEndOfContents;
+ } else {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ }
+ }
+}
+
+static unsigned long
+sec_asn1d_parse_length(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
+{
+ unsigned char byte;
+
+ PORT_Assert(state->place == beforeLength);
+
+ if (len == 0) {
+ state->top->status = needBytes;
+ return 0;
+ }
+
+ /*
+ * The default/likely outcome. It may get adjusted below.
+ */
+ state->place = afterLength;
+
+ byte = (unsigned char)*buf;
+
+ if (LENGTH_IS_SHORT_FORM(byte)) {
+ state->contents_length = byte;
+ } else {
+ state->contents_length = 0;
+ state->pending = LONG_FORM_LENGTH(byte);
+ if (state->pending == 0) {
+ state->indefinite = PR_TRUE;
+ } else {
+ state->place = duringLength;
+ }
+ }
+
+ /* If we're parsing an ANY, SKIP, or SAVE template, and
+ ** the object being saved is definite length encoded and constructed,
+ ** there's no point in decoding that construct's members.
+ ** So, just forget it's constructed and treat it as primitive.
+ ** (SAVE appears as an ANY at this point)
+ */
+ if (!state->indefinite &&
+ (state->underlying_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP))) {
+ state->found_tag_modifiers &= ~SEC_ASN1_CONSTRUCTED;
+ }
+
+ return 1;
+}
+
+static unsigned long
+sec_asn1d_parse_more_length(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
+{
+ int count;
+
+ PORT_Assert(state->pending > 0);
+ PORT_Assert(state->place == duringLength);
+
+ if (len == 0) {
+ state->top->status = needBytes;
+ return 0;
+ }
+
+ count = 0;
+
+ while (len && state->pending) {
+ if (HIGH_BITS(state->contents_length, 9) != 0) {
+ /*
+ * The given full content length overflows our container;
+ * just give up.
+ */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
+
+ state->contents_length <<= 8;
+ state->contents_length |= (unsigned char)buf[count++];
+
+ len--;
+ state->pending--;
+ }
+
+ if (state->pending == 0)
+ state->place = afterLength;
+
+ return count;
+}
+
+/*
+ * Helper function for sec_asn1d_prepare_for_contents.
+ * Checks that a value representing a number of bytes consumed can be
+ * subtracted from a remaining length. If so, returns PR_TRUE.
+ * Otherwise, sets the error SEC_ERROR_BAD_DER, indicates that there was a
+ * decoding error in the given SEC_ASN1DecoderContext, and returns PR_FALSE.
+ */
+static PRBool
+sec_asn1d_check_and_subtract_length(unsigned long *remaining,
+ unsigned long consumed,
+ SEC_ASN1DecoderContext *cx)
+{
+ PORT_Assert(remaining);
+ PORT_Assert(cx);
+ if (!remaining || !cx) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ cx->status = decodeError;
+ return PR_FALSE;
+ }
+ if (*remaining < consumed) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ cx->status = decodeError;
+ return PR_FALSE;
+ }
+ *remaining -= consumed;
+ return PR_TRUE;
+}
+
+static void
+sec_asn1d_prepare_for_contents(sec_asn1d_state *state)
+{
+ SECItem *item;
+ PLArenaPool *poolp;
+ unsigned long alloc_len;
+ sec_asn1d_state *parent;
+
+#ifdef DEBUG_ASN1D_STATES
+ {
+ printf("Found Length %lu %s\n", state->contents_length,
+ state->indefinite ? "indefinite" : "");
+ }
+#endif
+
+ /**
+ * The maximum length for a child element should be constrained to the
+ * length remaining in the first definite length element in the ancestor
+ * stack. If there is no definite length element in the ancestor stack,
+ * there's nothing to constrain the length of the child, so there's no
+ * further processing necessary.
+ *
+ * It's necessary to walk the ancestor stack, because it's possible to have
+ * definite length children that are part of an indefinite length element,
+ * which is itself part of an indefinite length element, and which is
+ * ultimately part of a definite length element. A simple example of this
+ * would be the handling of constructed OCTET STRINGs in BER encoding.
+ *
+ * This algorithm finds the first definite length element in the ancestor
+ * stack, if any, and if so, ensures that the length of the child element
+ * is consistent with the number of bytes remaining in the constraining
+ * ancestor element (that is, after accounting for any other sibling
+ * elements that may have been read).
+ *
+ * It's slightly complicated by the need to account both for integer
+ * underflow and overflow, as well as ensure that for indefinite length
+ * encodings, there's also enough space for the End-of-Contents (EOC)
+ * octets (Tag = 0x00, Length = 0x00, or two bytes).
+ */
+
+ /* Determine the maximum length available for this element by finding the
+ * first definite length ancestor, if any. */
+ parent = sec_asn1d_get_enclosing_construct(state);
+ while (parent && parent->indefinite) {
+ parent = sec_asn1d_get_enclosing_construct(parent);
+ }
+ /* If parent is null, state is either the outermost state / at the top of
+ * the stack, or the outermost state uses indefinite length encoding. In
+ * these cases, there's nothing external to constrain this element, so
+ * there's nothing to check. */
+ if (parent) {
+ unsigned long remaining = parent->pending;
+ parent = state;
+ do {
+ if (!sec_asn1d_check_and_subtract_length(
+ &remaining, parent->consumed, state->top) ||
+ /* If parent->indefinite is true, parent->contents_length is
+ * zero and this is a no-op. */
+ !sec_asn1d_check_and_subtract_length(
+ &remaining, parent->contents_length, state->top) ||
+ /* If parent->indefinite is true, then ensure there is enough
+ * space for an EOC tag of 2 bytes. */
+ (parent->indefinite && !sec_asn1d_check_and_subtract_length(&remaining, 2, state->top))) {
+ /* This element is larger than its enclosing element, which is
+ * invalid. */
+ return;
+ }
+ } while ((parent = sec_asn1d_get_enclosing_construct(parent)) &&
+ parent->indefinite);
+ }
+
+ /*
+ * XXX I cannot decide if this allocation should exclude the case
+ * where state->endofcontents is true -- figure it out!
+ */
+ if (state->allocate) {
+ void *dest;
+
+ PORT_Assert(state->dest == NULL);
+ /*
+ * We are handling a POINTER or a member of a GROUP, and need to
+ * allocate for the data structure.
+ */
+ dest = sec_asn1d_zalloc(state->top->their_pool,
+ state->theTemplate->size);
+ if (dest == NULL) {
+ state->top->status = decodeError;
+ return;
+ }
+ state->dest = (char *)dest + state->theTemplate->offset;
+
+ /*
+ * For a member of a GROUP, our parent will later put the
+ * pointer wherever it belongs. But for a POINTER, we need
+ * to record the destination now, in case notify or filter
+ * procs need access to it -- they cannot find it otherwise,
+ * until it is too late (for one-pass processing).
+ */
+ if (state->parent->place == afterPointer) {
+ void **placep;
+
+ placep = state->parent->dest;
+ *placep = dest;
+ }
+ }
+
+ /*
+ * Remember, length may be indefinite here! In that case,
+ * both contents_length and pending will be zero.
+ */
+ state->pending = state->contents_length;
+
+ /*
+ * An EXPLICIT is nothing but an outer header, which we have
+ * already parsed and accepted. Now we need to do the inner
+ * header and its contents.
+ */
+ if (state->explicit) {
+ state->place = afterExplicit;
+ state = sec_asn1d_push_state(state->top,
+ SEC_ASN1GetSubtemplate(state->theTemplate,
+ state->dest,
+ PR_FALSE),
+ state->dest, PR_TRUE);
+ if (state != NULL) {
+ (void)sec_asn1d_init_state_based_on_template(state);
+ }
+ return;
+ }
+
+ /*
+ * For GROUP (SET OF, SEQUENCE OF), even if we know the length here
+ * we cannot tell how many items we will end up with ... so push a
+ * state that can keep track of "children" (the individual members
+ * of the group; we will allocate as we go and put them all together
+ * at the end.
+ */
+ if (state->underlying_kind & SEC_ASN1_GROUP) {
+ /* XXX If this assertion holds (should be able to confirm it via
+ * inspection, too) then move this code into the switch statement
+ * below under cases SET_OF and SEQUENCE_OF; it will be cleaner.
+ */
+ PORT_Assert(state->underlying_kind == SEC_ASN1_SET_OF || state->underlying_kind == SEC_ASN1_SEQUENCE_OF || state->underlying_kind == (SEC_ASN1_SET_OF | SEC_ASN1_DYNAMIC) || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF | SEC_ASN1_DYNAMIC));
+ if (state->contents_length != 0 || state->indefinite) {
+ const SEC_ASN1Template *subt;
+
+ state->place = duringGroup;
+ subt = SEC_ASN1GetSubtemplate(state->theTemplate, state->dest,
+ PR_FALSE);
+ state = sec_asn1d_push_state(state->top, subt, NULL, PR_TRUE);
+ if (state != NULL) {
+ if (!state->top->filter_only)
+ state->allocate = PR_TRUE; /* XXX propogate this? */
+ /*
+ * Do the "before" field notification for next in group.
+ */
+ sec_asn1d_notify_before(state->top, state->dest, state->depth);
+ (void)sec_asn1d_init_state_based_on_template(state);
+ }
+ } else {
+ /*
+ * A group of zero; we are done.
+ * Set state to afterGroup and let that code plant the NULL.
+ */
+ state->place = afterGroup;
+ }
+ return;
+ }
+
+ switch (state->underlying_kind) {
+ case SEC_ASN1_SEQUENCE:
+ /*
+ * We need to push a child to handle the individual fields.
+ */
+ state->place = duringSequence;
+ state = sec_asn1d_push_state(state->top, state->theTemplate + 1,
+ state->dest, PR_TRUE);
+ if (state != NULL) {
+ /*
+ * Do the "before" field notification.
+ */
+ sec_asn1d_notify_before(state->top, state->dest, state->depth);
+ (void)sec_asn1d_init_state_based_on_template(state);
+ }
+ break;
+
+ case SEC_ASN1_SET: /* XXX SET is not really implemented */
+ /*
+ * XXX A plain SET requires special handling; scanning of a
+ * template to see where a field should go (because by definition,
+ * they are not in any particular order, and you have to look at
+ * each tag to disambiguate what the field is). We may never
+ * implement this because in practice, it seems to be unused.
+ */
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_BAD_DER); /* XXX */
+ state->top->status = decodeError;
+ break;
+
+ case SEC_ASN1_NULL:
+ /*
+ * The NULL type, by definition, is "nothing", content length of zero.
+ * An indefinite-length encoding is not alloweed.
+ */
+ if (state->contents_length || state->indefinite) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ break;
+ }
+ if (state->dest != NULL) {
+ item = (SECItem *)(state->dest);
+ item->data = NULL;
+ item->len = 0;
+ }
+ state->place = afterEndOfContents;
+ break;
+
+ case SEC_ASN1_BMP_STRING:
+ /* Error if length is not divisable by 2 */
+ if (state->contents_length % 2) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ break;
+ }
+ /* otherwise, handle as other string types */
+ goto regular_string_type;
+
+ case SEC_ASN1_UNIVERSAL_STRING:
+ /* Error if length is not divisable by 4 */
+ if (state->contents_length % 4) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ break;
+ }
+ /* otherwise, handle as other string types */
+ goto regular_string_type;
+
+ case SEC_ASN1_SKIP:
+ case SEC_ASN1_ANY:
+ case SEC_ASN1_ANY_CONTENTS:
+ /*
+ * These are not (necessarily) strings, but they need nearly
+ * identical handling (especially when we need to deal with
+ * constructed sub-pieces), so we pretend they are.
+ */
+ /* fallthru */
+ regular_string_type:
+ case SEC_ASN1_BIT_STRING:
+ case SEC_ASN1_IA5_STRING:
+ case SEC_ASN1_OCTET_STRING:
+ case SEC_ASN1_PRINTABLE_STRING:
+ case SEC_ASN1_T61_STRING:
+ case SEC_ASN1_UTC_TIME:
+ case SEC_ASN1_UTF8_STRING:
+ case SEC_ASN1_VISIBLE_STRING:
+ /*
+ * We are allocating for a primitive or a constructed string.
+ * If it is a constructed string, it may also be indefinite-length.
+ * If it is primitive, the length can (legally) be zero.
+ * Our first order of business is to allocate the memory for
+ * the string, if we can (if we know the length).
+ */
+ item = (SECItem *)(state->dest);
+
+ /*
+ * If the item is a definite-length constructed string, then
+ * the contents_length is actually larger than what we need
+ * (because it also counts each intermediate header which we
+ * will be throwing away as we go), but it is a perfectly good
+ * upper bound that we just allocate anyway, and then concat
+ * as we go; we end up wasting a few extra bytes but save a
+ * whole other copy.
+ */
+ alloc_len = state->contents_length;
+ poolp = NULL; /* quiet compiler warnings about unused... */
+
+ if (item == NULL || state->top->filter_only) {
+ if (item != NULL) {
+ item->data = NULL;
+ item->len = 0;
+ }
+ alloc_len = 0;
+ } else if (state->substring) {
+ /*
+ * If we are a substring of a constructed string, then we may
+ * not have to allocate anything (because our parent, the
+ * actual constructed string, did it for us). If we are a
+ * substring and we *do* have to allocate, that means our
+ * parent is an indefinite-length, so we allocate from our pool;
+ * later our parent will copy our string into the aggregated
+ * whole and free our pool allocation.
+ */
+ if (item->data == NULL) {
+ PORT_Assert(item->len == 0);
+ poolp = state->top->our_pool;
+ } else {
+ alloc_len = 0;
+ }
+ } else {
+ item->len = 0;
+ item->data = NULL;
+ poolp = state->top->their_pool;
+ }
+
+ if (alloc_len || ((!state->indefinite) && (state->subitems_head != NULL))) {
+ struct subitem *subitem;
+ int len;
+
+ PORT_Assert(item);
+ if (!item) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
+ PORT_Assert(item->len == 0 && item->data == NULL);
+ /*
+ * Check for and handle an ANY which has stashed aside the
+ * header (identifier and length) bytes for us to include
+ * in the saved contents.
+ */
+ if (state->subitems_head != NULL) {
+ PORT_Assert(state->underlying_kind == SEC_ASN1_ANY);
+ for (subitem = state->subitems_head;
+ subitem != NULL; subitem = subitem->next)
+ alloc_len += subitem->len;
+ }
+
+ if (state->top->max_element_size > 0 &&
+ alloc_len > state->top->max_element_size) {
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ state->top->status = decodeError;
+ return;
+ }
+
+ item->data = (unsigned char *)sec_asn1d_zalloc(poolp, alloc_len);
+ if (item->data == NULL) {
+ state->top->status = decodeError;
+ break;
+ }
+
+ len = 0;
+ for (subitem = state->subitems_head;
+ subitem != NULL; subitem = subitem->next) {
+ PORT_Memcpy(item->data + len, subitem->data, subitem->len);
+ len += subitem->len;
+ }
+ item->len = len;
+
+ /*
+ * Because we use arenas and have a mark set, we later free
+ * everything we have allocated, so this does *not* present
+ * a memory leak (it is just temporarily left dangling).
+ */
+ state->subitems_head = state->subitems_tail = NULL;
+ }
+
+ if (state->contents_length == 0 && (!state->indefinite)) {
+ /*
+ * A zero-length simple or constructed string; we are done.
+ */
+ state->place = afterEndOfContents;
+ } else if (state->found_tag_modifiers & SEC_ASN1_CONSTRUCTED) {
+ const SEC_ASN1Template *sub;
+
+ switch (state->underlying_kind) {
+ case SEC_ASN1_ANY:
+ case SEC_ASN1_ANY_CONTENTS:
+ sub = SEC_AnyTemplate;
+ break;
+ case SEC_ASN1_BIT_STRING:
+ sub = SEC_BitStringTemplate;
+ break;
+ case SEC_ASN1_BMP_STRING:
+ sub = SEC_BMPStringTemplate;
+ break;
+ case SEC_ASN1_GENERALIZED_TIME:
+ sub = SEC_GeneralizedTimeTemplate;
+ break;
+ case SEC_ASN1_IA5_STRING:
+ sub = SEC_IA5StringTemplate;
+ break;
+ case SEC_ASN1_OCTET_STRING:
+ sub = SEC_OctetStringTemplate;
+ break;
+ case SEC_ASN1_PRINTABLE_STRING:
+ sub = SEC_PrintableStringTemplate;
+ break;
+ case SEC_ASN1_T61_STRING:
+ sub = SEC_T61StringTemplate;
+ break;
+ case SEC_ASN1_UNIVERSAL_STRING:
+ sub = SEC_UniversalStringTemplate;
+ break;
+ case SEC_ASN1_UTC_TIME:
+ sub = SEC_UTCTimeTemplate;
+ break;
+ case SEC_ASN1_UTF8_STRING:
+ sub = SEC_UTF8StringTemplate;
+ break;
+ case SEC_ASN1_VISIBLE_STRING:
+ sub = SEC_VisibleStringTemplate;
+ break;
+ case SEC_ASN1_SKIP:
+ sub = SEC_SkipTemplate;
+ break;
+ default: /* redundant given outer switch cases, but */
+ PORT_Assert(0); /* the compiler does not seem to know that, */
+ sub = NULL; /* so just do enough to quiet it. */
+ break;
+ }
+
+ state->place = duringConstructedString;
+ state = sec_asn1d_push_state(state->top, sub, item, PR_TRUE);
+ if (state != NULL) {
+ state->substring = PR_TRUE; /* XXX propogate? */
+ (void)sec_asn1d_init_state_based_on_template(state);
+ }
+ } else if (state->indefinite) {
+ /*
+ * An indefinite-length string *must* be constructed!
+ */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ } else {
+ /*
+ * A non-zero-length simple string.
+ */
+ if (state->underlying_kind == SEC_ASN1_BIT_STRING)
+ state->place = beforeBitString;
+ else
+ state->place = duringLeaf;
+ }
+ break;
+
+ default:
+ /*
+ * We are allocating for a simple leaf item.
+ */
+ if (state->contents_length) {
+ if (state->dest != NULL) {
+ item = (SECItem *)(state->dest);
+ item->len = 0;
+ if (state->top->max_element_size > 0 &&
+ state->contents_length > state->top->max_element_size) {
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ state->top->status = decodeError;
+ return;
+ }
+
+ if (state->top->filter_only) {
+ item->data = NULL;
+ } else {
+ item->data = (unsigned char *)
+ sec_asn1d_zalloc(state->top->their_pool,
+ state->contents_length);
+ if (item->data == NULL) {
+ state->top->status = decodeError;
+ return;
+ }
+ }
+ }
+ state->place = duringLeaf;
+ } else {
+ /*
+ * An indefinite-length or zero-length item is not allowed.
+ * (All legal cases of such were handled above.)
+ */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ }
+ }
+}
+
+static void
+sec_asn1d_free_child(sec_asn1d_state *state, PRBool error)
+{
+ if (state->child != NULL) {
+ PORT_Assert(error || state->child->consumed == 0);
+ PORT_Assert(state->our_mark != NULL);
+ PORT_ArenaZRelease(state->top->our_pool, state->our_mark);
+ if (error && state->top->their_pool == NULL) {
+ /*
+ * XXX We need to free anything allocated.
+ * At this point, we failed in the middle of decoding. But we
+ * can't free the data we previously allocated with PR_Malloc
+ * unless we keep track of every pointer. So instead we have a
+ * memory leak when decoding fails half-way, unless an arena is
+ * used. See bug 95311 .
+ */
+ }
+ state->child = NULL;
+ state->our_mark = NULL;
+ } else {
+ /*
+ * It is important that we do not leave a mark unreleased/unmarked.
+ * But I do not think we should ever have one set in this case, only
+ * if we had a child (handled above). So check for that. If this
+ * assertion should ever get hit, then we probably need to add code
+ * here to release back to our_mark (and then set our_mark to NULL).
+ */
+ PORT_Assert(state->our_mark == NULL);
+ }
+ state->place = beforeEndOfContents;
+}
+
+/* We have just saved an entire encoded ASN.1 object (type) for a SAVE
+** template, and now in the next template, we are going to decode that
+** saved data by calling SEC_ASN1DecoderUpdate recursively.
+** If that recursive call fails with needBytes, it is a fatal error,
+** because the encoded object should have been complete.
+** If that recursive call fails with decodeError, it will have already
+** cleaned up the state stack, so we must bail out quickly.
+**
+** These checks of the status returned by the recursive call are now
+** done in the caller of this function, immediately after it returns.
+*/
+static void
+sec_asn1d_reuse_encoding(sec_asn1d_state *state)
+{
+ sec_asn1d_state *child;
+ unsigned long consumed;
+ SECItem *item;
+ void *dest;
+
+ child = state->child;
+ PORT_Assert(child != NULL);
+
+ consumed = child->consumed;
+ child->consumed = 0;
+
+ item = (SECItem *)(state->dest);
+ PORT_Assert(item != NULL);
+
+ PORT_Assert(item->len == consumed);
+
+ /*
+ * Free any grandchild.
+ */
+ sec_asn1d_free_child(child, PR_FALSE);
+
+ /*
+ * Notify after the SAVE field.
+ */
+ sec_asn1d_notify_after(state->top, state->dest, state->depth);
+
+ /*
+ * Adjust to get new dest and move forward.
+ */
+ dest = (char *)state->dest - state->theTemplate->offset;
+ state->theTemplate++;
+ child->dest = (char *)dest + state->theTemplate->offset;
+ child->theTemplate = state->theTemplate;
+
+ /*
+ * Notify before the "real" field.
+ */
+ PORT_Assert(state->depth == child->depth);
+ sec_asn1d_notify_before(state->top, child->dest, child->depth);
+
+ /*
+ * This will tell DecoderUpdate to return when it is done.
+ */
+ state->place = afterSaveEncoding;
+
+ /*
+ * We already have a child; "push" it by making it current.
+ */
+ state->top->current = child;
+
+ /*
+ * And initialize it so it is ready to parse.
+ */
+ (void)sec_asn1d_init_state_based_on_template(child);
+
+ /*
+ * Now parse that out of our data.
+ */
+ if (SEC_ASN1DecoderUpdate(state->top,
+ (char *)item->data, item->len) != SECSuccess)
+ return;
+ if (state->top->status == needBytes) {
+ return;
+ }
+
+ PORT_Assert(state->top->current == state);
+ PORT_Assert(state->child == child);
+
+ /*
+ * That should have consumed what we consumed before.
+ */
+ PORT_Assert(consumed == child->consumed);
+ child->consumed = 0;
+
+ /*
+ * Done.
+ */
+ state->consumed += consumed;
+ child->place = notInUse;
+ state->place = afterEndOfContents;
+}
+
+static unsigned long
+sec_asn1d_parse_leaf(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
+{
+ SECItem *item;
+ unsigned long bufLen;
+
+ if (len == 0) {
+ state->top->status = needBytes;
+ return 0;
+ }
+
+ if (state->pending < len)
+ len = state->pending;
+
+ bufLen = len;
+
+ item = (SECItem *)(state->dest);
+ if (item != NULL && item->data != NULL) {
+ unsigned long offset;
+ /* Strip leading zeroes when target is unsigned integer */
+ if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */
+ item->len == 0 && /* MSB */
+ item->type == siUnsignedInteger) /* unsigned */
+ {
+ while (len > 1 && buf[0] == 0) { /* leading 0 */
+ buf++;
+ len--;
+ }
+ }
+ offset = item->len;
+ if (state->underlying_kind == SEC_ASN1_BIT_STRING) {
+ // The previous bit string must have no unused bits.
+ if (item->len & 0x7) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
+ // If this is a bit string, the length is bits, not bytes.
+ offset = item->len >> 3;
+ }
+ if (state->underlying_kind == SEC_ASN1_BIT_STRING) {
+ unsigned long len_in_bits;
+ // Protect against overflow during the bytes-to-bits conversion.
+ if (len >= (ULONG_MAX >> 3) + 1) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
+ len_in_bits = (len << 3) - state->bit_string_unused_bits;
+ // Protect against overflow when computing the total length in bits.
+ if (UINT_MAX - item->len < len_in_bits) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
+ item->len += len_in_bits;
+ } else {
+ if (UINT_MAX - item->len < len) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
+ item->len += len;
+ }
+ PORT_Memcpy(item->data + offset, buf, len);
+ }
+ state->pending -= bufLen;
+ if (state->pending == 0)
+ state->place = beforeEndOfContents;
+
+ return bufLen;
+}
+
+static unsigned long
+sec_asn1d_parse_bit_string(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
+{
+ unsigned char byte;
+
+ /*PORT_Assert (state->pending > 0); */
+ PORT_Assert(state->place == beforeBitString);
+
+ if (state->pending == 0) {
+ if (state->dest != NULL) {
+ SECItem *item = (SECItem *)(state->dest);
+ item->data = NULL;
+ item->len = 0;
+ state->place = beforeEndOfContents;
+ return 0;
+ }
+ }
+
+ if (len == 0) {
+ state->top->status = needBytes;
+ return 0;
+ }
+
+ byte = (unsigned char)*buf;
+ if (byte > 7) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
+
+ state->bit_string_unused_bits = byte;
+ state->place = duringBitString;
+ state->pending -= 1;
+
+ return 1;
+}
+
+static unsigned long
+sec_asn1d_parse_more_bit_string(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
+{
+ PORT_Assert(state->place == duringBitString);
+ if (state->pending == 0) {
+ /* An empty bit string with some unused bits is invalid. */
+ if (state->bit_string_unused_bits) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ } else {
+ /* An empty bit string with no unused bits is OK. */
+ state->place = beforeEndOfContents;
+ }
+ return 0;
+ }
+
+ len = sec_asn1d_parse_leaf(state, buf, len);
+ return len;
+}
+
+/*
+ * XXX All callers should be looking at return value to detect
+ * out-of-memory errors (and stop!).
+ */
+static struct subitem *
+sec_asn1d_add_to_subitems(sec_asn1d_state *state,
+ const void *data, unsigned long len,
+ PRBool copy_data)
+{
+ struct subitem *thing;
+
+ thing = (struct subitem *)sec_asn1d_zalloc(state->top->our_pool,
+ sizeof(struct subitem));
+ if (thing == NULL) {
+ state->top->status = decodeError;
+ return NULL;
+ }
+
+ if (copy_data) {
+ void *copy;
+ copy = sec_asn1d_alloc(state->top->our_pool, len);
+ if (copy == NULL) {
+ state->top->status = decodeError;
+ if (!state->top->our_pool)
+ PORT_Free(thing);
+ return NULL;
+ }
+ PORT_Memcpy(copy, data, len);
+ thing->data = copy;
+ } else {
+ thing->data = data;
+ }
+ thing->len = len;
+ thing->next = NULL;
+
+ if (state->subitems_head == NULL) {
+ PORT_Assert(state->subitems_tail == NULL);
+ state->subitems_head = state->subitems_tail = thing;
+ } else {
+ state->subitems_tail->next = thing;
+ state->subitems_tail = thing;
+ }
+
+ return thing;
+}
+
+static void
+sec_asn1d_record_any_header(sec_asn1d_state *state,
+ const char *buf,
+ unsigned long len)
+{
+ SECItem *item;
+
+ item = (SECItem *)(state->dest);
+ if (item != NULL && item->data != NULL) {
+ PORT_Assert(state->substring);
+ PORT_Memcpy(item->data + item->len, buf, len);
+ item->len += len;
+ } else {
+ sec_asn1d_add_to_subitems(state, buf, len, PR_TRUE);
+ }
+}
+
+/*
+ * We are moving along through the substrings of a constructed string,
+ * and have just finished parsing one -- we need to save our child data
+ * (if the child was not already writing directly into the destination)
+ * and then move forward by one.
+ *
+ * We also have to detect when we are done:
+ * - a definite-length encoding stops when our pending value hits 0
+ * - an indefinite-length encoding stops when our child is empty
+ * (which means it was the end-of-contents octets)
+ */
+static void
+sec_asn1d_next_substring(sec_asn1d_state *state)
+{
+ sec_asn1d_state *child;
+ SECItem *item;
+ unsigned long child_consumed;
+ PRBool done;
+
+ PORT_Assert(state->place == duringConstructedString);
+ PORT_Assert(state->child != NULL);
+
+ child = state->child;
+
+ child_consumed = child->consumed;
+ child->consumed = 0;
+ state->consumed += child_consumed;
+
+ done = PR_FALSE;
+
+ if (state->pending) {
+ PORT_Assert(!state->indefinite);
+ if (child_consumed > state->pending) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
+
+ state->pending -= child_consumed;
+ if (state->pending == 0)
+ done = PR_TRUE;
+ } else {
+ PRBool preallocatedString;
+ sec_asn1d_state *temp_state;
+ PORT_Assert(state->indefinite);
+
+ item = (SECItem *)(child->dest);
+
+ /**
+ * At this point, there's three states at play:
+ * child: The element that was just parsed
+ * state: The currently processed element
+ * 'parent' (aka state->parent): The enclosing construct
+ * of state, or NULL if this is the top-most element.
+ *
+ * This state handles both substrings of a constructed string AND
+ * child elements of items whose template type was that of
+ * SEC_ASN1_ANY, SEC_ASN1_SAVE, SEC_ASN1_ANY_CONTENTS, SEC_ASN1_SKIP
+ * template, as described in sec_asn1d_prepare_for_contents. For
+ * brevity, these will be referred to as 'string' and 'any' types.
+ *
+ * This leads to the following possibilities:
+ * 1: This element is an indefinite length string, part of a
+ * definite length string.
+ * 2: This element is an indefinite length string, part of an
+ * indefinite length string.
+ * 3: This element is an indefinite length any, part of a
+ * definite length any.
+ * 4: This element is an indefinite length any, part of an
+ * indefinite length any.
+ * 5: This element is an indefinite length any and does not
+ * meet any of the above criteria. Note that this would include
+ * an indefinite length string type matching an indefinite
+ * length any template.
+ *
+ * In Cases #1 and #3, the definite length 'parent' element will
+ * have allocated state->dest based on the parent elements definite
+ * size. During the processing of 'child', sec_asn1d_parse_leaf will
+ * have copied the (string, any) data directly into the offset of
+ * dest, as appropriate, so there's no need for this class to still
+ * store the child - it's already been processed.
+ *
+ * In Cases #2 and #4, dest will be set to the parent element's dest,
+ * but dest->data will not have been allocated yet, due to the
+ * indefinite length encoding. In this situation, it's necessary to
+ * hold onto child (and all other children) until the EOC, at which
+ * point, it becomes possible to compute 'state's overall length. Once
+ * 'state' has a computed length, this can then be fed to 'parent' (via
+ * this state), and then 'parent' can similarly compute the length of
+ * all of its children up to the EOC, which will ultimately transit to
+ * sec_asn1d_concat_substrings, determine the overall size needed,
+ * allocate, and copy the contents (of all of parent's children, which
+ * would include 'state', just as 'state' will have copied all of its
+ * children via sec_asn1d_concat_substrings)
+ *
+ * The final case, Case #5, will manifest in that item->data and
+ * item->len will be NULL/0, respectively, since this element was
+ * indefinite-length encoded. In that case, both the tag and length will
+ * already exist in state's subitems, via sec_asn1d_record_any_header,
+ * and so the contents (aka 'child') should be added to that list of
+ * items to concatenate in sec_asn1d_concat_substrings once the EOC
+ * is encountered.
+ *
+ * To distinguish #2/#4 from #1/#3, it's sufficient to walk the ancestor
+ * tree. If the current type is a string type, then the enclosing
+ * construct will be that same type (#1/#2). If the current type is an
+ * any type, then the enclosing construct is either an any type (#3/#4)
+ * or some other type (#5). Since this is BER, this nesting relationship
+ * between 'state' and 'parent' may go through several levels of
+ * constructed encoding, so continue walking the ancestor chain until a
+ * clear determination can be made.
+ *
+ * The variable preallocatedString is used to indicate Case #1/#3,
+ * indicating an in-place copy has already occurred, and Cases #2, #4,
+ * and #5 all have the same behaviour of adding a new substring.
+ */
+ preallocatedString = PR_FALSE;
+ temp_state = state;
+ while (temp_state && item == temp_state->dest && temp_state->indefinite) {
+ sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(temp_state);
+ if (!parent || parent->underlying_kind != temp_state->underlying_kind) {
+ /* Case #5 - Either this is a top-level construct or it is part
+ * of some other element (e.g. a SEQUENCE), in which case, a
+ * new item should be allocated. */
+ break;
+ }
+ if (!parent->indefinite) {
+ /* Cases #1 / #3 - A definite length ancestor exists, for which
+ * this is a substring that has already copied into dest. */
+ preallocatedString = PR_TRUE;
+ break;
+ }
+ if (!parent->substring) {
+ /* Cases #2 / #4 - If the parent is not a substring, but is
+ * indefinite, then there's nothing further up that may have
+ * preallocated dest, thus child will not have already
+ * been copied in place, therefore it's necessary to save child
+ * as a subitem. */
+ break;
+ }
+ temp_state = parent;
+ }
+ if (item != NULL && item->data != NULL && !preallocatedString) {
+ /*
+ * Save the string away for later concatenation.
+ */
+ PORT_Assert(item->data != NULL);
+ sec_asn1d_add_to_subitems(state, item->data, item->len, PR_FALSE);
+ /*
+ * Clear the child item for the next round.
+ */
+ item->data = NULL;
+ item->len = 0;
+ }
+
+ /*
+ * If our child was just our end-of-contents octets, we are done.
+ */
+ if (child->endofcontents)
+ done = PR_TRUE;
+ }
+
+ /*
+ * Stop or do the next one.
+ */
+ if (done) {
+ child->place = notInUse;
+ state->place = afterConstructedString;
+ } else {
+ sec_asn1d_scrub_state(child);
+ state->top->current = child;
+ }
+}
+
+/*
+ * We are doing a SET OF or SEQUENCE OF, and have just finished an item.
+ */
+static void
+sec_asn1d_next_in_group(sec_asn1d_state *state)
+{
+ sec_asn1d_state *child;
+ unsigned long child_consumed;
+
+ PORT_Assert(state->place == duringGroup);
+ PORT_Assert(state->child != NULL);
+
+ child = state->child;
+
+ child_consumed = child->consumed;
+ child->consumed = 0;
+ state->consumed += child_consumed;
+
+ /*
+ * If our child was just our end-of-contents octets, we are done.
+ */
+ if (child->endofcontents) {
+ /* XXX I removed the PORT_Assert (child->dest == NULL) because there
+ * was a bug in that a template that was a sequence of which also had
+ * a child of a sequence of, in an indefinite group was not working
+ * properly. This fix seems to work, (added the if statement below),
+ * and nothing appears broken, but I am putting this note here just
+ * in case. */
+ /*
+ * XXX No matter how many times I read that comment,
+ * I cannot figure out what case he was fixing. I believe what he
+ * did was deliberate, so I am loathe to touch it. I need to
+ * understand how it could ever be that child->dest != NULL but
+ * child->endofcontents is true, and why it is important to check
+ * that state->subitems_head is NULL. This really needs to be
+ * figured out, as I am not sure if the following code should be
+ * compensating for "offset", as is done a little farther below
+ * in the more normal case.
+ */
+ /*
+ * XXX We used to assert our overall state was that we were decoding
+ * an indefinite-length object here (state->indefinite == TRUE and no
+ * pending bytes in the decoder), but those assertions aren't correct
+ * as it's legitimate to wrap indefinite sequences inside definite ones
+ * and this code handles that case. Additionally, when compiled in
+ * release mode these assertions aren't checked anyway, yet function
+ * safely.
+ */
+ if (child->dest && !state->subitems_head) {
+ sec_asn1d_add_to_subitems(state, child->dest, 0, PR_FALSE);
+ child->dest = NULL;
+ }
+
+ child->place = notInUse;
+ state->place = afterGroup;
+ return;
+ }
+
+ /*
+ * Do the "after" field notification for next in group.
+ */
+ sec_asn1d_notify_after(state->top, child->dest, child->depth);
+
+ /*
+ * Save it away (unless we are not storing).
+ */
+ if (child->dest != NULL) {
+ void *dest;
+
+ dest = child->dest;
+ dest = (char *)dest - child->theTemplate->offset;
+ sec_asn1d_add_to_subitems(state, dest, 0, PR_FALSE);
+ child->dest = NULL;
+ }
+
+ /*
+ * Account for those bytes; see if we are done.
+ */
+ if (state->pending) {
+ PORT_Assert(!state->indefinite);
+ if (child_consumed > state->pending) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
+
+ state->pending -= child_consumed;
+ if (state->pending == 0) {
+ child->place = notInUse;
+ state->place = afterGroup;
+ return;
+ }
+ }
+
+ /*
+ * Do the "before" field notification for next item in group.
+ */
+ sec_asn1d_notify_before(state->top, child->dest, child->depth);
+
+ /*
+ * Now we do the next one.
+ */
+ sec_asn1d_scrub_state(child);
+
+ /* Initialize child state from the template */
+ sec_asn1d_init_state_based_on_template(child);
+
+ state->top->current = child;
+}
+
+/*
+ * We are moving along through a sequence; move forward by one,
+ * (detecting end-of-sequence when it happens).
+ * XXX The handling of "missing" is ugly. Fix it.
+ */
+static void
+sec_asn1d_next_in_sequence(sec_asn1d_state *state)
+{
+ sec_asn1d_state *child;
+ unsigned long child_consumed;
+ PRBool child_missing;
+
+ PORT_Assert(state->place == duringSequence);
+ PORT_Assert(state->child != NULL);
+
+ child = state->child;
+
+ /*
+ * Do the "after" field notification.
+ */
+ sec_asn1d_notify_after(state->top, child->dest, child->depth);
+
+ child_missing = (PRBool)child->missing;
+ child_consumed = child->consumed;
+ child->consumed = 0;
+
+ /*
+ * Take care of accounting.
+ */
+ if (child_missing) {
+ PORT_Assert(child->optional);
+ } else {
+ state->consumed += child_consumed;
+ /*
+ * Free any grandchild.
+ */
+ sec_asn1d_free_child(child, PR_FALSE);
+ if (state->pending) {
+ PORT_Assert(!state->indefinite);
+ if (child_consumed > state->pending) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
+ state->pending -= child_consumed;
+ if (state->pending == 0) {
+ child->theTemplate++;
+ while (child->theTemplate->kind != 0) {
+ if ((child->theTemplate->kind & SEC_ASN1_OPTIONAL) == 0) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
+ child->theTemplate++;
+ }
+ child->place = notInUse;
+ state->place = afterEndOfContents;
+ return;
+ }
+ }
+ }
+
+ /*
+ * Move forward.
+ */
+ child->theTemplate++;
+ if (child->theTemplate->kind == 0) {
+ /*
+ * We are done with this sequence.
+ */
+ child->place = notInUse;
+ if (state->pending) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ } else if (child_missing) {
+ /*
+ * We got to the end, but have a child that started parsing
+ * and ended up "missing". The only legitimate reason for
+ * this is that we had one or more optional fields at the
+ * end of our sequence, and we were encoded indefinite-length,
+ * so when we went looking for those optional fields we
+ * found our end-of-contents octets instead.
+ * (Yes, this is ugly; dunno a better way to handle it.)
+ * So, first confirm the situation, and then mark that we
+ * are done.
+ */
+ if (state->indefinite && child->endofcontents) {
+ PORT_Assert(child_consumed == 2);
+ if (child_consumed != 2) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ } else {
+ state->consumed += child_consumed;
+ state->place = afterEndOfContents;
+ }
+ } else {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ }
+ } else {
+ /*
+ * We have to finish out, maybe reading end-of-contents octets;
+ * let the normal logic do the right thing.
+ */
+ state->place = beforeEndOfContents;
+ }
+ } else {
+ unsigned char child_found_tag_modifiers = 0;
+ unsigned long child_found_tag_number = 0;
+
+ /*
+ * Reset state and push.
+ */
+ if (state->dest != NULL)
+ child->dest = (char *)state->dest + child->theTemplate->offset;
+
+ /*
+ * Do the "before" field notification.
+ */
+ sec_asn1d_notify_before(state->top, child->dest, child->depth);
+
+ if (child_missing) { /* if previous child was missing, copy the tag data we already have */
+ child_found_tag_modifiers = child->found_tag_modifiers;
+ child_found_tag_number = child->found_tag_number;
+ }
+ state->top->current = child;
+ child = sec_asn1d_init_state_based_on_template(child);
+ if (child_missing && child) {
+ child->place = afterIdentifier;
+ child->found_tag_modifiers = child_found_tag_modifiers;
+ child->found_tag_number = child_found_tag_number;
+ child->consumed = child_consumed;
+ if (child->underlying_kind == SEC_ASN1_ANY && !child->top->filter_only) {
+ /*
+ * If the new field is an ANY, and we are storing, then
+ * we need to save the tag out. We would have done this
+ * already in the normal case, but since we were looking
+ * for an optional field, and we did not find it, we only
+ * now realize we need to save the tag.
+ */
+ unsigned char identifier;
+
+ /*
+ * Check that we did not end up with a high tag; for that
+ * we need to re-encode the tag into multiple bytes in order
+ * to store it back to look like what we parsed originally.
+ * In practice this does not happen, but for completeness
+ * sake it should probably be made to work at some point.
+ */
+ if (child_found_tag_modifiers >= SEC_ASN1_HIGH_TAG_NUMBER) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ state->top->status = decodeError;
+ } else {
+ identifier = (unsigned char)(child_found_tag_modifiers | child_found_tag_number);
+ sec_asn1d_record_any_header(child, (char *)&identifier, 1);
+ }
+ }
+ }
+ }
+}
+
+static void
+sec_asn1d_concat_substrings(sec_asn1d_state *state)
+{
+ PORT_Assert(state->place == afterConstructedString);
+
+ if (state->subitems_head != NULL) {
+ struct subitem *substring;
+ unsigned long alloc_len, item_len;
+ unsigned char *where;
+ SECItem *item;
+ PRBool is_bit_string;
+
+ item_len = 0;
+ is_bit_string = (state->underlying_kind == SEC_ASN1_BIT_STRING)
+ ? PR_TRUE
+ : PR_FALSE;
+
+ substring = state->subitems_head;
+ while (substring != NULL) {
+ /*
+ * All bit-string substrings except the last one should be
+ * a clean multiple of 8 bits.
+ */
+ if (is_bit_string && (substring->next != NULL) && (substring->len & 0x7)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
+ item_len += substring->len;
+ substring = substring->next;
+ }
+
+ if (is_bit_string) {
+ alloc_len = ((item_len + 7) >> 3);
+ } else {
+ /*
+ * Add 2 for the end-of-contents octets of an indefinite-length
+ * ANY that is *not* also an INNER. Because we zero-allocate
+ * below, all we need to do is increase the length here.
+ */
+ if (state->underlying_kind == SEC_ASN1_ANY && state->indefinite)
+ item_len += 2;
+ alloc_len = item_len;
+ }
+
+ if (state->top->max_element_size > 0 &&
+ alloc_len > state->top->max_element_size) {
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ state->top->status = decodeError;
+ return;
+ }
+
+ item = (SECItem *)(state->dest);
+ PORT_Assert(item != NULL);
+ PORT_Assert(item->data == NULL);
+ item->data = (unsigned char *)sec_asn1d_zalloc(state->top->their_pool,
+ alloc_len);
+ if (item->data == NULL) {
+ state->top->status = decodeError;
+ return;
+ }
+ item->len = item_len;
+
+ where = item->data;
+ substring = state->subitems_head;
+ while (substring != NULL) {
+ if (is_bit_string)
+ item_len = (substring->len + 7) >> 3;
+ else
+ item_len = substring->len;
+ PORT_Memcpy(where, substring->data, item_len);
+ where += item_len;
+ substring = substring->next;
+ }
+
+ /*
+ * Because we use arenas and have a mark set, we later free
+ * everything we have allocated, so this does *not* present
+ * a memory leak (it is just temporarily left dangling).
+ */
+ state->subitems_head = state->subitems_tail = NULL;
+ }
+
+ state->place = afterEndOfContents;
+}
+
+static void
+sec_asn1d_concat_group(sec_asn1d_state *state)
+{
+ const void ***placep;
+
+ PORT_Assert(state->place == afterGroup);
+
+ placep = (const void ***)state->dest;
+ PORT_Assert(state->subitems_head == NULL || placep != NULL);
+ if (placep != NULL) {
+ struct subitem *item;
+ const void **group;
+ int count;
+
+ count = 0;
+ item = state->subitems_head;
+ while (item != NULL) {
+ PORT_Assert(item->next != NULL || item == state->subitems_tail);
+ count++;
+ item = item->next;
+ }
+
+ group = (const void **)sec_asn1d_zalloc(state->top->their_pool,
+ (count + 1) * (sizeof(void *)));
+ if (group == NULL) {
+ state->top->status = decodeError;
+ return;
+ }
+
+ *placep = group;
+
+ item = state->subitems_head;
+ while (item != NULL) {
+ *group++ = item->data;
+ item = item->next;
+ }
+ *group = NULL;
+
+ /*
+ * Because we use arenas and have a mark set, we later free
+ * everything we have allocated, so this does *not* present
+ * a memory leak (it is just temporarily left dangling).
+ */
+ state->subitems_head = state->subitems_tail = NULL;
+ }
+
+ state->place = afterEndOfContents;
+}
+
+/*
+ * For those states that push a child to handle a subtemplate,
+ * "absorb" that child (transfer necessary information).
+ */
+static void
+sec_asn1d_absorb_child(sec_asn1d_state *state)
+{
+ /*
+ * There is absolutely supposed to be a child there.
+ */
+ PORT_Assert(state->child != NULL);
+
+ /*
+ * Inherit the missing status of our child, and do the ugly
+ * backing-up if necessary.
+ */
+ state->missing = state->child->missing;
+ if (state->missing) {
+ state->found_tag_number = state->child->found_tag_number;
+ state->found_tag_modifiers = state->child->found_tag_modifiers;
+ state->endofcontents = state->child->endofcontents;
+ }
+
+ /*
+ * Add in number of bytes consumed by child.
+ * (Only EXPLICIT should have already consumed bytes itself.)
+ */
+ PORT_Assert(state->place == afterExplicit || state->consumed == 0);
+ state->consumed += state->child->consumed;
+
+ /*
+ * Subtract from bytes pending; this only applies to a definite-length
+ * EXPLICIT field.
+ */
+ if (state->pending) {
+ PORT_Assert(!state->indefinite);
+ PORT_Assert(state->place == afterExplicit);
+
+ /*
+ * If we had a definite-length explicit, then what the child
+ * consumed should be what was left pending.
+ */
+ if (state->pending != state->child->consumed) {
+ if (state->pending < state->child->consumed) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
+ /*
+ * Okay, this is a hack. It *should* be an error whether
+ * pending is too big or too small, but it turns out that
+ * we had a bug in our *old* DER encoder that ended up
+ * counting an explicit header twice in the case where
+ * the underlying type was an ANY. So, because we cannot
+ * prevent receiving these (our own certificate server can
+ * send them to us), we need to be lenient and accept them.
+ * To do so, we need to pretend as if we read all of the
+ * bytes that the header said we would find, even though
+ * we actually came up short.
+ */
+ state->consumed += (state->pending - state->child->consumed);
+ }
+ state->pending = 0;
+ }
+
+ /*
+ * Indicate that we are done with child.
+ */
+ state->child->consumed = 0;
+
+ /*
+ * And move on to final state.
+ * (Technically everybody could move to afterEndOfContents except
+ * for an indefinite-length EXPLICIT; for simplicity though we assert
+ * that but let the end-of-contents code do the real determination.)
+ */
+ PORT_Assert(state->place == afterExplicit || (!state->indefinite));
+ state->place = beforeEndOfContents;
+}
+
+static void
+sec_asn1d_prepare_for_end_of_contents(sec_asn1d_state *state)
+{
+ PORT_Assert(state->place == beforeEndOfContents);
+
+ if (state->indefinite) {
+ state->place = duringEndOfContents;
+ state->pending = 2;
+ } else {
+ state->place = afterEndOfContents;
+ }
+}
+
+static unsigned long
+sec_asn1d_parse_end_of_contents(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
+{
+ unsigned int i;
+
+ PORT_Assert(state->pending <= 2);
+ PORT_Assert(state->place == duringEndOfContents);
+
+ if (len == 0) {
+ state->top->status = needBytes;
+ return 0;
+ }
+
+ if (state->pending < len)
+ len = state->pending;
+
+ for (i = 0; i < len; i++) {
+ if (buf[i] != 0) {
+ /*
+ * We expect to find only zeros; if not, just give up.
+ */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
+ }
+
+ state->pending -= len;
+
+ if (state->pending == 0) {
+ state->place = afterEndOfContents;
+ /* These end-of-contents octets either terminate a SEQUENCE, a GROUP,
+ * or a constructed string. The SEQUENCE case is unique in that the
+ * state parses its own end-of-contents octets and therefore should not
+ * have its `endofcontents` flag set. We identify the SEQUENCE case by
+ * checking whether the child state's template is pointing at a
+ * template terminator (see `sec_asn1d_next_in_sequence`).
+ */
+ if (state->child && state->child->theTemplate->kind == 0) {
+ state->endofcontents = PR_FALSE;
+ } else {
+ state->endofcontents = PR_TRUE;
+ }
+ }
+
+ return len;
+}
+
+static void
+sec_asn1d_pop_state(sec_asn1d_state *state)
+{
+#if 0 /* XXX I think this should always be handled explicitly by parent? */
+ /*
+ * Account for our child.
+ */
+ if (state->child != NULL) {
+ state->consumed += state->child->consumed;
+ if (state->pending) {
+ PORT_Assert (!state->indefinite);
+ if (state->child->consumed > state->pending) {
+ PORT_SetError (SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ } else {
+ state->pending -= state->child->consumed;
+ }
+ }
+ state->child->consumed = 0;
+ }
+#endif /* XXX */
+
+ /*
+ * Free our child.
+ */
+ sec_asn1d_free_child(state, PR_FALSE);
+
+ /*
+ * Just make my parent be the current state. It will then clean
+ * up after me and free me (or reuse me).
+ */
+ state->top->current = state->parent;
+}
+
+static sec_asn1d_state *
+sec_asn1d_before_choice(sec_asn1d_state *state)
+{
+ sec_asn1d_state *child;
+
+ if (state->allocate) {
+ void *dest;
+
+ dest = sec_asn1d_zalloc(state->top->their_pool, state->theTemplate->size);
+ if ((void *)NULL == dest) {
+ state->top->status = decodeError;
+ return (sec_asn1d_state *)NULL;
+ }
+
+ state->dest = (char *)dest + state->theTemplate->offset;
+ }
+
+ child = sec_asn1d_push_state(state->top, state->theTemplate + 1,
+ (char *)state->dest - state->theTemplate->offset,
+ PR_FALSE);
+ if ((sec_asn1d_state *)NULL == child) {
+ return (sec_asn1d_state *)NULL;
+ }
+
+ sec_asn1d_scrub_state(child);
+ child = sec_asn1d_init_state_based_on_template(child);
+ if ((sec_asn1d_state *)NULL == child) {
+ return (sec_asn1d_state *)NULL;
+ }
+
+ child->optional = PR_TRUE;
+
+ state->place = duringChoice;
+
+ return child;
+}
+
+static sec_asn1d_state *
+sec_asn1d_during_choice(sec_asn1d_state *state)
+{
+ sec_asn1d_state *child = state->child;
+
+ PORT_Assert((sec_asn1d_state *)NULL != child);
+
+ if (child->missing) {
+ unsigned char child_found_tag_modifiers = 0;
+ unsigned long child_found_tag_number = 0;
+ void *dest;
+
+ state->consumed += child->consumed;
+
+ if (child->endofcontents) {
+ /* This choice is probably the first item in a GROUP
+ ** (e.g. SET_OF) that was indefinite-length encoded.
+ ** We're actually at the end of that GROUP.
+ ** We look up the stack to be sure that we find
+ ** a state with indefinite length encoding before we
+ ** find a state (like a SEQUENCE) that is definite.
+ */
+ child->place = notInUse;
+ state->place = afterChoice;
+ state->endofcontents = PR_TRUE; /* propagate this up */
+ if (sec_asn1d_parent_allows_EOC(state))
+ return state;
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return NULL;
+ }
+
+ dest = (char *)child->dest - child->theTemplate->offset;
+ child->theTemplate++;
+
+ if (0 == child->theTemplate->kind) {
+ /* Ran out of choices */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return (sec_asn1d_state *)NULL;
+ }
+ child->dest = (char *)dest + child->theTemplate->offset;
+
+ /* cargo'd from next_in_sequence innards */
+ if (state->pending) {
+ PORT_Assert(!state->indefinite);
+ if (child->consumed > state->pending) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return NULL;
+ }
+ state->pending -= child->consumed;
+ if (0 == state->pending) {
+ /* XXX uh.. not sure if I should have stopped this
+ * from happening before. */
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return (sec_asn1d_state *)NULL;
+ }
+ }
+
+ child->consumed = 0;
+ sec_asn1d_scrub_state(child);
+
+ /* move it on top again */
+ state->top->current = child;
+
+ child_found_tag_modifiers = child->found_tag_modifiers;
+ child_found_tag_number = child->found_tag_number;
+
+ child = sec_asn1d_init_state_based_on_template(child);
+ if ((sec_asn1d_state *)NULL == child) {
+ return (sec_asn1d_state *)NULL;
+ }
+
+ /* copy our findings to the new top */
+ child->found_tag_modifiers = child_found_tag_modifiers;
+ child->found_tag_number = child_found_tag_number;
+
+ child->optional = PR_TRUE;
+ child->place = afterIdentifier;
+
+ return child;
+ }
+ if ((void *)NULL != state->dest) {
+ /* Store the enum */
+ int *which = (int *)state->dest;
+ *which = (int)child->theTemplate->size;
+ }
+
+ child->place = notInUse;
+
+ state->place = afterChoice;
+ return state;
+}
+
+static void
+sec_asn1d_after_choice(sec_asn1d_state *state)
+{
+ state->consumed += state->child->consumed;
+ state->child->consumed = 0;
+ state->place = afterEndOfContents;
+ sec_asn1d_pop_state(state);
+}
+
+unsigned long
+sec_asn1d_uinteger(SECItem *src)
+{
+ unsigned long value;
+ int len;
+
+ if (src->len > 5 || (src->len > 4 && src->data[0] == 0))
+ return 0;
+
+ value = 0;
+ len = src->len;
+ while (len) {
+ value <<= 8;
+ value |= src->data[--len];
+ }
+ return value;
+}
+
+SECStatus
+SEC_ASN1DecodeInteger(SECItem *src, unsigned long *value)
+{
+ unsigned long v;
+ unsigned int i;
+
+ if (src == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (src->len > sizeof(unsigned long)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (src->data == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (src->data[0] & 0x80)
+ v = -1; /* signed and negative - start with all 1's */
+ else
+ v = 0;
+
+ for (i = 0; i < src->len; i++) {
+ /* shift in next byte */
+ v <<= 8;
+ v |= src->data[i];
+ }
+ *value = v;
+ return SECSuccess;
+}
+
+#ifdef DEBUG_ASN1D_STATES
+static void
+dump_states(SEC_ASN1DecoderContext *cx)
+{
+ sec_asn1d_state *state;
+ int bufsize = 256;
+ char kindBuf[bufsize];
+
+ for (state = cx->current; state->parent; state = state->parent) {
+ ;
+ }
+
+ for (; state; state = state->child) {
+ int i;
+ for (i = 0; i < state->depth; i++) {
+ printf(" ");
+ }
+
+ i = formatKind(state->theTemplate->kind, kindBuf, bufsize);
+ printf("%s: tmpl kind %s",
+ (state == cx->current) ? "STATE" : "State",
+ kindBuf);
+ printf(" %s", (state->place >= 0 && state->place <= notInUse) ? place_names[state->place] : "(undefined)");
+ if (!i)
+ printf(", expect 0x%02lx",
+ state->expect_tag_number | state->expect_tag_modifiers);
+
+ printf("%s%s%s %lu\n",
+ state->indefinite ? ", indef" : "",
+ state->missing ? ", miss" : "",
+ state->endofcontents ? ", EOC" : "",
+ state->pending);
+ }
+
+ return;
+}
+#endif /* DEBUG_ASN1D_STATES */
+
+SECStatus
+SEC_ASN1DecoderUpdate(SEC_ASN1DecoderContext *cx,
+ const char *buf, unsigned long len)
+{
+ sec_asn1d_state *state = NULL;
+ unsigned long consumed;
+ SEC_ASN1EncodingPart what;
+
+ if (cx->status == needBytes)
+ cx->status = keepGoing;
+
+ while (cx->status == keepGoing) {
+ state = cx->current;
+ what = SEC_ASN1_Contents;
+ consumed = 0;
+#ifdef DEBUG_ASN1D_STATES
+ printf("\nPLACE = %s, next byte = 0x%02x, %p[%lu]\n",
+ (state->place >= 0 && state->place <= notInUse) ? place_names[state->place] : "(undefined)",
+ len ? (unsigned int)((unsigned char *)buf)[consumed] : 0,
+ buf, consumed);
+ dump_states(cx);
+#endif /* DEBUG_ASN1D_STATES */
+ switch (state->place) {
+ case beforeIdentifier:
+ consumed = sec_asn1d_parse_identifier(state, buf, len);
+ what = SEC_ASN1_Identifier;
+ break;
+ case duringIdentifier:
+ consumed = sec_asn1d_parse_more_identifier(state, buf, len);
+ what = SEC_ASN1_Identifier;
+ break;
+ case afterIdentifier:
+ sec_asn1d_confirm_identifier(state);
+ break;
+ case beforeLength:
+ consumed = sec_asn1d_parse_length(state, buf, len);
+ what = SEC_ASN1_Length;
+ break;
+ case duringLength:
+ consumed = sec_asn1d_parse_more_length(state, buf, len);
+ what = SEC_ASN1_Length;
+ break;
+ case afterLength:
+ sec_asn1d_prepare_for_contents(state);
+ break;
+ case beforeBitString:
+ consumed = sec_asn1d_parse_bit_string(state, buf, len);
+ break;
+ case duringBitString:
+ consumed = sec_asn1d_parse_more_bit_string(state, buf, len);
+ break;
+ case duringConstructedString:
+ sec_asn1d_next_substring(state);
+ break;
+ case duringGroup:
+ sec_asn1d_next_in_group(state);
+ break;
+ case duringLeaf:
+ consumed = sec_asn1d_parse_leaf(state, buf, len);
+ break;
+ case duringSaveEncoding:
+ sec_asn1d_reuse_encoding(state);
+ if (cx->status == decodeError) {
+ /* recursive call has already popped all states from stack.
+ ** Bail out quickly.
+ */
+ return SECFailure;
+ }
+ if (cx->status == needBytes) {
+ /* recursive call wanted more data. Fatal. Clean up below. */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ cx->status = decodeError;
+ }
+ break;
+ case duringSequence:
+ sec_asn1d_next_in_sequence(state);
+ break;
+ case afterConstructedString:
+ sec_asn1d_concat_substrings(state);
+ break;
+ case afterExplicit:
+ case afterImplicit:
+ case afterInline:
+ case afterPointer:
+ sec_asn1d_absorb_child(state);
+ break;
+ case afterGroup:
+ sec_asn1d_concat_group(state);
+ break;
+ case afterSaveEncoding:
+ /* SEC_ASN1DecoderUpdate has called itself recursively to
+ ** decode SAVEd encoded data, and now is done decoding that.
+ ** Return to the calling copy of SEC_ASN1DecoderUpdate.
+ */
+ return SECSuccess;
+ case beforeEndOfContents:
+ sec_asn1d_prepare_for_end_of_contents(state);
+ break;
+ case duringEndOfContents:
+ consumed = sec_asn1d_parse_end_of_contents(state, buf, len);
+ what = SEC_ASN1_EndOfContents;
+ break;
+ case afterEndOfContents:
+ sec_asn1d_pop_state(state);
+ break;
+ case beforeChoice:
+ state = sec_asn1d_before_choice(state);
+ break;
+ case duringChoice:
+ state = sec_asn1d_during_choice(state);
+ break;
+ case afterChoice:
+ sec_asn1d_after_choice(state);
+ break;
+ case notInUse:
+ default:
+ /* This is not an error, but rather a plain old BUG! */
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ cx->status = decodeError;
+ break;
+ }
+
+ if (cx->status == decodeError)
+ break;
+
+ /* We should not consume more than we have. */
+ PORT_Assert(consumed <= len);
+ if (consumed > len) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ cx->status = decodeError;
+ break;
+ }
+
+ /* It might have changed, so we have to update our local copy. */
+ state = cx->current;
+
+ /* If it is NULL, we have popped all the way to the top. */
+ if (state == NULL) {
+ PORT_Assert(consumed == 0);
+#if 0 /* XXX I want this here, but it seems that we have situations (like \
+ * downloading a pkcs7 cert chain from some issuers) that give us a \
+ * length which is greater than the entire encoding. So, we cannot \
+ * have this be an error. \
+ */
+ if (len > 0) {
+ PORT_SetError (SEC_ERROR_BAD_DER);
+ cx->status = decodeError;
+ } else
+#endif
+ cx->status = allDone;
+ break;
+ } else if (state->theTemplate->kind == SEC_ASN1_SKIP_REST) {
+ cx->status = allDone;
+ break;
+ }
+
+ if (consumed == 0)
+ continue;
+
+ /*
+ * The following check is specifically looking for an ANY
+ * that is *not* also an INNER, because we need to save aside
+ * all bytes in that case -- the contents parts will get
+ * handled like all other contents, and the end-of-contents
+ * bytes are added by the concat code, but the outer header
+ * bytes need to get saved too, so we do them explicitly here.
+ */
+ if (state->underlying_kind == SEC_ASN1_ANY && !cx->filter_only && (what == SEC_ASN1_Identifier || what == SEC_ASN1_Length)) {
+ sec_asn1d_record_any_header(state, buf, consumed);
+ }
+
+ /*
+ * We had some number of good, accepted bytes. If the caller
+ * has registered to see them, pass them along.
+ */
+ if (state->top->filter_proc != NULL) {
+ int depth;
+
+ depth = state->depth;
+ if (what == SEC_ASN1_EndOfContents && !state->indefinite) {
+ PORT_Assert(state->parent != NULL && state->parent->indefinite);
+ depth--;
+ PORT_Assert(depth == state->parent->depth);
+ }
+ (*state->top->filter_proc)(state->top->filter_arg,
+ buf, consumed, depth, what);
+ }
+
+ state->consumed += consumed;
+ buf += consumed;
+ len -= consumed;
+ }
+
+ if (cx->status == decodeError) {
+ while (state != NULL) {
+ sec_asn1d_free_child(state, PR_TRUE);
+ state = state->parent;
+ }
+#ifdef SEC_ASN1D_FREE_ON_ERROR /* \
+ * XXX This does not work because we can \
+ * end up leaving behind dangling pointers \
+ * to stuff that was allocated. In order \
+ * to make this really work (which would \
+ * be a good thing, I think), we need to \
+ * keep track of every place/pointer that \
+ * was allocated and make sure to NULL it \
+ * out before we then free back to the mark. \
+ */
+ if (cx->their_pool != NULL) {
+ PORT_Assert(cx->their_mark != NULL);
+ PORT_ArenaRelease(cx->their_pool, cx->their_mark);
+ cx->their_mark = NULL;
+ }
+#endif
+ return SECFailure;
+ }
+
+#if 0 /* XXX This is what I want, but cannot have because it seems we \
+ * have situations (like when downloading a pkcs7 cert chain from \
+ * some issuers) that give us a total length which is greater than \
+ * the entire encoding. So, we have to allow allDone to have a \
+ * remaining length greater than zero. I wanted to catch internal \
+ * bugs with this, noticing when we do not have the right length. \
+ * Oh well. \
+ */
+ PORT_Assert (len == 0
+ && (cx->status == needBytes || cx->status == allDone));
+#else
+ PORT_Assert((len == 0 && cx->status == needBytes) || cx->status == allDone);
+#endif
+ return SECSuccess;
+}
+
+SECStatus
+SEC_ASN1DecoderFinish(SEC_ASN1DecoderContext *cx)
+{
+ SECStatus rv;
+
+ if (!cx || cx->status == needBytes) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ rv = SECFailure;
+ } else {
+ rv = SECSuccess;
+ }
+
+ /*
+ * XXX anything else that needs to be finished?
+ */
+
+ if (cx) {
+ PORT_FreeArena(cx->our_pool, PR_TRUE);
+ }
+
+ return rv;
+}
+
+SEC_ASN1DecoderContext *
+SEC_ASN1DecoderStart(PLArenaPool *their_pool, void *dest,
+ const SEC_ASN1Template *theTemplate)
+{
+ PLArenaPool *our_pool;
+ SEC_ASN1DecoderContext *cx;
+
+ our_pool = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (our_pool == NULL)
+ return NULL;
+
+ cx = (SEC_ASN1DecoderContext *)PORT_ArenaZAlloc(our_pool, sizeof(*cx));
+ if (cx == NULL) {
+ PORT_FreeArena(our_pool, PR_FALSE);
+ return NULL;
+ }
+
+ cx->our_pool = our_pool;
+ if (their_pool != NULL) {
+ cx->their_pool = their_pool;
+#ifdef SEC_ASN1D_FREE_ON_ERROR
+ cx->their_mark = PORT_ArenaMark(their_pool);
+#endif
+ }
+
+ cx->status = needBytes;
+
+ if (sec_asn1d_push_state(cx, theTemplate, dest, PR_FALSE) == NULL || sec_asn1d_init_state_based_on_template(cx->current) == NULL) {
+ /*
+ * Trouble initializing (probably due to failed allocations)
+ * requires that we just give up.
+ */
+ PORT_FreeArena(our_pool, PR_FALSE);
+ return NULL;
+ }
+
+ return cx;
+}
+
+void
+SEC_ASN1DecoderSetFilterProc(SEC_ASN1DecoderContext *cx,
+ SEC_ASN1WriteProc fn, void *arg,
+ PRBool only)
+{
+ /* check that we are "between" fields here */
+ PORT_Assert(cx->during_notify);
+
+ cx->filter_proc = fn;
+ cx->filter_arg = arg;
+ cx->filter_only = only;
+}
+
+void
+SEC_ASN1DecoderClearFilterProc(SEC_ASN1DecoderContext *cx)
+{
+ /* check that we are "between" fields here */
+ PORT_Assert(cx->during_notify);
+
+ cx->filter_proc = NULL;
+ cx->filter_arg = NULL;
+ cx->filter_only = PR_FALSE;
+}
+
+void
+SEC_ASN1DecoderSetNotifyProc(SEC_ASN1DecoderContext *cx,
+ SEC_ASN1NotifyProc fn, void *arg)
+{
+ cx->notify_proc = fn;
+ cx->notify_arg = arg;
+}
+
+void
+SEC_ASN1DecoderClearNotifyProc(SEC_ASN1DecoderContext *cx)
+{
+ cx->notify_proc = NULL;
+ cx->notify_arg = NULL; /* not necessary; just being clean */
+}
+
+void
+SEC_ASN1DecoderSetMaximumElementSize(SEC_ASN1DecoderContext *cx,
+ unsigned long max_size)
+{
+ cx->max_element_size = max_size;
+}
+
+void
+SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error)
+{
+ PORT_Assert(cx);
+ PORT_SetError(error);
+ cx->status = decodeError;
+}
+
+SECStatus
+SEC_ASN1Decode(PLArenaPool *poolp, void *dest,
+ const SEC_ASN1Template *theTemplate,
+ const char *buf, long len)
+{
+ SEC_ASN1DecoderContext *dcx;
+ SECStatus urv, frv;
+
+ dcx = SEC_ASN1DecoderStart(poolp, dest, theTemplate);
+ if (dcx == NULL)
+ return SECFailure;
+
+ /* In one-shot mode, there's no possibility of streaming data beyond the
+ * length of len */
+ SEC_ASN1DecoderSetMaximumElementSize(dcx, len);
+
+ urv = SEC_ASN1DecoderUpdate(dcx, buf, len);
+ frv = SEC_ASN1DecoderFinish(dcx);
+
+ if (urv != SECSuccess)
+ return urv;
+
+ return frv;
+}
+
+SECStatus
+SEC_ASN1DecodeItem(PLArenaPool *poolp, void *dest,
+ const SEC_ASN1Template *theTemplate,
+ const SECItem *src)
+{
+ return SEC_ASN1Decode(poolp, dest, theTemplate,
+ (const char *)src->data, src->len);
+}
+
+#ifdef DEBUG_ASN1D_STATES
+void
+sec_asn1d_Assert(const char *s, const char *file, PRIntn ln)
+{
+ printf("Assertion failed, \"%s\", file %s, line %d\n", s, file, ln);
+ fflush(stdout);
+}
+#endif
+
+/*
+ * Generic templates for individual/simple items and pointers to
+ * and sets of same.
+ *
+ * If you need to add a new one, please note the following:
+ * - For each new basic type you should add *four* templates:
+ * one plain, one PointerTo, one SequenceOf and one SetOf.
+ * - If the new type can be constructed (meaning, it is a
+ * *string* type according to BER/DER rules), then you should
+ * or-in SEC_ASN1_MAY_STREAM to the type in the basic template.
+ * See the definition of the OctetString template for an example.
+ * - It may not be obvious, but these are in *alphabetical*
+ * order based on the SEC_ASN1_XXX name; so put new ones in
+ * the appropriate place.
+ */
+
+const SEC_ASN1Template SEC_SequenceOfAnyTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate }
+};
+
+#if 0
+
+const SEC_ASN1Template SEC_PointerToBitStringTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_BitStringTemplate }
+};
+
+const SEC_ASN1Template SEC_SequenceOfBitStringTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_BitStringTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfBitStringTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_BitStringTemplate }
+};
+
+const SEC_ASN1Template SEC_PointerToBMPStringTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_BMPStringTemplate }
+};
+
+const SEC_ASN1Template SEC_SequenceOfBMPStringTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_BMPStringTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfBMPStringTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_BMPStringTemplate }
+};
+
+const SEC_ASN1Template SEC_PointerToBooleanTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_BooleanTemplate }
+};
+
+const SEC_ASN1Template SEC_SequenceOfBooleanTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_BooleanTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfBooleanTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_BooleanTemplate }
+};
+
+#endif
+
+const SEC_ASN1Template SEC_EnumeratedTemplate[] = {
+ { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) }
+};
+
+const SEC_ASN1Template SEC_PointerToEnumeratedTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_EnumeratedTemplate }
+};
+
+#if 0
+
+const SEC_ASN1Template SEC_SequenceOfEnumeratedTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_EnumeratedTemplate }
+};
+
+#endif
+
+const SEC_ASN1Template SEC_SetOfEnumeratedTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_EnumeratedTemplate }
+};
+
+const SEC_ASN1Template SEC_PointerToGeneralizedTimeTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_GeneralizedTimeTemplate }
+};
+
+#if 0
+
+const SEC_ASN1Template SEC_SequenceOfGeneralizedTimeTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_GeneralizedTimeTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfGeneralizedTimeTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_GeneralizedTimeTemplate }
+};
+
+const SEC_ASN1Template SEC_PointerToIA5StringTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_IA5StringTemplate }
+};
+
+const SEC_ASN1Template SEC_SequenceOfIA5StringTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_IA5StringTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfIA5StringTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_IA5StringTemplate }
+};
+
+const SEC_ASN1Template SEC_PointerToIntegerTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_IntegerTemplate }
+};
+
+const SEC_ASN1Template SEC_SequenceOfIntegerTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_IntegerTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfIntegerTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_IntegerTemplate }
+};
+
+const SEC_ASN1Template SEC_PointerToNullTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_NullTemplate }
+};
+
+const SEC_ASN1Template SEC_SequenceOfNullTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_NullTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfNullTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_NullTemplate }
+};
+
+const SEC_ASN1Template SEC_PointerToObjectIDTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_ObjectIDTemplate }
+};
+
+#endif
+
+const SEC_ASN1Template SEC_SequenceOfObjectIDTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_ObjectIDTemplate }
+};
+
+#if 0
+
+const SEC_ASN1Template SEC_SetOfObjectIDTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_ObjectIDTemplate }
+};
+
+const SEC_ASN1Template SEC_SequenceOfOctetStringTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_OctetStringTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfOctetStringTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_OctetStringTemplate }
+};
+
+#endif
+
+const SEC_ASN1Template SEC_PrintableStringTemplate[] = {
+ { SEC_ASN1_PRINTABLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
+};
+
+#if 0
+
+const SEC_ASN1Template SEC_PointerToPrintableStringTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_PrintableStringTemplate }
+};
+
+const SEC_ASN1Template SEC_SequenceOfPrintableStringTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_PrintableStringTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfPrintableStringTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_PrintableStringTemplate }
+};
+
+#endif
+
+const SEC_ASN1Template SEC_T61StringTemplate[] = {
+ { SEC_ASN1_T61_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
+};
+
+#if 0
+
+const SEC_ASN1Template SEC_PointerToT61StringTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_T61StringTemplate }
+};
+
+const SEC_ASN1Template SEC_SequenceOfT61StringTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_T61StringTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfT61StringTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_T61StringTemplate }
+};
+
+#endif
+
+const SEC_ASN1Template SEC_UniversalStringTemplate[] = {
+ { SEC_ASN1_UNIVERSAL_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
+};
+
+#if 0
+
+const SEC_ASN1Template SEC_PointerToUniversalStringTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_UniversalStringTemplate }
+};
+
+const SEC_ASN1Template SEC_SequenceOfUniversalStringTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_UniversalStringTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfUniversalStringTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_UniversalStringTemplate }
+};
+
+const SEC_ASN1Template SEC_PointerToUTCTimeTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_UTCTimeTemplate }
+};
+
+const SEC_ASN1Template SEC_SequenceOfUTCTimeTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTCTimeTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfUTCTimeTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_UTCTimeTemplate }
+};
+
+const SEC_ASN1Template SEC_PointerToUTF8StringTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_UTF8StringTemplate }
+};
+
+const SEC_ASN1Template SEC_SequenceOfUTF8StringTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTF8StringTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfUTF8StringTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_UTF8StringTemplate }
+};
+
+#endif
+
+const SEC_ASN1Template SEC_VisibleStringTemplate[] = {
+ { SEC_ASN1_VISIBLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
+};
+
+#if 0
+
+const SEC_ASN1Template SEC_PointerToVisibleStringTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_VisibleStringTemplate }
+};
+
+const SEC_ASN1Template SEC_SequenceOfVisibleStringTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_VisibleStringTemplate }
+};
+
+const SEC_ASN1Template SEC_SetOfVisibleStringTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_VisibleStringTemplate }
+};
+
+#endif
+
+/*
+ * Template for skipping a subitem.
+ *
+ * Note that it only makes sense to use this for decoding (when you want
+ * to decode something where you are only interested in one or two of
+ * the fields); you cannot encode a SKIP!
+ */
+const SEC_ASN1Template SEC_SkipTemplate[] = {
+ { SEC_ASN1_SKIP }
+};
+
+/* These functions simply return the address of the above-declared templates.
+** This is necessary for Windows DLLs. Sigh.
+*/
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_EnumeratedTemplate)
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToEnumeratedTemplate)
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SequenceOfAnyTemplate)
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SequenceOfObjectIDTemplate)
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SkipTemplate)
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UniversalStringTemplate)
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PrintableStringTemplate)
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_T61StringTemplate)
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToGeneralizedTimeTemplate)
diff --git a/security/nss/lib/util/secasn1e.c b/security/nss/lib/util/secasn1e.c
new file mode 100644
index 0000000000..41d2848971
--- /dev/null
+++ b/security/nss/lib/util/secasn1e.c
@@ -0,0 +1,1572 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Support for ENcoding ASN.1 data based on BER/DER (Basic/Distinguished
+ * Encoding Rules).
+ */
+
+#include "secasn1.h"
+
+typedef enum {
+ beforeHeader,
+ duringContents,
+ duringGroup,
+ duringSequence,
+ afterContents,
+ afterImplicit,
+ afterInline,
+ afterPointer,
+ afterChoice,
+ notInUse
+} sec_asn1e_parse_place;
+
+typedef enum {
+ allDone,
+ encodeError,
+ keepGoing,
+ needBytes
+} sec_asn1e_parse_status;
+
+typedef enum {
+ hdr_normal = 0, /* encode header normally */
+ hdr_any = 1, /* header already encoded in content */
+ hdr_decoder = 2, /* template only used by decoder. skip it. */
+ hdr_optional = 3, /* optional component, to be omitted */
+ hdr_placeholder = 4 /* place holder for from_buf content */
+} sec_asn1e_hdr_encoding;
+
+typedef struct sec_asn1e_state_struct {
+ SEC_ASN1EncoderContext *top;
+ const SEC_ASN1Template *theTemplate;
+ void *src;
+
+ struct sec_asn1e_state_struct *parent; /* aka prev */
+ struct sec_asn1e_state_struct *child; /* aka next */
+
+ sec_asn1e_parse_place place; /* where we are in encoding process */
+
+ /*
+ * XXX explain the next fields as clearly as possible...
+ */
+ unsigned char tag_modifiers;
+ unsigned char tag_number;
+ unsigned long underlying_kind;
+
+ int depth;
+
+ PRBool isExplicit, /* we are handling an isExplicit header */
+ indefinite, /* need end-of-contents */
+ is_string, /* encoding a simple string or an ANY */
+ may_stream, /* when streaming, do indefinite encoding */
+ optional, /* omit field if it has no contents */
+ disallowStreaming; /* disallow streaming in all sub-templates */
+} sec_asn1e_state;
+
+/*
+ * An "outsider" will have an opaque pointer to this, created by calling
+ * SEC_ASN1EncoderStart(). It will be passed back in to all subsequent
+ * calls to SEC_ASN1EncoderUpdate() and related routines, and when done
+ * it is passed to SEC_ASN1EncoderFinish().
+ */
+struct sec_EncoderContext_struct {
+ PLArenaPool *our_pool; /* for our internal allocs */
+
+ sec_asn1e_state *current;
+ sec_asn1e_parse_status status;
+
+ PRBool streaming;
+ PRBool from_buf;
+
+ SEC_ASN1NotifyProc notify_proc; /* call before/after handling field */
+ void *notify_arg; /* argument to notify_proc */
+ PRBool during_notify; /* true during call to notify_proc */
+
+ SEC_ASN1WriteProc output_proc; /* pass encoded bytes to this */
+ void *output_arg; /* argument to that function */
+};
+
+static sec_asn1e_state *
+sec_asn1e_push_state(SEC_ASN1EncoderContext *cx,
+ const SEC_ASN1Template *theTemplate,
+ const void *src, PRBool new_depth)
+{
+ sec_asn1e_state *state, *new_state;
+
+ if (theTemplate == NULL) {
+ cx->status = encodeError;
+ return NULL;
+ }
+
+ state = cx->current;
+ new_state = (sec_asn1e_state *)PORT_ArenaZAlloc(cx->our_pool,
+ sizeof(*new_state));
+ if (new_state == NULL) {
+ cx->status = encodeError;
+ return NULL;
+ }
+
+ new_state->top = cx;
+ new_state->parent = state;
+ new_state->theTemplate = theTemplate;
+ new_state->place = notInUse;
+ if (src != NULL)
+ new_state->src = (char *)src + theTemplate->offset;
+
+ if (state != NULL) {
+ new_state->depth = state->depth;
+ if (new_depth)
+ new_state->depth++;
+ state->child = new_state;
+ }
+
+ cx->current = new_state;
+ return new_state;
+}
+
+static void
+sec_asn1e_scrub_state(sec_asn1e_state *state)
+{
+ /*
+ * Some default "scrubbing".
+ * XXX right set of initializations?
+ */
+ state->place = beforeHeader;
+ state->indefinite = PR_FALSE;
+}
+
+static void
+sec_asn1e_notify_before(SEC_ASN1EncoderContext *cx, void *src, int depth)
+{
+ if (cx->notify_proc == NULL)
+ return;
+
+ cx->during_notify = PR_TRUE;
+ (*cx->notify_proc)(cx->notify_arg, PR_TRUE, src, depth);
+ cx->during_notify = PR_FALSE;
+}
+
+static void
+sec_asn1e_notify_after(SEC_ASN1EncoderContext *cx, void *src, int depth)
+{
+ if (cx->notify_proc == NULL)
+ return;
+
+ cx->during_notify = PR_TRUE;
+ (*cx->notify_proc)(cx->notify_arg, PR_FALSE, src, depth);
+ cx->during_notify = PR_FALSE;
+}
+
+static sec_asn1e_state *
+sec_asn1e_init_state_based_on_template(sec_asn1e_state *state)
+{
+ PRBool isExplicit, is_string, may_stream, optional, universal;
+ PRBool disallowStreaming;
+ unsigned char tag_modifiers;
+ unsigned long encode_kind, under_kind;
+ unsigned long tag_number;
+ PRBool isInline = PR_FALSE;
+
+ encode_kind = state->theTemplate->kind;
+
+ universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL)
+ ? PR_TRUE
+ : PR_FALSE;
+
+ isExplicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE;
+ encode_kind &= ~SEC_ASN1_EXPLICIT;
+
+ optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE;
+ encode_kind &= ~SEC_ASN1_OPTIONAL;
+
+ PORT_Assert(!(isExplicit && universal)); /* bad templates */
+
+ may_stream = (encode_kind & SEC_ASN1_MAY_STREAM) ? PR_TRUE : PR_FALSE;
+ encode_kind &= ~SEC_ASN1_MAY_STREAM;
+
+ disallowStreaming = (encode_kind & SEC_ASN1_NO_STREAM) ? PR_TRUE : PR_FALSE;
+ encode_kind &= ~SEC_ASN1_NO_STREAM;
+
+ /* Just clear this to get it out of the way; we do not need it here */
+ encode_kind &= ~SEC_ASN1_DYNAMIC;
+
+ if (encode_kind & SEC_ASN1_CHOICE) {
+ under_kind = SEC_ASN1_CHOICE;
+ } else if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) ||
+ (!universal && !isExplicit)) {
+ const SEC_ASN1Template *subt;
+ void *src = NULL;
+
+ PORT_Assert((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0);
+
+ sec_asn1e_scrub_state(state);
+
+ if (encode_kind & SEC_ASN1_POINTER) {
+ src = *(void **)state->src;
+ state->place = afterPointer;
+
+ if (src == NULL) {
+ /*
+ * If this is optional, but NULL, then the field does
+ * not need to be encoded. In this case we are done;
+ * we do not want to push a subtemplate.
+ */
+ if (optional)
+ return state;
+
+ /*
+ * XXX this is an error; need to figure out
+ * how to handle this
+ */
+ }
+ } else {
+ src = state->src;
+ if (encode_kind & SEC_ASN1_INLINE) {
+ /* check that there are no extraneous bits */
+ /* PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional); */
+ state->place = afterInline;
+ isInline = PR_TRUE;
+ } else {
+ /*
+ * Save the tag modifiers and tag number here before moving
+ * on to the next state in case this is a member of a
+ * SEQUENCE OF
+ */
+ state->tag_modifiers = (unsigned char)(encode_kind & (SEC_ASN1_TAG_MASK & ~SEC_ASN1_TAGNUM_MASK));
+ state->tag_number = (unsigned char)(encode_kind & SEC_ASN1_TAGNUM_MASK);
+
+ state->place = afterImplicit;
+ state->optional = optional;
+ }
+ }
+
+ subt = SEC_ASN1GetSubtemplate(state->theTemplate, state->src, PR_TRUE);
+ if (isInline && optional) {
+ /* we only handle a very limited set of optional inline cases at
+ this time */
+ if (PR_FALSE != SEC_ASN1IsTemplateSimple(subt)) {
+ /* we now know that the target is a SECItem*, so we can check
+ if the source contains one */
+ SECItem *target = (SECItem *)state->src;
+ if (!target || !target->data || !target->len) {
+ /* no valid data to encode subtemplate */
+ return state;
+ }
+ } else {
+ PORT_Assert(0); /* complex templates are not handled as
+ inline optional */
+ }
+ }
+ state = sec_asn1e_push_state(state->top, subt, src, PR_FALSE);
+ if (state == NULL)
+ return state;
+
+ if (universal) {
+ /*
+ * This is a POINTER or INLINE; just init based on that
+ * and we are done.
+ */
+ return sec_asn1e_init_state_based_on_template(state);
+ }
+
+ /*
+ * This is an implicit, non-universal (meaning, application-private
+ * or context-specific) field. This results in a "magic" tag but
+ * encoding based on the underlying type. We pushed a new state
+ * that is based on the subtemplate (the underlying type), but
+ * now we will sort of alias it to give it some of our properties
+ * (tag, optional status, etc.).
+ *
+ * NB: ALL the following flags in the subtemplate are disallowed
+ * and/or ignored: EXPLICIT, OPTIONAL, INNER, INLINE, POINTER.
+ */
+
+ under_kind = state->theTemplate->kind;
+ if ((under_kind & SEC_ASN1_MAY_STREAM) && !disallowStreaming) {
+ may_stream = PR_TRUE;
+ }
+ under_kind &= ~(SEC_ASN1_MAY_STREAM | SEC_ASN1_DYNAMIC);
+ } else {
+ under_kind = encode_kind;
+ }
+
+/*
+ * Sanity check that there are no unwanted bits marked in under_kind.
+ * These bits were either removed above (after we recorded them) or
+ * they simply should not be found (signalling a bad/broken template).
+ * XXX is this the right set of bits to test here? (i.e. need to add
+ * or remove any?)
+ */
+#define UNEXPECTED_FLAGS \
+ (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_SKIP | SEC_ASN1_INNER | \
+ SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM | SEC_ASN1_INLINE | SEC_ASN1_POINTER)
+
+ PORT_Assert((under_kind & UNEXPECTED_FLAGS) == 0);
+ under_kind &= ~UNEXPECTED_FLAGS;
+#undef UNEXPECTED_FLAGS
+
+ if (encode_kind & SEC_ASN1_ANY) {
+ PORT_Assert(encode_kind == under_kind);
+ tag_modifiers = 0;
+ tag_number = 0;
+ is_string = PR_TRUE;
+ } else {
+ tag_modifiers = (unsigned char)(encode_kind & (SEC_ASN1_TAG_MASK & ~SEC_ASN1_TAGNUM_MASK));
+ /*
+ * XXX This assumes only single-octet identifiers. To handle
+ * the HIGH TAG form we would need to do some more work, especially
+ * in how to specify them in the template, because right now we
+ * do not provide a way to specify more *tag* bits in encode_kind.
+ */
+ tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK;
+
+ is_string = PR_FALSE;
+ switch (under_kind & SEC_ASN1_TAGNUM_MASK) {
+ case SEC_ASN1_SET:
+ /*
+ * XXX A plain old SET (as opposed to a SET OF) is not implemented.
+ * If it ever is, remove this assert...
+ */
+ PORT_Assert((under_kind & SEC_ASN1_GROUP) != 0);
+ /* fallthru */
+ case SEC_ASN1_SEQUENCE:
+ tag_modifiers |= SEC_ASN1_CONSTRUCTED;
+ break;
+ case SEC_ASN1_BIT_STRING:
+ case SEC_ASN1_BMP_STRING:
+ case SEC_ASN1_GENERALIZED_TIME:
+ case SEC_ASN1_IA5_STRING:
+ case SEC_ASN1_OCTET_STRING:
+ case SEC_ASN1_PRINTABLE_STRING:
+ case SEC_ASN1_T61_STRING:
+ case SEC_ASN1_UNIVERSAL_STRING:
+ case SEC_ASN1_UTC_TIME:
+ case SEC_ASN1_UTF8_STRING:
+ case SEC_ASN1_VISIBLE_STRING:
+ /*
+ * We do not yet know if we will be constructing the string,
+ * so we have to wait to do this final tag modification.
+ */
+ is_string = PR_TRUE;
+ break;
+ }
+ }
+
+ state->tag_modifiers = tag_modifiers;
+ state->tag_number = (unsigned char)tag_number;
+ state->underlying_kind = under_kind;
+ state->isExplicit = isExplicit;
+ state->may_stream = may_stream;
+ state->is_string = is_string;
+ state->optional = optional;
+ state->disallowStreaming = disallowStreaming;
+
+ sec_asn1e_scrub_state(state);
+
+ return state;
+}
+
+static void
+sec_asn1e_write_part(sec_asn1e_state *state,
+ const char *buf, unsigned long len,
+ SEC_ASN1EncodingPart part)
+{
+ SEC_ASN1EncoderContext *cx;
+
+ cx = state->top;
+ (*cx->output_proc)(cx->output_arg, buf, len, state->depth, part);
+}
+
+/*
+ * XXX This assumes only single-octet identifiers. To handle
+ * the HIGH TAG form we would need to modify this interface and
+ * teach it to properly encode the special form.
+ */
+static void
+sec_asn1e_write_identifier_bytes(sec_asn1e_state *state, unsigned char value)
+{
+ char byte;
+
+ byte = (char)value;
+ sec_asn1e_write_part(state, &byte, 1, SEC_ASN1_Identifier);
+}
+
+int
+SEC_ASN1EncodeLength(unsigned char *buf, int value)
+{
+ int lenlen;
+
+ lenlen = SEC_ASN1LengthLength(value);
+ if (lenlen == 1) {
+ buf[0] = value;
+ } else {
+ int i;
+
+ i = lenlen - 1;
+ buf[0] = 0x80 | i;
+ while (i) {
+ buf[i--] = value;
+ value >>= 8;
+ }
+ PORT_Assert(value == 0);
+ }
+ return lenlen;
+}
+
+static void
+sec_asn1e_write_length_bytes(sec_asn1e_state *state, unsigned long value,
+ PRBool indefinite)
+{
+ int lenlen;
+ unsigned char buf[sizeof(unsigned long) + 1];
+
+ if (indefinite) {
+ PORT_Assert(value == 0);
+ buf[0] = 0x80;
+ lenlen = 1;
+ } else {
+ lenlen = SEC_ASN1EncodeLength(buf, value);
+ }
+
+ sec_asn1e_write_part(state, (char *)buf, lenlen, SEC_ASN1_Length);
+}
+
+static void
+sec_asn1e_write_contents_bytes(sec_asn1e_state *state,
+ const char *buf, unsigned long len)
+{
+ sec_asn1e_write_part(state, buf, len, SEC_ASN1_Contents);
+}
+
+static void
+sec_asn1e_write_end_of_contents_bytes(sec_asn1e_state *state)
+{
+ const char eoc[2] = { 0, 0 };
+
+ sec_asn1e_write_part(state, eoc, 2, SEC_ASN1_EndOfContents);
+}
+
+static int
+sec_asn1e_which_choice(
+ void *src,
+ const SEC_ASN1Template *theTemplate)
+{
+ int rv;
+ unsigned int which = *(unsigned int *)src;
+
+ for (rv = 1, theTemplate++; theTemplate->kind != 0; rv++, theTemplate++) {
+ if (which == theTemplate->size) {
+ return rv;
+ }
+ }
+
+ return 0;
+}
+
+static unsigned long
+sec_asn1e_contents_length(const SEC_ASN1Template *theTemplate, void *src,
+ PRBool disallowStreaming, PRBool insideIndefinite,
+ sec_asn1e_hdr_encoding *pHdrException)
+{
+ unsigned long encode_kind, underlying_kind;
+ PRBool isExplicit, optional, universal, may_stream;
+ unsigned long len;
+
+ /*
+ * This function currently calculates the length in all cases
+ * except the following: when writing out the contents of a
+ * template that belongs to a state where it was a sub-template
+ * with the SEC_ASN1_MAY_STREAM bit set and it's parent had the
+ * optional bit set. The information that the parent is optional
+ * and that we should return the length of 0 when that length is
+ * present since that means the optional field is no longer present.
+ * So we add the disallowStreaming flag which is passed in when
+ * writing the contents, but for all recursive calls to
+ * sec_asn1e_contents_length, we pass PR_FALSE, because this
+ * function correctly calculates the length for children templates
+ * from that point on. Confused yet? At least you didn't have
+ * to figure it out. ;) -javi
+ */
+ encode_kind = theTemplate->kind;
+
+ universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL)
+ ? PR_TRUE
+ : PR_FALSE;
+
+ isExplicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE;
+ encode_kind &= ~SEC_ASN1_EXPLICIT;
+
+ optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE;
+ encode_kind &= ~SEC_ASN1_OPTIONAL;
+
+ PORT_Assert(!(isExplicit && universal)); /* bad templates */
+
+ may_stream = (encode_kind & SEC_ASN1_MAY_STREAM) ? PR_TRUE : PR_FALSE;
+ encode_kind &= ~SEC_ASN1_MAY_STREAM;
+
+ /* Just clear this to get it out of the way; we do not need it here */
+ encode_kind &= ~SEC_ASN1_DYNAMIC;
+
+ if (encode_kind & SEC_ASN1_NO_STREAM) {
+ disallowStreaming = PR_TRUE;
+ }
+ encode_kind &= ~SEC_ASN1_NO_STREAM;
+
+ if (encode_kind & SEC_ASN1_CHOICE) {
+ void *src2;
+ int indx = sec_asn1e_which_choice(src, theTemplate);
+ if (0 == indx) {
+ /* XXX set an error? "choice not found" */
+ /* state->top->status = encodeError; */
+ return 0;
+ }
+
+ src2 = (void *)((char *)src - theTemplate->offset + theTemplate[indx].offset);
+
+ return sec_asn1e_contents_length(&theTemplate[indx], src2,
+ disallowStreaming, insideIndefinite,
+ pHdrException);
+ }
+
+ if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || !universal) {
+ /* XXX any bits we want to disallow (PORT_Assert against) here? */
+ theTemplate = SEC_ASN1GetSubtemplate(theTemplate, src, PR_TRUE);
+ if (encode_kind & SEC_ASN1_POINTER) {
+ src = *(void **)src;
+ if (src == NULL) {
+ *pHdrException = optional ? hdr_optional : hdr_normal;
+ return 0;
+ }
+ } else if (encode_kind & SEC_ASN1_INLINE) {
+ /* check that there are no extraneous bits */
+ if (optional) {
+ if (PR_FALSE != SEC_ASN1IsTemplateSimple(theTemplate)) {
+ /* we now know that the target is a SECItem*, so we can check
+ if the source contains one */
+ SECItem *target = (SECItem *)src;
+ if (!target || !target->data || !target->len) {
+ /* no valid data to encode subtemplate */
+ *pHdrException = hdr_optional;
+ return 0;
+ }
+ } else {
+ PORT_Assert(0); /* complex templates not handled as inline
+ optional */
+ }
+ }
+ }
+
+ src = (char *)src + theTemplate->offset;
+
+ /* recurse to find the length of the subtemplate */
+ len = sec_asn1e_contents_length(theTemplate, src, disallowStreaming,
+ insideIndefinite, pHdrException);
+ if (len == 0 && optional) {
+ *pHdrException = hdr_optional;
+ } else if (isExplicit) {
+ if (*pHdrException == hdr_any) {
+ /* *we* do not want to add in a header,
+ ** but our caller still does.
+ */
+ *pHdrException = hdr_normal;
+ } else if (*pHdrException == hdr_normal) {
+ /* if the inner content exists, our length is
+ * len(identifier) + len(length) + len(innercontent)
+ * XXX we currently assume len(identifier) == 1;
+ * to support a high-tag-number this would need to be smarter.
+ */
+ len += 1 + SEC_ASN1LengthLength(len);
+ }
+ }
+ return len;
+ }
+ underlying_kind = encode_kind;
+
+ /* This is only used in decoding; it plays no part in encoding. */
+ if (underlying_kind & SEC_ASN1_SAVE) {
+ /* check that there are no extraneous bits */
+ PORT_Assert(underlying_kind == SEC_ASN1_SAVE);
+ *pHdrException = hdr_decoder;
+ return 0;
+ }
+
+#define UNEXPECTED_FLAGS \
+ (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_INLINE | SEC_ASN1_POINTER | \
+ SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM | SEC_ASN1_SAVE | SEC_ASN1_SKIP)
+
+ /* Having any of these bits is not expected here... */
+ PORT_Assert((underlying_kind & UNEXPECTED_FLAGS) == 0);
+ underlying_kind &= ~UNEXPECTED_FLAGS;
+#undef UNEXPECTED_FLAGS
+
+ if (underlying_kind & SEC_ASN1_CHOICE) {
+ void *src2;
+ int indx = sec_asn1e_which_choice(src, theTemplate);
+ if (0 == indx) {
+ /* XXX set an error? "choice not found" */
+ /* state->top->status = encodeError; */
+ return 0;
+ }
+
+ src2 = (void *)((char *)src - theTemplate->offset + theTemplate[indx].offset);
+ len = sec_asn1e_contents_length(&theTemplate[indx], src2,
+ disallowStreaming, insideIndefinite,
+ pHdrException);
+ } else {
+ switch (underlying_kind) {
+ case SEC_ASN1_SEQUENCE_OF:
+ case SEC_ASN1_SET_OF: {
+ const SEC_ASN1Template *tmpt;
+ void *sub_src;
+ unsigned long sub_len;
+ void **group;
+
+ len = 0;
+
+ group = *(void ***)src;
+ if (group == NULL)
+ break;
+
+ tmpt = SEC_ASN1GetSubtemplate(theTemplate, src, PR_TRUE);
+
+ for (; *group != NULL; group++) {
+ sub_src = (char *)(*group) + tmpt->offset;
+ sub_len = sec_asn1e_contents_length(tmpt, sub_src,
+ disallowStreaming,
+ insideIndefinite,
+ pHdrException);
+ len += sub_len;
+ /*
+ * XXX The 1 below is the presumed length of the identifier;
+ * to support a high-tag-number this would need to be smarter.
+ */
+ if (*pHdrException == hdr_normal)
+ len += 1 + SEC_ASN1LengthLength(sub_len);
+ }
+ } break;
+
+ case SEC_ASN1_SEQUENCE:
+ case SEC_ASN1_SET: {
+ const SEC_ASN1Template *tmpt;
+ void *sub_src;
+ unsigned long sub_len;
+
+ len = 0;
+ for (tmpt = theTemplate + 1; tmpt->kind; tmpt++) {
+ sub_src = (char *)src + tmpt->offset;
+ sub_len = sec_asn1e_contents_length(tmpt, sub_src,
+ disallowStreaming,
+ insideIndefinite,
+ pHdrException);
+ len += sub_len;
+ /*
+ * XXX The 1 below is the presumed length of the identifier;
+ * to support a high-tag-number this would need to be smarter.
+ */
+ if (*pHdrException == hdr_normal)
+ len += 1 + SEC_ASN1LengthLength(sub_len);
+ }
+ } break;
+
+ case SEC_ASN1_BIT_STRING:
+ /* convert bit length to byte */
+ len = (((SECItem *)src)->len + 7) >> 3;
+ /* bit string contents involve an extra octet */
+ if (len)
+ len++;
+ break;
+
+ case SEC_ASN1_INTEGER:
+ /* ASN.1 INTEGERs are signed.
+ * If the source is an unsigned integer, the encoder will need
+ * to handle the conversion here.
+ */
+ {
+ unsigned char *buf = ((SECItem *)src)->data;
+ SECItemType integerType = ((SECItem *)src)->type;
+ len = ((SECItem *)src)->len;
+ while (len > 0) {
+ if (*buf != 0) {
+ if (*buf & 0x80 && integerType == siUnsignedInteger) {
+ len++; /* leading zero needed to make number signed */
+ }
+ break; /* reached beginning of number */
+ }
+ if (len == 1) {
+ break; /* the number 0 */
+ }
+ if (buf[1] & 0x80) {
+ break; /* leading zero already present */
+ }
+ /* extraneous leading zero, keep going */
+ buf++;
+ len--;
+ }
+ }
+ break;
+
+ default:
+ len = ((SECItem *)src)->len;
+ break;
+ } /* end switch */
+
+#ifndef WHAT_PROBLEM_DOES_THIS_SOLVE
+ /* if we're streaming, we may have a secitem w/len 0 as placeholder */
+ if (!len && insideIndefinite && may_stream && !disallowStreaming) {
+ len = 1;
+ }
+#endif
+ } /* end else */
+
+ if (len == 0 && optional)
+ *pHdrException = hdr_optional;
+ else if (underlying_kind == SEC_ASN1_ANY)
+ *pHdrException = hdr_any;
+ else
+ *pHdrException = hdr_normal;
+
+ return len;
+}
+
+static void
+sec_asn1e_write_header(sec_asn1e_state *state)
+{
+ unsigned long contents_length;
+ unsigned char tag_number, tag_modifiers;
+ sec_asn1e_hdr_encoding hdrException = hdr_normal;
+ PRBool indefinite = PR_FALSE;
+
+ PORT_Assert(state->place == beforeHeader);
+
+ tag_number = state->tag_number;
+ tag_modifiers = state->tag_modifiers;
+
+ if (state->underlying_kind == SEC_ASN1_ANY) {
+ state->place = duringContents;
+ return;
+ }
+
+ if (state->underlying_kind & SEC_ASN1_CHOICE) {
+ int indx = sec_asn1e_which_choice(state->src, state->theTemplate);
+ if (0 == indx) {
+ /* XXX set an error? "choice not found" */
+ state->top->status = encodeError;
+ return;
+ }
+ state->place = afterChoice;
+ state = sec_asn1e_push_state(state->top, &state->theTemplate[indx],
+ (char *)state->src - state->theTemplate->offset,
+ PR_TRUE);
+ if (state) {
+ /*
+ * Do the "before" field notification.
+ */
+ sec_asn1e_notify_before(state->top, state->src, state->depth);
+ (void)sec_asn1e_init_state_based_on_template(state);
+ }
+ return;
+ }
+
+ /* The !isString test below is apparently intended to ensure that all
+ ** constructed types receive indefinite length encoding.
+ */
+ indefinite = (PRBool)(state->top->streaming && state->may_stream &&
+ (state->top->from_buf || !state->is_string));
+
+ /*
+ * If we are doing a definite-length encoding, first we have to
+ * walk the data structure to calculate the entire contents length.
+ * If we are doing an indefinite-length encoding, we still need to
+ * know if the contents is:
+ * optional and to be omitted, or
+ * an ANY (header is pre-encoded), or
+ * a SAVE or some other kind of template used only by the decoder.
+ * So, we call this function either way.
+ */
+ contents_length = sec_asn1e_contents_length(state->theTemplate,
+ state->src,
+ state->disallowStreaming,
+ indefinite,
+ &hdrException);
+ /*
+ * We might be told explicitly not to put out a header.
+ * But it can also be the case, via a pushed subtemplate, that
+ * sec_asn1e_contents_length could not know that this field is
+ * really optional. So check for that explicitly, too.
+ */
+ if (hdrException != hdr_normal ||
+ (contents_length == 0 && state->optional)) {
+ state->place = afterContents;
+ if (state->top->streaming &&
+ state->may_stream &&
+ state->top->from_buf) {
+ /* we did not find an optional indefinite string, so we
+ * don't encode it. However, if TakeFromBuf is on, we stop
+ * here anyway to give our caller a chance to intercept at the
+ * same point where we would stop if the field were present.
+ */
+ state->top->status = needBytes;
+ }
+ return;
+ }
+
+ if (indefinite) {
+ /*
+ * We need to put out an indefinite-length encoding.
+ * The only universal types that can be constructed are SETs,
+ * SEQUENCEs, and strings; so check that it is one of those,
+ * or that it is not universal (e.g. context-specific).
+ */
+ state->indefinite = PR_TRUE;
+ PORT_Assert((tag_number == SEC_ASN1_SET) || (tag_number == SEC_ASN1_SEQUENCE) || ((tag_modifiers & SEC_ASN1_CLASS_MASK) != 0) || state->is_string);
+ tag_modifiers |= SEC_ASN1_CONSTRUCTED;
+ contents_length = 0;
+ }
+
+ sec_asn1e_write_identifier_bytes(state,
+ (unsigned char)(tag_number | tag_modifiers));
+ sec_asn1e_write_length_bytes(state, contents_length, state->indefinite);
+
+ if (contents_length == 0 && !state->indefinite) {
+ /*
+ * If no real contents to encode, then we are done with this field.
+ */
+ state->place = afterContents;
+ return;
+ }
+
+ /*
+ * An EXPLICIT is nothing but an outer header, which we have already
+ * written. Now we need to do the inner header and contents.
+ */
+ if (state->isExplicit) {
+ const SEC_ASN1Template *subt =
+ SEC_ASN1GetSubtemplate(state->theTemplate, state->src, PR_TRUE);
+ state->place = afterContents;
+ state = sec_asn1e_push_state(state->top, subt, state->src, PR_TRUE);
+ if (state != NULL) {
+ (void)sec_asn1e_init_state_based_on_template(state);
+ }
+ return;
+ }
+
+ switch (state->underlying_kind) {
+ case SEC_ASN1_SET_OF:
+ case SEC_ASN1_SEQUENCE_OF:
+ /*
+ * We need to push a child to handle each member.
+ */
+ {
+ void **group;
+ const SEC_ASN1Template *subt;
+
+ group = *(void ***)state->src;
+ if (group == NULL || *group == NULL) {
+ /*
+ * Group is empty; we are done.
+ */
+ state->place = afterContents;
+ return;
+ }
+ state->place = duringGroup;
+ subt = SEC_ASN1GetSubtemplate(state->theTemplate, state->src,
+ PR_TRUE);
+ state = sec_asn1e_push_state(state->top, subt, *group, PR_TRUE);
+ if (state != NULL) {
+ (void)sec_asn1e_init_state_based_on_template(state);
+ }
+ }
+ break;
+
+ case SEC_ASN1_SEQUENCE:
+ case SEC_ASN1_SET:
+ /*
+ * We need to push a child to handle the individual fields.
+ */
+ state->place = duringSequence;
+ state = sec_asn1e_push_state(state->top, state->theTemplate + 1,
+ state->src, PR_TRUE);
+ if (state != NULL) {
+ /*
+ * Do the "before" field notification.
+ */
+ sec_asn1e_notify_before(state->top, state->src, state->depth);
+ (void)sec_asn1e_init_state_based_on_template(state);
+ }
+ break;
+
+ default:
+ /*
+ * I think we do not need to do anything else.
+ * XXX Correct?
+ */
+ state->place = duringContents;
+ break;
+ }
+}
+
+static void
+sec_asn1e_write_contents_from_buf(sec_asn1e_state *state,
+ const char *buf, unsigned long len)
+{
+ PORT_Assert(state->place == duringContents);
+ PORT_Assert(state->top->from_buf);
+ PORT_Assert(state->may_stream && !state->disallowStreaming);
+
+ /*
+ * Probably they just turned on "take from buf", but have not
+ * yet given us any bytes. If there is nothing in the buffer
+ * then we have nothing to do but return and wait.
+ */
+ if (buf == NULL || len == 0) {
+ state->top->status = needBytes;
+ return;
+ }
+ /*
+ * We are streaming, reading from a passed-in buffer.
+ * This means we are encoding a simple string or an ANY.
+ * For the former, we need to put out a substring, with its
+ * own identifier and length. For an ANY, we just write it
+ * out as is (our caller is required to ensure that it
+ * is a properly encoded entity).
+ */
+ PORT_Assert(state->is_string); /* includes ANY */
+ if (state->underlying_kind != SEC_ASN1_ANY) {
+ unsigned char identifier;
+
+ /*
+ * Create the identifier based on underlying_kind. We cannot
+ * use tag_number and tag_modifiers because this can be an
+ * implicitly encoded field. In that case, the underlying
+ * substrings *are* encoded with their real tag.
+ */
+ identifier = (unsigned char)(state->underlying_kind & SEC_ASN1_TAG_MASK);
+ /*
+ * The underlying kind should just be a simple string; there
+ * should be no bits like CONTEXT_SPECIFIC or CONSTRUCTED set.
+ */
+ PORT_Assert((identifier & SEC_ASN1_TAGNUM_MASK) == identifier);
+ /*
+ * Write out the tag and length for the substring.
+ */
+ sec_asn1e_write_identifier_bytes(state, identifier);
+ if (state->underlying_kind == SEC_ASN1_BIT_STRING) {
+ char byte;
+ /*
+ * Assume we have a length in bytes but we need to output
+ * a proper bit string. This interface only works for bit
+ * strings that are full multiples of 8. If support for
+ * real, variable length bit strings is needed then the
+ * caller will have to know to pass in a bit length instead
+ * of a byte length and then this code will have to
+ * perform the encoding necessary (length written is length
+ * in bytes plus 1, and the first octet of string is the
+ * number of bits remaining between the end of the bit
+ * string and the next byte boundary).
+ */
+ sec_asn1e_write_length_bytes(state, len + 1, PR_FALSE);
+ byte = 0;
+ sec_asn1e_write_contents_bytes(state, &byte, 1);
+ } else {
+ sec_asn1e_write_length_bytes(state, len, PR_FALSE);
+ }
+ }
+ sec_asn1e_write_contents_bytes(state, buf, len);
+ state->top->status = needBytes;
+}
+
+static void
+sec_asn1e_write_contents(sec_asn1e_state *state)
+{
+ unsigned long len = 0;
+
+ PORT_Assert(state->place == duringContents);
+
+ switch (state->underlying_kind) {
+ case SEC_ASN1_SET:
+ case SEC_ASN1_SEQUENCE:
+ PORT_Assert(0);
+ break;
+
+ case SEC_ASN1_BIT_STRING: {
+ SECItem *item;
+ char rem;
+
+ item = (SECItem *)state->src;
+ len = (item->len + 7) >> 3;
+ rem = (unsigned char)((len << 3) - item->len); /* remaining bits */
+ sec_asn1e_write_contents_bytes(state, &rem, 1);
+ sec_asn1e_write_contents_bytes(state, (char *)item->data, len);
+ } break;
+
+ case SEC_ASN1_BMP_STRING:
+ /* The number of bytes must be divisable by 2 */
+ if ((((SECItem *)state->src)->len) % 2) {
+ SEC_ASN1EncoderContext *cx;
+
+ cx = state->top;
+ cx->status = encodeError;
+ break;
+ }
+ /* otherwise, fall through to write the content */
+ goto process_string;
+
+ case SEC_ASN1_UNIVERSAL_STRING:
+ /* The number of bytes must be divisable by 4 */
+ if ((((SECItem *)state->src)->len) % 4) {
+ SEC_ASN1EncoderContext *cx;
+
+ cx = state->top;
+ cx->status = encodeError;
+ break;
+ }
+ /* otherwise, fall through to write the content */
+ goto process_string;
+
+ case SEC_ASN1_INTEGER:
+ /* ASN.1 INTEGERs are signed. If the source is an unsigned
+ * integer, the encoder will need to handle the conversion here.
+ */
+ {
+ unsigned int blen;
+ unsigned char *buf;
+ SECItemType integerType;
+ blen = ((SECItem *)state->src)->len;
+ buf = ((SECItem *)state->src)->data;
+ integerType = ((SECItem *)state->src)->type;
+ while (blen > 0) {
+ if (*buf & 0x80 && integerType == siUnsignedInteger) {
+ char zero = 0; /* write a leading 0 */
+ sec_asn1e_write_contents_bytes(state, &zero, 1);
+ /* and then the remaining buffer */
+ sec_asn1e_write_contents_bytes(state,
+ (char *)buf, blen);
+ break;
+ }
+ /* Check three possibilities:
+ * 1. No leading zeros, msb of MSB is not 1;
+ * 2. The number is zero itself;
+ * 3. Encoding a signed integer with a leading zero,
+ * keep the zero so that the number is positive.
+ */
+ if (*buf != 0 ||
+ blen == 1 ||
+ (buf[1] & 0x80 && integerType != siUnsignedInteger)) {
+ sec_asn1e_write_contents_bytes(state,
+ (char *)buf, blen);
+ break;
+ }
+ /* byte is 0, continue */
+ buf++;
+ blen--;
+ }
+ }
+ /* done with this content */
+ break;
+
+ process_string:
+ default: {
+ SECItem *item;
+
+ item = (SECItem *)state->src;
+ sec_asn1e_write_contents_bytes(state, (char *)item->data,
+ item->len);
+ } break;
+ }
+ state->place = afterContents;
+}
+
+/*
+ * We are doing a SET OF or SEQUENCE OF, and have just finished an item.
+ */
+static void
+sec_asn1e_next_in_group(sec_asn1e_state *state)
+{
+ sec_asn1e_state *child;
+ void **group;
+ void *member;
+
+ PORT_Assert(state->place == duringGroup);
+ PORT_Assert(state->child != NULL);
+
+ child = state->child;
+
+ group = *(void ***)state->src;
+
+ /*
+ * Find placement of current item.
+ */
+ member = (char *)(state->child->src) - child->theTemplate->offset;
+ while (*group != member)
+ group++;
+
+ /*
+ * Move forward to next item.
+ */
+ group++;
+ if (*group == NULL) {
+ /*
+ * That was our last one; we are done now.
+ */
+ child->place = notInUse;
+ state->place = afterContents;
+ return;
+ }
+ child->src = (char *)(*group) + child->theTemplate->offset;
+
+ /*
+ * Re-"push" child.
+ */
+ sec_asn1e_scrub_state(child);
+ state->top->current = child;
+}
+
+/*
+ * We are moving along through a sequence; move forward by one,
+ * (detecting end-of-sequence when it happens).
+ */
+static void
+sec_asn1e_next_in_sequence(sec_asn1e_state *state)
+{
+ sec_asn1e_state *child;
+
+ PORT_Assert(state->place == duringSequence);
+ PORT_Assert(state->child != NULL);
+
+ child = state->child;
+
+ /*
+ * Do the "after" field notification.
+ */
+ sec_asn1e_notify_after(state->top, child->src, child->depth);
+
+ /*
+ * Move forward.
+ */
+ child->theTemplate++;
+ if (child->theTemplate->kind == 0) {
+ /*
+ * We are done with this sequence.
+ */
+ child->place = notInUse;
+ state->place = afterContents;
+ return;
+ }
+
+ /*
+ * Reset state and push.
+ */
+
+ child->src = (char *)state->src + child->theTemplate->offset;
+
+ /*
+ * Do the "before" field notification.
+ */
+ sec_asn1e_notify_before(state->top, child->src, child->depth);
+
+ state->top->current = child;
+ (void)sec_asn1e_init_state_based_on_template(child);
+}
+
+static void
+sec_asn1e_after_contents(sec_asn1e_state *state)
+{
+ PORT_Assert(state->place == afterContents);
+
+ if (state->indefinite)
+ sec_asn1e_write_end_of_contents_bytes(state);
+
+ /*
+ * Just make my parent be the current state. It will then clean
+ * up after me and free me (or reuse me).
+ */
+ state->top->current = state->parent;
+}
+
+/*
+ * This function is called whether or not we are streaming; if we
+ * *are* streaming, our caller can also instruct us to take bytes
+ * from the passed-in buffer (at buf, for length len, which is likely
+ * bytes but could even mean bits if the current field is a bit string).
+ * If we have been so instructed, we will gobble up bytes from there
+ * (rather than from our src structure) and output them, and then
+ * we will just return, expecting to be called again -- either with
+ * more bytes or after our caller has instructed us that we are done
+ * (for now) with the buffer.
+ */
+SECStatus
+SEC_ASN1EncoderUpdate(SEC_ASN1EncoderContext *cx,
+ const char *buf, unsigned long len)
+{
+ sec_asn1e_state *state;
+
+ if (cx->status == needBytes) {
+ cx->status = keepGoing;
+ }
+
+ while (cx->status == keepGoing) {
+ state = cx->current;
+ switch (state->place) {
+ case beforeHeader:
+ sec_asn1e_write_header(state);
+ break;
+ case duringContents:
+ if (cx->from_buf)
+ sec_asn1e_write_contents_from_buf(state, buf, len);
+ else
+ sec_asn1e_write_contents(state);
+ break;
+ case duringGroup:
+ sec_asn1e_next_in_group(state);
+ break;
+ case duringSequence:
+ sec_asn1e_next_in_sequence(state);
+ break;
+ case afterContents:
+ sec_asn1e_after_contents(state);
+ break;
+ case afterImplicit:
+ case afterInline:
+ case afterPointer:
+ case afterChoice:
+ /*
+ * These states are more documentation than anything.
+ * They just need to force a pop.
+ */
+ PORT_Assert(!state->indefinite);
+ state->place = afterContents;
+ break;
+ case notInUse:
+ default:
+ /* This is not an error, but rather a plain old BUG! */
+ PORT_Assert(0);
+ cx->status = encodeError;
+ break;
+ }
+
+ if (cx->status == encodeError)
+ break;
+
+ /* It might have changed, so we have to update our local copy. */
+ state = cx->current;
+
+ /* If it is NULL, we have popped all the way to the top. */
+ if (state == NULL) {
+ cx->status = allDone;
+ break;
+ }
+ }
+
+ if (cx->status == encodeError) {
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+void
+SEC_ASN1EncoderFinish(SEC_ASN1EncoderContext *cx)
+{
+ /*
+ * XXX anything else that needs to be finished?
+ */
+
+ PORT_FreeArena(cx->our_pool, PR_FALSE);
+}
+
+SEC_ASN1EncoderContext *
+SEC_ASN1EncoderStart(const void *src, const SEC_ASN1Template *theTemplate,
+ SEC_ASN1WriteProc output_proc, void *output_arg)
+{
+ PLArenaPool *our_pool;
+ SEC_ASN1EncoderContext *cx;
+
+ our_pool = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (our_pool == NULL)
+ return NULL;
+
+ cx = (SEC_ASN1EncoderContext *)PORT_ArenaZAlloc(our_pool, sizeof(*cx));
+ if (cx == NULL) {
+ PORT_FreeArena(our_pool, PR_FALSE);
+ return NULL;
+ }
+
+ cx->our_pool = our_pool;
+ cx->output_proc = output_proc;
+ cx->output_arg = output_arg;
+
+ cx->status = keepGoing;
+
+ if (sec_asn1e_push_state(cx, theTemplate, src, PR_FALSE) == NULL ||
+ sec_asn1e_init_state_based_on_template(cx->current) == NULL) {
+ /*
+ * Trouble initializing (probably due to failed allocations)
+ * requires that we just give up.
+ */
+ PORT_FreeArena(our_pool, PR_FALSE);
+ return NULL;
+ }
+
+ return cx;
+}
+
+/*
+ * XXX Do we need a FilterProc, too?
+ */
+
+void
+SEC_ASN1EncoderSetNotifyProc(SEC_ASN1EncoderContext *cx,
+ SEC_ASN1NotifyProc fn, void *arg)
+{
+ cx->notify_proc = fn;
+ cx->notify_arg = arg;
+}
+
+void
+SEC_ASN1EncoderClearNotifyProc(SEC_ASN1EncoderContext *cx)
+{
+ cx->notify_proc = NULL;
+ cx->notify_arg = NULL; /* not necessary; just being clean */
+}
+
+void
+SEC_ASN1EncoderAbort(SEC_ASN1EncoderContext *cx, int error)
+{
+ PORT_Assert(cx);
+ PORT_SetError(error);
+ cx->status = encodeError;
+}
+
+void
+SEC_ASN1EncoderSetStreaming(SEC_ASN1EncoderContext *cx)
+{
+ /* XXX is there a way to check that we are "between" fields here? */
+
+ cx->streaming = PR_TRUE;
+}
+
+void
+SEC_ASN1EncoderClearStreaming(SEC_ASN1EncoderContext *cx)
+{
+ /* XXX is there a way to check that we are "between" fields here? */
+
+ cx->streaming = PR_FALSE;
+}
+
+void
+SEC_ASN1EncoderSetTakeFromBuf(SEC_ASN1EncoderContext *cx)
+{
+ /*
+ * XXX is there a way to check that we are "between" fields here? this
+ * needs to include a check for being in between groups of items in
+ * a SET_OF or SEQUENCE_OF.
+ */
+ PORT_Assert(cx->streaming);
+
+ cx->from_buf = PR_TRUE;
+}
+
+void
+SEC_ASN1EncoderClearTakeFromBuf(SEC_ASN1EncoderContext *cx)
+{
+ /* we should actually be taking from buf *now* */
+ PORT_Assert(cx->from_buf);
+ if (!cx->from_buf) /* if not, just do nothing */
+ return;
+
+ cx->from_buf = PR_FALSE;
+
+ if (cx->status == needBytes) {
+ cx->status = keepGoing;
+ cx->current->place = afterContents;
+ }
+}
+
+SECStatus
+SEC_ASN1Encode(const void *src, const SEC_ASN1Template *theTemplate,
+ SEC_ASN1WriteProc output_proc, void *output_arg)
+{
+ SEC_ASN1EncoderContext *ecx;
+ SECStatus rv;
+
+ ecx = SEC_ASN1EncoderStart(src, theTemplate, output_proc, output_arg);
+ if (ecx == NULL)
+ return SECFailure;
+
+ rv = SEC_ASN1EncoderUpdate(ecx, NULL, 0);
+
+ SEC_ASN1EncoderFinish(ecx);
+ return rv;
+}
+
+/*
+ * XXX depth and data_kind are unused; is there a PC way to silence warnings?
+ * (I mean "politically correct", not anything to do with intel/win platform)
+ */
+static void
+sec_asn1e_encode_item_count(void *arg, const char *buf, unsigned long len,
+ int depth, SEC_ASN1EncodingPart data_kind)
+{
+ unsigned long *count;
+
+ count = (unsigned long *)arg;
+ PORT_Assert(count != NULL);
+
+ *count += len;
+}
+
+/* XXX depth and data_kind are unused; is there a PC way to silence warnings? */
+static void
+sec_asn1e_encode_item_store(void *arg, const char *buf, unsigned long len,
+ int depth, SEC_ASN1EncodingPart data_kind)
+{
+ SECItem *dest;
+
+ dest = (SECItem *)arg;
+ PORT_Assert(dest != NULL);
+
+ if (len > 0) {
+ PORT_Memcpy(dest->data + dest->len, buf, len);
+ dest->len += len;
+ }
+}
+
+/*
+ * Allocate an entire SECItem, or just the data part of it, to hold
+ * "len" bytes of stuff. Allocate from the given pool, if specified,
+ * otherwise just do a vanilla PORT_Alloc.
+ *
+ * XXX This seems like a reasonable general-purpose function (for SECITEM_)?
+ */
+static SECItem *
+sec_asn1e_allocate_item(PLArenaPool *poolp, SECItem *dest, unsigned long len)
+{
+ if (poolp != NULL) {
+ void *release;
+
+ release = PORT_ArenaMark(poolp);
+ if (dest == NULL)
+ dest = (SECItem *)PORT_ArenaAlloc(poolp, sizeof(SECItem));
+ if (dest != NULL) {
+ dest->data = (unsigned char *)PORT_ArenaAlloc(poolp, len);
+ if (dest->data == NULL) {
+ dest = NULL;
+ }
+ }
+ if (dest == NULL) {
+ /* one or both allocations failed; release everything */
+ PORT_ArenaRelease(poolp, release);
+ } else {
+ /* everything okay; unmark the arena */
+ PORT_ArenaUnmark(poolp, release);
+ }
+ } else {
+ SECItem *indest;
+
+ indest = dest;
+ if (dest == NULL)
+ dest = (SECItem *)PORT_Alloc(sizeof(SECItem));
+ if (dest != NULL) {
+ dest->type = siBuffer;
+ dest->data = (unsigned char *)PORT_Alloc(len);
+ if (dest->data == NULL) {
+ if (indest == NULL)
+ PORT_Free(dest);
+ dest = NULL;
+ }
+ }
+ }
+
+ return dest;
+}
+
+SECItem *
+SEC_ASN1EncodeItem(PLArenaPool *poolp, SECItem *dest, const void *src,
+ const SEC_ASN1Template *theTemplate)
+{
+ unsigned long encoding_length;
+ SECStatus rv;
+
+ PORT_Assert(dest == NULL || dest->data == NULL);
+
+ encoding_length = 0;
+ rv = SEC_ASN1Encode(src, theTemplate,
+ sec_asn1e_encode_item_count, &encoding_length);
+ if (rv != SECSuccess)
+ return NULL;
+
+ dest = sec_asn1e_allocate_item(poolp, dest, encoding_length);
+ if (dest == NULL)
+ return NULL;
+
+ /* XXX necessary? This really just checks for a bug in the allocate fn */
+ PORT_Assert(dest->data != NULL);
+ if (dest->data == NULL)
+ return NULL;
+
+ dest->len = 0;
+ (void)SEC_ASN1Encode(src, theTemplate, sec_asn1e_encode_item_store, dest);
+
+ PORT_Assert(encoding_length == dest->len);
+ return dest;
+}
+
+static SECItem *
+sec_asn1e_integer(PLArenaPool *poolp, SECItem *dest, unsigned long value,
+ PRBool is_unsigned)
+{
+ unsigned long copy;
+ unsigned char sign;
+ int len = 0;
+
+ /*
+ * Determine the length of the encoded value (minimum of 1).
+ */
+ copy = value;
+ do {
+ len++;
+ sign = (unsigned char)(copy & 0x80);
+ copy >>= 8;
+ } while (copy);
+
+ /*
+ * If 'value' is non-negative, and the high bit of the last
+ * byte we counted was set, we need to add one to the length so
+ * we put a high-order zero byte in the encoding.
+ */
+ if (sign && (is_unsigned || (long)value >= 0))
+ len++;
+
+ /*
+ * Allocate the item (if necessary) and the data pointer within.
+ */
+ dest = sec_asn1e_allocate_item(poolp, dest, len);
+ if (dest == NULL)
+ return NULL;
+
+ /*
+ * Store the value, byte by byte, in the item.
+ */
+ dest->len = len;
+ while (len) {
+ dest->data[--len] = (unsigned char)value;
+ value >>= 8;
+ }
+ PORT_Assert(value == 0);
+
+ return dest;
+}
+
+SECItem *
+SEC_ASN1EncodeInteger(PLArenaPool *poolp, SECItem *dest, long value)
+{
+ return sec_asn1e_integer(poolp, dest, (unsigned long)value, PR_FALSE);
+}
+
+SECItem *
+SEC_ASN1EncodeUnsignedInteger(PLArenaPool *poolp,
+ SECItem *dest, unsigned long value)
+{
+ return sec_asn1e_integer(poolp, dest, value, PR_TRUE);
+}
diff --git a/security/nss/lib/util/secasn1t.h b/security/nss/lib/util/secasn1t.h
new file mode 100644
index 0000000000..0d1a6aea07
--- /dev/null
+++ b/security/nss/lib/util/secasn1t.h
@@ -0,0 +1,267 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Types for encoding/decoding of ASN.1 using BER/DER (Basic/Distinguished
+ * Encoding Rules).
+ */
+
+#ifndef _SECASN1T_H_
+#define _SECASN1T_H_
+
+#include "utilrename.h"
+
+/*
+** An array of these structures defines a BER/DER encoding for an object.
+**
+** The array usually starts with a dummy entry whose kind is SEC_ASN1_SEQUENCE;
+** such an array is terminated with an entry where kind == 0. (An array
+** which consists of a single component does not require a second dummy
+** entry -- the array is only searched as long as previous component(s)
+** instruct it.)
+*/
+typedef struct sec_ASN1Template_struct {
+ /*
+ ** Kind of item being decoded/encoded, including tags and modifiers.
+ */
+ unsigned long kind;
+
+ /*
+ ** The value is the offset from the base of the structure to the
+ ** field that holds the value being decoded/encoded.
+ */
+ unsigned long offset;
+
+ /*
+ ** When kind suggests it (SEC_ASN1_POINTER, SEC_ASN1_GROUP, SEC_ASN1_INLINE,
+ ** or a component that is *not* a SEC_ASN1_UNIVERSAL), this points to
+ ** a sub-template for nested encoding/decoding,
+ ** OR, iff SEC_ASN1_DYNAMIC is set, then this is a pointer to a pointer
+ ** to a function which will return the appropriate template when called
+ ** at runtime. NOTE! that explicit level of indirection, which is
+ ** necessary because ANSI does not allow you to store a function
+ ** pointer directly as a "void *" so we must store it separately and
+ ** dereference it to get at the function pointer itself.
+ */
+ const void *sub;
+
+ /*
+ ** In the first element of a template array, the value is the size
+ ** of the structure to allocate when this template is being referenced
+ ** by another template via SEC_ASN1_POINTER or SEC_ASN1_GROUP.
+ ** In all other cases, the value is ignored.
+ */
+ unsigned int size;
+} SEC_ASN1Template;
+
+/* default size used for allocation of encoding/decoding stuff */
+/* XXX what is the best value here? */
+#define SEC_ASN1_DEFAULT_ARENA_SIZE (2048)
+
+/*
+** BER/DER values for ASN.1 identifier octets.
+*/
+#define SEC_ASN1_TAG_MASK 0xff
+
+/*
+ * BER/DER universal type tag numbers.
+ * The values are defined by the X.208 standard; do not change them!
+ * NOTE: if you add anything to this list, you must add code to secasn1d.c
+ * to accept the tag, and probably also to secasn1e.c to encode it.
+ * XXX It appears some have been added recently without being added to
+ * the code; so need to go through the list now and double-check them all.
+ * (Look especially at those added in revision 1.10.)
+ */
+#define SEC_ASN1_TAGNUM_MASK 0x1f
+#define SEC_ASN1_BOOLEAN 0x01
+#define SEC_ASN1_INTEGER 0x02
+#define SEC_ASN1_BIT_STRING 0x03
+#define SEC_ASN1_OCTET_STRING 0x04
+#define SEC_ASN1_NULL 0x05
+#define SEC_ASN1_OBJECT_ID 0x06
+#define SEC_ASN1_OBJECT_DESCRIPTOR 0x07
+/* External type and instance-of type 0x08 */
+#define SEC_ASN1_REAL 0x09
+#define SEC_ASN1_ENUMERATED 0x0a
+#define SEC_ASN1_EMBEDDED_PDV 0x0b
+#define SEC_ASN1_UTF8_STRING 0x0c
+/* 0x0d */
+/* 0x0e */
+/* 0x0f */
+#define SEC_ASN1_SEQUENCE 0x10
+#define SEC_ASN1_SET 0x11
+#define SEC_ASN1_NUMERIC_STRING 0x12
+#define SEC_ASN1_PRINTABLE_STRING 0x13
+#define SEC_ASN1_T61_STRING 0x14
+#define SEC_ASN1_VIDEOTEX_STRING 0x15
+#define SEC_ASN1_IA5_STRING 0x16
+#define SEC_ASN1_UTC_TIME 0x17
+#define SEC_ASN1_GENERALIZED_TIME 0x18
+#define SEC_ASN1_GRAPHIC_STRING 0x19
+#define SEC_ASN1_VISIBLE_STRING 0x1a
+#define SEC_ASN1_GENERAL_STRING 0x1b
+#define SEC_ASN1_UNIVERSAL_STRING 0x1c
+/* 0x1d */
+#define SEC_ASN1_BMP_STRING 0x1e
+#define SEC_ASN1_HIGH_TAG_NUMBER 0x1f
+#define SEC_ASN1_TELETEX_STRING SEC_ASN1_T61_STRING
+
+/*
+** Modifiers to type tags. These are also specified by a/the
+** standard, and must not be changed.
+*/
+
+#define SEC_ASN1_METHOD_MASK 0x20
+#define SEC_ASN1_PRIMITIVE 0x00
+#define SEC_ASN1_CONSTRUCTED 0x20
+
+#define SEC_ASN1_CLASS_MASK 0xc0
+#define SEC_ASN1_UNIVERSAL 0x00
+#define SEC_ASN1_APPLICATION 0x40
+#define SEC_ASN1_CONTEXT_SPECIFIC 0x80
+#define SEC_ASN1_PRIVATE 0xc0
+
+/*
+** Our additions, used for templates.
+** These are not defined by any standard; the values are used internally only.
+** Just be careful to keep them out of the low 8 bits.
+** XXX finish comments
+*/
+#define SEC_ASN1_OPTIONAL 0x00100
+#define SEC_ASN1_EXPLICIT 0x00200
+#define SEC_ASN1_ANY 0x00400
+#define SEC_ASN1_INLINE 0x00800
+#define SEC_ASN1_POINTER 0x01000
+#define SEC_ASN1_GROUP 0x02000 /* with SET or SEQUENCE means \
+ * SET OF or SEQUENCE OF */
+#define SEC_ASN1_DYNAMIC 0x04000 /* subtemplate is found by calling \
+ * a function at runtime */
+#define SEC_ASN1_SKIP 0x08000 /* skip a field; only for decoding */
+#define SEC_ASN1_INNER 0x10000 /* with ANY means capture the \
+ * contents only (not the id, len, \
+ * or eoc); only for decoding */
+#define SEC_ASN1_SAVE 0x20000 /* stash away the encoded bytes first; \
+ * only for decoding */
+#define SEC_ASN1_MAY_STREAM 0x40000 /* field or one of its sub-fields may \
+ * stream in and so should encode as \
+ * indefinite-length when streaming \
+ * has been indicated; only for \
+ * encoding */
+#define SEC_ASN1_SKIP_REST 0x80000 /* skip all following fields; \
+ only for decoding */
+#define SEC_ASN1_CHOICE 0x100000 /* pick one from a template */
+#define SEC_ASN1_NO_STREAM 0X200000 /* This entry will not stream \
+ even if the sub-template says \
+ streaming is possible. Helps \
+ to solve ambiguities with potential \
+ streaming entries that are \
+ optional */
+#define SEC_ASN1_DEBUG_BREAK 0X400000 /* put this in your template and the \
+ decoder will assert when it \
+ processes it. Only for use with \
+ SEC_QuickDERDecodeItem */
+
+/* Shorthand/Aliases */
+#define SEC_ASN1_SEQUENCE_OF (SEC_ASN1_GROUP | SEC_ASN1_SEQUENCE)
+#define SEC_ASN1_SET_OF (SEC_ASN1_GROUP | SEC_ASN1_SET)
+#define SEC_ASN1_ANY_CONTENTS (SEC_ASN1_ANY | SEC_ASN1_INNER)
+
+/* Maximum depth of nested SEQUENCEs and SETs */
+#define SEC_ASN1D_MAX_DEPTH 32
+
+/*
+** Function used for SEC_ASN1_DYNAMIC.
+** "arg" is a pointer to the structure being encoded/decoded
+** "enc", when true, means that we are encoding (false means decoding)
+*/
+typedef const SEC_ASN1Template *SEC_ASN1TemplateChooser(void *arg, PRBool enc);
+typedef SEC_ASN1TemplateChooser *SEC_ASN1TemplateChooserPtr;
+
+#if defined(_WIN32) || defined(ANDROID)
+#define SEC_ASN1_GET(x) NSS_Get_##x(NULL, PR_FALSE)
+#define SEC_ASN1_SUB(x) &p_NSS_Get_##x
+#define SEC_ASN1_XTRN SEC_ASN1_DYNAMIC
+#define SEC_ASN1_MKSUB(x) \
+ static const SEC_ASN1TemplateChooserPtr p_NSS_Get_##x = &NSS_Get_##x;
+#else
+#define SEC_ASN1_GET(x) x
+#define SEC_ASN1_SUB(x) x
+#define SEC_ASN1_XTRN 0
+#define SEC_ASN1_MKSUB(x)
+#endif
+
+#define SEC_ASN1_CHOOSER_DECLARE(x) \
+ extern const SEC_ASN1Template *NSS_Get_##x(void *arg, PRBool enc);
+
+#define SEC_ASN1_CHOOSER_IMPLEMENT(x) \
+ const SEC_ASN1Template *NSS_Get_##x(void *arg, PRBool enc) \
+ { \
+ return x; \
+ }
+
+/*
+** Opaque object used by the decoder to store state.
+*/
+typedef struct sec_DecoderContext_struct SEC_ASN1DecoderContext;
+
+/*
+** Opaque object used by the encoder to store state.
+*/
+typedef struct sec_EncoderContext_struct SEC_ASN1EncoderContext;
+
+/*
+ * This is used to describe to a filter function the bytes that are
+ * being passed to it. This is only useful when the filter is an "outer"
+ * one, meaning it expects to get *all* of the bytes not just the
+ * contents octets.
+ */
+typedef enum {
+ SEC_ASN1_Identifier = 0,
+ SEC_ASN1_Length = 1,
+ SEC_ASN1_Contents = 2,
+ SEC_ASN1_EndOfContents = 3
+} SEC_ASN1EncodingPart;
+
+/*
+ * Type of the function pointer used either for decoding or encoding,
+ * when doing anything "funny" (e.g. manipulating the data stream)
+ */
+typedef void (*SEC_ASN1NotifyProc)(void *arg, PRBool before,
+ void *dest, int real_depth);
+
+/*
+ * Type of the function pointer used for grabbing encoded bytes.
+ * This can be used during either encoding or decoding, as follows...
+ *
+ * When decoding, this can be used to filter the encoded bytes as they
+ * are parsed. This is what you would do if you wanted to process the data
+ * along the way (like to decrypt it, or to perform a hash on it in order
+ * to do a signature check later). See SEC_ASN1DecoderSetFilterProc().
+ * When processing only part of the encoded bytes is desired, you "watch"
+ * for the field(s) you are interested in with a "notify proc" (see
+ * SEC_ASN1DecoderSetNotifyProc()) and for even finer granularity (e.g. to
+ * ignore all by the contents bytes) you pay attention to the "data_kind"
+ * parameter.
+ *
+ * When encoding, this is the specification for the output function which
+ * will receive the bytes as they are encoded. The output function can
+ * perform any postprocessing necessary (like hashing (some of) the data
+ * to create a digest that gets included at the end) as well as shoving
+ * the data off wherever it needs to go. (In order to "tune" any processing,
+ * you can set a "notify proc" as described above in the decoding case.)
+ *
+ * The parameters:
+ * - "arg" is an opaque pointer that you provided at the same time you
+ * specified a function of this type
+ * - "data" is a buffer of length "len", containing the encoded bytes
+ * - "depth" is how deep in a nested encoding we are (it is not usually
+ * valuable, but can be useful sometimes so I included it)
+ * - "data_kind" tells you if these bytes are part of the ASN.1 encoded
+ * octets for identifier, length, contents, or end-of-contents
+ */
+typedef void (*SEC_ASN1WriteProc)(void *arg,
+ const char *data, unsigned long len,
+ int depth, SEC_ASN1EncodingPart data_kind);
+
+#endif /* _SECASN1T_H_ */
diff --git a/security/nss/lib/util/secasn1u.c b/security/nss/lib/util/secasn1u.c
new file mode 100644
index 0000000000..7d086fb0d5
--- /dev/null
+++ b/security/nss/lib/util/secasn1u.c
@@ -0,0 +1,94 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Utility routines to complement the ASN.1 encoding and decoding functions.
+ */
+
+#include "secasn1.h"
+
+/*
+ * We have a length that needs to be encoded; how many bytes will the
+ * encoding take?
+ *
+ * The rules are that 0 - 0x7f takes one byte (the length itself is the
+ * entire encoding); everything else takes one plus the number of bytes
+ * in the length.
+ */
+int
+SEC_ASN1LengthLength(unsigned long len)
+{
+ int lenlen = 1;
+
+ if (len > 0x7f) {
+ do {
+ lenlen++;
+ len >>= 8;
+ } while (len);
+ }
+
+ return lenlen;
+}
+
+/*
+ * XXX Move over (and rewrite as appropriate) the rest of the
+ * stuff in dersubr.c!
+ */
+
+/*
+ * Find the appropriate subtemplate for the given template.
+ * This may involve calling a "chooser" function, or it may just
+ * be right there. In either case, it is expected to *have* a
+ * subtemplate; this is asserted in debug builds (in non-debug
+ * builds, NULL will be returned).
+ *
+ * "thing" is a pointer to the structure being encoded/decoded
+ * "encoding", when true, means that we are in the process of encoding
+ * (as opposed to in the process of decoding)
+ */
+const SEC_ASN1Template *
+SEC_ASN1GetSubtemplate(const SEC_ASN1Template *theTemplate, void *thing,
+ PRBool encoding)
+{
+ const SEC_ASN1Template *subt = NULL;
+
+ PORT_Assert(theTemplate->sub != NULL);
+ if (theTemplate->sub != NULL) {
+ if (theTemplate->kind & SEC_ASN1_DYNAMIC) {
+ SEC_ASN1TemplateChooserPtr chooserp;
+
+ chooserp = *(SEC_ASN1TemplateChooserPtr *)theTemplate->sub;
+ if (chooserp) {
+ if (thing != NULL)
+ thing = (char *)thing - theTemplate->offset;
+ subt = (*chooserp)(thing, encoding);
+ }
+ } else {
+ subt = (SEC_ASN1Template *)theTemplate->sub;
+ }
+ }
+ return subt;
+}
+
+PRBool
+SEC_ASN1IsTemplateSimple(const SEC_ASN1Template *theTemplate)
+{
+ if (!theTemplate) {
+ return PR_TRUE; /* it doesn't get any simpler than NULL */
+ }
+ /* only templates made of one primitive type or a choice of primitive
+ types are considered simple */
+ if (!(theTemplate->kind & (~SEC_ASN1_TAGNUM_MASK))) {
+ return PR_TRUE; /* primitive type */
+ }
+ if (!(theTemplate->kind & SEC_ASN1_CHOICE)) {
+ return PR_FALSE; /* no choice means not simple */
+ }
+ while (++theTemplate && theTemplate->kind) {
+ if (theTemplate->kind & (~SEC_ASN1_TAGNUM_MASK)) {
+ return PR_FALSE; /* complex type */
+ }
+ }
+ return PR_TRUE; /* choice of primitive types */
+}
diff --git a/security/nss/lib/util/seccomon.h b/security/nss/lib/util/seccomon.h
new file mode 100644
index 0000000000..2c6be3502d
--- /dev/null
+++ b/security/nss/lib/util/seccomon.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/. */
+
+/*
+ * seccomon.h - common data structures for security libraries
+ *
+ * This file should have lowest-common-denominator datastructures
+ * for security libraries. It should not be dependent on any other
+ * headers, and should not require linking with any libraries.
+ */
+
+#ifndef _SECCOMMON_H_
+#define _SECCOMMON_H_
+
+#include "utilrename.h"
+#include "prtypes.h"
+
+#ifdef __cplusplus
+#define SEC_BEGIN_PROTOS extern "C" {
+#define SEC_END_PROTOS }
+#else
+#define SEC_BEGIN_PROTOS
+#define SEC_END_PROTOS
+#endif
+
+#include "secport.h"
+
+typedef enum {
+ siBuffer = 0,
+ siClearDataBuffer = 1,
+ siCipherDataBuffer = 2,
+ siDERCertBuffer = 3,
+ siEncodedCertBuffer = 4,
+ siDERNameBuffer = 5,
+ siEncodedNameBuffer = 6,
+ siAsciiNameString = 7,
+ siAsciiString = 8,
+ siDEROID = 9,
+ siUnsignedInteger = 10,
+ siUTCTime = 11,
+ siGeneralizedTime = 12,
+ siVisibleString = 13,
+ siUTF8String = 14,
+ siBMPString = 15
+} SECItemType;
+
+typedef struct SECItemStr SECItem;
+
+struct SECItemStr {
+ SECItemType type;
+ unsigned char *data;
+ unsigned int len;
+};
+
+typedef struct SECItemArrayStr SECItemArray;
+
+struct SECItemArrayStr {
+ SECItem *items;
+ unsigned int len;
+};
+
+/*
+** A status code. Statuses are used by procedures that return status
+** values. Again the motivation is so that a compiler can generate
+** warnings when return values are wrong. Correct testing of status codes:
+**
+** SECStatus rv;
+** rv = some_function (some_argument);
+** if (rv != SECSuccess)
+** do_an_error_thing();
+**
+*/
+typedef enum _SECStatus {
+ SECWouldBlock = -2,
+ SECFailure = -1,
+ SECSuccess = 0
+} SECStatus;
+
+/*
+** A comparison code. Used for procedures that return comparison
+** values. Again the motivation is so that a compiler can generate
+** warnings when return values are wrong.
+*/
+typedef enum _SECComparison {
+ SECLessThan = -1,
+ SECEqual = 0,
+ SECGreaterThan = 1
+} SECComparison;
+
+#endif /* _SECCOMMON_H_ */
diff --git a/security/nss/lib/util/secder.h b/security/nss/lib/util/secder.h
new file mode 100644
index 0000000000..1b487d1938
--- /dev/null
+++ b/security/nss/lib/util/secder.h
@@ -0,0 +1,175 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 _SECDER_H_
+#define _SECDER_H_
+
+#include "utilrename.h"
+
+/*
+ * secder.h - public data structures and prototypes for the DER encoding and
+ * decoding utilities library
+ */
+
+#include <time.h>
+
+#include "plarena.h"
+#include "prlong.h"
+
+#include "seccomon.h"
+#include "secdert.h"
+#include "prtime.h"
+
+SEC_BEGIN_PROTOS
+
+/*
+** Encode a data structure into DER.
+** "dest" will be filled in (and memory allocated) to hold the der
+** encoded structure in "src"
+** "t" is a template structure which defines the shape of the
+** stored data
+** "src" is a pointer to the structure that will be encoded
+*/
+extern SECStatus DER_Encode(PLArenaPool *arena, SECItem *dest, DERTemplate *t,
+ void *src);
+
+/*
+** This function is deprecated.
+*/
+extern SECStatus DER_Lengths(SECItem *item, int *header_len_p,
+ PRUint32 *contents_len_p);
+
+/*
+** Lower level der subroutine that stores the standard header into "to".
+** The header is of variable length, based on encodingLen.
+** The return value is the new value of "to" after skipping over the header.
+** "to" is where the header will be stored
+** "code" is the der code to write
+** "encodingLen" is the number of bytes of data that will follow
+** the header
+*/
+extern unsigned char *DER_StoreHeader(unsigned char *to, unsigned int code,
+ PRUint32 encodingLen);
+
+/*
+** Return the number of bytes it will take to hold a der encoded length.
+*/
+extern int DER_LengthLength(PRUint32 len);
+
+/*
+** Store a der encoded *signed* integer (whose value is "src") into "dst".
+** XXX This should really be enhanced to take a long.
+*/
+extern SECStatus DER_SetInteger(PLArenaPool *arena, SECItem *dst, PRInt32 src);
+
+/*
+** Store a der encoded *unsigned* integer (whose value is "src") into "dst".
+** XXX This should really be enhanced to take an unsigned long.
+*/
+extern SECStatus DER_SetUInteger(PLArenaPool *arena, SECItem *dst, PRUint32 src);
+
+/*
+** Decode a der encoded *signed* integer that is stored in "src".
+** If "-1" is returned, then the caller should check the error in
+** XP_GetError() to see if an overflow occurred (SEC_ERROR_BAD_DER).
+*/
+extern long DER_GetInteger(const SECItem *src);
+
+/*
+** Decode a der encoded *unsigned* integer that is stored in "src".
+** If the ULONG_MAX is returned, then the caller should check the error
+** in XP_GetError() to see if an overflow occurred (SEC_ERROR_BAD_DER).
+*/
+extern unsigned long DER_GetUInteger(SECItem *src);
+
+/*
+** Convert an NSPR time value to a der encoded time value.
+** "result" is the der encoded time (memory is allocated)
+** "time" is the NSPR time value (Since Jan 1st, 1970).
+** time must be on or after January 1, 1950, and
+** before January 1, 2050
+** The caller is responsible for freeing up the buffer which
+** result->data points to upon a successful operation.
+*/
+extern SECStatus DER_TimeToUTCTime(SECItem *result, PRTime time);
+extern SECStatus DER_TimeToUTCTimeArena(PLArenaPool *arenaOpt,
+ SECItem *dst, PRTime gmttime);
+
+/*
+** Convert an ascii encoded time value (according to DER rules) into
+** an NSPR time value.
+** "result" the resulting NSPR time
+** "string" the der notation ascii value to decode
+*/
+extern SECStatus DER_AsciiToTime(PRTime *result, const char *string);
+
+/*
+** Same as DER_AsciiToTime except takes an SECItem instead of a string
+*/
+extern SECStatus DER_UTCTimeToTime(PRTime *result, const SECItem *time);
+
+/*
+** Convert a DER encoded UTC time to an ascii time representation
+** "utctime" is the DER encoded UTC time to be converted. The
+** caller is responsible for deallocating the returned buffer.
+*/
+extern char *DER_UTCTimeToAscii(SECItem *utcTime);
+
+/*
+** Convert a DER encoded UTC time to an ascii time representation, but only
+** include the day, not the time.
+** "utctime" is the DER encoded UTC time to be converted.
+** The caller is responsible for deallocating the returned buffer.
+*/
+extern char *DER_UTCDayToAscii(SECItem *utctime);
+/* same thing for DER encoded GeneralizedTime */
+extern char *DER_GeneralizedDayToAscii(SECItem *gentime);
+/* same thing for either DER UTCTime or GeneralizedTime */
+extern char *DER_TimeChoiceDayToAscii(SECItem *timechoice);
+
+/*
+** Convert a PRTime to a DER encoded Generalized time
+** gmttime must be on or after January 1, year 1 and
+** before January 1, 10000.
+*/
+extern SECStatus DER_TimeToGeneralizedTime(SECItem *dst, PRTime gmttime);
+extern SECStatus DER_TimeToGeneralizedTimeArena(PLArenaPool *arenaOpt,
+ SECItem *dst, PRTime gmttime);
+
+/*
+** Convert a DER encoded Generalized time value into an NSPR time value.
+** "dst" the resulting NSPR time
+** "string" the der notation ascii value to decode
+*/
+extern SECStatus DER_GeneralizedTimeToTime(PRTime *dst, const SECItem *time);
+
+/*
+** Convert from a PRTime UTC time value to a formatted ascii value. The
+** caller is responsible for deallocating the returned buffer.
+*/
+extern char *CERT_UTCTime2FormattedAscii(PRTime utcTime, char *format);
+#define CERT_GeneralizedTime2FormattedAscii CERT_UTCTime2FormattedAscii
+
+/*
+** Convert from a PRTime Generalized time value to a formatted ascii value. The
+** caller is responsible for deallocating the returned buffer.
+*/
+extern char *CERT_GenTime2FormattedAscii(PRTime genTime, char *format);
+
+/*
+** decode a SECItem containing either a SEC_ASN1_GENERALIZED_TIME
+** or a SEC_ASN1_UTC_TIME
+*/
+
+extern SECStatus DER_DecodeTimeChoice(PRTime *output, const SECItem *input);
+
+/* encode a PRTime to an ASN.1 DER SECItem containing either a
+ SEC_ASN1_GENERALIZED_TIME or a SEC_ASN1_UTC_TIME */
+
+extern SECStatus DER_EncodeTimeChoice(PLArenaPool *arena, SECItem *output,
+ PRTime input);
+
+SEC_END_PROTOS
+
+#endif /* _SECDER_H_ */
diff --git a/security/nss/lib/util/secdert.h b/security/nss/lib/util/secdert.h
new file mode 100644
index 0000000000..de67eafe12
--- /dev/null
+++ b/security/nss/lib/util/secdert.h
@@ -0,0 +1,129 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 _SECDERT_H_
+#define _SECDERT_H_
+/*
+ * secdert.h - public data structures for the DER encoding and
+ * decoding utilities library
+ */
+
+#include "utilrename.h"
+#include "seccomon.h"
+
+typedef struct DERTemplateStr DERTemplate;
+
+/*
+** An array of these structures defines an encoding for an object using DER.
+** The array usually starts with a dummy entry whose kind is DER_SEQUENCE;
+** such an array is terminated with an entry where kind == 0. (An array
+** which consists of a single component does not require a second dummy
+** entry -- the array is only searched as long as previous component(s)
+** instruct it.)
+*/
+struct DERTemplateStr {
+ /*
+ ** Kind of item being decoded/encoded, including tags and modifiers.
+ */
+ unsigned long kind;
+
+ /*
+ ** Offset from base of structure to field that holds the value
+ ** being decoded/encoded.
+ */
+ unsigned int offset;
+
+ /*
+ ** When kind suggests it (DER_POINTER, DER_INDEFINITE, DER_INLINE),
+ ** this points to a sub-template for nested encoding/decoding.
+ */
+ DERTemplate *sub;
+
+ /*
+ ** Argument value, dependent on "kind" and/or template placement
+ ** within an array of templates:
+ ** - In the first element of a template array, the value is the
+ ** size of the structure to allocate when this template is being
+ ** referenced by another template via DER_POINTER or DER_INDEFINITE.
+ ** - In a component of a DER_SET or DER_SEQUENCE which is *not* a
+ ** DER_UNIVERSAL type (that is, it has a class tag for either
+ ** DER_APPLICATION, DER_CONTEXT_SPECIFIC, or DER_PRIVATE), the
+ ** value is the underlying type of item being decoded/encoded.
+ */
+ unsigned long arg;
+};
+
+/************************************************************************/
+
+/* default chunksize for arenas used for DER stuff */
+#define DER_DEFAULT_CHUNKSIZE (2048)
+
+/*
+** BER/DER values for ASN.1 identifier octets.
+*/
+#define DER_TAG_MASK 0xff
+
+/*
+ * BER/DER universal type tag numbers.
+ * The values are defined by the X.208 standard; do not change them!
+ * NOTE: if you add anything to this list, you must add code to derdec.c
+ * to accept the tag, and probably also to derenc.c to encode it.
+ */
+#define DER_TAGNUM_MASK 0x1f
+#define DER_BOOLEAN 0x01
+#define DER_INTEGER 0x02
+#define DER_BIT_STRING 0x03
+#define DER_OCTET_STRING 0x04
+#define DER_NULL 0x05
+#define DER_OBJECT_ID 0x06
+#define DER_SEQUENCE 0x10
+#define DER_SET 0x11
+#define DER_PRINTABLE_STRING 0x13
+#define DER_T61_STRING 0x14
+#define DER_IA5_STRING 0x16
+#define DER_UTC_TIME 0x17
+#define DER_VISIBLE_STRING 0x1a
+#define DER_HIGH_TAG_NUMBER 0x1f
+
+/*
+** Modifiers to type tags. These are also specified by a/the
+** standard, and must not be changed.
+*/
+
+#define DER_METHOD_MASK 0x20
+#define DER_PRIMITIVE 0x00
+#define DER_CONSTRUCTED 0x20
+
+#define DER_CLASS_MASK 0xc0
+#define DER_UNIVERSAL 0x00
+#define DER_APPLICATION 0x40
+#define DER_CONTEXT_SPECIFIC 0x80
+#define DER_PRIVATE 0xc0
+
+/*
+** Our additions, used for templates.
+** These are not defined by any standard; the values are used internally only.
+** Just be careful to keep them out of the low 8 bits.
+*/
+#define DER_OPTIONAL 0x00100
+#define DER_EXPLICIT 0x00200
+#define DER_ANY 0x00400
+#define DER_INLINE 0x00800
+#define DER_POINTER 0x01000
+#define DER_INDEFINITE 0x02000
+#define DER_DERPTR 0x04000
+#define DER_SKIP 0x08000
+#define DER_FORCE 0x10000
+#define DER_OUTER 0x40000 /* for DER_DERPTR */
+
+/*
+** Macro to convert der decoded bit string into a decoded octet
+** string. All it needs to do is fiddle with the length code.
+*/
+#define DER_ConvertBitString(item) \
+ { \
+ (item)->len = ((item)->len + 7) >> 3; \
+ }
+
+#endif /* _SECDERT_H_ */
diff --git a/security/nss/lib/util/secdig.c b/security/nss/lib/util/secdig.c
new file mode 100644
index 0000000000..28377c2f8d
--- /dev/null
+++ b/security/nss/lib/util/secdig.c
@@ -0,0 +1,182 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "secdig.h"
+
+#include "secoid.h"
+#include "secasn1.h"
+#include "secerr.h"
+
+/*
+ * XXX Want to have a SGN_DecodeDigestInfo, like:
+ * SGNDigestInfo *SGN_DecodeDigestInfo(SECItem *didata);
+ * that creates a pool and allocates from it and decodes didata into
+ * the newly allocated DigestInfo structure. Then fix secvfy.c (it
+ * will no longer need an arena itself) to call this and then call
+ * DestroyDigestInfo when it is done, then can remove the old template
+ * above and keep our new template static and "hidden".
+ */
+
+/*
+ * XXX It might be nice to combine the following two functions (create
+ * and encode). I think that is all anybody ever wants to do anyway.
+ */
+
+SECItem *
+SGN_EncodeDigestInfo(PLArenaPool *poolp, SECItem *dest, SGNDigestInfo *diginfo)
+{
+ return SEC_ASN1EncodeItem(poolp, dest, diginfo, sgn_DigestInfoTemplate);
+}
+
+SGNDigestInfo *
+SGN_CreateDigestInfo(SECOidTag algorithm, const unsigned char *sig,
+ unsigned len)
+{
+ SGNDigestInfo *di;
+ SECStatus rv;
+ PLArenaPool *arena;
+ SECItem *null_param;
+ SECItem dummy_value;
+
+ switch (algorithm) {
+ case SEC_OID_MD2:
+ case SEC_OID_MD5:
+ case SEC_OID_SHA1:
+ case SEC_OID_SHA224:
+ case SEC_OID_SHA256:
+ case SEC_OID_SHA384:
+ case SEC_OID_SHA512:
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+ return NULL;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ return NULL;
+ }
+
+ di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
+ if (di == NULL) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return NULL;
+ }
+
+ di->arena = arena;
+
+ /*
+ * PKCS #1 specifies that the AlgorithmID must have a NULL parameter
+ * (as opposed to no parameter at all).
+ */
+ dummy_value.data = NULL;
+ dummy_value.len = 0;
+ null_param = SEC_ASN1EncodeItem(NULL, NULL, &dummy_value, SEC_NullTemplate);
+ if (null_param == NULL) {
+ goto loser;
+ }
+
+ rv = SECOID_SetAlgorithmID(arena, &di->digestAlgorithm, algorithm,
+ null_param);
+
+ SECITEM_FreeItem(null_param, PR_TRUE);
+
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ di->digest.data = (unsigned char *)PORT_ArenaAlloc(arena, len);
+ if (di->digest.data == NULL) {
+ goto loser;
+ }
+
+ di->digest.len = len;
+ PORT_Memcpy(di->digest.data, sig, len);
+ return di;
+
+loser:
+ SGN_DestroyDigestInfo(di);
+ return NULL;
+}
+
+SGNDigestInfo *
+SGN_DecodeDigestInfo(SECItem *didata)
+{
+ PLArenaPool *arena;
+ SGNDigestInfo *di;
+ SECStatus rv = SECFailure;
+ SECItem diCopy = { siBuffer, NULL, 0 };
+
+ arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (arena == NULL)
+ return NULL;
+
+ rv = SECITEM_CopyItem(arena, &diCopy, didata);
+ if (rv != SECSuccess) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return NULL;
+ }
+
+ di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
+ if (di != NULL) {
+ di->arena = arena;
+ rv = SEC_QuickDERDecodeItem(arena, di, sgn_DigestInfoTemplate, &diCopy);
+ }
+
+ if ((di == NULL) || (rv != SECSuccess)) {
+ PORT_FreeArena(arena, PR_FALSE);
+ di = NULL;
+ }
+
+ return di;
+}
+
+void
+SGN_DestroyDigestInfo(SGNDigestInfo *di)
+{
+ if (di && di->arena) {
+ PORT_FreeArena(di->arena, PR_TRUE);
+ }
+
+ return;
+}
+
+SECStatus
+SGN_CopyDigestInfo(PLArenaPool *poolp, SGNDigestInfo *a, SGNDigestInfo *b)
+{
+ SECStatus rv;
+ void *mark;
+
+ if ((poolp == NULL) || (a == NULL) || (b == NULL))
+ return SECFailure;
+
+ mark = PORT_ArenaMark(poolp);
+ a->arena = poolp;
+ rv = SECOID_CopyAlgorithmID(poolp, &a->digestAlgorithm,
+ &b->digestAlgorithm);
+ if (rv == SECSuccess)
+ rv = SECITEM_CopyItem(poolp, &a->digest, &b->digest);
+
+ if (rv != SECSuccess) {
+ PORT_ArenaRelease(poolp, mark);
+ } else {
+ PORT_ArenaUnmark(poolp, mark);
+ }
+
+ return rv;
+}
+
+SECComparison
+SGN_CompareDigestInfo(SGNDigestInfo *a, SGNDigestInfo *b)
+{
+ SECComparison rv;
+
+ /* Check signature algorithm's */
+ rv = SECOID_CompareAlgorithmID(&a->digestAlgorithm, &b->digestAlgorithm);
+ if (rv)
+ return rv;
+
+ /* Compare signature block length's */
+ rv = SECITEM_CompareItem(&a->digest, &b->digest);
+ return rv;
+}
diff --git a/security/nss/lib/util/secdig.h b/security/nss/lib/util/secdig.h
new file mode 100644
index 0000000000..1531bf10ba
--- /dev/null
+++ b/security/nss/lib/util/secdig.h
@@ -0,0 +1,100 @@
+/*
+ * secdig.h - public prototypes for digest-info functions
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 _SECDIG_H_
+#define _SECDIG_H_
+
+#include "utilrename.h"
+#include "secdigt.h"
+
+#include "seccomon.h"
+#include "secasn1t.h"
+#include "secdert.h"
+
+SEC_BEGIN_PROTOS
+
+extern const SEC_ASN1Template sgn_DigestInfoTemplate[];
+
+SEC_ASN1_CHOOSER_DECLARE(sgn_DigestInfoTemplate)
+
+/****************************************/
+/*
+** Digest-info functions
+*/
+
+/*
+** Create a new digest-info object
+** "algorithm" one of SEC_OID_MD2, SEC_OID_MD5, or SEC_OID_SHA1
+** "sig" the raw signature data (from MD2 or MD5)
+** "sigLen" the length of the signature data
+**
+** NOTE: this is a low level routine used to prepare some data for PKCS#1
+** digital signature formatting.
+**
+** XXX It might be nice to combine the create and encode functions.
+** I think that is all anybody ever wants to do anyway.
+*/
+extern SGNDigestInfo *SGN_CreateDigestInfo(SECOidTag algorithm,
+ const unsigned char *sig,
+ unsigned int sigLen);
+
+/*
+** Destroy a digest-info object
+*/
+extern void SGN_DestroyDigestInfo(SGNDigestInfo *info);
+
+/*
+** Encode a digest-info object
+** "poolp" is where to allocate the result from; it can be NULL in
+** which case generic heap allocation (XP_ALLOC) will be used
+** "dest" is where to store the result; it can be NULL, in which case
+** it will be allocated (from poolp or heap, as explained above)
+** "diginfo" is the object to be encoded
+** The return value is NULL if any error occurred, otherwise it is the
+** resulting SECItem (either allocated or the same as the "dest" parameter).
+**
+** XXX It might be nice to combine the create and encode functions.
+** I think that is all anybody ever wants to do anyway.
+*/
+extern SECItem *SGN_EncodeDigestInfo(PLArenaPool *poolp, SECItem *dest,
+ SGNDigestInfo *diginfo);
+
+/*
+** Decode a DER encoded digest info objct.
+** didata is thr source of the encoded digest.
+** The return value is NULL if an error occurs. Otherwise, a
+** digest info object which is allocated within it's own
+** pool is returned. The digest info should be deleted
+** by later calling SGN_DestroyDigestInfo.
+*/
+extern SGNDigestInfo *SGN_DecodeDigestInfo(SECItem *didata);
+
+/*
+** Copy digest info.
+** poolp is the arena to which the digest will be copied.
+** a is the destination digest, it must be non-NULL.
+** b is the source digest
+** This function is for copying digests. It allows digests
+** to be copied into a specified pool. If the digest is in
+** the same pool as other data, you do not want to delete
+** the digest by calling SGN_DestroyDigestInfo.
+** A return value of SECFailure indicates an error. A return
+** of SECSuccess indicates no error occurred.
+*/
+extern SECStatus SGN_CopyDigestInfo(PLArenaPool *poolp,
+ SGNDigestInfo *a,
+ SGNDigestInfo *b);
+
+/*
+** Compare two digest-info objects, returning the difference between
+** them.
+*/
+extern SECComparison SGN_CompareDigestInfo(SGNDigestInfo *a, SGNDigestInfo *b);
+
+SEC_END_PROTOS
+
+#endif /* _SECDIG_H_ */
diff --git a/security/nss/lib/util/secdigt.h b/security/nss/lib/util/secdigt.h
new file mode 100644
index 0000000000..4553434679
--- /dev/null
+++ b/security/nss/lib/util/secdigt.h
@@ -0,0 +1,26 @@
+/*
+ * secdigt.h - public data structures for digest-info objects
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 _SECDIGT_H_
+#define _SECDIGT_H_
+
+#include "utilrename.h"
+#include "plarena.h"
+#include "secoidt.h"
+#include "secitem.h"
+
+/*
+** A PKCS#1 digest-info object
+*/
+struct SGNDigestInfoStr {
+ PLArenaPool* arena;
+ SECAlgorithmID digestAlgorithm;
+ SECItem digest;
+};
+typedef struct SGNDigestInfoStr SGNDigestInfo;
+
+#endif /* _SECDIGT_H_ */
diff --git a/security/nss/lib/util/secerr.h b/security/nss/lib/util/secerr.h
new file mode 100644
index 0000000000..5b7c9cc5fa
--- /dev/null
+++ b/security/nss/lib/util/secerr.h
@@ -0,0 +1,226 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __SEC_ERR_H_
+#define __SEC_ERR_H_
+
+#include "utilrename.h"
+
+#define SEC_ERROR_BASE (-0x2000)
+#define SEC_ERROR_LIMIT (SEC_ERROR_BASE + 1000)
+
+#define IS_SEC_ERROR(code) \
+ (((code) >= SEC_ERROR_BASE) && ((code) < SEC_ERROR_LIMIT))
+
+#ifndef NO_SECURITY_ERROR_ENUM
+typedef enum {
+ SEC_ERROR_IO = SEC_ERROR_BASE + 0,
+ SEC_ERROR_LIBRARY_FAILURE = SEC_ERROR_BASE + 1,
+ SEC_ERROR_BAD_DATA = SEC_ERROR_BASE + 2,
+ SEC_ERROR_OUTPUT_LEN = SEC_ERROR_BASE + 3,
+ SEC_ERROR_INPUT_LEN = SEC_ERROR_BASE + 4,
+ SEC_ERROR_INVALID_ARGS = SEC_ERROR_BASE + 5,
+ SEC_ERROR_INVALID_ALGORITHM = SEC_ERROR_BASE + 6,
+ SEC_ERROR_INVALID_AVA = SEC_ERROR_BASE + 7,
+ SEC_ERROR_INVALID_TIME = SEC_ERROR_BASE + 8,
+ SEC_ERROR_BAD_DER = SEC_ERROR_BASE + 9,
+ SEC_ERROR_BAD_SIGNATURE = SEC_ERROR_BASE + 10,
+ SEC_ERROR_EXPIRED_CERTIFICATE = SEC_ERROR_BASE + 11,
+ SEC_ERROR_REVOKED_CERTIFICATE = SEC_ERROR_BASE + 12,
+ SEC_ERROR_UNKNOWN_ISSUER = SEC_ERROR_BASE + 13,
+ SEC_ERROR_BAD_KEY = SEC_ERROR_BASE + 14,
+ SEC_ERROR_BAD_PASSWORD = SEC_ERROR_BASE + 15,
+ SEC_ERROR_RETRY_PASSWORD = SEC_ERROR_BASE + 16,
+ SEC_ERROR_NO_NODELOCK = SEC_ERROR_BASE + 17,
+ SEC_ERROR_BAD_DATABASE = SEC_ERROR_BASE + 18,
+ SEC_ERROR_NO_MEMORY = SEC_ERROR_BASE + 19,
+ SEC_ERROR_UNTRUSTED_ISSUER = SEC_ERROR_BASE + 20,
+ SEC_ERROR_UNTRUSTED_CERT = SEC_ERROR_BASE + 21,
+ SEC_ERROR_DUPLICATE_CERT = (SEC_ERROR_BASE + 22),
+ SEC_ERROR_DUPLICATE_CERT_NAME = (SEC_ERROR_BASE + 23),
+ SEC_ERROR_ADDING_CERT = (SEC_ERROR_BASE + 24),
+ SEC_ERROR_FILING_KEY = (SEC_ERROR_BASE + 25),
+ SEC_ERROR_NO_KEY = (SEC_ERROR_BASE + 26),
+ SEC_ERROR_CERT_VALID = (SEC_ERROR_BASE + 27),
+ SEC_ERROR_CERT_NOT_VALID = (SEC_ERROR_BASE + 28),
+ SEC_ERROR_CERT_NO_RESPONSE = (SEC_ERROR_BASE + 29),
+ SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE = (SEC_ERROR_BASE + 30),
+ SEC_ERROR_CRL_EXPIRED = (SEC_ERROR_BASE + 31),
+ SEC_ERROR_CRL_BAD_SIGNATURE = (SEC_ERROR_BASE + 32),
+ SEC_ERROR_CRL_INVALID = (SEC_ERROR_BASE + 33),
+ SEC_ERROR_EXTENSION_VALUE_INVALID = (SEC_ERROR_BASE + 34),
+ SEC_ERROR_EXTENSION_NOT_FOUND = (SEC_ERROR_BASE + 35),
+ SEC_ERROR_CA_CERT_INVALID = (SEC_ERROR_BASE + 36),
+ SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID = (SEC_ERROR_BASE + 37),
+ SEC_ERROR_CERT_USAGES_INVALID = (SEC_ERROR_BASE + 38),
+ SEC_INTERNAL_ONLY = (SEC_ERROR_BASE + 39),
+ SEC_ERROR_INVALID_KEY = (SEC_ERROR_BASE + 40),
+ SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION = (SEC_ERROR_BASE + 41),
+ SEC_ERROR_OLD_CRL = (SEC_ERROR_BASE + 42),
+ SEC_ERROR_NO_EMAIL_CERT = (SEC_ERROR_BASE + 43),
+ SEC_ERROR_NO_RECIPIENT_CERTS_QUERY = (SEC_ERROR_BASE + 44),
+ SEC_ERROR_NOT_A_RECIPIENT = (SEC_ERROR_BASE + 45),
+ SEC_ERROR_PKCS7_KEYALG_MISMATCH = (SEC_ERROR_BASE + 46),
+ SEC_ERROR_PKCS7_BAD_SIGNATURE = (SEC_ERROR_BASE + 47),
+ SEC_ERROR_UNSUPPORTED_KEYALG = (SEC_ERROR_BASE + 48),
+ SEC_ERROR_DECRYPTION_DISALLOWED = (SEC_ERROR_BASE + 49),
+ /* Fortezza Alerts */
+ XP_SEC_FORTEZZA_BAD_CARD = (SEC_ERROR_BASE + 50),
+ XP_SEC_FORTEZZA_NO_CARD = (SEC_ERROR_BASE + 51),
+ XP_SEC_FORTEZZA_NONE_SELECTED = (SEC_ERROR_BASE + 52),
+ XP_SEC_FORTEZZA_MORE_INFO = (SEC_ERROR_BASE + 53),
+ XP_SEC_FORTEZZA_PERSON_NOT_FOUND = (SEC_ERROR_BASE + 54),
+ XP_SEC_FORTEZZA_NO_MORE_INFO = (SEC_ERROR_BASE + 55),
+ XP_SEC_FORTEZZA_BAD_PIN = (SEC_ERROR_BASE + 56),
+ XP_SEC_FORTEZZA_PERSON_ERROR = (SEC_ERROR_BASE + 57),
+ SEC_ERROR_NO_KRL = (SEC_ERROR_BASE + 58),
+ SEC_ERROR_KRL_EXPIRED = (SEC_ERROR_BASE + 59),
+ SEC_ERROR_KRL_BAD_SIGNATURE = (SEC_ERROR_BASE + 60),
+ SEC_ERROR_REVOKED_KEY = (SEC_ERROR_BASE + 61),
+ SEC_ERROR_KRL_INVALID = (SEC_ERROR_BASE + 62),
+ SEC_ERROR_NEED_RANDOM = (SEC_ERROR_BASE + 63),
+ SEC_ERROR_NO_MODULE = (SEC_ERROR_BASE + 64),
+ SEC_ERROR_NO_TOKEN = (SEC_ERROR_BASE + 65),
+ SEC_ERROR_READ_ONLY = (SEC_ERROR_BASE + 66),
+ SEC_ERROR_NO_SLOT_SELECTED = (SEC_ERROR_BASE + 67),
+ SEC_ERROR_CERT_NICKNAME_COLLISION = (SEC_ERROR_BASE + 68),
+ SEC_ERROR_KEY_NICKNAME_COLLISION = (SEC_ERROR_BASE + 69),
+ SEC_ERROR_SAFE_NOT_CREATED = (SEC_ERROR_BASE + 70),
+ SEC_ERROR_BAGGAGE_NOT_CREATED = (SEC_ERROR_BASE + 71),
+ XP_JAVA_REMOVE_PRINCIPAL_ERROR = (SEC_ERROR_BASE + 72),
+ XP_JAVA_DELETE_PRIVILEGE_ERROR = (SEC_ERROR_BASE + 73),
+ XP_JAVA_CERT_NOT_EXISTS_ERROR = (SEC_ERROR_BASE + 74),
+ SEC_ERROR_BAD_EXPORT_ALGORITHM = (SEC_ERROR_BASE + 75),
+ SEC_ERROR_EXPORTING_CERTIFICATES = (SEC_ERROR_BASE + 76),
+ SEC_ERROR_IMPORTING_CERTIFICATES = (SEC_ERROR_BASE + 77),
+ SEC_ERROR_PKCS12_DECODING_PFX = (SEC_ERROR_BASE + 78),
+ SEC_ERROR_PKCS12_INVALID_MAC = (SEC_ERROR_BASE + 79),
+ SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM = (SEC_ERROR_BASE + 80),
+ SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE = (SEC_ERROR_BASE + 81),
+ SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE = (SEC_ERROR_BASE + 82),
+ SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM = (SEC_ERROR_BASE + 83),
+ SEC_ERROR_PKCS12_UNSUPPORTED_VERSION = (SEC_ERROR_BASE + 84),
+ SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT = (SEC_ERROR_BASE + 85),
+ SEC_ERROR_PKCS12_CERT_COLLISION = (SEC_ERROR_BASE + 86),
+ SEC_ERROR_USER_CANCELLED = (SEC_ERROR_BASE + 87),
+ SEC_ERROR_PKCS12_DUPLICATE_DATA = (SEC_ERROR_BASE + 88),
+ SEC_ERROR_MESSAGE_SEND_ABORTED = (SEC_ERROR_BASE + 89),
+ SEC_ERROR_INADEQUATE_KEY_USAGE = (SEC_ERROR_BASE + 90),
+ SEC_ERROR_INADEQUATE_CERT_TYPE = (SEC_ERROR_BASE + 91),
+ SEC_ERROR_CERT_ADDR_MISMATCH = (SEC_ERROR_BASE + 92),
+ SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY = (SEC_ERROR_BASE + 93),
+ SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN = (SEC_ERROR_BASE + 94),
+ SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME = (SEC_ERROR_BASE + 95),
+ SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY = (SEC_ERROR_BASE + 96),
+ SEC_ERROR_PKCS12_UNABLE_TO_WRITE = (SEC_ERROR_BASE + 97),
+ SEC_ERROR_PKCS12_UNABLE_TO_READ = (SEC_ERROR_BASE + 98),
+ SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED = (SEC_ERROR_BASE + 99),
+ SEC_ERROR_KEYGEN_FAIL = (SEC_ERROR_BASE + 100),
+ SEC_ERROR_INVALID_PASSWORD = (SEC_ERROR_BASE + 101),
+ SEC_ERROR_RETRY_OLD_PASSWORD = (SEC_ERROR_BASE + 102),
+ SEC_ERROR_BAD_NICKNAME = (SEC_ERROR_BASE + 103),
+ SEC_ERROR_NOT_FORTEZZA_ISSUER = (SEC_ERROR_BASE + 104),
+ SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY = (SEC_ERROR_BASE + 105),
+ SEC_ERROR_JS_INVALID_MODULE_NAME = (SEC_ERROR_BASE + 106),
+ SEC_ERROR_JS_INVALID_DLL = (SEC_ERROR_BASE + 107),
+ SEC_ERROR_JS_ADD_MOD_FAILURE = (SEC_ERROR_BASE + 108),
+ SEC_ERROR_JS_DEL_MOD_FAILURE = (SEC_ERROR_BASE + 109),
+ SEC_ERROR_OLD_KRL = (SEC_ERROR_BASE + 110),
+ SEC_ERROR_CKL_CONFLICT = (SEC_ERROR_BASE + 111),
+ SEC_ERROR_CERT_NOT_IN_NAME_SPACE = (SEC_ERROR_BASE + 112),
+ SEC_ERROR_KRL_NOT_YET_VALID = (SEC_ERROR_BASE + 113),
+ SEC_ERROR_CRL_NOT_YET_VALID = (SEC_ERROR_BASE + 114),
+ SEC_ERROR_UNKNOWN_CERT = (SEC_ERROR_BASE + 115),
+ SEC_ERROR_UNKNOWN_SIGNER = (SEC_ERROR_BASE + 116),
+ SEC_ERROR_CERT_BAD_ACCESS_LOCATION = (SEC_ERROR_BASE + 117),
+ SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE = (SEC_ERROR_BASE + 118),
+ SEC_ERROR_OCSP_BAD_HTTP_RESPONSE = (SEC_ERROR_BASE + 119),
+ SEC_ERROR_OCSP_MALFORMED_REQUEST = (SEC_ERROR_BASE + 120),
+ SEC_ERROR_OCSP_SERVER_ERROR = (SEC_ERROR_BASE + 121),
+ SEC_ERROR_OCSP_TRY_SERVER_LATER = (SEC_ERROR_BASE + 122),
+ SEC_ERROR_OCSP_REQUEST_NEEDS_SIG = (SEC_ERROR_BASE + 123),
+ SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST = (SEC_ERROR_BASE + 124),
+ SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS = (SEC_ERROR_BASE + 125),
+ SEC_ERROR_OCSP_UNKNOWN_CERT = (SEC_ERROR_BASE + 126),
+ SEC_ERROR_OCSP_NOT_ENABLED = (SEC_ERROR_BASE + 127),
+ SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER = (SEC_ERROR_BASE + 128),
+ SEC_ERROR_OCSP_MALFORMED_RESPONSE = (SEC_ERROR_BASE + 129),
+ SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE = (SEC_ERROR_BASE + 130),
+ SEC_ERROR_OCSP_FUTURE_RESPONSE = (SEC_ERROR_BASE + 131),
+ SEC_ERROR_OCSP_OLD_RESPONSE = (SEC_ERROR_BASE + 132),
+ /* smime stuff */
+ SEC_ERROR_DIGEST_NOT_FOUND = (SEC_ERROR_BASE + 133),
+ SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE = (SEC_ERROR_BASE + 134),
+ SEC_ERROR_MODULE_STUCK = (SEC_ERROR_BASE + 135),
+ SEC_ERROR_BAD_TEMPLATE = (SEC_ERROR_BASE + 136),
+ SEC_ERROR_CRL_NOT_FOUND = (SEC_ERROR_BASE + 137),
+ SEC_ERROR_REUSED_ISSUER_AND_SERIAL = (SEC_ERROR_BASE + 138),
+ SEC_ERROR_BUSY = (SEC_ERROR_BASE + 139),
+ SEC_ERROR_EXTRA_INPUT = (SEC_ERROR_BASE + 140),
+ /* error codes used by elliptic curve code */
+ SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE = (SEC_ERROR_BASE + 141),
+ SEC_ERROR_UNSUPPORTED_EC_POINT_FORM = (SEC_ERROR_BASE + 142),
+ SEC_ERROR_UNRECOGNIZED_OID = (SEC_ERROR_BASE + 143),
+ SEC_ERROR_OCSP_INVALID_SIGNING_CERT = (SEC_ERROR_BASE + 144),
+ /* new revocation errors */
+ SEC_ERROR_REVOKED_CERTIFICATE_CRL = (SEC_ERROR_BASE + 145),
+ SEC_ERROR_REVOKED_CERTIFICATE_OCSP = (SEC_ERROR_BASE + 146),
+ SEC_ERROR_CRL_INVALID_VERSION = (SEC_ERROR_BASE + 147),
+ SEC_ERROR_CRL_V1_CRITICAL_EXTENSION = (SEC_ERROR_BASE + 148),
+ SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION = (SEC_ERROR_BASE + 149),
+ SEC_ERROR_UNKNOWN_OBJECT_TYPE = (SEC_ERROR_BASE + 150),
+ SEC_ERROR_INCOMPATIBLE_PKCS11 = (SEC_ERROR_BASE + 151),
+ SEC_ERROR_NO_EVENT = (SEC_ERROR_BASE + 152),
+ SEC_ERROR_CRL_ALREADY_EXISTS = (SEC_ERROR_BASE + 153),
+ SEC_ERROR_NOT_INITIALIZED = (SEC_ERROR_BASE + 154),
+ SEC_ERROR_TOKEN_NOT_LOGGED_IN = (SEC_ERROR_BASE + 155),
+ SEC_ERROR_OCSP_RESPONDER_CERT_INVALID = (SEC_ERROR_BASE + 156),
+ SEC_ERROR_OCSP_BAD_SIGNATURE = (SEC_ERROR_BASE + 157),
+
+ SEC_ERROR_OUT_OF_SEARCH_LIMITS = (SEC_ERROR_BASE + 158),
+ SEC_ERROR_INVALID_POLICY_MAPPING = (SEC_ERROR_BASE + 159),
+ SEC_ERROR_POLICY_VALIDATION_FAILED = (SEC_ERROR_BASE + 160),
+ /* No longer used. Unknown AIA location types are now silently ignored. */
+ SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE = (SEC_ERROR_BASE + 161),
+ SEC_ERROR_BAD_HTTP_RESPONSE = (SEC_ERROR_BASE + 162),
+ SEC_ERROR_BAD_LDAP_RESPONSE = (SEC_ERROR_BASE + 163),
+ SEC_ERROR_FAILED_TO_ENCODE_DATA = (SEC_ERROR_BASE + 164),
+ SEC_ERROR_BAD_INFO_ACCESS_LOCATION = (SEC_ERROR_BASE + 165),
+
+ SEC_ERROR_LIBPKIX_INTERNAL = (SEC_ERROR_BASE + 166),
+
+ SEC_ERROR_PKCS11_GENERAL_ERROR = (SEC_ERROR_BASE + 167),
+ SEC_ERROR_PKCS11_FUNCTION_FAILED = (SEC_ERROR_BASE + 168),
+ SEC_ERROR_PKCS11_DEVICE_ERROR = (SEC_ERROR_BASE + 169),
+
+ SEC_ERROR_BAD_INFO_ACCESS_METHOD = (SEC_ERROR_BASE + 170),
+ SEC_ERROR_CRL_IMPORT_FAILED = (SEC_ERROR_BASE + 171),
+
+ SEC_ERROR_EXPIRED_PASSWORD = (SEC_ERROR_BASE + 172),
+ SEC_ERROR_LOCKED_PASSWORD = (SEC_ERROR_BASE + 173),
+
+ SEC_ERROR_UNKNOWN_PKCS11_ERROR = (SEC_ERROR_BASE + 174),
+
+ SEC_ERROR_BAD_CRL_DP_URL = (SEC_ERROR_BASE + 175),
+
+ SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED = (SEC_ERROR_BASE + 176),
+
+ SEC_ERROR_LEGACY_DATABASE = (SEC_ERROR_BASE + 177),
+
+ SEC_ERROR_APPLICATION_CALLBACK_ERROR = (SEC_ERROR_BASE + 178),
+
+ SEC_ERROR_INVALID_STATE = (SEC_ERROR_BASE + 179),
+
+ SEC_ERROR_POLICY_LOCKED = (SEC_ERROR_BASE + 180),
+ SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED = (SEC_ERROR_BASE + 181),
+ SEC_ERROR_ALGORITHM_MISMATCH = (SEC_ERROR_BASE + 182),
+
+ SEC_ERROR_CERTIFICATE_COMPRESSION_ALGORITHM_NOT_SUPPORTED = (SEC_ERROR_BASE + 183),
+ SEC_ERROR_UNEXPECTED_COMPRESSED_CERTIFICATE = (SEC_ERROR_BASE + 184),
+ /* Add new error codes above here. */
+ SEC_ERROR_END_OF_LIST
+} SECErrorCodes;
+#endif /* NO_SECURITY_ERROR_ENUM */
+
+#endif /* __SEC_ERR_H_ */
diff --git a/security/nss/lib/util/secitem.c b/security/nss/lib/util/secitem.c
new file mode 100644
index 0000000000..cd69961782
--- /dev/null
+++ b/security/nss/lib/util/secitem.c
@@ -0,0 +1,496 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Support routines for SECItem data structure.
+ */
+
+#include "seccomon.h"
+#include "secitem.h"
+#include "secerr.h"
+#include "secport.h"
+
+SECItem *
+SECITEM_AllocItem(PLArenaPool *arena, SECItem *item, unsigned int len)
+{
+ SECItem *result = NULL;
+ void *mark = NULL;
+
+ if (arena != NULL) {
+ mark = PORT_ArenaMark(arena);
+ }
+
+ if (item == NULL) {
+ if (arena != NULL) {
+ result = PORT_ArenaZAlloc(arena, sizeof(SECItem));
+ } else {
+ result = PORT_ZAlloc(sizeof(SECItem));
+ }
+ if (result == NULL) {
+ goto loser;
+ }
+ } else {
+ PORT_Assert(item->data == NULL);
+ result = item;
+ }
+
+ result->len = len;
+ if (len) {
+ if (arena != NULL) {
+ result->data = PORT_ArenaAlloc(arena, len);
+ } else {
+ result->data = PORT_Alloc(len);
+ }
+ if (result->data == NULL) {
+ goto loser;
+ }
+ } else {
+ result->data = NULL;
+ }
+
+ if (mark) {
+ PORT_ArenaUnmark(arena, mark);
+ }
+ return (result);
+
+loser:
+ if (arena != NULL) {
+ if (mark) {
+ PORT_ArenaRelease(arena, mark);
+ }
+ if (item != NULL) {
+ item->data = NULL;
+ item->len = 0;
+ }
+ } else {
+ if (result != NULL) {
+ SECITEM_FreeItem(result, (item == NULL) ? PR_TRUE : PR_FALSE);
+ }
+ /*
+ * If item is not NULL, the above has set item->data and
+ * item->len to 0.
+ */
+ }
+ return (NULL);
+}
+
+SECStatus
+SECITEM_MakeItem(PLArenaPool *arena, SECItem *dest, const unsigned char *data,
+ unsigned int len)
+{
+ SECItem it = { siBuffer, (unsigned char *)data, len };
+
+ return SECITEM_CopyItem(arena, dest, &it);
+}
+
+SECStatus
+SECITEM_ReallocItem(PLArenaPool *arena, SECItem *item, unsigned int oldlen,
+ unsigned int newlen)
+{
+ PORT_Assert(item != NULL);
+ if (item == NULL) {
+ /* XXX Set error. But to what? */
+ return SECFailure;
+ }
+
+ /*
+ * If no old length, degenerate to just plain alloc.
+ */
+ if (oldlen == 0) {
+ PORT_Assert(item->data == NULL || item->len == 0);
+ if (newlen == 0) {
+ /* Nothing to do. Weird, but not a failure. */
+ return SECSuccess;
+ }
+ item->len = newlen;
+ if (arena != NULL) {
+ item->data = PORT_ArenaAlloc(arena, newlen);
+ } else {
+ item->data = PORT_Alloc(newlen);
+ }
+ } else {
+ if (arena != NULL) {
+ item->data = PORT_ArenaGrow(arena, item->data, oldlen, newlen);
+ } else {
+ item->data = PORT_Realloc(item->data, newlen);
+ }
+ }
+
+ if (item->data == NULL) {
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+SECStatus
+SECITEM_ReallocItemV2(PLArenaPool *arena, SECItem *item, unsigned int newlen)
+{
+ unsigned char *newdata = NULL;
+
+ PORT_Assert(item);
+ if (!item) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (item->len == newlen) {
+ return SECSuccess;
+ }
+
+ if (!newlen) {
+ if (!arena) {
+ PORT_Free(item->data);
+ }
+ item->data = NULL;
+ item->len = 0;
+ return SECSuccess;
+ }
+
+ if (!item->data) {
+ /* allocate fresh block of memory */
+ PORT_Assert(!item->len);
+ if (arena) {
+ newdata = PORT_ArenaAlloc(arena, newlen);
+ } else {
+ newdata = PORT_Alloc(newlen);
+ }
+ } else {
+ /* reallocate or adjust existing block of memory */
+ if (arena) {
+ if (item->len > newlen) {
+ /* There's no need to realloc a shorter block from the arena,
+ * because it would result in using even more memory!
+ * Therefore we'll continue to use the old block and
+ * set the item to the shorter size.
+ */
+ item->len = newlen;
+ return SECSuccess;
+ }
+ newdata = PORT_ArenaGrow(arena, item->data, item->len, newlen);
+ } else {
+ newdata = PORT_Realloc(item->data, newlen);
+ }
+ }
+
+ if (!newdata) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return SECFailure;
+ }
+
+ item->len = newlen;
+ item->data = newdata;
+ return SECSuccess;
+}
+
+SECComparison
+SECITEM_CompareItem(const SECItem *a, const SECItem *b)
+{
+ unsigned m;
+ int rv;
+
+ if (a == b)
+ return SECEqual;
+ if (!a || !a->len || !a->data)
+ return (!b || !b->len || !b->data) ? SECEqual : SECLessThan;
+ if (!b || !b->len || !b->data)
+ return SECGreaterThan;
+
+ m = ((a->len < b->len) ? a->len : b->len);
+
+ rv = PORT_Memcmp(a->data, b->data, m);
+ if (rv) {
+ return rv < 0 ? SECLessThan : SECGreaterThan;
+ }
+ if (a->len < b->len) {
+ return SECLessThan;
+ }
+ if (a->len == b->len) {
+ return SECEqual;
+ }
+ return SECGreaterThan;
+}
+
+PRBool
+SECITEM_ItemsAreEqual(const SECItem *a, const SECItem *b)
+{
+ if (a->len != b->len)
+ return PR_FALSE;
+ if (!a->len)
+ return PR_TRUE;
+ if (!a->data || !b->data) {
+ /* avoid null pointer crash. */
+ return (PRBool)(a->data == b->data);
+ }
+ return (PRBool)!PORT_Memcmp(a->data, b->data, a->len);
+}
+
+SECItem *
+SECITEM_DupItem(const SECItem *from)
+{
+ return SECITEM_ArenaDupItem(NULL, from);
+}
+
+SECItem *
+SECITEM_ArenaDupItem(PLArenaPool *arena, const SECItem *from)
+{
+ SECItem *to;
+
+ if (from == NULL) {
+ return (NULL);
+ }
+
+ if (arena != NULL) {
+ to = (SECItem *)PORT_ArenaAlloc(arena, sizeof(SECItem));
+ } else {
+ to = (SECItem *)PORT_Alloc(sizeof(SECItem));
+ }
+ if (to == NULL) {
+ return (NULL);
+ }
+
+ if (arena != NULL) {
+ to->data = (unsigned char *)PORT_ArenaAlloc(arena, from->len);
+ } else {
+ to->data = (unsigned char *)PORT_Alloc(from->len);
+ }
+ if (to->data == NULL) {
+ PORT_Free(to);
+ return (NULL);
+ }
+
+ to->len = from->len;
+ to->type = from->type;
+ if (to->len) {
+ PORT_Memcpy(to->data, from->data, to->len);
+ }
+
+ return (to);
+}
+
+SECStatus
+SECITEM_CopyItem(PLArenaPool *arena, SECItem *to, const SECItem *from)
+{
+ to->type = from->type;
+ if (from->data && from->len) {
+ if (arena) {
+ to->data = (unsigned char *)PORT_ArenaAlloc(arena, from->len);
+ } else {
+ to->data = (unsigned char *)PORT_Alloc(from->len);
+ }
+
+ if (!to->data) {
+ return SECFailure;
+ }
+ PORT_Memcpy(to->data, from->data, from->len);
+ to->len = from->len;
+ } else {
+ /*
+ * If from->data is NULL but from->len is nonzero, this function
+ * will succeed. Is this right?
+ */
+ to->data = 0;
+ to->len = 0;
+ }
+ return SECSuccess;
+}
+
+void
+SECITEM_FreeItem(SECItem *zap, PRBool freeit)
+{
+ if (zap) {
+ PORT_Free(zap->data);
+ zap->data = 0;
+ zap->len = 0;
+ if (freeit) {
+ PORT_Free(zap);
+ }
+ }
+}
+
+void
+SECITEM_ZfreeItem(SECItem *zap, PRBool freeit)
+{
+ if (zap) {
+ PORT_ZFree(zap->data, zap->len);
+ zap->data = 0;
+ zap->len = 0;
+ if (freeit) {
+ PORT_ZFree(zap, sizeof(SECItem));
+ }
+ }
+}
+/* these reroutines were taken from pkix oid.c, which is supposed to
+ * replace this file some day */
+/*
+ * This is the hash function. We simply XOR the encoded form with
+ * itself in sizeof(PLHashNumber)-byte chunks. Improving this
+ * routine is left as an excercise for the more mathematically
+ * inclined student.
+ */
+PLHashNumber PR_CALLBACK
+SECITEM_Hash(const void *key)
+{
+ const SECItem *item = (const SECItem *)key;
+ PLHashNumber rv = 0;
+
+ PRUint8 *data = (PRUint8 *)item->data;
+ PRUint32 i;
+ PRUint8 *rvc = (PRUint8 *)&rv;
+
+ for (i = 0; i < item->len; i++) {
+ rvc[i % sizeof(rv)] ^= *data;
+ data++;
+ }
+
+ return rv;
+}
+
+/*
+ * This is the key-compare function. It simply does a lexical
+ * comparison on the item data. This does not result in
+ * quite the same ordering as the "sequence of numbers" order,
+ * but heck it's only used internally by the hash table anyway.
+ */
+PRIntn PR_CALLBACK
+SECITEM_HashCompare(const void *k1, const void *k2)
+{
+ const SECItem *i1 = (const SECItem *)k1;
+ const SECItem *i2 = (const SECItem *)k2;
+
+ return SECITEM_ItemsAreEqual(i1, i2);
+}
+
+SECItemArray *
+SECITEM_AllocArray(PLArenaPool *arena, SECItemArray *array, unsigned int len)
+{
+ SECItemArray *result = NULL;
+ void *mark = NULL;
+
+ if (array != NULL && array->items != NULL) {
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ if (arena != NULL) {
+ mark = PORT_ArenaMark(arena);
+ }
+
+ if (array == NULL) {
+ if (arena != NULL) {
+ result = PORT_ArenaZAlloc(arena, sizeof(SECItemArray));
+ } else {
+ result = PORT_ZAlloc(sizeof(SECItemArray));
+ }
+ if (result == NULL) {
+ goto loser;
+ }
+ } else {
+ result = array;
+ }
+
+ result->len = len;
+ if (len) {
+ if (arena != NULL) {
+ result->items = PORT_ArenaZNewArray(arena, SECItem, len);
+ } else {
+ result->items = PORT_ZNewArray(SECItem, len);
+ }
+ if (result->items == NULL) {
+ goto loser;
+ }
+ } else {
+ result->items = NULL;
+ }
+
+ if (mark) {
+ PORT_ArenaUnmark(arena, mark);
+ }
+ return result;
+
+loser:
+ if (arena != NULL) {
+ if (mark) {
+ PORT_ArenaRelease(arena, mark);
+ }
+ } else {
+ if (result != NULL && array == NULL) {
+ PORT_Free(result);
+ }
+ }
+ if (array != NULL) {
+ array->items = NULL;
+ array->len = 0;
+ }
+ return NULL;
+}
+
+static void
+secitem_FreeArray(SECItemArray *array, PRBool zero_items, PRBool freeit)
+{
+ unsigned int i;
+
+ if (!array || !array->len || !array->items)
+ return;
+
+ for (i = 0; i < array->len; ++i) {
+ SECItem *item = &array->items[i];
+
+ if (item->data) {
+ if (zero_items) {
+ SECITEM_ZfreeItem(item, PR_FALSE);
+ } else {
+ SECITEM_FreeItem(item, PR_FALSE);
+ }
+ }
+ }
+ PORT_Free(array->items);
+ array->items = NULL;
+ array->len = 0;
+
+ if (freeit)
+ PORT_Free(array);
+}
+
+void
+SECITEM_FreeArray(SECItemArray *array, PRBool freeit)
+{
+ secitem_FreeArray(array, PR_FALSE, freeit);
+}
+
+void
+SECITEM_ZfreeArray(SECItemArray *array, PRBool freeit)
+{
+ secitem_FreeArray(array, PR_TRUE, freeit);
+}
+
+SECItemArray *
+SECITEM_DupArray(PLArenaPool *arena, const SECItemArray *from)
+{
+ SECItemArray *result;
+ unsigned int i;
+
+ /* Require a "from" array.
+ * Reject an inconsistent "from" array with NULL data and nonzero length.
+ * However, allow a "from" array of zero length.
+ */
+ if (!from || (!from->items && from->len))
+ return NULL;
+
+ result = SECITEM_AllocArray(arena, NULL, from->len);
+ if (!result)
+ return NULL;
+
+ for (i = 0; i < from->len; ++i) {
+ SECStatus rv = SECITEM_CopyItem(arena,
+ &result->items[i], &from->items[i]);
+ if (rv != SECSuccess) {
+ SECITEM_ZfreeArray(result, PR_TRUE);
+ return NULL;
+ }
+ }
+
+ return result;
+}
diff --git a/security/nss/lib/util/secitem.h b/security/nss/lib/util/secitem.h
new file mode 100644
index 0000000000..f7a8241b5d
--- /dev/null
+++ b/security/nss/lib/util/secitem.h
@@ -0,0 +1,126 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _SECITEM_H_
+#define _SECITEM_H_
+
+#include "utilrename.h"
+
+/*
+ * secitem.h - public data structures and prototypes for handling
+ * SECItems
+ */
+
+#include "plarena.h"
+#include "plhash.h"
+#include "seccomon.h"
+
+SEC_BEGIN_PROTOS
+
+/*
+** Allocate an item. If "arena" is not NULL, then allocate from there,
+** otherwise allocate from the heap. If "item" is not NULL, allocate
+** only the data buffer for the item, not the item itself. If "len" is
+** 0, do not allocate the data buffer for the item; simply set the data
+** field to NULL and the len field to 0. The item structure is allocated
+** zero-filled; the data buffer is not zeroed. The caller is responsible
+** for initializing the type field of the item.
+**
+** The resulting item is returned; NULL if any error occurs.
+**
+** XXX This probably should take a SECItemType, but since that is mostly
+** unused and our improved APIs (aka Stan) are looming, I left it out.
+*/
+extern SECItem *SECITEM_AllocItem(PLArenaPool *arena, SECItem *item,
+ unsigned int len);
+
+/* Allocate and make an item with the requested contents.
+ *
+ * We seem to have mostly given up on SECItemType, so the result is
+ * always siBuffer.
+ */
+extern SECStatus SECITEM_MakeItem(PLArenaPool *arena, SECItem *dest,
+ const unsigned char *data, unsigned int len);
+
+/*
+** This is a legacy function containing bugs. It doesn't update item->len,
+** and it has other issues as described in bug 298649 and bug 298938.
+** However, the function is kept unchanged for consumers that might depend
+** on the broken behaviour. New code should call SECITEM_ReallocItemV2.
+**
+** Reallocate the data for the specified "item". If "arena" is not NULL,
+** then reallocate from there, otherwise reallocate from the heap.
+** In the case where oldlen is 0, the data is allocated (not reallocated).
+** In any case, "item" is expected to be a valid SECItem pointer;
+** SECFailure is returned if it is not. If the allocation succeeds,
+** SECSuccess is returned.
+*/
+extern SECStatus SECITEM_ReallocItem(/* deprecated function */
+ PLArenaPool *arena, SECItem *item,
+ unsigned int oldlen, unsigned int newlen);
+
+/*
+** Reallocate the data for the specified "item". If "arena" is not NULL,
+** then reallocate from there, otherwise reallocate from the heap.
+** If item->data is NULL, the data is allocated (not reallocated).
+** In any case, "item" is expected to be a valid SECItem pointer;
+** SECFailure is returned if it is not, and the item will remain unchanged.
+** If the allocation succeeds, the item is updated and SECSuccess is returned.
+ */
+extern SECStatus SECITEM_ReallocItemV2(PLArenaPool *arena, SECItem *item,
+ unsigned int newlen);
+
+/*
+** Compare two items returning the difference between them.
+*/
+extern SECComparison SECITEM_CompareItem(const SECItem *a, const SECItem *b);
+
+/*
+** Compare two items -- if they are the same, return true; otherwise false.
+*/
+extern PRBool SECITEM_ItemsAreEqual(const SECItem *a, const SECItem *b);
+
+/*
+** Copy "from" to "to"
+*/
+extern SECStatus SECITEM_CopyItem(PLArenaPool *arena, SECItem *to,
+ const SECItem *from);
+
+/*
+** Allocate an item and copy "from" into it.
+*/
+extern SECItem *SECITEM_DupItem(const SECItem *from);
+
+/*
+** Allocate an item and copy "from" into it. The item itself and the
+** data it points to are both allocated from the arena. If arena is
+** NULL, this function is equivalent to SECITEM_DupItem.
+*/
+extern SECItem *SECITEM_ArenaDupItem(PLArenaPool *arena, const SECItem *from);
+
+/*
+** Free "zap". If freeit is PR_TRUE then "zap" itself is freed.
+*/
+extern void SECITEM_FreeItem(SECItem *zap, PRBool freeit);
+
+/*
+** Zero and then free "zap". If freeit is PR_TRUE then "zap" itself is freed.
+*/
+extern void SECITEM_ZfreeItem(SECItem *zap, PRBool freeit);
+
+PLHashNumber PR_CALLBACK SECITEM_Hash(const void *key);
+
+PRIntn PR_CALLBACK SECITEM_HashCompare(const void *k1, const void *k2);
+
+extern SECItemArray *SECITEM_AllocArray(PLArenaPool *arena,
+ SECItemArray *array,
+ unsigned int len);
+extern SECItemArray *SECITEM_DupArray(PLArenaPool *arena,
+ const SECItemArray *from);
+extern void SECITEM_FreeArray(SECItemArray *array, PRBool freeit);
+extern void SECITEM_ZfreeArray(SECItemArray *array, PRBool freeit);
+
+SEC_END_PROTOS
+
+#endif /* _SECITEM_H_ */
diff --git a/security/nss/lib/util/secload.c b/security/nss/lib/util/secload.c
new file mode 100644
index 0000000000..1cebae4e27
--- /dev/null
+++ b/security/nss/lib/util/secload.c
@@ -0,0 +1,182 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secport.h"
+#include "nspr.h"
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#define BL_MAXSYMLINKS 20
+
+/*
+ * If 'link' is a symbolic link, this function follows the symbolic links
+ * and returns the pathname of the ultimate source of the symbolic links.
+ * If 'link' is not a symbolic link, this function returns NULL.
+ * The caller should call PR_Free to free the string returned by this
+ * function.
+ */
+static char*
+loader_GetOriginalPathname(const char* link)
+{
+ char* resolved = NULL;
+ char* input = NULL;
+ PRUint32 iterations = 0;
+ PRInt32 len = 0, retlen = 0;
+ if (!link) {
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ return NULL;
+ }
+ len = PR_MAX(1024, strlen(link) + 1);
+ resolved = PR_Malloc(len);
+ input = PR_Malloc(len);
+ if (!resolved || !input) {
+ if (resolved) {
+ PR_Free(resolved);
+ }
+ if (input) {
+ PR_Free(input);
+ }
+ return NULL;
+ }
+ strcpy(input, link);
+ while ((iterations++ < BL_MAXSYMLINKS) &&
+ ((retlen = readlink(input, resolved, len - 1)) > 0)) {
+ char* tmp = input;
+ resolved[retlen] = '\0'; /* NULL termination */
+ input = resolved;
+ resolved = tmp;
+ }
+ PR_Free(resolved);
+ if (iterations == 1 && retlen < 0) {
+ PR_Free(input);
+ input = NULL;
+ }
+ return input;
+}
+#endif /* XP_UNIX */
+
+/*
+ * Load the library with the file name 'name' residing in the same
+ * directory as the reference library, whose pathname is 'referencePath'.
+ */
+static PRLibrary*
+loader_LoadLibInReferenceDir(const char* referencePath, const char* name)
+{
+ PRLibrary* dlh = NULL;
+ char* fullName = NULL;
+ char* c;
+ PRLibSpec libSpec;
+
+ /* Remove the trailing filename from referencePath and add the new one */
+ c = strrchr(referencePath, PR_GetDirectorySeparator());
+ if (c) {
+ size_t referencePathSize = 1 + c - referencePath;
+ fullName = (char*)PORT_Alloc(strlen(name) + referencePathSize + 1);
+ if (fullName) {
+ memcpy(fullName, referencePath, referencePathSize);
+ strcpy(fullName + referencePathSize, name);
+#ifdef DEBUG_LOADER
+ PR_fprintf(PR_STDOUT, "\nAttempting to load fully-qualified %s\n",
+ fullName);
+#endif
+ libSpec.type = PR_LibSpec_Pathname;
+ libSpec.value.pathname = fullName;
+ dlh = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL
+#ifdef PR_LD_ALT_SEARCH_PATH
+ /* allow library's dependencies to be found in the same directory
+ * on Windows even if PATH is not set. Requires NSPR 4.8.1 . */
+ | PR_LD_ALT_SEARCH_PATH
+#endif
+ );
+ PORT_Free(fullName);
+ }
+ }
+ return dlh;
+}
+
+/*
+ * Load a shared library called "newShLibName" in the same directory as
+ * a shared library that is already loaded, called existingShLibName.
+ * A pointer to a static function in that shared library,
+ * staticShLibFunc, is required.
+ *
+ * existingShLibName:
+ * The file name of the shared library that shall be used as the
+ * "reference library". The loader will attempt to load the requested
+ * library from the same directory as the reference library.
+ *
+ * staticShLibFunc:
+ * Pointer to a static function in the "reference library".
+ *
+ * newShLibName:
+ * The simple file name of the new shared library to be loaded.
+ *
+ * We use PR_GetLibraryFilePathname to get the pathname of the loaded
+ * shared lib that contains this function, and then do a
+ * PR_LoadLibraryWithFlags with an absolute pathname for the shared
+ * library to be loaded.
+ *
+ * On Windows, the "alternate search path" strategy is employed, if available.
+ * On Unix, if existingShLibName is a symbolic link, and no link exists for the
+ * new library, the original link will be resolved, and the new library loaded
+ * from the resolved location.
+ *
+ * If the new shared library is not found in the same location as the reference
+ * library, it will then be loaded from the normal system library path.
+ *
+ */
+
+PRLibrary*
+PORT_LoadLibraryFromOrigin(const char* existingShLibName,
+ PRFuncPtr staticShLibFunc,
+ const char* newShLibName)
+{
+ PRLibrary* lib = NULL;
+ char* fullPath = NULL;
+ PRLibSpec libSpec;
+
+ /* Get the pathname for existingShLibName, e.g. /usr/lib/libnss3.so
+ * PR_GetLibraryFilePathname works with either the base library name or a
+ * function pointer, depending on the platform.
+ * We require the address of a function in the "reference library",
+ * provided by the caller. To avoid getting the address of the stub/thunk
+ * of an exported function by accident, use the address of a static
+ * function rather than an exported function.
+ */
+ fullPath = PR_GetLibraryFilePathname(existingShLibName,
+ staticShLibFunc);
+
+ if (fullPath) {
+ lib = loader_LoadLibInReferenceDir(fullPath, newShLibName);
+#ifdef XP_UNIX
+ if (!lib) {
+ /*
+ * If fullPath is a symbolic link, resolve the symbolic
+ * link and try again.
+ */
+ char* originalfullPath = loader_GetOriginalPathname(fullPath);
+ if (originalfullPath) {
+ PR_Free(fullPath);
+ fullPath = originalfullPath;
+ lib = loader_LoadLibInReferenceDir(fullPath, newShLibName);
+ }
+ }
+#endif
+ PR_Free(fullPath);
+ }
+ if (!lib) {
+#ifdef DEBUG_LOADER
+ PR_fprintf(PR_STDOUT, "\nAttempting to load %s\n", newShLibName);
+#endif
+ libSpec.type = PR_LibSpec_Pathname;
+ libSpec.value.pathname = newShLibName;
+ lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL);
+ }
+ if (NULL == lib) {
+#ifdef DEBUG_LOADER
+ PR_fprintf(PR_STDOUT, "\nLoading failed : %s.\n", newShLibName);
+#endif
+ }
+ return lib;
+}
diff --git a/security/nss/lib/util/secoid.c b/security/nss/lib/util/secoid.c
new file mode 100644
index 0000000000..800cc7ff62
--- /dev/null
+++ b/security/nss/lib/util/secoid.c
@@ -0,0 +1,2402 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secoid.h"
+#include "pkcs11t.h"
+#include "secitem.h"
+#include "secerr.h"
+#include "prenv.h"
+#include "plhash.h"
+#include "nssrwlk.h"
+#include "nssutil.h"
+#include "secoidt.h"
+
+/* Library identity and versioning */
+
+#if defined(DEBUG)
+#define _DEBUG_STRING " (debug)"
+#else
+#define _DEBUG_STRING ""
+#endif
+
+/*
+ * Version information
+ */
+const char __nss_util_version[] = "Version: NSS " NSSUTIL_VERSION _DEBUG_STRING;
+
+/* MISSI Mosaic Object ID space */
+/* USGov algorithm OID space: { 2 16 840 1 101 } */
+#define USGOV 0x60, 0x86, 0x48, 0x01, 0x65
+#define MISSI USGOV, 0x02, 0x01, 0x01
+#define MISSI_OLD_KEA_DSS MISSI, 0x0c
+#define MISSI_OLD_DSS MISSI, 0x02
+#define MISSI_KEA_DSS MISSI, 0x14
+#define MISSI_DSS MISSI, 0x13
+#define MISSI_KEA MISSI, 0x0a
+#define MISSI_ALT_KEA MISSI, 0x16
+
+#define NISTALGS USGOV, 3, 4
+#define AES NISTALGS, 1
+#define SHAXXX NISTALGS, 2
+#define DSA2 NISTALGS, 3
+
+/**
+ ** The Netscape OID space is allocated by Terry Hayes. If you need
+ ** a piece of the space, contact him at thayes@netscape.com.
+ **/
+
+/* Netscape Communications Corporation Object ID space */
+/* { 2 16 840 1 113730 } */
+#define NETSCAPE_OID 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42
+#define NETSCAPE_CERT_EXT NETSCAPE_OID, 0x01
+#define NETSCAPE_DATA_TYPE NETSCAPE_OID, 0x02
+/* netscape directory oid - owned by Mark Smith (mcs@netscape.com) */
+#define NETSCAPE_DIRECTORY NETSCAPE_OID, 0x03
+#define NETSCAPE_POLICY NETSCAPE_OID, 0x04
+#define NETSCAPE_CERT_SERVER NETSCAPE_OID, 0x05
+#define NETSCAPE_ALGS NETSCAPE_OID, 0x06 /* algorithm OIDs */
+#define NETSCAPE_NAME_COMPONENTS NETSCAPE_OID, 0x07
+
+#define NETSCAPE_CERT_EXT_AIA NETSCAPE_CERT_EXT, 0x10
+#define NETSCAPE_CERT_SERVER_CRMF NETSCAPE_CERT_SERVER, 0x01
+
+/* these are old and should go away soon */
+#define OLD_NETSCAPE 0x60, 0x86, 0x48, 0xd8, 0x6a
+#define NS_CERT_EXT OLD_NETSCAPE, 0x01
+#define NS_FILE_TYPE OLD_NETSCAPE, 0x02
+#define NS_IMAGE_TYPE OLD_NETSCAPE, 0x03
+
+/* RSA OID name space */
+#define RSADSI 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d
+#define PKCS RSADSI, 0x01
+#define DIGEST RSADSI, 0x02
+#define CIPHER RSADSI, 0x03
+#define PKCS1 PKCS, 0x01
+#define PKCS5 PKCS, 0x05
+#define PKCS7 PKCS, 0x07
+#define PKCS9 PKCS, 0x09
+#define PKCS12 PKCS, 0x0c
+
+/* Other OID name spaces */
+#define ALGORITHM 0x2b, 0x0e, 0x03, 0x02
+#define X500 0x55
+#define X520_ATTRIBUTE_TYPE X500, 0x04
+#define X500_ALG X500, 0x08
+#define X500_ALG_ENCRYPTION X500_ALG, 0x01
+
+/** X.509 v3 Extension OID
+ ** {joint-iso-ccitt (2) ds(5) 29}
+ **/
+#define ID_CE_OID X500, 0x1d
+
+#define RFC1274_ATTR_TYPE 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x1
+/* #define RFC2247_ATTR_TYPE 0x09, 0x92, 0x26, 0xf5, 0x98, 0x1e, 0x64, 0x1 this is WRONG! */
+
+/* PKCS #12 name spaces */
+#define PKCS12_MODE_IDS PKCS12, 0x01
+#define PKCS12_ESPVK_IDS PKCS12, 0x02
+#define PKCS12_BAG_IDS PKCS12, 0x03
+#define PKCS12_CERT_BAG_IDS PKCS12, 0x04
+#define PKCS12_OIDS PKCS12, 0x05
+#define PKCS12_PBE_IDS PKCS12_OIDS, 0x01
+#define PKCS12_ENVELOPING_IDS PKCS12_OIDS, 0x02
+#define PKCS12_SIGNATURE_IDS PKCS12_OIDS, 0x03
+#define PKCS12_V2_PBE_IDS PKCS12, 0x01
+#define PKCS9_CERT_TYPES PKCS9, 0x16
+#define PKCS9_CRL_TYPES PKCS9, 0x17
+#define PKCS9_SMIME_IDS PKCS9, 0x10
+#define PKCS9_SMIME_ATTRS PKCS9_SMIME_IDS, 2
+#define PKCS9_SMIME_ALGS PKCS9_SMIME_IDS, 3
+#define PKCS12_VERSION1 PKCS12, 0x0a
+#define PKCS12_V1_BAG_IDS PKCS12_VERSION1, 1
+
+/* for DSA algorithm */
+/* { iso(1) member-body(2) us(840) x9-57(10040) x9algorithm(4) } */
+#define ANSI_X9_ALGORITHM 0x2a, 0x86, 0x48, 0xce, 0x38, 0x4
+
+/* for DH algorithm */
+/* { iso(1) member-body(2) us(840) x9-57(10046) number-type(2) } */
+/* need real OID person to look at this, copied the above line
+ * and added 6 to second to last value (and changed '4' to '2' */
+#define ANSI_X942_ALGORITHM 0x2a, 0x86, 0x48, 0xce, 0x3e, 0x2
+
+#define VERISIGN 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x45
+
+#define INTERNET_SECURITY_MECH 0x2b, 0x06, 0x01, 0x05, 0x05
+
+#define PKIX INTERNET_SECURITY_MECH, 0x07
+#define PKIX_CERT_EXTENSIONS PKIX, 1
+#define PKIX_POLICY_QUALIFIERS PKIX, 2
+#define PKIX_KEY_USAGE PKIX, 3
+#define PKIX_ACCESS_DESCRIPTION PKIX, 0x30
+#define PKIX_OCSP PKIX_ACCESS_DESCRIPTION, 1
+#define PKIX_CA_ISSUERS PKIX_ACCESS_DESCRIPTION, 2
+
+#define PKIX_ID_PKIP PKIX, 5
+#define PKIX_ID_REGCTRL PKIX_ID_PKIP, 1
+#define PKIX_ID_REGINFO PKIX_ID_PKIP, 2
+
+/* Microsoft Object ID space */
+/* { 1.3.6.1.4.1.311 } */
+#define MICROSOFT_OID 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0x37
+#define EV_NAME_ATTRIBUTE MICROSOFT_OID, 60, 2, 1
+
+/* Microsoft Crypto 2.0 ID space */
+/* { 1.3.6.1.4.1.311.10 } */
+#define MS_CRYPTO_20 MICROSOFT_OID, 10
+/* Microsoft Crypto 2.0 Extended Key Usage ID space */
+/* { 1.3.6.1.4.1.311.10.3 } */
+#define MS_CRYPTO_EKU MS_CRYPTO_20, 3
+
+#define CERTICOM_OID 0x2b, 0x81, 0x04
+#define SECG_OID CERTICOM_OID, 0x00
+
+#define ANSI_X962_OID 0x2a, 0x86, 0x48, 0xce, 0x3d
+#define ANSI_X962_CURVE_OID ANSI_X962_OID, 0x03
+#define ANSI_X962_GF2m_OID ANSI_X962_CURVE_OID, 0x00
+#define ANSI_X962_GFp_OID ANSI_X962_CURVE_OID, 0x01
+#define ANSI_X962_SIGNATURE_OID ANSI_X962_OID, 0x04
+#define ANSI_X962_SPECIFY_OID ANSI_X962_SIGNATURE_OID, 0x03
+
+/* for Camellia: iso(1) member-body(2) jisc(392)
+ * mitsubishi(200011) isl(61) security(1) algorithm(1)
+ */
+#define MITSUBISHI_ALG 0x2a, 0x83, 0x08, 0x8c, 0x9a, 0x4b, 0x3d, 0x01, 0x01
+#define CAMELLIA_ENCRYPT_OID MITSUBISHI_ALG, 1
+#define CAMELLIA_WRAP_OID MITSUBISHI_ALG, 3
+
+/* For IDEA: 1.3.6.1.4.1.188.7.1.1
+ */
+#define ASCOM_OID 0x2b, 0x6, 0x1, 0x4, 0x1, 0xbc
+#define ASCOM_IDEA_ALG ASCOM_OID, 0x7, 0x1, 0x1
+
+/* for SEED : iso(1) member-body(2) korea(410)
+ * kisa(200004) algorithm(1)
+ */
+#define SEED_OID 0x2a, 0x83, 0x1a, 0x8c, 0x9a, 0x44, 0x01
+
+#define CONST_OID static const unsigned char
+
+CONST_OID md2[] = { DIGEST, 0x02 };
+CONST_OID md4[] = { DIGEST, 0x04 };
+CONST_OID md5[] = { DIGEST, 0x05 };
+CONST_OID hmac_sha1[] = { DIGEST, 7 };
+CONST_OID hmac_sha224[] = { DIGEST, 8 };
+CONST_OID hmac_sha256[] = { DIGEST, 9 };
+CONST_OID hmac_sha384[] = { DIGEST, 10 };
+CONST_OID hmac_sha512[] = { DIGEST, 11 };
+
+CONST_OID rc2cbc[] = { CIPHER, 0x02 };
+CONST_OID rc4[] = { CIPHER, 0x04 };
+CONST_OID desede3cbc[] = { CIPHER, 0x07 };
+CONST_OID rc5cbcpad[] = { CIPHER, 0x09 };
+
+CONST_OID desecb[] = { ALGORITHM, 0x06 };
+CONST_OID descbc[] = { ALGORITHM, 0x07 };
+CONST_OID desofb[] = { ALGORITHM, 0x08 };
+CONST_OID descfb[] = { ALGORITHM, 0x09 };
+CONST_OID desmac[] = { ALGORITHM, 0x0a };
+CONST_OID sdn702DSASignature[] = { ALGORITHM, 0x0c };
+CONST_OID isoSHAWithRSASignature[] = { ALGORITHM, 0x0f };
+CONST_OID desede[] = { ALGORITHM, 0x11 };
+CONST_OID sha1[] = { ALGORITHM, 0x1a };
+CONST_OID bogusDSASignaturewithSHA1Digest[] = { ALGORITHM, 0x1b };
+CONST_OID isoSHA1WithRSASignature[] = { ALGORITHM, 0x1d };
+
+CONST_OID pkcs1RSAEncryption[] = { PKCS1, 0x01 };
+CONST_OID pkcs1MD2WithRSAEncryption[] = { PKCS1, 0x02 };
+CONST_OID pkcs1MD4WithRSAEncryption[] = { PKCS1, 0x03 };
+CONST_OID pkcs1MD5WithRSAEncryption[] = { PKCS1, 0x04 };
+CONST_OID pkcs1SHA1WithRSAEncryption[] = { PKCS1, 0x05 };
+CONST_OID pkcs1RSAOAEPEncryption[] = { PKCS1, 0x07 };
+CONST_OID pkcs1MGF1[] = { PKCS1, 0x08 };
+CONST_OID pkcs1PSpecified[] = { PKCS1, 0x09 };
+CONST_OID pkcs1RSAPSSSignature[] = { PKCS1, 10 };
+CONST_OID pkcs1SHA256WithRSAEncryption[] = { PKCS1, 11 };
+CONST_OID pkcs1SHA384WithRSAEncryption[] = { PKCS1, 12 };
+CONST_OID pkcs1SHA512WithRSAEncryption[] = { PKCS1, 13 };
+CONST_OID pkcs1SHA224WithRSAEncryption[] = { PKCS1, 14 };
+
+CONST_OID pkcs5PbeWithMD2AndDEScbc[] = { PKCS5, 0x01 };
+CONST_OID pkcs5PbeWithMD5AndDEScbc[] = { PKCS5, 0x03 };
+CONST_OID pkcs5PbeWithSha1AndDEScbc[] = { PKCS5, 0x0a };
+CONST_OID pkcs5Pbkdf2[] = { PKCS5, 12 };
+CONST_OID pkcs5Pbes2[] = { PKCS5, 13 };
+CONST_OID pkcs5Pbmac1[] = { PKCS5, 14 };
+
+CONST_OID pkcs7[] = { PKCS7 };
+CONST_OID pkcs7Data[] = { PKCS7, 0x01 };
+CONST_OID pkcs7SignedData[] = { PKCS7, 0x02 };
+CONST_OID pkcs7EnvelopedData[] = { PKCS7, 0x03 };
+CONST_OID pkcs7SignedEnvelopedData[] = { PKCS7, 0x04 };
+CONST_OID pkcs7DigestedData[] = { PKCS7, 0x05 };
+CONST_OID pkcs7EncryptedData[] = { PKCS7, 0x06 };
+
+CONST_OID pkcs9EmailAddress[] = { PKCS9, 0x01 };
+CONST_OID pkcs9UnstructuredName[] = { PKCS9, 0x02 };
+CONST_OID pkcs9ContentType[] = { PKCS9, 0x03 };
+CONST_OID pkcs9MessageDigest[] = { PKCS9, 0x04 };
+CONST_OID pkcs9SigningTime[] = { PKCS9, 0x05 };
+CONST_OID pkcs9CounterSignature[] = { PKCS9, 0x06 };
+CONST_OID pkcs9ChallengePassword[] = { PKCS9, 0x07 };
+CONST_OID pkcs9UnstructuredAddress[] = { PKCS9, 0x08 };
+CONST_OID pkcs9ExtendedCertificateAttributes[] = { PKCS9, 0x09 };
+CONST_OID pkcs9ExtensionRequest[] = { PKCS9, 14 };
+CONST_OID pkcs9SMIMECapabilities[] = { PKCS9, 15 };
+CONST_OID pkcs9FriendlyName[] = { PKCS9, 20 };
+CONST_OID pkcs9LocalKeyID[] = { PKCS9, 21 };
+
+CONST_OID pkcs9X509Certificate[] = { PKCS9_CERT_TYPES, 1 };
+CONST_OID pkcs9SDSICertificate[] = { PKCS9_CERT_TYPES, 2 };
+CONST_OID pkcs9X509CRL[] = { PKCS9_CRL_TYPES, 1 };
+
+/* RFC2630 (CMS) OIDs */
+CONST_OID cmsESDH[] = { PKCS9_SMIME_ALGS, 5 };
+CONST_OID cms3DESwrap[] = { PKCS9_SMIME_ALGS, 6 };
+CONST_OID cmsRC2wrap[] = { PKCS9_SMIME_ALGS, 7 };
+
+/* RFC2633 SMIME message attributes */
+CONST_OID smimeEncryptionKeyPreference[] = { PKCS9_SMIME_ATTRS, 11 };
+CONST_OID ms_smimeEncryptionKeyPreference[] = { MICROSOFT_OID, 0x10, 0x4 };
+
+CONST_OID x520CommonName[] = { X520_ATTRIBUTE_TYPE, 3 };
+CONST_OID x520SurName[] = { X520_ATTRIBUTE_TYPE, 4 };
+CONST_OID x520SerialNumber[] = { X520_ATTRIBUTE_TYPE, 5 };
+CONST_OID x520CountryName[] = { X520_ATTRIBUTE_TYPE, 6 };
+CONST_OID x520LocalityName[] = { X520_ATTRIBUTE_TYPE, 7 };
+CONST_OID x520StateOrProvinceName[] = { X520_ATTRIBUTE_TYPE, 8 };
+CONST_OID x520StreetAddress[] = { X520_ATTRIBUTE_TYPE, 9 };
+CONST_OID x520OrgName[] = { X520_ATTRIBUTE_TYPE, 10 };
+CONST_OID x520OrgUnitName[] = { X520_ATTRIBUTE_TYPE, 11 };
+CONST_OID x520Title[] = { X520_ATTRIBUTE_TYPE, 12 };
+CONST_OID x520BusinessCategory[] = { X520_ATTRIBUTE_TYPE, 15 };
+CONST_OID x520PostalAddress[] = { X520_ATTRIBUTE_TYPE, 16 };
+CONST_OID x520PostalCode[] = { X520_ATTRIBUTE_TYPE, 17 };
+CONST_OID x520PostOfficeBox[] = { X520_ATTRIBUTE_TYPE, 18 };
+CONST_OID x520Name[] = { X520_ATTRIBUTE_TYPE, 41 };
+CONST_OID x520GivenName[] = { X520_ATTRIBUTE_TYPE, 42 };
+CONST_OID x520Initials[] = { X520_ATTRIBUTE_TYPE, 43 };
+CONST_OID x520GenerationQualifier[] = { X520_ATTRIBUTE_TYPE, 44 };
+CONST_OID x520DnQualifier[] = { X520_ATTRIBUTE_TYPE, 46 };
+CONST_OID x520HouseIdentifier[] = { X520_ATTRIBUTE_TYPE, 51 };
+CONST_OID x520Pseudonym[] = { X520_ATTRIBUTE_TYPE, 65 };
+
+CONST_OID nsTypeGIF[] = { NETSCAPE_DATA_TYPE, 0x01 };
+CONST_OID nsTypeJPEG[] = { NETSCAPE_DATA_TYPE, 0x02 };
+CONST_OID nsTypeURL[] = { NETSCAPE_DATA_TYPE, 0x03 };
+CONST_OID nsTypeHTML[] = { NETSCAPE_DATA_TYPE, 0x04 };
+CONST_OID nsTypeCertSeq[] = { NETSCAPE_DATA_TYPE, 0x05 };
+
+CONST_OID missiCertKEADSSOld[] = { MISSI_OLD_KEA_DSS };
+CONST_OID missiCertDSSOld[] = { MISSI_OLD_DSS };
+CONST_OID missiCertKEADSS[] = { MISSI_KEA_DSS };
+CONST_OID missiCertDSS[] = { MISSI_DSS };
+CONST_OID missiCertKEA[] = { MISSI_KEA };
+CONST_OID missiCertAltKEA[] = { MISSI_ALT_KEA };
+CONST_OID x500RSAEncryption[] = { X500_ALG_ENCRYPTION, 0x01 };
+
+/* added for alg 1485 */
+CONST_OID rfc1274Uid[] = { RFC1274_ATTR_TYPE, 1 };
+CONST_OID rfc1274Mail[] = { RFC1274_ATTR_TYPE, 3 };
+CONST_OID rfc2247DomainComponent[] = { RFC1274_ATTR_TYPE, 25 };
+
+/* Netscape private certificate extensions */
+CONST_OID nsCertExtNetscapeOK[] = { NS_CERT_EXT, 1 };
+CONST_OID nsCertExtIssuerLogo[] = { NS_CERT_EXT, 2 };
+CONST_OID nsCertExtSubjectLogo[] = { NS_CERT_EXT, 3 };
+CONST_OID nsExtCertType[] = { NETSCAPE_CERT_EXT, 0x01 };
+CONST_OID nsExtBaseURL[] = { NETSCAPE_CERT_EXT, 0x02 };
+CONST_OID nsExtRevocationURL[] = { NETSCAPE_CERT_EXT, 0x03 };
+CONST_OID nsExtCARevocationURL[] = { NETSCAPE_CERT_EXT, 0x04 };
+CONST_OID nsExtCACRLURL[] = { NETSCAPE_CERT_EXT, 0x05 };
+CONST_OID nsExtCACertURL[] = { NETSCAPE_CERT_EXT, 0x06 };
+CONST_OID nsExtCertRenewalURL[] = { NETSCAPE_CERT_EXT, 0x07 };
+CONST_OID nsExtCAPolicyURL[] = { NETSCAPE_CERT_EXT, 0x08 };
+CONST_OID nsExtHomepageURL[] = { NETSCAPE_CERT_EXT, 0x09 };
+CONST_OID nsExtEntityLogo[] = { NETSCAPE_CERT_EXT, 0x0a };
+CONST_OID nsExtUserPicture[] = { NETSCAPE_CERT_EXT, 0x0b };
+CONST_OID nsExtSSLServerName[] = { NETSCAPE_CERT_EXT, 0x0c };
+CONST_OID nsExtComment[] = { NETSCAPE_CERT_EXT, 0x0d };
+
+/* the following 2 extensions are defined for and used by Cartman(NSM) */
+CONST_OID nsExtLostPasswordURL[] = { NETSCAPE_CERT_EXT, 0x0e };
+CONST_OID nsExtCertRenewalTime[] = { NETSCAPE_CERT_EXT, 0x0f };
+
+CONST_OID nsExtAIACertRenewal[] = { NETSCAPE_CERT_EXT_AIA, 0x01 };
+CONST_OID nsExtCertScopeOfUse[] = { NETSCAPE_CERT_EXT, 0x11 };
+/* Reserved Netscape (2 16 840 1 113730 1 18) = { NETSCAPE_CERT_EXT, 0x12 }; */
+
+/* Netscape policy values */
+CONST_OID nsKeyUsageGovtApproved[] = { NETSCAPE_POLICY, 0x01 };
+
+/* Netscape other name types */
+CONST_OID netscapeNickname[] = { NETSCAPE_NAME_COMPONENTS, 0x01 };
+CONST_OID netscapeAOLScreenname[] = { NETSCAPE_NAME_COMPONENTS, 0x02 };
+
+/* OIDs needed for cert server */
+CONST_OID netscapeRecoveryRequest[] = { NETSCAPE_CERT_SERVER_CRMF, 0x01 };
+
+/* Standard x.509 v3 Certificate & CRL Extensions */
+CONST_OID x509SubjectDirectoryAttr[] = { ID_CE_OID, 9 };
+CONST_OID x509SubjectKeyID[] = { ID_CE_OID, 14 };
+CONST_OID x509KeyUsage[] = { ID_CE_OID, 15 };
+CONST_OID x509PrivateKeyUsagePeriod[] = { ID_CE_OID, 16 };
+CONST_OID x509SubjectAltName[] = { ID_CE_OID, 17 };
+CONST_OID x509IssuerAltName[] = { ID_CE_OID, 18 };
+CONST_OID x509BasicConstraints[] = { ID_CE_OID, 19 };
+CONST_OID x509CRLNumber[] = { ID_CE_OID, 20 };
+CONST_OID x509ReasonCode[] = { ID_CE_OID, 21 };
+CONST_OID x509HoldInstructionCode[] = { ID_CE_OID, 23 };
+CONST_OID x509InvalidDate[] = { ID_CE_OID, 24 };
+CONST_OID x509DeltaCRLIndicator[] = { ID_CE_OID, 27 };
+CONST_OID x509IssuingDistributionPoint[] = { ID_CE_OID, 28 };
+CONST_OID x509CertIssuer[] = { ID_CE_OID, 29 };
+CONST_OID x509NameConstraints[] = { ID_CE_OID, 30 };
+CONST_OID x509CRLDistPoints[] = { ID_CE_OID, 31 };
+CONST_OID x509CertificatePolicies[] = { ID_CE_OID, 32 };
+CONST_OID x509PolicyMappings[] = { ID_CE_OID, 33 };
+CONST_OID x509AuthKeyID[] = { ID_CE_OID, 35 };
+CONST_OID x509PolicyConstraints[] = { ID_CE_OID, 36 };
+CONST_OID x509ExtKeyUsage[] = { ID_CE_OID, 37 };
+CONST_OID x509FreshestCRL[] = { ID_CE_OID, 46 };
+CONST_OID x509InhibitAnyPolicy[] = { ID_CE_OID, 54 };
+
+CONST_OID x509CertificatePoliciesAnyPolicy[] = { ID_CE_OID, 32, 0 };
+CONST_OID x509ExtKeyUsageAnyUsage[] = { ID_CE_OID, 37, 0 };
+
+CONST_OID x509AuthInfoAccess[] = { PKIX_CERT_EXTENSIONS, 1 };
+CONST_OID x509SubjectInfoAccess[] = { PKIX_CERT_EXTENSIONS, 11 };
+
+CONST_OID x509SIATimeStamping[] = { PKIX_ACCESS_DESCRIPTION, 0x03 };
+CONST_OID x509SIACaRepository[] = { PKIX_ACCESS_DESCRIPTION, 0x05 };
+
+/* pkcs 12 additions */
+CONST_OID pkcs12[] = { PKCS12 };
+CONST_OID pkcs12ModeIDs[] = { PKCS12_MODE_IDS };
+CONST_OID pkcs12ESPVKIDs[] = { PKCS12_ESPVK_IDS };
+CONST_OID pkcs12BagIDs[] = { PKCS12_BAG_IDS };
+CONST_OID pkcs12CertBagIDs[] = { PKCS12_CERT_BAG_IDS };
+CONST_OID pkcs12OIDs[] = { PKCS12_OIDS };
+CONST_OID pkcs12PBEIDs[] = { PKCS12_PBE_IDS };
+CONST_OID pkcs12EnvelopingIDs[] = { PKCS12_ENVELOPING_IDS };
+CONST_OID pkcs12SignatureIDs[] = { PKCS12_SIGNATURE_IDS };
+CONST_OID pkcs12PKCS8KeyShrouding[] = { PKCS12_ESPVK_IDS, 0x01 };
+CONST_OID pkcs12KeyBagID[] = { PKCS12_BAG_IDS, 0x01 };
+CONST_OID pkcs12CertAndCRLBagID[] = { PKCS12_BAG_IDS, 0x02 };
+CONST_OID pkcs12SecretBagID[] = { PKCS12_BAG_IDS, 0x03 };
+CONST_OID pkcs12X509CertCRLBag[] = { PKCS12_CERT_BAG_IDS, 0x01 };
+CONST_OID pkcs12SDSICertBag[] = { PKCS12_CERT_BAG_IDS, 0x02 };
+CONST_OID pkcs12PBEWithSha1And128BitRC4[] = { PKCS12_PBE_IDS, 0x01 };
+CONST_OID pkcs12PBEWithSha1And40BitRC4[] = { PKCS12_PBE_IDS, 0x02 };
+CONST_OID pkcs12PBEWithSha1AndTripleDESCBC[] = { PKCS12_PBE_IDS, 0x03 };
+CONST_OID pkcs12PBEWithSha1And128BitRC2CBC[] = { PKCS12_PBE_IDS, 0x04 };
+CONST_OID pkcs12PBEWithSha1And40BitRC2CBC[] = { PKCS12_PBE_IDS, 0x05 };
+CONST_OID pkcs12RSAEncryptionWith128BitRC4[] = { PKCS12_ENVELOPING_IDS, 0x01 };
+CONST_OID pkcs12RSAEncryptionWith40BitRC4[] = { PKCS12_ENVELOPING_IDS, 0x02 };
+CONST_OID pkcs12RSAEncryptionWithTripleDES[] = { PKCS12_ENVELOPING_IDS, 0x03 };
+CONST_OID pkcs12RSASignatureWithSHA1Digest[] = { PKCS12_SIGNATURE_IDS, 0x01 };
+
+/* pkcs 12 version 1.0 ids */
+CONST_OID pkcs12V2PBEWithSha1And128BitRC4[] = { PKCS12_V2_PBE_IDS, 0x01 };
+CONST_OID pkcs12V2PBEWithSha1And40BitRC4[] = { PKCS12_V2_PBE_IDS, 0x02 };
+CONST_OID pkcs12V2PBEWithSha1And3KeyTripleDEScbc[] = { PKCS12_V2_PBE_IDS, 0x03 };
+CONST_OID pkcs12V2PBEWithSha1And2KeyTripleDEScbc[] = { PKCS12_V2_PBE_IDS, 0x04 };
+CONST_OID pkcs12V2PBEWithSha1And128BitRC2cbc[] = { PKCS12_V2_PBE_IDS, 0x05 };
+CONST_OID pkcs12V2PBEWithSha1And40BitRC2cbc[] = { PKCS12_V2_PBE_IDS, 0x06 };
+
+CONST_OID pkcs12SafeContentsID[] = { PKCS12_BAG_IDS, 0x04 };
+CONST_OID pkcs12PKCS8ShroudedKeyBagID[] = { PKCS12_BAG_IDS, 0x05 };
+
+CONST_OID pkcs12V1KeyBag[] = { PKCS12_V1_BAG_IDS, 0x01 };
+CONST_OID pkcs12V1PKCS8ShroudedKeyBag[] = { PKCS12_V1_BAG_IDS, 0x02 };
+CONST_OID pkcs12V1CertBag[] = { PKCS12_V1_BAG_IDS, 0x03 };
+CONST_OID pkcs12V1CRLBag[] = { PKCS12_V1_BAG_IDS, 0x04 };
+CONST_OID pkcs12V1SecretBag[] = { PKCS12_V1_BAG_IDS, 0x05 };
+CONST_OID pkcs12V1SafeContentsBag[] = { PKCS12_V1_BAG_IDS, 0x06 };
+
+/* The following encoding is INCORRECT, but correcting it would create a
+ * duplicate OID in the table. So, we will leave it alone.
+ */
+CONST_OID pkcs12KeyUsageAttr[] = { 2, 5, 29, 15 };
+
+CONST_OID ansix9DSASignature[] = { ANSI_X9_ALGORITHM, 0x01 };
+CONST_OID ansix9DSASignaturewithSHA1Digest[] = { ANSI_X9_ALGORITHM, 0x03 };
+CONST_OID nistDSASignaturewithSHA224Digest[] = { DSA2, 0x01 };
+CONST_OID nistDSASignaturewithSHA256Digest[] = { DSA2, 0x02 };
+
+/* verisign OIDs */
+CONST_OID verisignUserNotices[] = { VERISIGN, 1, 7, 1, 1 };
+
+/* pkix OIDs */
+CONST_OID pkixCPSPointerQualifier[] = { PKIX_POLICY_QUALIFIERS, 1 };
+CONST_OID pkixUserNoticeQualifier[] = { PKIX_POLICY_QUALIFIERS, 2 };
+
+CONST_OID pkixOCSP[] = { PKIX_OCSP };
+CONST_OID pkixOCSPBasicResponse[] = { PKIX_OCSP, 1 };
+CONST_OID pkixOCSPNonce[] = { PKIX_OCSP, 2 };
+CONST_OID pkixOCSPCRL[] = { PKIX_OCSP, 3 };
+CONST_OID pkixOCSPResponse[] = { PKIX_OCSP, 4 };
+CONST_OID pkixOCSPNoCheck[] = { PKIX_OCSP, 5 };
+CONST_OID pkixOCSPArchiveCutoff[] = { PKIX_OCSP, 6 };
+CONST_OID pkixOCSPServiceLocator[] = { PKIX_OCSP, 7 };
+
+CONST_OID pkixCAIssuers[] = { PKIX_CA_ISSUERS };
+
+CONST_OID pkixRegCtrlRegToken[] = { PKIX_ID_REGCTRL, 1 };
+CONST_OID pkixRegCtrlAuthenticator[] = { PKIX_ID_REGCTRL, 2 };
+CONST_OID pkixRegCtrlPKIPubInfo[] = { PKIX_ID_REGCTRL, 3 };
+CONST_OID pkixRegCtrlPKIArchOptions[] = { PKIX_ID_REGCTRL, 4 };
+CONST_OID pkixRegCtrlOldCertID[] = { PKIX_ID_REGCTRL, 5 };
+CONST_OID pkixRegCtrlProtEncKey[] = { PKIX_ID_REGCTRL, 6 };
+CONST_OID pkixRegInfoUTF8Pairs[] = { PKIX_ID_REGINFO, 1 };
+CONST_OID pkixRegInfoCertReq[] = { PKIX_ID_REGINFO, 2 };
+
+CONST_OID pkixExtendedKeyUsageServerAuth[] = { PKIX_KEY_USAGE, 1 };
+CONST_OID pkixExtendedKeyUsageClientAuth[] = { PKIX_KEY_USAGE, 2 };
+CONST_OID pkixExtendedKeyUsageCodeSign[] = { PKIX_KEY_USAGE, 3 };
+CONST_OID pkixExtendedKeyUsageEMailProtect[] = { PKIX_KEY_USAGE, 4 };
+/* IPsecEnd, IPsecTunnel, and IPsecUser are deprecated, but still in use
+ * (see RFC4945) */
+CONST_OID pkixExtendedKeyUsageIPsecEnd[] = { PKIX_KEY_USAGE, 5 };
+CONST_OID pkixExtendedKeyUsageIPsecTunnel[] = { PKIX_KEY_USAGE, 6 };
+CONST_OID pkixExtendedKeyUsageIPsecUser[] = { PKIX_KEY_USAGE, 7 };
+CONST_OID pkixExtendedKeyUsageTimeStamp[] = { PKIX_KEY_USAGE, 8 };
+CONST_OID pkixOCSPResponderExtendedKeyUsage[] = { PKIX_KEY_USAGE, 9 };
+/* 17 replaces 5 + 6 + 7 (declared obsolete in RFC 4945) */
+CONST_OID pkixExtendedKeyUsageIPsecIKE[] = { PKIX_KEY_USAGE, 17 };
+CONST_OID msExtendedKeyUsageTrustListSigning[] = { MS_CRYPTO_EKU, 1 };
+
+CONST_OID ipsecIKEEnd[] = { INTERNET_SECURITY_MECH, 0x08, 0x02, 0x01 };
+CONST_OID ipsecIKEIntermediate[] = { INTERNET_SECURITY_MECH, 0x08, 0x02, 0x02 };
+
+/* OIDs for Netscape defined algorithms */
+CONST_OID netscapeSMimeKEA[] = { NETSCAPE_ALGS, 0x01 };
+
+/* Fortezza algorithm OIDs */
+CONST_OID skipjackCBC[] = { MISSI, 0x04 };
+CONST_OID dhPublicKey[] = { ANSI_X942_ALGORITHM, 0x1 };
+
+CONST_OID idea_CBC[] = { ASCOM_IDEA_ALG, 2 };
+CONST_OID aes128_GCM[] = { AES, 0x6 };
+CONST_OID aes192_GCM[] = { AES, 0x1a };
+CONST_OID aes256_GCM[] = { AES, 0x2e };
+CONST_OID aes128_ECB[] = { AES, 1 };
+CONST_OID aes128_CBC[] = { AES, 2 };
+#ifdef DEFINE_ALL_AES_CIPHERS
+CONST_OID aes128_OFB[] = { AES, 3 };
+CONST_OID aes128_CFB[] = { AES, 4 };
+#endif
+CONST_OID aes128_KEY_WRAP[] = { AES, 5 };
+
+CONST_OID aes192_ECB[] = { AES, 21 };
+CONST_OID aes192_CBC[] = { AES, 22 };
+#ifdef DEFINE_ALL_AES_CIPHERS
+CONST_OID aes192_OFB[] = { AES, 23 };
+CONST_OID aes192_CFB[] = { AES, 24 };
+#endif
+CONST_OID aes192_KEY_WRAP[] = { AES, 25 };
+
+CONST_OID aes256_ECB[] = { AES, 41 };
+CONST_OID aes256_CBC[] = { AES, 42 };
+#ifdef DEFINE_ALL_AES_CIPHERS
+CONST_OID aes256_OFB[] = { AES, 43 };
+CONST_OID aes256_CFB[] = { AES, 44 };
+#endif
+CONST_OID aes256_KEY_WRAP[] = { AES, 45 };
+
+CONST_OID camellia128_CBC[] = { CAMELLIA_ENCRYPT_OID, 2 };
+CONST_OID camellia192_CBC[] = { CAMELLIA_ENCRYPT_OID, 3 };
+CONST_OID camellia256_CBC[] = { CAMELLIA_ENCRYPT_OID, 4 };
+
+CONST_OID sha256[] = { SHAXXX, 1 };
+CONST_OID sha384[] = { SHAXXX, 2 };
+CONST_OID sha512[] = { SHAXXX, 3 };
+CONST_OID sha224[] = { SHAXXX, 4 };
+
+CONST_OID sha3_224[] = { SHAXXX, 7 };
+CONST_OID sha3_256[] = { SHAXXX, 8 };
+CONST_OID sha3_384[] = { SHAXXX, 9 };
+CONST_OID sha3_512[] = { SHAXXX, 10 };
+
+CONST_OID hmac_sha3_224[] = { SHAXXX, 13 };
+CONST_OID hmac_sha3_256[] = { SHAXXX, 14 };
+CONST_OID hmac_sha3_384[] = { SHAXXX, 15 };
+CONST_OID hmac_sha3_512[] = { SHAXXX, 16 };
+
+CONST_OID ansix962ECPublicKey[] = { ANSI_X962_OID, 0x02, 0x01 };
+CONST_OID ansix962SignaturewithSHA1Digest[] = { ANSI_X962_SIGNATURE_OID, 0x01 };
+CONST_OID ansix962SignatureRecommended[] = { ANSI_X962_SIGNATURE_OID, 0x02 };
+CONST_OID ansix962SignatureSpecified[] = { ANSI_X962_SPECIFY_OID };
+CONST_OID ansix962SignaturewithSHA224Digest[] = { ANSI_X962_SPECIFY_OID, 0x01 };
+CONST_OID ansix962SignaturewithSHA256Digest[] = { ANSI_X962_SPECIFY_OID, 0x02 };
+CONST_OID ansix962SignaturewithSHA384Digest[] = { ANSI_X962_SPECIFY_OID, 0x03 };
+CONST_OID ansix962SignaturewithSHA512Digest[] = { ANSI_X962_SPECIFY_OID, 0x04 };
+
+/* ANSI X9.62 prime curve OIDs */
+/* NOTE: prime192v1 is the same as secp192r1, prime256v1 is the
+ * same as secp256r1
+ */
+CONST_OID ansiX962prime192v1[] = { ANSI_X962_GFp_OID, 0x01 }; /* unsupported by freebl */
+CONST_OID ansiX962prime192v2[] = { ANSI_X962_GFp_OID, 0x02 }; /* unsupported by freebl */
+CONST_OID ansiX962prime192v3[] = { ANSI_X962_GFp_OID, 0x03 }; /* unsupported by freebl */
+CONST_OID ansiX962prime239v1[] = { ANSI_X962_GFp_OID, 0x04 }; /* unsupported by freebl */
+CONST_OID ansiX962prime239v2[] = { ANSI_X962_GFp_OID, 0x05 }; /* unsupported by freebl */
+CONST_OID ansiX962prime239v3[] = { ANSI_X962_GFp_OID, 0x06 }; /* unsupported by freebl */
+CONST_OID ansiX962prime256v1[] = { ANSI_X962_GFp_OID, 0x07 };
+
+/* SECG prime curve OIDs */
+CONST_OID secgECsecp112r1[] = { SECG_OID, 0x06 }; /* unsupported by freebl */
+CONST_OID secgECsecp112r2[] = { SECG_OID, 0x07 }; /* unsupported by freebl */
+CONST_OID secgECsecp128r1[] = { SECG_OID, 0x1c }; /* unsupported by freebl */
+CONST_OID secgECsecp128r2[] = { SECG_OID, 0x1d }; /* unsupported by freebl */
+CONST_OID secgECsecp160k1[] = { SECG_OID, 0x09 }; /* unsupported by freebl */
+CONST_OID secgECsecp160r1[] = { SECG_OID, 0x08 }; /* unsupported by freebl */
+CONST_OID secgECsecp160r2[] = { SECG_OID, 0x1e }; /* unsupported by freebl */
+CONST_OID secgECsecp192k1[] = { SECG_OID, 0x1f }; /* unsupported by freebl */
+CONST_OID secgECsecp224k1[] = { SECG_OID, 0x20 }; /* unsupported by freebl */
+CONST_OID secgECsecp224r1[] = { SECG_OID, 0x21 }; /* unsupported by freebl */
+CONST_OID secgECsecp256k1[] = { SECG_OID, 0x0a }; /* unsupported by freebl */
+CONST_OID secgECsecp384r1[] = { SECG_OID, 0x22 };
+CONST_OID secgECsecp521r1[] = { SECG_OID, 0x23 };
+
+/* ANSI X9.62 characteristic two curve OIDs */
+CONST_OID ansiX962c2pnb163v1[] = { ANSI_X962_GF2m_OID, 0x01 }; /* unsupported by freebl */
+CONST_OID ansiX962c2pnb163v2[] = { ANSI_X962_GF2m_OID, 0x02 }; /* unsupported by freebl */
+CONST_OID ansiX962c2pnb163v3[] = { ANSI_X962_GF2m_OID, 0x03 }; /* unsupported by freebl */
+CONST_OID ansiX962c2pnb176v1[] = { ANSI_X962_GF2m_OID, 0x04 }; /* unsupported by freebl */
+CONST_OID ansiX962c2tnb191v1[] = { ANSI_X962_GF2m_OID, 0x05 }; /* unsupported by freebl */
+CONST_OID ansiX962c2tnb191v2[] = { ANSI_X962_GF2m_OID, 0x06 }; /* unsupported by freebl */
+CONST_OID ansiX962c2tnb191v3[] = { ANSI_X962_GF2m_OID, 0x07 }; /* unsupported by freebl */
+CONST_OID ansiX962c2onb191v4[] = { ANSI_X962_GF2m_OID, 0x08 }; /* unsupported by freebl */
+CONST_OID ansiX962c2onb191v5[] = { ANSI_X962_GF2m_OID, 0x09 }; /* unsupported by freebl */
+CONST_OID ansiX962c2pnb208w1[] = { ANSI_X962_GF2m_OID, 0x0a }; /* unsupported by freebl */
+CONST_OID ansiX962c2tnb239v1[] = { ANSI_X962_GF2m_OID, 0x0b }; /* unsupported by freebl */
+CONST_OID ansiX962c2tnb239v2[] = { ANSI_X962_GF2m_OID, 0x0c }; /* unsupported by freebl */
+CONST_OID ansiX962c2tnb239v3[] = { ANSI_X962_GF2m_OID, 0x0d }; /* unsupported by freebl */
+CONST_OID ansiX962c2onb239v4[] = { ANSI_X962_GF2m_OID, 0x0e }; /* unsupported by freebl */
+CONST_OID ansiX962c2onb239v5[] = { ANSI_X962_GF2m_OID, 0x0f }; /* unsupported by freebl */
+CONST_OID ansiX962c2pnb272w1[] = { ANSI_X962_GF2m_OID, 0x10 }; /* unsupported by freebl */
+CONST_OID ansiX962c2pnb304w1[] = { ANSI_X962_GF2m_OID, 0x11 }; /* unsupported by freebl */
+CONST_OID ansiX962c2tnb359v1[] = { ANSI_X962_GF2m_OID, 0x12 }; /* unsupported by freebl */
+CONST_OID ansiX962c2pnb368w1[] = { ANSI_X962_GF2m_OID, 0x13 }; /* unsupported by freebl */
+CONST_OID ansiX962c2tnb431r1[] = { ANSI_X962_GF2m_OID, 0x14 }; /* unsupported by freebl */
+
+/* SECG characterisitic two curve OIDs */
+CONST_OID secgECsect113r1[] = { SECG_OID, 0x04 }; /* unsupported by freebl */
+CONST_OID secgECsect113r2[] = { SECG_OID, 0x05 }; /* unsupported by freebl */
+CONST_OID secgECsect131r1[] = { SECG_OID, 0x16 }; /* unsupported by freebl */
+CONST_OID secgECsect131r2[] = { SECG_OID, 0x17 }; /* unsupported by freebl */
+CONST_OID secgECsect163k1[] = { SECG_OID, 0x01 }; /* unsupported by freebl */
+CONST_OID secgECsect163r1[] = { SECG_OID, 0x02 }; /* unsupported by freebl */
+CONST_OID secgECsect163r2[] = { SECG_OID, 0x0f }; /* unsupported by freebl */
+CONST_OID secgECsect193r1[] = { SECG_OID, 0x18 }; /* unsupported by freebl */
+CONST_OID secgECsect193r2[] = { SECG_OID, 0x19 }; /* unsupported by freebl */
+CONST_OID secgECsect233k1[] = { SECG_OID, 0x1a }; /* unsupported by freebl */
+CONST_OID secgECsect233r1[] = { SECG_OID, 0x1b }; /* unsupported by freebl */
+CONST_OID secgECsect239k1[] = { SECG_OID, 0x03 }; /* unsupported by freebl */
+CONST_OID secgECsect283k1[] = { SECG_OID, 0x10 }; /* unsupported by freebl */
+CONST_OID secgECsect283r1[] = { SECG_OID, 0x11 }; /* unsupported by freebl */
+CONST_OID secgECsect409k1[] = { SECG_OID, 0x24 }; /* unsupported by freebl */
+CONST_OID secgECsect409r1[] = { SECG_OID, 0x25 }; /* unsupported by freebl */
+CONST_OID secgECsect571k1[] = { SECG_OID, 0x26 }; /* unsupported by freebl */
+CONST_OID secgECsect571r1[] = { SECG_OID, 0x27 }; /* unsupported by freebl */
+
+CONST_OID seed_CBC[] = { SEED_OID, 4 };
+
+CONST_OID evIncorporationLocality[] = { EV_NAME_ATTRIBUTE, 1 };
+CONST_OID evIncorporationState[] = { EV_NAME_ATTRIBUTE, 2 };
+CONST_OID evIncorporationCountry[] = { EV_NAME_ATTRIBUTE, 3 };
+
+/* https://tools.ietf.org/html/draft-josefsson-pkix-newcurves-01
+ * 1.3.6.1.4.1.11591.15.1
+ */
+CONST_OID curve25519[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01 };
+
+#define OI(x) \
+ { \
+ siDEROID, (unsigned char *)x, sizeof x \
+ }
+#ifndef SECOID_NO_STRINGS
+#define OD(oid, tag, desc, mech, ext) \
+ { \
+ OI(oid) \
+ , tag, desc, mech, ext \
+ }
+#define ODE(tag, desc, mech, ext) \
+ { \
+ { siDEROID, NULL, 0 }, tag, desc, mech, ext \
+ }
+#else
+#define OD(oid, tag, desc, mech, ext) \
+ { \
+ OI(oid) \
+ , tag, 0, mech, ext \
+ }
+#define ODE(tag, desc, mech, ext) \
+ { \
+ { siDEROID, NULL, 0 }, tag, 0, mech, ext \
+ }
+#endif
+
+#if defined(NSS_ALLOW_UNSUPPORTED_CRITICAL)
+#define FAKE_SUPPORTED_CERT_EXTENSION SUPPORTED_CERT_EXTENSION
+#else
+#define FAKE_SUPPORTED_CERT_EXTENSION UNSUPPORTED_CERT_EXTENSION
+#endif
+
+/*
+ * NOTE: the order of these entries must mach the SECOidTag enum in secoidt.h!
+ */
+const static SECOidData oids[SEC_OID_TOTAL] = {
+ { { siDEROID, NULL, 0 }, SEC_OID_UNKNOWN, "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+ OD(md2, SEC_OID_MD2, "MD2", CKM_MD2, INVALID_CERT_EXTENSION),
+ OD(md4, SEC_OID_MD4,
+ "MD4", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(md5, SEC_OID_MD5, "MD5", CKM_MD5, INVALID_CERT_EXTENSION),
+ OD(sha1, SEC_OID_SHA1, "SHA-1", CKM_SHA_1, INVALID_CERT_EXTENSION),
+ OD(rc2cbc, SEC_OID_RC2_CBC,
+ "RC2-CBC", CKM_RC2_CBC, INVALID_CERT_EXTENSION),
+ OD(rc4, SEC_OID_RC4, "RC4", CKM_RC4, INVALID_CERT_EXTENSION),
+ OD(desede3cbc, SEC_OID_DES_EDE3_CBC,
+ "DES-EDE3-CBC", CKM_DES3_CBC, INVALID_CERT_EXTENSION),
+ OD(rc5cbcpad, SEC_OID_RC5_CBC_PAD,
+ "RC5-CBCPad", CKM_RC5_CBC, INVALID_CERT_EXTENSION),
+ OD(desecb, SEC_OID_DES_ECB,
+ "DES-ECB", CKM_DES_ECB, INVALID_CERT_EXTENSION),
+ OD(descbc, SEC_OID_DES_CBC,
+ "DES-CBC", CKM_DES_CBC, INVALID_CERT_EXTENSION),
+ OD(desofb, SEC_OID_DES_OFB,
+ "DES-OFB", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(descfb, SEC_OID_DES_CFB,
+ "DES-CFB", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(desmac, SEC_OID_DES_MAC,
+ "DES-MAC", CKM_DES_MAC, INVALID_CERT_EXTENSION),
+ OD(desede, SEC_OID_DES_EDE,
+ "DES-EDE", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(isoSHAWithRSASignature, SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE,
+ "ISO SHA with RSA Signature",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs1RSAEncryption, SEC_OID_PKCS1_RSA_ENCRYPTION,
+ "PKCS #1 RSA Encryption", CKM_RSA_PKCS, INVALID_CERT_EXTENSION),
+
+ /* the following Signing mechanisms should get new CKM_ values when
+ * values for CKM_RSA_WITH_MDX and CKM_RSA_WITH_SHA_1 get defined in
+ * PKCS #11.
+ */
+ OD(pkcs1MD2WithRSAEncryption, SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION,
+ "PKCS #1 MD2 With RSA Encryption", CKM_MD2_RSA_PKCS,
+ INVALID_CERT_EXTENSION),
+ OD(pkcs1MD4WithRSAEncryption, SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION,
+ "PKCS #1 MD4 With RSA Encryption",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs1MD5WithRSAEncryption, SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
+ "PKCS #1 MD5 With RSA Encryption", CKM_MD5_RSA_PKCS,
+ INVALID_CERT_EXTENSION),
+ OD(pkcs1SHA1WithRSAEncryption, SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION,
+ "PKCS #1 SHA-1 With RSA Encryption", CKM_SHA1_RSA_PKCS,
+ INVALID_CERT_EXTENSION),
+
+ OD(pkcs5PbeWithMD2AndDEScbc, SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC,
+ "PKCS #5 Password Based Encryption with MD2 and DES-CBC",
+ CKM_PBE_MD2_DES_CBC, INVALID_CERT_EXTENSION),
+ OD(pkcs5PbeWithMD5AndDEScbc, SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC,
+ "PKCS #5 Password Based Encryption with MD5 and DES-CBC",
+ CKM_PBE_MD5_DES_CBC, INVALID_CERT_EXTENSION),
+ OD(pkcs5PbeWithSha1AndDEScbc, SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC,
+ "PKCS #5 Password Based Encryption with SHA-1 and DES-CBC",
+ CKM_NSS_PBE_SHA1_DES_CBC, INVALID_CERT_EXTENSION),
+ OD(pkcs7, SEC_OID_PKCS7,
+ "PKCS #7", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs7Data, SEC_OID_PKCS7_DATA,
+ "PKCS #7 Data", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs7SignedData, SEC_OID_PKCS7_SIGNED_DATA,
+ "PKCS #7 Signed Data", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs7EnvelopedData, SEC_OID_PKCS7_ENVELOPED_DATA,
+ "PKCS #7 Enveloped Data",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs7SignedEnvelopedData, SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA,
+ "PKCS #7 Signed And Enveloped Data",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs7DigestedData, SEC_OID_PKCS7_DIGESTED_DATA,
+ "PKCS #7 Digested Data",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs7EncryptedData, SEC_OID_PKCS7_ENCRYPTED_DATA,
+ "PKCS #7 Encrypted Data",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9EmailAddress, SEC_OID_PKCS9_EMAIL_ADDRESS,
+ "PKCS #9 Email Address",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9UnstructuredName, SEC_OID_PKCS9_UNSTRUCTURED_NAME,
+ "PKCS #9 Unstructured Name",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9ContentType, SEC_OID_PKCS9_CONTENT_TYPE,
+ "PKCS #9 Content Type",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9MessageDigest, SEC_OID_PKCS9_MESSAGE_DIGEST,
+ "PKCS #9 Message Digest",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9SigningTime, SEC_OID_PKCS9_SIGNING_TIME,
+ "PKCS #9 Signing Time",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9CounterSignature, SEC_OID_PKCS9_COUNTER_SIGNATURE,
+ "PKCS #9 Counter Signature",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9ChallengePassword, SEC_OID_PKCS9_CHALLENGE_PASSWORD,
+ "PKCS #9 Challenge Password",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9UnstructuredAddress, SEC_OID_PKCS9_UNSTRUCTURED_ADDRESS,
+ "PKCS #9 Unstructured Address",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9ExtendedCertificateAttributes,
+ SEC_OID_PKCS9_EXTENDED_CERTIFICATE_ATTRIBUTES,
+ "PKCS #9 Extended Certificate Attributes",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9SMIMECapabilities, SEC_OID_PKCS9_SMIME_CAPABILITIES,
+ "PKCS #9 S/MIME Capabilities",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520CommonName, SEC_OID_AVA_COMMON_NAME,
+ "X520 Common Name", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520CountryName, SEC_OID_AVA_COUNTRY_NAME,
+ "X520 Country Name", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520LocalityName, SEC_OID_AVA_LOCALITY,
+ "X520 Locality Name", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520StateOrProvinceName, SEC_OID_AVA_STATE_OR_PROVINCE,
+ "X520 State Or Province Name",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520OrgName, SEC_OID_AVA_ORGANIZATION_NAME,
+ "X520 Organization Name",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520OrgUnitName, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME,
+ "X520 Organizational Unit Name",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520DnQualifier, SEC_OID_AVA_DN_QUALIFIER,
+ "X520 DN Qualifier", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(rfc2247DomainComponent, SEC_OID_AVA_DC,
+ "RFC 2247 Domain Component",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ OD(nsTypeGIF, SEC_OID_NS_TYPE_GIF,
+ "GIF", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(nsTypeJPEG, SEC_OID_NS_TYPE_JPEG,
+ "JPEG", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(nsTypeURL, SEC_OID_NS_TYPE_URL,
+ "URL", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(nsTypeHTML, SEC_OID_NS_TYPE_HTML,
+ "HTML", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(nsTypeCertSeq, SEC_OID_NS_TYPE_CERT_SEQUENCE,
+ "Certificate Sequence",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(missiCertKEADSSOld, SEC_OID_MISSI_KEA_DSS_OLD,
+ "MISSI KEA and DSS Algorithm (Old)",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(missiCertDSSOld, SEC_OID_MISSI_DSS_OLD,
+ "MISSI DSS Algorithm (Old)",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(missiCertKEADSS, SEC_OID_MISSI_KEA_DSS,
+ "MISSI KEA and DSS Algorithm",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(missiCertDSS, SEC_OID_MISSI_DSS,
+ "MISSI DSS Algorithm",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(missiCertKEA, SEC_OID_MISSI_KEA,
+ "MISSI KEA Algorithm",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(missiCertAltKEA, SEC_OID_MISSI_ALT_KEA,
+ "MISSI Alternate KEA Algorithm",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ /* Netscape private extensions */
+ OD(nsCertExtNetscapeOK, SEC_OID_NS_CERT_EXT_NETSCAPE_OK,
+ "Netscape says this cert is OK",
+ CKM_INVALID_MECHANISM, UNSUPPORTED_CERT_EXTENSION),
+ OD(nsCertExtIssuerLogo, SEC_OID_NS_CERT_EXT_ISSUER_LOGO,
+ "Certificate Issuer Logo",
+ CKM_INVALID_MECHANISM, UNSUPPORTED_CERT_EXTENSION),
+ OD(nsCertExtSubjectLogo, SEC_OID_NS_CERT_EXT_SUBJECT_LOGO,
+ "Certificate Subject Logo",
+ CKM_INVALID_MECHANISM, UNSUPPORTED_CERT_EXTENSION),
+ OD(nsExtCertType, SEC_OID_NS_CERT_EXT_CERT_TYPE,
+ "Certificate Type",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(nsExtBaseURL, SEC_OID_NS_CERT_EXT_BASE_URL,
+ "Certificate Extension Base URL",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(nsExtRevocationURL, SEC_OID_NS_CERT_EXT_REVOCATION_URL,
+ "Certificate Revocation URL",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(nsExtCARevocationURL, SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL,
+ "Certificate Authority Revocation URL",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(nsExtCACRLURL, SEC_OID_NS_CERT_EXT_CA_CRL_URL,
+ "Certificate Authority CRL Download URL",
+ CKM_INVALID_MECHANISM, UNSUPPORTED_CERT_EXTENSION),
+ OD(nsExtCACertURL, SEC_OID_NS_CERT_EXT_CA_CERT_URL,
+ "Certificate Authority Certificate Download URL",
+ CKM_INVALID_MECHANISM, UNSUPPORTED_CERT_EXTENSION),
+ OD(nsExtCertRenewalURL, SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL,
+ "Certificate Renewal URL",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(nsExtCAPolicyURL, SEC_OID_NS_CERT_EXT_CA_POLICY_URL,
+ "Certificate Authority Policy URL",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(nsExtHomepageURL, SEC_OID_NS_CERT_EXT_HOMEPAGE_URL,
+ "Certificate Homepage URL",
+ CKM_INVALID_MECHANISM, UNSUPPORTED_CERT_EXTENSION),
+ OD(nsExtEntityLogo, SEC_OID_NS_CERT_EXT_ENTITY_LOGO,
+ "Certificate Entity Logo",
+ CKM_INVALID_MECHANISM, UNSUPPORTED_CERT_EXTENSION),
+ OD(nsExtUserPicture, SEC_OID_NS_CERT_EXT_USER_PICTURE,
+ "Certificate User Picture",
+ CKM_INVALID_MECHANISM, UNSUPPORTED_CERT_EXTENSION),
+ OD(nsExtSSLServerName, SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME,
+ "Certificate SSL Server Name",
+ CKM_INVALID_MECHANISM, UNSUPPORTED_CERT_EXTENSION),
+ OD(nsExtComment, SEC_OID_NS_CERT_EXT_COMMENT,
+ "Certificate Comment",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(nsExtLostPasswordURL, SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL,
+ "Lost Password URL",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(nsExtCertRenewalTime, SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME,
+ "Certificate Renewal Time",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(nsKeyUsageGovtApproved, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED,
+ "Strong Crypto Export Approved",
+ CKM_INVALID_MECHANISM, UNSUPPORTED_CERT_EXTENSION),
+
+ /* x.509 v3 certificate extensions */
+ OD(x509SubjectDirectoryAttr, SEC_OID_X509_SUBJECT_DIRECTORY_ATTR,
+ "Certificate Subject Directory Attributes",
+ CKM_INVALID_MECHANISM, UNSUPPORTED_CERT_EXTENSION),
+ OD(x509SubjectKeyID, SEC_OID_X509_SUBJECT_KEY_ID,
+ "Certificate Subject Key ID",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(x509KeyUsage, SEC_OID_X509_KEY_USAGE,
+ "Certificate Key Usage",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(x509PrivateKeyUsagePeriod, SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD,
+ "Certificate Private Key Usage Period",
+ CKM_INVALID_MECHANISM, UNSUPPORTED_CERT_EXTENSION),
+ OD(x509SubjectAltName, SEC_OID_X509_SUBJECT_ALT_NAME,
+ "Certificate Subject Alt Name",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(x509IssuerAltName, SEC_OID_X509_ISSUER_ALT_NAME,
+ "Certificate Issuer Alt Name",
+ CKM_INVALID_MECHANISM, FAKE_SUPPORTED_CERT_EXTENSION),
+ OD(x509BasicConstraints, SEC_OID_X509_BASIC_CONSTRAINTS,
+ "Certificate Basic Constraints",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(x509NameConstraints, SEC_OID_X509_NAME_CONSTRAINTS,
+ "Certificate Name Constraints",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(x509CRLDistPoints, SEC_OID_X509_CRL_DIST_POINTS,
+ "CRL Distribution Points",
+ CKM_INVALID_MECHANISM, FAKE_SUPPORTED_CERT_EXTENSION),
+ OD(x509CertificatePolicies, SEC_OID_X509_CERTIFICATE_POLICIES,
+ "Certificate Policies",
+ CKM_INVALID_MECHANISM, FAKE_SUPPORTED_CERT_EXTENSION),
+ OD(x509PolicyMappings, SEC_OID_X509_POLICY_MAPPINGS,
+ "Certificate Policy Mappings",
+ CKM_INVALID_MECHANISM, UNSUPPORTED_CERT_EXTENSION),
+ OD(x509PolicyConstraints, SEC_OID_X509_POLICY_CONSTRAINTS,
+ "Certificate Policy Constraints",
+ CKM_INVALID_MECHANISM, FAKE_SUPPORTED_CERT_EXTENSION),
+ OD(x509AuthKeyID, SEC_OID_X509_AUTH_KEY_ID,
+ "Certificate Authority Key Identifier",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(x509ExtKeyUsage, SEC_OID_X509_EXT_KEY_USAGE,
+ "Extended Key Usage",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(x509AuthInfoAccess, SEC_OID_X509_AUTH_INFO_ACCESS,
+ "Authority Information Access",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+
+ /* x.509 v3 CRL extensions */
+ OD(x509CRLNumber, SEC_OID_X509_CRL_NUMBER,
+ "CRL Number", CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(x509ReasonCode, SEC_OID_X509_REASON_CODE,
+ "CRL reason code", CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(x509InvalidDate, SEC_OID_X509_INVALID_DATE,
+ "Invalid Date", CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+
+ OD(x500RSAEncryption, SEC_OID_X500_RSA_ENCRYPTION,
+ "X500 RSA Encryption", CKM_RSA_X_509, INVALID_CERT_EXTENSION),
+
+ /* added for alg 1485 */
+ OD(rfc1274Uid, SEC_OID_RFC1274_UID,
+ "RFC1274 User Id", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(rfc1274Mail, SEC_OID_RFC1274_MAIL,
+ "RFC1274 E-mail Address",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ /* pkcs 12 additions */
+ OD(pkcs12, SEC_OID_PKCS12,
+ "PKCS #12", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12ModeIDs, SEC_OID_PKCS12_MODE_IDS,
+ "PKCS #12 Mode IDs", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12ESPVKIDs, SEC_OID_PKCS12_ESPVK_IDS,
+ "PKCS #12 ESPVK IDs", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12BagIDs, SEC_OID_PKCS12_BAG_IDS,
+ "PKCS #12 Bag IDs", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12CertBagIDs, SEC_OID_PKCS12_CERT_BAG_IDS,
+ "PKCS #12 Cert Bag IDs",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12OIDs, SEC_OID_PKCS12_OIDS,
+ "PKCS #12 OIDs", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12PBEIDs, SEC_OID_PKCS12_PBE_IDS,
+ "PKCS #12 PBE IDs", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12SignatureIDs, SEC_OID_PKCS12_SIGNATURE_IDS,
+ "PKCS #12 Signature IDs",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12EnvelopingIDs, SEC_OID_PKCS12_ENVELOPING_IDS,
+ "PKCS #12 Enveloping IDs",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12PKCS8KeyShrouding, SEC_OID_PKCS12_PKCS8_KEY_SHROUDING,
+ "PKCS #12 Key Shrouding",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12KeyBagID, SEC_OID_PKCS12_KEY_BAG_ID,
+ "PKCS #12 Key Bag ID",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12CertAndCRLBagID, SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID,
+ "PKCS #12 Cert And CRL Bag ID",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12SecretBagID, SEC_OID_PKCS12_SECRET_BAG_ID,
+ "PKCS #12 Secret Bag ID",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12X509CertCRLBag, SEC_OID_PKCS12_X509_CERT_CRL_BAG,
+ "PKCS #12 X509 Cert CRL Bag",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12SDSICertBag, SEC_OID_PKCS12_SDSI_CERT_BAG,
+ "PKCS #12 SDSI Cert Bag",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12PBEWithSha1And128BitRC4,
+ SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4,
+ "PKCS #12 PBE With SHA-1 and 128 Bit RC4",
+ CKM_NSS_PBE_SHA1_128_BIT_RC4, INVALID_CERT_EXTENSION),
+ OD(pkcs12PBEWithSha1And40BitRC4,
+ SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4,
+ "PKCS #12 PBE With SHA-1 and 40 Bit RC4",
+ CKM_NSS_PBE_SHA1_40_BIT_RC4, INVALID_CERT_EXTENSION),
+ OD(pkcs12PBEWithSha1AndTripleDESCBC,
+ SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC,
+ "PKCS #12 PBE With SHA-1 and Triple DES-CBC",
+ CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC, INVALID_CERT_EXTENSION),
+ OD(pkcs12PBEWithSha1And128BitRC2CBC,
+ SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC,
+ "PKCS #12 PBE With SHA-1 and 128 Bit RC2 CBC",
+ CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC, INVALID_CERT_EXTENSION),
+ OD(pkcs12PBEWithSha1And40BitRC2CBC,
+ SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC,
+ "PKCS #12 PBE With SHA-1 and 40 Bit RC2 CBC",
+ CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC, INVALID_CERT_EXTENSION),
+ OD(pkcs12RSAEncryptionWith128BitRC4,
+ SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_128_BIT_RC4,
+ "PKCS #12 RSA Encryption with 128 Bit RC4",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12RSAEncryptionWith40BitRC4,
+ SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_40_BIT_RC4,
+ "PKCS #12 RSA Encryption with 40 Bit RC4",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12RSAEncryptionWithTripleDES,
+ SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_TRIPLE_DES,
+ "PKCS #12 RSA Encryption with Triple DES",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12RSASignatureWithSHA1Digest,
+ SEC_OID_PKCS12_RSA_SIGNATURE_WITH_SHA1_DIGEST,
+ "PKCS #12 RSA Encryption with Triple DES",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ /* DSA signatures */
+ OD(ansix9DSASignature, SEC_OID_ANSIX9_DSA_SIGNATURE,
+ "ANSI X9.57 DSA Signature", CKM_DSA, INVALID_CERT_EXTENSION),
+ OD(ansix9DSASignaturewithSHA1Digest,
+ SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST,
+ "ANSI X9.57 DSA Signature with SHA-1 Digest",
+ CKM_DSA_SHA1, INVALID_CERT_EXTENSION),
+ OD(bogusDSASignaturewithSHA1Digest,
+ SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST,
+ "FORTEZZA DSA Signature with SHA-1 Digest",
+ CKM_DSA_SHA1, INVALID_CERT_EXTENSION),
+
+ /* verisign oids */
+ OD(verisignUserNotices, SEC_OID_VERISIGN_USER_NOTICES,
+ "Verisign User Notices",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ /* pkix oids */
+ OD(pkixCPSPointerQualifier, SEC_OID_PKIX_CPS_POINTER_QUALIFIER,
+ "PKIX CPS Pointer Qualifier",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixUserNoticeQualifier, SEC_OID_PKIX_USER_NOTICE_QUALIFIER,
+ "PKIX User Notice Qualifier",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ OD(pkixOCSP, SEC_OID_PKIX_OCSP,
+ "PKIX Online Certificate Status Protocol",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixOCSPBasicResponse, SEC_OID_PKIX_OCSP_BASIC_RESPONSE,
+ "OCSP Basic Response", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixOCSPNonce, SEC_OID_PKIX_OCSP_NONCE,
+ "OCSP Nonce Extension", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixOCSPCRL, SEC_OID_PKIX_OCSP_CRL,
+ "OCSP CRL Reference Extension",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixOCSPResponse, SEC_OID_PKIX_OCSP_RESPONSE,
+ "OCSP Response Types Extension",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixOCSPNoCheck, SEC_OID_PKIX_OCSP_NO_CHECK,
+ "OCSP No Check Extension",
+ CKM_INVALID_MECHANISM, SUPPORTED_CERT_EXTENSION),
+ OD(pkixOCSPArchiveCutoff, SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF,
+ "OCSP Archive Cutoff Extension",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixOCSPServiceLocator, SEC_OID_PKIX_OCSP_SERVICE_LOCATOR,
+ "OCSP Service Locator Extension",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ OD(pkixRegCtrlRegToken, SEC_OID_PKIX_REGCTRL_REGTOKEN,
+ "PKIX CRMF Registration Control, Registration Token",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixRegCtrlAuthenticator, SEC_OID_PKIX_REGCTRL_AUTHENTICATOR,
+ "PKIX CRMF Registration Control, Registration Authenticator",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixRegCtrlPKIPubInfo, SEC_OID_PKIX_REGCTRL_PKIPUBINFO,
+ "PKIX CRMF Registration Control, PKI Publication Info",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixRegCtrlPKIArchOptions,
+ SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS,
+ "PKIX CRMF Registration Control, PKI Archive Options",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixRegCtrlOldCertID, SEC_OID_PKIX_REGCTRL_OLD_CERT_ID,
+ "PKIX CRMF Registration Control, Old Certificate ID",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixRegCtrlProtEncKey, SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY,
+ "PKIX CRMF Registration Control, Protocol Encryption Key",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixRegInfoUTF8Pairs, SEC_OID_PKIX_REGINFO_UTF8_PAIRS,
+ "PKIX CRMF Registration Info, UTF8 Pairs",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixRegInfoCertReq, SEC_OID_PKIX_REGINFO_CERT_REQUEST,
+ "PKIX CRMF Registration Info, Certificate Request",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixExtendedKeyUsageServerAuth,
+ SEC_OID_EXT_KEY_USAGE_SERVER_AUTH,
+ "TLS Web Server Authentication Certificate",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixExtendedKeyUsageClientAuth,
+ SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH,
+ "TLS Web Client Authentication Certificate",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixExtendedKeyUsageCodeSign, SEC_OID_EXT_KEY_USAGE_CODE_SIGN,
+ "Code Signing Certificate",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixExtendedKeyUsageEMailProtect,
+ SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT,
+ "E-Mail Protection Certificate",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixExtendedKeyUsageTimeStamp,
+ SEC_OID_EXT_KEY_USAGE_TIME_STAMP,
+ "Time Stamping Certifcate",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixOCSPResponderExtendedKeyUsage, SEC_OID_OCSP_RESPONDER,
+ "OCSP Responder Certificate",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ /* Netscape Algorithm OIDs */
+
+ OD(netscapeSMimeKEA, SEC_OID_NETSCAPE_SMIME_KEA,
+ "Netscape S/MIME KEA", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ /* Skipjack OID -- ### mwelch temporary */
+ OD(skipjackCBC, SEC_OID_FORTEZZA_SKIPJACK,
+ "Skipjack CBC64", CKM_SKIPJACK_CBC64, INVALID_CERT_EXTENSION),
+
+ /* pkcs12 v2 oids */
+ OD(pkcs12V2PBEWithSha1And128BitRC4,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4,
+ "PKCS #12 V2 PBE With SHA-1 And 128 Bit RC4",
+ CKM_PBE_SHA1_RC4_128, INVALID_CERT_EXTENSION),
+ OD(pkcs12V2PBEWithSha1And40BitRC4,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4,
+ "PKCS #12 V2 PBE With SHA-1 And 40 Bit RC4",
+ CKM_PBE_SHA1_RC4_40, INVALID_CERT_EXTENSION),
+ OD(pkcs12V2PBEWithSha1And3KeyTripleDEScbc,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC,
+ "PKCS #12 V2 PBE With SHA-1 And 3KEY Triple DES-CBC",
+ CKM_PBE_SHA1_DES3_EDE_CBC, INVALID_CERT_EXTENSION),
+ OD(pkcs12V2PBEWithSha1And2KeyTripleDEScbc,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC,
+ "PKCS #12 V2 PBE With SHA-1 And 2KEY Triple DES-CBC",
+ CKM_PBE_SHA1_DES2_EDE_CBC, INVALID_CERT_EXTENSION),
+ OD(pkcs12V2PBEWithSha1And128BitRC2cbc,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC,
+ "PKCS #12 V2 PBE With SHA-1 And 128 Bit RC2 CBC",
+ CKM_PBE_SHA1_RC2_128_CBC, INVALID_CERT_EXTENSION),
+ OD(pkcs12V2PBEWithSha1And40BitRC2cbc,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC,
+ "PKCS #12 V2 PBE With SHA-1 And 40 Bit RC2 CBC",
+ CKM_PBE_SHA1_RC2_40_CBC, INVALID_CERT_EXTENSION),
+ OD(pkcs12SafeContentsID, SEC_OID_PKCS12_SAFE_CONTENTS_ID,
+ "PKCS #12 Safe Contents ID",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12PKCS8ShroudedKeyBagID,
+ SEC_OID_PKCS12_PKCS8_SHROUDED_KEY_BAG_ID,
+ "PKCS #12 Safe Contents ID",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12V1KeyBag, SEC_OID_PKCS12_V1_KEY_BAG_ID,
+ "PKCS #12 V1 Key Bag",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12V1PKCS8ShroudedKeyBag,
+ SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID,
+ "PKCS #12 V1 PKCS8 Shrouded Key Bag",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12V1CertBag, SEC_OID_PKCS12_V1_CERT_BAG_ID,
+ "PKCS #12 V1 Cert Bag",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12V1CRLBag, SEC_OID_PKCS12_V1_CRL_BAG_ID,
+ "PKCS #12 V1 CRL Bag",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12V1SecretBag, SEC_OID_PKCS12_V1_SECRET_BAG_ID,
+ "PKCS #12 V1 Secret Bag",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12V1SafeContentsBag, SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID,
+ "PKCS #12 V1 Safe Contents Bag",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ OD(pkcs9X509Certificate, SEC_OID_PKCS9_X509_CERT,
+ "PKCS #9 X509 Certificate",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9SDSICertificate, SEC_OID_PKCS9_SDSI_CERT,
+ "PKCS #9 SDSI Certificate",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9X509CRL, SEC_OID_PKCS9_X509_CRL,
+ "PKCS #9 X509 CRL", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9FriendlyName, SEC_OID_PKCS9_FRIENDLY_NAME,
+ "PKCS #9 Friendly Name",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9LocalKeyID, SEC_OID_PKCS9_LOCAL_KEY_ID,
+ "PKCS #9 Local Key ID",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs12KeyUsageAttr, SEC_OID_BOGUS_KEY_USAGE,
+ "Bogus Key Usage", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(dhPublicKey, SEC_OID_X942_DIFFIE_HELMAN_KEY,
+ "Diffie-Helman Public Key", CKM_DH_PKCS_DERIVE,
+ INVALID_CERT_EXTENSION),
+ OD(netscapeNickname, SEC_OID_NETSCAPE_NICKNAME,
+ "Netscape Nickname", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ /* Cert Server specific OIDs */
+ OD(netscapeRecoveryRequest, SEC_OID_NETSCAPE_RECOVERY_REQUEST,
+ "Recovery Request OID",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ OD(nsExtAIACertRenewal, SEC_OID_CERT_RENEWAL_LOCATOR,
+ "Certificate Renewal Locator OID", CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+
+ OD(nsExtCertScopeOfUse, SEC_OID_NS_CERT_EXT_SCOPE_OF_USE,
+ "Certificate Scope-of-Use Extension", CKM_INVALID_MECHANISM,
+ SUPPORTED_CERT_EXTENSION),
+
+ /* CMS stuff */
+ OD(cmsESDH, SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN,
+ "Ephemeral-Static Diffie-Hellman", CKM_INVALID_MECHANISM /* XXX */,
+ INVALID_CERT_EXTENSION),
+ OD(cms3DESwrap, SEC_OID_CMS_3DES_KEY_WRAP,
+ "CMS Triple DES Key Wrap", CKM_INVALID_MECHANISM /* XXX */,
+ INVALID_CERT_EXTENSION),
+ OD(cmsRC2wrap, SEC_OID_CMS_RC2_KEY_WRAP,
+ "CMS RC2 Key Wrap", CKM_INVALID_MECHANISM /* XXX */,
+ INVALID_CERT_EXTENSION),
+ OD(smimeEncryptionKeyPreference, SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE,
+ "S/MIME Encryption Key Preference",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ /* AES algorithm OIDs */
+ OD(aes128_ECB, SEC_OID_AES_128_ECB,
+ "AES-128-ECB", CKM_AES_ECB, INVALID_CERT_EXTENSION),
+ OD(aes128_CBC, SEC_OID_AES_128_CBC,
+ "AES-128-CBC", CKM_AES_CBC, INVALID_CERT_EXTENSION),
+ OD(aes192_ECB, SEC_OID_AES_192_ECB,
+ "AES-192-ECB", CKM_AES_ECB, INVALID_CERT_EXTENSION),
+ OD(aes192_CBC, SEC_OID_AES_192_CBC,
+ "AES-192-CBC", CKM_AES_CBC, INVALID_CERT_EXTENSION),
+ OD(aes256_ECB, SEC_OID_AES_256_ECB,
+ "AES-256-ECB", CKM_AES_ECB, INVALID_CERT_EXTENSION),
+ OD(aes256_CBC, SEC_OID_AES_256_CBC,
+ "AES-256-CBC", CKM_AES_CBC, INVALID_CERT_EXTENSION),
+
+ /* More bogus DSA OIDs */
+ OD(sdn702DSASignature, SEC_OID_SDN702_DSA_SIGNATURE,
+ "SDN.702 DSA Signature", CKM_DSA_SHA1, INVALID_CERT_EXTENSION),
+
+ OD(ms_smimeEncryptionKeyPreference,
+ SEC_OID_MS_SMIME_ENCRYPTION_KEY_PREFERENCE,
+ "Microsoft S/MIME Encryption Key Preference",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ OD(sha256, SEC_OID_SHA256, "SHA-256", CKM_SHA256, INVALID_CERT_EXTENSION),
+ OD(sha384, SEC_OID_SHA384, "SHA-384", CKM_SHA384, INVALID_CERT_EXTENSION),
+ OD(sha512, SEC_OID_SHA512, "SHA-512", CKM_SHA512, INVALID_CERT_EXTENSION),
+
+ OD(pkcs1SHA256WithRSAEncryption, SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION,
+ "PKCS #1 SHA-256 With RSA Encryption", CKM_SHA256_RSA_PKCS,
+ INVALID_CERT_EXTENSION),
+ OD(pkcs1SHA384WithRSAEncryption, SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION,
+ "PKCS #1 SHA-384 With RSA Encryption", CKM_SHA384_RSA_PKCS,
+ INVALID_CERT_EXTENSION),
+ OD(pkcs1SHA512WithRSAEncryption, SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION,
+ "PKCS #1 SHA-512 With RSA Encryption", CKM_SHA512_RSA_PKCS,
+ INVALID_CERT_EXTENSION),
+
+ OD(aes128_KEY_WRAP, SEC_OID_AES_128_KEY_WRAP,
+ "AES-128 Key Wrap", CKM_NSS_AES_KEY_WRAP, INVALID_CERT_EXTENSION),
+ OD(aes192_KEY_WRAP, SEC_OID_AES_192_KEY_WRAP,
+ "AES-192 Key Wrap", CKM_NSS_AES_KEY_WRAP, INVALID_CERT_EXTENSION),
+ OD(aes256_KEY_WRAP, SEC_OID_AES_256_KEY_WRAP,
+ "AES-256 Key Wrap", CKM_NSS_AES_KEY_WRAP, INVALID_CERT_EXTENSION),
+
+ /* Elliptic Curve Cryptography (ECC) OIDs */
+ OD(ansix962ECPublicKey, SEC_OID_ANSIX962_EC_PUBLIC_KEY,
+ "X9.62 elliptic curve public key", CKM_ECDH1_DERIVE,
+ INVALID_CERT_EXTENSION),
+ OD(ansix962SignaturewithSHA1Digest,
+ SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE,
+ "X9.62 ECDSA signature with SHA-1", CKM_ECDSA_SHA1,
+ INVALID_CERT_EXTENSION),
+
+ /* Named curves */
+ /* NOTE: Only P256, P384, P521, and 25519 are supported by softoken.
+ * Using other curves requires an appropriate token. */
+
+ /* ANSI X9.62 named elliptic curves (prime field) */
+ OD(ansiX962prime192v1, SEC_OID_ANSIX962_EC_PRIME192V1,
+ "ANSI X9.62 elliptic curve prime192v1 (aka secp192r1, NIST P-192)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962prime192v2, SEC_OID_ANSIX962_EC_PRIME192V2,
+ "ANSI X9.62 elliptic curve prime192v2",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962prime192v3, SEC_OID_ANSIX962_EC_PRIME192V3,
+ "ANSI X9.62 elliptic curve prime192v3",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962prime239v1, SEC_OID_ANSIX962_EC_PRIME239V1,
+ "ANSI X9.62 elliptic curve prime239v1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962prime239v2, SEC_OID_ANSIX962_EC_PRIME239V2,
+ "ANSI X9.62 elliptic curve prime239v2",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962prime239v3, SEC_OID_ANSIX962_EC_PRIME239V3,
+ "ANSI X9.62 elliptic curve prime239v3",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962prime256v1, SEC_OID_ANSIX962_EC_PRIME256V1,
+ "ANSI X9.62 elliptic curve prime256v1 (aka secp256r1, NIST P-256)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+
+ /* SECG named elliptic curves (prime field) */
+ OD(secgECsecp112r1, SEC_OID_SECG_EC_SECP112R1,
+ "SECG elliptic curve secp112r1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsecp112r2, SEC_OID_SECG_EC_SECP112R2,
+ "SECG elliptic curve secp112r2",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsecp128r1, SEC_OID_SECG_EC_SECP128R1,
+ "SECG elliptic curve secp128r1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsecp128r2, SEC_OID_SECG_EC_SECP128R2,
+ "SECG elliptic curve secp128r2",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsecp160k1, SEC_OID_SECG_EC_SECP160K1,
+ "SECG elliptic curve secp160k1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsecp160r1, SEC_OID_SECG_EC_SECP160R1,
+ "SECG elliptic curve secp160r1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsecp160r2, SEC_OID_SECG_EC_SECP160R2,
+ "SECG elliptic curve secp160r2",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsecp192k1, SEC_OID_SECG_EC_SECP192K1,
+ "SECG elliptic curve secp192k1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsecp224k1, SEC_OID_SECG_EC_SECP224K1,
+ "SECG elliptic curve secp224k1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsecp224r1, SEC_OID_SECG_EC_SECP224R1,
+ "SECG elliptic curve secp224r1 (aka NIST P-224)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsecp256k1, SEC_OID_SECG_EC_SECP256K1,
+ "SECG elliptic curve secp256k1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsecp384r1, SEC_OID_SECG_EC_SECP384R1,
+ "SECG elliptic curve secp384r1 (aka NIST P-384)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsecp521r1, SEC_OID_SECG_EC_SECP521R1,
+ "SECG elliptic curve secp521r1 (aka NIST P-521)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+
+ /* ANSI X9.62 named elliptic curves (characteristic two field) */
+ OD(ansiX962c2pnb163v1, SEC_OID_ANSIX962_EC_C2PNB163V1,
+ "ANSI X9.62 elliptic curve c2pnb163v1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2pnb163v2, SEC_OID_ANSIX962_EC_C2PNB163V2,
+ "ANSI X9.62 elliptic curve c2pnb163v2",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2pnb163v3, SEC_OID_ANSIX962_EC_C2PNB163V3,
+ "ANSI X9.62 elliptic curve c2pnb163v3",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2pnb176v1, SEC_OID_ANSIX962_EC_C2PNB176V1,
+ "ANSI X9.62 elliptic curve c2pnb176v1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2tnb191v1, SEC_OID_ANSIX962_EC_C2TNB191V1,
+ "ANSI X9.62 elliptic curve c2tnb191v1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2tnb191v2, SEC_OID_ANSIX962_EC_C2TNB191V2,
+ "ANSI X9.62 elliptic curve c2tnb191v2",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2tnb191v3, SEC_OID_ANSIX962_EC_C2TNB191V3,
+ "ANSI X9.62 elliptic curve c2tnb191v3",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2onb191v4, SEC_OID_ANSIX962_EC_C2ONB191V4,
+ "ANSI X9.62 elliptic curve c2onb191v4",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2onb191v5, SEC_OID_ANSIX962_EC_C2ONB191V5,
+ "ANSI X9.62 elliptic curve c2onb191v5",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2pnb208w1, SEC_OID_ANSIX962_EC_C2PNB208W1,
+ "ANSI X9.62 elliptic curve c2pnb208w1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2tnb239v1, SEC_OID_ANSIX962_EC_C2TNB239V1,
+ "ANSI X9.62 elliptic curve c2tnb239v1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2tnb239v2, SEC_OID_ANSIX962_EC_C2TNB239V2,
+ "ANSI X9.62 elliptic curve c2tnb239v2",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2tnb239v3, SEC_OID_ANSIX962_EC_C2TNB239V3,
+ "ANSI X9.62 elliptic curve c2tnb239v3",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2onb239v4, SEC_OID_ANSIX962_EC_C2ONB239V4,
+ "ANSI X9.62 elliptic curve c2onb239v4",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2onb239v5, SEC_OID_ANSIX962_EC_C2ONB239V5,
+ "ANSI X9.62 elliptic curve c2onb239v5",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2pnb272w1, SEC_OID_ANSIX962_EC_C2PNB272W1,
+ "ANSI X9.62 elliptic curve c2pnb272w1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2pnb304w1, SEC_OID_ANSIX962_EC_C2PNB304W1,
+ "ANSI X9.62 elliptic curve c2pnb304w1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2tnb359v1, SEC_OID_ANSIX962_EC_C2TNB359V1,
+ "ANSI X9.62 elliptic curve c2tnb359v1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2pnb368w1, SEC_OID_ANSIX962_EC_C2PNB368W1,
+ "ANSI X9.62 elliptic curve c2pnb368w1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansiX962c2tnb431r1, SEC_OID_ANSIX962_EC_C2TNB431R1,
+ "ANSI X9.62 elliptic curve c2tnb431r1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+
+ /* SECG named elliptic curves (characterisitic two field) */
+ OD(secgECsect113r1, SEC_OID_SECG_EC_SECT113R1,
+ "SECG elliptic curve sect113r1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect113r2, SEC_OID_SECG_EC_SECT113R2,
+ "SECG elliptic curve sect113r2",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect131r1, SEC_OID_SECG_EC_SECT131R1,
+ "SECG elliptic curve sect131r1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect131r2, SEC_OID_SECG_EC_SECT131R2,
+ "SECG elliptic curve sect131r2",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect163k1, SEC_OID_SECG_EC_SECT163K1,
+ "SECG elliptic curve sect163k1 (aka NIST K-163)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect163r1, SEC_OID_SECG_EC_SECT163R1,
+ "SECG elliptic curve sect163r1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect163r2, SEC_OID_SECG_EC_SECT163R2,
+ "SECG elliptic curve sect163r2 (aka NIST B-163)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect193r1, SEC_OID_SECG_EC_SECT193R1,
+ "SECG elliptic curve sect193r1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect193r2, SEC_OID_SECG_EC_SECT193R2,
+ "SECG elliptic curve sect193r2",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect233k1, SEC_OID_SECG_EC_SECT233K1,
+ "SECG elliptic curve sect233k1 (aka NIST K-233)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect233r1, SEC_OID_SECG_EC_SECT233R1,
+ "SECG elliptic curve sect233r1 (aka NIST B-233)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect239k1, SEC_OID_SECG_EC_SECT239K1,
+ "SECG elliptic curve sect239k1",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect283k1, SEC_OID_SECG_EC_SECT283K1,
+ "SECG elliptic curve sect283k1 (aka NIST K-283)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect283r1, SEC_OID_SECG_EC_SECT283R1,
+ "SECG elliptic curve sect283r1 (aka NIST B-283)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect409k1, SEC_OID_SECG_EC_SECT409K1,
+ "SECG elliptic curve sect409k1 (aka NIST K-409)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect409r1, SEC_OID_SECG_EC_SECT409R1,
+ "SECG elliptic curve sect409r1 (aka NIST B-409)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect571k1, SEC_OID_SECG_EC_SECT571K1,
+ "SECG elliptic curve sect571k1 (aka NIST K-571)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(secgECsect571r1, SEC_OID_SECG_EC_SECT571R1,
+ "SECG elliptic curve sect571r1 (aka NIST B-571)",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+
+ OD(netscapeAOLScreenname, SEC_OID_NETSCAPE_AOLSCREENNAME,
+ "AOL Screenname", CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+
+ OD(x520SurName, SEC_OID_AVA_SURNAME,
+ "X520 Title", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520SerialNumber, SEC_OID_AVA_SERIAL_NUMBER,
+ "X520 Serial Number", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520StreetAddress, SEC_OID_AVA_STREET_ADDRESS,
+ "X520 Street Address", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520Title, SEC_OID_AVA_TITLE,
+ "X520 Title", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520PostalAddress, SEC_OID_AVA_POSTAL_ADDRESS,
+ "X520 Postal Address", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520PostalCode, SEC_OID_AVA_POSTAL_CODE,
+ "X520 Postal Code", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520PostOfficeBox, SEC_OID_AVA_POST_OFFICE_BOX,
+ "X520 Post Office Box", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520GivenName, SEC_OID_AVA_GIVEN_NAME,
+ "X520 Given Name", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520Initials, SEC_OID_AVA_INITIALS,
+ "X520 Initials", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520GenerationQualifier, SEC_OID_AVA_GENERATION_QUALIFIER,
+ "X520 Generation Qualifier",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520HouseIdentifier, SEC_OID_AVA_HOUSE_IDENTIFIER,
+ "X520 House Identifier",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520Pseudonym, SEC_OID_AVA_PSEUDONYM,
+ "X520 Pseudonym", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ /* More OIDs */
+ OD(pkixCAIssuers, SEC_OID_PKIX_CA_ISSUERS,
+ "PKIX CA issuers access method",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs9ExtensionRequest, SEC_OID_PKCS9_EXTENSION_REQUEST,
+ "PKCS #9 Extension Request",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ /* more ECC Signature Oids */
+ OD(ansix962SignatureRecommended,
+ SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST,
+ "X9.62 ECDSA signature with recommended digest", CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansix962SignatureSpecified,
+ SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST,
+ "X9.62 ECDSA signature with specified digest", CKM_ECDSA,
+ INVALID_CERT_EXTENSION),
+ OD(ansix962SignaturewithSHA224Digest,
+ SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE,
+ "X9.62 ECDSA signature with SHA224", CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansix962SignaturewithSHA256Digest,
+ SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE,
+ "X9.62 ECDSA signature with SHA256", CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansix962SignaturewithSHA384Digest,
+ SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE,
+ "X9.62 ECDSA signature with SHA384", CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(ansix962SignaturewithSHA512Digest,
+ SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE,
+ "X9.62 ECDSA signature with SHA512", CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+
+ /* More id-ce and id-pe OIDs from RFC 3280 */
+ OD(x509HoldInstructionCode, SEC_OID_X509_HOLD_INSTRUCTION_CODE,
+ "CRL Hold Instruction Code", CKM_INVALID_MECHANISM,
+ UNSUPPORTED_CERT_EXTENSION),
+ OD(x509DeltaCRLIndicator, SEC_OID_X509_DELTA_CRL_INDICATOR,
+ "Delta CRL Indicator", CKM_INVALID_MECHANISM,
+ FAKE_SUPPORTED_CERT_EXTENSION),
+ OD(x509IssuingDistributionPoint, SEC_OID_X509_ISSUING_DISTRIBUTION_POINT,
+ "Issuing Distribution Point", CKM_INVALID_MECHANISM,
+ FAKE_SUPPORTED_CERT_EXTENSION),
+ OD(x509CertIssuer, SEC_OID_X509_CERT_ISSUER,
+ "Certificate Issuer Extension", CKM_INVALID_MECHANISM,
+ FAKE_SUPPORTED_CERT_EXTENSION),
+ OD(x509FreshestCRL, SEC_OID_X509_FRESHEST_CRL,
+ "Freshest CRL", CKM_INVALID_MECHANISM,
+ UNSUPPORTED_CERT_EXTENSION),
+ OD(x509InhibitAnyPolicy, SEC_OID_X509_INHIBIT_ANY_POLICY,
+ "Inhibit Any Policy", CKM_INVALID_MECHANISM,
+ FAKE_SUPPORTED_CERT_EXTENSION),
+ OD(x509SubjectInfoAccess, SEC_OID_X509_SUBJECT_INFO_ACCESS,
+ "Subject Info Access", CKM_INVALID_MECHANISM,
+ UNSUPPORTED_CERT_EXTENSION),
+
+ /* Camellia algorithm OIDs */
+ OD(camellia128_CBC, SEC_OID_CAMELLIA_128_CBC,
+ "CAMELLIA-128-CBC", CKM_CAMELLIA_CBC, INVALID_CERT_EXTENSION),
+ OD(camellia192_CBC, SEC_OID_CAMELLIA_192_CBC,
+ "CAMELLIA-192-CBC", CKM_CAMELLIA_CBC, INVALID_CERT_EXTENSION),
+ OD(camellia256_CBC, SEC_OID_CAMELLIA_256_CBC,
+ "CAMELLIA-256-CBC", CKM_CAMELLIA_CBC, INVALID_CERT_EXTENSION),
+
+ /* PKCS 5 v2 OIDS */
+ OD(pkcs5Pbkdf2, SEC_OID_PKCS5_PBKDF2,
+ "PKCS #5 Password Based Key Dervive Function v2 ",
+ CKM_PKCS5_PBKD2, INVALID_CERT_EXTENSION),
+ OD(pkcs5Pbes2, SEC_OID_PKCS5_PBES2,
+ "PKCS #5 Password Based Encryption v2 ",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkcs5Pbmac1, SEC_OID_PKCS5_PBMAC1,
+ "PKCS #5 Password Based Authentication v1 ",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(hmac_sha1, SEC_OID_HMAC_SHA1, "HMAC SHA-1",
+ CKM_SHA_1_HMAC, INVALID_CERT_EXTENSION),
+ OD(hmac_sha224, SEC_OID_HMAC_SHA224, "HMAC SHA-224",
+ CKM_SHA224_HMAC, INVALID_CERT_EXTENSION),
+ OD(hmac_sha256, SEC_OID_HMAC_SHA256, "HMAC SHA-256",
+ CKM_SHA256_HMAC, INVALID_CERT_EXTENSION),
+ OD(hmac_sha384, SEC_OID_HMAC_SHA384, "HMAC SHA-384",
+ CKM_SHA384_HMAC, INVALID_CERT_EXTENSION),
+ OD(hmac_sha512, SEC_OID_HMAC_SHA512, "HMAC SHA-512",
+ CKM_SHA512_HMAC, INVALID_CERT_EXTENSION),
+
+ /* SIA extension OIDs */
+ OD(x509SIATimeStamping, SEC_OID_PKIX_TIMESTAMPING,
+ "SIA Time Stamping", CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+ OD(x509SIACaRepository, SEC_OID_PKIX_CA_REPOSITORY,
+ "SIA CA Repository", CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+
+ OD(isoSHA1WithRSASignature, SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE,
+ "ISO SHA-1 with RSA Signature",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ /* SEED algorithm OIDs */
+ OD(seed_CBC, SEC_OID_SEED_CBC,
+ "SEED-CBC", CKM_SEED_CBC, INVALID_CERT_EXTENSION),
+
+ OD(x509CertificatePoliciesAnyPolicy, SEC_OID_X509_ANY_POLICY,
+ "Certificate Policies AnyPolicy",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ OD(pkcs1RSAOAEPEncryption, SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION,
+ "PKCS #1 RSA-OAEP Encryption", CKM_RSA_PKCS_OAEP,
+ INVALID_CERT_EXTENSION),
+
+ OD(pkcs1MGF1, SEC_OID_PKCS1_MGF1,
+ "PKCS #1 MGF1 Mask Generation Function", CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION),
+
+ OD(pkcs1PSpecified, SEC_OID_PKCS1_PSPECIFIED,
+ "PKCS #1 RSA-OAEP Explicitly Specified Encoding Parameters",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ OD(pkcs1RSAPSSSignature, SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
+ "PKCS #1 RSA-PSS Signature", CKM_RSA_PKCS_PSS,
+ INVALID_CERT_EXTENSION),
+
+ OD(pkcs1SHA224WithRSAEncryption, SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION,
+ "PKCS #1 SHA-224 With RSA Encryption", CKM_SHA224_RSA_PKCS,
+ INVALID_CERT_EXTENSION),
+
+ OD(sha224, SEC_OID_SHA224, "SHA-224", CKM_SHA224, INVALID_CERT_EXTENSION),
+
+ OD(evIncorporationLocality, SEC_OID_EV_INCORPORATION_LOCALITY,
+ "Jurisdiction of Incorporation Locality Name",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(evIncorporationState, SEC_OID_EV_INCORPORATION_STATE,
+ "Jurisdiction of Incorporation State Name",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(evIncorporationCountry, SEC_OID_EV_INCORPORATION_COUNTRY,
+ "Jurisdiction of Incorporation Country Name",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520BusinessCategory, SEC_OID_BUSINESS_CATEGORY,
+ "Business Category",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ OD(nistDSASignaturewithSHA224Digest,
+ SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST,
+ "DSA with SHA-224 Signature",
+ CKM_INVALID_MECHANISM /* not yet defined */, INVALID_CERT_EXTENSION),
+ OD(nistDSASignaturewithSHA256Digest,
+ SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST,
+ "DSA with SHA-256 Signature",
+ CKM_INVALID_MECHANISM /* not yet defined */, INVALID_CERT_EXTENSION),
+ OD(msExtendedKeyUsageTrustListSigning,
+ SEC_OID_MS_EXT_KEY_USAGE_CTL_SIGNING,
+ "Microsoft Trust List Signing",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(x520Name, SEC_OID_AVA_NAME,
+ "X520 Name", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ OD(aes128_GCM, SEC_OID_AES_128_GCM,
+ "AES-128-GCM", CKM_AES_GCM, INVALID_CERT_EXTENSION),
+ OD(aes192_GCM, SEC_OID_AES_192_GCM,
+ "AES-192-GCM", CKM_AES_GCM, INVALID_CERT_EXTENSION),
+ OD(aes256_GCM, SEC_OID_AES_256_GCM,
+ "AES-256-GCM", CKM_AES_GCM, INVALID_CERT_EXTENSION),
+ OD(idea_CBC, SEC_OID_IDEA_CBC,
+ "IDEA_CBC", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ ODE(SEC_OID_RC2_40_CBC,
+ "RC2-40-CBC", CKM_RC2_CBC, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_DES_40_CBC,
+ "DES-40-CBC", CKM_RC2_CBC, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_RC4_40,
+ "RC4-40", CKM_RC4, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_RC4_56,
+ "RC4-56", CKM_RC4, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_NULL_CIPHER,
+ "NULL cipher", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_HMAC_MD5,
+ "HMAC-MD5", CKM_MD5_HMAC, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_RSA,
+ "TLS RSA key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_DHE_RSA,
+ "TLS DHE-RSA key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_DHE_DSS,
+ "TLS DHE-DSS key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_DH_RSA,
+ "TLS DH-RSA key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_DH_DSS,
+ "TLS DH-DSS key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_DH_ANON,
+ "TLS DH-ANON key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_ECDHE_ECDSA,
+ "TLS ECDHE-ECDSA key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_ECDHE_RSA,
+ "TLS ECDHE-RSA key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_ECDH_ECDSA,
+ "TLS ECDH-ECDSA key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_ECDH_RSA,
+ "TLS ECDH-RSA key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_ECDH_ANON,
+ "TLS ECDH-ANON key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_RSA_EXPORT,
+ "TLS RSA-EXPORT key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_DHE_RSA_EXPORT,
+ "TLS DHE-RSA-EXPORT key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_DHE_DSS_EXPORT,
+ "TLS DHE-DSS-EXPORT key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_DH_RSA_EXPORT,
+ "TLS DH-RSA-EXPORT key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_DH_DSS_EXPORT,
+ "TLS DH-DSS-EXPORT key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_DH_ANON_EXPORT,
+ "TLS DH-ANON-EXPORT key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_APPLY_SSL_POLICY,
+ "Apply SSL policy (pseudo-OID)", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_CHACHA20_POLY1305,
+ "ChaCha20-Poly1305", CKM_NSS_CHACHA20_POLY1305, INVALID_CERT_EXTENSION),
+
+ ODE(SEC_OID_TLS_ECDHE_PSK,
+ "TLS ECHDE-PSK key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_DHE_PSK,
+ "TLS DHE-PSK key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ ODE(SEC_OID_TLS_FFDHE_2048,
+ "TLS FFDHE 2048-bit key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_FFDHE_3072,
+ "TLS FFDHE 3072-bit key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_FFDHE_4096,
+ "TLS FFDHE 4096-bit key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_FFDHE_6144,
+ "TLS FFDHE 6144-bit key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_FFDHE_8192,
+ "TLS FFDHE 8192-bit key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS_DHE_CUSTOM,
+ "TLS DHE custom group key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(curve25519, SEC_OID_CURVE25519,
+ "Curve25519", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ ODE(SEC_OID_TLS13_KEA_ANY,
+ "TLS 1.3 fake key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ OD(x509ExtKeyUsageAnyUsage, SEC_OID_X509_ANY_EXT_KEY_USAGE,
+ "Any Extended Key Usage",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixExtendedKeyUsageIPsecIKE,
+ SEC_OID_EXT_KEY_USAGE_IPSEC_IKE,
+ "IPsec IKE Certificate",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(ipsecIKEEnd,
+ SEC_OID_IPSEC_IKE_END,
+ "IPsec IKE End",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(ipsecIKEIntermediate,
+ SEC_OID_IPSEC_IKE_INTERMEDIATE,
+ "IPsec IKE Intermediate",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixExtendedKeyUsageIPsecEnd,
+ SEC_OID_EXT_KEY_USAGE_IPSEC_END,
+ "IPsec Tunnel",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixExtendedKeyUsageIPsecTunnel,
+ SEC_OID_EXT_KEY_USAGE_IPSEC_TUNNEL,
+ "IPsec Tunnel",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+ OD(pkixExtendedKeyUsageIPsecUser,
+ SEC_OID_EXT_KEY_USAGE_IPSEC_USER,
+ "IPsec User",
+ CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
+ OD(sha3_224, SEC_OID_SHA3_224, "SHA3-224", CKM_SHA3_224, INVALID_CERT_EXTENSION),
+ OD(sha3_256, SEC_OID_SHA3_256, "SHA3-256", CKM_SHA3_256, INVALID_CERT_EXTENSION),
+ OD(sha3_384, SEC_OID_SHA3_384, "SHA3-384", CKM_SHA3_384, INVALID_CERT_EXTENSION),
+ OD(sha3_512, SEC_OID_SHA3_512, "SHA3-512", CKM_SHA3_512, INVALID_CERT_EXTENSION),
+
+ OD(hmac_sha3_224, SEC_OID_HMAC_SHA3_224, "HMAC SHA3-224", CKM_SHA3_224_HMAC, INVALID_CERT_EXTENSION),
+ OD(hmac_sha3_256, SEC_OID_HMAC_SHA3_256, "HMAC SHA3-256", CKM_SHA3_256_HMAC, INVALID_CERT_EXTENSION),
+ OD(hmac_sha3_384, SEC_OID_HMAC_SHA3_384, "HMAC SHA3-384", CKM_SHA3_384_HMAC, INVALID_CERT_EXTENSION),
+ OD(hmac_sha3_512, SEC_OID_HMAC_SHA3_512, "HMAC SHA3-512", CKM_SHA3_512_HMAC, INVALID_CERT_EXTENSION),
+
+ ODE(SEC_OID_XYBER768D00,
+ "X25519+Kyber768 key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+};
+
+/* PRIVATE EXTENDED SECOID Table
+ * This table is private. Its structure is opaque to the outside.
+ * It is indexed by the same SECOidTag as the oids table above.
+ * Every member of this struct must have accessor functions (set, get)
+ * and those functions must operate by value, not by reference.
+ * The addresses of the contents of this table must not be exposed
+ * by the accessor functions.
+ */
+typedef struct privXOidStr {
+ PRUint32 notPolicyFlags; /* ones complement of policy flags */
+} privXOid;
+
+static privXOid xOids[SEC_OID_TOTAL];
+
+/*
+ * now the dynamic table. The dynamic table gets build at init time.
+ * and conceivably gets modified if the user loads new crypto modules.
+ * All this static data, and the allocated data to which it points,
+ * is protected by a global reader/writer lock.
+ * The c language guarantees that global and static data that is not
+ * explicitly initialized will be initialized with zeros. If we
+ * initialize it with zeros, the data goes into the initialized data
+ * secment, and increases the size of the library. By leaving it
+ * uninitialized, it is allocated in BSS, and does NOT increase the
+ * library size.
+ */
+
+typedef struct dynXOidStr {
+ SECOidData data;
+ privXOid priv;
+} dynXOid;
+
+static NSSRWLock *dynOidLock;
+static PLArenaPool *dynOidPool;
+static PLHashTable *dynOidHash;
+static dynXOid **dynOidTable; /* not in the pool */
+static int dynOidEntriesAllocated;
+static int dynOidEntriesUsed;
+
+/* Creates NSSRWLock and dynOidPool at initialization time.
+*/
+static SECStatus
+secoid_InitDynOidData(void)
+{
+ SECStatus rv = SECSuccess;
+
+ dynOidLock = NSSRWLock_New(1, "dynamic OID data");
+ if (!dynOidLock) {
+ return SECFailure; /* Error code should already be set. */
+ }
+ dynOidPool = PORT_NewArena(2048);
+ if (!dynOidPool) {
+ rv = SECFailure /* Error code should already be set. */;
+ }
+ return rv;
+}
+
+/* Add oidData to hash table. Caller holds write lock dynOidLock. */
+static SECStatus
+secoid_HashDynamicOiddata(const SECOidData *oid)
+{
+ PLHashEntry *entry;
+
+ if (!dynOidHash) {
+ dynOidHash = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare,
+ PL_CompareValues, NULL, NULL);
+ if (!dynOidHash) {
+ return SECFailure;
+ }
+ }
+
+ entry = PL_HashTableAdd(dynOidHash, &oid->oid, (void *)oid);
+ return entry ? SECSuccess : SECFailure;
+}
+
+/*
+ * Lookup a Dynamic OID. Dynamic OID's still change slowly, so it's
+ * cheaper to rehash the table when it changes than it is to do the loop
+ * each time.
+ */
+static SECOidData *
+secoid_FindDynamic(const SECItem *key)
+{
+ SECOidData *ret = NULL;
+
+ NSSRWLock_LockRead(dynOidLock);
+ if (dynOidHash) {
+ ret = (SECOidData *)PL_HashTableLookup(dynOidHash, key);
+ }
+ NSSRWLock_UnlockRead(dynOidLock);
+ if (ret == NULL) {
+ PORT_SetError(SEC_ERROR_UNRECOGNIZED_OID);
+ }
+ return ret;
+}
+
+static dynXOid *
+secoid_FindDynamicByTag(SECOidTag tagnum)
+{
+ dynXOid *dxo = NULL;
+ int tagNumDiff;
+
+ if (tagnum < SEC_OID_TOTAL) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return NULL;
+ }
+ tagNumDiff = tagnum - SEC_OID_TOTAL;
+
+ NSSRWLock_LockRead(dynOidLock);
+ if (dynOidTable != NULL &&
+ tagNumDiff < dynOidEntriesUsed) {
+ dxo = dynOidTable[tagNumDiff];
+ }
+ NSSRWLock_UnlockRead(dynOidLock);
+ if (dxo == NULL) {
+ PORT_SetError(SEC_ERROR_UNRECOGNIZED_OID);
+ }
+ return dxo;
+}
+
+/*
+ * This routine is thread safe now.
+ */
+SECOidTag
+SECOID_AddEntry(const SECOidData *src)
+{
+ SECOidData *dst;
+ dynXOid **table;
+ SECOidTag ret = SEC_OID_UNKNOWN;
+ SECStatus rv;
+ int tableEntries;
+ int used;
+
+ if (!src || !src->oid.data || !src->oid.len ||
+ !src->desc || !strlen(src->desc)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return ret;
+ }
+ if (src->supportedExtension != INVALID_CERT_EXTENSION &&
+ src->supportedExtension != UNSUPPORTED_CERT_EXTENSION &&
+ src->supportedExtension != SUPPORTED_CERT_EXTENSION) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return ret;
+ }
+
+ if (!dynOidPool || !dynOidLock) {
+ PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
+ return ret;
+ }
+
+ NSSRWLock_LockWrite(dynOidLock);
+
+ /* We've just acquired the write lock, and now we call FindOIDTag
+ ** which will acquire and release the read lock. NSSRWLock has been
+ ** designed to allow this very case without deadlock. This approach
+ ** makes the test for the presence of the OID, and the subsequent
+ ** addition of the OID to the table a single atomic write operation.
+ */
+ ret = SECOID_FindOIDTag(&src->oid);
+ if (ret != SEC_OID_UNKNOWN) {
+ /* we could return an error here, but I chose not to do that.
+ ** This way, if we add an OID to the shared library's built in
+ ** list of OIDs in some future release, and that OID is the same
+ ** as some OID that a program has been adding, the program will
+ ** not suddenly stop working.
+ */
+ goto done;
+ }
+
+ table = dynOidTable;
+ tableEntries = dynOidEntriesAllocated;
+ used = dynOidEntriesUsed;
+
+ if (used + 1 > tableEntries) {
+ dynXOid **newTable;
+ int newTableEntries = tableEntries + 16;
+
+ newTable = (dynXOid **)PORT_Realloc(table,
+ newTableEntries * sizeof(dynXOid *));
+ if (newTable == NULL) {
+ goto done;
+ }
+ dynOidTable = table = newTable;
+ dynOidEntriesAllocated = tableEntries = newTableEntries;
+ }
+
+ /* copy oid structure */
+ dst = (SECOidData *)PORT_ArenaZNew(dynOidPool, dynXOid);
+ if (!dst) {
+ goto done;
+ }
+ rv = SECITEM_CopyItem(dynOidPool, &dst->oid, &src->oid);
+ if (rv != SECSuccess) {
+ goto done;
+ }
+ dst->desc = PORT_ArenaStrdup(dynOidPool, src->desc);
+ if (!dst->desc) {
+ goto done;
+ }
+ dst->offset = (SECOidTag)(used + SEC_OID_TOTAL);
+ dst->mechanism = src->mechanism;
+ dst->supportedExtension = src->supportedExtension;
+
+ rv = secoid_HashDynamicOiddata(dst);
+ if (rv == SECSuccess) {
+ table[used++] = (dynXOid *)dst;
+ dynOidEntriesUsed = used;
+ ret = dst->offset;
+ }
+done:
+ NSSRWLock_UnlockWrite(dynOidLock);
+ return ret;
+}
+
+/* normal static table processing */
+static PLHashTable *oidhash = NULL;
+static PLHashTable *oidmechhash = NULL;
+
+static PLHashNumber
+secoid_HashNumber(const void *key)
+{
+ return (PLHashNumber)((char *)key - (char *)NULL);
+}
+
+#define DEF_FLAGS (NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SSL_KX)
+static void
+handleHashAlgSupport(char *envVal)
+{
+ char *myVal = PORT_Strdup(envVal); /* Get a copy we can alter */
+ char *arg = myVal;
+
+ while (arg && *arg) {
+ char *nextArg = PL_strpbrk(arg, ";");
+ PRUint32 notEnable;
+
+ if (nextArg) {
+ while (*nextArg == ';') {
+ *nextArg++ = '\0';
+ }
+ }
+ notEnable = (*arg == '-') ? (DEF_FLAGS) : 0;
+ if ((*arg == '+' || *arg == '-') && *++arg) {
+ int i;
+
+ for (i = 1; i < SEC_OID_TOTAL; i++) {
+ if (oids[i].desc && strstr(arg, oids[i].desc)) {
+ xOids[i].notPolicyFlags = notEnable |
+ (xOids[i].notPolicyFlags & ~(DEF_FLAGS));
+ }
+ }
+ }
+ arg = nextArg;
+ }
+ PORT_Free(myVal); /* can handle NULL argument OK */
+}
+
+SECStatus
+SECOID_Init(void)
+{
+ PLHashEntry *entry;
+ const SECOidData *oid;
+ SECOidTag i;
+ char *envVal;
+
+#define NSS_VERSION_VARIABLE __nss_util_version
+#include "verref.h"
+
+ if (oidhash) {
+ return SECSuccess; /* already initialized */
+ }
+
+ /* xyber768d00 must be enabled explicitly */
+ xOids[SEC_OID_XYBER768D00].notPolicyFlags = NSS_USE_ALG_IN_SSL_KX;
+
+ if (!PR_GetEnvSecure("NSS_ALLOW_WEAK_SIGNATURE_ALG")) {
+ /* initialize any policy flags that are disabled by default */
+ xOids[SEC_OID_MD2].notPolicyFlags = ~0;
+ xOids[SEC_OID_MD4].notPolicyFlags = ~0;
+ xOids[SEC_OID_MD5].notPolicyFlags = ~0;
+ xOids[SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION].notPolicyFlags = ~0;
+ xOids[SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION].notPolicyFlags = ~0;
+ xOids[SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION].notPolicyFlags = ~0;
+ xOids[SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC].notPolicyFlags = ~0;
+ xOids[SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC].notPolicyFlags = ~0;
+ }
+
+ /* turn off NSS_USE_POLICY_IN_SSL by default */
+ xOids[SEC_OID_APPLY_SSL_POLICY].notPolicyFlags = NSS_USE_POLICY_IN_SSL;
+
+ envVal = PR_GetEnvSecure("NSS_HASH_ALG_SUPPORT");
+ if (envVal)
+ handleHashAlgSupport(envVal);
+
+ if (secoid_InitDynOidData() != SECSuccess) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ PORT_Assert(0); /* this function should never fail */
+ return SECFailure;
+ }
+
+ oidhash = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare,
+ PL_CompareValues, NULL, NULL);
+ oidmechhash = PL_NewHashTable(0, secoid_HashNumber, PL_CompareValues,
+ PL_CompareValues, NULL, NULL);
+
+ if (!oidhash || !oidmechhash) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ PORT_Assert(0); /*This function should never fail. */
+ return (SECFailure);
+ }
+
+ for (i = 0; i < SEC_OID_TOTAL; i++) {
+ oid = &oids[i];
+
+ PORT_Assert(oid->offset == i);
+
+ entry = PL_HashTableAdd(oidhash, &oid->oid, (void *)oid);
+ if (entry == NULL) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ PORT_Assert(0); /*This function should never fail. */
+ return (SECFailure);
+ }
+
+ if (oid->mechanism != CKM_INVALID_MECHANISM) {
+ entry = PL_HashTableAdd(oidmechhash,
+ (void *)(uintptr_t)oid->mechanism, (void *)oid);
+ if (entry == NULL) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ PORT_Assert(0); /* This function should never fail. */
+ return (SECFailure);
+ }
+ }
+ }
+
+ PORT_Assert(i == SEC_OID_TOTAL);
+
+ return (SECSuccess);
+}
+
+SECOidData *
+SECOID_FindOIDByMechanism(unsigned long mechanism)
+{
+ SECOidData *ret;
+
+ PR_ASSERT(oidmechhash != NULL);
+ if (oidmechhash == NULL && SECOID_Init() != SECSuccess) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return NULL;
+ }
+
+ ret = PL_HashTableLookupConst(oidmechhash, (void *)(uintptr_t)mechanism);
+ if (ret == NULL) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ }
+
+ return (ret);
+}
+
+SECOidData *
+SECOID_FindOID(const SECItem *oid)
+{
+ SECOidData *ret;
+
+ PR_ASSERT(oidhash != NULL);
+ if (oidhash == NULL && SECOID_Init() != SECSuccess) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return NULL;
+ }
+
+ ret = PL_HashTableLookupConst(oidhash, oid);
+ if (ret == NULL) {
+ ret = secoid_FindDynamic(oid);
+ if (ret == NULL) {
+ PORT_SetError(SEC_ERROR_UNRECOGNIZED_OID);
+ }
+ }
+
+ return (ret);
+}
+
+SECOidTag
+SECOID_FindOIDTag(const SECItem *oid)
+{
+ SECOidData *oiddata;
+
+ oiddata = SECOID_FindOID(oid);
+ if (oiddata == NULL)
+ return SEC_OID_UNKNOWN;
+
+ return oiddata->offset;
+}
+
+/* This really should return const. */
+SECOidData *
+SECOID_FindOIDByTag(SECOidTag tagnum)
+{
+ if (tagnum >= SEC_OID_TOTAL) {
+ return (SECOidData *)secoid_FindDynamicByTag(tagnum);
+ }
+
+ PORT_Assert((unsigned int)tagnum < SEC_OID_TOTAL);
+ return (SECOidData *)(&oids[tagnum]);
+}
+
+PRBool
+SECOID_KnownCertExtenOID(SECItem *extenOid)
+{
+ SECOidData *oidData;
+
+ oidData = SECOID_FindOID(extenOid);
+ if (oidData == (SECOidData *)NULL)
+ return (PR_FALSE);
+ return ((oidData->supportedExtension == SUPPORTED_CERT_EXTENSION) ? PR_TRUE : PR_FALSE);
+}
+
+const char *
+SECOID_FindOIDTagDescription(SECOidTag tagnum)
+{
+ const SECOidData *oidData = SECOID_FindOIDByTag(tagnum);
+ return oidData ? oidData->desc : 0;
+}
+
+/* --------- opaque extended OID table accessor functions ---------------*/
+/*
+ * Any of these functions may return SECSuccess or SECFailure with the error
+ * code set to SEC_ERROR_UNKNOWN_OBJECT_TYPE if the SECOidTag is out of range.
+ */
+
+static privXOid *
+secoid_FindXOidByTag(SECOidTag tagnum)
+{
+ if (tagnum >= SEC_OID_TOTAL) {
+ dynXOid *dxo = secoid_FindDynamicByTag(tagnum);
+ return (dxo ? &dxo->priv : NULL);
+ }
+
+ PORT_Assert((unsigned int)tagnum < SEC_OID_TOTAL);
+ return &xOids[tagnum];
+}
+
+/* The Get function outputs the 32-bit value associated with the SECOidTag.
+ * Flags bits are the NSS_USE_ALG_ #defines in "secoidt.h".
+ * Default value for any algorithm is 0xffffffff (enabled for all purposes).
+ * No value is output if function returns SECFailure.
+ */
+SECStatus
+NSS_GetAlgorithmPolicy(SECOidTag tag, PRUint32 *pValue)
+{
+ privXOid *pxo = secoid_FindXOidByTag(tag);
+ if (!pxo)
+ return SECFailure;
+ if (!pValue) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ *pValue = ~(pxo->notPolicyFlags);
+ return SECSuccess;
+}
+
+static PRBool nss_policy_locked = PR_FALSE;
+
+/* The Set function modifies the stored value according to the following
+ * algorithm:
+ * policy[tag] = (policy[tag] & ~clearBits) | setBits;
+ */
+SECStatus
+NSS_SetAlgorithmPolicy(SECOidTag tag, PRUint32 setBits, PRUint32 clearBits)
+{
+ privXOid *pxo = secoid_FindXOidByTag(tag);
+ PRUint32 policyFlags;
+ if (!pxo)
+ return SECFailure;
+
+ if (nss_policy_locked) {
+ PORT_SetError(SEC_ERROR_POLICY_LOCKED);
+ return SECFailure;
+ }
+ /* The stored policy flags are the ones complement of the flags as
+ * seen by the user. This is not atomic, but these changes should
+ * be done rarely, e.g. at initialization time.
+ */
+ policyFlags = ~(pxo->notPolicyFlags);
+ policyFlags = (policyFlags & ~clearBits) | setBits;
+ pxo->notPolicyFlags = ~policyFlags;
+ return SECSuccess;
+}
+
+/* Get the state of nss_policy_locked */
+PRBool
+NSS_IsPolicyLocked(void)
+{
+ return nss_policy_locked;
+}
+
+/* Once the policy is locked, it can't be unlocked */
+void
+NSS_LockPolicy(void)
+{
+ nss_policy_locked = PR_TRUE;
+}
+
+/* --------- END OF opaque extended OID table accessor functions ---------*/
+
+/* for now, this is only used in a single place, so it can remain static */
+static PRBool parentForkedAfterC_Initialize;
+
+#define SKIP_AFTER_FORK(x) \
+ if (!parentForkedAfterC_Initialize) \
+ x
+
+/*
+ * free up the oid tables.
+ */
+SECStatus
+SECOID_Shutdown(void)
+{
+ if (oidhash) {
+ PL_HashTableDestroy(oidhash);
+ oidhash = NULL;
+ }
+ if (oidmechhash) {
+ PL_HashTableDestroy(oidmechhash);
+ oidmechhash = NULL;
+ }
+ /* Have to handle the case where the lock was created, but
+ ** the pool wasn't.
+ ** I'm not going to attempt to create the lock, just to protect
+ ** the destruction of data that probably isn't initialized anyway.
+ */
+ if (dynOidLock) {
+ SKIP_AFTER_FORK(NSSRWLock_LockWrite(dynOidLock));
+ if (dynOidHash) {
+ PL_HashTableDestroy(dynOidHash);
+ dynOidHash = NULL;
+ }
+ if (dynOidPool) {
+ PORT_FreeArena(dynOidPool, PR_FALSE);
+ dynOidPool = NULL;
+ }
+ if (dynOidTable) {
+ PORT_Free(dynOidTable);
+ dynOidTable = NULL;
+ }
+ dynOidEntriesAllocated = 0;
+ dynOidEntriesUsed = 0;
+
+ SKIP_AFTER_FORK(NSSRWLock_UnlockWrite(dynOidLock));
+ SKIP_AFTER_FORK(NSSRWLock_Destroy(dynOidLock));
+ dynOidLock = NULL;
+ } else {
+ /* Since dynOidLock doesn't exist, then all the data it protects
+ ** should be uninitialized. We'll check that (in DEBUG builds),
+ ** and then make sure it is so, in case NSS is reinitialized.
+ */
+ PORT_Assert(!dynOidHash && !dynOidPool && !dynOidTable &&
+ !dynOidEntriesAllocated && !dynOidEntriesUsed);
+ dynOidHash = NULL;
+ dynOidPool = NULL;
+ dynOidTable = NULL;
+ dynOidEntriesAllocated = 0;
+ dynOidEntriesUsed = 0;
+ }
+ /* we are trashing the old policy state now, also reenable changing
+ * the policy as well */
+ nss_policy_locked = PR_FALSE;
+ memset(xOids, 0, sizeof xOids);
+ return SECSuccess;
+}
+
+void
+UTIL_SetForkState(PRBool forked)
+{
+ parentForkedAfterC_Initialize = forked;
+}
+
+const char *
+NSSUTIL_GetVersion(void)
+{
+ return NSSUTIL_VERSION;
+}
diff --git a/security/nss/lib/util/secoid.h b/security/nss/lib/util/secoid.h
new file mode 100644
index 0000000000..20d4cf551a
--- /dev/null
+++ b/security/nss/lib/util/secoid.h
@@ -0,0 +1,149 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 _SECOID_H_
+#define _SECOID_H_
+
+#include "utilrename.h"
+
+/*
+ * secoid.h - public data structures and prototypes for ASN.1 OID functions
+ */
+
+#include "plarena.h"
+
+#include "seccomon.h"
+#include "secoidt.h"
+#include "secasn1t.h"
+
+SEC_BEGIN_PROTOS
+
+extern const SEC_ASN1Template SECOID_AlgorithmIDTemplate[];
+
+/* This functions simply returns the address of the above-declared template. */
+SEC_ASN1_CHOOSER_DECLARE(SECOID_AlgorithmIDTemplate)
+
+/*
+ * OID handling routines
+ */
+extern SECOidData *SECOID_FindOID(const SECItem *oid);
+extern SECOidTag SECOID_FindOIDTag(const SECItem *oid);
+extern SECOidData *SECOID_FindOIDByTag(SECOidTag tagnum);
+extern SECOidData *SECOID_FindOIDByMechanism(unsigned long mechanism);
+
+/****************************************/
+/*
+** Algorithm id handling operations
+*/
+
+/*
+** Fill in an algorithm-ID object given a tag and some parameters.
+** "aid" where the DER encoded algorithm info is stored (memory
+** is allocated)
+** "tag" the tag number defining the algorithm
+** "params" if not NULL, the parameters to go with the algorithm
+*/
+extern SECStatus SECOID_SetAlgorithmID(PLArenaPool *arena, SECAlgorithmID *aid,
+ SECOidTag tag, SECItem *params);
+
+/*
+** Copy the "src" object to "dest". Memory is allocated in "dest" for
+** each of the appropriate sub-objects. Memory in "dest" is not freed
+** before memory is allocated (use SECOID_DestroyAlgorithmID(dest, PR_FALSE)
+** to do that).
+*/
+extern SECStatus SECOID_CopyAlgorithmID(PLArenaPool *arena, SECAlgorithmID *dest,
+ const SECAlgorithmID *src);
+
+/*
+** Get the tag number for the given algorithm-id object.
+*/
+extern SECOidTag SECOID_GetAlgorithmTag(const SECAlgorithmID *aid);
+
+/*
+** Destroy an algorithm-id object.
+** "aid" the certificate-request to destroy
+** "freeit" if PR_TRUE then free the object as well as its sub-objects
+*/
+extern void SECOID_DestroyAlgorithmID(SECAlgorithmID *aid, PRBool freeit);
+
+/*
+** Compare two algorithm-id objects, returning the difference between
+** them.
+*/
+extern SECComparison SECOID_CompareAlgorithmID(SECAlgorithmID *a,
+ SECAlgorithmID *b);
+
+extern PRBool SECOID_KnownCertExtenOID(SECItem *extenOid);
+
+/* Given a tag number, return a string describing it.
+ */
+extern const char *SECOID_FindOIDTagDescription(SECOidTag tagnum);
+
+/* Add a dynamic SECOidData to the dynamic OID table.
+** Routine copies the src entry, and returns the new SECOidTag.
+** Returns SEC_OID_INVALID if failed to add for some reason.
+*/
+extern SECOidTag SECOID_AddEntry(const SECOidData *src);
+
+/*
+ * initialize the oid data structures.
+ */
+extern SECStatus SECOID_Init(void);
+
+/*
+ * free up the oid data structures.
+ */
+extern SECStatus SECOID_Shutdown(void);
+
+/* if to->data is not NULL, and to->len is large enough to hold the result,
+ * then the resultant OID will be copyed into to->data, and to->len will be
+ * changed to show the actual OID length.
+ * Otherwise, memory for the OID will be allocated (from the caller's
+ * PLArenaPool, if pool is non-NULL) and to->data will receive the address
+ * of the allocated data, and to->len will receive the OID length.
+ * The original value of to->data is not freed when a new buffer is allocated.
+ *
+ * The input string may begin with "OID." and this still be ignored.
+ * The length of the input string is given in len. If len == 0, then
+ * len will be computed as strlen(from), meaning it must be NUL terminated.
+ * It is an error if from == NULL, or if *from == '\0'.
+ */
+extern SECStatus SEC_StringToOID(PLArenaPool *pool, SECItem *to,
+ const char *from, PRUint32 len);
+
+extern void UTIL_SetForkState(PRBool forked);
+
+/*
+ * Accessor functions for new opaque extended SECOID table.
+ * Any of these functions may return SECSuccess or SECFailure with the error
+ * code set to SEC_ERROR_UNKNOWN_OBJECT_TYPE if the SECOidTag is out of range.
+ */
+
+/* The Get function outputs the 32-bit value associated with the SECOidTag.
+ * Flags bits are the NSS_USE_ALG_ #defines in "secoidt.h".
+ * Default value for any algorithm is 0xffffffff (enabled for all purposes).
+ * No value is output if function returns SECFailure.
+ */
+extern SECStatus NSS_GetAlgorithmPolicy(SECOidTag tag, PRUint32 *pValue);
+
+/* The Set function modifies the stored value according to the following
+ * algorithm:
+ * policy[tag] = (policy[tag] & ~clearBits) | setBits;
+ */
+extern SECStatus
+NSS_SetAlgorithmPolicy(SECOidTag tag, PRUint32 setBits, PRUint32 clearBits);
+
+/* Lock the policy so NSS_SetAlgorithmPolicy (and other policy functions)
+ * No longer function */
+void
+NSS_LockPolicy(void);
+
+/* return true if policy changes are now locked out */
+PRBool
+NSS_IsPolicyLocked(void);
+
+SEC_END_PROTOS
+
+#endif /* _SECOID_H_ */
diff --git a/security/nss/lib/util/secoidt.h b/security/nss/lib/util/secoidt.h
new file mode 100644
index 0000000000..3ab0d6cc74
--- /dev/null
+++ b/security/nss/lib/util/secoidt.h
@@ -0,0 +1,578 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 _SECOIDT_H_
+#define _SECOIDT_H_
+
+#include "utilrename.h"
+
+/*
+ * secoidt.h - public data structures for ASN.1 OID functions
+ */
+
+#include "secitem.h"
+
+typedef struct SECOidDataStr SECOidData;
+typedef struct SECAlgorithmIDStr SECAlgorithmID;
+
+/*
+** An X.500 algorithm identifier
+*/
+struct SECAlgorithmIDStr {
+ SECItem algorithm;
+ SECItem parameters;
+};
+
+/*
+ * Misc object IDs - these numbers are for convenient handling.
+ * They are mapped into real object IDs
+ *
+ * NOTE: the order of these entries must mach the array "oids" of SECOidData
+ * in util/secoid.c.
+ */
+typedef enum {
+ SEC_OID_UNKNOWN = 0,
+ SEC_OID_MD2 = 1,
+ SEC_OID_MD4 = 2,
+ SEC_OID_MD5 = 3,
+ SEC_OID_SHA1 = 4,
+ SEC_OID_RC2_CBC = 5,
+ SEC_OID_RC4 = 6,
+ SEC_OID_DES_EDE3_CBC = 7,
+ SEC_OID_RC5_CBC_PAD = 8,
+ SEC_OID_DES_ECB = 9,
+ SEC_OID_DES_CBC = 10,
+ SEC_OID_DES_OFB = 11,
+ SEC_OID_DES_CFB = 12,
+ SEC_OID_DES_MAC = 13,
+ SEC_OID_DES_EDE = 14,
+ SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE = 15,
+ SEC_OID_PKCS1_RSA_ENCRYPTION = 16,
+ SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION = 17,
+ SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION = 18,
+ SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION = 19,
+ SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION = 20,
+ SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC = 21,
+ SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC = 22,
+ SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC = 23,
+ SEC_OID_PKCS7 = 24,
+ SEC_OID_PKCS7_DATA = 25,
+ SEC_OID_PKCS7_SIGNED_DATA = 26,
+ SEC_OID_PKCS7_ENVELOPED_DATA = 27,
+ SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA = 28,
+ SEC_OID_PKCS7_DIGESTED_DATA = 29,
+ SEC_OID_PKCS7_ENCRYPTED_DATA = 30,
+ SEC_OID_PKCS9_EMAIL_ADDRESS = 31,
+ SEC_OID_PKCS9_UNSTRUCTURED_NAME = 32,
+ SEC_OID_PKCS9_CONTENT_TYPE = 33,
+ SEC_OID_PKCS9_MESSAGE_DIGEST = 34,
+ SEC_OID_PKCS9_SIGNING_TIME = 35,
+ SEC_OID_PKCS9_COUNTER_SIGNATURE = 36,
+ SEC_OID_PKCS9_CHALLENGE_PASSWORD = 37,
+ SEC_OID_PKCS9_UNSTRUCTURED_ADDRESS = 38,
+ SEC_OID_PKCS9_EXTENDED_CERTIFICATE_ATTRIBUTES = 39,
+ SEC_OID_PKCS9_SMIME_CAPABILITIES = 40,
+ SEC_OID_AVA_COMMON_NAME = 41,
+ SEC_OID_AVA_COUNTRY_NAME = 42,
+ SEC_OID_AVA_LOCALITY = 43,
+ SEC_OID_AVA_STATE_OR_PROVINCE = 44,
+ SEC_OID_AVA_ORGANIZATION_NAME = 45,
+ SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME = 46,
+ SEC_OID_AVA_DN_QUALIFIER = 47,
+ SEC_OID_AVA_DC = 48,
+
+ SEC_OID_NS_TYPE_GIF = 49,
+ SEC_OID_NS_TYPE_JPEG = 50,
+ SEC_OID_NS_TYPE_URL = 51,
+ SEC_OID_NS_TYPE_HTML = 52,
+ SEC_OID_NS_TYPE_CERT_SEQUENCE = 53,
+ SEC_OID_MISSI_KEA_DSS_OLD = 54,
+ SEC_OID_MISSI_DSS_OLD = 55,
+ SEC_OID_MISSI_KEA_DSS = 56,
+ SEC_OID_MISSI_DSS = 57,
+ SEC_OID_MISSI_KEA = 58,
+ SEC_OID_MISSI_ALT_KEA = 59,
+
+ /* Netscape private certificate extensions */
+ SEC_OID_NS_CERT_EXT_NETSCAPE_OK = 60,
+ SEC_OID_NS_CERT_EXT_ISSUER_LOGO = 61,
+ SEC_OID_NS_CERT_EXT_SUBJECT_LOGO = 62,
+ SEC_OID_NS_CERT_EXT_CERT_TYPE = 63,
+ SEC_OID_NS_CERT_EXT_BASE_URL = 64,
+ SEC_OID_NS_CERT_EXT_REVOCATION_URL = 65,
+ SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL = 66,
+ SEC_OID_NS_CERT_EXT_CA_CRL_URL = 67,
+ SEC_OID_NS_CERT_EXT_CA_CERT_URL = 68,
+ SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL = 69,
+ SEC_OID_NS_CERT_EXT_CA_POLICY_URL = 70,
+ SEC_OID_NS_CERT_EXT_HOMEPAGE_URL = 71,
+ SEC_OID_NS_CERT_EXT_ENTITY_LOGO = 72,
+ SEC_OID_NS_CERT_EXT_USER_PICTURE = 73,
+ SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME = 74,
+ SEC_OID_NS_CERT_EXT_COMMENT = 75,
+ SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL = 76,
+ SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME = 77,
+ SEC_OID_NS_KEY_USAGE_GOVT_APPROVED = 78,
+
+ /* x.509 v3 Extensions */
+ SEC_OID_X509_SUBJECT_DIRECTORY_ATTR = 79,
+ SEC_OID_X509_SUBJECT_KEY_ID = 80,
+ SEC_OID_X509_KEY_USAGE = 81,
+ SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD = 82,
+ SEC_OID_X509_SUBJECT_ALT_NAME = 83,
+ SEC_OID_X509_ISSUER_ALT_NAME = 84,
+ SEC_OID_X509_BASIC_CONSTRAINTS = 85,
+ SEC_OID_X509_NAME_CONSTRAINTS = 86,
+ SEC_OID_X509_CRL_DIST_POINTS = 87,
+ SEC_OID_X509_CERTIFICATE_POLICIES = 88,
+ SEC_OID_X509_POLICY_MAPPINGS = 89,
+ SEC_OID_X509_POLICY_CONSTRAINTS = 90,
+ SEC_OID_X509_AUTH_KEY_ID = 91,
+ SEC_OID_X509_EXT_KEY_USAGE = 92,
+ SEC_OID_X509_AUTH_INFO_ACCESS = 93,
+
+ SEC_OID_X509_CRL_NUMBER = 94,
+ SEC_OID_X509_REASON_CODE = 95,
+ SEC_OID_X509_INVALID_DATE = 96,
+ /* End of x.509 v3 Extensions */
+
+ SEC_OID_X500_RSA_ENCRYPTION = 97,
+
+ /* alg 1485 additions */
+ SEC_OID_RFC1274_UID = 98,
+ SEC_OID_RFC1274_MAIL = 99,
+
+ /* PKCS 12 additions */
+ SEC_OID_PKCS12 = 100,
+ SEC_OID_PKCS12_MODE_IDS = 101,
+ SEC_OID_PKCS12_ESPVK_IDS = 102,
+ SEC_OID_PKCS12_BAG_IDS = 103,
+ SEC_OID_PKCS12_CERT_BAG_IDS = 104,
+ SEC_OID_PKCS12_OIDS = 105,
+ SEC_OID_PKCS12_PBE_IDS = 106,
+ SEC_OID_PKCS12_SIGNATURE_IDS = 107,
+ SEC_OID_PKCS12_ENVELOPING_IDS = 108,
+ /* SEC_OID_PKCS12_OFFLINE_TRANSPORT_MODE,
+ SEC_OID_PKCS12_ONLINE_TRANSPORT_MODE, */
+ SEC_OID_PKCS12_PKCS8_KEY_SHROUDING = 109,
+ SEC_OID_PKCS12_KEY_BAG_ID = 110,
+ SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID = 111,
+ SEC_OID_PKCS12_SECRET_BAG_ID = 112,
+ SEC_OID_PKCS12_X509_CERT_CRL_BAG = 113,
+ SEC_OID_PKCS12_SDSI_CERT_BAG = 114,
+ SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4 = 115,
+ SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4 = 116,
+ SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC = 117,
+ SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC = 118,
+ SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC = 119,
+ SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_128_BIT_RC4 = 120,
+ SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_40_BIT_RC4 = 121,
+ SEC_OID_PKCS12_RSA_ENCRYPTION_WITH_TRIPLE_DES = 122,
+ SEC_OID_PKCS12_RSA_SIGNATURE_WITH_SHA1_DIGEST = 123,
+ /* end of PKCS 12 additions */
+
+ /* DSA signatures */
+ SEC_OID_ANSIX9_DSA_SIGNATURE = 124,
+ SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST = 125,
+ SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST = 126,
+
+ /* Verisign OIDs */
+ SEC_OID_VERISIGN_USER_NOTICES = 127,
+
+ /* PKIX OIDs */
+ SEC_OID_PKIX_CPS_POINTER_QUALIFIER = 128,
+ SEC_OID_PKIX_USER_NOTICE_QUALIFIER = 129,
+ SEC_OID_PKIX_OCSP = 130,
+ SEC_OID_PKIX_OCSP_BASIC_RESPONSE = 131,
+ SEC_OID_PKIX_OCSP_NONCE = 132,
+ SEC_OID_PKIX_OCSP_CRL = 133,
+ SEC_OID_PKIX_OCSP_RESPONSE = 134,
+ SEC_OID_PKIX_OCSP_NO_CHECK = 135,
+ SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF = 136,
+ SEC_OID_PKIX_OCSP_SERVICE_LOCATOR = 137,
+ SEC_OID_PKIX_REGCTRL_REGTOKEN = 138,
+ SEC_OID_PKIX_REGCTRL_AUTHENTICATOR = 139,
+ SEC_OID_PKIX_REGCTRL_PKIPUBINFO = 140,
+ SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS = 141,
+ SEC_OID_PKIX_REGCTRL_OLD_CERT_ID = 142,
+ SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY = 143,
+ SEC_OID_PKIX_REGINFO_UTF8_PAIRS = 144,
+ SEC_OID_PKIX_REGINFO_CERT_REQUEST = 145,
+ SEC_OID_EXT_KEY_USAGE_SERVER_AUTH = 146,
+ SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH = 147,
+ SEC_OID_EXT_KEY_USAGE_CODE_SIGN = 148,
+ SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT = 149,
+ SEC_OID_EXT_KEY_USAGE_TIME_STAMP = 150,
+ SEC_OID_OCSP_RESPONDER = 151,
+
+ /* Netscape Algorithm OIDs */
+ SEC_OID_NETSCAPE_SMIME_KEA = 152,
+
+ /* Skipjack OID -- ### mwelch temporary */
+ SEC_OID_FORTEZZA_SKIPJACK = 153,
+
+ /* PKCS 12 V2 oids */
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4 = 154,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4 = 155,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC = 156,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC = 157,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC = 158,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC = 159,
+ SEC_OID_PKCS12_SAFE_CONTENTS_ID = 160,
+ SEC_OID_PKCS12_PKCS8_SHROUDED_KEY_BAG_ID = 161,
+
+ SEC_OID_PKCS12_V1_KEY_BAG_ID = 162,
+ SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID = 163,
+ SEC_OID_PKCS12_V1_CERT_BAG_ID = 164,
+ SEC_OID_PKCS12_V1_CRL_BAG_ID = 165,
+ SEC_OID_PKCS12_V1_SECRET_BAG_ID = 166,
+ SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID = 167,
+ SEC_OID_PKCS9_X509_CERT = 168,
+ SEC_OID_PKCS9_SDSI_CERT = 169,
+ SEC_OID_PKCS9_X509_CRL = 170,
+ SEC_OID_PKCS9_FRIENDLY_NAME = 171,
+ SEC_OID_PKCS9_LOCAL_KEY_ID = 172,
+ SEC_OID_BOGUS_KEY_USAGE = 173,
+
+ /*Diffe Helman OIDS */
+ SEC_OID_X942_DIFFIE_HELMAN_KEY = 174,
+
+ /* Netscape other name types */
+ /* SEC_OID_NETSCAPE_NICKNAME is an otherName field of type IA5String
+ * in the subjectAltName certificate extension. NSS dropped support
+ * for SEC_OID_NETSCAPE_NICKNAME in NSS 3.13. */
+ SEC_OID_NETSCAPE_NICKNAME = 175,
+
+ /* Cert Server OIDS */
+ SEC_OID_NETSCAPE_RECOVERY_REQUEST = 176,
+
+ /* New PSM certificate management OIDs */
+ SEC_OID_CERT_RENEWAL_LOCATOR = 177,
+ SEC_OID_NS_CERT_EXT_SCOPE_OF_USE = 178,
+
+ /* CMS (RFC2630) OIDs */
+ SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN = 179,
+ SEC_OID_CMS_3DES_KEY_WRAP = 180,
+ SEC_OID_CMS_RC2_KEY_WRAP = 181,
+
+ /* SMIME attributes */
+ SEC_OID_SMIME_ENCRYPTION_KEY_PREFERENCE = 182,
+
+ /* AES OIDs */
+ SEC_OID_AES_128_ECB = 183,
+ SEC_OID_AES_128_CBC = 184,
+ SEC_OID_AES_192_ECB = 185,
+ SEC_OID_AES_192_CBC = 186,
+ SEC_OID_AES_256_ECB = 187,
+ SEC_OID_AES_256_CBC = 188,
+
+ SEC_OID_SDN702_DSA_SIGNATURE = 189,
+
+ SEC_OID_MS_SMIME_ENCRYPTION_KEY_PREFERENCE = 190,
+
+ SEC_OID_SHA256 = 191,
+ SEC_OID_SHA384 = 192,
+ SEC_OID_SHA512 = 193,
+
+ SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION = 194,
+ SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION = 195,
+ SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION = 196,
+
+ SEC_OID_AES_128_KEY_WRAP = 197,
+ SEC_OID_AES_192_KEY_WRAP = 198,
+ SEC_OID_AES_256_KEY_WRAP = 199,
+
+ /* Elliptic Curve Cryptography (ECC) OIDs */
+ SEC_OID_ANSIX962_EC_PUBLIC_KEY = 200,
+ SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE = 201,
+
+#define SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST \
+ SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE
+
+ /* ANSI X9.62 named elliptic curves (prime field) */
+ SEC_OID_ANSIX962_EC_PRIME192V1 = 202,
+ SEC_OID_ANSIX962_EC_PRIME192V2 = 203,
+ SEC_OID_ANSIX962_EC_PRIME192V3 = 204,
+ SEC_OID_ANSIX962_EC_PRIME239V1 = 205,
+ SEC_OID_ANSIX962_EC_PRIME239V2 = 206,
+ SEC_OID_ANSIX962_EC_PRIME239V3 = 207,
+ SEC_OID_ANSIX962_EC_PRIME256V1 = 208,
+
+ /* SECG named elliptic curves (prime field) */
+ SEC_OID_SECG_EC_SECP112R1 = 209,
+ SEC_OID_SECG_EC_SECP112R2 = 210,
+ SEC_OID_SECG_EC_SECP128R1 = 211,
+ SEC_OID_SECG_EC_SECP128R2 = 212,
+ SEC_OID_SECG_EC_SECP160K1 = 213,
+ SEC_OID_SECG_EC_SECP160R1 = 214,
+ SEC_OID_SECG_EC_SECP160R2 = 215,
+ SEC_OID_SECG_EC_SECP192K1 = 216,
+ /* SEC_OID_SECG_EC_SECP192R1 is SEC_OID_ANSIX962_EC_PRIME192V1 */
+ SEC_OID_SECG_EC_SECP224K1 = 217,
+ SEC_OID_SECG_EC_SECP224R1 = 218,
+ SEC_OID_SECG_EC_SECP256K1 = 219,
+ /* SEC_OID_SECG_EC_SECP256R1 is SEC_OID_ANSIX962_EC_PRIME256V1 */
+ SEC_OID_SECG_EC_SECP384R1 = 220,
+ SEC_OID_SECG_EC_SECP521R1 = 221,
+
+ /* ANSI X9.62 named elliptic curves (characteristic two field) */
+ SEC_OID_ANSIX962_EC_C2PNB163V1 = 222,
+ SEC_OID_ANSIX962_EC_C2PNB163V2 = 223,
+ SEC_OID_ANSIX962_EC_C2PNB163V3 = 224,
+ SEC_OID_ANSIX962_EC_C2PNB176V1 = 225,
+ SEC_OID_ANSIX962_EC_C2TNB191V1 = 226,
+ SEC_OID_ANSIX962_EC_C2TNB191V2 = 227,
+ SEC_OID_ANSIX962_EC_C2TNB191V3 = 228,
+ SEC_OID_ANSIX962_EC_C2ONB191V4 = 229,
+ SEC_OID_ANSIX962_EC_C2ONB191V5 = 230,
+ SEC_OID_ANSIX962_EC_C2PNB208W1 = 231,
+ SEC_OID_ANSIX962_EC_C2TNB239V1 = 232,
+ SEC_OID_ANSIX962_EC_C2TNB239V2 = 233,
+ SEC_OID_ANSIX962_EC_C2TNB239V3 = 234,
+ SEC_OID_ANSIX962_EC_C2ONB239V4 = 235,
+ SEC_OID_ANSIX962_EC_C2ONB239V5 = 236,
+ SEC_OID_ANSIX962_EC_C2PNB272W1 = 237,
+ SEC_OID_ANSIX962_EC_C2PNB304W1 = 238,
+ SEC_OID_ANSIX962_EC_C2TNB359V1 = 239,
+ SEC_OID_ANSIX962_EC_C2PNB368W1 = 240,
+ SEC_OID_ANSIX962_EC_C2TNB431R1 = 241,
+
+ /* SECG named elliptic curves (characteristic two field) */
+ SEC_OID_SECG_EC_SECT113R1 = 242,
+ SEC_OID_SECG_EC_SECT113R2 = 243,
+ SEC_OID_SECG_EC_SECT131R1 = 244,
+ SEC_OID_SECG_EC_SECT131R2 = 245,
+ SEC_OID_SECG_EC_SECT163K1 = 246,
+ SEC_OID_SECG_EC_SECT163R1 = 247,
+ SEC_OID_SECG_EC_SECT163R2 = 248,
+ SEC_OID_SECG_EC_SECT193R1 = 249,
+ SEC_OID_SECG_EC_SECT193R2 = 250,
+ SEC_OID_SECG_EC_SECT233K1 = 251,
+ SEC_OID_SECG_EC_SECT233R1 = 252,
+ SEC_OID_SECG_EC_SECT239K1 = 253,
+ SEC_OID_SECG_EC_SECT283K1 = 254,
+ SEC_OID_SECG_EC_SECT283R1 = 255,
+ SEC_OID_SECG_EC_SECT409K1 = 256,
+ SEC_OID_SECG_EC_SECT409R1 = 257,
+ SEC_OID_SECG_EC_SECT571K1 = 258,
+ SEC_OID_SECG_EC_SECT571R1 = 259,
+
+ SEC_OID_NETSCAPE_AOLSCREENNAME = 260,
+
+ SEC_OID_AVA_SURNAME = 261,
+ SEC_OID_AVA_SERIAL_NUMBER = 262,
+ SEC_OID_AVA_STREET_ADDRESS = 263,
+ SEC_OID_AVA_TITLE = 264,
+ SEC_OID_AVA_POSTAL_ADDRESS = 265,
+ SEC_OID_AVA_POSTAL_CODE = 266,
+ SEC_OID_AVA_POST_OFFICE_BOX = 267,
+ SEC_OID_AVA_GIVEN_NAME = 268,
+ SEC_OID_AVA_INITIALS = 269,
+ SEC_OID_AVA_GENERATION_QUALIFIER = 270,
+ SEC_OID_AVA_HOUSE_IDENTIFIER = 271,
+ SEC_OID_AVA_PSEUDONYM = 272,
+
+ /* More OIDs */
+ SEC_OID_PKIX_CA_ISSUERS = 273,
+ SEC_OID_PKCS9_EXTENSION_REQUEST = 274,
+
+ /* new EC Signature oids */
+ SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST = 275,
+ SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST = 276,
+ SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE = 277,
+ SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE = 278,
+ SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE = 279,
+ SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE = 280,
+
+ /* More id-ce and id-pe OIDs from RFC 3280 */
+ SEC_OID_X509_HOLD_INSTRUCTION_CODE = 281,
+ SEC_OID_X509_DELTA_CRL_INDICATOR = 282,
+ SEC_OID_X509_ISSUING_DISTRIBUTION_POINT = 283,
+ SEC_OID_X509_CERT_ISSUER = 284,
+ SEC_OID_X509_FRESHEST_CRL = 285,
+ SEC_OID_X509_INHIBIT_ANY_POLICY = 286,
+ SEC_OID_X509_SUBJECT_INFO_ACCESS = 287,
+
+ /* Camellia OIDs (RFC3657)*/
+ SEC_OID_CAMELLIA_128_CBC = 288,
+ SEC_OID_CAMELLIA_192_CBC = 289,
+ SEC_OID_CAMELLIA_256_CBC = 290,
+
+ /* PKCS 5 V2 OIDS */
+ SEC_OID_PKCS5_PBKDF2 = 291,
+ SEC_OID_PKCS5_PBES2 = 292,
+ SEC_OID_PKCS5_PBMAC1 = 293,
+ SEC_OID_HMAC_SHA1 = 294,
+ SEC_OID_HMAC_SHA224 = 295,
+ SEC_OID_HMAC_SHA256 = 296,
+ SEC_OID_HMAC_SHA384 = 297,
+ SEC_OID_HMAC_SHA512 = 298,
+
+ SEC_OID_PKIX_TIMESTAMPING = 299,
+ SEC_OID_PKIX_CA_REPOSITORY = 300,
+
+ SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE = 301,
+
+ SEC_OID_SEED_CBC = 302,
+
+ SEC_OID_X509_ANY_POLICY = 303,
+
+ SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION = 304,
+ SEC_OID_PKCS1_MGF1 = 305,
+ SEC_OID_PKCS1_PSPECIFIED = 306,
+ SEC_OID_PKCS1_RSA_PSS_SIGNATURE = 307,
+ SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION = 308,
+
+ SEC_OID_SHA224 = 309,
+
+ SEC_OID_EV_INCORPORATION_LOCALITY = 310,
+ SEC_OID_EV_INCORPORATION_STATE = 311,
+ SEC_OID_EV_INCORPORATION_COUNTRY = 312,
+ SEC_OID_BUSINESS_CATEGORY = 313,
+
+ SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST = 314,
+ SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST = 315,
+
+ /* Microsoft Trust List Signing
+ * szOID_KP_CTL_USAGE_SIGNING
+ * where KP stands for Key Purpose
+ */
+ SEC_OID_MS_EXT_KEY_USAGE_CTL_SIGNING = 316,
+
+ /* The 'name' attribute type in X.520 */
+ SEC_OID_AVA_NAME = 317,
+
+ SEC_OID_AES_128_GCM = 318,
+ SEC_OID_AES_192_GCM = 319,
+ SEC_OID_AES_256_GCM = 320,
+ SEC_OID_IDEA_CBC = 321,
+
+ /* pseudo - OIDs */
+
+ SEC_OID_RC2_40_CBC = 322,
+ SEC_OID_DES_40_CBC = 323,
+ SEC_OID_RC4_40 = 324,
+ SEC_OID_RC4_56 = 325,
+ SEC_OID_NULL_CIPHER = 326,
+
+ SEC_OID_HMAC_MD5 = 327,
+
+ SEC_OID_TLS_RSA = 328,
+ SEC_OID_TLS_DHE_RSA = 329,
+ SEC_OID_TLS_DHE_DSS = 330,
+ SEC_OID_TLS_DH_RSA = 331,
+ SEC_OID_TLS_DH_DSS = 332,
+ SEC_OID_TLS_DH_ANON = 333,
+ SEC_OID_TLS_ECDHE_ECDSA = 334,
+ SEC_OID_TLS_ECDHE_RSA = 335,
+ SEC_OID_TLS_ECDH_ECDSA = 336,
+ SEC_OID_TLS_ECDH_RSA = 337,
+ SEC_OID_TLS_ECDH_ANON = 338,
+ SEC_OID_TLS_RSA_EXPORT = 339,
+
+ SEC_OID_TLS_DHE_RSA_EXPORT = 340,
+ SEC_OID_TLS_DHE_DSS_EXPORT = 341,
+ SEC_OID_TLS_DH_RSA_EXPORT = 342,
+ SEC_OID_TLS_DH_DSS_EXPORT = 343,
+ SEC_OID_TLS_DH_ANON_EXPORT = 344,
+ SEC_OID_APPLY_SSL_POLICY = 345,
+
+ SEC_OID_CHACHA20_POLY1305 = 346,
+
+ SEC_OID_TLS_ECDHE_PSK = 347,
+ SEC_OID_TLS_DHE_PSK = 348,
+
+ SEC_OID_TLS_FFDHE_2048 = 349,
+ SEC_OID_TLS_FFDHE_3072 = 350,
+ SEC_OID_TLS_FFDHE_4096 = 351,
+ SEC_OID_TLS_FFDHE_6144 = 352,
+ SEC_OID_TLS_FFDHE_8192 = 353,
+ SEC_OID_TLS_DHE_CUSTOM = 354,
+
+ SEC_OID_CURVE25519 = 355,
+
+ SEC_OID_TLS13_KEA_ANY = 356,
+
+ SEC_OID_X509_ANY_EXT_KEY_USAGE = 357,
+ SEC_OID_EXT_KEY_USAGE_IPSEC_IKE = 358,
+ SEC_OID_IPSEC_IKE_END = 359,
+ SEC_OID_IPSEC_IKE_INTERMEDIATE = 360,
+ SEC_OID_EXT_KEY_USAGE_IPSEC_END = 361,
+ SEC_OID_EXT_KEY_USAGE_IPSEC_TUNNEL = 362,
+ SEC_OID_EXT_KEY_USAGE_IPSEC_USER = 363,
+
+ SEC_OID_SHA3_224 = 364,
+ SEC_OID_SHA3_256 = 365,
+ SEC_OID_SHA3_384 = 366,
+ SEC_OID_SHA3_512 = 367,
+
+ SEC_OID_HMAC_SHA3_224 = 368,
+ SEC_OID_HMAC_SHA3_256 = 369,
+ SEC_OID_HMAC_SHA3_384 = 370,
+ SEC_OID_HMAC_SHA3_512 = 371,
+
+ SEC_OID_XYBER768D00 = 372,
+
+ SEC_OID_TOTAL
+} SECOidTag;
+
+#define SEC_OID_SECG_EC_SECP192R1 SEC_OID_ANSIX962_EC_PRIME192V1
+#define SEC_OID_SECG_EC_SECP256R1 SEC_OID_ANSIX962_EC_PRIME256V1
+#define SEC_OID_PKCS12_KEY_USAGE SEC_OID_X509_KEY_USAGE
+
+/* fake OID for DSS sign/verify */
+#define SEC_OID_SHA SEC_OID_MISS_DSS
+
+typedef enum {
+ INVALID_CERT_EXTENSION = 0,
+ UNSUPPORTED_CERT_EXTENSION = 1,
+ SUPPORTED_CERT_EXTENSION = 2
+} SECSupportExtenTag;
+
+struct SECOidDataStr {
+ SECItem oid;
+ SECOidTag offset;
+ const char* desc;
+ unsigned long mechanism;
+ SECSupportExtenTag supportedExtension;
+ /* only used for x.509 v3 extensions, so
+ that we can print the names of those
+ extensions that we don't even support */
+};
+
+/* New Opaque extended OID table API.
+ * These are algorithm policy Flags, used with functions
+ * NSS_SetAlgorithmPolicy & NSS_GetAlgorithmPolicy.
+ */
+#define NSS_USE_ALG_IN_CERT_SIGNATURE 0x00000001 /* CRLs and OCSP, too */
+#define NSS_USE_ALG_IN_CMS_SIGNATURE 0x00000002 /* used in S/MIME */
+#define NSS_USE_ALG_IN_SSL_KX 0x00000004 /* used in SSL key exchange */
+#define NSS_USE_ALG_IN_SSL 0x00000008 /* used in SSL record protocol */
+#define NSS_USE_POLICY_IN_SSL 0x00000010 /* enable policy in SSL protocol */
+#define NSS_USE_ALG_IN_ANY_SIGNATURE 0x00000020 /* used in any signature */
+#define NSS_USE_ALG_IN_PKCS12 0x00000040 /* used in pkcs12 */
+#define NSS_USE_DEFAULT_NOT_VALID 0x80000000 /* clear to make the default flag valid */
+#define NSS_USE_DEFAULT_SSL_ENABLE 0x40000000 /* default cipher suite setting 1=enable */
+
+/* Combo policy bites */
+#define NSS_USE_ALG_RESERVED 0x3fffffc0 /* may be used in future */
+/* Alias of all the signature values. */
+#define NSS_USE_ALG_IN_SIGNATURE (NSS_USE_ALG_IN_CERT_SIGNATURE | \
+ NSS_USE_ALG_IN_CMS_SIGNATURE | \
+ NSS_USE_ALG_IN_ANY_SIGNATURE)
+/* all the bits needed for a certificate signature
+ * and only the bits needed for a certificate signature */
+#define NSS_USE_CERT_SIGNATURE_OK (NSS_USE_ALG_IN_CERT_SIGNATURE | \
+ NSS_USE_ALG_IN_ANY_SIGNATURE)
+/* all the bits needed for an SMIME signature
+ * and only the bits needed for an SMIME signature */
+#define NSS_USE_CMS_SIGNATURE_OK (NSS_USE_ALG_IN_CMS_SIGNATURE | \
+ NSS_USE_ALG_IN_ANY_SIGNATURE)
+
+/* Code MUST NOT SET or CLEAR reserved bits, and must NOT depend on them
+ * being all zeros or having any other known value. The reserved bits
+ * must be ignored.
+ */
+
+#endif /* _SECOIDT_H_ */
diff --git a/security/nss/lib/util/secplcy.c b/security/nss/lib/util/secplcy.c
new file mode 100644
index 0000000000..0c784d0553
--- /dev/null
+++ b/security/nss/lib/util/secplcy.c
@@ -0,0 +1,83 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 "secplcy.h"
+#include "prmem.h"
+
+SECCipherFind *
+sec_CipherFindInit(PRBool onlyAllowed,
+ secCPStruct *policy,
+ long *ciphers)
+{
+ SECCipherFind *find = PR_NEWZAP(SECCipherFind);
+ if (find) {
+ find->policy = policy;
+ find->ciphers = ciphers;
+ find->onlyAllowed = onlyAllowed;
+ find->index = -1;
+ }
+ return find;
+}
+
+long
+sec_CipherFindNext(SECCipherFind *find)
+{
+ char *policy;
+ long rv = -1;
+ secCPStruct *policies = (secCPStruct *)find->policy;
+ long *ciphers = (long *)find->ciphers;
+ long numCiphers = policies->num_ciphers;
+
+ find->index++;
+ while ((find->index < numCiphers) && (rv == -1)) {
+ /* Translate index to cipher. */
+ rv = ciphers[find->index];
+
+ /* If we're only looking for allowed ciphers, and if this
+ cipher isn't allowed, loop around.*/
+ if (find->onlyAllowed) {
+ /* Find the appropriate policy flag. */
+ policy = (&(policies->begin_ciphers)) + find->index + 1;
+
+ /* If this cipher isn't allowed by policy, continue. */
+ if (!(*policy)) {
+ rv = -1;
+ find->index++;
+ }
+ }
+ }
+
+ return rv;
+}
+
+char
+sec_IsCipherAllowed(long cipher, secCPStruct *policies,
+ long *ciphers)
+{
+ char result = SEC_CIPHER_NOT_ALLOWED; /* our default answer */
+ long numCiphers = policies->num_ciphers;
+ char *policy;
+ int i;
+
+ /* Convert the cipher number into a policy flag location. */
+ for (i = 0, policy = (&(policies->begin_ciphers) + 1);
+ i < numCiphers;
+ i++, policy++) {
+ if (cipher == ciphers[i])
+ break;
+ }
+
+ if (i < numCiphers) {
+ /* Found the cipher, get the policy value. */
+ result = *policy;
+ }
+
+ return result;
+}
+
+void
+sec_CipherFindEnd(SECCipherFind *find)
+{
+ PR_FREEIF(find);
+}
diff --git a/security/nss/lib/util/secplcy.h b/security/nss/lib/util/secplcy.h
new file mode 100644
index 0000000000..6a85e03f11
--- /dev/null
+++ b/security/nss/lib/util/secplcy.h
@@ -0,0 +1,104 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __secplcy_h__
+#define __secplcy_h__
+
+#include "utilrename.h"
+
+#include "prtypes.h"
+
+/*
+** Cipher policy enforcement. This code isn't very pretty, but it accomplishes
+** the purpose of obscuring policy information from potential fortifiers. :-)
+**
+** The following routines are generic and intended for anywhere where cipher
+** policy enforcement is to be done, e.g. SSL and PKCS7&12.
+*/
+
+#define SEC_CIPHER_NOT_ALLOWED 0
+#define SEC_CIPHER_ALLOWED 1
+#define SEC_CIPHER_RESTRICTED 2 /* cipher is allowed in limited cases \
+ e.g. step-up */
+
+/* The length of the header string for each cipher table.
+ (It's the same regardless of whether we're using md5 strings or not.) */
+#define SEC_POLICY_HEADER_LENGTH 48
+
+/* If we're testing policy stuff, we may want to use the plaintext version */
+#define SEC_POLICY_USE_MD5_STRINGS 1
+
+#define SEC_POLICY_THIS_IS_THE \
+ "\x2a\x3a\x51\xbf\x2f\x71\xb7\x73\xaa\xca\x6b\x57\x70\xcd\xc8\x9f"
+#define SEC_POLICY_STRING_FOR_THE \
+ "\x97\x15\xe2\x70\xd2\x8a\xde\xa9\xe7\xa7\x6a\xe2\x83\xe5\xb1\xf6"
+#define SEC_POLICY_SSL_TAIL \
+ "\x70\x16\x25\xc0\x2a\xb2\x4a\xca\xb6\x67\xb1\x89\x20\xdf\x87\xca"
+#define SEC_POLICY_SMIME_TAIL \
+ "\xdf\xd4\xe7\x2a\xeb\xc4\x1b\xb5\xd8\xe5\xe0\x2a\x16\x9f\xc4\xb9"
+#define SEC_POLICY_PKCS12_TAIL \
+ "\x1c\xf8\xa4\x85\x4a\xc6\x8a\xfe\xe6\xca\x03\x72\x50\x1c\xe2\xc8"
+
+#if defined(SEC_POLICY_USE_MD5_STRINGS)
+
+/* We're not testing.
+ Use md5 checksums of the strings. */
+
+#define SEC_POLICY_SSL_HEADER \
+ SEC_POLICY_THIS_IS_THE SEC_POLICY_STRING_FOR_THE SEC_POLICY_SSL_TAIL
+
+#define SEC_POLICY_SMIME_HEADER \
+ SEC_POLICY_THIS_IS_THE SEC_POLICY_STRING_FOR_THE SEC_POLICY_SMIME_TAIL
+
+#define SEC_POLICY_PKCS12_HEADER \
+ SEC_POLICY_THIS_IS_THE SEC_POLICY_STRING_FOR_THE SEC_POLICY_PKCS12_TAIL
+
+#else
+
+/* We're testing.
+ Use plaintext versions of the strings, for testing purposes. */
+#define SEC_POLICY_SSL_HEADER \
+ "This is the string for the SSL policy table. "
+#define SEC_POLICY_SMIME_HEADER \
+ "This is the string for the PKCS7 policy table. "
+#define SEC_POLICY_PKCS12_HEADER \
+ "This is the string for the PKCS12 policy table. "
+
+#endif
+
+/* Local cipher tables have to have these members at the top. */
+typedef struct _sec_cp_struct {
+ char policy_string[SEC_POLICY_HEADER_LENGTH];
+ long unused; /* placeholder for max keybits in pkcs12 struct */
+ char num_ciphers;
+ char begin_ciphers;
+ /* cipher policy settings follow. each is a char. */
+} secCPStruct;
+
+struct SECCipherFindStr {
+ /* (policy) and (ciphers) are opaque to the outside world */
+ void *policy;
+ void *ciphers;
+ long index;
+ PRBool onlyAllowed;
+};
+
+typedef struct SECCipherFindStr SECCipherFind;
+
+SEC_BEGIN_PROTOS
+
+SECCipherFind *sec_CipherFindInit(PRBool onlyAllowed,
+ secCPStruct *policy,
+ long *ciphers);
+
+long sec_CipherFindNext(SECCipherFind *find);
+
+char sec_IsCipherAllowed(long cipher, secCPStruct *policies,
+ long *ciphers);
+
+void sec_CipherFindEnd(SECCipherFind *find);
+
+SEC_END_PROTOS
+
+#endif /* __SECPLCY_H__ */
diff --git a/security/nss/lib/util/secport.c b/security/nss/lib/util/secport.c
new file mode 100644
index 0000000000..30215a80f9
--- /dev/null
+++ b/security/nss/lib/util/secport.c
@@ -0,0 +1,925 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * secport.c - portability interfaces for security libraries
+ *
+ * This file abstracts out libc functionality that libsec depends on
+ *
+ * NOTE - These are not public interfaces
+ */
+
+#include "seccomon.h"
+#include "prmem.h"
+#include "prerror.h"
+#include "plarena.h"
+#include "secerr.h"
+#include "prmon.h"
+#include "nssilock.h"
+#include "secport.h"
+#include "prenv.h"
+#include "prinit.h"
+
+#include <stdint.h>
+
+#ifdef DEBUG
+#define THREADMARK
+#endif /* DEBUG */
+
+#ifdef THREADMARK
+#include "prthread.h"
+#endif /* THREADMARK */
+
+#if defined(XP_UNIX) || defined(XP_OS2)
+#include <stdlib.h>
+#else
+#include "wtypes.h"
+#endif
+
+#define SET_ERROR_CODE /* place holder for code to set PR error code. */
+
+#ifdef THREADMARK
+typedef struct threadmark_mark_str {
+ struct threadmark_mark_str *next;
+ void *mark;
+} threadmark_mark;
+
+#endif /* THREADMARK */
+
+/* The value of this magic must change each time PORTArenaPool changes. */
+#define ARENAPOOL_MAGIC 0xB8AC9BDF
+
+#define CHEAP_ARENAPOOL_MAGIC 0x3F16BB09
+
+typedef struct PORTArenaPool_str {
+ PLArenaPool arena;
+ PRUint32 magic;
+ PRLock *lock;
+#ifdef THREADMARK
+ PRThread *marking_thread;
+ threadmark_mark *first_mark;
+#endif
+} PORTArenaPool;
+
+/* locations for registering Unicode conversion functions.
+ * XXX is this the appropriate location? or should they be
+ * moved to client/server specific locations?
+ */
+PORTCharConversionFunc ucs4Utf8ConvertFunc;
+PORTCharConversionFunc ucs2Utf8ConvertFunc;
+PORTCharConversionWSwapFunc ucs2AsciiConvertFunc;
+
+/* NSPR memory allocation functions (PR_Malloc, PR_Calloc, and PR_Realloc)
+ * use the PRUint32 type for the size parameter. Before we pass a size_t or
+ * unsigned long size to these functions, we need to ensure it is <= half of
+ * the maximum PRUint32 value to avoid truncation and catch a negative size.
+ */
+#define MAX_SIZE (PR_UINT32_MAX >> 1)
+
+void *
+PORT_Alloc(size_t bytes)
+{
+ void *rv = NULL;
+
+ if (bytes <= MAX_SIZE) {
+ /* Always allocate a non-zero amount of bytes */
+ rv = PR_Malloc(bytes ? bytes : 1);
+ }
+ if (!rv) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ }
+ return rv;
+}
+
+void *
+PORT_Realloc(void *oldptr, size_t bytes)
+{
+ void *rv = NULL;
+
+ if (bytes <= MAX_SIZE) {
+ rv = PR_Realloc(oldptr, bytes);
+ }
+ if (!rv) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ }
+ return rv;
+}
+
+void *
+PORT_ZAlloc(size_t bytes)
+{
+ void *rv = NULL;
+
+ if (bytes <= MAX_SIZE) {
+ /* Always allocate a non-zero amount of bytes */
+ rv = PR_Calloc(1, bytes ? bytes : 1);
+ }
+ if (!rv) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ }
+ return rv;
+}
+
+/* aligned_alloc is C11. This is an alternative to get aligned memory. */
+void *
+PORT_ZAllocAligned(size_t bytes, size_t alignment, void **mem)
+{
+ size_t x = alignment - 1;
+
+ /* This only works if alignment is a power of 2. */
+ if ((alignment == 0) || (alignment & (alignment - 1))) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ if (!mem) {
+ return NULL;
+ }
+
+ /* Always allocate a non-zero amount of bytes */
+ *mem = PORT_ZAlloc((bytes ? bytes : 1) + x);
+ if (!*mem) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+
+ return (void *)(((uintptr_t)*mem + x) & ~(uintptr_t)x);
+}
+
+void *
+PORT_ZAllocAlignedOffset(size_t size, size_t alignment, size_t offset)
+{
+ PORT_Assert(offset < size);
+ if (offset > size) {
+ return NULL;
+ }
+
+ void *mem = NULL;
+ void *v = PORT_ZAllocAligned(size, alignment, &mem);
+ if (!v) {
+ return NULL;
+ }
+
+ PORT_Assert(mem);
+ *((void **)((uintptr_t)v + offset)) = mem;
+ return v;
+}
+
+void
+PORT_Free(void *ptr)
+{
+ if (ptr) {
+ PR_Free(ptr);
+ }
+}
+
+void
+PORT_ZFree(void *ptr, size_t len)
+{
+ if (ptr) {
+ memset(ptr, 0, len);
+ PR_Free(ptr);
+ }
+}
+
+char *
+PORT_Strdup(const char *str)
+{
+ size_t len = PORT_Strlen(str) + 1;
+ char *newstr;
+
+ newstr = (char *)PORT_Alloc(len);
+ if (newstr) {
+ PORT_Memcpy(newstr, str, len);
+ }
+ return newstr;
+}
+
+void
+PORT_SetError(int value)
+{
+ PR_SetError(value, 0);
+ return;
+}
+
+int
+PORT_GetError(void)
+{
+ return (PR_GetError());
+}
+
+/********************* Arena code follows *****************************
+ * ArenaPools are like heaps. The memory in them consists of large blocks,
+ * called arenas, which are allocated from the/a system heap. Inside an
+ * ArenaPool, the arenas are organized as if they were in a stack. Newly
+ * allocated arenas are "pushed" on that stack. When you attempt to
+ * allocate memory from an ArenaPool, the code first looks to see if there
+ * is enough unused space in the top arena on the stack to satisfy your
+ * request, and if so, your request is satisfied from that arena.
+ * Otherwise, a new arena is allocated (or taken from NSPR's list of freed
+ * arenas) and pushed on to the stack. The new arena is always big enough
+ * to satisfy the request, and is also at least a minimum size that is
+ * established at the time that the ArenaPool is created.
+ *
+ * The ArenaMark function returns the address of a marker in the arena at
+ * the top of the arena stack. It is the address of the place in the arena
+ * on the top of the arena stack from which the next block of memory will
+ * be allocated. Each ArenaPool has its own separate stack, and hence
+ * marks are only relevant to the ArenaPool from which they are gotten.
+ * Marks may be nested. That is, a thread can get a mark, and then get
+ * another mark.
+ *
+ * It is intended that all the marks in an ArenaPool may only be owned by a
+ * single thread. In DEBUG builds, this is enforced. In non-DEBUG builds,
+ * it is not. In DEBUG builds, when a thread gets a mark from an
+ * ArenaPool, no other thread may acquire a mark in that ArenaPool while
+ * that mark exists, that is, until that mark is unmarked or released.
+ * Therefore, it is important that every mark be unmarked or released when
+ * the creating thread has no further need for exclusive ownership of the
+ * right to manage the ArenaPool.
+ *
+ * The ArenaUnmark function discards the ArenaMark at the address given,
+ * and all marks nested inside that mark (that is, acquired from that same
+ * ArenaPool while that mark existed). It is an error for a thread other
+ * than the mark's creator to try to unmark it. When a thread has unmarked
+ * all its marks from an ArenaPool, then another thread is able to set
+ * marks in that ArenaPool. ArenaUnmark does not deallocate (or "pop") any
+ * memory allocated from the ArenaPool since the mark was created.
+ *
+ * ArenaRelease "pops" the stack back to the mark, deallocating all the
+ * memory allocated from the arenas in the ArenaPool since that mark was
+ * created, and removing any arenas from the ArenaPool that have no
+ * remaining active allocations when that is done. It implicitly releases
+ * any marks nested inside the mark being explicitly released. It is the
+ * only operation, other than destroying the arenapool, that potentially
+ * reduces the number of arenas on the stack. Otherwise, the stack grows
+ * until the arenapool is destroyed, at which point all the arenas are
+ * freed or returned to a "free arena list", depending on their sizes.
+ */
+PLArenaPool *
+PORT_NewArena(unsigned long chunksize)
+{
+ PORTArenaPool *pool;
+
+ if (chunksize > MAX_SIZE) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+ pool = PORT_ZNew(PORTArenaPool);
+ if (!pool) {
+ return NULL;
+ }
+ pool->magic = ARENAPOOL_MAGIC;
+ pool->lock = PZ_NewLock(nssILockArena);
+ if (!pool->lock) {
+ PORT_Free(pool);
+ return NULL;
+ }
+ PL_InitArenaPool(&pool->arena, "security", chunksize, sizeof(double));
+ return (&pool->arena);
+}
+
+void
+PORT_InitCheapArena(PORTCheapArenaPool *pool, unsigned long chunksize)
+{
+ pool->magic = CHEAP_ARENAPOOL_MAGIC;
+ PL_InitArenaPool(&pool->arena, "security", chunksize, sizeof(double));
+}
+
+void *
+PORT_ArenaAlloc(PLArenaPool *arena, size_t size)
+{
+ void *p = NULL;
+
+ PORTArenaPool *pool = (PORTArenaPool *)arena;
+
+ if (size <= 0) {
+ size = 1;
+ }
+
+ if (size > MAX_SIZE) {
+ /* you lose. */
+ } else
+ /* Is it one of ours? Assume so and check the magic */
+ if (ARENAPOOL_MAGIC == pool->magic) {
+ PZ_Lock(pool->lock);
+#ifdef THREADMARK
+ /* Most likely one of ours. Is there a thread id? */
+ if (pool->marking_thread &&
+ pool->marking_thread != PR_GetCurrentThread()) {
+ /* Another thread holds a mark in this arena */
+ PZ_Unlock(pool->lock);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ PORT_Assert(0);
+ return NULL;
+ } /* tid != null */
+#endif /* THREADMARK */
+ PL_ARENA_ALLOCATE(p, arena, size);
+ PZ_Unlock(pool->lock);
+ } else {
+ PL_ARENA_ALLOCATE(p, arena, size);
+ }
+
+ if (!p) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ }
+
+ return (p);
+}
+
+void *
+PORT_ArenaZAlloc(PLArenaPool *arena, size_t size)
+{
+ void *p;
+
+ if (size <= 0)
+ size = 1;
+
+ p = PORT_ArenaAlloc(arena, size);
+
+ if (p) {
+ PORT_Memset(p, 0, size);
+ }
+
+ return (p);
+}
+
+static PRCallOnceType setupUseFreeListOnce;
+static PRBool useFreeList;
+
+static PRStatus
+SetupUseFreeList(void)
+{
+ useFreeList = (PR_GetEnvSecure("NSS_DISABLE_ARENA_FREE_LIST") == NULL);
+ return PR_SUCCESS;
+}
+
+/*
+ * If zero is true, zeroize the arena memory before freeing it.
+ */
+void
+PORT_FreeArena(PLArenaPool *arena, PRBool zero)
+{
+ PORTArenaPool *pool = (PORTArenaPool *)arena;
+ PRLock *lock = (PRLock *)0;
+ size_t len = sizeof *arena;
+
+ if (!pool)
+ return;
+ if (ARENAPOOL_MAGIC == pool->magic) {
+ len = sizeof *pool;
+ lock = pool->lock;
+ PZ_Lock(lock);
+ }
+ if (zero) {
+ PL_ClearArenaPool(arena, 0);
+ }
+ (void)PR_CallOnce(&setupUseFreeListOnce, &SetupUseFreeList);
+ if (useFreeList) {
+ PL_FreeArenaPool(arena);
+ } else {
+ PL_FinishArenaPool(arena);
+ }
+ PORT_ZFree(arena, len);
+ if (lock) {
+ PZ_Unlock(lock);
+ PZ_DestroyLock(lock);
+ }
+}
+
+void
+PORT_DestroyCheapArena(PORTCheapArenaPool *pool)
+{
+ (void)PR_CallOnce(&setupUseFreeListOnce, &SetupUseFreeList);
+ if (useFreeList) {
+ PL_FreeArenaPool(&pool->arena);
+ } else {
+ PL_FinishArenaPool(&pool->arena);
+ }
+}
+
+void *
+PORT_ArenaGrow(PLArenaPool *arena, void *ptr, size_t oldsize, size_t newsize)
+{
+ PORTArenaPool *pool = (PORTArenaPool *)arena;
+ PORT_Assert(newsize >= oldsize);
+
+ if (newsize > MAX_SIZE) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+
+ if (ARENAPOOL_MAGIC == pool->magic) {
+ PZ_Lock(pool->lock);
+ /* Do we do a THREADMARK check here? */
+ PL_ARENA_GROW(ptr, arena, oldsize, (newsize - oldsize));
+ PZ_Unlock(pool->lock);
+ } else {
+ PL_ARENA_GROW(ptr, arena, oldsize, (newsize - oldsize));
+ }
+
+ return (ptr);
+}
+
+void *
+PORT_ArenaMark(PLArenaPool *arena)
+{
+ void *result;
+
+ PORTArenaPool *pool = (PORTArenaPool *)arena;
+ if (ARENAPOOL_MAGIC == pool->magic) {
+ PZ_Lock(pool->lock);
+#ifdef THREADMARK
+ {
+ threadmark_mark *tm, **pw;
+ PRThread *currentThread = PR_GetCurrentThread();
+
+ if (!pool->marking_thread) {
+ /* First mark */
+ pool->marking_thread = currentThread;
+ } else if (currentThread != pool->marking_thread) {
+ PZ_Unlock(pool->lock);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ PORT_Assert(0);
+ return NULL;
+ }
+
+ result = PL_ARENA_MARK(arena);
+ PL_ARENA_ALLOCATE(tm, arena, sizeof(threadmark_mark));
+ if (!tm) {
+ PZ_Unlock(pool->lock);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+
+ tm->mark = result;
+ tm->next = (threadmark_mark *)NULL;
+
+ pw = &pool->first_mark;
+ while (*pw) {
+ pw = &(*pw)->next;
+ }
+
+ *pw = tm;
+ }
+#else /* THREADMARK */
+ result = PL_ARENA_MARK(arena);
+#endif /* THREADMARK */
+ PZ_Unlock(pool->lock);
+ } else {
+ /* a "pure" NSPR arena */
+ result = PL_ARENA_MARK(arena);
+ }
+ return result;
+}
+
+/*
+ * This function accesses the internals of PLArena, which is why it needs
+ * to use the NSPR internal macro PL_MAKE_MEM_UNDEFINED before the memset
+ * calls.
+ *
+ * We should move this function to NSPR as PL_ClearArenaAfterMark or add
+ * a PL_ARENA_CLEAR_AND_RELEASE macro.
+ *
+ * TODO: remove the #ifdef PL_MAKE_MEM_UNDEFINED tests when NSPR 4.10+ is
+ * widely available.
+ */
+static void
+port_ArenaZeroAfterMark(PLArenaPool *arena, void *mark)
+{
+ PLArena *a = arena->current;
+ if (a->base <= (PRUword)mark && (PRUword)mark <= a->avail) {
+/* fast path: mark falls in the current arena */
+#ifdef PL_MAKE_MEM_UNDEFINED
+ PL_MAKE_MEM_UNDEFINED(mark, a->avail - (PRUword)mark);
+#endif
+ memset(mark, 0, a->avail - (PRUword)mark);
+ } else {
+ /* slow path: need to find the arena that mark falls in */
+ for (a = arena->first.next; a; a = a->next) {
+ PR_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+ if (a->base <= (PRUword)mark && (PRUword)mark <= a->avail) {
+#ifdef PL_MAKE_MEM_UNDEFINED
+ PL_MAKE_MEM_UNDEFINED(mark, a->avail - (PRUword)mark);
+#endif
+ memset(mark, 0, a->avail - (PRUword)mark);
+ a = a->next;
+ break;
+ }
+ }
+ for (; a; a = a->next) {
+ PR_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+#ifdef PL_MAKE_MEM_UNDEFINED
+ PL_MAKE_MEM_UNDEFINED((void *)a->base, a->avail - a->base);
+#endif
+ memset((void *)a->base, 0, a->avail - a->base);
+ }
+ }
+}
+
+static void
+port_ArenaRelease(PLArenaPool *arena, void *mark, PRBool zero)
+{
+ PORTArenaPool *pool = (PORTArenaPool *)arena;
+ if (ARENAPOOL_MAGIC == pool->magic) {
+ PZ_Lock(pool->lock);
+#ifdef THREADMARK
+ {
+ threadmark_mark **pw;
+
+ if (PR_GetCurrentThread() != pool->marking_thread) {
+ PZ_Unlock(pool->lock);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ PORT_Assert(0);
+ return /* no error indication available */;
+ }
+
+ pw = &pool->first_mark;
+ while (*pw && (mark != (*pw)->mark)) {
+ pw = &(*pw)->next;
+ }
+
+ if (!*pw) {
+ /* bad mark */
+ PZ_Unlock(pool->lock);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ PORT_Assert(0);
+ return /* no error indication available */;
+ }
+
+ *pw = (threadmark_mark *)NULL;
+
+ if (zero) {
+ port_ArenaZeroAfterMark(arena, mark);
+ }
+ PL_ARENA_RELEASE(arena, mark);
+
+ if (!pool->first_mark) {
+ pool->marking_thread = (PRThread *)NULL;
+ }
+ }
+#else /* THREADMARK */
+ if (zero) {
+ port_ArenaZeroAfterMark(arena, mark);
+ }
+ PL_ARENA_RELEASE(arena, mark);
+#endif /* THREADMARK */
+ PZ_Unlock(pool->lock);
+ } else {
+ if (zero) {
+ port_ArenaZeroAfterMark(arena, mark);
+ }
+ PL_ARENA_RELEASE(arena, mark);
+ }
+}
+
+void
+PORT_ArenaRelease(PLArenaPool *arena, void *mark)
+{
+ port_ArenaRelease(arena, mark, PR_FALSE);
+}
+
+/*
+ * Zeroize the arena memory before releasing it.
+ */
+void
+PORT_ArenaZRelease(PLArenaPool *arena, void *mark)
+{
+ port_ArenaRelease(arena, mark, PR_TRUE);
+}
+
+void
+PORT_ArenaUnmark(PLArenaPool *arena, void *mark)
+{
+#ifdef THREADMARK
+ PORTArenaPool *pool = (PORTArenaPool *)arena;
+ if (ARENAPOOL_MAGIC == pool->magic) {
+ threadmark_mark **pw;
+
+ PZ_Lock(pool->lock);
+
+ if (PR_GetCurrentThread() != pool->marking_thread) {
+ PZ_Unlock(pool->lock);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ PORT_Assert(0);
+ return /* no error indication available */;
+ }
+
+ pw = &pool->first_mark;
+ while (((threadmark_mark *)NULL != *pw) && (mark != (*pw)->mark)) {
+ pw = &(*pw)->next;
+ }
+
+ if ((threadmark_mark *)NULL == *pw) {
+ /* bad mark */
+ PZ_Unlock(pool->lock);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ PORT_Assert(0);
+ return /* no error indication available */;
+ }
+
+ *pw = (threadmark_mark *)NULL;
+
+ if (!pool->first_mark) {
+ pool->marking_thread = (PRThread *)NULL;
+ }
+
+ PZ_Unlock(pool->lock);
+ }
+#endif /* THREADMARK */
+}
+
+char *
+PORT_ArenaStrdup(PLArenaPool *arena, const char *str)
+{
+ int len = PORT_Strlen(str) + 1;
+ char *newstr;
+
+ newstr = (char *)PORT_ArenaAlloc(arena, len);
+ if (newstr) {
+ PORT_Memcpy(newstr, str, len);
+ }
+ return newstr;
+}
+
+/********************** end of arena functions ***********************/
+
+/****************** unicode conversion functions ***********************/
+/*
+ * NOTE: These conversion functions all assume that the multibyte
+ * characters are going to be in NETWORK BYTE ORDER, not host byte
+ * order. This is because the only time we deal with UCS-2 and UCS-4
+ * are when the data was received from or is going to be sent out
+ * over the wire (in, e.g. certificates).
+ */
+
+void
+PORT_SetUCS4_UTF8ConversionFunction(PORTCharConversionFunc convFunc)
+{
+ ucs4Utf8ConvertFunc = convFunc;
+}
+
+void
+PORT_SetUCS2_ASCIIConversionFunction(PORTCharConversionWSwapFunc convFunc)
+{
+ ucs2AsciiConvertFunc = convFunc;
+}
+
+void
+PORT_SetUCS2_UTF8ConversionFunction(PORTCharConversionFunc convFunc)
+{
+ ucs2Utf8ConvertFunc = convFunc;
+}
+
+PRBool
+PORT_UCS4_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf,
+ unsigned int inBufLen, unsigned char *outBuf,
+ unsigned int maxOutBufLen, unsigned int *outBufLen)
+{
+ if (!ucs4Utf8ConvertFunc) {
+ return sec_port_ucs4_utf8_conversion_function(toUnicode,
+ inBuf, inBufLen, outBuf, maxOutBufLen, outBufLen);
+ }
+
+ return (*ucs4Utf8ConvertFunc)(toUnicode, inBuf, inBufLen, outBuf,
+ maxOutBufLen, outBufLen);
+}
+
+PRBool
+PORT_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf,
+ unsigned int inBufLen, unsigned char *outBuf,
+ unsigned int maxOutBufLen, unsigned int *outBufLen)
+{
+ if (!ucs2Utf8ConvertFunc) {
+ return sec_port_ucs2_utf8_conversion_function(toUnicode,
+ inBuf, inBufLen, outBuf, maxOutBufLen, outBufLen);
+ }
+
+ return (*ucs2Utf8ConvertFunc)(toUnicode, inBuf, inBufLen, outBuf,
+ maxOutBufLen, outBufLen);
+}
+
+PRBool
+PORT_ISO88591_UTF8Conversion(const unsigned char *inBuf,
+ unsigned int inBufLen, unsigned char *outBuf,
+ unsigned int maxOutBufLen, unsigned int *outBufLen)
+{
+ return sec_port_iso88591_utf8_conversion_function(inBuf, inBufLen,
+ outBuf, maxOutBufLen, outBufLen);
+}
+
+PRBool
+PORT_UCS2_ASCIIConversion(PRBool toUnicode, unsigned char *inBuf,
+ unsigned int inBufLen, unsigned char *outBuf,
+ unsigned int maxOutBufLen, unsigned int *outBufLen,
+ PRBool swapBytes)
+{
+ if (!ucs2AsciiConvertFunc) {
+ return PR_FALSE;
+ }
+
+ return (*ucs2AsciiConvertFunc)(toUnicode, inBuf, inBufLen, outBuf,
+ maxOutBufLen, outBufLen, swapBytes);
+}
+
+/* Portable putenv. Creates/replaces an environment variable of the form
+ * envVarName=envValue
+ */
+int
+NSS_PutEnv(const char *envVarName, const char *envValue)
+{
+ SECStatus result = SECSuccess;
+#ifdef _WIN32
+ PRBool setOK;
+
+ setOK = SetEnvironmentVariable(envVarName, envValue);
+ if (!setOK) {
+ SET_ERROR_CODE
+ return SECFailure;
+ }
+#elif defined(__GNUC__) && __GNUC__ >= 7
+ int setEnvFailed;
+ setEnvFailed = setenv(envVarName, envValue, 1);
+ if (setEnvFailed) {
+ SET_ERROR_CODE
+ return SECFailure;
+ }
+#else
+ char *encoded = (char *)PORT_ZAlloc(strlen(envVarName) + 2 + strlen(envValue));
+ if (!encoded) {
+ return SECFailure;
+ }
+ strcpy(encoded, envVarName);
+ strcat(encoded, "=");
+ strcat(encoded, envValue);
+ int putEnvFailed = putenv(encoded); /* adopt. */
+
+ if (putEnvFailed) {
+ SET_ERROR_CODE
+ result = SECFailure;
+ PORT_Free(encoded);
+ }
+#endif
+ return result;
+}
+
+/*
+ * Perform a constant-time compare of two memory regions. The return value is
+ * 0 if the memory regions are equal and non-zero otherwise.
+ */
+int
+NSS_SecureMemcmp(const void *ia, const void *ib, size_t n)
+{
+ const unsigned char *a = (const unsigned char *)ia;
+ const unsigned char *b = (const unsigned char *)ib;
+ int r = 0;
+
+ for (size_t i = 0; i < n; ++i) {
+ r |= a[i] ^ b[i];
+ }
+
+ /* 0 <= r < 256, so -r has bit 8 set when r != 0 */
+ return 1 & (-r >> 8);
+}
+
+/*
+ * Perform a constant-time check if a memory region is all 0. The return value
+ * is 0 if the memory region is all zero.
+ */
+unsigned int
+NSS_SecureMemcmpZero(const void *mem, size_t n)
+{
+ const unsigned char *a = (const unsigned char *)mem;
+ int r = 0;
+
+ for (size_t i = 0; i < n; ++i) {
+ r |= a[i];
+ }
+
+ /* 0 <= r < 256, so -r has bit 8 set when r != 0 */
+ return 1 & (-r >> 8);
+}
+
+/*
+ * A "value barrier" prevents the compiler from making optimizations based on
+ * the value that a variable takes.
+ *
+ * Standard C does not have value barriers, so C implementations of them are
+ * compiler-specific and are not guaranteed to be effective. Thus, the value
+ * barriers here are a best-effort, defense-in-depth, strategy. They are not a
+ * substitute for standard constant-time programming discipline.
+ *
+ * Some implementations have a performance penalty, so value barriers should
+ * be used sparingly.
+ */
+static inline int
+value_barrier_int(int x)
+{
+#if defined(__GNUC__) || defined(__clang__)
+ /* This inline assembly trick from Chandler Carruth's CppCon 2015 talk
+ * generates no instructions.
+ *
+ * "+r"(x) means that x will be mapped to a register that is both an input
+ * and an output to the assembly routine (""). The compiler will not
+ * inspect the assembly routine itself, so it cannot assume anything about
+ * the value of x after this line.
+ */
+ __asm__(""
+ : "+r"(x)
+ : /* no other inputs */);
+ return x;
+#else
+ /* If the compiler does not support the inline assembly trick above, we can
+ * put x in `volatile` storage and read it out again. This will generate
+ * explict store and load instructions, and possibly more depending on the
+ * target.
+ */
+ volatile int y = x;
+ return y;
+#endif
+}
+
+/*
+ * A branch-free implementation of
+ * if (!b) {
+ * memmove(dest, src0, n);
+ * } else {
+ * memmove(dest, src1, n);
+ * }
+ *
+ * The memmove is performed with src0 if `b == 0` and with src1
+ * otherwise.
+ *
+ * As with memmove, the selected src can overlap dest.
+ *
+ * Each of dest, src0, and src1 must point to an allocated buffer
+ * of at least n bytes.
+ */
+void
+NSS_SecureSelect(void *dest, const void *src0, const void *src1, size_t n, unsigned char b)
+
+{
+ // This value barrier makes it safe for the compiler to inline
+ // NSS_SecureSelect into a routine where it could otherwise infer something
+ // about the value of b, e.g. that b is 0/1 valued.
+ int w = value_barrier_int(b);
+
+ // 0 <= b < 256, and int is at least 16 bits, so -w has bits 8-15
+ // set when w != 0.
+ unsigned char mask = 0xff & (-w >> 8);
+
+ for (size_t i = 0; i < n; ++i) {
+ unsigned char s0i = ((unsigned char *)src0)[i];
+ unsigned char s1i = ((unsigned char *)src1)[i];
+ // if mask == 0 this simplifies to s0 ^ 0
+ // if mask == -1 this simplifies to s0 ^ s0 ^ s1
+ ((unsigned char *)dest)[i] = s0i ^ (mask & (s0i ^ s1i));
+ }
+}
+
+/*
+ * consolidate all the calls to get the system FIPS status in one spot.
+ * This function allows an environment variable to override what is returned.
+ */
+PRBool
+NSS_GetSystemFIPSEnabled(void)
+{
+/* if FIPS is disabled in NSS, always return FALSE, even if the environment
+ * variable is set, or the system is in FIPS mode */
+#ifndef NSS_FIPS_DISABLED
+ const char *env;
+
+ /* The environment variable is active for all platforms */
+ env = PR_GetEnvSecure("NSS_FIPS");
+ /* we generally accept y, Y, 1, FIPS, TRUE, and ON as turning on FIPS
+ * mode. Anything else is considered 'off' */
+ if (env && (*env == 'y' || *env == '1' || *env == 'Y' ||
+ (PORT_Strcasecmp(env, "fips") == 0) ||
+ (PORT_Strcasecmp(env, "true") == 0) ||
+ (PORT_Strcasecmp(env, "on") == 0))) {
+ return PR_TRUE;
+ }
+
+/* currently only Linux has a system FIPS indicator. Add others here
+ * as they become available/known */
+#ifdef LINUX
+ {
+ FILE *f;
+ char d;
+ size_t size;
+ f = fopen("/proc/sys/crypto/fips_enabled", "r");
+ if (!f)
+ return PR_FALSE;
+
+ size = fread(&d, 1, 1, f);
+ fclose(f);
+ if (size != 1)
+ return PR_FALSE;
+ if (d == '1')
+ return PR_TRUE;
+ }
+#endif /* LINUX */
+#endif /* NSS_FIPS_DISABLED == 0 */
+ return PR_FALSE;
+}
diff --git a/security/nss/lib/util/secport.h b/security/nss/lib/util/secport.h
new file mode 100644
index 0000000000..489f9468d5
--- /dev/null
+++ b/security/nss/lib/util/secport.h
@@ -0,0 +1,378 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * secport.h - portability interfaces for security libraries
+ */
+
+#ifndef _SECPORT_H_
+#define _SECPORT_H_
+
+#include "utilrename.h"
+#include "prlink.h"
+
+/*
+ * define XP_WIN, or XP_UNIX, in case they are not defined
+ * by anyone else
+ */
+#ifdef _WINDOWS
+#ifndef XP_WIN
+#define XP_WIN
+#endif
+#if defined(_WIN32) || defined(WIN32)
+#ifndef XP_WIN32
+#define XP_WIN32
+#endif
+#endif
+#endif
+
+#ifdef unix
+#ifndef XP_UNIX
+#define XP_UNIX
+#endif
+#endif
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "prtypes.h"
+#include "prlog.h" /* for PR_ASSERT */
+#include "plarena.h"
+#include "plstr.h"
+
+/*
+ * HACK for NSS 2.8 to allow Admin to compile without source changes.
+ */
+#ifndef SEC_BEGIN_PROTOS
+#include "seccomon.h"
+#endif
+
+/*
+ * The PORT_*Arena* function signatures mostly involve PLArenaPool* arguments.
+ * But this is misleading! It's not actually safe to use vanilla PLArenaPools
+ * with them. There are two "subclasses" of PLArenaPool that should be used
+ * instead.
+ *
+ * - PORTArenaPool (defined in secport.c): this "subclass" is always
+ * heap-allocated and uses a (heap-allocated) lock to protect all accesses.
+ * Use PORT_NewArena() and PORT_FreeArena() to create and destroy
+ * PORTArenaPools.
+ *
+ * - PORTCheapArenaPool (defined here): this "subclass" can be stack-allocated
+ * and does not use a lock to protect accesses. This makes it cheaper but
+ * less general. It is best used for arena pools that (a) are hot, (b) have
+ * lifetimes bounded within a single function, and (c) don't need locking.
+ * Use PORT_InitCheapArena() and PORT_DestroyCheapArena() to initialize and
+ * finalize PORTCheapArenaPools.
+ *
+ * All the other PORT_Arena* functions will operate safely with either
+ * subclass.
+ */
+typedef struct PORTCheapArenaPool_str {
+ PLArenaPool arena;
+ PRUint32 magic; /* This is used to distinguish the two subclasses. */
+} PORTCheapArenaPool;
+
+SEC_BEGIN_PROTOS
+
+extern void *PORT_Alloc(size_t len);
+extern void *PORT_Realloc(void *old, size_t len);
+extern void *PORT_ZAlloc(size_t len);
+extern void *PORT_ZAllocAligned(size_t bytes, size_t alignment, void **mem);
+extern void *PORT_ZAllocAlignedOffset(size_t bytes, size_t alignment,
+ size_t offset);
+extern void PORT_Free(void *ptr);
+extern void PORT_ZFree(void *ptr, size_t len);
+extern char *PORT_Strdup(const char *s);
+extern void PORT_SetError(int value);
+extern int PORT_GetError(void);
+
+/* These functions are for use with PORTArenaPools. */
+extern PLArenaPool *PORT_NewArena(unsigned long chunksize);
+extern void PORT_FreeArena(PLArenaPool *arena, PRBool zero);
+
+/* These functions are for use with PORTCheapArenaPools. */
+extern void PORT_InitCheapArena(PORTCheapArenaPool *arena,
+ unsigned long chunksize);
+extern void PORT_DestroyCheapArena(PORTCheapArenaPool *arena);
+
+/* These functions work with both kinds of arena pool. */
+extern void *PORT_ArenaAlloc(PLArenaPool *arena, size_t size);
+extern void *PORT_ArenaZAlloc(PLArenaPool *arena, size_t size);
+extern void *PORT_ArenaGrow(PLArenaPool *arena, void *ptr,
+ size_t oldsize, size_t newsize);
+extern void *PORT_ArenaMark(PLArenaPool *arena);
+extern void PORT_ArenaRelease(PLArenaPool *arena, void *mark);
+extern void PORT_ArenaZRelease(PLArenaPool *arena, void *mark);
+extern void PORT_ArenaUnmark(PLArenaPool *arena, void *mark);
+extern char *PORT_ArenaStrdup(PLArenaPool *arena, const char *str);
+
+SEC_END_PROTOS
+
+#define PORT_Assert PR_ASSERT
+/* This is a variation of PORT_Assert where the arguments will be always
+ * used either in Debug or not. But, in optimized mode the result will be
+ * ignored. See more details in Bug 1588015. */
+#define PORT_AssertArg PR_ASSERT_ARG
+
+/* Assert the current location can't be reached, passing a reason-string. */
+#define PORT_AssertNotReached(reasonStr) PR_NOT_REACHED(reasonStr)
+
+/* macros to handle endian based byte conversion */
+#define PORT_GET_BYTE_BE(value, offset, len) \
+ ((unsigned char)(((len) - (offset)-1) >= sizeof(value) ? 0 : (((value) >> (((len) - (offset)-1) * PR_BITS_PER_BYTE)) & 0xff)))
+#define PORT_GET_BYTE_LE(value, offset, len) \
+ ((unsigned char)((offset) > sizeof(value) ? 0 : (((value) >> ((offset)*PR_BITS_PER_BYTE)) & 0xff)))
+
+/* This runs a function that should return SECSuccess.
+ * Intended for NSS internal use only.
+ * The return value is asserted in a debug build, otherwise it is ignored.
+ * This is no substitute for proper error handling. It is OK only if you
+ * have ensured that the function cannot fail by other means such as checking
+ * prerequisites. In that case this can be used as a safeguard against
+ * unexpected changes in a function.
+ */
+#ifdef DEBUG
+#define PORT_CheckSuccess(f) PR_ASSERT((f) == SECSuccess)
+#else
+#define PORT_CheckSuccess(f) (f)
+#endif
+#define PORT_ZNew(type) (type *)PORT_ZAlloc(sizeof(type))
+#define PORT_ZNewAligned(type, alignment, mem) \
+ (type *)PORT_ZAllocAlignedOffset(sizeof(type), alignment, offsetof(type, mem))
+#define PORT_New(type) (type *)PORT_Alloc(sizeof(type))
+#define PORT_ArenaNew(poolp, type) \
+ (type *)PORT_ArenaAlloc(poolp, sizeof(type))
+#define PORT_ArenaZNew(poolp, type) \
+ (type *)PORT_ArenaZAlloc(poolp, sizeof(type))
+#define PORT_NewArray(type, num) \
+ (type *)PORT_Alloc(sizeof(type) * (num))
+#define PORT_ZNewArray(type, num) \
+ (type *)PORT_ZAlloc(sizeof(type) * (num))
+#define PORT_ArenaNewArray(poolp, type, num) \
+ (type *)PORT_ArenaAlloc(poolp, sizeof(type) * (num))
+#define PORT_ArenaZNewArray(poolp, type, num) \
+ (type *)PORT_ArenaZAlloc(poolp, sizeof(type) * (num))
+
+/* Please, keep these defines sorted alphabetically. Thanks! */
+
+#define PORT_Atoi(buff) (int)strtol(buff, NULL, 10)
+
+/* Returns a UTF-8 encoded constant error string for err.
+ * Returns NULL if initialization of the error tables fails
+ * due to insufficient memory.
+ *
+ * This string must not be modified by the application.
+ */
+#define PORT_ErrorToString(err) PR_ErrorToString((err), PR_LANGUAGE_I_DEFAULT)
+
+#define PORT_ErrorToName PR_ErrorToName
+
+#define PORT_Memcmp memcmp
+#define PORT_Memcpy memcpy
+#ifndef SUNOS4
+#define PORT_Memmove memmove
+#else /*SUNOS4*/
+#define PORT_Memmove(s, ct, n) bcopy((ct), (s), (n))
+#endif /*SUNOS4*/
+#define PORT_Memset memset
+
+#define PORT_Strcasecmp PL_strcasecmp
+#define PORT_Strcat strcat
+#define PORT_Strchr strchr
+#define PORT_Strrchr strrchr
+#define PORT_Strcmp strcmp
+#define PORT_Strcpy strcpy
+#define PORT_Strlen(s) strlen(s)
+#define PORT_Strncasecmp PL_strncasecmp
+#define PORT_Strncat strncat
+#define PORT_Strncmp strncmp
+#define PORT_Strncpy strncpy
+#define PORT_Strpbrk strpbrk
+#define PORT_Strstr strstr
+#define PORT_Strtok strtok
+
+#define PORT_Tolower tolower
+
+typedef PRBool(PR_CALLBACK *PORTCharConversionWSwapFunc)(PRBool toUnicode,
+ unsigned char *inBuf, unsigned int inBufLen,
+ unsigned char *outBuf, unsigned int maxOutBufLen,
+ unsigned int *outBufLen, PRBool swapBytes);
+
+typedef PRBool(PR_CALLBACK *PORTCharConversionFunc)(PRBool toUnicode,
+ unsigned char *inBuf, unsigned int inBufLen,
+ unsigned char *outBuf, unsigned int maxOutBufLen,
+ unsigned int *outBufLen);
+
+SEC_BEGIN_PROTOS
+
+void PORT_SetUCS4_UTF8ConversionFunction(PORTCharConversionFunc convFunc);
+void PORT_SetUCS2_ASCIIConversionFunction(PORTCharConversionWSwapFunc convFunc);
+PRBool PORT_UCS4_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf,
+ unsigned int inBufLen, unsigned char *outBuf,
+ unsigned int maxOutBufLen, unsigned int *outBufLen);
+PRBool PORT_UCS2_ASCIIConversion(PRBool toUnicode, unsigned char *inBuf,
+ unsigned int inBufLen, unsigned char *outBuf,
+ unsigned int maxOutBufLen, unsigned int *outBufLen,
+ PRBool swapBytes);
+void PORT_SetUCS2_UTF8ConversionFunction(PORTCharConversionFunc convFunc);
+PRBool PORT_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf,
+ unsigned int inBufLen, unsigned char *outBuf,
+ unsigned int maxOutBufLen, unsigned int *outBufLen);
+
+/* One-way conversion from ISO-8859-1 to UTF-8 */
+PRBool PORT_ISO88591_UTF8Conversion(const unsigned char *inBuf,
+ unsigned int inBufLen, unsigned char *outBuf,
+ unsigned int maxOutBufLen, unsigned int *outBufLen);
+
+extern PRBool
+sec_port_ucs4_utf8_conversion_function(
+ PRBool toUnicode,
+ unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen);
+
+extern PRBool
+sec_port_ucs2_utf8_conversion_function(
+ PRBool toUnicode,
+ unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen);
+
+/* One-way conversion from ISO-8859-1 to UTF-8 */
+extern PRBool
+sec_port_iso88591_utf8_conversion_function(
+ const unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen);
+
+extern int NSS_PutEnv(const char *envVarName, const char *envValue);
+
+extern int NSS_SecureMemcmp(const void *a, const void *b, size_t n);
+extern unsigned int NSS_SecureMemcmpZero(const void *mem, size_t n);
+extern void NSS_SecureSelect(void *dest, const void *src0, const void *src1, size_t n, unsigned char b);
+extern PRBool NSS_GetSystemFIPSEnabled(void);
+
+/*
+ * Load a shared library called "newShLibName" in the same directory as
+ * a shared library that is already loaded, called existingShLibName.
+ * A pointer to a static function in that shared library,
+ * staticShLibFunc, is required.
+ *
+ * existingShLibName:
+ * The file name of the shared library that shall be used as the
+ * "reference library". The loader will attempt to load the requested
+ * library from the same directory as the reference library.
+ *
+ * staticShLibFunc:
+ * Pointer to a static function in the "reference library".
+ *
+ * newShLibName:
+ * The simple file name of the new shared library to be loaded.
+ *
+ * We use PR_GetLibraryFilePathname to get the pathname of the loaded
+ * shared lib that contains this function, and then do a
+ * PR_LoadLibraryWithFlags with an absolute pathname for the shared
+ * library to be loaded.
+ *
+ * On Windows, the "alternate search path" strategy is employed, if available.
+ * On Unix, if existingShLibName is a symbolic link, and no link exists for the
+ * new library, the original link will be resolved, and the new library loaded
+ * from the resolved location.
+ *
+ * If the new shared library is not found in the same location as the reference
+ * library, it will then be loaded from the normal system library path.
+ */
+PRLibrary *
+PORT_LoadLibraryFromOrigin(const char *existingShLibName,
+ PRFuncPtr staticShLibFunc,
+ const char *newShLibName);
+
+SEC_END_PROTOS
+
+/*
+ * Constant time macros
+ */
+/* These macros use the fact that arithmetic shift shifts-in the sign bit.
+ * However, this is not ensured by the C standard so you may need to replace
+ * them with something else for odd compilers. These macros work for object
+ * sizes up to 32 bits. The inequalities will produce incorrect results if
+ * abs(a-b) >= PR_UINT32_MAX/2. This can be a voided if unsigned values stay
+ * within the range 0-PRUINT32_MAX/2 and signed values stay within the range
+ * -PRINT32_MAX/2-PRINT32_MAX/2. If these are insufficient, we can fix
+ * this by either expanding the PORT_CT_DUPLICATE_MSB_TO_ALL to PRUint64
+ * or by creating the following new macros for inequality:
+ *
+ * PORT_CT_OVERFLOW prevents the overflow condition by handling the case
+ * where the high bits in a and b are different specially. Basically if
+ * the high bit in a and b differs we can just
+ * copy the high bit of one of the parameters to determine the result as
+ * follows:
+ * GxU if a has the high bit on, a>b, so d=a
+ * LxU if b has the high bit on, a<b, so d=b
+ * GxS if b has the high bit on, it's negative a>b so d=b
+ * LxS if a has the high bit on, it's negative a<b so d=a
+ * where PORT_CT_xxU() macros do unsigned compares and PORT_CT_xxS() do signed
+ * compares.
+ *
+ * #define PORT_CT_OVERFLOW(a,b,c,d) \
+ * PORT_CT_SEL(PORT_CT_DUPLICATE_MSB_TO_ALL((a)^(b)), \
+ * (PORT_CT_DUPLICATE_MSB_TO_ALL(d)),c)
+ * #define PORT_CT_GTU(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_GT(a,b),a)
+ * #define PORT_CT_LTU(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_LT(a,b),b)
+ * #define PORT_CT_GEU(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_GE(a,b),a)
+ * #define PORT_CT_LEU(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_LE(a,b),b)
+ * #define PORT_CT_GTS(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_GT(a,b),b)
+ * #define PORT_CT_LTS(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_LT(a,b),a)
+ * #define PORT_CT_GES(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_GE(a,b),b)
+ * #define PORT_CT_LES(a,b) PORT_CT_OVERFLOW(a,b,PORT_CT_LE(a,b),a)
+ *
+ *
+ * */
+/* Constant-time helper macro that copies the MSB of x to all other bits. */
+#define PORT_CT_DUPLICATE_MSB_TO_ALL(x) ((PRUint32)((PRInt32)(x) >> (sizeof(PRInt32) * 8 - 1)))
+
+/* Constant-time helper macro that selects l or r depending on all-1 or all-0
+ * mask m */
+#define PORT_CT_SEL(m, l, r) (((m) & (l)) | (~(m) & (r)))
+
+/* Constant-time helper macro that returns all-1s if x is not 0; and all-0s
+ * otherwise. */
+#define PORT_CT_NOT_ZERO(x) (PORT_CT_DUPLICATE_MSB_TO_ALL(((x) | (0 - (x)))))
+
+/* Constant-time helper macro that returns all-1s if x is 0; and all-0s
+ * otherwise. */
+#define PORT_CT_ZERO(x) (~PORT_CT_DUPLICATE_MSB_TO_ALL(((x) | (0 - (x)))))
+
+/* Constant-time helper macro for equalities and inequalities.
+ * returns all-1's for true and all-0's for false */
+#define PORT_CT_EQ(a, b) PORT_CT_ZERO(((a) - (b)))
+#define PORT_CT_NE(a, b) PORT_CT_NOT_ZERO(((a) - (b)))
+#define PORT_CT_GT(a, b) PORT_CT_DUPLICATE_MSB_TO_ALL((b) - (a))
+#define PORT_CT_LT(a, b) PORT_CT_DUPLICATE_MSB_TO_ALL((a) - (b))
+#define PORT_CT_GE(a, b) (~PORT_CT_LT(a, b))
+#define PORT_CT_LE(a, b) (~PORT_CT_GT(a, b))
+#define PORT_CT_TRUE (~0)
+#define PORT_CT_FALSE 0
+
+#ifdef CT_VERIF
+#include <valgrind/memcheck.h>
+#define NSS_CLASSIFY(buf, length) VALGRIND_MAKE_MEM_UNDEFINED(buf, length);
+#define NSS_DECLASSIFY(buf, length) VALGRIND_MAKE_MEM_DEFINED(buf, length);
+#else
+#define NSS_CLASSIFY(buf, length)
+#define NSS_DECLASSIFY(buf, length)
+#endif
+
+#endif /* _SECPORT_H_ */
diff --git a/security/nss/lib/util/sectime.c b/security/nss/lib/util/sectime.c
new file mode 100644
index 0000000000..11ee5ffeb5
--- /dev/null
+++ b/security/nss/lib/util/sectime.c
@@ -0,0 +1,163 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "prtime.h"
+#include "secder.h"
+#include "secitem.h"
+#include "secerr.h"
+
+static char *DecodeUTCTime2FormattedAscii(SECItem *utcTimeDER, char *format);
+static char *DecodeGeneralizedTime2FormattedAscii(SECItem *generalizedTimeDER, char *format);
+
+/* convert DER utc time to ascii time string */
+char *
+DER_UTCTimeToAscii(SECItem *utcTime)
+{
+ return (DecodeUTCTime2FormattedAscii(utcTime, "%a %b %d %H:%M:%S %Y"));
+}
+
+/* convert DER utc time to ascii time string, only include day, not time */
+char *
+DER_UTCDayToAscii(SECItem *utctime)
+{
+ return (DecodeUTCTime2FormattedAscii(utctime, "%a %b %d, %Y"));
+}
+
+/* convert DER generalized time to ascii time string, only include day,
+ not time */
+char *
+DER_GeneralizedDayToAscii(SECItem *gentime)
+{
+ return (DecodeGeneralizedTime2FormattedAscii(gentime, "%a %b %d, %Y"));
+}
+
+/* convert DER generalized or UTC time to ascii time string, only include
+ day, not time */
+char *
+DER_TimeChoiceDayToAscii(SECItem *timechoice)
+{
+ switch (timechoice->type) {
+
+ case siUTCTime:
+ return DER_UTCDayToAscii(timechoice);
+
+ case siGeneralizedTime:
+ return DER_GeneralizedDayToAscii(timechoice);
+
+ default:
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+}
+
+char *
+CERT_UTCTime2FormattedAscii(PRTime utcTime, char *format)
+{
+ PRExplodedTime printableTime;
+ char *timeString;
+
+ /* Converse time to local time and decompose it into components */
+ PR_ExplodeTime(utcTime, PR_LocalTimeParameters, &printableTime);
+
+ timeString = (char *)PORT_Alloc(256);
+
+ if (timeString) {
+ if (!PR_FormatTime(timeString, 256, format, &printableTime)) {
+ PORT_Free(timeString);
+ timeString = NULL;
+ }
+ }
+
+ return (timeString);
+}
+
+char *
+CERT_GenTime2FormattedAscii(PRTime genTime, char *format)
+{
+ PRExplodedTime printableTime;
+ char *timeString;
+
+ /* Decompose time into components */
+ PR_ExplodeTime(genTime, PR_GMTParameters, &printableTime);
+
+ timeString = (char *)PORT_Alloc(256);
+
+ if (timeString) {
+ if (!PR_FormatTime(timeString, 256, format, &printableTime)) {
+ PORT_Free(timeString);
+ timeString = NULL;
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ }
+ }
+
+ return (timeString);
+}
+
+/* convert DER utc time to ascii time string, The format of the time string
+ depends on the input "format"
+ */
+static char *
+DecodeUTCTime2FormattedAscii(SECItem *utcTimeDER, char *format)
+{
+ PRTime utcTime;
+ int rv;
+
+ rv = DER_UTCTimeToTime(&utcTime, utcTimeDER);
+ if (rv) {
+ return (NULL);
+ }
+ return (CERT_UTCTime2FormattedAscii(utcTime, format));
+}
+
+/* convert DER utc time to ascii time string, The format of the time string
+ depends on the input "format"
+ */
+static char *
+DecodeGeneralizedTime2FormattedAscii(SECItem *generalizedTimeDER, char *format)
+{
+ PRTime generalizedTime;
+ int rv;
+
+ rv = DER_GeneralizedTimeToTime(&generalizedTime, generalizedTimeDER);
+ if (rv) {
+ return (NULL);
+ }
+ return (CERT_GeneralizedTime2FormattedAscii(generalizedTime, format));
+}
+
+/* decode a SECItem containing either a SEC_ASN1_GENERALIZED_TIME
+ or a SEC_ASN1_UTC_TIME */
+
+SECStatus
+DER_DecodeTimeChoice(PRTime *output, const SECItem *input)
+{
+ switch (input->type) {
+ case siGeneralizedTime:
+ return DER_GeneralizedTimeToTime(output, input);
+
+ case siUTCTime:
+ return DER_UTCTimeToTime(output, input);
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ PORT_Assert(0);
+ return SECFailure;
+ }
+}
+
+/* encode a PRTime to an ASN.1 DER SECItem containing either a
+ SEC_ASN1_GENERALIZED_TIME or a SEC_ASN1_UTC_TIME */
+
+SECStatus
+DER_EncodeTimeChoice(PLArenaPool *arena, SECItem *output, PRTime input)
+{
+ SECStatus rv;
+
+ rv = DER_TimeToUTCTimeArena(arena, output, input);
+ if (rv == SECSuccess || PORT_GetError() != SEC_ERROR_INVALID_ARGS) {
+ return rv;
+ }
+ return DER_TimeToGeneralizedTimeArena(arena, output, input);
+}
diff --git a/security/nss/lib/util/templates.c b/security/nss/lib/util/templates.c
new file mode 100644
index 0000000000..6118aeeba3
--- /dev/null
+++ b/security/nss/lib/util/templates.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/. */
+
+/*
+ * Templates that are compiled and exported from both libnss3 and libnssutil3.
+ * They have to be, because they were previously exported from libnss3, and
+ * there is no way to create data forwarder symbols on Unix.
+ *
+ * Please do not add to this file. New shared templates should be exported
+ * from libnssutil3 only.
+ *
+ */
+
+#include "utilrename.h"
+#include "secasn1.h"
+#include "secder.h"
+#include "secoid.h"
+#include "secdig.h"
+
+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 }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SECOID_AlgorithmIDTemplate)
+
+const SEC_ASN1Template SEC_AnyTemplate[] = {
+ { SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_AnyTemplate)
+
+const SEC_ASN1Template SEC_BMPStringTemplate[] = {
+ { SEC_ASN1_BMP_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BMPStringTemplate)
+
+const SEC_ASN1Template SEC_BitStringTemplate[] = {
+ { SEC_ASN1_BIT_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BitStringTemplate)
+
+const SEC_ASN1Template SEC_BooleanTemplate[] = {
+ { SEC_ASN1_BOOLEAN, 0, NULL, sizeof(SECItem) }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BooleanTemplate)
+
+const SEC_ASN1Template SEC_GeneralizedTimeTemplate[] = {
+ { SEC_ASN1_GENERALIZED_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_GeneralizedTimeTemplate)
+
+const SEC_ASN1Template SEC_IA5StringTemplate[] = {
+ { SEC_ASN1_IA5_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_IA5StringTemplate)
+
+const SEC_ASN1Template SEC_IntegerTemplate[] = {
+ { SEC_ASN1_INTEGER, 0, NULL, sizeof(SECItem) }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_IntegerTemplate)
+
+const SEC_ASN1Template SEC_NullTemplate[] = {
+ { SEC_ASN1_NULL, 0, NULL, sizeof(SECItem) }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_NullTemplate)
+
+const SEC_ASN1Template SEC_ObjectIDTemplate[] = {
+ { SEC_ASN1_OBJECT_ID, 0, NULL, sizeof(SECItem) }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_ObjectIDTemplate)
+
+const SEC_ASN1Template SEC_OctetStringTemplate[] = {
+ { SEC_ASN1_OCTET_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_OctetStringTemplate)
+
+const SEC_ASN1Template SEC_PointerToAnyTemplate[] = {
+ { SEC_ASN1_POINTER, 0, SEC_AnyTemplate }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToAnyTemplate)
+
+const SEC_ASN1Template SEC_PointerToOctetStringTemplate[] = {
+ { SEC_ASN1_POINTER | SEC_ASN1_MAY_STREAM, 0, SEC_OctetStringTemplate }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToOctetStringTemplate)
+
+const SEC_ASN1Template SEC_SetOfAnyTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, SEC_AnyTemplate }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SetOfAnyTemplate)
+
+const SEC_ASN1Template SEC_UTCTimeTemplate[] = {
+ { SEC_ASN1_UTC_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UTCTimeTemplate)
+
+const SEC_ASN1Template SEC_UTF8StringTemplate[] = {
+ { SEC_ASN1_UTF8_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UTF8StringTemplate)
+
+/* XXX See comment below about SGN_DecodeDigestInfo -- keep this static! */
+/* XXX Changed from static -- need to change name? */
+const SEC_ASN1Template sgn_DigestInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(SGNDigestInfo) },
+ { SEC_ASN1_INLINE,
+ offsetof(SGNDigestInfo, digestAlgorithm),
+ SECOID_AlgorithmIDTemplate },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(SGNDigestInfo, digest) },
+ { 0 }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(sgn_DigestInfoTemplate)
diff --git a/security/nss/lib/util/utf8.c b/security/nss/lib/util/utf8.c
new file mode 100644
index 0000000000..7bdd714829
--- /dev/null
+++ b/security/nss/lib/util/utf8.c
@@ -0,0 +1,445 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "seccomon.h"
+#include "secport.h"
+
+/*
+ * From RFC 2044:
+ *
+ * UCS-4 range (hex.) UTF-8 octet sequence (binary)
+ * 0000 0000-0000 007F 0xxxxxxx
+ * 0000 0080-0000 07FF 110xxxxx 10xxxxxx
+ * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
+ * 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ * 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ * 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx
+ */
+
+/*
+ * From http://www.imc.org/draft-hoffman-utf16
+ *
+ * For U on [0x00010000,0x0010FFFF]: Let U' = U - 0x00010000
+ *
+ * U' = yyyyyyyyyyxxxxxxxxxx
+ * W1 = 110110yyyyyyyyyy
+ * W2 = 110111xxxxxxxxxx
+ */
+
+/*
+ * This code is assuming NETWORK BYTE ORDER for the 16- and 32-bit
+ * character values. If you wish to use this code for working with
+ * host byte order values, define the following:
+ *
+ * #if IS_BIG_ENDIAN
+ * #define L_0 0
+ * #define L_1 1
+ * #define L_2 2
+ * #define L_3 3
+ * #define H_0 0
+ * #define H_1 1
+ * #else / * not everyone has elif * /
+ * #if IS_LITTLE_ENDIAN
+ * #define L_0 3
+ * #define L_1 2
+ * #define L_2 1
+ * #define L_3 0
+ * #define H_0 1
+ * #define H_1 0
+ * #else
+ * #error "PDP and NUXI support deferred"
+ * #endif / * IS_LITTLE_ENDIAN * /
+ * #endif / * IS_BIG_ENDIAN * /
+ */
+
+#define L_0 0
+#define L_1 1
+#define L_2 2
+#define L_3 3
+#define H_0 0
+#define H_1 1
+
+#define BAD_UTF8 ((PRUint32)-1)
+
+/*
+ * Parse a single UTF-8 character per the spec. in section 3.9 (D36)
+ * of Unicode 4.0.0.
+ *
+ * Parameters:
+ * index - Points to the byte offset in inBuf of character to read. On success,
+ * updated to the offset of the following character.
+ * inBuf - Input buffer, UTF-8 encoded
+ * inbufLen - Length of input buffer, in bytes.
+ *
+ * Returns:
+ * Success - The UCS4 encoded character
+ * Failure - BAD_UTF8
+ */
+static PRUint32
+sec_port_read_utf8(unsigned int *index, unsigned char *inBuf, unsigned int inBufLen)
+{
+ PRUint32 result;
+ unsigned int i = *index;
+ int bytes_left;
+ PRUint32 min_value;
+
+ PORT_Assert(i < inBufLen);
+
+ if ((inBuf[i] & 0x80) == 0x00) {
+ result = inBuf[i++];
+ bytes_left = 0;
+ min_value = 0;
+ } else if ((inBuf[i] & 0xE0) == 0xC0) {
+ result = inBuf[i++] & 0x1F;
+ bytes_left = 1;
+ min_value = 0x80;
+ } else if ((inBuf[i] & 0xF0) == 0xE0) {
+ result = inBuf[i++] & 0x0F;
+ bytes_left = 2;
+ min_value = 0x800;
+ } else if ((inBuf[i] & 0xF8) == 0xF0) {
+ result = inBuf[i++] & 0x07;
+ bytes_left = 3;
+ min_value = 0x10000;
+ } else {
+ return BAD_UTF8;
+ }
+
+ while (bytes_left--) {
+ if (i >= inBufLen || (inBuf[i] & 0xC0) != 0x80)
+ return BAD_UTF8;
+ result = (result << 6) | (inBuf[i++] & 0x3F);
+ }
+
+ /* Check for overlong sequences, surrogates, and outside unicode range */
+ if (result < min_value || (result & 0xFFFFF800) == 0xD800 || result > 0x10FFFF) {
+ return BAD_UTF8;
+ }
+
+ *index = i;
+ return result;
+}
+
+PRBool
+sec_port_ucs4_utf8_conversion_function(
+ PRBool toUnicode,
+ unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen)
+{
+ PORT_Assert((unsigned int *)NULL != outBufLen);
+
+ if (toUnicode) {
+ unsigned int i, len = 0;
+
+ for (i = 0; i < inBufLen;) {
+ if ((inBuf[i] & 0x80) == 0x00)
+ i += 1;
+ else if ((inBuf[i] & 0xE0) == 0xC0)
+ i += 2;
+ else if ((inBuf[i] & 0xF0) == 0xE0)
+ i += 3;
+ else if ((inBuf[i] & 0xF8) == 0xF0)
+ i += 4;
+ else
+ return PR_FALSE;
+
+ len += 4;
+ }
+
+ if (len > maxOutBufLen) {
+ *outBufLen = len;
+ return PR_FALSE;
+ }
+
+ len = 0;
+
+ for (i = 0; i < inBufLen;) {
+ PRUint32 ucs4 = sec_port_read_utf8(&i, inBuf, inBufLen);
+
+ if (ucs4 == BAD_UTF8)
+ return PR_FALSE;
+
+ outBuf[len + L_0] = 0x00;
+ outBuf[len + L_1] = (unsigned char)(ucs4 >> 16);
+ outBuf[len + L_2] = (unsigned char)(ucs4 >> 8);
+ outBuf[len + L_3] = (unsigned char)ucs4;
+
+ len += 4;
+ }
+
+ *outBufLen = len;
+ return PR_TRUE;
+ } else {
+ unsigned int i, len = 0;
+ PORT_Assert((inBufLen % 4) == 0);
+ if ((inBufLen % 4) != 0) {
+ *outBufLen = 0;
+ return PR_FALSE;
+ }
+
+ for (i = 0; i < inBufLen; i += 4) {
+ if ((inBuf[i + L_0] > 0x00) || (inBuf[i + L_1] > 0x10)) {
+ *outBufLen = 0;
+ return PR_FALSE;
+ } else if (inBuf[i + L_1] >= 0x01)
+ len += 4;
+ else if (inBuf[i + L_2] >= 0x08)
+ len += 3;
+ else if ((inBuf[i + L_2] > 0x00) || (inBuf[i + L_3] >= 0x80))
+ len += 2;
+ else
+ len += 1;
+ }
+
+ if (len > maxOutBufLen) {
+ *outBufLen = len;
+ return PR_FALSE;
+ }
+
+ len = 0;
+
+ for (i = 0; i < inBufLen; i += 4) {
+ if (inBuf[i + L_1] >= 0x01) {
+ /* 0001 0000-001F FFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ /* 00000000 000abcde fghijklm nopqrstu ->
+ 11110abc 10defghi 10jklmno 10pqrstu */
+
+ outBuf[len + 0] = 0xF0 | ((inBuf[i + L_1] & 0x1C) >> 2);
+ outBuf[len + 1] = 0x80 | ((inBuf[i + L_1] & 0x03) << 4) | ((inBuf[i + L_2] & 0xF0) >> 4);
+ outBuf[len + 2] = 0x80 | ((inBuf[i + L_2] & 0x0F) << 2) | ((inBuf[i + L_3] & 0xC0) >> 6);
+ outBuf[len + 3] = 0x80 | ((inBuf[i + L_3] & 0x3F) >> 0);
+
+ len += 4;
+ } else if (inBuf[i + L_2] >= 0x08) {
+ /* 0000 0800-0000 FFFF -> 1110xxxx 10xxxxxx 10xxxxxx */
+ /* 00000000 00000000 abcdefgh ijklmnop ->
+ 1110abcd 10efghij 10klmnop */
+
+ outBuf[len + 0] = 0xE0 | ((inBuf[i + L_2] & 0xF0) >> 4);
+ outBuf[len + 1] = 0x80 | ((inBuf[i + L_2] & 0x0F) << 2) | ((inBuf[i + L_3] & 0xC0) >> 6);
+ outBuf[len + 2] = 0x80 | ((inBuf[i + L_3] & 0x3F) >> 0);
+
+ len += 3;
+ } else if ((inBuf[i + L_2] > 0x00) || (inBuf[i + L_3] >= 0x80)) {
+ /* 0000 0080-0000 07FF -> 110xxxxx 10xxxxxx */
+ /* 00000000 00000000 00000abc defghijk ->
+ 110abcde 10fghijk */
+
+ outBuf[len + 0] = 0xC0 | ((inBuf[i + L_2] & 0x07) << 2) | ((inBuf[i + L_3] & 0xC0) >> 6);
+ outBuf[len + 1] = 0x80 | ((inBuf[i + L_3] & 0x3F) >> 0);
+
+ len += 2;
+ } else {
+ /* 0000 0000-0000 007F -> 0xxxxxx */
+ /* 00000000 00000000 00000000 0abcdefg ->
+ 0abcdefg */
+
+ outBuf[len + 0] = (inBuf[i + L_3] & 0x7F);
+
+ len += 1;
+ }
+ }
+
+ *outBufLen = len;
+ return PR_TRUE;
+ }
+}
+
+PRBool
+sec_port_ucs2_utf8_conversion_function(
+ PRBool toUnicode,
+ unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen)
+{
+ PORT_Assert((unsigned int *)NULL != outBufLen);
+
+ if (toUnicode) {
+ unsigned int i, len = 0;
+
+ for (i = 0; i < inBufLen;) {
+ if ((inBuf[i] & 0x80) == 0x00) {
+ i += 1;
+ len += 2;
+ } else if ((inBuf[i] & 0xE0) == 0xC0) {
+ i += 2;
+ len += 2;
+ } else if ((inBuf[i] & 0xF0) == 0xE0) {
+ i += 3;
+ len += 2;
+ } else if ((inBuf[i] & 0xF8) == 0xF0) {
+ i += 4;
+ len += 4;
+ } else
+ return PR_FALSE;
+ }
+
+ if (len > maxOutBufLen) {
+ *outBufLen = len;
+ return PR_FALSE;
+ }
+
+ len = 0;
+
+ for (i = 0; i < inBufLen;) {
+ PRUint32 ucs4 = sec_port_read_utf8(&i, inBuf, inBufLen);
+
+ if (ucs4 == BAD_UTF8)
+ return PR_FALSE;
+
+ if (ucs4 < 0x10000) {
+ outBuf[len + H_0] = (unsigned char)(ucs4 >> 8);
+ outBuf[len + H_1] = (unsigned char)ucs4;
+ len += 2;
+ } else {
+ ucs4 -= 0x10000;
+ outBuf[len + 0 + H_0] = (unsigned char)(0xD8 | ((ucs4 >> 18) & 0x3));
+ outBuf[len + 0 + H_1] = (unsigned char)(ucs4 >> 10);
+ outBuf[len + 2 + H_0] = (unsigned char)(0xDC | ((ucs4 >> 8) & 0x3));
+ outBuf[len + 2 + H_1] = (unsigned char)ucs4;
+ len += 4;
+ }
+ }
+
+ *outBufLen = len;
+ return PR_TRUE;
+ } else {
+ unsigned int i, len = 0;
+ PORT_Assert((inBufLen % 2) == 0);
+ if ((inBufLen % 2) != 0) {
+ *outBufLen = 0;
+ return PR_FALSE;
+ }
+
+ for (i = 0; i < inBufLen; i += 2) {
+ if ((inBuf[i + H_0] == 0x00) && ((inBuf[i + H_1] & 0x80) == 0x00))
+ len += 1;
+ else if (inBuf[i + H_0] < 0x08)
+ len += 2;
+ else if (((inBuf[i + H_0] & 0xFC) == 0xD8)) {
+ if (((inBufLen - i) > 2) && ((inBuf[i + 2 + H_0] & 0xFC) == 0xDC)) {
+ i += 2;
+ len += 4;
+ } else {
+ return PR_FALSE;
+ }
+ } else if ((inBuf[i + H_0] & 0xFC) == 0xDC) {
+ return PR_FALSE;
+ } else {
+ len += 3;
+ }
+ }
+
+ if (len > maxOutBufLen) {
+ *outBufLen = len;
+ return PR_FALSE;
+ }
+
+ len = 0;
+
+ for (i = 0; i < inBufLen; i += 2) {
+ if ((inBuf[i + H_0] == 0x00) && ((inBuf[i + H_1] & 0x80) == 0x00)) {
+ /* 0000-007F -> 0xxxxxx */
+ /* 00000000 0abcdefg -> 0abcdefg */
+
+ outBuf[len] = inBuf[i + H_1] & 0x7F;
+
+ len += 1;
+ } else if (inBuf[i + H_0] < 0x08) {
+ /* 0080-07FF -> 110xxxxx 10xxxxxx */
+ /* 00000abc defghijk -> 110abcde 10fghijk */
+
+ outBuf[len + 0] = 0xC0 | ((inBuf[i + H_0] & 0x07) << 2) | ((inBuf[i + H_1] & 0xC0) >> 6);
+ outBuf[len + 1] = 0x80 | ((inBuf[i + H_1] & 0x3F) >> 0);
+
+ len += 2;
+ } else if ((inBuf[i + H_0] & 0xFC) == 0xD8) {
+ int abcde, BCDE;
+
+ PORT_Assert(((inBufLen - i) > 2) && ((inBuf[i + 2 + H_0] & 0xFC) == 0xDC));
+
+ /* D800-DBFF DC00-DFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ /* 110110BC DEfghijk 110111lm nopqrstu ->
+ { Let abcde = BCDE + 1 }
+ 11110abc 10defghi 10jklmno 10pqrstu */
+
+ BCDE = ((inBuf[i + H_0] & 0x03) << 2) | ((inBuf[i + H_1] & 0xC0) >> 6);
+ abcde = BCDE + 1;
+
+ outBuf[len + 0] = 0xF0 | ((abcde & 0x1C) >> 2);
+ outBuf[len + 1] = 0x80 | ((abcde & 0x03) << 4) | ((inBuf[i + 0 + H_1] & 0x3C) >> 2);
+ outBuf[len + 2] = 0x80 | ((inBuf[i + 0 + H_1] & 0x03) << 4) | ((inBuf[i + 2 + H_0] & 0x03) << 2) | ((inBuf[i + 2 + H_1] & 0xC0) >> 6);
+ outBuf[len + 3] = 0x80 | ((inBuf[i + 2 + H_1] & 0x3F) >> 0);
+
+ i += 2;
+ len += 4;
+ } else {
+ /* 0800-FFFF -> 1110xxxx 10xxxxxx 10xxxxxx */
+ /* abcdefgh ijklmnop -> 1110abcd 10efghij 10klmnop */
+
+ outBuf[len + 0] = 0xE0 | ((inBuf[i + H_0] & 0xF0) >> 4);
+ outBuf[len + 1] = 0x80 | ((inBuf[i + H_0] & 0x0F) << 2) | ((inBuf[i + H_1] & 0xC0) >> 6);
+ outBuf[len + 2] = 0x80 | ((inBuf[i + H_1] & 0x3F) >> 0);
+
+ len += 3;
+ }
+ }
+
+ *outBufLen = len;
+ return PR_TRUE;
+ }
+}
+
+PRBool
+sec_port_iso88591_utf8_conversion_function(
+ const unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen)
+{
+ unsigned int i, len = 0;
+
+ PORT_Assert((unsigned int *)NULL != outBufLen);
+
+ for (i = 0; i < inBufLen; i++) {
+ if ((inBuf[i] & 0x80) == 0x00)
+ len += 1;
+ else
+ len += 2;
+ }
+
+ if (len > maxOutBufLen) {
+ *outBufLen = len;
+ return PR_FALSE;
+ }
+
+ len = 0;
+
+ for (i = 0; i < inBufLen; i++) {
+ if ((inBuf[i] & 0x80) == 0x00) {
+ /* 00-7F -> 0xxxxxxx */
+ /* 0abcdefg -> 0abcdefg */
+
+ outBuf[len] = inBuf[i];
+ len += 1;
+ } else {
+ /* 80-FF <- 110xxxxx 10xxxxxx */
+ /* 00000000 abcdefgh -> 110000ab 10cdefgh */
+
+ outBuf[len + 0] = 0xC0 | ((inBuf[i] & 0xC0) >> 6);
+ outBuf[len + 1] = 0x80 | ((inBuf[i] & 0x3F) >> 0);
+
+ len += 2;
+ }
+ }
+
+ *outBufLen = len;
+ return PR_TRUE;
+}
diff --git a/security/nss/lib/util/util.gyp b/security/nss/lib/util/util.gyp
new file mode 100644
index 0000000000..74eaef4bfb
--- /dev/null
+++ b/security/nss/lib/util/util.gyp
@@ -0,0 +1,60 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.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': 'nssutil',
+ 'type': 'static_library',
+ 'sources': [
+ 'derdec.c',
+ 'derenc.c',
+ 'dersubr.c',
+ 'dertime.c',
+ 'errstrs.c',
+ 'nssb64d.c',
+ 'nssb64e.c',
+ 'nssilock.c',
+ 'nssrwlk.c',
+ 'oidstring.c',
+ 'pkcs1sig.c',
+ 'pkcs11uri.c',
+ 'portreg.c',
+ 'quickder.c',
+ 'secalgid.c',
+ 'secasn1d.c',
+ 'secasn1e.c',
+ 'secasn1u.c',
+ 'secdig.c',
+ 'secitem.c',
+ 'secload.c',
+ 'secoid.c',
+ 'secport.c',
+ 'sectime.c',
+ 'templates.c',
+ 'utf8.c',
+ 'utilmod.c',
+ 'utilpars.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ },
+ {
+ 'target_name': 'nssutil3',
+ 'type': 'shared_library',
+ 'dependencies': [
+ 'nssutil'
+ ],
+ 'variables': {
+ 'mapfile': 'nssutil.def'
+ }
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/lib/util/utilmod.c b/security/nss/lib/util/utilmod.c
new file mode 100644
index 0000000000..3ed7b3dd61
--- /dev/null
+++ b/security/nss/lib/util/utilmod.c
@@ -0,0 +1,946 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * The following code handles the storage of PKCS 11 modules used by the
+ * NSS. For the rest of NSS, only one kind of database handle exists:
+ *
+ * SFTKDBHandle
+ *
+ * There is one SFTKDBHandle for each key database and one for each cert
+ * database. These databases are opened as associated pairs, one pair per
+ * slot. SFTKDBHandles are reference counted objects.
+ *
+ * Each SFTKDBHandle points to a low level database handle (SDB). This handle
+ * represents the underlying physical database. These objects are not
+ * reference counted, and are 'owned' by their respective SFTKDBHandles.
+ */
+
+#include "prprf.h"
+#include "prsystem.h"
+#include "secport.h"
+#include "utilpars.h"
+#include "secerr.h"
+
+#if defined(_WIN32)
+#include <io.h>
+#include <windows.h>
+#endif
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#if defined(_WIN32)
+#define os_fdopen _fdopen
+#define os_truncate_open_flags _O_CREAT | _O_RDWR | _O_TRUNC
+#define os_append_open_flags _O_CREAT | _O_RDWR | _O_APPEND
+#define os_open_permissions_type int
+#define os_open_permissions_default _S_IREAD | _S_IWRITE
+#define os_stat_type struct _stat
+
+/*
+ * Convert a UTF8 string to Unicode wide character
+ */
+LPWSTR
+_NSSUTIL_UTF8ToWide(const char *buf)
+{
+ DWORD size;
+ LPWSTR wide;
+
+ if (!buf) {
+ return NULL;
+ }
+
+ size = MultiByteToWideChar(CP_UTF8, 0, buf, -1, NULL, 0);
+ if (size == 0) {
+ return NULL;
+ }
+ wide = PORT_Alloc(sizeof(WCHAR) * size);
+ if (!wide) {
+ return NULL;
+ }
+ size = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wide, size);
+ if (size == 0) {
+ PORT_Free(wide);
+ return NULL;
+ }
+ return wide;
+}
+
+static int
+os_open(const char *filename, int oflag, int pmode)
+{
+ int fd;
+
+ if (!filename) {
+ return -1;
+ }
+
+ wchar_t *filenameWide = _NSSUTIL_UTF8ToWide(filename);
+ if (!filenameWide) {
+ return -1;
+ }
+ fd = _wopen(filenameWide, oflag, pmode);
+ PORT_Free(filenameWide);
+
+ return fd;
+}
+
+static int
+os_stat(const char *path, os_stat_type *buffer)
+{
+ int result;
+
+ if (!path) {
+ return -1;
+ }
+
+ wchar_t *pathWide = _NSSUTIL_UTF8ToWide(path);
+ if (!pathWide) {
+ return -1;
+ }
+ result = _wstat(pathWide, buffer);
+ PORT_Free(pathWide);
+
+ return result;
+}
+
+static FILE *
+os_fopen(const char *filename, const char *mode)
+{
+ FILE *fp;
+
+ if (!filename || !mode) {
+ return NULL;
+ }
+
+ wchar_t *filenameWide = _NSSUTIL_UTF8ToWide(filename);
+ if (!filenameWide) {
+ return NULL;
+ }
+ wchar_t *modeWide = _NSSUTIL_UTF8ToWide(mode);
+ if (!modeWide) {
+ PORT_Free(filenameWide);
+ return NULL;
+ }
+ fp = _wfopen(filenameWide, modeWide);
+ PORT_Free(filenameWide);
+ PORT_Free(modeWide);
+
+ return fp;
+}
+
+PRStatus
+_NSSUTIL_Access(const char *path, PRAccessHow how)
+{
+ int result;
+
+ if (!path) {
+ return PR_FAILURE;
+ }
+
+ int mode;
+ switch (how) {
+ case PR_ACCESS_WRITE_OK:
+ mode = 2;
+ break;
+ case PR_ACCESS_READ_OK:
+ mode = 4;
+ break;
+ case PR_ACCESS_EXISTS:
+ mode = 0;
+ break;
+ default:
+ return PR_FAILURE;
+ }
+
+ wchar_t *pathWide = _NSSUTIL_UTF8ToWide(path);
+ if (!pathWide) {
+ return PR_FAILURE;
+ }
+ result = _waccess(pathWide, mode);
+ PORT_Free(pathWide);
+
+ return result < 0 ? PR_FAILURE : PR_SUCCESS;
+}
+
+static PRStatus
+nssutil_Delete(const char *name)
+{
+ BOOL result;
+
+ if (!name) {
+ return PR_FAILURE;
+ }
+
+ wchar_t *nameWide = _NSSUTIL_UTF8ToWide(name);
+ if (!nameWide) {
+ return PR_FAILURE;
+ }
+ result = DeleteFileW(nameWide);
+ PORT_Free(nameWide);
+
+ return result ? PR_SUCCESS : PR_FAILURE;
+}
+
+static PRStatus
+nssutil_Rename(const char *from, const char *to)
+{
+ BOOL result;
+
+ if (!from || !to) {
+ return PR_FAILURE;
+ }
+
+ wchar_t *fromWide = _NSSUTIL_UTF8ToWide(from);
+ if (!fromWide) {
+ return PR_FAILURE;
+ }
+ wchar_t *toWide = _NSSUTIL_UTF8ToWide(to);
+ if (!toWide) {
+ PORT_Free(fromWide);
+ return PR_FAILURE;
+ }
+ result = MoveFileW(fromWide, toWide);
+ PORT_Free(fromWide);
+ PORT_Free(toWide);
+
+ return result ? PR_SUCCESS : PR_FAILURE;
+}
+#else
+#define os_fopen fopen
+#define os_open open
+#define os_fdopen fdopen
+#define os_stat stat
+#define os_truncate_open_flags O_CREAT | O_RDWR | O_TRUNC
+#define os_append_open_flags O_CREAT | O_RDWR | O_APPEND
+#define os_open_permissions_type mode_t
+#define os_open_permissions_default 0600
+#define os_stat_type struct stat
+#define nssutil_Delete PR_Delete
+#define nssutil_Rename PR_Rename
+#endif
+
+/****************************************************************
+ *
+ * Secmod database.
+ *
+ * The new secmod database is simply a text file with each of the module
+ * entries in the following form:
+ *
+ * #
+ * # This is a comment The next line is the library to load
+ * library=libmypkcs11.so
+ * name="My PKCS#11 module"
+ * params="my library's param string"
+ * nss="NSS parameters"
+ * other="parameters for other libraries and applications"
+ *
+ * library=libmynextpk11.so
+ * name="My other PKCS#11 module"
+ */
+
+/*
+ * Smart string cat functions. Automatically manage the memory.
+ * The first parameter is the destination string. If it's null, we
+ * allocate memory for it. If it's not, we reallocate memory
+ * so the the concanenated string fits.
+ */
+static char *
+nssutil_DupnCat(char *baseString, const char *str, int str_len)
+{
+ int baseStringLen = baseString ? PORT_Strlen(baseString) : 0;
+ int len = baseStringLen + 1;
+ char *newString;
+
+ len += str_len;
+ newString = (char *)PORT_Realloc(baseString, len);
+ if (newString == NULL) {
+ PORT_Free(baseString);
+ return NULL;
+ }
+ PORT_Memcpy(&newString[baseStringLen], str, str_len);
+ newString[len - 1] = 0;
+ return newString;
+}
+
+/* Same as nssutil_DupnCat except it concatenates the full string, not a
+ * partial one */
+static char *
+nssutil_DupCat(char *baseString, const char *str)
+{
+ return nssutil_DupnCat(baseString, str, PORT_Strlen(str));
+}
+
+/* function to free up all the memory associated with a null terminated
+ * array of module specs */
+static SECStatus
+nssutil_releaseSpecList(char **moduleSpecList)
+{
+ if (moduleSpecList) {
+ char **index;
+ for (index = moduleSpecList; *index; index++) {
+ PORT_Free(*index);
+ }
+ PORT_Free(moduleSpecList);
+ }
+ return SECSuccess;
+}
+
+#define SECMOD_STEP 10
+static SECStatus
+nssutil_growList(char ***pModuleList, int *useCount, int last)
+{
+ char **newModuleList;
+
+ *useCount += SECMOD_STEP;
+ newModuleList = (char **)PORT_Realloc(*pModuleList,
+ *useCount * sizeof(char *));
+ if (newModuleList == NULL) {
+ return SECFailure;
+ }
+ PORT_Memset(&newModuleList[last], 0, sizeof(char *) * SECMOD_STEP);
+ *pModuleList = newModuleList;
+ return SECSuccess;
+}
+
+static char *
+_NSSUTIL_GetOldSecmodName(const char *dbname, const char *filename)
+{
+ char *file = NULL;
+ char *dirPath = PORT_Strdup(dbname);
+ char *sep;
+
+ sep = PORT_Strrchr(dirPath, *NSSUTIL_PATH_SEPARATOR);
+#ifdef _WIN32
+ if (!sep) {
+ /* utilparst.h defines NSSUTIL_PATH_SEPARATOR as "/" for all
+ * platforms. */
+ sep = PORT_Strrchr(dirPath, '\\');
+ }
+#endif
+ if (sep) {
+ *sep = 0;
+ file = PR_smprintf("%s" NSSUTIL_PATH_SEPARATOR "%s", dirPath, filename);
+ } else {
+ file = PR_smprintf("%s", filename);
+ }
+ PORT_Free(dirPath);
+ return file;
+}
+
+static SECStatus nssutil_AddSecmodDBEntry(const char *appName,
+ const char *filename,
+ const char *dbname,
+ const char *module, PRBool rw);
+
+enum lfopen_mode { lfopen_truncate,
+ lfopen_append };
+
+FILE *
+lfopen(const char *name, enum lfopen_mode om, os_open_permissions_type open_perms)
+{
+ int fd;
+ FILE *file;
+
+ fd = os_open(name,
+ (om == lfopen_truncate) ? os_truncate_open_flags : os_append_open_flags,
+ open_perms);
+ if (fd < 0) {
+ return NULL;
+ }
+ file = os_fdopen(fd, (om == lfopen_truncate) ? "w+" : "a+");
+ if (!file) {
+ close(fd);
+ }
+ /* file inherits fd */
+ return file;
+}
+
+#define MAX_LINE_LENGTH 2048
+
+/*
+ * Read all the existing modules in out of the file.
+ */
+static char **
+nssutil_ReadSecmodDB(const char *appName,
+ const char *filename, const char *dbname,
+ char *params, PRBool rw)
+{
+ FILE *fd = NULL;
+ char **moduleList = NULL;
+ int moduleCount = 1;
+ int useCount = SECMOD_STEP;
+ char line[MAX_LINE_LENGTH];
+ PRBool internal = PR_FALSE;
+ PRBool skipParams = PR_FALSE;
+ char *moduleString = NULL;
+ char *paramsValue = NULL;
+ PRBool failed = PR_TRUE;
+
+ moduleList = (char **)PORT_ZAlloc(useCount * sizeof(char *));
+ if (moduleList == NULL)
+ return NULL;
+
+ if (dbname == NULL) {
+ goto return_default;
+ }
+
+ /* do we really want to use streams here */
+ fd = os_fopen(dbname, "r");
+ if (fd == NULL)
+ goto done;
+
+ /*
+ * the following loop takes line separated config lines and collapses
+ * the lines to a single string, escaping and quoting as necessary.
+ */
+ /* loop state variables */
+ moduleString = NULL; /* current concatenated string */
+ internal = PR_FALSE; /* is this an internal module */
+ skipParams = PR_FALSE; /* did we find an override parameter block*/
+ paramsValue = NULL; /* the current parameter block value */
+ do {
+ int len;
+
+ if (fgets(line, sizeof(line), fd) == NULL) {
+ goto endloop;
+ }
+
+ /* remove the ending newline */
+ len = PORT_Strlen(line);
+ if (len >= 2 && line[len - 2] == '\r' && line[len - 1] == '\n') {
+ len = len - 2;
+ line[len] = 0;
+ } else if (len && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
+ len--;
+ line[len] = 0;
+ }
+ if (*line == '#') {
+ continue;
+ }
+ if (*line != 0) {
+ /*
+ * The PKCS #11 group standard assumes blocks of strings
+ * separated by new lines, clumped by new lines. Internally
+ * we take strings separated by spaces, so we may need to escape
+ * certain spaces.
+ */
+ char *value = PORT_Strchr(line, '=');
+
+ /* there is no value, write out the stanza as is */
+ if (value == NULL || value[1] == 0) {
+ if (moduleString) {
+ moduleString = nssutil_DupnCat(moduleString, " ", 1);
+ if (moduleString == NULL)
+ goto loser;
+ }
+ moduleString = nssutil_DupCat(moduleString, line);
+ if (moduleString == NULL)
+ goto loser;
+ /* value is already quoted, just write it out */
+ } else if (value[1] == '"') {
+ if (moduleString) {
+ moduleString = nssutil_DupnCat(moduleString, " ", 1);
+ if (moduleString == NULL)
+ goto loser;
+ }
+ moduleString = nssutil_DupCat(moduleString, line);
+ if (moduleString == NULL)
+ goto loser;
+ /* we have an override parameter section, remember that
+ * we found this (see following comment about why this
+ * is necessary). */
+ if (PORT_Strncasecmp(line, "parameters", 10) == 0) {
+ skipParams = PR_TRUE;
+ }
+ /*
+ * The internal token always overrides it's parameter block
+ * from the passed in parameters, so wait until then end
+ * before we include the parameter block in case we need to
+ * override it. NOTE: if the parameter block is quoted with ("),
+ * this override does not happen. This allows you to override
+ * the application's parameter configuration.
+ *
+ * parameter block state is controlled by the following variables:
+ * skipParams - Bool : set to true of we have an override param
+ * block (all other blocks, either implicit or explicit are
+ * ignored).
+ * paramsValue - char * : pointer to the current param block. In
+ * the absence of overrides, paramsValue is set to the first
+ * parameter block we find. All subsequent blocks are ignored.
+ * When we find an internal token, the application passed
+ * parameters take precident.
+ */
+ } else if (PORT_Strncasecmp(line, "parameters", 10) == 0) {
+ /* already have parameters */
+ if (paramsValue) {
+ continue;
+ }
+ paramsValue = NSSUTIL_Quote(&value[1], '"');
+ if (paramsValue == NULL)
+ goto loser;
+ continue;
+ } else {
+ /* may need to quote */
+ char *newLine;
+ if (moduleString) {
+ moduleString = nssutil_DupnCat(moduleString, " ", 1);
+ if (moduleString == NULL)
+ goto loser;
+ }
+ moduleString = nssutil_DupnCat(moduleString, line, value - line + 1);
+ if (moduleString == NULL)
+ goto loser;
+ newLine = NSSUTIL_Quote(&value[1], '"');
+ if (newLine == NULL)
+ goto loser;
+ moduleString = nssutil_DupCat(moduleString, newLine);
+ PORT_Free(newLine);
+ if (moduleString == NULL)
+ goto loser;
+ }
+
+ /* check to see if it's internal? */
+ if (PORT_Strncasecmp(line, "NSS=", 4) == 0) {
+ /* This should be case insensitive! reviewers make
+ * me fix it if it's not */
+ if (PORT_Strstr(line, "internal")) {
+ internal = PR_TRUE;
+ /* override the parameters */
+ if (paramsValue) {
+ PORT_Free(paramsValue);
+ }
+ paramsValue = NSSUTIL_Quote(params, '"');
+ }
+ }
+ continue;
+ }
+ if ((moduleString == NULL) || (*moduleString == 0)) {
+ continue;
+ }
+
+ endloop:
+ /*
+ * if we are here, we have found a complete stanza. Now write out
+ * any param section we may have found.
+ */
+ if (paramsValue) {
+ /* we had an override */
+ if (!skipParams) {
+ moduleString = nssutil_DupnCat(moduleString, " parameters=", 12);
+ if (moduleString == NULL)
+ goto loser;
+ moduleString = nssutil_DupCat(moduleString, paramsValue);
+ if (moduleString == NULL)
+ goto loser;
+ }
+ PORT_Free(paramsValue);
+ paramsValue = NULL;
+ }
+
+ if ((moduleCount + 1) >= useCount) {
+ SECStatus rv;
+ rv = nssutil_growList(&moduleList, &useCount, moduleCount + 1);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+
+ if (internal) {
+ moduleList[0] = moduleString;
+ } else {
+ moduleList[moduleCount] = moduleString;
+ moduleCount++;
+ }
+ moduleString = NULL;
+ internal = PR_FALSE;
+ skipParams = PR_FALSE;
+ } while (!feof(fd));
+
+ if (moduleString) {
+ PORT_Free(moduleString);
+ moduleString = NULL;
+ }
+done:
+ /* if we couldn't open a pkcs11 database, look for the old one */
+ if (fd == NULL) {
+ char *olddbname = _NSSUTIL_GetOldSecmodName(dbname, filename);
+ PRStatus status;
+
+ /* couldn't get the old name */
+ if (!olddbname) {
+ goto bail;
+ }
+
+ /* old one exists */
+ status = _NSSUTIL_Access(olddbname, PR_ACCESS_EXISTS);
+ if (status == PR_SUCCESS) {
+ PR_smprintf_free(olddbname);
+ PORT_ZFree(moduleList, useCount * sizeof(char *));
+ PORT_SetError(SEC_ERROR_LEGACY_DATABASE);
+ return NULL;
+ }
+
+ bail:
+ if (olddbname) {
+ PR_smprintf_free(olddbname);
+ }
+ }
+
+return_default:
+
+ if (!moduleList[0]) {
+ char *newParams;
+ moduleString = PORT_Strdup(NSSUTIL_DEFAULT_INTERNAL_INIT1);
+ newParams = NSSUTIL_Quote(params, '"');
+ if (newParams == NULL)
+ goto loser;
+ moduleString = nssutil_DupCat(moduleString, newParams);
+ PORT_Free(newParams);
+ if (moduleString == NULL)
+ goto loser;
+ moduleString = nssutil_DupCat(moduleString,
+ NSSUTIL_DEFAULT_INTERNAL_INIT2);
+ if (moduleString == NULL)
+ goto loser;
+ moduleString = nssutil_DupCat(moduleString,
+ NSSUTIL_DEFAULT_SFTKN_FLAGS);
+ if (moduleString == NULL)
+ goto loser;
+ moduleString = nssutil_DupCat(moduleString,
+ NSSUTIL_DEFAULT_INTERNAL_INIT3);
+ if (moduleString == NULL)
+ goto loser;
+ moduleList[0] = moduleString;
+ moduleString = NULL;
+ }
+ failed = PR_FALSE;
+
+loser:
+ /*
+ * cleanup
+ */
+ /* deal with trust cert db here */
+ if (moduleString) {
+ PORT_Free(moduleString);
+ moduleString = NULL;
+ }
+ if (paramsValue) {
+ PORT_Free(paramsValue);
+ paramsValue = NULL;
+ }
+ if (failed || (moduleList[0] == NULL)) {
+ /* This is wrong! FIXME */
+ nssutil_releaseSpecList(moduleList);
+ moduleList = NULL;
+ failed = PR_TRUE;
+ }
+ if (fd != NULL) {
+ fclose(fd);
+ } else if (!failed && rw) {
+ /* update our internal module */
+ nssutil_AddSecmodDBEntry(appName, filename, dbname, moduleList[0], rw);
+ }
+ return moduleList;
+}
+
+static SECStatus
+nssutil_ReleaseSecmodDBData(const char *appName,
+ const char *filename, const char *dbname,
+ char **moduleSpecList, PRBool rw)
+{
+ if (moduleSpecList) {
+ nssutil_releaseSpecList(moduleSpecList);
+ }
+ return SECSuccess;
+}
+
+/*
+ * Delete a module from the Data Base
+ */
+static SECStatus
+nssutil_DeleteSecmodDBEntry(const char *appName,
+ const char *filename,
+ const char *dbname,
+ const char *args,
+ PRBool rw)
+{
+ /* SHDB_FIXME implement */
+ os_stat_type stat_existing;
+ os_open_permissions_type file_mode;
+ FILE *fd = NULL;
+ FILE *fd2 = NULL;
+ char line[MAX_LINE_LENGTH];
+ char *dbname2 = NULL;
+ char *block = NULL;
+ char *name = NULL;
+ char *lib = NULL;
+ int name_len = 0, lib_len = 0;
+ PRBool skip = PR_FALSE;
+ PRBool found = PR_FALSE;
+
+ if (dbname == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (!rw) {
+ PORT_SetError(SEC_ERROR_READ_ONLY);
+ return SECFailure;
+ }
+
+ dbname2 = PORT_Strdup(dbname);
+ if (dbname2 == NULL)
+ goto loser;
+ dbname2[strlen(dbname) - 1]++;
+
+ /* get the permissions of the existing file, or use the default */
+ if (!os_stat(dbname, &stat_existing)) {
+ file_mode = stat_existing.st_mode;
+ } else {
+ file_mode = os_open_permissions_default;
+ }
+
+ /* do we really want to use streams here */
+ fd = os_fopen(dbname, "r");
+ if (fd == NULL)
+ goto loser;
+
+ fd2 = lfopen(dbname2, lfopen_truncate, file_mode);
+
+ if (fd2 == NULL)
+ goto loser;
+
+ name = NSSUTIL_ArgGetParamValue("name", args);
+ if (name) {
+ name_len = PORT_Strlen(name);
+ }
+ lib = NSSUTIL_ArgGetParamValue("library", args);
+ if (lib) {
+ lib_len = PORT_Strlen(lib);
+ }
+
+ /*
+ * the following loop takes line separated config files and collapses
+ * the lines to a single string, escaping and quoting as necessary.
+ */
+ /* loop state variables */
+ block = NULL;
+ skip = PR_FALSE;
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ /* If we are processing a block (we haven't hit a blank line yet */
+ if (*line != '\n') {
+ /* skip means we are in the middle of a block we are deleting */
+ if (skip) {
+ continue;
+ }
+ /* if we haven't found the block yet, check to see if this block
+ * matches our requirements */
+ if (!found && ((name && (PORT_Strncasecmp(line, "name=", 5) == 0) &&
+ (PORT_Strncmp(line + 5, name, name_len) == 0)) ||
+ (lib && (PORT_Strncasecmp(line, "library=", 8) == 0) &&
+ (PORT_Strncmp(line + 8, lib, lib_len) == 0)))) {
+
+ /* yup, we don't need to save any more data, */
+ PORT_Free(block);
+ block = NULL;
+ /* we don't need to collect more of this block */
+ skip = PR_TRUE;
+ /* we don't need to continue searching for the block */
+ found = PR_TRUE;
+ continue;
+ }
+ /* not our match, continue to collect data in this block */
+ block = nssutil_DupCat(block, line);
+ continue;
+ }
+ /* we've collected a block of data that wasn't the module we were
+ * looking for, write it out */
+ if (block) {
+ fwrite(block, PORT_Strlen(block), 1, fd2);
+ PORT_Free(block);
+ block = NULL;
+ }
+ /* If we didn't just delete the this block, keep the blank line */
+ if (!skip) {
+ fputs(line, fd2);
+ }
+ /* we are definately not in a deleted block anymore */
+ skip = PR_FALSE;
+ }
+ fclose(fd);
+ fclose(fd2);
+ if (found) {
+ /* rename dbname2 to dbname */
+ nssutil_Delete(dbname);
+ nssutil_Rename(dbname2, dbname);
+ } else {
+ nssutil_Delete(dbname2);
+ }
+ PORT_Free(dbname2);
+ PORT_Free(lib);
+ PORT_Free(name);
+ PORT_Free(block);
+ return SECSuccess;
+
+loser:
+ if (fd != NULL) {
+ fclose(fd);
+ }
+ if (fd2 != NULL) {
+ fclose(fd2);
+ }
+ if (dbname2) {
+ nssutil_Delete(dbname2);
+ PORT_Free(dbname2);
+ }
+ PORT_Free(lib);
+ PORT_Free(name);
+ return SECFailure;
+}
+
+/*
+ * Add a module to the Data base
+ */
+static SECStatus
+nssutil_AddSecmodDBEntry(const char *appName,
+ const char *filename, const char *dbname,
+ const char *module, PRBool rw)
+{
+ os_stat_type stat_existing;
+ os_open_permissions_type file_mode;
+ FILE *fd = NULL;
+ char *block = NULL;
+ PRBool libFound = PR_FALSE;
+
+ if (dbname == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ /* can't write to a read only module */
+ if (!rw) {
+ PORT_SetError(SEC_ERROR_READ_ONLY);
+ return SECFailure;
+ }
+
+ /* remove the previous version if it exists */
+ (void)nssutil_DeleteSecmodDBEntry(appName, filename, dbname, module, rw);
+
+ /* get the permissions of the existing file, or use the default */
+ if (!os_stat(dbname, &stat_existing)) {
+ file_mode = stat_existing.st_mode;
+ } else {
+ file_mode = os_open_permissions_default;
+ }
+
+ fd = lfopen(dbname, lfopen_append, file_mode);
+ if (fd == NULL) {
+ return SECFailure;
+ }
+ module = NSSUTIL_ArgStrip(module);
+ while (*module) {
+ int count;
+ char *keyEnd = PORT_Strchr(module, '=');
+ char *value;
+
+ if (PORT_Strncmp(module, "library=", 8) == 0) {
+ libFound = PR_TRUE;
+ }
+ if (keyEnd == NULL) {
+ block = nssutil_DupCat(block, module);
+ break;
+ }
+ block = nssutil_DupnCat(block, module, keyEnd - module + 1);
+ if (block == NULL) {
+ goto loser;
+ }
+ value = NSSUTIL_ArgFetchValue(&keyEnd[1], &count);
+ if (value) {
+ block = nssutil_DupCat(block, NSSUTIL_ArgStrip(value));
+ PORT_Free(value);
+ }
+ if (block == NULL) {
+ goto loser;
+ }
+ block = nssutil_DupnCat(block, "\n", 1);
+ module = keyEnd + 1 + count;
+ module = NSSUTIL_ArgStrip(module);
+ }
+ if (block) {
+ if (!libFound) {
+ fprintf(fd, "library=\n");
+ }
+ fwrite(block, PORT_Strlen(block), 1, fd);
+ fprintf(fd, "\n");
+ PORT_Free(block);
+ block = NULL;
+ }
+ fclose(fd);
+ return SECSuccess;
+
+loser:
+ PORT_Free(block);
+ fclose(fd);
+ return SECFailure;
+}
+
+char **
+NSSUTIL_DoModuleDBFunction(unsigned long function, char *parameters, void *args)
+{
+ char *secmod = NULL;
+ char *appName = NULL;
+ char *filename = NULL;
+ NSSDBType dbType = NSS_DB_TYPE_NONE;
+ PRBool rw;
+ static char *success = "Success";
+ char **rvstr = NULL;
+
+ secmod = _NSSUTIL_GetSecmodName(parameters, &dbType, &appName,
+ &filename, &rw);
+ if ((dbType == NSS_DB_TYPE_LEGACY) ||
+ (dbType == NSS_DB_TYPE_MULTIACCESS)) {
+ /* we can't handle the old database, only softoken can */
+ PORT_SetError(SEC_ERROR_LEGACY_DATABASE);
+ rvstr = NULL;
+ goto done;
+ }
+
+ switch (function) {
+ case SECMOD_MODULE_DB_FUNCTION_FIND:
+ rvstr = nssutil_ReadSecmodDB(appName, filename,
+ secmod, (char *)parameters, rw);
+ break;
+ case SECMOD_MODULE_DB_FUNCTION_ADD:
+ rvstr = (nssutil_AddSecmodDBEntry(appName, filename,
+ secmod, (char *)args, rw) == SECSuccess)
+ ? &success
+ : NULL;
+ break;
+ case SECMOD_MODULE_DB_FUNCTION_DEL:
+ rvstr = (nssutil_DeleteSecmodDBEntry(appName, filename,
+ secmod, (char *)args, rw) == SECSuccess)
+ ? &success
+ : NULL;
+ break;
+ case SECMOD_MODULE_DB_FUNCTION_RELEASE:
+ rvstr = (nssutil_ReleaseSecmodDBData(appName, filename,
+ secmod, (char **)args, rw) == SECSuccess)
+ ? &success
+ : NULL;
+ break;
+ }
+done:
+ if (secmod)
+ PR_smprintf_free(secmod);
+ if (appName)
+ PORT_Free(appName);
+ if (filename)
+ PORT_Free(filename);
+ return rvstr;
+}
diff --git a/security/nss/lib/util/utilmodt.h b/security/nss/lib/util/utilmodt.h
new file mode 100644
index 0000000000..e1555f37fa
--- /dev/null
+++ b/security/nss/lib/util/utilmodt.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/. */
+
+#ifndef _UTILMODT_H_
+#define _UTILMODT_H_ 1
+
+/*
+ * these are SECMOD flags that would normally be in secmodt.h, but are needed
+ * for the parser in util. Fort this reason we preserve the SECMOD names.
+ */
+#define SECMOD_RSA_FLAG 0x00000001L
+#define SECMOD_DSA_FLAG 0x00000002L
+#define SECMOD_RC2_FLAG 0x00000004L
+#define SECMOD_RC4_FLAG 0x00000008L
+#define SECMOD_DES_FLAG 0x00000010L
+#define SECMOD_DH_FLAG 0x00000020L
+#define SECMOD_FORTEZZA_FLAG 0x00000040L
+#define SECMOD_RC5_FLAG 0x00000080L
+#define SECMOD_SHA1_FLAG 0x00000100L
+#define SECMOD_MD5_FLAG 0x00000200L
+#define SECMOD_MD2_FLAG 0x00000400L
+#define SECMOD_SSL_FLAG 0x00000800L
+#define SECMOD_TLS_FLAG 0x00001000L
+#define SECMOD_AES_FLAG 0x00002000L
+#define SECMOD_SHA256_FLAG 0x00004000L /* also for SHA224 */
+#define SECMOD_SHA512_FLAG 0x00008000L /* also for SHA384 */
+#define SECMOD_CAMELLIA_FLAG 0x00010000L /* = PUBLIC_MECH_CAMELLIA_FLAG */
+#define SECMOD_SEED_FLAG 0x00020000L
+#define SECMOD_ECC_FLAG 0x00040000L
+/* reserved bit for future, do not use */
+#define SECMOD_RESERVED_FLAG 0X08000000L
+#define SECMOD_FRIENDLY_FLAG 0x10000000L
+#define SECMOD_RANDOM_FLAG 0x80000000L
+
+#define PK11_OWN_PW_DEFAULTS 0x20000000L
+#define PK11_DISABLE_FLAG 0x40000000L
+
+/* need to make SECMOD and PK11 prefixes consistent. */
+#define SECMOD_OWN_PW_DEFAULTS PK11_OWN_PW_DEFAULTS
+#define SECMOD_DISABLE_FLAG PK11_DISABLE_FLAG
+
+#endif /* _UTILMODT_H_ */
diff --git a/security/nss/lib/util/utilpars.c b/security/nss/lib/util/utilpars.c
new file mode 100644
index 0000000000..dd3d2326a9
--- /dev/null
+++ b/security/nss/lib/util/utilpars.c
@@ -0,0 +1,1314 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * The following code handles the storage of PKCS 11 modules used by the
+ * NSS. This file is written to abstract away how the modules are
+ * stored so we can decide that later.
+ */
+#include "secport.h"
+#include "prprf.h"
+#include "prenv.h"
+#include "utilpars.h"
+#include "utilmodt.h"
+
+/*
+ * return the expected matching quote value for the one specified
+ */
+PRBool
+NSSUTIL_ArgGetPair(char c)
+{
+ switch (c) {
+ case '\'':
+ return c;
+ case '\"':
+ return c;
+ case '<':
+ return '>';
+ case '{':
+ return '}';
+ case '[':
+ return ']';
+ case '(':
+ return ')';
+ default:
+ break;
+ }
+ return ' ';
+}
+
+PRBool
+NSSUTIL_ArgIsBlank(char c)
+{
+ return isspace((unsigned char)c);
+}
+
+PRBool
+NSSUTIL_ArgIsEscape(char c)
+{
+ return c == '\\';
+}
+
+PRBool
+NSSUTIL_ArgIsQuote(char c)
+{
+ switch (c) {
+ case '\'':
+ case '\"':
+ case '<':
+ case '{': /* } end curly to keep vi bracket matching working */
+ case '(': /* ) */
+ case '[': /* ] */
+ return PR_TRUE;
+ default:
+ break;
+ }
+ return PR_FALSE;
+}
+
+const char *
+NSSUTIL_ArgStrip(const char *c)
+{
+ while (*c && NSSUTIL_ArgIsBlank(*c))
+ c++;
+ return c;
+}
+
+/*
+ * find the end of the current tag/value pair. string should be pointing just
+ * after the equal sign. Handles quoted characters.
+ */
+const char *
+NSSUTIL_ArgFindEnd(const char *string)
+{
+ char endChar = ' ';
+ PRBool lastEscape = PR_FALSE;
+
+ if (NSSUTIL_ArgIsQuote(*string)) {
+ endChar = NSSUTIL_ArgGetPair(*string);
+ string++;
+ }
+
+ for (; *string; string++) {
+ if (lastEscape) {
+ lastEscape = PR_FALSE;
+ continue;
+ }
+ if (NSSUTIL_ArgIsEscape(*string) && !lastEscape) {
+ lastEscape = PR_TRUE;
+ continue;
+ }
+ if ((endChar == ' ') && NSSUTIL_ArgIsBlank(*string))
+ break;
+ if (*string == endChar) {
+ break;
+ }
+ }
+
+ return string;
+}
+
+/*
+ * get the value pointed to by string. string should be pointing just beyond
+ * the equal sign.
+ */
+char *
+NSSUTIL_ArgFetchValue(const char *string, int *pcount)
+{
+ const char *end = NSSUTIL_ArgFindEnd(string);
+ char *retString, *copyString;
+ PRBool lastEscape = PR_FALSE;
+ int len;
+
+ len = end - string;
+ if (len == 0) {
+ *pcount = 0;
+ return NULL;
+ }
+
+ copyString = retString = (char *)PORT_Alloc(len + 1);
+
+ if (*end)
+ len++;
+ *pcount = len;
+ if (retString == NULL)
+ return NULL;
+
+ if (NSSUTIL_ArgIsQuote(*string))
+ string++;
+ for (; string < end; string++) {
+ if (NSSUTIL_ArgIsEscape(*string) && !lastEscape) {
+ lastEscape = PR_TRUE;
+ continue;
+ }
+ lastEscape = PR_FALSE;
+ *copyString++ = *string;
+ }
+ *copyString = 0;
+ return retString;
+}
+
+/*
+ * point to the next parameter in string
+ */
+const char *
+NSSUTIL_ArgSkipParameter(const char *string)
+{
+ const char *end;
+ /* look for the end of the <name>= */
+ for (; *string; string++) {
+ if (*string == '=') {
+ string++;
+ break;
+ }
+ if (NSSUTIL_ArgIsBlank(*string))
+ return (string);
+ }
+
+ end = NSSUTIL_ArgFindEnd(string);
+ if (*end)
+ end++;
+ return end;
+}
+
+/*
+ * get the value from that tag value pair.
+ */
+char *
+NSSUTIL_ArgGetParamValue(const char *paramName, const char *parameters)
+{
+ char searchValue[256];
+ size_t paramLen = strlen(paramName);
+ char *returnValue = NULL;
+ int next;
+
+ if ((parameters == NULL) || (*parameters == 0))
+ return NULL;
+
+ PORT_Assert(paramLen + 2 < sizeof(searchValue));
+
+ PORT_Strcpy(searchValue, paramName);
+ PORT_Strcat(searchValue, "=");
+ while (*parameters) {
+ if (PORT_Strncasecmp(parameters, searchValue, paramLen + 1) == 0) {
+ parameters += paramLen + 1;
+ returnValue = NSSUTIL_ArgFetchValue(parameters, &next);
+ break;
+ } else {
+ parameters = NSSUTIL_ArgSkipParameter(parameters);
+ }
+ parameters = NSSUTIL_ArgStrip(parameters);
+ }
+ return returnValue;
+}
+
+/*
+ * find the next flag in the parameter list
+ */
+const char *
+NSSUTIL_ArgNextFlag(const char *flags)
+{
+ for (; *flags; flags++) {
+ if (*flags == ',') {
+ flags++;
+ break;
+ }
+ }
+ return flags;
+}
+
+/*
+ * return true if the flag is set in the label parameter.
+ */
+PRBool
+NSSUTIL_ArgHasFlag(const char *label, const char *flag, const char *parameters)
+{
+ char *flags;
+ const char *index;
+ int len = strlen(flag);
+ PRBool found = PR_FALSE;
+
+ flags = NSSUTIL_ArgGetParamValue(label, parameters);
+ if (flags == NULL)
+ return PR_FALSE;
+
+ for (index = flags; *index; index = NSSUTIL_ArgNextFlag(index)) {
+ if (PORT_Strncasecmp(index, flag, len) == 0) {
+ found = PR_TRUE;
+ break;
+ }
+ }
+ PORT_Free(flags);
+ return found;
+}
+
+/*
+ * decode a number. handle octal (leading '0'), hex (leading '0x') or decimal
+ */
+long
+NSSUTIL_ArgDecodeNumber(const char *num)
+{
+ int radix = 10;
+ unsigned long value = 0;
+ long retValue = 0;
+ int sign = 1;
+ int digit;
+
+ if (num == NULL)
+ return retValue;
+
+ num = NSSUTIL_ArgStrip(num);
+
+ if (*num == '-') {
+ sign = -1;
+ num++;
+ }
+
+ if (*num == '0') {
+ radix = 8;
+ num++;
+ if ((*num == 'x') || (*num == 'X')) {
+ radix = 16;
+ num++;
+ }
+ }
+
+ for (; *num; num++) {
+ if (isdigit(*num)) {
+ digit = *num - '0';
+ } else if ((*num >= 'a') && (*num <= 'f')) {
+ digit = *num - 'a' + 10;
+ } else if ((*num >= 'A') && (*num <= 'F')) {
+ digit = *num - 'A' + 10;
+ } else {
+ break;
+ }
+ if (digit >= radix)
+ break;
+ value = value * radix + digit;
+ }
+
+ retValue = ((int)value) * sign;
+ return retValue;
+}
+
+/*
+ * parameters are tag value pairs. This function returns the tag or label (the
+ * value before the equal size.
+ */
+char *
+NSSUTIL_ArgGetLabel(const char *inString, int *next)
+{
+ char *name = NULL;
+ const char *string;
+ int len;
+
+ /* look for the end of the <label>= */
+ for (string = inString; *string; string++) {
+ if (*string == '=') {
+ break;
+ }
+ if (NSSUTIL_ArgIsBlank(*string))
+ break;
+ }
+
+ len = string - inString;
+
+ *next = len;
+ if (*string == '=')
+ (*next) += 1;
+ if (len > 0) {
+ name = PORT_Alloc(len + 1);
+ PORT_Strncpy(name, inString, len);
+ name[len] = 0;
+ }
+ return name;
+}
+
+/*
+ * read an argument at a Long integer
+ */
+long
+NSSUTIL_ArgReadLong(const char *label, const char *params,
+ long defValue, PRBool *isdefault)
+{
+ char *value;
+ long retValue;
+ if (isdefault)
+ *isdefault = PR_FALSE;
+
+ value = NSSUTIL_ArgGetParamValue(label, params);
+ if (value == NULL) {
+ if (isdefault)
+ *isdefault = PR_TRUE;
+ return defValue;
+ }
+ retValue = NSSUTIL_ArgDecodeNumber(value);
+ if (value)
+ PORT_Free(value);
+
+ return retValue;
+}
+
+/*
+ * prepare a string to be quoted with 'quote' marks. We do that by adding
+ * appropriate escapes.
+ */
+static int
+nssutil_escapeQuotesSize(const char *string, char quote, PRBool addquotes)
+{
+ int escapes = 0, size = 0;
+ const char *src;
+
+ size = addquotes ? 2 : 0;
+ for (src = string; *src; src++) {
+ if ((*src == quote) || (*src == '\\'))
+ escapes++;
+ size++;
+ }
+ return size + escapes + 1;
+}
+
+static char *
+nssutil_escapeQuotes(const char *string, char quote, PRBool addquotes)
+{
+ char *newString = 0;
+ int size = 0;
+ const char *src;
+ char *dest;
+
+ size = nssutil_escapeQuotesSize(string, quote, addquotes);
+
+ dest = newString = PORT_ZAlloc(size);
+ if (newString == NULL) {
+ return NULL;
+ }
+
+ if (addquotes)
+ *dest++ = quote;
+ for (src = string; *src; src++, dest++) {
+ if ((*src == '\\') || (*src == quote)) {
+ *dest++ = '\\';
+ }
+ *dest = *src;
+ }
+ if (addquotes)
+ *dest = quote;
+
+ return newString;
+}
+
+int
+NSSUTIL_EscapeSize(const char *string, char quote)
+{
+ return nssutil_escapeQuotesSize(string, quote, PR_FALSE);
+}
+
+char *
+NSSUTIL_Escape(const char *string, char quote)
+{
+ return nssutil_escapeQuotes(string, quote, PR_FALSE);
+}
+
+int
+NSSUTIL_QuoteSize(const char *string, char quote)
+{
+ return nssutil_escapeQuotesSize(string, quote, PR_TRUE);
+}
+
+char *
+NSSUTIL_Quote(const char *string, char quote)
+{
+ return nssutil_escapeQuotes(string, quote, PR_TRUE);
+}
+
+int
+NSSUTIL_DoubleEscapeSize(const char *string, char quote1, char quote2)
+{
+ int escapes = 0, size = 0;
+ const char *src;
+ for (src = string; *src; src++) {
+ if (*src == '\\')
+ escapes += 3; /* \\\\ */
+ if (*src == quote1)
+ escapes += 2; /* \\quote1 */
+ if (*src == quote2)
+ escapes++; /* \quote2 */
+ size++;
+ }
+
+ return escapes + size + 1;
+}
+
+char *
+NSSUTIL_DoubleEscape(const char *string, char quote1, char quote2)
+{
+ char *round1 = NULL;
+ char *retValue = NULL;
+ if (string == NULL) {
+ goto done;
+ }
+ round1 = nssutil_escapeQuotes(string, quote1, PR_FALSE);
+ if (round1) {
+ retValue = nssutil_escapeQuotes(round1, quote2, PR_FALSE);
+ PORT_Free(round1);
+ }
+
+done:
+ if (retValue == NULL) {
+ retValue = PORT_Strdup("");
+ }
+ return retValue;
+}
+
+/************************************************************************
+ * These functions are used in contructing strings.
+ * NOTE: they will always return a string, but sometimes it will return
+ * a specific NULL string. These strings must be freed with util_freePair.
+ */
+
+/* string to return on error... */
+static char *nssutil_nullString = "";
+
+static char *
+nssutil_formatValue(PLArenaPool *arena, char *value, char quote)
+{
+ char *vp, *vp2, *retval;
+ int size = 0, escapes = 0;
+
+ for (vp = value; *vp; vp++) {
+ if ((*vp == quote) || (*vp == NSSUTIL_ARG_ESCAPE))
+ escapes++;
+ size++;
+ }
+ if (arena) {
+ retval = PORT_ArenaZAlloc(arena, size + escapes + 1);
+ } else {
+ retval = PORT_ZAlloc(size + escapes + 1);
+ }
+ if (retval == NULL)
+ return NULL;
+ vp2 = retval;
+ for (vp = value; *vp; vp++) {
+ if ((*vp == quote) || (*vp == NSSUTIL_ARG_ESCAPE))
+ *vp2++ = NSSUTIL_ARG_ESCAPE;
+ *vp2++ = *vp;
+ }
+ return retval;
+}
+
+static PRBool
+nssutil_argHasChar(char *v, char c)
+{
+ for (; *v; v++) {
+ if (*v == c)
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+static PRBool
+nssutil_argHasBlanks(char *v)
+{
+ for (; *v; v++) {
+ if (NSSUTIL_ArgIsBlank(*v))
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+static char *
+nssutil_formatPair(char *name, char *value, char quote)
+{
+ char openQuote = quote;
+ char closeQuote = NSSUTIL_ArgGetPair(quote);
+ char *newValue = NULL;
+ char *returnValue;
+ PRBool need_quote = PR_FALSE;
+
+ if (!value || (*value == 0))
+ return nssutil_nullString;
+
+ if (nssutil_argHasBlanks(value) || NSSUTIL_ArgIsQuote(value[0]))
+ need_quote = PR_TRUE;
+
+ if ((need_quote && nssutil_argHasChar(value, closeQuote)) || nssutil_argHasChar(value, NSSUTIL_ARG_ESCAPE)) {
+ value = newValue = nssutil_formatValue(NULL, value, quote);
+ if (newValue == NULL)
+ return nssutil_nullString;
+ }
+ if (need_quote) {
+ returnValue = PR_smprintf("%s=%c%s%c", name, openQuote, value, closeQuote);
+ } else {
+ returnValue = PR_smprintf("%s=%s", name, value);
+ }
+ if (returnValue == NULL)
+ returnValue = nssutil_nullString;
+
+ if (newValue)
+ PORT_Free(newValue);
+
+ return returnValue;
+}
+
+static char *
+nssutil_formatIntPair(char *name, unsigned long value,
+ unsigned long def)
+{
+ char *returnValue;
+
+ if (value == def)
+ return nssutil_nullString;
+
+ returnValue = PR_smprintf("%s=%d", name, value);
+
+ return returnValue;
+}
+
+static void
+nssutil_freePair(char *pair)
+{
+ if (pair && pair != nssutil_nullString) {
+ PR_smprintf_free(pair);
+ }
+}
+
+/************************************************************************
+ * Parse the Slot specific parameters in the NSS params.
+ */
+
+struct nssutilArgSlotFlagTable {
+ char *name;
+ int len;
+ unsigned long value;
+};
+
+#define NSSUTIL_ARG_ENTRY(arg, flag) \
+ { \
+#arg, sizeof(#arg) - 1, flag \
+ }
+static struct nssutilArgSlotFlagTable nssutil_argSlotFlagTable[] = {
+ NSSUTIL_ARG_ENTRY(RSA, SECMOD_RSA_FLAG),
+ NSSUTIL_ARG_ENTRY(ECC, SECMOD_ECC_FLAG),
+ NSSUTIL_ARG_ENTRY(DSA, SECMOD_RSA_FLAG),
+ NSSUTIL_ARG_ENTRY(RC2, SECMOD_RC4_FLAG),
+ NSSUTIL_ARG_ENTRY(RC4, SECMOD_RC2_FLAG),
+ NSSUTIL_ARG_ENTRY(DES, SECMOD_DES_FLAG),
+ NSSUTIL_ARG_ENTRY(DH, SECMOD_DH_FLAG),
+ NSSUTIL_ARG_ENTRY(FORTEZZA, SECMOD_FORTEZZA_FLAG),
+ NSSUTIL_ARG_ENTRY(RC5, SECMOD_RC5_FLAG),
+ NSSUTIL_ARG_ENTRY(SHA1, SECMOD_SHA1_FLAG),
+ NSSUTIL_ARG_ENTRY(SHA256, SECMOD_SHA256_FLAG),
+ NSSUTIL_ARG_ENTRY(SHA512, SECMOD_SHA512_FLAG),
+ NSSUTIL_ARG_ENTRY(MD5, SECMOD_MD5_FLAG),
+ NSSUTIL_ARG_ENTRY(MD2, SECMOD_MD2_FLAG),
+ NSSUTIL_ARG_ENTRY(SSL, SECMOD_SSL_FLAG),
+ NSSUTIL_ARG_ENTRY(TLS, SECMOD_TLS_FLAG),
+ NSSUTIL_ARG_ENTRY(AES, SECMOD_AES_FLAG),
+ NSSUTIL_ARG_ENTRY(Camellia, SECMOD_CAMELLIA_FLAG),
+ NSSUTIL_ARG_ENTRY(SEED, SECMOD_SEED_FLAG),
+ NSSUTIL_ARG_ENTRY(PublicCerts, SECMOD_FRIENDLY_FLAG),
+ NSSUTIL_ARG_ENTRY(RANDOM, SECMOD_RANDOM_FLAG),
+ NSSUTIL_ARG_ENTRY(Disable, SECMOD_DISABLE_FLAG),
+};
+
+static int nssutil_argSlotFlagTableSize =
+ sizeof(nssutil_argSlotFlagTable) / sizeof(nssutil_argSlotFlagTable[0]);
+
+/* turn the slot flags into a bit mask */
+unsigned long
+NSSUTIL_ArgParseSlotFlags(const char *label, const char *params)
+{
+ char *flags;
+ const char *index;
+ unsigned long retValue = 0;
+ int i;
+ PRBool all = PR_FALSE;
+
+ flags = NSSUTIL_ArgGetParamValue(label, params);
+ if (flags == NULL)
+ return 0;
+
+ if (PORT_Strcasecmp(flags, "all") == 0)
+ all = PR_TRUE;
+
+ for (index = flags; *index; index = NSSUTIL_ArgNextFlag(index)) {
+ for (i = 0; i < nssutil_argSlotFlagTableSize; i++) {
+ if (all ||
+ (PORT_Strncasecmp(index, nssutil_argSlotFlagTable[i].name,
+ nssutil_argSlotFlagTable[i].len) == 0)) {
+ retValue |= nssutil_argSlotFlagTable[i].value;
+ }
+ }
+ }
+ PORT_Free(flags);
+ return retValue;
+}
+
+/* parse a single slot specific parameter */
+static void
+nssutil_argDecodeSingleSlotInfo(char *name, char *params,
+ struct NSSUTILPreSlotInfoStr *slotInfo)
+{
+ char *askpw;
+
+ slotInfo->slotID = NSSUTIL_ArgDecodeNumber(name);
+ slotInfo->defaultFlags = NSSUTIL_ArgParseSlotFlags("slotFlags", params);
+ slotInfo->timeout = NSSUTIL_ArgReadLong("timeout", params, 0, NULL);
+
+ askpw = NSSUTIL_ArgGetParamValue("askpw", params);
+ slotInfo->askpw = 0;
+
+ if (askpw) {
+ if (PORT_Strcasecmp(askpw, "every") == 0) {
+ slotInfo->askpw = -1;
+ } else if (PORT_Strcasecmp(askpw, "timeout") == 0) {
+ slotInfo->askpw = 1;
+ }
+ PORT_Free(askpw);
+ slotInfo->defaultFlags |= PK11_OWN_PW_DEFAULTS;
+ }
+ slotInfo->hasRootCerts = NSSUTIL_ArgHasFlag("rootFlags", "hasRootCerts",
+ params);
+ slotInfo->hasRootTrust = NSSUTIL_ArgHasFlag("rootFlags", "hasRootTrust",
+ params);
+}
+
+/* parse all the slot specific parameters. */
+struct NSSUTILPreSlotInfoStr *
+NSSUTIL_ArgParseSlotInfo(PLArenaPool *arena, const char *slotParams,
+ int *retCount)
+{
+ const char *slotIndex;
+ struct NSSUTILPreSlotInfoStr *slotInfo = NULL;
+ int i = 0, count = 0, next;
+
+ *retCount = 0;
+ if ((slotParams == NULL) || (*slotParams == 0))
+ return NULL;
+
+ /* first count the number of slots */
+ for (slotIndex = NSSUTIL_ArgStrip(slotParams); *slotIndex;
+ slotIndex = NSSUTIL_ArgStrip(NSSUTIL_ArgSkipParameter(slotIndex))) {
+ count++;
+ }
+
+ /* get the data structures */
+ if (arena) {
+ slotInfo = PORT_ArenaZNewArray(arena,
+ struct NSSUTILPreSlotInfoStr, count);
+ } else {
+ slotInfo = PORT_ZNewArray(struct NSSUTILPreSlotInfoStr, count);
+ }
+ if (slotInfo == NULL)
+ return NULL;
+
+ for (slotIndex = NSSUTIL_ArgStrip(slotParams), i = 0;
+ *slotIndex && i < count;) {
+ char *name;
+ name = NSSUTIL_ArgGetLabel(slotIndex, &next);
+ slotIndex += next;
+
+ if (!NSSUTIL_ArgIsBlank(*slotIndex)) {
+ char *args = NSSUTIL_ArgFetchValue(slotIndex, &next);
+ slotIndex += next;
+ if (args) {
+ nssutil_argDecodeSingleSlotInfo(name, args, &slotInfo[i]);
+ i++;
+ PORT_Free(args);
+ }
+ }
+ if (name)
+ PORT_Free(name);
+ slotIndex = NSSUTIL_ArgStrip(slotIndex);
+ }
+ *retCount = i;
+ return slotInfo;
+}
+
+/************************************************************************
+ * make a new slot specific parameter
+ */
+/* first make the slot flags */
+static char *
+nssutil_mkSlotFlags(unsigned long defaultFlags)
+{
+ char *flags = NULL;
+ unsigned int i;
+ int j;
+
+ for (i = 0; i < sizeof(defaultFlags) * 8; i++) {
+ if (defaultFlags & (1UL << i)) {
+ char *string = NULL;
+
+ for (j = 0; j < nssutil_argSlotFlagTableSize; j++) {
+ if (nssutil_argSlotFlagTable[j].value == (1UL << i)) {
+ string = nssutil_argSlotFlagTable[j].name;
+ break;
+ }
+ }
+ if (string) {
+ if (flags) {
+ char *tmp;
+ tmp = PR_smprintf("%s,%s", flags, string);
+ PR_smprintf_free(flags);
+ flags = tmp;
+ } else {
+ flags = PR_smprintf("%s", string);
+ }
+ }
+ }
+ }
+
+ return flags;
+}
+
+/* now make the root flags */
+#define NSSUTIL_MAX_ROOT_FLAG_SIZE sizeof("hasRootCerts") + sizeof("hasRootTrust")
+static char *
+nssutil_mkRootFlags(PRBool hasRootCerts, PRBool hasRootTrust)
+{
+ char *flags = (char *)PORT_ZAlloc(NSSUTIL_MAX_ROOT_FLAG_SIZE);
+ PRBool first = PR_TRUE;
+
+ PORT_Memset(flags, 0, NSSUTIL_MAX_ROOT_FLAG_SIZE);
+ if (hasRootCerts) {
+ PORT_Strcat(flags, "hasRootCerts");
+ first = PR_FALSE;
+ }
+ if (hasRootTrust) {
+ if (!first)
+ PORT_Strcat(flags, ",");
+ PORT_Strcat(flags, "hasRootTrust");
+ }
+ return flags;
+}
+
+/* now make a full slot string */
+char *
+NSSUTIL_MkSlotString(unsigned long slotID, unsigned long defaultFlags,
+ unsigned long timeout, unsigned char askpw_in,
+ PRBool hasRootCerts, PRBool hasRootTrust)
+{
+ char *askpw, *flags, *rootFlags, *slotString;
+ char *flagPair, *rootFlagsPair;
+
+ switch (askpw_in) {
+ case 0xff:
+ askpw = "every";
+ break;
+ case 1:
+ askpw = "timeout";
+ break;
+ default:
+ askpw = "any";
+ break;
+ }
+ flags = nssutil_mkSlotFlags(defaultFlags);
+ rootFlags = nssutil_mkRootFlags(hasRootCerts, hasRootTrust);
+ flagPair = nssutil_formatPair("slotFlags", flags, '\'');
+ rootFlagsPair = nssutil_formatPair("rootFlags", rootFlags, '\'');
+ if (flags)
+ PR_smprintf_free(flags);
+ if (rootFlags)
+ PORT_Free(rootFlags);
+ if (defaultFlags & PK11_OWN_PW_DEFAULTS) {
+ slotString = PR_smprintf("0x%08lx=[%s askpw=%s timeout=%d %s]",
+ (PRUint32)slotID, flagPair, askpw, timeout,
+ rootFlagsPair);
+ } else {
+ slotString = PR_smprintf("0x%08lx=[%s %s]",
+ (PRUint32)slotID, flagPair, rootFlagsPair);
+ }
+ nssutil_freePair(flagPair);
+ nssutil_freePair(rootFlagsPair);
+ return slotString;
+}
+
+/************************************************************************
+ * Parse Full module specs into: library, commonName, module parameters,
+ * and NSS specifi parameters.
+ */
+SECStatus
+NSSUTIL_ArgParseModuleSpecEx(const char *modulespec, char **lib, char **mod,
+ char **parameters, char **nss,
+ char **config)
+{
+ int next;
+ modulespec = NSSUTIL_ArgStrip(modulespec);
+
+ *lib = *mod = *parameters = *nss = *config = 0;
+
+ while (*modulespec) {
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *lib, "library=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *mod, "name=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *parameters, "parameters=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *nss, "nss=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *config, "config=", ;)
+ NSSUTIL_HANDLE_FINAL_ARG(modulespec)
+ }
+ return SECSuccess;
+}
+
+/************************************************************************
+ * Parse Full module specs into: library, commonName, module parameters,
+ * and NSS specifi parameters.
+ */
+SECStatus
+NSSUTIL_ArgParseModuleSpec(const char *modulespec, char **lib, char **mod,
+ char **parameters, char **nss)
+{
+ int next;
+ modulespec = NSSUTIL_ArgStrip(modulespec);
+
+ *lib = *mod = *parameters = *nss = 0;
+
+ while (*modulespec) {
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *lib, "library=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *mod, "name=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *parameters, "parameters=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(modulespec, *nss, "nss=", ;)
+ NSSUTIL_HANDLE_FINAL_ARG(modulespec)
+ }
+ return SECSuccess;
+}
+
+/************************************************************************
+ * make a new module spec from it's components */
+char *
+NSSUTIL_MkModuleSpecEx(char *dllName, char *commonName, char *parameters,
+ char *NSS,
+ char *config)
+{
+ char *moduleSpec;
+ char *lib, *name, *param, *nss, *conf;
+
+ /*
+ * now the final spec
+ */
+ lib = nssutil_formatPair("library", dllName, '\"');
+ name = nssutil_formatPair("name", commonName, '\"');
+ param = nssutil_formatPair("parameters", parameters, '\"');
+ nss = nssutil_formatPair("NSS", NSS, '\"');
+ if (config) {
+ conf = nssutil_formatPair("config", config, '\"');
+ moduleSpec = PR_smprintf("%s %s %s %s %s", lib, name, param, nss, conf);
+ nssutil_freePair(conf);
+ } else {
+ moduleSpec = PR_smprintf("%s %s %s %s", lib, name, param, nss);
+ }
+ nssutil_freePair(lib);
+ nssutil_freePair(name);
+ nssutil_freePair(param);
+ nssutil_freePair(nss);
+ return (moduleSpec);
+}
+
+/************************************************************************
+ * make a new module spec from it's components */
+char *
+NSSUTIL_MkModuleSpec(char *dllName, char *commonName, char *parameters,
+ char *NSS)
+{
+ return NSSUTIL_MkModuleSpecEx(dllName, commonName, parameters, NSS, NULL);
+}
+
+/************************************************************************
+ * add a single flag to the Flags= section inside the spec's NSS= section */
+char *
+NSSUTIL_AddNSSFlagToModuleSpec(char *spec, char *addFlag)
+{
+ const char *prefix = "flags=";
+ const size_t prefixLen = strlen(prefix);
+ char *lib = NULL, *name = NULL, *param = NULL, *nss = NULL, *conf = NULL;
+ char *nss2 = NULL, *result = NULL;
+ SECStatus rv;
+
+ rv = NSSUTIL_ArgParseModuleSpecEx(spec, &lib, &name, &param, &nss, &conf);
+ if (rv != SECSuccess) {
+ return NULL;
+ }
+
+ if (nss && NSSUTIL_ArgHasFlag("flags", addFlag, nss)) {
+ /* It's already there, nothing to do! */
+ PORT_Free(lib);
+ PORT_Free(name);
+ PORT_Free(param);
+ PORT_Free(nss);
+ PORT_Free(conf);
+ return PORT_Strdup(spec);
+ }
+
+ if (!nss || !strlen(nss)) {
+ nss2 = PORT_Alloc(prefixLen + strlen(addFlag) + 1);
+ PORT_Strcpy(nss2, prefix);
+ PORT_Strcat(nss2, addFlag);
+ } else {
+ const char *iNss = nss;
+ PRBool alreadyAdded = PR_FALSE;
+ size_t maxSize = strlen(nss) + strlen(addFlag) + prefixLen + 2; /* space and null terminator */
+ nss2 = PORT_Alloc(maxSize);
+ *nss2 = 0;
+ while (*iNss) {
+ iNss = NSSUTIL_ArgStrip(iNss);
+ if (PORT_Strncasecmp(iNss, prefix, prefixLen) == 0) {
+ /* We found an existing Flags= section. */
+ char *oldFlags;
+ const char *valPtr;
+ int valSize;
+ valPtr = iNss + prefixLen;
+ oldFlags = NSSUTIL_ArgFetchValue(valPtr, &valSize);
+ iNss = valPtr + valSize;
+ PORT_Strcat(nss2, prefix);
+ PORT_Strcat(nss2, oldFlags);
+ PORT_Strcat(nss2, ",");
+ PORT_Strcat(nss2, addFlag);
+ PORT_Strcat(nss2, " ");
+ PORT_Free(oldFlags);
+ alreadyAdded = PR_TRUE;
+ iNss = NSSUTIL_ArgStrip(iNss);
+ PORT_Strcat(nss2, iNss); /* remainder of input */
+ break;
+ } else {
+ /* Append this other name=value pair and continue. */
+ const char *startOfNext = NSSUTIL_ArgSkipParameter(iNss);
+ PORT_Strncat(nss2, iNss, (startOfNext - iNss));
+ if (nss2[strlen(nss2) - 1] != ' ') {
+ PORT_Strcat(nss2, " ");
+ }
+ iNss = startOfNext;
+ }
+ iNss = NSSUTIL_ArgStrip(iNss);
+ }
+ if (!alreadyAdded) {
+ /* nss wasn't empty, and it didn't contain a Flags section. We can
+ * assume that other content from nss has already been added to
+ * nss2, which means we already have a trailing space separator. */
+ PORT_Strcat(nss2, prefix);
+ PORT_Strcat(nss2, addFlag);
+ }
+ }
+
+ result = NSSUTIL_MkModuleSpecEx(lib, name, param, nss2, conf);
+ PORT_Free(lib);
+ PORT_Free(name);
+ PORT_Free(param);
+ PORT_Free(nss);
+ PORT_Free(nss2);
+ PORT_Free(conf);
+ return result;
+}
+
+#define NSSUTIL_ARG_FORTEZZA_FLAG "FORTEZZA"
+/******************************************************************************
+ * Parse the cipher flags from the NSS parameter
+ */
+void
+NSSUTIL_ArgParseCipherFlags(unsigned long *newCiphers, const char *cipherList)
+{
+ newCiphers[0] = newCiphers[1] = 0;
+ if ((cipherList == NULL) || (*cipherList == 0))
+ return;
+
+ for (; *cipherList; cipherList = NSSUTIL_ArgNextFlag(cipherList)) {
+ if (PORT_Strncasecmp(cipherList, NSSUTIL_ARG_FORTEZZA_FLAG,
+ sizeof(NSSUTIL_ARG_FORTEZZA_FLAG) - 1) == 0) {
+ newCiphers[0] |= SECMOD_FORTEZZA_FLAG;
+ }
+
+ /* add additional flags here as necessary */
+ /* direct bit mapping escape */
+ if (*cipherList == 0) {
+ if (cipherList[1] == 'l') {
+ newCiphers[1] |= atoi(&cipherList[2]);
+ } else {
+ newCiphers[0] |= atoi(&cipherList[2]);
+ }
+ }
+ }
+}
+
+/*********************************************************************
+ * make NSS parameter...
+ */
+/* First make NSS specific flags */
+#define MAX_FLAG_SIZE sizeof("internal") + sizeof("FIPS") + sizeof("moduleDB") + \
+ sizeof("moduleDBOnly") + sizeof("critical")
+static char *
+nssutil_mkNSSFlags(PRBool internal, PRBool isFIPS,
+ PRBool isModuleDB, PRBool isModuleDBOnly, PRBool isCritical)
+{
+ char *flags = (char *)PORT_ZAlloc(MAX_FLAG_SIZE);
+ PRBool first = PR_TRUE;
+
+ PORT_Memset(flags, 0, MAX_FLAG_SIZE);
+ if (internal) {
+ PORT_Strcat(flags, "internal");
+ first = PR_FALSE;
+ }
+ if (isFIPS) {
+ if (!first)
+ PORT_Strcat(flags, ",");
+ PORT_Strcat(flags, "FIPS");
+ first = PR_FALSE;
+ }
+ if (isModuleDB) {
+ if (!first)
+ PORT_Strcat(flags, ",");
+ PORT_Strcat(flags, "moduleDB");
+ first = PR_FALSE;
+ }
+ if (isModuleDBOnly) {
+ if (!first)
+ PORT_Strcat(flags, ",");
+ PORT_Strcat(flags, "moduleDBOnly");
+ first = PR_FALSE;
+ }
+ if (isCritical) {
+ if (!first)
+ PORT_Strcat(flags, ",");
+ PORT_Strcat(flags, "critical");
+ }
+ return flags;
+}
+
+/* construct the NSS cipher flags */
+static char *
+nssutil_mkCipherFlags(unsigned long ssl0, unsigned long ssl1)
+{
+ char *cipher = NULL;
+ unsigned int i;
+
+ for (i = 0; i < sizeof(ssl0) * 8; i++) {
+ if (ssl0 & (1UL << i)) {
+ char *string;
+ if ((1UL << i) == SECMOD_FORTEZZA_FLAG) {
+ string = PR_smprintf("%s", NSSUTIL_ARG_FORTEZZA_FLAG);
+ } else {
+ string = PR_smprintf("0h0x%08lx", 1UL << i);
+ }
+ if (cipher) {
+ char *tmp;
+ tmp = PR_smprintf("%s,%s", cipher, string);
+ PR_smprintf_free(cipher);
+ PR_smprintf_free(string);
+ cipher = tmp;
+ } else {
+ cipher = string;
+ }
+ }
+ }
+ for (i = 0; i < sizeof(ssl0) * 8; i++) {
+ if (ssl1 & (1UL << i)) {
+ if (cipher) {
+ char *tmp;
+ tmp = PR_smprintf("%s,0l0x%08lx", cipher, 1UL << i);
+ PR_smprintf_free(cipher);
+ cipher = tmp;
+ } else {
+ cipher = PR_smprintf("0l0x%08lx", 1UL << i);
+ }
+ }
+ }
+
+ return cipher;
+}
+
+/* Assemble a full NSS string. */
+char *
+NSSUTIL_MkNSSString(char **slotStrings, int slotCount, PRBool internal,
+ PRBool isFIPS, PRBool isModuleDB, PRBool isModuleDBOnly,
+ PRBool isCritical, unsigned long trustOrder,
+ unsigned long cipherOrder, unsigned long ssl0, unsigned long ssl1)
+{
+ int slotLen, i;
+ char *slotParams, *ciphers, *nss, *nssFlags;
+ const char *tmp;
+ char *trustOrderPair, *cipherOrderPair, *slotPair, *cipherPair, *flagPair;
+
+ /* now let's build up the string
+ * first the slot infos
+ */
+ slotLen = 0;
+ for (i = 0; i < (int)slotCount; i++) {
+ slotLen += PORT_Strlen(slotStrings[i]) + 1;
+ }
+ slotLen += 1; /* space for the final NULL */
+
+ slotParams = (char *)PORT_ZAlloc(slotLen);
+ PORT_Memset(slotParams, 0, slotLen);
+ for (i = 0; i < (int)slotCount; i++) {
+ PORT_Strcat(slotParams, slotStrings[i]);
+ PORT_Strcat(slotParams, " ");
+ PR_smprintf_free(slotStrings[i]);
+ slotStrings[i] = NULL;
+ }
+
+ /*
+ * now the NSS structure
+ */
+ nssFlags = nssutil_mkNSSFlags(internal, isFIPS, isModuleDB, isModuleDBOnly,
+ isCritical);
+ /* for now only the internal module is critical */
+ ciphers = nssutil_mkCipherFlags(ssl0, ssl1);
+
+ trustOrderPair = nssutil_formatIntPair("trustOrder", trustOrder,
+ NSSUTIL_DEFAULT_TRUST_ORDER);
+ cipherOrderPair = nssutil_formatIntPair("cipherOrder", cipherOrder,
+ NSSUTIL_DEFAULT_CIPHER_ORDER);
+ slotPair = nssutil_formatPair("slotParams", slotParams, '{'); /* } */
+ if (slotParams)
+ PORT_Free(slotParams);
+ cipherPair = nssutil_formatPair("ciphers", ciphers, '\'');
+ if (ciphers)
+ PR_smprintf_free(ciphers);
+ flagPair = nssutil_formatPair("Flags", nssFlags, '\'');
+ if (nssFlags)
+ PORT_Free(nssFlags);
+ nss = PR_smprintf("%s %s %s %s %s", trustOrderPair,
+ cipherOrderPair, slotPair, cipherPair, flagPair);
+ nssutil_freePair(trustOrderPair);
+ nssutil_freePair(cipherOrderPair);
+ nssutil_freePair(slotPair);
+ nssutil_freePair(cipherPair);
+ nssutil_freePair(flagPair);
+ tmp = NSSUTIL_ArgStrip(nss);
+ if (*tmp == '\0') {
+ PR_smprintf_free(nss);
+ nss = NULL;
+ }
+ return nss;
+}
+
+/*****************************************************************************
+ *
+ * Private calls for use by softoken and utilmod.c
+ */
+
+#define SQLDB "sql:"
+#define EXTERNDB "extern:"
+#define LEGACY "dbm:"
+#define MULTIACCESS "multiaccess:"
+#define SECMOD_DB "secmod.db"
+const char *
+_NSSUTIL_EvaluateConfigDir(const char *configdir,
+ NSSDBType *pdbType, char **appName)
+{
+ NSSDBType dbType;
+ PRBool checkEnvDefaultDB = PR_FALSE;
+ *appName = NULL;
+ /* force the default */
+ dbType = NSS_DB_TYPE_SQL;
+ if (configdir == NULL) {
+ checkEnvDefaultDB = PR_TRUE;
+ } else if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS) - 1) == 0) {
+ char *cdir;
+ dbType = NSS_DB_TYPE_MULTIACCESS;
+
+ *appName = PORT_Strdup(configdir + sizeof(MULTIACCESS) - 1);
+ if (*appName == NULL) {
+ return configdir;
+ }
+ cdir = *appName;
+ while (*cdir && *cdir != ':') {
+ cdir++;
+ }
+ if (*cdir == ':') {
+ *cdir = 0;
+ cdir++;
+ }
+ configdir = cdir;
+ } else if (PORT_Strncmp(configdir, SQLDB, sizeof(SQLDB) - 1) == 0) {
+ dbType = NSS_DB_TYPE_SQL;
+ configdir = configdir + sizeof(SQLDB) - 1;
+ } else if (PORT_Strncmp(configdir, EXTERNDB, sizeof(EXTERNDB) - 1) == 0) {
+ dbType = NSS_DB_TYPE_EXTERN;
+ configdir = configdir + sizeof(EXTERNDB) - 1;
+ } else if (PORT_Strncmp(configdir, LEGACY, sizeof(LEGACY) - 1) == 0) {
+ dbType = NSS_DB_TYPE_LEGACY;
+ configdir = configdir + sizeof(LEGACY) - 1;
+ } else {
+ checkEnvDefaultDB = PR_TRUE;
+ }
+
+ /* look up the default from the environment */
+ if (checkEnvDefaultDB) {
+ char *defaultType = PR_GetEnvSecure("NSS_DEFAULT_DB_TYPE");
+ if (defaultType != NULL) {
+ if (PORT_Strncmp(defaultType, SQLDB, sizeof(SQLDB) - 2) == 0) {
+ dbType = NSS_DB_TYPE_SQL;
+ } else if (PORT_Strncmp(defaultType, EXTERNDB, sizeof(EXTERNDB) - 2) == 0) {
+ dbType = NSS_DB_TYPE_EXTERN;
+ } else if (PORT_Strncmp(defaultType, LEGACY, sizeof(LEGACY) - 2) == 0) {
+ dbType = NSS_DB_TYPE_LEGACY;
+ }
+ }
+ }
+ /* if the caller has already set a type, don't change it */
+ if (*pdbType == NSS_DB_TYPE_NONE) {
+ *pdbType = dbType;
+ }
+ return configdir;
+}
+
+char *
+_NSSUTIL_GetSecmodName(const char *param, NSSDBType *dbType, char **appName,
+ char **filename, PRBool *rw)
+{
+ int next;
+ char *configdir = NULL;
+ char *secmodName = NULL;
+ char *value = NULL;
+ const char *save_params = param;
+ const char *lconfigdir;
+ PRBool noModDB = PR_FALSE;
+ param = NSSUTIL_ArgStrip(param);
+
+ while (*param) {
+ NSSUTIL_HANDLE_STRING_ARG(param, configdir, "configDir=", ;)
+ NSSUTIL_HANDLE_STRING_ARG(param, secmodName, "secmod=", ;)
+ NSSUTIL_HANDLE_FINAL_ARG(param)
+ }
+
+ *rw = PR_TRUE;
+ if (NSSUTIL_ArgHasFlag("flags", "readOnly", save_params)) {
+ *rw = PR_FALSE;
+ }
+
+ if (!secmodName || *secmodName == '\0') {
+ if (secmodName)
+ PORT_Free(secmodName);
+ secmodName = PORT_Strdup(SECMOD_DB);
+ }
+
+ *filename = secmodName;
+ lconfigdir = _NSSUTIL_EvaluateConfigDir(configdir, dbType, appName);
+
+ if (NSSUTIL_ArgHasFlag("flags", "noModDB", save_params)) {
+ /* there isn't a module db, don't load the legacy support */
+ noModDB = PR_TRUE;
+ *dbType = NSS_DB_TYPE_SQL;
+ PORT_Free(*filename);
+ *filename = NULL;
+ *rw = PR_FALSE;
+ }
+
+ /* only use the renamed secmod for legacy databases */
+ if ((*dbType != NSS_DB_TYPE_LEGACY) &&
+ (*dbType != NSS_DB_TYPE_MULTIACCESS) &&
+ !NSSUTIL_ArgHasFlag("flags", "forceSecmodChoice", save_params)) {
+ secmodName = "pkcs11.txt";
+ }
+
+ if (noModDB) {
+ value = NULL;
+ } else if (lconfigdir && lconfigdir[0] != '\0') {
+ value = PR_smprintf("%s" NSSUTIL_PATH_SEPARATOR "%s",
+ lconfigdir, secmodName);
+ } else {
+ value = PR_smprintf("%s", secmodName);
+ }
+ if (configdir)
+ PORT_Free(configdir);
+ return value;
+}
diff --git a/security/nss/lib/util/utilpars.h b/security/nss/lib/util/utilpars.h
new file mode 100644
index 0000000000..289fdca975
--- /dev/null
+++ b/security/nss/lib/util/utilpars.h
@@ -0,0 +1,70 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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 _UTILPARS_H_
+#define _UTILPARS_H_ 1
+
+#include "utilparst.h"
+#include "plarena.h"
+
+/* handle a module db request */
+char **NSSUTIL_DoModuleDBFunction(unsigned long function, char *parameters, void *args);
+
+/* parsing functions */
+char *NSSUTIL_ArgFetchValue(const char *string, int *pcount);
+const char *NSSUTIL_ArgStrip(const char *c);
+char *NSSUTIL_ArgGetParamValue(const char *paramName, const char *parameters);
+const char *NSSUTIL_ArgSkipParameter(const char *string);
+char *NSSUTIL_ArgGetLabel(const char *inString, int *next);
+long NSSUTIL_ArgDecodeNumber(const char *num);
+PRBool NSSUTIL_ArgIsBlank(char c);
+PRBool NSSUTIL_ArgHasFlag(const char *label, const char *flag,
+ const char *parameters);
+long NSSUTIL_ArgReadLong(const char *label, const char *params, long defValue,
+ PRBool *isdefault);
+
+/* quoting functions */
+int NSSUTIL_EscapeSize(const char *string, char quote);
+char *NSSUTIL_Escape(const char *string, char quote);
+int NSSUTIL_QuoteSize(const char *string, char quote);
+char *NSSUTIL_Quote(const char *string, char quote);
+int NSSUTIL_DoubleEscapeSize(const char *string, char quote1, char quote2);
+char *NSSUTIL_DoubleEscape(const char *string, char quote1, char quote2);
+
+unsigned long NSSUTIL_ArgParseSlotFlags(const char *label, const char *params);
+struct NSSUTILPreSlotInfoStr *NSSUTIL_ArgParseSlotInfo(PLArenaPool *arena,
+ const char *slotParams, int *retCount);
+char *NSSUTIL_MkSlotString(unsigned long slotID, unsigned long defaultFlags,
+ unsigned long timeout, unsigned char askpw_in,
+ PRBool hasRootCerts, PRBool hasRootTrust);
+SECStatus NSSUTIL_ArgParseModuleSpec(const char *modulespec, char **lib,
+ char **mod, char **parameters, char **nss);
+SECStatus NSSUTIL_ArgParseModuleSpecEx(const char *modulespec, char **lib,
+ char **mod, char **parameters, char **nss, char **config);
+char *NSSUTIL_MkModuleSpec(char *dllName, char *commonName,
+ char *parameters, char *NSS);
+char *NSSUTIL_MkModuleSpecEx(char *dllName, char *commonName,
+ char *parameters, char *NSS, char *config);
+char *NSSUTIL_AddNSSFlagToModuleSpec(char *spec, char *addFlag);
+void NSSUTIL_ArgParseCipherFlags(unsigned long *newCiphers,
+ const char *cipherList);
+char *NSSUTIL_MkNSSString(char **slotStrings, int slotCount, PRBool internal,
+ PRBool isFIPS, PRBool isModuleDB, PRBool isModuleDBOnly,
+ PRBool isCritical, unsigned long trustOrder,
+ unsigned long cipherOrder, unsigned long ssl0, unsigned long ssl1);
+
+/*
+ * private functions for softoken.
+ */
+char *_NSSUTIL_GetSecmodName(const char *param, NSSDBType *dbType,
+ char **appName, char **filename, PRBool *rw);
+const char *_NSSUTIL_EvaluateConfigDir(const char *configdir, NSSDBType *dbType, char **app);
+#if defined(_WIN32)
+wchar_t *_NSSUTIL_UTF8ToWide(const char *buf);
+PRStatus _NSSUTIL_Access(const char *path, PRAccessHow how);
+#else
+#define _NSSUTIL_Access(path, how) PR_Access((path), (how))
+#endif
+
+#endif /* _UTILPARS_H_ */
diff --git a/security/nss/lib/util/utilparst.h b/security/nss/lib/util/utilparst.h
new file mode 100644
index 0000000000..5dda090288
--- /dev/null
+++ b/security/nss/lib/util/utilparst.h
@@ -0,0 +1,78 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef UTILPARS_T_H
+#define UTILPARS_T_H 1
+#include "pkcs11t.h"
+
+/*
+ * macros to handle parsing strings of blank sparated arguments.
+ * Several NSSUTIL_HANDLE_STRING() macros should be places one after another with no intervening
+ * code. The first ones have precedence over the later ones. The last Macro should be
+ * NSSUTIL_HANDLE_FINAL_ARG.
+ *
+ * param is the input parameters. On exit param will point to the next parameter to parse. If the
+ * last paramter has been returned, param points to a null byte (*param = '0');
+ * target is the location to store any data aquired from the parameter. Caller is responsible to free this data.
+ * value is the string value of the parameter.
+ * command is any commands you need to run to help process the parameter's data.
+ */
+#define NSSUTIL_HANDLE_STRING_ARG(param, target, value, command) \
+ if (PORT_Strncasecmp(param, value, sizeof(value) - 1) == 0) { \
+ param += sizeof(value) - 1; \
+ if (target) \
+ PORT_Free(target); \
+ target = NSSUTIL_ArgFetchValue(param, &next); \
+ param += next; \
+ command; \
+ } else
+
+#define NSSUTIL_HANDLE_FINAL_ARG(param) \
+ { \
+ param = NSSUTIL_ArgSkipParameter(param); \
+ } \
+ param = NSSUTIL_ArgStrip(param);
+
+#define NSSUTIL_PATH_SEPARATOR "/"
+
+/* default module configuration strings */
+#define NSSUTIL_DEFAULT_INTERNAL_INIT1 \
+ "library= name=\"NSS Internal PKCS #11 Module\" parameters="
+#define NSSUTIL_DEFAULT_INTERNAL_INIT2 \
+ " NSS=\"Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={"
+#define NSSUTIL_DEFAULT_INTERNAL_INIT3 \
+ " askpw=any timeout=30})\""
+#define NSSUTIL_DEFAULT_SFTKN_FLAGS \
+ "slotFlags=[ECC,RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512]"
+
+#define NSSUTIL_DEFAULT_CIPHER_ORDER 0
+#define NSSUTIL_DEFAULT_TRUST_ORDER 50
+#define NSSUTIL_ARG_ESCAPE '\\'
+
+/* hold slot default flags until we initialize a slot. This structure is only
+ * useful between the time we define a module (either by hand or from the
+ * database) and the time the module is loaded. Not reference counted */
+struct NSSUTILPreSlotInfoStr {
+ CK_SLOT_ID slotID; /* slot these flags are for */
+ unsigned long defaultFlags; /* bit mask of default implementation this slot
+ * provides */
+ int askpw; /* slot specific password bits */
+ long timeout; /* slot specific timeout value */
+ char hasRootCerts; /* is this the root cert PKCS #11 module? */
+ char hasRootTrust; /* is this the root cert PKCS #11 module? */
+ int reserved0[2];
+ void *reserved1[2];
+};
+
+/*
+ * private functions for softoken.
+ */
+typedef enum {
+ NSS_DB_TYPE_NONE = 0,
+ NSS_DB_TYPE_SQL,
+ NSS_DB_TYPE_EXTERN,
+ NSS_DB_TYPE_LEGACY,
+ NSS_DB_TYPE_MULTIACCESS
+} NSSDBType;
+
+#endif /* UTILPARS_T_H */
diff --git a/security/nss/lib/util/utilrename.h b/security/nss/lib/util/utilrename.h
new file mode 100644
index 0000000000..19ddba666e
--- /dev/null
+++ b/security/nss/lib/util/utilrename.h
@@ -0,0 +1,164 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * utilrename.h - rename symbols moved from libnss3 to libnssutil3
+ *
+ */
+
+#ifndef _LIBUTIL_H_
+#define _LIBUTIL_H_ _LIBUTIL_H__Util
+
+#ifdef USE_UTIL_DIRECTLY
+
+/* functions moved from libnss3 */
+#define ATOB_AsciiToData ATOB_AsciiToData_Util
+#define ATOB_ConvertAsciiToItem ATOB_ConvertAsciiToItem_Util
+#define BTOA_ConvertItemToAscii BTOA_ConvertItemToAscii_Util
+#define BTOA_DataToAscii BTOA_DataToAscii_Util
+#define CERT_GenTime2FormattedAscii CERT_GenTime2FormattedAscii_Util
+#define DER_AsciiToTime DER_AsciiToTime_Util
+#define DER_DecodeTimeChoice DER_DecodeTimeChoice_Util
+#define DER_Encode DER_Encode_Util
+#define DER_EncodeTimeChoice DER_EncodeTimeChoice_Util
+#define DER_GeneralizedDayToAscii DER_GeneralizedDayToAscii_Util
+#define DER_GeneralizedTimeToTime DER_GeneralizedTimeToTime_Util
+#define DER_GetInteger DER_GetInteger_Util
+#define DER_Lengths DER_Lengths_Util
+#define DER_TimeChoiceDayToAscii DER_TimeChoiceDayToAscii_Util
+#define DER_TimeToGeneralizedTime DER_TimeToGeneralizedTime_Util
+#define DER_TimeToGeneralizedTimeArena DER_TimeToGeneralizedTimeArena_Util
+#define DER_TimeToUTCTime DER_TimeToUTCTime_Util
+#define DER_UTCDayToAscii DER_UTCDayToAscii_Util
+#define DER_UTCTimeToAscii DER_UTCTimeToAscii_Util
+#define DER_UTCTimeToTime DER_UTCTimeToTime_Util
+#define NSS_PutEnv NSS_PutEnv_Util
+#define NSSBase64_DecodeBuffer NSSBase64_DecodeBuffer_Util
+#define NSSBase64_EncodeItem NSSBase64_EncodeItem_Util
+#define NSSBase64Decoder_Create NSSBase64Decoder_Create_Util
+#define NSSBase64Decoder_Destroy NSSBase64Decoder_Destroy_Util
+#define NSSBase64Decoder_Update NSSBase64Decoder_Update_Util
+#define NSSBase64Encoder_Create NSSBase64Encoder_Create_Util
+#define NSSBase64Encoder_Destroy NSSBase64Encoder_Destroy_Util
+#define NSSBase64Encoder_Update NSSBase64Encoder_Update_Util
+#define NSSRWLock_Destroy NSSRWLock_Destroy_Util
+#define NSSRWLock_HaveWriteLock NSSRWLock_HaveWriteLock_Util
+#define NSSRWLock_LockRead NSSRWLock_LockRead_Util
+#define NSSRWLock_LockWrite NSSRWLock_LockWrite_Util
+#define NSSRWLock_New NSSRWLock_New_Util
+#define NSSRWLock_UnlockRead NSSRWLock_UnlockRead_Util
+#define NSSRWLock_UnlockWrite NSSRWLock_UnlockWrite_Util
+#define PORT_Alloc PORT_Alloc_Util
+#define PORT_ArenaAlloc PORT_ArenaAlloc_Util
+#define PORT_ArenaGrow PORT_ArenaGrow_Util
+#define PORT_ArenaMark PORT_ArenaMark_Util
+#define PORT_ArenaRelease PORT_ArenaRelease_Util
+#define PORT_ArenaStrdup PORT_ArenaStrdup_Util
+#define PORT_ArenaUnmark PORT_ArenaUnmark_Util
+#define PORT_ArenaZAlloc PORT_ArenaZAlloc_Util
+#define PORT_Free PORT_Free_Util
+#define PORT_FreeArena PORT_FreeArena_Util
+#define PORT_GetError PORT_GetError_Util
+#define PORT_NewArena PORT_NewArena_Util
+#define PORT_Realloc PORT_Realloc_Util
+#define PORT_SetError PORT_SetError_Util
+#define PORT_SetUCS2_ASCIIConversionFunction PORT_SetUCS2_ASCIIConversionFunction_Util
+#define PORT_SetUCS2_UTF8ConversionFunction PORT_SetUCS2_UTF8ConversionFunction_Util
+#define PORT_SetUCS4_UTF8ConversionFunction PORT_SetUCS4_UTF8ConversionFunction_Util
+#define PORT_Strdup PORT_Strdup_Util
+#define PORT_UCS2_ASCIIConversion PORT_UCS2_ASCIIConversion_Util
+#define PORT_UCS2_UTF8Conversion PORT_UCS2_UTF8Conversion_Util
+#define PORT_ZAlloc PORT_ZAlloc_Util
+#define PORT_ZAllocAligned PORT_ZAllocAligned_Util
+#define PORT_ZAllocAlignedOffset PORT_ZAllocAlignedOffset_Util
+#define PORT_ZFree PORT_ZFree_Util
+#define SEC_ASN1Decode SEC_ASN1Decode_Util
+#define SEC_ASN1DecodeInteger SEC_ASN1DecodeInteger_Util
+#define SEC_ASN1DecodeItem SEC_ASN1DecodeItem_Util
+#define SEC_ASN1DecoderAbort SEC_ASN1DecoderAbort_Util
+#define SEC_ASN1DecoderClearFilterProc SEC_ASN1DecoderClearFilterProc_Util
+#define SEC_ASN1DecoderClearNotifyProc SEC_ASN1DecoderClearNotifyProc_Util
+#define SEC_ASN1DecoderFinish SEC_ASN1DecoderFinish_Util
+#define SEC_ASN1DecoderSetFilterProc SEC_ASN1DecoderSetFilterProc_Util
+#define SEC_ASN1DecoderSetNotifyProc SEC_ASN1DecoderSetNotifyProc_Util
+#define SEC_ASN1DecoderStart SEC_ASN1DecoderStart_Util
+#define SEC_ASN1DecoderUpdate SEC_ASN1DecoderUpdate_Util
+#define SEC_ASN1Encode SEC_ASN1Encode_Util
+#define SEC_ASN1EncodeInteger SEC_ASN1EncodeInteger_Util
+#define SEC_ASN1EncodeItem SEC_ASN1EncodeItem_Util
+#define SEC_ASN1EncoderAbort SEC_ASN1EncoderAbort_Util
+#define SEC_ASN1EncoderClearNotifyProc SEC_ASN1EncoderClearNotifyProc_Util
+#define SEC_ASN1EncoderClearStreaming SEC_ASN1EncoderClearStreaming_Util
+#define SEC_ASN1EncoderClearTakeFromBuf SEC_ASN1EncoderClearTakeFromBuf_Util
+#define SEC_ASN1EncoderFinish SEC_ASN1EncoderFinish_Util
+#define SEC_ASN1EncoderSetNotifyProc SEC_ASN1EncoderSetNotifyProc_Util
+#define SEC_ASN1EncoderSetStreaming SEC_ASN1EncoderSetStreaming_Util
+#define SEC_ASN1EncoderSetTakeFromBuf SEC_ASN1EncoderSetTakeFromBuf_Util
+#define SEC_ASN1EncoderStart SEC_ASN1EncoderStart_Util
+#define SEC_ASN1EncoderUpdate SEC_ASN1EncoderUpdate_Util
+#define SEC_ASN1EncodeUnsignedInteger SEC_ASN1EncodeUnsignedInteger_Util
+#define SEC_ASN1LengthLength SEC_ASN1LengthLength_Util
+#define SEC_QuickDERDecodeItem SEC_QuickDERDecodeItem_Util
+#define SECITEM_AllocItem SECITEM_AllocItem_Util
+#define SECITEM_ArenaDupItem SECITEM_ArenaDupItem_Util
+#define SECITEM_CompareItem SECITEM_CompareItem_Util
+#define SECITEM_CopyItem SECITEM_CopyItem_Util
+#define SECITEM_DupItem SECITEM_DupItem_Util
+#define SECITEM_FreeItem SECITEM_FreeItem_Util
+#define SECITEM_ItemsAreEqual SECITEM_ItemsAreEqual_Util
+#define SECITEM_ZfreeItem SECITEM_ZfreeItem_Util
+#define SECOID_AddEntry SECOID_AddEntry_Util
+#define SECOID_CompareAlgorithmID SECOID_CompareAlgorithmID_Util
+#define SECOID_CopyAlgorithmID SECOID_CopyAlgorithmID_Util
+#define SECOID_DestroyAlgorithmID SECOID_DestroyAlgorithmID_Util
+#define SECOID_FindOID SECOID_FindOID_Util
+#define SECOID_FindOIDByTag SECOID_FindOIDByTag_Util
+#define SECOID_FindOIDTag SECOID_FindOIDTag_Util
+#define SECOID_FindOIDTagDescription SECOID_FindOIDTagDescription_Util
+#define SECOID_GetAlgorithmTag SECOID_GetAlgorithmTag_Util
+#define SECOID_SetAlgorithmID SECOID_SetAlgorithmID_Util
+#define SGN_CompareDigestInfo SGN_CompareDigestInfo_Util
+#define SGN_CopyDigestInfo SGN_CopyDigestInfo_Util
+#define SGN_CreateDigestInfo SGN_CreateDigestInfo_Util
+#define SGN_DestroyDigestInfo SGN_DestroyDigestInfo_Util
+
+/* templates moved from libnss3 */
+#define NSS_Get_SEC_AnyTemplate NSS_Get_SEC_AnyTemplate_Util
+#define NSS_Get_SEC_BitStringTemplate NSS_Get_SEC_BitStringTemplate_Util
+#define NSS_Get_SEC_BMPStringTemplate NSS_Get_SEC_BMPStringTemplate_Util
+#define NSS_Get_SEC_BooleanTemplate NSS_Get_SEC_BooleanTemplate_Util
+#define NSS_Get_SEC_GeneralizedTimeTemplate NSS_Get_SEC_GeneralizedTimeTemplate_Util
+#define NSS_Get_SEC_IA5StringTemplate NSS_Get_SEC_IA5StringTemplate_Util
+#define NSS_Get_SEC_IntegerTemplate NSS_Get_SEC_IntegerTemplate_Util
+#define NSS_Get_SEC_NullTemplate NSS_Get_SEC_NullTemplate_Util
+#define NSS_Get_SEC_ObjectIDTemplate NSS_Get_SEC_ObjectIDTemplate_Util
+#define NSS_Get_SEC_OctetStringTemplate NSS_Get_SEC_OctetStringTemplate_Util
+#define NSS_Get_SEC_PointerToAnyTemplate NSS_Get_SEC_PointerToAnyTemplate_Util
+#define NSS_Get_SEC_PointerToOctetStringTemplate NSS_Get_SEC_PointerToOctetStringTemplate_Util
+#define NSS_Get_SEC_SetOfAnyTemplate NSS_Get_SEC_SetOfAnyTemplate_Util
+#define NSS_Get_SEC_UTCTimeTemplate NSS_Get_SEC_UTCTimeTemplate_Util
+#define NSS_Get_SEC_UTF8StringTemplate NSS_Get_SEC_UTF8StringTemplate_Util
+#define NSS_Get_SECOID_AlgorithmIDTemplate NSS_Get_SECOID_AlgorithmIDTemplate_Util
+#define NSS_Get_sgn_DigestInfoTemplate NSS_Get_sgn_DigestInfoTemplate_Util
+#define SEC_AnyTemplate SEC_AnyTemplate_Util
+#define SEC_BitStringTemplate SEC_BitStringTemplate_Util
+#define SEC_BMPStringTemplate SEC_BMPStringTemplate_Util
+#define SEC_BooleanTemplate SEC_BooleanTemplate_Util
+#define SEC_GeneralizedTimeTemplate SEC_GeneralizedTimeTemplate_Util
+#define SEC_IA5StringTemplate SEC_IA5StringTemplate_Util
+#define SEC_IntegerTemplate SEC_IntegerTemplate_Util
+#define SEC_NullTemplate SEC_NullTemplate_Util
+#define SEC_ObjectIDTemplate SEC_ObjectIDTemplate_Util
+#define SEC_OctetStringTemplate SEC_OctetStringTemplate_Util
+#define SEC_PointerToAnyTemplate SEC_PointerToAnyTemplate_Util
+#define SEC_PointerToOctetStringTemplate SEC_PointerToOctetStringTemplate_Util
+#define SEC_SetOfAnyTemplate SEC_SetOfAnyTemplate_Util
+#define SEC_UTCTimeTemplate SEC_UTCTimeTemplate_Util
+#define SEC_UTF8StringTemplate SEC_UTF8StringTemplate_Util
+#define SECOID_AlgorithmIDTemplate SECOID_AlgorithmIDTemplate_Util
+#define sgn_DigestInfoTemplate sgn_DigestInfoTemplate_Util
+
+#endif /* USE_UTIL_DIRECTLY */
+
+#endif /* _LIBUTIL_H_ */
diff --git a/security/nss/lib/util/verref.h b/security/nss/lib/util/verref.h
new file mode 100644
index 0000000000..a7d5280e24
--- /dev/null
+++ b/security/nss/lib/util/verref.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/. */
+
+/* This header is used inline in a function to ensure that a version string
+ * symbol is linked in and not optimized out. A volatile reference is added to
+ * the variable identified by NSS_VERSION_VARIABLE.
+ *
+ * Use this as follows:
+ *
+ * #define NSS_VERSION_VARIABLE __nss_ssl_version
+ * #include "verref.h"
+ */
+
+/* Suppress unused variable warnings. */
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4101)
+#endif
+/* This works for both gcc and clang */
+#if defined(__GNUC__) && !defined(NSS_NO_GCC48)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#endif
+
+#ifndef NSS_VERSION_VARIABLE
+#error NSS_VERSION_VARIABLE must be set before including "verref.h"
+#endif
+{
+ extern const char NSS_VERSION_VARIABLE[];
+#if defined(__GNUC__) || defined(__clang__)
+ __attribute__((unused))
+#endif
+ volatile const char _nss_version_c = NSS_VERSION_VARIABLE[0];
+}
+#undef NSS_VERSION_VARIABLE
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+#if defined(__GNUC__) && !defined(NSS_NO_GCC48)
+#pragma GCC diagnostic pop
+#endif