summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--security/nss/lib/asn1/Makefile44
-rw-r--r--security/nss/lib/asn1/asn1.c1730
-rw-r--r--security/nss/lib/asn1/asn1.h882
-rw-r--r--security/nss/lib/asn1/asn1m.h83
-rw-r--r--security/nss/lib/asn1/asn1t.h169
-rw-r--r--security/nss/lib/asn1/config.mk52
-rw-r--r--security/nss/lib/asn1/manifest.mn59
-rw-r--r--security/nss/lib/asn1/nssasn1t.h70
-rw-r--r--security/nss/lib/dev/devmod.c878
-rw-r--r--security/nss/lib/pkcs12/p12dec.c696
10 files changed, 4663 insertions, 0 deletions
diff --git a/security/nss/lib/asn1/Makefile b/security/nss/lib/asn1/Makefile
new file mode 100644
index 000000000..2d25c00f2
--- /dev/null
+++ b/security/nss/lib/asn1/Makefile
@@ -0,0 +1,44 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+MAKEFILE_CVS_ID = "@(#) $RCSfile$ $Revision$ $Date$"
+
+include manifest.mn
+include $(CORE_DEPTH)/coreconf/config.mk
+include config.mk
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+export:: private_export
diff --git a/security/nss/lib/asn1/asn1.c b/security/nss/lib/asn1/asn1.c
new file mode 100644
index 000000000..fda5bd71a
--- /dev/null
+++ b/security/nss/lib/asn1/asn1.c
@@ -0,0 +1,1730 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef DEBUG
+static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
+#endif /* DEBUG */
+
+/*
+ * asn1.c
+ *
+ * At this point in time, this file contains the NSS wrappers for
+ * the old "SEC" ASN.1 encoder/decoder stuff.
+ */
+
+#ifndef ASN1M_H
+#include "asn1m.h"
+#endif /* ASN1M_H */
+
+#include "plarena.h"
+#include "secasn1.h"
+
+/*
+ * The pointer-tracking stuff
+ */
+
+#ifdef DEBUG
+extern const NSSError NSS_ERROR_INTERNAL_ERROR;
+
+static nssPointerTracker decoder_pointer_tracker;
+
+static PRStatus
+decoder_add_pointer
+(
+ const nssASN1Decoder *decoder
+)
+{
+ PRStatus rv;
+
+ rv = nssPointerTracker_initialize(&decoder_pointer_tracker);
+ if( PR_SUCCESS != rv ) {
+ return rv;
+ }
+
+ rv = nssPointerTracker_add(&decoder_pointer_tracker, decoder);
+ if( PR_SUCCESS != rv ) {
+ NSSError e = NSS_GetError();
+ if( NSS_ERROR_NO_MEMORY != e ) {
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ }
+
+ return rv;
+ }
+
+ return PR_SUCCESS;
+}
+
+static PRStatus
+decoder_remove_pointer
+(
+ const nssASN1Decoder *decoder
+)
+{
+ PRStatus rv;
+
+ rv = nssPointerTracker_remove(&decoder_pointer_tracker, decoder);
+ if( PR_SUCCESS != rv ) {
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ }
+
+ return rv;
+}
+
+/*
+ * nssASN1Decoder_verify
+ *
+ * This routine is only available in debug builds.
+ *
+ * If the specified pointer is a valid pointer to an nssASN1Decoder
+ * object, this routine will return PR_SUCCESS. Otherwise, it will
+ * put an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Decoder_verify
+(
+ nssASN1Decoder *decoder
+)
+{
+ PRStatus rv;
+
+ rv = nssPointerTracker_initialize(&decoder_pointer_tracker);
+ if( PR_SUCCESS != rv ) {
+ return PR_FAILURE;
+ }
+
+ rv = nssPointerTracker_verify(&decoder_pointer_tracker, decoder);
+ if( PR_SUCCESS != rv ) {
+ nss_SetError(NSS_ERROR_INVALID_ASN1DECODER);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+static nssPointerTracker encoder_pointer_tracker;
+
+static PRStatus
+encoder_add_pointer
+(
+ const nssASN1Encoder *encoder
+)
+{
+ PRStatus rv;
+
+ rv = nssPointerTracker_initialize(&encoder_pointer_tracker);
+ if( PR_SUCCESS != rv ) {
+ return rv;
+ }
+
+ rv = nssPointerTracker_add(&encoder_pointer_tracker, encoder);
+ if( PR_SUCCESS != rv ) {
+ NSSError e = NSS_GetError();
+ if( NSS_ERROR_NO_MEMORY != e ) {
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ }
+
+ return rv;
+ }
+
+ return PR_SUCCESS;
+}
+
+static PRStatus
+encoder_remove_pointer
+(
+ const nssASN1Encoder *encoder
+)
+{
+ PRStatus rv;
+
+ rv = nssPointerTracker_remove(&encoder_pointer_tracker, encoder);
+ if( PR_SUCCESS != rv ) {
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ }
+
+ return rv;
+}
+
+/*
+ * nssASN1Encoder_verify
+ *
+ * This routine is only available in debug builds.
+ *
+ * If the specified pointer is a valid pointer to an nssASN1Encoder
+ * object, this routine will return PR_SUCCESS. Otherwise, it will
+ * put an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Encoder_verify
+(
+ nssASN1Encoder *encoder
+)
+{
+ PRStatus rv;
+
+ rv = nssPointerTracker_initialize(&encoder_pointer_tracker);
+ if( PR_SUCCESS != rv ) {
+ return PR_FAILURE;
+ }
+
+ rv = nssPointerTracker_verify(&encoder_pointer_tracker, encoder);
+ if( PR_SUCCESS != rv ) {
+ nss_SetError(NSS_ERROR_INVALID_ASN1ENCODER);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+#endif /* DEBUG */
+
+/*
+ * nssASN1Decoder_Create
+ *
+ * This routine creates an ASN.1 Decoder, which will use the specified
+ * template to decode a datastream into the specified destination
+ * structure. If the optional arena argument is non-NULL, blah blah
+ * blah. XXX fgmr Should we include an nssASN1EncodingType argument,
+ * as a hint? Or is each encoding distinctive? This routine may
+ * return NULL upon error, in which case an error will have been
+ * placed upon the error stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_POINTER
+ * ...
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to an ASN.1 Decoder upon success.
+ */
+
+NSS_IMPLEMENT nssASN1Decoder *
+nssASN1Decoder_Create
+(
+ NSSArena *arenaOpt,
+ void *destination,
+ const nssASN1Template template[]
+)
+{
+ SEC_ASN1DecoderContext *rv;
+ PLArenaPool *hack = (PLArenaPool *)arenaOpt;
+
+#ifdef DEBUG
+ if( (NSSArena *)NULL != arenaOpt ) {
+ if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
+ return (nssASN1Decoder *)NULL;
+ }
+ }
+
+ /*
+ * May destination be NULL? I'd think so, since one might
+ * have only a filter proc. But if not, check the pointer here.
+ */
+
+ if( (nssASN1Template *)NULL == template ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (nssASN1Decoder *)NULL;
+ }
+#endif /* DEBUG */
+
+ rv = SEC_ASN1DecoderStart(hack, destination, template);
+ if( (SEC_ASN1DecoderContext *)NULL == rv ) {
+ nss_SetError(PORT_GetError()); /* also evil */
+ return (nssASN1Decoder *)NULL;
+ }
+
+#ifdef DEBUG
+ if( PR_SUCCESS != decoder_add_pointer(rv) ) {
+ (void)SEC_ASN1DecoderFinish(rv);
+ return (nssASN1Decoder *)NULL;
+ }
+#endif /* DEBUG */
+
+ return (nssASN1Decoder *)rv;
+}
+
+/*
+ * nssASN1Decoder_Update
+ *
+ * This routine feeds data to the decoder. In the event of an error,
+ * it will place an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_INVALID_ASN1DECODER
+ * NSS_ERROR_INVALID_BER
+ * ...
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success.
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Decoder_Update
+(
+ nssASN1Decoder *decoder,
+ const void *data,
+ PRUint32 amount
+)
+{
+ SECStatus rv;
+
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
+ return PR_FAILURE;
+ }
+
+ if( (void *)NULL == data ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ rv = SEC_ASN1DecoderUpdate((SEC_ASN1DecoderContext *)decoder,
+ (const char *)data,
+ (unsigned long)amount);
+ if( SECSuccess != rv ) {
+ nss_SetError(PORT_GetError()); /* ugly */
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+/*
+ * nssASN1Decoder_Finish
+ *
+ * This routine finishes the decoding and destroys the decoder.
+ * In the event of an error, it will place an error on the error
+ * stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Decoder_Finish
+(
+ nssASN1Decoder *decoder
+)
+{
+ PRStatus rv = PR_SUCCESS;
+ SECStatus srv;
+
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ srv = SEC_ASN1DecoderFinish((SEC_ASN1DecoderContext *)decoder);
+
+ if( SECSuccess != srv ) {
+ nss_SetError(PORT_GetError()); /* ugly */
+ rv = PR_FAILURE;
+ }
+
+#ifdef DEBUG
+ {
+ PRStatus rv2 = decoder_remove_pointer(decoder);
+ if( PR_SUCCESS == rv ) {
+ rv = rv2;
+ }
+ }
+#endif /* DEBUG */
+
+ return rv;
+}
+
+/*
+ * nssASN1Decoder_SetFilter
+ *
+ * This routine registers a callback filter routine with the decoder,
+ * which will be called blah blah blah. The specified argument will
+ * be passed as-is to the filter routine. The routine pointer may
+ * be NULL, in which case no filter callback will be called. If the
+ * noStore boolean is PR_TRUE, then decoded fields will not be stored
+ * in the destination structure specified when the decoder was
+ * created. This routine returns a PRStatus value; in the event of
+ * an error, it will place an error on the error stack and return
+ * PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Decoder_SetFilter
+(
+ nssASN1Decoder *decoder,
+ nssASN1DecoderFilterFunction *callback,
+ void *argument,
+ PRBool noStore
+)
+{
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ if( (nssASN1DecoderFilterFunction *)NULL == callback ) {
+ SEC_ASN1DecoderClearFilterProc((SEC_ASN1DecoderContext *)decoder);
+ } else {
+ SEC_ASN1DecoderSetFilterProc((SEC_ASN1DecoderContext *)decoder,
+ (SEC_ASN1WriteProc)callback,
+ argument, noStore);
+ }
+
+ /* No error returns defined for those routines */
+
+ return PR_SUCCESS;
+}
+
+/*
+ * nssASN1Decoder_GetFilter
+ *
+ * If the optional pCallbackOpt argument to this routine is non-null,
+ * then the pointer to any callback function established for this
+ * decoder with nssASN1Decoder_SetFilter will be stored at the
+ * location indicated by it. If the optional pArgumentOpt
+ * pointer is non-null, the filter's closure argument will be stored
+ * there. If the optional pNoStoreOpt pointer is non-null, the
+ * noStore value specified when setting the filter will be stored
+ * there. This routine returns a PRStatus value; in the event of
+ * an error it will place an error on the error stack and return
+ * PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+extern const NSSError NSS_ERROR_INTERNAL_ERROR;
+
+NSS_IMPLEMENT PRStatus
+nssASN1Decoder_GetFilter
+(
+ nssASN1Decoder *decoder,
+ nssASN1DecoderFilterFunction **pCallbackOpt,
+ void **pArgumentOpt,
+ PRBool *pNoStoreOpt
+)
+{
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ if( (nssASN1DecoderFilterFunction **)NULL != pCallbackOpt ) {
+ *pCallbackOpt = (nssASN1DecoderFilterFunction *)NULL;
+ }
+
+ if( (void **)NULL != pArgumentOpt ) {
+ *pArgumentOpt = (void *)NULL;
+ }
+
+ if( (PRBool *)NULL != pNoStoreOpt ) {
+ *pNoStoreOpt = PR_FALSE;
+ }
+
+ /* Error because it's unimplemented */
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ return PR_FAILURE;
+}
+
+/*
+ * nssASN1Decoder_SetNotify
+ *
+ * This routine registers a callback notify routine with the decoder,
+ * which will be called whenever.. The specified argument will be
+ * passed as-is to the notify routine. The routine pointer may be
+ * NULL, in which case no notify routine will be called. This routine
+ * returns a PRStatus value; in the event of an error it will place
+ * an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Decoder_SetNotify
+(
+ nssASN1Decoder *decoder,
+ nssASN1NotifyFunction *callback,
+ void *argument
+)
+{
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ if( (nssASN1NotifyFunction *)NULL == callback ) {
+ SEC_ASN1DecoderClearNotifyProc((SEC_ASN1DecoderContext *)decoder);
+ } else {
+ SEC_ASN1DecoderSetNotifyProc((SEC_ASN1DecoderContext *)decoder,
+ (SEC_ASN1NotifyProc)callback,
+ argument);
+ }
+
+ /* No error returns defined for those routines */
+
+ return PR_SUCCESS;
+}
+
+/*
+ * nssASN1Decoder_GetNotify
+ *
+ * If the optional pCallbackOpt argument to this routine is non-null,
+ * then the pointer to any callback function established for this
+ * decoder with nssASN1Decoder_SetNotify will be stored at the
+ * location indicated by it. If the optional pArgumentOpt pointer is
+ * non-null, the filter's closure argument will be stored there.
+ * This routine returns a PRStatus value; in the event of an error it
+ * will place an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Decoder_GetNotify
+(
+ nssASN1Decoder *decoder,
+ nssASN1NotifyFunction **pCallbackOpt,
+ void **pArgumentOpt
+)
+{
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Decoder_verify(decoder) ) {
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ if( (nssASN1NotifyFunction **)NULL != pCallbackOpt ) {
+ *pCallbackOpt = (nssASN1NotifyFunction *)NULL;
+ }
+
+ if( (void **)NULL != pArgumentOpt ) {
+ *pArgumentOpt = (void *)NULL;
+ }
+
+ /* Error because it's unimplemented */
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ return PR_FAILURE;
+}
+
+/*
+ * nssASN1_Decode
+ *
+ * This routine will decode the specified data into the specified
+ * destination structure, as specified by the specified template.
+ * This routine returns a PRStatus value; in the event of an error
+ * it will place an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_INVALID_BER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1_Decode
+(
+ NSSArena *arenaOpt,
+ void *destination,
+ const nssASN1Template template[],
+ const void *berData,
+ PRUint32 amount
+)
+{
+ PRStatus rv;
+ nssASN1Decoder *decoder;
+
+ /* This call will do our pointer-checking for us! */
+ decoder = nssASN1Decoder_Create(arenaOpt, destination, template);
+ if( (nssASN1Decoder *)NULL == decoder ) {
+ return PR_FAILURE;
+ }
+
+ rv = nssASN1Decoder_Update(decoder, berData, amount);
+ if( PR_SUCCESS != nssASN1Decoder_Finish(decoder) ) {
+ rv = PR_FAILURE;
+ }
+
+ return rv;
+}
+
+/*
+ * nssASN1_DecodeBER
+ *
+ * This routine will decode the data in the specified NSSBER
+ * into the destination structure, as specified by the template.
+ * This routine returns a PRStatus value; in the event of an error
+ * it will place an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_INVALID_NSSBER
+ * NSS_ERROR_INVALID_BER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1_DecodeBER
+(
+ NSSArena *arenaOpt,
+ void *destination,
+ const nssASN1Template template[],
+ const NSSBER *data
+)
+{
+ return nssASN1_Decode(arenaOpt, destination, template,
+ data->data, data->size);
+}
+
+/*
+ * nssASN1Encoder_Create
+ *
+ * This routine creates an ASN.1 Encoder, blah blah blah. This
+ * may return NULL upon error, in which case an error will have been
+ * placed on the error stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_POINTER
+ * ...
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to an ASN.1 Encoder upon success
+ */
+
+NSS_IMPLEMENT nssASN1Encoder *
+nssASN1Encoder_Create
+(
+ const void *source,
+ const nssASN1Template template[],
+ NSSASN1EncodingType encoding,
+ nssASN1EncoderWriteFunction *sink,
+ void *argument
+)
+{
+ SEC_ASN1EncoderContext *rv;
+
+#ifdef DEBUG
+ if( (void *)NULL == source ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (nssASN1Encoder *)NULL;
+ }
+
+ if( (nssASN1Template *)NULL == template ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (nssASN1Encoder *)NULL;
+ }
+
+ if( (nssASN1EncoderWriteFunction *)NULL == sink ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (nssASN1Encoder *)NULL;
+ }
+#endif /* DEBUG */
+
+ switch( encoding ) {
+ case NSSASN1BER:
+ case NSSASN1DER:
+ break;
+ case NSSASN1CER:
+ case NSSASN1LWER:
+ case NSSASN1PER:
+ case NSSASN1UnknownEncoding:
+ default:
+ nss_SetError(NSS_ERROR_ENCODING_NOT_SUPPORTED);
+ return (nssASN1Encoder *)NULL;
+ }
+
+ rv = SEC_ASN1EncoderStart((void *)source, template,
+ (SEC_ASN1WriteProc)sink, argument);
+ if( (SEC_ASN1EncoderContext *)NULL == rv ) {
+ nss_SetError(PORT_GetError()); /* ugly */
+ return (nssASN1Encoder *)NULL;
+ }
+
+ if( NSSASN1DER == encoding ) {
+ sec_ASN1EncoderSetDER(rv);
+ }
+
+#ifdef DEBUG
+ if( PR_SUCCESS != encoder_add_pointer(rv) ) {
+ (void)SEC_ASN1EncoderFinish(rv);
+ return (nssASN1Encoder *)NULL;
+ }
+#endif /* DEBUG */
+
+ return (nssASN1Encoder *)rv;
+}
+
+/*
+ * nssASN1Encoder_Update
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Encoder_Update
+(
+ nssASN1Encoder *encoder,
+ const void *data,
+ PRUint32 length
+)
+{
+ SECStatus rv;
+
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
+ return PR_FAILURE;
+ }
+
+ /*
+ * Can data legitimately be NULL? If not, verify..
+ */
+#endif /* DEBUG */
+
+ rv = SEC_ASN1EncoderUpdate((SEC_ASN1EncoderContext *)encoder,
+ (const char *)data,
+ (unsigned long)length);
+ if( SECSuccess != rv ) {
+ nss_SetError(PORT_GetError()); /* ugly */
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+/*
+ * nssASN1Encoder_Finish
+ *
+ * Destructor.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Encoder_Finish
+(
+ nssASN1Encoder *encoder
+)
+{
+ PRStatus rv;
+
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ SEC_ASN1EncoderFinish((SEC_ASN1EncoderContext *)encoder);
+ rv = PR_SUCCESS; /* no error return defined for that call */
+
+#ifdef DEBUG
+ {
+ PRStatus rv2 = encoder_remove_pointer(encoder);
+ if( PR_SUCCESS == rv ) {
+ rv = rv2;
+ }
+ }
+#endif /* DEBUG */
+
+ return rv;
+}
+
+/*
+ * nssASN1Encoder_SetNotify
+ *
+ * This routine registers a callback notify routine with the encoder,
+ * which will be called whenever.. The specified argument will be
+ * passed as-is to the notify routine. The routine pointer may be
+ * NULL, in which case no notify routine will be called. This routine
+ * returns a PRStatus value; in the event of an error it will place
+ * an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Encoder_SetNotify
+(
+ nssASN1Encoder *encoder,
+ nssASN1NotifyFunction *callback,
+ void *argument
+)
+{
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ if( (nssASN1NotifyFunction *)NULL == callback ) {
+ SEC_ASN1EncoderClearNotifyProc((SEC_ASN1EncoderContext *)encoder);
+ } else {
+ SEC_ASN1EncoderSetNotifyProc((SEC_ASN1EncoderContext *)encoder,
+ (SEC_ASN1NotifyProc)callback,
+ argument);
+ }
+
+ /* no error return defined for those routines */
+
+ return PR_SUCCESS;
+}
+
+/*
+ * nssASN1Encoder_GetNotify
+ *
+ * If the optional pCallbackOpt argument to this routine is non-null,
+ * then the pointer to any callback function established for this
+ * decoder with nssASN1Encoder_SetNotify will be stored at the
+ * location indicated by it. If the optional pArgumentOpt pointer is
+ * non-null, the filter's closure argument will be stored there.
+ * This routine returns a PRStatus value; in the event of an error it
+ * will place an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Encoder_GetNotify
+(
+ nssASN1Encoder *encoder,
+ nssASN1NotifyFunction **pCallbackOpt,
+ void **pArgumentOpt
+)
+{
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ if( (nssASN1NotifyFunction **)NULL != pCallbackOpt ) {
+ *pCallbackOpt = (nssASN1NotifyFunction *)NULL;
+ }
+
+ if( (void **)NULL != pArgumentOpt ) {
+ *pArgumentOpt = (void *)NULL;
+ }
+
+ /* Error because it's unimplemented */
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ return PR_FAILURE;
+}
+
+/*
+ * nssASN1Encoder_SetStreaming
+ *
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Encoder_SetStreaming
+(
+ nssASN1Encoder *encoder,
+ PRBool streaming
+)
+{
+ SEC_ASN1EncoderContext *cx = (SEC_ASN1EncoderContext *)encoder;
+
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ if( streaming ) {
+ SEC_ASN1EncoderSetStreaming(cx);
+ } else {
+ SEC_ASN1EncoderClearStreaming(cx);
+ }
+
+ /* no error return defined for those routines */
+
+ return PR_SUCCESS;
+}
+
+/*
+ * nssASN1Encoder_GetStreaming
+ *
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Encoder_GetStreaming
+(
+ nssASN1Encoder *encoder,
+ PRBool *pStreaming
+)
+{
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ if( (PRBool *)NULL != pStreaming ) {
+ *pStreaming = PR_FALSE;
+ }
+
+ /* Error because it's unimplemented */
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ return PR_FAILURE;
+}
+
+/*
+ * nssASN1Encoder_SetTakeFromBuffer
+ *
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Encoder_SetTakeFromBuffer
+(
+ nssASN1Encoder *encoder,
+ PRBool takeFromBuffer
+)
+{
+ SEC_ASN1EncoderContext *cx = (SEC_ASN1EncoderContext *)encoder;
+
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ if( takeFromBuffer ) {
+ SEC_ASN1EncoderSetTakeFromBuf(cx);
+ } else {
+ SEC_ASN1EncoderClearTakeFromBuf(cx);
+ }
+
+ /* no error return defined for those routines */
+
+ return PR_SUCCESS;
+}
+
+/*
+ * nssASN1Encoder_GetTakeFromBuffer
+ *
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1Encoder_GetTakeFromBuffer
+(
+ nssASN1Encoder *encoder,
+ PRBool *pTakeFromBuffer
+)
+{
+#ifdef DEBUG
+ if( PR_SUCCESS != nssASN1Encoder_verify(encoder) ) {
+ return PR_FAILURE;
+ }
+#endif /* DEBUG */
+
+ if( (PRBool *)NULL != pTakeFromBuffer ) {
+ *pTakeFromBuffer = PR_FALSE;
+ }
+
+ /* Error because it's unimplemented */
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ return PR_FAILURE;
+}
+
+/*
+ * nssASN1_Encode
+ *
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_ENCODING_NOT_SUPPORTED
+ * ...
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1_Encode
+(
+ const void *source,
+ const nssASN1Template template[],
+ NSSASN1EncodingType encoding,
+ nssASN1EncoderWriteFunction *sink,
+ void *argument
+)
+{
+ PRStatus rv;
+ nssASN1Encoder *encoder;
+
+ encoder = nssASN1Encoder_Create(source, template, encoding, sink, argument);
+ if( (nssASN1Encoder *)NULL == encoder ) {
+ return PR_FAILURE;
+ }
+
+ rv = nssASN1Encoder_Update(encoder, (const void *)NULL, 0);
+ if( PR_SUCCESS != nssASN1Encoder_Finish(encoder) ) {
+ rv = PR_FAILURE;
+ }
+
+ return rv;
+}
+
+/*
+ * nssasn1_encode_item_count
+ *
+ * This is a helper function for nssASN1_EncodeItem. It just counts
+ * up the space required for an encoding.
+ */
+
+static void
+nssasn1_encode_item_count
+(
+ void *arg,
+ const char *buf,
+ unsigned long len,
+ int depth,
+ nssASN1EncodingPart data_kind
+)
+{
+ unsigned long *count;
+
+ count = (unsigned long*)arg;
+ PR_ASSERT (count != NULL);
+
+ *count += len;
+}
+
+/*
+ * nssasn1_encode_item_store
+ *
+ * This is a helper function for nssASN1_EncodeItem. It appends the
+ * new data onto the destination item.
+ */
+
+static void
+nssasn1_encode_item_store
+(
+ void *arg,
+ const char *buf,
+ unsigned long len,
+ int depth,
+ nssASN1EncodingPart data_kind
+)
+{
+ NSSItem *dest;
+
+ dest = (NSSItem*)arg;
+ PR_ASSERT (dest != NULL);
+
+ memcpy((unsigned char *)dest->data + dest->size, buf, len);
+ dest->size += len;
+}
+
+/*
+ * nssASN1_EncodeItem
+ *
+ * There must be a better name. If the optional arena argument is
+ * non-null, it'll be used for the space. If the optional rvOpt is
+ * non-null, it'll be the return value-- if it is null, a new one
+ * will be allocated.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_ENCODING_NOT_SUPPORTED
+ *
+ * Return value:
+ * NULL upon error
+ * A valid pointer to an NSSDER upon success
+ */
+
+NSS_IMPLEMENT NSSDER *
+nssASN1_EncodeItem
+(
+ NSSArena *arenaOpt,
+ NSSDER *rvOpt,
+ const void *source,
+ const nssASN1Template template[],
+ NSSASN1EncodingType encoding
+)
+{
+ NSSDER *rv;
+ PRUint32 len = 0;
+ PRStatus status;
+
+#ifdef DEBUG
+ if( (NSSArena *)NULL != arenaOpt ) {
+ if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
+ return (NSSDER *)NULL;
+ }
+ }
+
+ if( (void *)NULL == source ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (NSSDER *)NULL;
+ }
+
+ if( (nssASN1Template *)NULL == template ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (NSSDER *)NULL;
+ }
+#endif /* DEBUG */
+
+ status = nssASN1_Encode(source, template, encoding,
+ (nssASN1EncoderWriteFunction *)nssasn1_encode_item_count,
+ &len);
+ if( PR_SUCCESS != status ) {
+ return (NSSDER *)NULL;
+ }
+
+ if( (NSSDER *)NULL == rvOpt ) {
+ rv = nss_ZNEW(arenaOpt, NSSDER);
+ if( (NSSDER *)NULL == rv ) {
+ return (NSSDER *)NULL;
+ }
+ } else {
+ rv = rvOpt;
+ }
+
+ rv->size = len;
+ rv->data = nss_ZAlloc(arenaOpt, len);
+ if( (void *)NULL == rv->data ) {
+ if( (NSSDER *)NULL == rvOpt ) {
+ nss_ZFreeIf(rv);
+ }
+ return (NSSDER *)NULL;
+ }
+
+ rv->size = 0; /* for nssasn1_encode_item_store */
+
+ status = nssASN1_Encode(source, template, encoding,
+ (nssASN1EncoderWriteFunction *)nssasn1_encode_item_store,
+ rv);
+ if( PR_SUCCESS != status ) {
+ nss_ZFreeIf(rv->data);
+ if( (NSSDER *)NULL == rvOpt ) {
+ nss_ZFreeIf(rv);
+ }
+ return (NSSDER *)NULL;
+ }
+
+ PR_ASSERT(rv->size == len);
+
+ return rv;
+}
+
+/*
+ * nssASN1_CreatePRUint32FromBER
+ *
+ */
+
+NSS_IMPLEMENT PRStatus
+nssASN1_CreatePRUint32FromBER
+(
+ NSSBER *encoded,
+ PRUint32 *pResult
+)
+{
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ return PR_FALSE;
+}
+
+/*
+ * nssASN1_GetDERFromPRUint32
+ *
+ */
+
+NSS_EXTERN NSSDER *
+nssASN1_GetDERFromPRUint32
+(
+ NSSArena *arenaOpt,
+ NSSDER *rvOpt,
+ PRUint32 value
+)
+{
+ NSSDER *rv;
+ PLArenaPool *hack = (PLArenaPool *)arenaOpt;
+ SECItem *item;
+
+#ifdef DEBUG
+ if( (NSSArena *)NULL != arenaOpt ) {
+ if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
+ return (NSSDER *)NULL;
+ }
+ }
+#endif /* DEBUG */
+
+ if( (NSSDER *)NULL == rvOpt ) {
+ rv = nss_ZNEW(arenaOpt, NSSDER);
+ if( (NSSDER *)NULL == rv ) {
+ return (NSSDER *)NULL;
+ }
+ } else {
+ rv = rvOpt;
+ }
+
+ item = SEC_ASN1EncodeUnsignedInteger(hack, (SECItem *)rv, value);
+ if( (SECItem *)NULL == item ) {
+ if( (NSSDER *)NULL == rvOpt ) {
+ (void)nss_ZFreeIf(rv);
+ }
+
+ nss_SetError(PORT_GetError()); /* ugly */
+ return (NSSDER *)NULL;
+ }
+
+ /*
+ * I happen to know that these things look alike.. but I'm only
+ * doing it for these "temporary" wrappers. This is an evil thing.
+ */
+ return (NSSDER *)item;
+}
+
+/*himom*/
+NSS_IMPLEMENT PRStatus
+nssASN1_CreatePRInt32FromBER
+(
+ NSSBER *encoded,
+ PRInt32 *pResult
+)
+{
+ nss_SetError(NSS_ERROR_INTERNAL_ERROR);
+ return PR_FALSE;
+}
+
+/*
+ * nssASN1_GetDERFromPRInt32
+ *
+ */
+
+NSS_IMPLEMENT NSSDER *
+nssASN1_GetDERFromPRInt32
+(
+ NSSArena *arenaOpt,
+ NSSDER *rvOpt,
+ PRInt32 value
+)
+{
+ NSSDER *rv;
+ PLArenaPool *hack = (PLArenaPool *)arenaOpt;
+ SECItem *item;
+
+#ifdef DEBUG
+ if( (NSSArena *)NULL != arenaOpt ) {
+ if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
+ return (NSSDER *)NULL;
+ }
+ }
+#endif /* DEBUG */
+
+ if( (NSSDER *)NULL == rvOpt ) {
+ rv = nss_ZNEW(arenaOpt, NSSDER);
+ if( (NSSDER *)NULL == rv ) {
+ return (NSSDER *)NULL;
+ }
+ } else {
+ rv = rvOpt;
+ }
+
+ item = SEC_ASN1EncodeInteger(hack, (SECItem *)rv, value);
+ if( (SECItem *)NULL == item ) {
+ if( (NSSDER *)NULL == rvOpt ) {
+ (void)nss_ZFreeIf(rv);
+ }
+
+ nss_SetError(PORT_GetError()); /* ugly */
+ return (NSSDER *)NULL;
+ }
+
+ /*
+ * I happen to know that these things look alike.. but I'm only
+ * doing it for these "temporary" wrappers. This is an evil thing.
+ */
+ return (NSSDER *)item;
+}
+
+/*
+ * 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
+ *
+ * Note that these are alphabetical (case insensitive); please add new
+ * ones in the appropriate place.
+ */
+
+const nssASN1Template *nssASN1Template_Any = (nssASN1Template *)SEC_AnyTemplate;
+const nssASN1Template *nssASN1Template_BitString = (nssASN1Template *)SEC_BitStringTemplate;
+const nssASN1Template *nssASN1Template_BMPString = (nssASN1Template *)SEC_BMPStringTemplate;
+const nssASN1Template *nssASN1Template_Boolean = (nssASN1Template *)SEC_BooleanTemplate;
+const nssASN1Template *nssASN1Template_Enumerated = (nssASN1Template *)SEC_EnumeratedTemplate;
+const nssASN1Template *nssASN1Template_GeneralizedTime = (nssASN1Template *)SEC_GeneralizedTimeTemplate;
+const nssASN1Template *nssASN1Template_IA5String = (nssASN1Template *)SEC_IA5StringTemplate;
+const nssASN1Template *nssASN1Template_Integer = (nssASN1Template *)SEC_IntegerTemplate;
+const nssASN1Template *nssASN1Template_Null = (nssASN1Template *)SEC_NullTemplate;
+const nssASN1Template *nssASN1Template_ObjectID = (nssASN1Template *)SEC_ObjectIDTemplate;
+const nssASN1Template *nssASN1Template_OctetString = (nssASN1Template *)SEC_OctetStringTemplate;
+const nssASN1Template *nssASN1Template_PrintableString = (nssASN1Template *)SEC_PrintableStringTemplate;
+const nssASN1Template *nssASN1Template_T61String = (nssASN1Template *)SEC_T61StringTemplate;
+const nssASN1Template *nssASN1Template_UniversalString = (nssASN1Template *)SEC_UniversalStringTemplate;
+const nssASN1Template *nssASN1Template_UTCTime = (nssASN1Template *)SEC_UTCTimeTemplate;
+const nssASN1Template *nssASN1Template_UTF8String = (nssASN1Template *)SEC_UTF8StringTemplate;
+const nssASN1Template *nssASN1Template_VisibleString = (nssASN1Template *)SEC_VisibleStringTemplate;
+
+const nssASN1Template *nssASN1Template_PointerToAny = (nssASN1Template *)SEC_PointerToAnyTemplate;
+const nssASN1Template *nssASN1Template_PointerToBitString = (nssASN1Template *)SEC_PointerToBitStringTemplate;
+const nssASN1Template *nssASN1Template_PointerToBMPString = (nssASN1Template *)SEC_PointerToBMPStringTemplate;
+const nssASN1Template *nssASN1Template_PointerToBoolean = (nssASN1Template *)SEC_PointerToBooleanTemplate;
+const nssASN1Template *nssASN1Template_PointerToEnumerated = (nssASN1Template *)SEC_PointerToEnumeratedTemplate;
+const nssASN1Template *nssASN1Template_PointerToGeneralizedTime = (nssASN1Template *)SEC_PointerToGeneralizedTimeTemplate;
+const nssASN1Template *nssASN1Template_PointerToIA5String = (nssASN1Template *)SEC_PointerToIA5StringTemplate;
+const nssASN1Template *nssASN1Template_PointerToInteger = (nssASN1Template *)SEC_PointerToIntegerTemplate;
+const nssASN1Template *nssASN1Template_PointerToNull = (nssASN1Template *)SEC_PointerToNullTemplate;
+const nssASN1Template *nssASN1Template_PointerToObjectID = (nssASN1Template *)SEC_PointerToObjectIDTemplate;
+const nssASN1Template *nssASN1Template_PointerToOctetString = (nssASN1Template *)SEC_PointerToOctetStringTemplate;
+const nssASN1Template *nssASN1Template_PointerToPrintableString = (nssASN1Template *)SEC_PointerToPrintableStringTemplate;
+const nssASN1Template *nssASN1Template_PointerToT61String = (nssASN1Template *)SEC_PointerToT61StringTemplate;
+const nssASN1Template *nssASN1Template_PointerToUniversalString = (nssASN1Template *)SEC_PointerToUniversalStringTemplate;
+const nssASN1Template *nssASN1Template_PointerToUTCTime = (nssASN1Template *)SEC_PointerToUTCTimeTemplate;
+const nssASN1Template *nssASN1Template_PointerToUTF8String = (nssASN1Template *)SEC_PointerToUTF8StringTemplate;
+const nssASN1Template *nssASN1Template_PointerToVisibleString = (nssASN1Template *)SEC_PointerToVisibleStringTemplate;
+
+const nssASN1Template *nssASN1Template_SetOfAny = (nssASN1Template *)SEC_SetOfAnyTemplate;
+const nssASN1Template *nssASN1Template_SetOfBitString = (nssASN1Template *)SEC_SetOfBitStringTemplate;
+const nssASN1Template *nssASN1Template_SetOfBMPString = (nssASN1Template *)SEC_SetOfBMPStringTemplate;
+const nssASN1Template *nssASN1Template_SetOfBoolean = (nssASN1Template *)SEC_SetOfBooleanTemplate;
+const nssASN1Template *nssASN1Template_SetOfEnumerated = (nssASN1Template *)SEC_SetOfEnumeratedTemplate;
+const nssASN1Template *nssASN1Template_SetOfGeneralizedTime = (nssASN1Template *)SEC_SetOfGeneralizedTimeTemplate;
+const nssASN1Template *nssASN1Template_SetOfIA5String = (nssASN1Template *)SEC_SetOfIA5StringTemplate;
+const nssASN1Template *nssASN1Template_SetOfInteger = (nssASN1Template *)SEC_SetOfIntegerTemplate;
+const nssASN1Template *nssASN1Template_SetOfNull = (nssASN1Template *)SEC_SetOfNullTemplate;
+const nssASN1Template *nssASN1Template_SetOfObjectID = (nssASN1Template *)SEC_SetOfObjectIDTemplate;
+const nssASN1Template *nssASN1Template_SetOfOctetString = (nssASN1Template *)SEC_SetOfOctetStringTemplate;
+const nssASN1Template *nssASN1Template_SetOfPrintableString = (nssASN1Template *)SEC_SetOfPrintableStringTemplate;
+const nssASN1Template *nssASN1Template_SetOfT61String = (nssASN1Template *)SEC_SetOfT61StringTemplate;
+const nssASN1Template *nssASN1Template_SetOfUniversalString = (nssASN1Template *)SEC_SetOfUniversalStringTemplate;
+const nssASN1Template *nssASN1Template_SetOfUTCTime = (nssASN1Template *)SEC_SetOfUTCTimeTemplate;
+const nssASN1Template *nssASN1Template_SetOfUTF8String = (nssASN1Template *)SEC_SetOfUTF8StringTemplate;
+const nssASN1Template *nssASN1Template_SetOfVisibleString = (nssASN1Template *)SEC_SetOfVisibleStringTemplate;
+
+/*
+ *
+ */
+
+NSS_IMPLEMENT NSSUTF8 *
+nssUTF8_CreateFromBER
+(
+ NSSArena *arenaOpt,
+ nssStringType type,
+ NSSBER *berData
+)
+{
+ NSSUTF8 *rv = NULL;
+ PRUint8 tag;
+ NSSArena *a;
+ NSSItem in;
+ NSSItem out;
+ PRStatus st;
+ const nssASN1Template *templ;
+
+#ifdef NSSDEBUG
+ if( (NSSArena *)NULL != arenaOpt ) {
+ if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
+ return (NSSUTF8 *)NULL;
+ }
+ }
+
+ if( (NSSBER *)NULL == berData ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (NSSUTF8 *)NULL;
+ }
+
+ if( (void *)NULL == berData->data ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (NSSUTF8 *)NULL;
+ }
+#endif /* NSSDEBUG */
+
+ a = NSSArena_Create();
+ if( (NSSArena *)NULL == a ) {
+ return (NSSUTF8 *)NULL;
+ }
+
+ in = *berData;
+
+ /*
+ * By the way, at first I succumbed to the temptation to make
+ * this an incestuous nested switch statement. Count yourself
+ * lucky I cleaned it up.
+ */
+
+ switch( type ) {
+ case nssStringType_DirectoryString:
+ /*
+ * draft-ietf-pkix-ipki-part1-11 says in part:
+ *
+ * DirectoryString { INTEGER:maxSize } ::= CHOICE {
+ * teletexString TeletexString (SIZE (1..maxSize)),
+ * printableString PrintableString (SIZE (1..maxSize)),
+ * universalString UniversalString (SIZE (1..maxSize)),
+ * bmpString BMPString (SIZE(1..maxSize)),
+ * utf8String UTF8String (SIZE(1..maxSize))
+ * }
+ *
+ * The tags are:
+ * TeletexString UNIVERSAL 20
+ * PrintableString UNIVERSAL 19
+ * UniversalString UNIVERSAL 28
+ * BMPString UNIVERSAL 30
+ * UTF8String UNIVERSAL 12
+ *
+ * "UNIVERSAL" tags have bits 8 and 7 zero, bit 6 is zero for
+ * primitive encodings, and if the tag value is less than 30,
+ * the tag value is directly encoded in bits 5 through 1.
+ */
+ in.data = (void *)&(((PRUint8 *)berData->data)[1]);
+ in.size = berData->size-1;
+
+ tag = *(PRUint8 *)berData->data;
+ switch( tag & nssASN1_TAGNUM_MASK ) {
+ case 20:
+ /*
+ * XXX fgmr-- we have to accept Latin-1 for Teletex; (see
+ * below) but is T61 a suitable value for "Latin-1"?
+ */
+ templ = nssASN1Template_T61String;
+ type = nssStringType_TeletexString;
+ break;
+ case 19:
+ templ = nssASN1Template_PrintableString;
+ type = nssStringType_PrintableString;
+ break;
+ case 28:
+ templ = nssASN1Template_UniversalString;
+ type = nssStringType_UniversalString;
+ break;
+ case 30:
+ templ = nssASN1Template_BMPString;
+ type = nssStringType_BMPString;
+ break;
+ case 12:
+ templ = nssASN1Template_UTF8String;
+ type = nssStringType_UTF8String;
+ break;
+ default:
+ nss_SetError(NSS_ERROR_INVALID_POINTER); /* "pointer"? */
+ (void)NSSArena_Destroy(a);
+ return (NSSUTF8 *)NULL;
+ }
+
+ break;
+
+ case nssStringType_TeletexString:
+ /*
+ * XXX fgmr-- we have to accept Latin-1 for Teletex; (see
+ * below) but is T61 a suitable value for "Latin-1"?
+ */
+ templ = nssASN1Template_T61String;
+ break;
+
+ case nssStringType_PrintableString:
+ templ = nssASN1Template_PrintableString;
+ break;
+
+ case nssStringType_UniversalString:
+ templ = nssASN1Template_UniversalString;
+ break;
+
+ case nssStringType_BMPString:
+ templ = nssASN1Template_BMPString;
+ break;
+
+ case nssStringType_UTF8String:
+ templ = nssASN1Template_UTF8String;
+ break;
+
+ case nssStringType_PHGString:
+ templ = nssASN1Template_IA5String;
+ break;
+
+ default:
+ nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
+ (void)NSSArena_Destroy(a);
+ return (NSSUTF8 *)NULL;
+ }
+
+ st = nssASN1_DecodeBER(a, &out, templ, &in);
+
+ if( PR_SUCCESS == st ) {
+ rv = nssUTF8_Create(arenaOpt, type, out.data, out.size);
+ }
+ (void)NSSArena_Destroy(a);
+
+ return rv;
+}
+
+NSS_EXTERN NSSDER *
+nssUTF8_GetDEREncoding
+(
+ NSSArena *arenaOpt,
+ nssStringType type,
+ const NSSUTF8 *string
+)
+{
+ NSSDER *rv = (NSSDER *)NULL;
+ NSSItem str;
+ NSSDER *der;
+ const nssASN1Template *templ;
+ NSSArena *a;
+
+#ifdef NSSDEBUG
+ if( (NSSArena *)NULL != arenaOpt ) {
+ if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
+ return (NSSDER *)NULL;
+ }
+ }
+
+ if( (const NSSUTF8 *)NULL == string ) {
+ nss_SetError(NSS_ERROR_INVALID_POINTER);
+ return (NSSDER *)NULL;
+ }
+#endif /* NSSDEBUG */
+
+ str.data = (void *)string;
+ str.size = nssUTF8_Size(string, (PRStatus *)NULL);
+ if( 0 == str.size ) {
+ return (NSSDER *)NULL;
+ }
+
+ a = NSSArena_Create();
+ if( (NSSArena *)NULL == a ) {
+ return (NSSDER *)NULL;
+ }
+
+ switch( type ) {
+ case nssStringType_DirectoryString:
+ {
+ NSSDER *utf;
+ PRUint8 *c;
+
+ utf = nssASN1_EncodeItem(a, (NSSDER *)NULL, &str,
+ nssASN1Template_UTF8String,
+ NSSASN1DER);
+ if( (NSSDER *)NULL == utf ) {
+ (void)NSSArena_Destroy(a);
+ return (NSSDER *)NULL;
+ }
+
+ rv = nss_ZNEW(arenaOpt, NSSDER);
+ if( (NSSDER *)NULL == rv ) {
+ (void)NSSArena_Destroy(a);
+ return (NSSDER *)NULL;
+ }
+
+ rv->size = utf->size + 1;
+ rv->data = nss_ZAlloc(arenaOpt, rv->size);
+ if( (void *)NULL == rv->data ) {
+ (void)nss_ZFreeIf(rv);
+ (void)NSSArena_Destroy(a);
+ return (NSSDER *)NULL;
+ }
+
+ c = (PRUint8 *)rv->data;
+ (void)nsslibc_memcpy(&c[1], utf->data, utf->size);
+ *c = 12; /* UNIVERSAL primitive encoding tag for UTF8String */
+
+ (void)NSSArena_Destroy(a);
+ return rv;
+ }
+ case nssStringType_TeletexString:
+ /*
+ * XXX fgmr-- we have to accept Latin-1 for Teletex; (see
+ * below) but is T61 a suitable value for "Latin-1"?
+ */
+ templ = nssASN1Template_T61String;
+ break;
+ case nssStringType_PrintableString:
+ templ = nssASN1Template_PrintableString;
+ break;
+
+ case nssStringType_UniversalString:
+ templ = nssASN1Template_UniversalString;
+ break;
+
+ case nssStringType_BMPString:
+ templ = nssASN1Template_BMPString;
+ break;
+
+ case nssStringType_UTF8String:
+ templ = nssASN1Template_UTF8String;
+ break;
+
+ case nssStringType_PHGString:
+ templ = nssASN1Template_IA5String;
+ break;
+
+ default:
+ nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE);
+ (void)NSSArena_Destroy(a);
+ return (NSSDER *)NULL;
+ }
+
+ der = nssUTF8_GetDEREncoding(a, type, string);
+ if( (NSSItem *)NULL == der ) {
+ (void)NSSArena_Destroy(a);
+ return (NSSDER *)NULL;
+ }
+
+ rv = nssASN1_EncodeItem(arenaOpt, (NSSDER *)NULL, der, templ, NSSASN1DER);
+ if( (NSSDER *)NULL == rv ) {
+ (void)NSSArena_Destroy(a);
+ return (NSSDER *)NULL;
+ }
+
+ (void)NSSArena_Destroy(a);
+ return rv;
+}
diff --git a/security/nss/lib/asn1/asn1.h b/security/nss/lib/asn1/asn1.h
new file mode 100644
index 000000000..eecc54120
--- /dev/null
+++ b/security/nss/lib/asn1/asn1.h
@@ -0,0 +1,882 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef ASN1_H
+#define ASN1_H
+
+#ifdef DEBUG
+static const char ASN1_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
+#endif /* DEBUG */
+
+/*
+ * asn1.h
+ *
+ * This file contains the ASN.1 encoder/decoder routines available
+ * internally within NSS. It's not clear right now if this file
+ * will be folded into base.h or something, I just needed to get this
+ * going. At the moment, most of these routines wrap the old SEC_ASN1
+ * calls.
+ */
+
+#ifndef ASN1T_H
+#include "asn1t.h"
+#endif /* ASN1T_H */
+
+#ifndef BASE_H
+#include "base.h"
+#endif /* BASE_H */
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * nssASN1Decoder
+ *
+ * ... description here ...
+ *
+ * nssASN1Decoder_Create (Factory/Constructor)
+ * nssASN1Decoder_Update
+ * nssASN1Decoder_Finish (Destructor)
+ * nssASN1Decoder_SetFilter
+ * nssASN1Decoder_GetFilter
+ * nssASN1Decoder_SetNotify
+ * nssASN1Decoder_GetNotify
+ *
+ * Debug builds only:
+ *
+ * nssASN1Decoder_verify
+ *
+ * Related functions that aren't type methods:
+ *
+ * nssASN1_Decode
+ * nssASN1_DecodeBER
+ */
+
+/*
+ * nssASN1Decoder_Create
+ *
+ * This routine creates an ASN.1 Decoder, which will use the specified
+ * template to decode a datastream into the specified destination
+ * structure. If the optional arena argument is non-NULL, blah blah
+ * blah. XXX fgmr Should we include an nssASN1EncodingType argument,
+ * as a hint? Or is each encoding distinctive? This routine may
+ * return NULL upon error, in which case an error will have been
+ * placed upon the error stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_POINTER
+ * ...
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to an ASN.1 Decoder upon success.
+ */
+
+NSS_EXTERN nssASN1Decoder *
+nssASN1Decoder_Create
+(
+ NSSArena *arenaOpt,
+ void *destination,
+ const nssASN1Template template[]
+);
+
+extern const NSSError NSS_ERROR_NO_MEMORY;
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+
+/*
+ * nssASN1Decoder_Update
+ *
+ * This routine feeds data to the decoder. In the event of an error,
+ * it will place an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_INVALID_ASN1DECODER
+ * NSS_ERROR_INVALID_BER
+ * ...
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success.
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Decoder_Update
+(
+ nssASN1Decoder *decoder,
+ const void *data,
+ PRUint32 amount
+);
+
+extern const NSSError NSS_ERROR_NO_MEMORY;
+extern const NSSError NSS_ERROR_INVALID_ASN1DECODER;
+extern const NSSError NSS_ERROR_INVALID_BER;
+
+/*
+ * nssASN1Decoder_Finish
+ *
+ * This routine finishes the decoding and destroys the decoder.
+ * In the event of an error, it will place an error on the error
+ * stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Decoder_Finish
+(
+ nssASN1Decoder *decoder
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1DECODER;
+
+/*
+ * nssASN1Decoder_SetFilter
+ *
+ * This routine registers a callback filter routine with the decoder,
+ * which will be called blah blah blah. The specified argument will
+ * be passed as-is to the filter routine. The routine pointer may
+ * be NULL, in which case no filter callback will be called. If the
+ * noStore boolean is PR_TRUE, then decoded fields will not be stored
+ * in the destination structure specified when the decoder was
+ * created. This routine returns a PRStatus value; in the event of
+ * an error, it will place an error on the error stack and return
+ * PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Decoder_SetFilter
+(
+ nssASN1Decoder *decoder,
+ nssASN1DecoderFilterFunction *callback,
+ void *argument,
+ PRBool noStore
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1DECODER;
+
+/*
+ * nssASN1Decoder_GetFilter
+ *
+ * If the optional pCallbackOpt argument to this routine is non-null,
+ * then the pointer to any callback function established for this
+ * decoder with nssASN1Decoder_SetFilter will be stored at the
+ * location indicated by it. If the optional pArgumentOpt
+ * pointer is non-null, the filter's closure argument will be stored
+ * there. If the optional pNoStoreOpt pointer is non-null, the
+ * noStore value specified when setting the filter will be stored
+ * there. This routine returns a PRStatus value; in the event of
+ * an error it will place an error on the error stack and return
+ * PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Decoder_GetFilter
+(
+ nssASN1Decoder *decoder,
+ nssASN1DecoderFilterFunction **pCallbackOpt,
+ void **pArgumentOpt,
+ PRBool *pNoStoreOpt
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1DECODER;
+
+/*
+ * nssASN1Decoder_SetNotify
+ *
+ * This routine registers a callback notify routine with the decoder,
+ * which will be called whenever.. The specified argument will be
+ * passed as-is to the notify routine. The routine pointer may be
+ * NULL, in which case no notify routine will be called. This routine
+ * returns a PRStatus value; in the event of an error it will place
+ * an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Decoder_SetNotify
+(
+ nssASN1Decoder *decoder,
+ nssASN1NotifyFunction *callback,
+ void *argument
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1DECODER;
+
+/*
+ * nssASN1Decoder_GetNotify
+ *
+ * If the optional pCallbackOpt argument to this routine is non-null,
+ * then the pointer to any callback function established for this
+ * decoder with nssASN1Decoder_SetNotify will be stored at the
+ * location indicated by it. If the optional pArgumentOpt pointer is
+ * non-null, the filter's closure argument will be stored there.
+ * This routine returns a PRStatus value; in the event of an error it
+ * will place an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Decoder_GetNotify
+(
+ nssASN1Decoder *decoder,
+ nssASN1NotifyFunction **pCallbackOpt,
+ void **pArgumentOpt
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1DECODER;
+
+/*
+ * nssASN1Decoder_verify
+ *
+ * This routine is only available in debug builds.
+ *
+ * If the specified pointer is a valid pointer to an nssASN1Decoder
+ * object, this routine will return PR_SUCCESS. Otherwise, it will
+ * put an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+#ifdef DEBUG
+NSS_EXTERN PRStatus
+nssASN1Decoder_verify
+(
+ nssASN1Decoder *decoder
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1DECODER;
+#endif /* DEBUG */
+
+/*
+ * nssASN1_Decode
+ *
+ * This routine will decode the specified data into the specified
+ * destination structure, as specified by the specified template.
+ * This routine returns a PRStatus value; in the event of an error
+ * it will place an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_INVALID_BER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1_Decode
+(
+ NSSArena *arenaOpt,
+ void *destination,
+ const nssASN1Template template[],
+ const void *berData,
+ PRUint32 amount
+);
+
+extern const NSSError NSS_ERROR_NO_MEMORY;
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+extern const NSSError NSS_ERROR_INVALID_BER;
+
+/*
+ * nssASN1_DecodeBER
+ *
+ * This routine will decode the data in the specified NSSBER
+ * into the destination structure, as specified by the template.
+ * This routine returns a PRStatus value; in the event of an error
+ * it will place an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_INVALID_NSSBER
+ * NSS_ERROR_INVALID_BER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1_DecodeBER
+(
+ NSSArena *arenaOpt,
+ void *destination,
+ const nssASN1Template template[],
+ const NSSBER *data
+);
+
+extern const NSSError NSS_ERROR_NO_MEMORY;
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+extern const NSSError NSS_ERROR_INVALID_BER;
+
+/*
+ * nssASN1Encoder
+ *
+ * ... description here ...
+ *
+ * nssASN1Encoder_Create (Factory/Constructor)
+ * nssASN1Encoder_Update
+ * nssASN1Encoder_Finish (Destructor)
+ * nssASN1Encoder_SetNotify
+ * nssASN1Encoder_GetNotify
+ * nssASN1Encoder_SetStreaming
+ * nssASN1Encoder_GetStreaming
+ * nssASN1Encoder_SetTakeFromBuffer
+ * nssASN1Encoder_GetTakeFromBuffer
+ *
+ * Debug builds only:
+ *
+ * nssASN1Encoder_verify
+ *
+ * Related functions that aren't type methods:
+ *
+ * nssASN1_Encode
+ * nssASN1_EncodeItem
+ */
+
+/*
+ * nssASN1Encoder_Create
+ *
+ * This routine creates an ASN.1 Encoder, blah blah blah. This
+ * may return NULL upon error, in which case an error will have been
+ * placed on the error stack.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_ENCODING_NOT_SUPPORTED
+ * ...
+ *
+ * Return value:
+ * NULL upon error
+ * A pointer to an ASN.1 Encoder upon success
+ */
+
+NSS_EXTERN nssASN1Encoder *
+nssASN1Encoder_Create
+(
+ const void *source,
+ const nssASN1Template template[],
+ NSSASN1EncodingType encoding,
+ nssASN1EncoderWriteFunction *sink,
+ void *argument
+);
+
+extern const NSSError NSS_ERROR_NO_MEMORY;
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+extern const NSSError NSS_ERROR_ENCODING_NOT_SUPPORTED;
+
+/*
+ * nssASN1Encoder_Update
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Encoder_Update
+(
+ nssASN1Encoder *encoder,
+ const void *data,
+ PRUint32 length
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER;
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+
+/*
+ * nssASN1Encoder_Finish
+ *
+ * Destructor.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Encoder_Finish
+(
+ nssASN1Encoder *encoder
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER;
+
+/*
+ * nssASN1Encoder_SetNotify
+ *
+ * This routine registers a callback notify routine with the encoder,
+ * which will be called whenever.. The specified argument will be
+ * passed as-is to the notify routine. The routine pointer may be
+ * NULL, in which case no notify routine will be called. This routine
+ * returns a PRStatus value; in the event of an error it will place
+ * an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1DECODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Encoder_SetNotify
+(
+ nssASN1Encoder *encoder,
+ nssASN1NotifyFunction *callback,
+ void *argument
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER;
+
+/*
+ * nssASN1Encoder_GetNotify
+ *
+ * If the optional pCallbackOpt argument to this routine is non-null,
+ * then the pointer to any callback function established for this
+ * decoder with nssASN1Encoder_SetNotify will be stored at the
+ * location indicated by it. If the optional pArgumentOpt pointer is
+ * non-null, the filter's closure argument will be stored there.
+ * This routine returns a PRStatus value; in the event of an error it
+ * will place an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Encoder_GetNotify
+(
+ nssASN1Encoder *encoder,
+ nssASN1NotifyFunction **pCallbackOpt,
+ void **pArgumentOpt
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER;
+
+/*
+ * nssASN1Encoder_SetStreaming
+ *
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Encoder_SetStreaming
+(
+ nssASN1Encoder *encoder,
+ PRBool streaming
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER;
+
+/*
+ * nssASN1Encoder_GetStreaming
+ *
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Encoder_GetStreaming
+(
+ nssASN1Encoder *encoder,
+ PRBool *pStreaming
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER;
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+
+/*
+ * nssASN1Encoder_SetTakeFromBuffer
+ *
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Encoder_SetTakeFromBuffer
+(
+ nssASN1Encoder *encoder,
+ PRBool takeFromBuffer
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER;
+
+/*
+ * nssASN1Encoder_GetTakeFromBuffer
+ *
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ * NSS_ERROR_INVALID_POINTER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1Encoder_GetTakeFromBuffer
+(
+ nssASN1Encoder *encoder,
+ PRBool *pTakeFromBuffer
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER;
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+
+/*
+ * nssASN1Encoder_verify
+ *
+ * This routine is only available in debug builds.
+ *
+ * If the specified pointer is a valid pointer to an nssASN1Encoder
+ * object, this routine will return PR_SUCCESS. Otherwise, it will
+ * put an error on the error stack and return PR_FAILURE.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_INVALID_ASN1ENCODER
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+#ifdef DEBUG
+NSS_EXTERN PRStatus
+nssASN1Encoder_verify
+(
+ nssASN1Encoder *encoder
+);
+
+extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER;
+#endif /* DEBUG */
+
+/*
+ * nssASN1_Encode
+ *
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_ENCODING_NOT_SUPPORTED
+ * ...
+ *
+ * Return value:
+ * PR_FAILURE upon error
+ * PR_SUCCESS upon success
+ */
+
+NSS_EXTERN PRStatus
+nssASN1_Encode
+(
+ const void *source,
+ const nssASN1Template template[],
+ NSSASN1EncodingType encoding,
+ nssASN1EncoderWriteFunction *sink,
+ void *argument
+);
+
+extern const NSSError NSS_ERROR_NO_MEMORY;
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+extern const NSSError NSS_ERROR_ENCODING_NOT_SUPPORTED;
+
+/*
+ * nssASN1_EncodeItem
+ *
+ * There must be a better name. If the optional arena argument is
+ * non-null, it'll be used for the space. If the optional rvOpt is
+ * non-null, it'll be the return value-- if it is null, a new one
+ * will be allocated.
+ *
+ * The error may be one of the following values:
+ * NSS_ERROR_NO_MEMORY
+ * NSS_ERROR_INVALID_ARENA
+ * NSS_ERROR_INVALID_POINTER
+ * NSS_ERROR_ENCODING_NOT_SUPPORTED
+ *
+ * Return value:
+ * NULL upon error
+ * A valid pointer to an NSSDER upon success
+ */
+
+NSS_EXTERN NSSDER *
+nssASN1_EncodeItem
+(
+ NSSArena *arenaOpt,
+ NSSDER *rvOpt,
+ const void *source,
+ const nssASN1Template template[],
+ NSSASN1EncodingType encoding
+);
+
+extern const NSSError NSS_ERROR_NO_MEMORY;
+extern const NSSError NSS_ERROR_INVALID_ARENA;
+extern const NSSError NSS_ERROR_INVALID_POINTER;
+extern const NSSError NSS_ERROR_ENCODING_NOT_SUPPORTED;
+
+/*
+ * Other basic types' encoding and decoding helper functions:
+ *
+ * nssASN1_CreatePRUint32FromBER
+ * nssASN1_GetDERFromPRUint32
+ * nssASN1_CreatePRInt32FromBER
+ * nssASN1_GetDERFromPRInt32
+ * ..etc..
+ */
+
+/*
+ * nssASN1_CreatePRUint32FromBER
+ *
+ */
+
+NSS_EXTERN PRStatus
+nssASN1_CreatePRUint32FromBER
+(
+ NSSBER *encoded,
+ PRUint32 *pResult
+);
+
+/*
+ * nssASN1_GetDERFromPRUint32
+ *
+ */
+
+NSS_EXTERN NSSDER *
+nssASN1_GetDERFromPRUint32
+(
+ NSSArena *arenaOpt,
+ NSSDER *rvOpt,
+ PRUint32 value
+);
+
+/*
+ * nssASN1_CreatePRInt32FromBER
+ *
+ */
+
+NSS_EXTERN PRStatus
+nssASN1_CreatePRInt32FromBER
+(
+ NSSBER *encoded,
+ PRInt32 *pResult
+);
+
+/*
+ * nssASN1_GetDERFromPRInt32
+ *
+ */
+
+NSS_EXTERN NSSDER *
+nssASN1_GetDERFromPRInt32
+(
+ NSSArena *arenaOpt,
+ NSSDER *rvOpt,
+ PRInt32 value
+);
+
+/*
+ * Builtin templates
+ */
+
+/*
+ * 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
+ *
+ * Note that these are alphabetical (case insensitive); please add new
+ * ones in the appropriate place.
+ */
+
+extern const nssASN1Template *nssASN1Template_Any;
+extern const nssASN1Template *nssASN1Template_BitString;
+extern const nssASN1Template *nssASN1Template_BMPString;
+extern const nssASN1Template *nssASN1Template_Boolean;
+extern const nssASN1Template *nssASN1Template_Enumerated;
+extern const nssASN1Template *nssASN1Template_GeneralizedTime;
+extern const nssASN1Template *nssASN1Template_IA5String;
+extern const nssASN1Template *nssASN1Template_Integer;
+extern const nssASN1Template *nssASN1Template_Null;
+extern const nssASN1Template *nssASN1Template_ObjectID;
+extern const nssASN1Template *nssASN1Template_OctetString;
+extern const nssASN1Template *nssASN1Template_PrintableString;
+extern const nssASN1Template *nssASN1Template_T61String;
+extern const nssASN1Template *nssASN1Template_UniversalString;
+extern const nssASN1Template *nssASN1Template_UTCTime;
+extern const nssASN1Template *nssASN1Template_UTF8String;
+extern const nssASN1Template *nssASN1Template_VisibleString;
+
+extern const nssASN1Template *nssASN1Template_PointerToAny;
+extern const nssASN1Template *nssASN1Template_PointerToBitString;
+extern const nssASN1Template *nssASN1Template_PointerToBMPString;
+extern const nssASN1Template *nssASN1Template_PointerToBoolean;
+extern const nssASN1Template *nssASN1Template_PointerToEnumerated;
+extern const nssASN1Template *nssASN1Template_PointerToGeneralizedTime;
+extern const nssASN1Template *nssASN1Template_PointerToIA5String;
+extern const nssASN1Template *nssASN1Template_PointerToInteger;
+extern const nssASN1Template *nssASN1Template_PointerToNull;
+extern const nssASN1Template *nssASN1Template_PointerToObjectID;
+extern const nssASN1Template *nssASN1Template_PointerToOctetString;
+extern const nssASN1Template *nssASN1Template_PointerToPrintableString;
+extern const nssASN1Template *nssASN1Template_PointerToT61String;
+extern const nssASN1Template *nssASN1Template_PointerToUniversalString;
+extern const nssASN1Template *nssASN1Template_PointerToUTCTime;
+extern const nssASN1Template *nssASN1Template_PointerToUTF8String;
+extern const nssASN1Template *nssASN1Template_PointerToVisibleString;
+
+extern const nssASN1Template *nssASN1Template_SetOfAny;
+extern const nssASN1Template *nssASN1Template_SetOfBitString;
+extern const nssASN1Template *nssASN1Template_SetOfBMPString;
+extern const nssASN1Template *nssASN1Template_SetOfBoolean;
+extern const nssASN1Template *nssASN1Template_SetOfEnumerated;
+extern const nssASN1Template *nssASN1Template_SetOfGeneralizedTime;
+extern const nssASN1Template *nssASN1Template_SetOfIA5String;
+extern const nssASN1Template *nssASN1Template_SetOfInteger;
+extern const nssASN1Template *nssASN1Template_SetOfNull;
+extern const nssASN1Template *nssASN1Template_SetOfObjectID;
+extern const nssASN1Template *nssASN1Template_SetOfOctetString;
+extern const nssASN1Template *nssASN1Template_SetOfPrintableString;
+extern const nssASN1Template *nssASN1Template_SetOfT61String;
+extern const nssASN1Template *nssASN1Template_SetOfUniversalString;
+extern const nssASN1Template *nssASN1Template_SetOfUTCTime;
+extern const nssASN1Template *nssASN1Template_SetOfUTF8String;
+extern const nssASN1Template *nssASN1Template_SetOfVisibleString;
+
+/*
+ *
+ */
+
+NSS_EXTERN NSSUTF8 *
+nssUTF8_CreateFromBER
+(
+ NSSArena *arenaOpt,
+ nssStringType type,
+ NSSBER *berData
+);
+
+NSS_EXTERN NSSDER *
+nssUTF8_GetDEREncoding
+(
+ NSSArena *arenaOpt,
+ /* Should have an NSSDER *rvOpt */
+ nssStringType type,
+ const NSSUTF8 *string
+);
+
+PR_END_EXTERN_C
+
+#endif /* ASN1_H */
diff --git a/security/nss/lib/asn1/asn1m.h b/security/nss/lib/asn1/asn1m.h
new file mode 100644
index 000000000..957591d88
--- /dev/null
+++ b/security/nss/lib/asn1/asn1m.h
@@ -0,0 +1,83 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef ASN1M_H
+#define ASN1M_H
+
+#ifdef DEBUG
+static const char ASN1M_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
+#endif /* DEBUG */
+
+/*
+ * asn1m.h
+ *
+ * This file contains the ASN.1 encoder/decoder routines available
+ * only within the ASN.1 module itself.
+ */
+
+#ifndef ASN1_H
+#include "asn1.h"
+#endif /* ASN1_H */
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * nssasn1_number_length
+ *
+ */
+
+NSS_EXTERN PRUint32
+nssasn1_length_length
+(
+ PRUint32 number
+);
+
+/*
+ * nssasn1_get_subtemplate
+ *
+ */
+
+NSS_EXTERN const nssASN1Template *
+nssasn1_get_subtemplate
+(
+ const nssASN1Template template[],
+ void *thing,
+ PRBool encoding
+);
+
+PR_END_EXTERN_C
+
+#endif /* ASN1M_H */
diff --git a/security/nss/lib/asn1/asn1t.h b/security/nss/lib/asn1/asn1t.h
new file mode 100644
index 000000000..d7d8d6585
--- /dev/null
+++ b/security/nss/lib/asn1/asn1t.h
@@ -0,0 +1,169 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef ASN1T_H
+#define ASN1T_H
+
+#ifdef DEBUG
+static const char ASN1T_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
+#endif /* DEBUG */
+
+/*
+ * asn1t.h
+ *
+ * This file contains the ASN.1 encoder/decoder types available
+ * internally within NSS. It's not clear right now if this file
+ * will be folded into baset.h or something, I just needed to
+ * get this going. At the moment, these types are wrappers for
+ * the old types.
+ */
+
+#ifndef BASET_H
+#include "baset.h"
+#endif /* BASET_H */
+
+#ifndef NSSASN1T_H
+#include "nssasn1t.h"
+#endif /* NSSASN1T_H */
+
+#include "seccomon.h"
+#include "secasn1t.h"
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * XXX fgmr
+ *
+ * This sort of bites. Let's keep an eye on this, to make sure
+ * we aren't stuck with it forever.
+ */
+
+struct nssASN1ItemStr {
+ PRUint32 reserved;
+ PRUint8 *data;
+ PRUint32 size;
+};
+
+typedef struct nssASN1ItemStr nssASN1Item;
+
+/*
+ * I'm not documenting these here, since this'll require another
+ * pass anyway.
+ */
+
+typedef SEC_ASN1Template nssASN1Template;
+
+#define nssASN1_TAG_MASK SEC_ASN1_TAG_MASK
+
+#define nssASN1_TAGNUM_MASK SEC_ASN1_TAGNUM_MASK
+#define nssASN1_BOOLEAN SEC_ASN1_BOOLEAN
+#define nssASN1_INTEGER SEC_ASN1_INTEGER
+#define nssASN1_BIT_STRING SEC_ASN1_BIT_STRING
+#define nssASN1_OCTET_STRING SEC_ASN1_OCTET_STRING
+#define nssASN1_NULL SEC_ASN1_NULL
+#define nssASN1_OBJECT_ID SEC_ASN1_OBJECT_ID
+#define nssASN1_OBJECT_DESCRIPTOR SEC_ASN1_OBJECT_DESCRIPTOR
+/* External type and instance-of type 0x08 */
+#define nssASN1_REAL SEC_ASN1_REAL
+#define nssASN1_ENUMERATED SEC_ASN1_ENUMERATED
+#define nssASN1_EMBEDDED_PDV SEC_ASN1_EMBEDDED_PDV
+#define nssASN1_UTF8_STRING SEC_ASN1_UTF8_STRING
+#define nssASN1_SEQUENCE SEC_ASN1_SEQUENCE
+#define nssASN1_SET SEC_ASN1_SET
+#define nssASN1_NUMERIC_STRING SEC_ASN1_NUMERIC_STRING
+#define nssASN1_PRINTABLE_STRING SEC_ASN1_PRINTABLE_STRING
+#define nssASN1_T61_STRING SEC_ASN1_T61_STRING
+#define nssASN1_TELETEX_STRING nssASN1_T61_STRING
+#define nssASN1_VIDEOTEX_STRING SEC_ASN1_VIDEOTEX_STRING
+#define nssASN1_IA5_STRING SEC_ASN1_IA5_STRING
+#define nssASN1_UTC_TIME SEC_ASN1_UTC_TIME
+#define nssASN1_GENERALIZED_TIME SEC_ASN1_GENERALIZED_TIME
+#define nssASN1_GRAPHIC_STRING SEC_ASN1_GRAPHIC_STRING
+#define nssASN1_VISIBLE_STRING SEC_ASN1_VISIBLE_STRING
+#define nssASN1_GENERAL_STRING SEC_ASN1_GENERAL_STRING
+#define nssASN1_UNIVERSAL_STRING SEC_ASN1_UNIVERSAL_STRING
+/* 0x1d */
+#define nssASN1_BMP_STRING SEC_ASN1_BMP_STRING
+#define nssASN1_HIGH_TAG_NUMBER SEC_ASN1_HIGH_TAG_NUMBER
+
+#define nssASN1_METHOD_MASK SEC_ASN1_METHOD_MASK
+#define nssASN1_PRIMITIVE SEC_ASN1_PRIMITIVE
+#define nssASN1_CONSTRUCTED SEC_ASN1_CONSTRUCTED
+
+#define nssASN1_CLASS_MASK SEC_ASN1_CLASS_MASK
+#define nssASN1_UNIVERSAL SEC_ASN1_UNIVERSAL
+#define nssASN1_APPLICATION SEC_ASN1_APPLICATION
+#define nssASN1_CONTEXT_SPECIFIC SEC_ASN1_CONTEXT_SPECIFIC
+#define nssASN1_PRIVATE SEC_ASN1_PRIVATE
+
+#define nssASN1_OPTIONAL SEC_ASN1_OPTIONAL
+#define nssASN1_EXPLICIT SEC_ASN1_EXPLICIT
+#define nssASN1_ANY SEC_ASN1_ANY
+#define nssASN1_INLINE SEC_ASN1_INLINE
+#define nssASN1_POINTER SEC_ASN1_POINTER
+#define nssASN1_GROUP SEC_ASN1_GROUP
+#define nssASN1_DYNAMIC SEC_ASN1_DYNAMIC
+#define nssASN1_SKIP SEC_ASN1_SKIP
+#define nssASN1_INNER SEC_ASN1_INNER
+#define nssASN1_SAVE SEC_ASN1_SAVE
+#define nssASN1_MAY_STREAM SEC_ASN1_MAY_STREAM
+#define nssASN1_SKIP_REST SEC_ASN1_SKIP_REST
+#define nssASN1_CHOICE SEC_ASN1_CHOICE
+
+#define nssASN1_SEQUENCE_OF SEC_ASN1_SEQUENCE_OF
+#define nssASN1_SET_OF SEC_ASN1_SET_OF
+#define nssASN1_ANY_CONTENTS SEC_ASN1_ANY_CONTENTS
+
+typedef SEC_ASN1TemplateChooserPtr nssASN1ChooseTemplateFunction;
+
+typedef SEC_ASN1DecoderContext nssASN1Decoder;
+typedef SEC_ASN1EncoderContext nssASN1Encoder;
+
+typedef enum {
+ nssASN1EncodingPartIdentifier = SEC_ASN1_Identifier,
+ nssASN1EncodingPartLength = SEC_ASN1_Length,
+ nssASN1EncodingPartContents = SEC_ASN1_Contents,
+ nssASN1EncodingPartEndOfContents = SEC_ASN1_EndOfContents
+} nssASN1EncodingPart;
+
+typedef SEC_ASN1NotifyProc nssASN1NotifyFunction;
+
+typedef SEC_ASN1WriteProc nssASN1EncoderWriteFunction;
+typedef SEC_ASN1WriteProc nssASN1DecoderFilterFunction;
+
+PR_END_EXTERN_C
+
+#endif /* ASN1T_H */
diff --git a/security/nss/lib/asn1/config.mk b/security/nss/lib/asn1/config.mk
new file mode 100644
index 000000000..f4e5b965b
--- /dev/null
+++ b/security/nss/lib/asn1/config.mk
@@ -0,0 +1,52 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+CONFIG_CVS_ID = "@(#) $RCSfile$ $Revision$ $Date$"
+
+ifdef BUILD_IDG
+DEFINES += -DNSSDEBUG
+endif
+
+#
+# Override TARGETS variable so that only static libraries
+# are specifed as dependencies within rules.mk.
+#
+
+TARGETS = $(LIBRARY)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+PROGRAM =
+
diff --git a/security/nss/lib/asn1/manifest.mn b/security/nss/lib/asn1/manifest.mn
new file mode 100644
index 000000000..382a5baa3
--- /dev/null
+++ b/security/nss/lib/asn1/manifest.mn
@@ -0,0 +1,59 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1994-2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+MANIFEST_CVS_ID = "@(#) $RCSfile$ $Revision$ $Date$"
+
+CORE_DEPTH = ../../..
+
+PRIVATE_EXPORTS = \
+ asn1t.h \
+ asn1m.h \
+ asn1.h \
+ nssasn1t.h \
+ $(NULL)
+
+EXPORTS = \
+ $(NULL)
+
+MODULE = nss
+
+CSRCS = \
+ asn1.c \
+ $(NULL)
+
+REQUIRES = nspr
+
+LIBRARY_NAME = asn1
diff --git a/security/nss/lib/asn1/nssasn1t.h b/security/nss/lib/asn1/nssasn1t.h
new file mode 100644
index 000000000..6df1f24a0
--- /dev/null
+++ b/security/nss/lib/asn1/nssasn1t.h
@@ -0,0 +1,70 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef NSSASN1T_H
+#define NSSASN1T_H
+
+#ifdef DEBUG
+static const char NSSASN1T_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
+#endif /* DEBUG */
+
+/*
+ * nssasn1t.h
+ *
+ * This file contains the public types related to our ASN.1 encoder
+ * and decoder.
+ */
+
+PR_BEGIN_EXTERN_C
+
+/*
+ * NSSASN1EncodingType
+ *
+ * This type enumerates specific types of ASN.1 encodings.
+ */
+
+typedef enum {
+ NSSASN1BER, /* Basic Encoding Rules */
+ NSSASN1CER, /* Canonical Encoding Rules */
+ NSSASN1DER, /* Distinguished Encoding Rules */
+ NSSASN1LWER, /* LightWeight Encoding Rules */
+ NSSASN1PER, /* Packed Encoding Rules */
+ NSSASN1UnknownEncoding = -1
+} NSSASN1EncodingType;
+
+PR_END_EXTERN_C
+
+#endif /* NSSASN1T_H */
diff --git a/security/nss/lib/dev/devmod.c b/security/nss/lib/dev/devmod.c
new file mode 100644
index 000000000..85e5c9dda
--- /dev/null
+++ b/security/nss/lib/dev/devmod.c
@@ -0,0 +1,878 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef DEBUG
+static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
+#endif /* DEBUG */
+
+#ifndef NSSCKEPV_H
+#include "nssckepv.h"
+#endif /* NSSCKEPV_H */
+
+#ifndef DEVM_H
+#include "devm.h"
+#endif /* DEVM_H */
+
+#ifndef CKHELPER_H
+#include "ckhelper.h"
+#endif /* CKHELPER_H */
+
+#ifdef PURE_STAN_CODE
+
+extern void FC_GetFunctionList(void);
+extern void NSC_GetFunctionList(void);
+extern void NSC_ModuleDBFunc(void);
+
+/* The list of boolean flags used to describe properties of a
+ * module.
+ */
+#define NSSMODULE_FLAGS_NOT_THREADSAFE 0x0001 /* isThreadSafe */
+#define NSSMODULE_FLAGS_INTERNAL 0x0002 /* isInternal */
+#define NSSMODULE_FLAGS_FIPS 0x0004 /* isFIPS */
+#define NSSMODULE_FLAGS_MODULE_DB 0x0008 /* isModuleDB */
+#define NSSMODULE_FLAGS_MODULE_DB_ONLY 0x0010 /* moduleDBOnly */
+#define NSSMODULE_FLAGS_CRITICAL 0x0020 /* isCritical */
+
+struct NSSModuleStr {
+ struct nssDeviceBaseStr base;
+ NSSUTF8 *libraryName;
+ PRLibrary *library;
+ char *libraryParams;
+ void *moduleDBFunc;
+ void *epv;
+ CK_INFO info;
+ NSSSlot **slots;
+ PRUint32 numSlots;
+ PRBool isLoaded;
+ struct {
+ PRInt32 trust;
+ PRInt32 cipher;
+ PRInt32 certStorage;
+ } order;
+};
+
+#define NSSMODULE_IS_THREADSAFE(module) \
+ (!(module->base.flags & NSSMODULE_FLAGS_NOT_THREADSAFE))
+
+#define NSSMODULE_IS_INTERNAL(module) \
+ (module->base.flags & NSSMODULE_FLAGS_INTERNAL)
+
+#define NSSMODULE_IS_FIPS(module) \
+ (module->base.flags & NSSMODULE_FLAGS_FIPS)
+
+#define NSSMODULE_IS_MODULE_DB(module) \
+ (module->base.flags & NSSMODULE_FLAGS_MODULE_DB)
+
+#define NSSMODULE_IS_MODULE_DB_ONLY(module) \
+ (module->base.flags & NSSMODULE_FLAGS_MODULE_DB_ONLY)
+
+#define NSSMODULE_IS_CRITICAL(module) \
+ (module->base.flags & NSSMODULE_FLAGS_CRITICAL)
+
+/* Threading callbacks for C_Initialize. Use NSPR threads. */
+
+CK_RV PR_CALLBACK
+nss_ck_CreateMutex(CK_VOID_PTR_PTR pMutex)
+{
+ CK_VOID_PTR mutex = (CK_VOID_PTR)PZ_NewLock(nssILockOther);
+ if (mutex != NULL) {
+ *pMutex = (CK_VOID_PTR)mutex;
+ return CKR_OK;
+ }
+ return CKR_HOST_MEMORY;
+}
+
+CK_RV PR_CALLBACK
+nss_ck_DestroyMutex(CK_VOID_PTR mutex)
+{
+ PZ_DestroyLock((PZLock *)mutex);
+ return CKR_OK;
+}
+
+CK_RV PR_CALLBACK
+nss_ck_LockMutex(CK_VOID_PTR mutex)
+{
+ PZ_Lock((PZLock *)mutex);
+ return CKR_OK;
+}
+
+CK_RV PR_CALLBACK
+nss_ck_UnlockMutex(CK_VOID_PTR mutex)
+{
+ return (PZ_Unlock((PZLock *)mutex) == PR_SUCCESS) ?
+ CKR_OK : CKR_MUTEX_NOT_LOCKED;
+}
+
+/* Default callback args to C_Initialize */
+/* XXX not const because we are modifying the pReserved argument in order
+ * to use the libraryParams extension.
+ */
+static CK_C_INITIALIZE_ARGS
+s_ck_initialize_args = {
+ nss_ck_CreateMutex, /* CreateMutex */
+ nss_ck_DestroyMutex, /* DestroyMutex */
+ nss_ck_LockMutex, /* LockMutex */
+ nss_ck_UnlockMutex, /* UnlockMutex */
+ CKF_LIBRARY_CANT_CREATE_OS_THREADS |
+ CKF_OS_LOCKING_OK, /* flags */
+ NULL /* pReserved */
+};
+
+/* load all slots in a module. */
+static PRStatus
+module_load_slots(NSSModule *mod)
+{
+ CK_ULONG i, ulNumSlots;
+ CK_SLOT_ID *slotIDs;
+ nssArenaMark *mark = NULL;
+ NSSSlot **slots;
+ PRStatus nssrv;
+ CK_RV ckrv;
+ /* Get the number of slots */
+ ckrv = CKAPI(mod->epv)->C_GetSlotList(CK_FALSE, NULL, &ulNumSlots);
+ if (ckrv != CKR_OK) {
+ /* what is the error? */
+ return PR_FAILURE;
+ }
+ /* Alloc memory for the array of slot ID's */
+ slotIDs = nss_ZNEWARRAY(NULL, CK_SLOT_ID, ulNumSlots);
+ if (!slotIDs) {
+ goto loser;
+ }
+ /* Get the actual slot list */
+ ckrv = CKAPI(mod->epv)->C_GetSlotList(CK_FALSE, slotIDs, &ulNumSlots);
+ if (ckrv != CKR_OK) {
+ /* what is the error? */
+ goto loser;
+ }
+ /* Alloc memory for the array of slots, in the module's arena */
+ mark = nssArena_Mark(mod->base.arena); /* why mark? it'll be destroyed */
+ if (!mark) {
+ return PR_FAILURE;
+ }
+ slots = nss_ZNEWARRAY(mod->base.arena, NSSSlot *, ulNumSlots);
+ if (!slots) {
+ goto loser;
+ }
+ /* Initialize each slot */
+ for (i=0; i<ulNumSlots; i++) {
+ slots[i] = nssSlot_Create(slotIDs[i], mod);
+ }
+ nss_ZFreeIf(slotIDs);
+ nssrv = nssArena_Unmark(mod->base.arena, mark);
+ if (nssrv != PR_SUCCESS) {
+ goto loser;
+ }
+ mod->slots = slots;
+ mod->numSlots = ulNumSlots;
+ return PR_SUCCESS;
+loser:
+ if (mark) {
+ nssArena_Release(mod->base.arena, mark);
+ }
+ nss_ZFreeIf(slotIDs);
+ return PR_FAILURE;
+}
+
+NSS_IMPLEMENT PRStatus
+nssModule_Load (
+ NSSModule *mod
+)
+{
+ PRLibrary *library = NULL;
+ CK_C_GetFunctionList epv;
+ CK_RV ckrv;
+ if (NSSMODULE_IS_INTERNAL(mod)) {
+ /* internal, statically get the C_GetFunctionList function */
+ if (NSSMODULE_IS_FIPS(mod)) {
+ epv = (CK_C_GetFunctionList) FC_GetFunctionList;
+ } else {
+ epv = (CK_C_GetFunctionList) NSC_GetFunctionList;
+ }
+ if (NSSMODULE_IS_MODULE_DB(mod)) {
+ mod->moduleDBFunc = (void *) NSC_ModuleDBFunc;
+ }
+ if (NSSMODULE_IS_MODULE_DB_ONLY(mod)) {
+ mod->isLoaded = PR_TRUE; /* XXX needed? */
+ return PR_SUCCESS;
+ }
+ } else {
+ /* Use NSPR to load the library */
+ library = PR_LoadLibrary(mod->libraryName);
+ if (!library) {
+ /* what's the error to set? */
+ return PR_FAILURE;
+ }
+ mod->library = library;
+ /* Skip if only getting the db loader function */
+ if (!NSSMODULE_IS_MODULE_DB_ONLY(mod)) {
+ /* Load the cryptoki entry point function */
+ epv = (CK_C_GetFunctionList)PR_FindSymbol(library,
+ "C_GetFunctionList");
+ }
+ /* Load the module database loader function */
+ if (NSSMODULE_IS_MODULE_DB(mod)) {
+ mod->moduleDBFunc = (void *)PR_FindSymbol(library,
+ "NSS_ReturnModuleSpecData");
+ }
+ }
+ if (epv == NULL) {
+ goto loser;
+ }
+ /* Load the cryptoki entry point vector (function list) */
+ ckrv = (*epv)((CK_FUNCTION_LIST_PTR *)&mod->epv);
+ if (ckrv != CKR_OK) {
+ goto loser;
+ }
+ /* Initialize the module */
+ if (mod->libraryParams) {
+ s_ck_initialize_args.LibraryParameters = (void *)mod->libraryParams;
+ } else {
+ s_ck_initialize_args.LibraryParameters = NULL;
+ }
+ ckrv = CKAPI(mod->epv)->C_Initialize(&s_ck_initialize_args);
+ if (ckrv != CKR_OK) {
+ /* Apparently the token is not thread safe. Retry without
+ * threading parameters.
+ */
+ mod->base.flags |= NSSMODULE_FLAGS_NOT_THREADSAFE;
+ ckrv = CKAPI(mod->epv)->C_Initialize((CK_VOID_PTR)NULL);
+ if (ckrv != CKR_OK) {
+ goto loser;
+ }
+ }
+ /* TODO: check the version # using C_GetInfo */
+ ckrv = CKAPI(mod->epv)->C_GetInfo(&mod->info);
+ if (ckrv != CKR_OK) {
+ goto loser;
+ }
+ /* TODO: if the name is not set, get it from info.libraryDescription */
+ /* Now load the slots */
+ if (module_load_slots(mod) != PR_SUCCESS) {
+ goto loser;
+ }
+ /* Module has successfully loaded */
+ mod->isLoaded = PR_TRUE;
+ return PR_SUCCESS;
+loser:
+ if (library) {
+ PR_UnloadLibrary(library);
+ }
+ /* clear all values set above, they are invalid now */
+ mod->library = NULL;
+ mod->epv = NULL;
+ return PR_FAILURE;
+}
+
+NSS_IMPLEMENT PRStatus
+nssModule_Unload (
+ NSSModule *mod
+)
+{
+ PRStatus nssrv = PR_SUCCESS;
+ if (mod->library) {
+ (void)CKAPI(mod->epv)->C_Finalize(NULL);
+ nssrv = PR_UnloadLibrary(mod->library);
+ }
+ /* Free the slots, yes? */
+ mod->library = NULL;
+ mod->epv = NULL;
+ mod->isLoaded = PR_FALSE;
+ return nssrv;
+}
+
+/* Alloc memory for a module. Copy in the module name and library path
+ * if provided. XXX use the opaque arg also, right?
+ */
+NSS_IMPLEMENT NSSModule *
+nssModule_Create (
+ NSSUTF8 *moduleOpt,
+ NSSUTF8 *uriOpt,
+ NSSUTF8 *opaqueOpt,
+ void *reserved
+)
+{
+ NSSArena *arena;
+ NSSModule *rvMod;
+ arena = NSSArena_Create();
+ if(!arena) {
+ return (NSSModule *)NULL;
+ }
+ rvMod = nss_ZNEW(arena, NSSModule);
+ if (!rvMod) {
+ goto loser;
+ }
+ if (moduleOpt) {
+ /* XXX making the gross assumption this is just the module name */
+ /* if the name is a duplicate, should that be tested here? or
+ * wait for Load?
+ */
+ rvMod->base.name = nssUTF8_Duplicate(moduleOpt, arena);
+ if (!rvMod->base.name) {
+ goto loser;
+ }
+ }
+ if (uriOpt) {
+ /* Load the module from a URI. */
+ /* XXX at this time - only file URI (even worse, no file:// for now) */
+ rvMod->libraryName = nssUTF8_Duplicate(uriOpt, arena);
+ if (!rvMod->libraryName) {
+ goto loser;
+ }
+ }
+ rvMod->base.arena = arena;
+ rvMod->base.refCount = 1;
+ rvMod->base.lock = PZ_NewLock(nssNSSILockOther);
+ if (!rvMod->base.lock) {
+ goto loser;
+ }
+ /* everything else is 0/NULL at this point. */
+ return rvMod;
+loser:
+ nssArena_Destroy(arena);
+ return (NSSModule *)NULL;
+}
+
+NSS_EXTERN PRStatus
+nssCryptokiArgs_ParseNextPair (
+ NSSUTF8 *start,
+ NSSUTF8 **attrib,
+ NSSUTF8 **value,
+ NSSUTF8 **remainder,
+ NSSArena *arenaOpt
+);
+
+static PRStatus
+parse_slot_flags (
+ NSSSlot *slot,
+ NSSUTF8 *slotFlags
+)
+{
+ PRStatus nssrv = PR_SUCCESS;
+#if 0
+ PRBool done = PR_FALSE;
+ NSSUTF8 *mark, *last;
+ last = mark = slotFlags;
+ while (PR_TRUE) {
+ while (*mark && *mark != ',') ++mark;
+ if (!*mark) done = PR_TRUE;
+ *mark = '\0';
+ if (nssUTF8_Equal(last, "RANDOM", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_HAS_RANDOM;
+ } else if (nssUTF8_Equal(last, "RSA", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_RSA;
+ } else if (nssUTF8_Equal(last, "DSA", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_DSA;
+ } else if (nssUTF8_Equal(last, "DH", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_DH;
+ } else if (nssUTF8_Equal(last, "RC2", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_RC2;
+ } else if (nssUTF8_Equal(last, "RC4", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_RC4;
+ } else if (nssUTF8_Equal(last, "RC5", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_RC5;
+ } else if (nssUTF8_Equal(last, "DES", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_DES;
+ } else if (nssUTF8_Equal(last, "AES", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_AES;
+ } else if (nssUTF8_Equal(last, "SHA1", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_SHA1;
+ } else if (nssUTF8_Equal(last, "MD2", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_MD2;
+ } else if (nssUTF8_Equal(last, "MD5", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_MD5;
+ } else if (nssUTF8_Equal(last, "SSL", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_SSL;
+ } else if (nssUTF8_Equal(last, "TLS", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_TLS;
+ } else if (nssUTF8_Equal(last, "PublicCerts", &nssrv)) {
+ slot->base.flags |= NSSSLOT_FLAGS_FRIENDLY;
+ } else {
+ return PR_FAILURE;
+ }
+ if (done) break;
+ last = ++mark;
+ }
+#endif
+ return nssrv;
+}
+
+static PRStatus
+parse_slot_parameters (
+ NSSSlot *slot,
+ NSSUTF8 *slotParams,
+ NSSArena *tmparena
+)
+{
+ PRStatus nssrv = PR_SUCCESS;
+ NSSUTF8 *current, *remainder;
+ NSSUTF8 *attrib, *value;
+ current = slotParams;
+ while (nssrv == PR_SUCCESS) {
+ nssrv = nssCryptokiArgs_ParseNextPair(current,
+ &attrib, &value,
+ &remainder, tmparena);
+ if (nssrv != PR_SUCCESS) break;
+ if (value) {
+ if (nssUTF8_Equal(attrib, "slotFlags", &nssrv)) {
+ nssrv = parse_slot_flags(slot, value);
+ } else if (nssUTF8_Equal(attrib, "askpw", &nssrv)) {
+ } else if (nssUTF8_Equal(attrib, "timeout", &nssrv)) {
+ }
+ }
+ if (*remainder == '\0') break;
+ current = remainder;
+ }
+ return nssrv;
+}
+
+/* softoken seems to use "0x0000001", but no standard yet... perhaps this
+ * should store the number as an ID, in case the input isn't 1,2,3,...?
+ */
+static PRIntn
+get_slot_number(NSSUTF8* snString)
+{
+ /* XXX super big hack */
+ return atoi(&snString[strlen(snString)-1]);
+}
+
+static PRStatus
+parse_module_slot_parameters (
+ NSSModule *mod,
+ NSSUTF8 *slotParams
+)
+{
+ PRStatus nssrv = PR_SUCCESS;
+ NSSUTF8 *current, *remainder;
+ NSSUTF8 *attrib, *value;
+ NSSArena *tmparena;
+ PRIntn slotNum;
+ tmparena = nssArena_Create();
+ if (!tmparena) {
+ return PR_FAILURE;
+ }
+ current = slotParams;
+ while (nssrv == PR_SUCCESS) {
+ nssrv = nssCryptokiArgs_ParseNextPair(current,
+ &attrib, &value,
+ &remainder, tmparena);
+ if (nssrv != PR_SUCCESS) break;
+ if (value) {
+ slotNum = get_slot_number(attrib);
+ if (slotNum < 0 || slotNum > mod->numSlots) {
+ return PR_FAILURE;
+ }
+ nssrv = parse_slot_parameters(mod->slots[slotNum],
+ value, tmparena);
+ if (nssrv != PR_SUCCESS) break;
+ }
+ if (*remainder == '\0') break;
+ current = remainder;
+ }
+ return nssrv;
+}
+
+static PRStatus
+parse_nss_flags (
+ NSSModule *mod,
+ NSSUTF8 *nssFlags
+)
+{
+ PRStatus nssrv = PR_SUCCESS;
+ PRBool done = PR_FALSE;
+ NSSUTF8 *mark, *last;
+ last = mark = nssFlags;
+ while (PR_TRUE) {
+ while (*mark && *mark != ',') ++mark;
+ if (!*mark) done = PR_TRUE;
+ *mark = '\0';
+ if (nssUTF8_Equal(last, "internal", &nssrv)) {
+ mod->base.flags |= NSSMODULE_FLAGS_INTERNAL;
+ } else if (nssUTF8_Equal(last, "moduleDB", &nssrv)) {
+ mod->base.flags |= NSSMODULE_FLAGS_MODULE_DB;
+ } else if (nssUTF8_Equal(last, "moduleDBOnly", &nssrv)) {
+ mod->base.flags |= NSSMODULE_FLAGS_MODULE_DB_ONLY;
+ } else if (nssUTF8_Equal(last, "critical", &nssrv)) {
+ mod->base.flags |= NSSMODULE_FLAGS_CRITICAL;
+ } else {
+ return PR_FAILURE;
+ }
+ if (done) break;
+ last = ++mark;
+ }
+ return nssrv;
+}
+
+static PRStatus
+parse_nss_parameters (
+ NSSModule *mod,
+ NSSUTF8 *nssParams,
+ NSSArena *tmparena,
+ NSSUTF8 **slotParams
+)
+{
+ PRStatus nssrv = PR_SUCCESS;
+ NSSUTF8 *current, *remainder;
+ NSSUTF8 *attrib, *value;
+ current = nssParams;
+ while (nssrv == PR_SUCCESS) {
+ nssrv = nssCryptokiArgs_ParseNextPair(current,
+ &attrib, &value,
+ &remainder, tmparena);
+ if (nssrv != PR_SUCCESS) break;
+ if (value) {
+ if (nssUTF8_Equal(attrib, "flags", &nssrv) ||
+ nssUTF8_Equal(attrib, "Flags", &nssrv)) {
+ nssrv = parse_nss_flags(mod, value);
+ } else if (nssUTF8_Equal(attrib, "trustOrder", &nssrv)) {
+ mod->order.trust = atoi(value);
+ } else if (nssUTF8_Equal(attrib, "cipherOrder", &nssrv)) {
+ mod->order.cipher = atoi(value);
+ } else if (nssUTF8_Equal(attrib, "ciphers", &nssrv)) {
+ } else if (nssUTF8_Equal(attrib, "slotParams", &nssrv)) {
+ /* slotParams doesn't get an arena, it is handled separately */
+ *slotParams = nssUTF8_Duplicate(value, NULL);
+ }
+ }
+ if (*remainder == '\0') break;
+ current = remainder;
+ }
+ return nssrv;
+}
+
+static PRStatus
+parse_module_parameters (
+ NSSModule *mod,
+ NSSUTF8 *moduleParams,
+ NSSUTF8 **slotParams
+)
+{
+ PRStatus nssrv = PR_SUCCESS;
+ NSSUTF8 *current, *remainder;
+ NSSUTF8 *attrib, *value;
+ NSSArena *arena = mod->base.arena;
+ NSSArena *tmparena;
+ current = moduleParams;
+ tmparena = nssArena_Create();
+ if (!tmparena) {
+ return PR_FAILURE;
+ }
+ while (nssrv == PR_SUCCESS) {
+ nssrv = nssCryptokiArgs_ParseNextPair(current,
+ &attrib, &value,
+ &remainder, tmparena);
+ if (nssrv != PR_SUCCESS) break;
+ if (value) {
+ if (nssUTF8_Equal(attrib, "name", &nssrv)) {
+ mod->base.name = nssUTF8_Duplicate(value, arena);
+ } else if (nssUTF8_Equal(attrib, "library", &nssrv)) {
+ mod->libraryName = nssUTF8_Duplicate(value, arena);
+ } else if (nssUTF8_Equal(attrib, "parameters", &nssrv)) {
+ mod->libraryParams = nssUTF8_Duplicate(value, arena);
+ } else if (nssUTF8_Equal(attrib, "NSS", &nssrv)) {
+ parse_nss_parameters(mod, value, tmparena, slotParams);
+ }
+ }
+ if (*remainder == '\0') break;
+ current = remainder;
+ }
+ nssArena_Destroy(tmparena);
+ return nssrv;
+}
+
+static NSSUTF8 **
+get_module_specs (
+ NSSModule *mod
+)
+{
+ SECMODModuleDBFunc func = (SECMODModuleDBFunc)mod->moduleDBFunc;
+ if (func) {
+ return (*func)(SECMOD_MODULE_DB_FUNCTION_FIND,
+ mod->libraryParams,
+ NULL);
+ }
+ return NULL;
+}
+
+/* XXX continue working on */
+NSS_IMPLEMENT NSSModule *
+nssModule_CreateFromSpec (
+ NSSUTF8 *moduleSpec,
+ NSSModule *parent,
+ PRBool loadSubModules
+)
+{
+ PRStatus nssrv;
+ NSSModule *thisModule;
+ NSSArena *arena;
+ NSSUTF8 *slotParams = NULL;
+ arena = nssArena_Create();
+ if (!arena) {
+ return NULL;
+ }
+ thisModule = nss_ZNEW(arena, NSSModule);
+ if (!thisModule) {
+ goto loser;
+ }
+ thisModule->base.lock = PZ_NewLock(nssILockOther);
+ if (!thisModule->base.lock) {
+ goto loser;
+ }
+ PR_AtomicIncrement(&thisModule->base.refCount);
+ thisModule->base.arena = arena;
+ thisModule->base.lock = PZ_NewLock(nssNSSILockOther);
+ if (!thisModule->base.lock) {
+ goto loser;
+ }
+ nssrv = parse_module_parameters(thisModule, moduleSpec, &slotParams);
+ if (nssrv != PR_SUCCESS) {
+ goto loser;
+ }
+ nssrv = nssModule_Load(thisModule);
+ if (nssrv != PR_SUCCESS) {
+ goto loser;
+ }
+ if (slotParams) {
+ nssrv = parse_module_slot_parameters(thisModule, slotParams);
+ nss_ZFreeIf(slotParams);
+ if (nssrv != PR_SUCCESS) {
+ goto loser;
+ }
+ }
+ if (loadSubModules && NSSMODULE_IS_MODULE_DB(thisModule)) {
+ NSSUTF8 **moduleSpecs;
+ NSSUTF8 **index;
+ /* get the array of sub modules one level below this module */
+ moduleSpecs = get_module_specs(thisModule);
+ /* iterate over the array */
+ for (index = moduleSpecs; index && *index; index++) {
+ NSSModule *child;
+ /* load the child recursively */
+ child = nssModule_CreateFromSpec(*index, thisModule, PR_TRUE);
+ if (!child) {
+ /* when children fail, does the parent? */
+ nssrv = PR_FAILURE;
+ break;
+ }
+ if (NSSMODULE_IS_CRITICAL(child) && !child->isLoaded) {
+ nssrv = PR_FAILURE;
+ nssModule_Destroy(child);
+ break;
+ }
+ nssModule_Destroy(child);
+ /*nss_ZFreeIf(*index);*/
+ }
+ /*nss_ZFreeIf(moduleSpecs);*/
+ }
+ /* The global list inherits the reference */
+ nssrv = nssGlobalModuleList_Add(thisModule);
+ if (nssrv != PR_SUCCESS) {
+ goto loser;
+ }
+ return thisModule;
+loser:
+ if (thisModule->base.lock) {
+ PZ_DestroyLock(thisModule->base.lock);
+ }
+ nssArena_Destroy(arena);
+ return (NSSModule *)NULL;
+}
+
+NSS_IMPLEMENT PRStatus
+nssModule_Destroy (
+ NSSModule *mod
+)
+{
+ PRUint32 i, numSlots;
+ if (PR_AtomicDecrement(&mod->base.refCount) == 0) {
+ if (mod->numSlots == 0) {
+ (void)nssModule_Unload(mod);
+ return nssArena_Destroy(mod->base.arena);
+ } else {
+ numSlots = mod->numSlots;
+ for (i=0; i<numSlots; i++) {
+ nssSlot_Destroy(mod->slots[i]);
+ }
+ }
+ }
+ return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT PRStatus
+nssModule_DestroyFromSlot (
+ NSSModule *mod,
+ NSSSlot *slot
+)
+{
+ PRUint32 i, numSlots = 0;
+ PR_ASSERT(mod->base.refCount == 0);
+ for (i=0; i<mod->numSlots; i++) {
+ if (mod->slots[i] == slot) {
+ mod->slots[i] = NULL;
+ } else if (mod->slots[i]) {
+ numSlots++;
+ }
+ }
+ if (numSlots == 0) {
+ (void)nssModule_Unload(mod);
+ return nssArena_Destroy(mod->base.arena);
+ }
+ return PR_SUCCESS;
+}
+
+NSS_IMPLEMENT NSSModule *
+nssModule_AddRef (
+ NSSModule *mod
+)
+{
+ PR_AtomicIncrement(&mod->base.refCount);
+ return mod;
+}
+
+NSS_IMPLEMENT NSSUTF8 *
+nssModule_GetName (
+ NSSModule *mod
+)
+{
+ return mod->base.name;
+}
+
+NSS_IMPLEMENT PRBool
+nssModule_IsThreadSafe (
+ NSSModule *module
+)
+{
+ return NSSMODULE_IS_THREADSAFE(module);
+}
+
+NSS_IMPLEMENT PRBool
+nssModule_IsInternal (
+ NSSModule *mod
+)
+{
+ return NSSMODULE_IS_INTERNAL(mod);
+}
+
+NSS_IMPLEMENT PRBool
+nssModule_IsModuleDBOnly (
+ NSSModule *mod
+)
+{
+ return NSSMODULE_IS_MODULE_DB_ONLY(mod);
+}
+
+NSS_IMPLEMENT void *
+nssModule_GetCryptokiEPV (
+ NSSModule *mod
+)
+{
+ return mod->epv;
+}
+
+NSS_IMPLEMENT NSSSlot **
+nssModule_GetSlots (
+ NSSModule *mod
+)
+{
+ PRUint32 i;
+ NSSSlot **rvSlots;
+ rvSlots = nss_ZNEWARRAY(NULL, NSSSlot *, mod->numSlots + 1);
+ if (rvSlots) {
+ for (i=0; i<mod->numSlots; i++) {
+ rvSlots[i] = nssSlot_AddRef(mod->slots[i]);
+ }
+ }
+ return rvSlots;
+}
+
+NSS_IMPLEMENT NSSSlot *
+nssModule_FindSlotByName (
+ NSSModule *mod,
+ NSSUTF8 *slotName
+)
+{
+ PRUint32 i;
+ PRStatus nssrv;
+ NSSSlot *slot;
+ NSSUTF8 *name;
+ for (i=0; i<mod->numSlots; i++) {
+ slot = mod->slots[i];
+ name = nssSlot_GetName(slot);
+ if (nssUTF8_Equal(name, slotName, &nssrv)) {
+ return nssSlot_AddRef(slot);
+ }
+ if (nssrv != PR_SUCCESS) {
+ break;
+ }
+ }
+ return (NSSSlot *)NULL;
+}
+
+NSS_IMPLEMENT NSSToken *
+nssModule_FindTokenByName (
+ NSSModule *mod,
+ NSSUTF8 *tokenName
+)
+{
+ PRUint32 i;
+ PRStatus nssrv;
+ NSSToken *tok;
+ NSSUTF8 *name;
+ for (i=0; i<mod->numSlots; i++) {
+ tok = nssSlot_GetToken(mod->slots[i]);
+ if (tok) {
+ name = nssToken_GetName(tok);
+ if (nssUTF8_Equal(name, tokenName, &nssrv)) {
+ return tok;
+ }
+ if (nssrv != PR_SUCCESS) {
+ break;
+ }
+ }
+ }
+ return (NSSToken *)NULL;
+}
+
+NSS_IMPLEMENT PRInt32
+nssModule_GetCertOrder (
+ NSSModule *module
+)
+{
+ return 1; /* XXX */
+}
+
+#endif /* PURE_STAN_BUILD */
+
diff --git a/security/nss/lib/pkcs12/p12dec.c b/security/nss/lib/pkcs12/p12dec.c
new file mode 100644
index 000000000..8124a01ed
--- /dev/null
+++ b/security/nss/lib/pkcs12/p12dec.c
@@ -0,0 +1,696 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "pkcs12.h"
+#include "plarena.h"
+#include "secpkcs7.h"
+#include "p12local.h"
+#include "secoid.h"
+#include "secitem.h"
+#include "secport.h"
+#include "secasn1.h"
+#include "secder.h"
+#include "secerr.h"
+#include "cert.h"
+#include "certdb.h"
+#include "p12plcy.h"
+#include "p12.h"
+#include "secpkcs5.h"
+
+/* PFX extraction and validation routines */
+
+/* decode the DER encoded PFX item. if unable to decode, check to see if it
+ * is an older PFX item. If that fails, assume the file was not a valid
+ * pfx file.
+ * the returned pfx structure should be destroyed using SEC_PKCS12DestroyPFX
+ */
+static SEC_PKCS12PFXItem *
+sec_pkcs12_decode_pfx(SECItem *der_pfx)
+{
+ SEC_PKCS12PFXItem *pfx;
+ SECStatus rv;
+
+ if(der_pfx == NULL) {
+ return NULL;
+ }
+
+ /* allocate the space for a new PFX item */
+ pfx = sec_pkcs12_new_pfx();
+ if(pfx == NULL) {
+ return NULL;
+ }
+
+ rv = SEC_ASN1DecodeItem(pfx->poolp, pfx, SEC_PKCS12PFXItemTemplate,
+ der_pfx);
+
+ /* if a failure occurred, check for older version...
+ * we also get rid of the old pfx structure, because we don't
+ * know where it failed and what data in may contain
+ */
+ if(rv != SECSuccess) {
+ SEC_PKCS12DestroyPFX(pfx);
+ pfx = sec_pkcs12_new_pfx();
+ if(pfx == NULL) {
+ return NULL;
+ }
+ rv = SEC_ASN1DecodeItem(pfx->poolp, pfx, SEC_PKCS12PFXItemTemplate_OLD,
+ der_pfx);
+ if(rv != SECSuccess) {
+ PORT_SetError(SEC_ERROR_PKCS12_DECODING_PFX);
+ PORT_FreeArena(pfx->poolp, PR_TRUE);
+ return NULL;
+ }
+ pfx->old = PR_TRUE;
+ SGN_CopyDigestInfo(pfx->poolp, &pfx->macData.safeMac, &pfx->old_safeMac);
+ SECITEM_CopyItem(pfx->poolp, &pfx->macData.macSalt, &pfx->old_macSalt);
+ } else {
+ pfx->old = PR_FALSE;
+ }
+
+ /* convert bit string from bits to bytes */
+ pfx->macData.macSalt.len /= 8;
+
+ return pfx;
+}
+
+/* validate the integrity MAC used in the PFX. The MAC is generated
+ * per the PKCS 12 document. If the MAC is incorrect, it is most likely
+ * due to an invalid password.
+ * pwitem is the integrity password
+ * pfx is the decoded pfx item
+ */
+static PRBool
+sec_pkcs12_check_pfx_mac(SEC_PKCS12PFXItem *pfx,
+ SECItem *pwitem)
+{
+ SECItem *key = NULL, *mac = NULL, *data = NULL;
+ SECItem *vpwd = NULL;
+ SECOidTag algorithm;
+ PRBool ret = PR_FALSE;
+
+ if(pfx == NULL) {
+ return PR_FALSE;
+ }
+
+ algorithm = SECOID_GetAlgorithmTag(&pfx->macData.safeMac.digestAlgorithm);
+ switch(algorithm) {
+ /* only SHA1 hashing supported as a MACing algorithm */
+ case SEC_OID_SHA1:
+ if(pfx->old == PR_FALSE) {
+ pfx->swapUnicode = PR_FALSE;
+ }
+
+recheckUnicodePassword:
+ vpwd = sec_pkcs12_create_virtual_password(pwitem,
+ &pfx->macData.macSalt,
+ pfx->swapUnicode);
+ if(vpwd == NULL) {
+ return PR_FALSE;
+ }
+
+ key = sec_pkcs12_generate_key_from_password(algorithm,
+ &pfx->macData.macSalt,
+ (pfx->old ? pwitem : vpwd));
+ /* free vpwd only for newer PFX */
+ if(vpwd) {
+ SECITEM_ZfreeItem(vpwd, PR_TRUE);
+ }
+ if(key == NULL) {
+ return PR_FALSE;
+ }
+
+ data = SEC_PKCS7GetContent(&pfx->authSafe);
+ if(data == NULL) {
+ break;
+ }
+
+ /* check MAC */
+ mac = sec_pkcs12_generate_mac(key, data, pfx->old);
+ ret = PR_TRUE;
+ if(mac) {
+ SECItem *safeMac = &pfx->macData.safeMac.digest;
+ if(SECITEM_CompareItem(mac, safeMac) != SECEqual) {
+
+ /* if we encounter an invalid mac, lets invert the
+ * password in case of unicode changes
+ */
+ if(((!pfx->old) && pfx->swapUnicode) || (pfx->old)){
+ PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC);
+ ret = PR_FALSE;
+ } else {
+ SECITEM_ZfreeItem(mac, PR_TRUE);
+ pfx->swapUnicode = PR_TRUE;
+ goto recheckUnicodePassword;
+ }
+ }
+ SECITEM_ZfreeItem(mac, PR_TRUE);
+ } else {
+ ret = PR_FALSE;
+ }
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM);
+ ret = PR_FALSE;
+ break;
+ }
+
+ /* let success fall through */
+ if(key != NULL)
+ SECITEM_ZfreeItem(key, PR_TRUE);
+
+ return ret;
+}
+
+/* check the validity of the pfx structure. we currently only support
+ * password integrity mode, so we check the MAC.
+ */
+static PRBool
+sec_pkcs12_validate_pfx(SEC_PKCS12PFXItem *pfx,
+ SECItem *pwitem)
+{
+ SECOidTag contentType;
+
+ contentType = SEC_PKCS7ContentType(&pfx->authSafe);
+ switch(contentType)
+ {
+ case SEC_OID_PKCS7_DATA:
+ return sec_pkcs12_check_pfx_mac(pfx, pwitem);
+ break;
+ case SEC_OID_PKCS7_SIGNED_DATA:
+ default:
+ PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE);
+ break;
+ }
+
+ return PR_FALSE;
+}
+
+/* decode and return the valid PFX. if the PFX item is not valid,
+ * NULL is returned.
+ */
+static SEC_PKCS12PFXItem *
+sec_pkcs12_get_pfx(SECItem *pfx_data,
+ SECItem *pwitem)
+{
+ SEC_PKCS12PFXItem *pfx;
+ PRBool valid_pfx;
+
+ if((pfx_data == NULL) || (pwitem == NULL)) {
+ return NULL;
+ }
+
+ pfx = sec_pkcs12_decode_pfx(pfx_data);
+ if(pfx == NULL) {
+ return NULL;
+ }
+
+ valid_pfx = sec_pkcs12_validate_pfx(pfx, pwitem);
+ if(valid_pfx != PR_TRUE) {
+ SEC_PKCS12DestroyPFX(pfx);
+ pfx = NULL;
+ }
+
+ return pfx;
+}
+
+/* authenticated safe decoding, validation, and access routines
+ */
+
+/* convert dogbert beta 3 authenticated safe structure to a post
+ * beta three structure, so that we don't have to change more routines.
+ */
+static SECStatus
+sec_pkcs12_convert_old_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe)
+{
+ SEC_PKCS12Baggage *baggage;
+ SEC_PKCS12BaggageItem *bag;
+ SECStatus rv = SECSuccess;
+
+ if(asafe->old_baggage.espvks == NULL) {
+ /* XXX should the ASN1 engine produce a single NULL element list
+ * rather than setting the pointer to NULL?
+ * There is no need to return an error -- assume that the list
+ * was empty.
+ */
+ return SECSuccess;
+ }
+
+ baggage = sec_pkcs12_create_baggage(asafe->poolp);
+ if(!baggage) {
+ return SECFailure;
+ }
+ bag = sec_pkcs12_create_external_bag(baggage);
+ if(!bag) {
+ return SECFailure;
+ }
+
+ PORT_Memcpy(&asafe->baggage, baggage, sizeof(SEC_PKCS12Baggage));
+
+ /* if there are shrouded keys, append them to the bag */
+ rv = SECSuccess;
+ if(asafe->old_baggage.espvks[0] != NULL) {
+ int nEspvk = 0;
+ rv = SECSuccess;
+ while((asafe->old_baggage.espvks[nEspvk] != NULL) &&
+ (rv == SECSuccess)) {
+ rv = sec_pkcs12_append_shrouded_key(bag,
+ asafe->old_baggage.espvks[nEspvk]);
+ nEspvk++;
+ }
+ }
+
+ return rv;
+}
+
+/* decodes the authenticated safe item. a return of NULL indicates
+ * an error. however, the error will have occured either in memory
+ * allocation or in decoding the authenticated safe.
+ *
+ * if an old PFX item has been found, we want to convert the
+ * old authenticated safe to the new one.
+ */
+static SEC_PKCS12AuthenticatedSafe *
+sec_pkcs12_decode_authenticated_safe(SEC_PKCS12PFXItem *pfx)
+{
+ SECItem *der_asafe = NULL;
+ SEC_PKCS12AuthenticatedSafe *asafe = NULL;
+ SECStatus rv;
+
+ if(pfx == NULL) {
+ return NULL;
+ }
+
+ der_asafe = SEC_PKCS7GetContent(&pfx->authSafe);
+ if(der_asafe == NULL) {
+ /* XXX set error ? */
+ goto loser;
+ }
+
+ asafe = sec_pkcs12_new_asafe(pfx->poolp);
+ if(asafe == NULL) {
+ goto loser;
+ }
+
+ if(pfx->old == PR_FALSE) {
+ rv = SEC_ASN1DecodeItem(pfx->poolp, asafe,
+ SEC_PKCS12AuthenticatedSafeTemplate,
+ der_asafe);
+ asafe->old = PR_FALSE;
+ asafe->swapUnicode = pfx->swapUnicode;
+ } else {
+ /* handle beta exported files */
+ rv = SEC_ASN1DecodeItem(pfx->poolp, asafe,
+ SEC_PKCS12AuthenticatedSafeTemplate_OLD,
+ der_asafe);
+ asafe->safe = &(asafe->old_safe);
+ rv = sec_pkcs12_convert_old_auth_safe(asafe);
+ asafe->old = PR_TRUE;
+ }
+
+ if(rv != SECSuccess) {
+ goto loser;
+ }
+
+ asafe->poolp = pfx->poolp;
+
+ return asafe;
+
+loser:
+ return NULL;
+}
+
+/* validates the safe within the authenticated safe item.
+ * in order to be valid:
+ * 1. the privacy salt must be present
+ * 2. the encryption algorithm must be supported (including
+ * export policy)
+ * PR_FALSE indicates an error, PR_TRUE indicates a valid safe
+ */
+static PRBool
+sec_pkcs12_validate_encrypted_safe(SEC_PKCS12AuthenticatedSafe *asafe)
+{
+ PRBool valid = PR_FALSE;
+ SECAlgorithmID *algid;
+
+ if(asafe == NULL) {
+ return PR_FALSE;
+ }
+
+ /* if mode is password privacy, then privacySalt is assumed
+ * to be non-zero.
+ */
+ if(asafe->privacySalt.len != 0) {
+ valid = PR_TRUE;
+ asafe->privacySalt.len /= 8;
+ } else {
+ PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE);
+ return PR_FALSE;
+ }
+
+ /* until spec changes, content will have between 2 and 8 bytes depending
+ * upon the algorithm used if certs are unencrypted...
+ * also want to support case where content is empty -- which we produce
+ */
+ if(SEC_PKCS7IsContentEmpty(asafe->safe, 8) == PR_TRUE) {
+ asafe->emptySafe = PR_TRUE;
+ return PR_TRUE;
+ }
+
+ asafe->emptySafe = PR_FALSE;
+
+ /* make sure that a pbe algorithm is being used */
+ algid = SEC_PKCS7GetEncryptionAlgorithm(asafe->safe);
+ if(algid != NULL) {
+ if(SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
+ valid = SEC_PKCS12DecryptionAllowed(algid);
+
+ if(valid == PR_FALSE) {
+ PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM);
+ }
+ } else {
+ PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM);
+ valid = PR_FALSE;
+ }
+ } else {
+ valid = PR_FALSE;
+ PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM);
+ }
+
+ return valid;
+}
+
+/* validates authenticates safe:
+ * 1. checks that the version is supported
+ * 2. checks that only password privacy mode is used (currently)
+ * 3. further, makes sure safe has appropriate policies per above function
+ * PR_FALSE indicates failure.
+ */
+static PRBool
+sec_pkcs12_validate_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe)
+{
+ PRBool valid = PR_TRUE;
+ SECOidTag safe_type;
+ int version;
+
+ if(asafe == NULL) {
+ return PR_FALSE;
+ }
+
+ /* check version, since it is default it may not be present.
+ * therefore, assume ok
+ */
+ if((asafe->version.len > 0) && (asafe->old == PR_FALSE)) {
+ version = DER_GetInteger(&asafe->version);
+ if(version > SEC_PKCS12_PFX_VERSION) {
+ PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION);
+ return PR_FALSE;
+ }
+ }
+
+ /* validate password mode is being used */
+ safe_type = SEC_PKCS7ContentType(asafe->safe);
+ switch(safe_type)
+ {
+ case SEC_OID_PKCS7_ENCRYPTED_DATA:
+ valid = sec_pkcs12_validate_encrypted_safe(asafe);
+ break;
+ case SEC_OID_PKCS7_ENVELOPED_DATA:
+ default:
+ PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE);
+ valid = PR_FALSE;
+ break;
+ }
+
+ return valid;
+}
+
+/* retrieves the authenticated safe item from the PFX item
+ * before returning the authenticated safe, the validity of the
+ * authenticated safe is checked and if valid, returned.
+ * a return of NULL indicates that an error occured.
+ */
+static SEC_PKCS12AuthenticatedSafe *
+sec_pkcs12_get_auth_safe(SEC_PKCS12PFXItem *pfx)
+{
+ SEC_PKCS12AuthenticatedSafe *asafe;
+ PRBool valid_safe;
+
+ if(pfx == NULL) {
+ return NULL;
+ }
+
+ asafe = sec_pkcs12_decode_authenticated_safe(pfx);
+ if(asafe == NULL) {
+ return NULL;
+ }
+
+ valid_safe = sec_pkcs12_validate_auth_safe(asafe);
+ if(valid_safe != PR_TRUE) {
+ asafe = NULL;
+ } else if(asafe) {
+ asafe->baggage.poolp = asafe->poolp;
+ }
+
+ return asafe;
+}
+
+/* decrypts the authenticated safe.
+ * a return of anything but SECSuccess indicates an error. the
+ * password is not known to be valid until the call to the
+ * function sec_pkcs12_get_safe_contents. If decoding the safe
+ * fails, it is assumed the password was incorrect and the error
+ * is set then. any failure here is assumed to be due to
+ * internal problems in SEC_PKCS7DecryptContents or below.
+ */
+static SECStatus
+sec_pkcs12_decrypt_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe,
+ SECItem *pwitem,
+ void *wincx)
+{
+ SECStatus rv = SECFailure;
+ SECItem *vpwd = NULL;
+
+ if((asafe == NULL) || (pwitem == NULL)) {
+ return SECFailure;
+ }
+
+ if(asafe->old == PR_FALSE) {
+ vpwd = sec_pkcs12_create_virtual_password(pwitem, &asafe->privacySalt,
+ asafe->swapUnicode);
+ if(vpwd == NULL) {
+ return SECFailure;
+ }
+ }
+
+ rv = SEC_PKCS7DecryptContents(asafe->poolp, asafe->safe,
+ (asafe->old ? pwitem : vpwd), wincx);
+
+ if(asafe->old == PR_FALSE) {
+ SECITEM_ZfreeItem(vpwd, PR_TRUE);
+ }
+
+ return rv;
+}
+
+/* extract the safe from the authenticated safe.
+ * if we are unable to decode the safe, then it is likely that the
+ * safe has not been decrypted or the password used to decrypt
+ * the safe was invalid. we assume that the password was invalid and
+ * set an error accordingly.
+ * a return of NULL indicates that an error occurred.
+ */
+static SEC_PKCS12SafeContents *
+sec_pkcs12_get_safe_contents(SEC_PKCS12AuthenticatedSafe *asafe)
+{
+ SECItem *src = NULL;
+ SEC_PKCS12SafeContents *safe = NULL;
+ SECStatus rv = SECFailure;
+
+ if(asafe == NULL) {
+ return NULL;
+ }
+
+ safe = (SEC_PKCS12SafeContents *)PORT_ArenaZAlloc(asafe->poolp,
+ sizeof(SEC_PKCS12SafeContents));
+ if(safe == NULL) {
+ return NULL;
+ }
+ safe->poolp = asafe->poolp;
+ safe->old = asafe->old;
+ safe->swapUnicode = asafe->swapUnicode;
+
+ src = SEC_PKCS7GetContent(asafe->safe);
+ if(src != NULL) {
+ const SEC_ASN1Template *theTemplate;
+ if(asafe->old != PR_TRUE) {
+ theTemplate = SEC_PKCS12SafeContentsTemplate;
+ } else {
+ theTemplate = SEC_PKCS12SafeContentsTemplate_OLD;
+ }
+
+ rv = SEC_ASN1DecodeItem(asafe->poolp, safe, theTemplate, src);
+
+ /* if we could not decode the item, password was probably invalid */
+ if(rv != SECSuccess) {
+ safe = NULL;
+ PORT_SetError(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT);
+ }
+ } else {
+ PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE);
+ rv = SECFailure;
+ }
+
+ return safe;
+}
+
+/* import PFX item
+ * der_pfx is the der encoded pfx structure
+ * pbef and pbearg are the integrity/encryption password call back
+ * ncCall is the nickname collision calllback
+ * slot is the destination token
+ * wincx window handler
+ *
+ * on error, error code set and SECFailure returned
+ */
+SECStatus
+SEC_PKCS12PutPFX(SECItem *der_pfx, SECItem *pwitem,
+ SEC_PKCS12NicknameCollisionCallback ncCall,
+ PK11SlotInfo *slot,
+ void *wincx)
+{
+ SEC_PKCS12PFXItem *pfx;
+ SEC_PKCS12AuthenticatedSafe *asafe;
+ SEC_PKCS12SafeContents *safe_contents = NULL;
+ SECStatus rv;
+
+ if(!der_pfx || !pwitem || !slot) {
+ return SECFailure;
+ }
+
+ /* decode and validate each section */
+ rv = SECFailure;
+
+ pfx = sec_pkcs12_get_pfx(der_pfx, pwitem);
+ if(pfx != NULL) {
+ asafe = sec_pkcs12_get_auth_safe(pfx);
+ if(asafe != NULL) {
+
+ /* decrypt safe -- only if not empty */
+ if(asafe->emptySafe != PR_TRUE) {
+ rv = sec_pkcs12_decrypt_auth_safe(asafe, pwitem, wincx);
+ if(rv == SECSuccess) {
+ safe_contents = sec_pkcs12_get_safe_contents(asafe);
+ if(safe_contents == NULL) {
+ rv = SECFailure;
+ }
+ }
+ } else {
+ safe_contents = sec_pkcs12_create_safe_contents(asafe->poolp);
+ safe_contents->swapUnicode = pfx->swapUnicode;
+ if(safe_contents == NULL) {
+ rv = SECFailure;
+ } else {
+ rv = SECSuccess;
+ }
+ }
+
+ /* get safe contents and begin import */
+ if(rv == SECSuccess) {
+ SEC_PKCS12DecoderContext *p12dcx;
+
+ p12dcx = sec_PKCS12ConvertOldSafeToNew(pfx->poolp, slot,
+ pfx->swapUnicode,
+ pwitem, wincx, safe_contents,
+ &asafe->baggage);
+ if(!p12dcx) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ if(SEC_PKCS12DecoderValidateBags(p12dcx, ncCall)
+ != SECSuccess) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ rv = SEC_PKCS12DecoderImportBags(p12dcx);
+ }
+
+ }
+ }
+
+loser:
+
+ if(pfx) {
+ SEC_PKCS12DestroyPFX(pfx);
+ }
+
+ return rv;
+}
+
+PRBool
+SEC_PKCS12ValidData(char *buf, int bufLen, long int totalLength)
+{
+ int lengthLength;
+
+ PRBool valid = PR_FALSE;
+
+ if(buf == NULL) {
+ return PR_FALSE;
+ }
+
+ /* check for constructed sequence identifier tag */
+ if(*buf == (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) {
+ totalLength--; /* header byte taken care of */
+ buf++;
+
+ lengthLength = (long int)SEC_ASN1LengthLength(totalLength - 1);
+ if(totalLength > 0x7f) {
+ lengthLength--;
+ *buf &= 0x7f; /* remove bit 8 indicator */
+ if((*buf - (char)lengthLength) == 0) {
+ valid = PR_TRUE;
+ }
+ } else {
+ lengthLength--;
+ if((*buf - (char)lengthLength) == 0) {
+ valid = PR_TRUE;
+ }
+ }
+ }
+
+ return valid;
+}