summaryrefslogtreecommitdiff
path: root/security/nss/lib/cryptohi
diff options
context:
space:
mode:
authorrelyea%netscape.com <devnull@localhost>2000-03-31 20:13:40 +0000
committerrelyea%netscape.com <devnull@localhost>2000-03-31 20:13:40 +0000
commit9502869e82d4f3ce26b292263e1c626dca3a34f3 (patch)
tree4d0f8ab157505b57c13a5e2bdf979560ab751527 /security/nss/lib/cryptohi
parent222a52dab759085f56dcb6588b69a6a937d82aa2 (diff)
downloadnss-hg-9502869e82d4f3ce26b292263e1c626dca3a34f3.tar.gz
Initial NSS Open Source checkin
Diffstat (limited to 'security/nss/lib/cryptohi')
-rw-r--r--security/nss/lib/cryptohi/Makefile77
-rw-r--r--security/nss/lib/cryptohi/config.mk44
-rw-r--r--security/nss/lib/cryptohi/cryptohi.h236
-rw-r--r--security/nss/lib/cryptohi/cryptoht.h45
-rw-r--r--security/nss/lib/cryptohi/dsautil.c229
-rw-r--r--security/nss/lib/cryptohi/hasht.h87
-rw-r--r--security/nss/lib/cryptohi/key.h44
-rw-r--r--security/nss/lib/cryptohi/keyhi.h211
-rw-r--r--security/nss/lib/cryptohi/keyt.h46
-rw-r--r--security/nss/lib/cryptohi/keythi.h83
-rw-r--r--security/nss/lib/cryptohi/manifest.mn64
-rw-r--r--security/nss/lib/cryptohi/sechash.c274
-rw-r--r--security/nss/lib/cryptohi/sechash.h77
-rw-r--r--security/nss/lib/cryptohi/seckey.c1649
-rw-r--r--security/nss/lib/cryptohi/secsign.c497
-rw-r--r--security/nss/lib/cryptohi/secvfy.c389
16 files changed, 4052 insertions, 0 deletions
diff --git a/security/nss/lib/cryptohi/Makefile b/security/nss/lib/cryptohi/Makefile
new file mode 100644
index 000000000..ced902117
--- /dev/null
+++ b/security/nss/lib/cryptohi/Makefile
@@ -0,0 +1,77 @@
+#! gmake
+#
+# 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 Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+-include config.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+export:: private_export
+
diff --git a/security/nss/lib/cryptohi/config.mk b/security/nss/lib/cryptohi/config.mk
new file mode 100644
index 000000000..a73a1086e
--- /dev/null
+++ b/security/nss/lib/cryptohi/config.mk
@@ -0,0 +1,44 @@
+#
+# 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 Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#
+# Override TARGETS variable so that only static libraries
+# are specifed as dependencies within rules.mk.
+#
+
+TARGETS = $(LIBRARY)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+PURE_LIBRARY =
+PROGRAM =
+
diff --git a/security/nss/lib/cryptohi/cryptohi.h b/security/nss/lib/cryptohi/cryptohi.h
new file mode 100644
index 000000000..07d8057c7
--- /dev/null
+++ b/security/nss/lib/cryptohi/cryptohi.h
@@ -0,0 +1,236 @@
+/*
+ * crypto.h - public data structures and prototypes for the crypto library
+ *
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ * $Id$
+ */
+
+#ifndef _CRYPTOHI_H_
+#define _CRYPTOHI_H_
+
+#include "blapi.h"
+
+#include "mcom_db.h"
+
+#include "seccomon.h"
+#include "secrngt.h"
+#include "secoidt.h"
+#include "secdert.h"
+#include "cryptoht.h"
+#include "keyt.h"
+#include "certt.h"
+
+
+SEC_BEGIN_PROTOS
+
+
+/****************************************/
+/*
+** DER encode/decode DSA signatures
+*/
+
+/* ANSI X9.57 defines DSA signatures as DER encoded data. Our DSA code (and
+ * most of the rest of the world) just generates 40 bytes of raw data. These
+ * functions convert between formats.
+ */
+extern SECStatus DSAU_EncodeDerSig(SECItem *dest, SECItem *src);
+extern SECItem *DSAU_DecodeDerSig(SECItem *item);
+
+
+
+/****************************************/
+/*
+** Signature creation operations
+*/
+
+/*
+** Create a new signature context used for signing a data stream.
+** "alg" the signature algorithm to use (e.g. SEC_OID_RSA_WITH_MD5)
+** "privKey" the private key to use
+*/
+extern SGNContext *SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *privKey);
+
+/*
+** Destroy a signature-context object
+** "key" the object
+** "freeit" if PR_TRUE then free the object as well as its sub-objects
+*/
+extern void SGN_DestroyContext(SGNContext *cx, PRBool freeit);
+
+/*
+** Reset the signing context "cx" to its initial state, preparing it for
+** another stream of data.
+*/
+extern SECStatus SGN_Begin(SGNContext *cx);
+
+/*
+** Update the signing context with more data to sign.
+** "cx" the context
+** "input" the input data to sign
+** "inputLen" the length of the input data
+*/
+extern SECStatus SGN_Update(SGNContext *cx, unsigned char *input,
+ unsigned int inputLen);
+
+/*
+** Finish the signature process. Use either k0 or k1 to sign the data
+** stream that was input using SGN_Update. The resulting signature is
+** formatted using PKCS#1 and then encrypted using RSA private or public
+** encryption.
+** "cx" the context
+** "result" the final signature data (memory is allocated)
+*/
+extern SECStatus SGN_End(SGNContext *cx, SECItem *result);
+
+/*
+** Sign a single block of data using private key encryption and given
+** signature/hash algorithm.
+** "result" the final signature data (memory is allocated)
+** "buf" the input data to sign
+** "len" the amount of data to sign
+** "pk" the private key to encrypt with
+** "algid" the signature/hash algorithm to sign with
+** (must be compatible with the key type).
+*/
+extern SECStatus SEC_SignData(SECItem *result, unsigned char *buf, int len,
+ SECKEYPrivateKey *pk, SECOidTag algid);
+
+/*
+** Sign a pre-digested block of data using private key encryption, encoding
+** The given signature/hash algorithm.
+** "result" the final signature data (memory is allocated)
+** "digest" the digest to sign
+** "pk" the private key to encrypt with
+** "algtag" The algorithm tag to encode (need for RSA only)
+*/
+extern SECStatus SGN_Digest(SECKEYPrivateKey *privKey,
+ SECOidTag algtag, SECItem *result, SECItem *digest);
+
+/*
+** DER sign a single block of data using private key encryption and the
+** MD5 hashing algorithm. This routine first computes a digital signature
+** using SEC_SignData, then wraps it with an CERTSignedData and then der
+** encodes the result.
+** "arena" is the memory arena to use to allocate data from
+** "result" the final der encoded data (memory is allocated)
+** "buf" the input data to sign
+** "len" the amount of data to sign
+** "pk" the private key to encrypt with
+*/
+extern SECStatus SEC_DerSignData(PRArenaPool *arena, SECItem *result,
+ unsigned char *buf, int len,
+ SECKEYPrivateKey *pk, SECOidTag algid);
+
+/*
+** Destroy a signed-data object.
+** "sd" the object
+** "freeit" if PR_TRUE then free the object as well as its sub-objects
+*/
+extern void SEC_DestroySignedData(CERTSignedData *sd, PRBool freeit);
+
+/****************************************/
+/*
+** Signature verification operations
+*/
+
+/*
+** Create a signature verification context.
+** "key" the public key to verify with
+** "sig" the encrypted signature data
+** "algid" specifies the signing algorithm to use. This must match
+** the key type.
+** "wincx" void pointer to the window context
+*/
+extern VFYContext *VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig,
+ SECOidTag algid, void *wincx);
+
+/*
+** Destroy a verification-context object.
+** "cx" the context to destroy
+** "freeit" if PR_TRUE then free the object as well as its sub-objects
+*/
+extern void VFY_DestroyContext(VFYContext *cx, PRBool freeit);
+
+extern SECStatus VFY_Begin(VFYContext *cx);
+
+/*
+** Update a verification context with more input data. The input data
+** is fed to a secure hash function (depending on what was in the
+** encrypted signature data).
+** "cx" the context
+** "input" the input data
+** "inputLen" the amount of input data
+*/
+extern SECStatus VFY_Update(VFYContext *cx, unsigned char *input,
+ unsigned int inputLen);
+
+/*
+** Finish the verification process. The return value is a status which
+** indicates success or failure. On success, the SECSuccess value is
+** returned. Otherwise, SECFailure is returned and the error code found
+** using PORT_GetError() indicates what failure occurred.
+** "cx" the context
+*/
+extern SECStatus VFY_End(VFYContext *cx);
+
+/*
+** Verify the signature on a block of data for which we already have
+** the digest. The signature data is an RSA private key encrypted
+** block of data formatted according to PKCS#1.
+** "dig" the digest
+** "key" the public key to check the signature with
+** "sig" the encrypted signature data
+** "algid" specifies the signing algorithm to use. This must match
+** the key type.
+**/
+extern SECStatus VFY_VerifyDigest(SECItem *dig, SECKEYPublicKey *key,
+ SECItem *sig, SECOidTag algid, void *wincx);
+
+/*
+** Verify the signature on a block of data. The signature data is an RSA
+** private key encrypted block of data formatted according to PKCS#1.
+** "buf" the input data
+** "len" the length of the input data
+** "key" the public key to check the signature with
+** "sig" the encrypted signature data
+** "algid" specifies the signing algorithm to use. This must match
+** the key type.
+*/
+extern SECStatus VFY_VerifyData(unsigned char *buf, int len,
+ SECKEYPublicKey *key, SECItem *sig,
+ SECOidTag algid, void *wincx);
+
+
+SEC_END_PROTOS
+
+#endif /* _CRYPTOHI_H_ */
diff --git a/security/nss/lib/cryptohi/cryptoht.h b/security/nss/lib/cryptohi/cryptoht.h
new file mode 100644
index 000000000..3116db279
--- /dev/null
+++ b/security/nss/lib/cryptohi/cryptoht.h
@@ -0,0 +1,45 @@
+/*
+ * cryptoht.h - public data structures for the crypto library
+ *
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ * $Id$
+ */
+
+#ifndef _CRYPTOHT_H_
+#define _CRYPTOHT_H_
+
+typedef struct SGNContextStr SGNContext;
+typedef struct VFYContextStr VFYContext;
+
+
+#endif /* _CRYPTOHT_H_ */
diff --git a/security/nss/lib/cryptohi/dsautil.c b/security/nss/lib/cryptohi/dsautil.c
new file mode 100644
index 000000000..ed6f9cec8
--- /dev/null
+++ b/security/nss/lib/cryptohi/dsautil.c
@@ -0,0 +1,229 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#include "secasn1.h"
+#include "secitem.h"
+#include "prerr.h"
+
+#ifndef DSA_SUBPRIME_LEN
+#define DSA_SUBPRIME_LEN 20 /* bytes */
+#endif
+
+typedef struct {
+ SECItem r;
+ SECItem s;
+} DSA_ASN1Signature;
+
+const SEC_ASN1Template DSA_SignatureTemplate[] =
+{
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(DSA_ASN1Signature) },
+ { SEC_ASN1_INTEGER, offsetof(DSA_ASN1Signature,r) },
+ { SEC_ASN1_INTEGER, offsetof(DSA_ASN1Signature,s) },
+ { 0, }
+};
+
+/* Input is variable length multi-byte integer, MSB first (big endian).
+** Most signficant bit of first byte is NOT treated as a sign bit.
+** May be one or more leading bytes of zeros.
+** Output is variable length multi-byte integer, MSB first (big endian).
+** Most significant bit of first byte will be zero (positive sign bit)
+** No more than one leading zero byte.
+** Caller supplies dest buffer, and assures that it is long enough,
+** e.g. at least one byte longer that src's buffer.
+*/
+void
+DSAU_ConvertUnsignedToSigned(SECItem *dest, SECItem *src)
+{
+ unsigned char *pSrc = src->data;
+ unsigned char *pDst = dest->data;
+ unsigned int cntSrc = src->len;
+ unsigned int cntDst = dest->len;
+ unsigned char c;
+
+ /* skip any leading zeros. */
+ while (cntSrc && !(c = *pSrc)) {
+ pSrc++;
+ cntSrc--;
+ }
+ if (!cntSrc) {
+ *pDst = 0;
+ dest->len = 1;
+ return;
+ }
+
+ if (c & 0x80)
+ *pDst++ = 0;
+
+ PORT_Memcpy(pDst, pSrc, cntSrc);
+ dest->len = (pDst - dest->data) + cntSrc;
+}
+
+/*
+** src is a buffer holding a signed variable length integer.
+** dest is a buffer which will be filled with an unsigned integer,
+** MSB first (big endian) with leading zeros, so that the last byte
+** of src will be the LSB of the integer. The result will be exactly
+** the length specified by the caller in dest->len.
+** src can be shorter than dest. src can be longer than dst, but only
+** if the extra leading bytes are zeros.
+*/
+SECStatus
+DSAU_ConvertSignedToFixedUnsigned(SECItem *dest, SECItem *src)
+{
+ unsigned char *pSrc = src->data;
+ unsigned char *pDst = dest->data;
+ unsigned int cntSrc = src->len;
+ unsigned int cntDst = dest->len;
+ int zCount = cntDst - cntSrc;
+
+ if (zCount > 0) {
+ PORT_Memset(pDst, 0, zCount);
+ PORT_Memcpy(pDst + zCount, pSrc, cntSrc);
+ return SECSuccess;
+ }
+ if (zCount <= 0) {
+ /* Source is longer than destination. Check for leading zeros. */
+ while (zCount++ < 0) {
+ if (*pSrc++ != 0)
+ goto loser;
+ }
+ }
+ PORT_Memcpy(pDst, pSrc, cntDst);
+ return SECSuccess;
+
+loser:
+ PORT_SetError( PR_INVALID_ARGUMENT_ERROR );
+ return SECFailure;
+}
+
+/* src is a "raw" DSA signature, 20 bytes of r followed by 20 bytes of s.
+** dest is the signature DER encoded. ?
+*/
+SECStatus
+DSAU_EncodeDerSig(SECItem *dest, SECItem *src)
+{
+ SECItem * item;
+ SECItem srcItem;
+ DSA_ASN1Signature sig;
+ unsigned char signedR[DSA_SUBPRIME_LEN + 1];
+ unsigned char signedS[DSA_SUBPRIME_LEN + 1];
+
+ PORT_Memset(&sig, 0, sizeof(sig));
+
+ PORT_Assert(src->len == 2 * DSA_SUBPRIME_LEN);
+ if (src->len != 2 * DSA_SUBPRIME_LEN) {
+ PORT_SetError( PR_INVALID_ARGUMENT_ERROR );
+ return SECFailure;
+ }
+
+ /* Must convert r and s from "unsigned" integers to "signed" integers.
+ ** If the high order bit of the first byte (MSB) is 1, then must
+ ** prepend with leading zero.
+ ** Must remove all but one leading zero byte from numbers.
+ */
+ sig.r.data = signedR;
+ sig.r.len = sizeof signedR;
+ sig.s.data = signedS;
+ sig.s.len = sizeof signedR;
+
+ srcItem.data = src->data;
+ srcItem.len = DSA_SUBPRIME_LEN;
+
+ DSAU_ConvertUnsignedToSigned(&sig.r, &srcItem);
+ srcItem.data += DSA_SUBPRIME_LEN;
+ DSAU_ConvertUnsignedToSigned(&sig.s, &srcItem);
+
+ item = SEC_ASN1EncodeItem(NULL, dest, &sig, DSA_SignatureTemplate);
+ if (item == NULL)
+ return SECFailure;
+
+ /* XXX leak item? */
+ return SECSuccess;
+}
+
+/* src is a DER-encoded DSA signature.
+** Returns a newly-allocated SECItem structure, pointing at a newly allocated
+** buffer containing the "raw" DSA signature, which is 20 bytes of r,
+** followed by 20 bytes of s.
+*/
+SECItem *
+DSAU_DecodeDerSig(SECItem *item)
+{
+ SECItem * result = NULL;
+ SECStatus status;
+ DSA_ASN1Signature sig;
+ SECItem dst;
+
+ PORT_Memset(&sig, 0, sizeof(sig));
+
+ result = PORT_ZNew(SECItem);
+ if (result == NULL)
+ goto loser;
+
+ result->len = 2 * DSA_SUBPRIME_LEN;
+ result->data = (unsigned char*)PORT_Alloc(2 * DSA_SUBPRIME_LEN);
+ if (result->data == NULL)
+ goto loser;
+
+ status = SEC_ASN1DecodeItem(NULL, &sig, DSA_SignatureTemplate, item);
+ if (status != SECSuccess)
+ goto loser;
+
+ /* Convert sig.r and sig.s from variable length signed integers to
+ ** fixed length unsigned integers.
+ */
+ dst.data = result->data;
+ dst.len = DSA_SUBPRIME_LEN;
+ status = DSAU_ConvertSignedToFixedUnsigned(&dst, &sig.r);
+ if (status != SECSuccess)
+ goto loser;
+
+ dst.data += DSA_SUBPRIME_LEN;
+ status = DSAU_ConvertSignedToFixedUnsigned(&dst, &sig.s);
+ if (status != SECSuccess)
+ goto loser;
+
+done:
+ if (sig.r.data != NULL)
+ PORT_Free(sig.r.data);
+ if (sig.s.data != NULL)
+ PORT_Free(sig.s.data);
+
+ return result;
+
+loser:
+ if (result != NULL) {
+ SECITEM_FreeItem(result, PR_TRUE);
+ result = NULL;
+ }
+ goto done;
+}
diff --git a/security/nss/lib/cryptohi/hasht.h b/security/nss/lib/cryptohi/hasht.h
new file mode 100644
index 000000000..697520015
--- /dev/null
+++ b/security/nss/lib/cryptohi/hasht.h
@@ -0,0 +1,87 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ * hasht.h - public data structures for the hashing library
+ *
+ * $Id$
+ */
+
+#ifndef _HASHT_H_
+#define _HASHT_H_
+
+/* Opaque objects */
+typedef struct SECHashObjectStr SECHashObject;
+typedef struct HASHContextStr HASHContext;
+
+/*
+ * The hash functions the security library supports
+ * NOTE the order must match the definition of SECHashObjects[]!
+ */
+typedef enum {
+ HASH_AlgNULL,
+ HASH_AlgMD2,
+ HASH_AlgMD5,
+ HASH_AlgSHA1,
+ HASH_AlgTOTAL
+} HASH_HashType;
+
+/*
+ * Number of bytes each hash algorithm produces
+ */
+#define MD2_LENGTH 16
+#define MD5_LENGTH 16
+#define SHA1_LENGTH 20
+
+/*
+ * Structure to hold hash computation info and routines
+ */
+struct SECHashObjectStr {
+ unsigned int length;
+ void * (*create)(void);
+ void * (*clone)(void *);
+ void (*destroy)(void *, PRBool);
+ void (*begin)(void *);
+ void (*update)(void *, const unsigned char *, unsigned int);
+ void (*end)(void *, unsigned char *, unsigned int *, unsigned int);
+};
+
+struct HASHContextStr {
+ struct SECHashObjectStr *hashobj;
+ void *hash_context;
+};
+
+extern SECHashObject SECHashObjects[];
+
+/*only those functions below the PKCS #11 line should use SECRawHashObjects*/
+extern SECHashObject SECRawHashObjects[];
+
+#endif /* _HASHT_H_ */
diff --git a/security/nss/lib/cryptohi/key.h b/security/nss/lib/cryptohi/key.h
new file mode 100644
index 000000000..7e68cdb58
--- /dev/null
+++ b/security/nss/lib/cryptohi/key.h
@@ -0,0 +1,44 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ * key.h - public data structures and prototypes for the private key library
+ *
+ * $Id$
+ */
+
+#ifndef _KEY_H_
+#define _KEY_H_
+
+#include "keyhi.h"
+#include "keylow.h"
+
+#endif /* _KEY_H_ */
diff --git a/security/nss/lib/cryptohi/keyhi.h b/security/nss/lib/cryptohi/keyhi.h
new file mode 100644
index 000000000..6c1a70546
--- /dev/null
+++ b/security/nss/lib/cryptohi/keyhi.h
@@ -0,0 +1,211 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ * key.h - public data structures and prototypes for the private key library
+ *
+ * $Id$
+ */
+
+#ifndef _KEYHI_H_
+#define _KEYHI_H_
+
+#include "plarena.h"
+
+#include "seccomon.h"
+#include "secoidt.h"
+#include "secdert.h"
+#include "keythi.h"
+#include "certt.h"
+#include "secpkcs5.h"
+
+SEC_BEGIN_PROTOS
+
+
+/*
+** Destroy a subject-public-key-info object.
+*/
+extern void SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki);
+
+/*
+** Copy subject-public-key-info "src" to "dst". "dst" is filled in
+** appropriately (memory is allocated for each of the sub objects).
+*/
+extern SECStatus SECKEY_CopySubjectPublicKeyInfo(PRArenaPool *arena,
+ CERTSubjectPublicKeyInfo *dst,
+ CERTSubjectPublicKeyInfo *src);
+
+/*
+** Update the PQG parameters for a cert's public key.
+** Only done for DSA and Fortezza certs
+*/
+extern SECStatus
+SECKEY_UpdateCertPQG(CERTCertificate * subjectCert);
+
+
+/* Compare the KEA parameters of two public keys.
+ * Only used by fortezza. */
+
+extern SECStatus
+SECKEY_KEAParamCompare(CERTCertificate *cert1,CERTCertificate *cert2);
+
+/*
+** Return the strength of the public key
+*/
+extern unsigned SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk);
+
+
+/*
+** Make a copy of the private key "privKey"
+*/
+extern SECKEYPrivateKey *SECKEY_CopyPrivateKey(SECKEYPrivateKey *privKey);
+
+/*
+** Make a copy of the public key "pubKey"
+*/
+extern SECKEYPublicKey *SECKEY_CopyPublicKey(SECKEYPublicKey *pubKey);
+
+/*
+** Convert a private key "privateKey" into a public key
+*/
+extern SECKEYPublicKey *SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privateKey);
+
+/*
+ * create a new RSA key pair. The public Key is returned...
+ */
+SECKEYPrivateKey *SECKEY_CreateRSAPrivateKey(int keySizeInBits,
+ SECKEYPublicKey **pubk, void *cx);
+/*
+** Create a subject-public-key-info based on a public key.
+*/
+extern CERTSubjectPublicKeyInfo *
+SECKEY_CreateSubjectPublicKeyInfo(SECKEYPublicKey *k);
+
+/*
+** Decode a DER encoded public key into an SECKEYPublicKey structure.
+*/
+extern SECKEYPublicKey *SECKEY_DecodeDERPublicKey(SECItem *pubkder);
+
+/*
+** Convert a base64 ascii encoded DER public key to our internal format.
+*/
+extern SECKEYPublicKey *SECKEY_ConvertAndDecodePublicKey(char *pubkstr);
+
+/*
+** Convert a base64 ascii encoded DER public key and challenge to spki,
+** and verify the signature and challenge data are correct
+*/
+extern CERTSubjectPublicKeyInfo *
+SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge,
+ void *cx);
+
+/*
+** Decode a DER encoded subject public key info into a
+** CERTSubjectPublicKeyInfo structure.
+*/
+extern CERTSubjectPublicKeyInfo *
+SECKEY_DecodeDERSubjectPublicKeyInfo(SECItem *spkider);
+
+/*
+** Convert a base64 ascii encoded DER subject public key info to our
+** internal format.
+*/
+extern CERTSubjectPublicKeyInfo *
+SECKEY_ConvertAndDecodeSubjectPublicKeyInfo(char *spkistr);
+
+/*
+** Destroy a private key object.
+** "key" the object
+*/
+extern void SECKEY_DestroyPrivateKey(SECKEYPrivateKey *key);
+
+/*
+** Destroy a public key object.
+** "key" the object
+*/
+extern void SECKEY_DestroyPublicKey(SECKEYPublicKey *key);
+
+/* Destroy and zero out a private key info structure. for now this
+ * function zero's out memory allocated in an arena for the key
+ * since PORT_FreeArena does not currently do this.
+ *
+ * NOTE -- If a private key info is allocated in an arena, one should
+ * not call this function with freeit = PR_FALSE. The function should
+ * destroy the arena.
+ */
+extern void
+SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk, PRBool freeit);
+
+/* Destroy and zero out an encrypted private key info.
+ *
+ * NOTE -- If a encrypted private key info is allocated in an arena, one should
+ * not call this function with freeit = PR_FALSE. The function should
+ * destroy the arena.
+ */
+extern void
+SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki,
+ PRBool freeit);
+
+/* Copy private key info structure.
+ * poolp is the arena into which the contents of from is to be copied.
+ * NULL is a valid entry.
+ * to is the destination private key info
+ * from is the source private key info
+ * if either from or to is NULL or an error occurs, SECFailure is
+ * returned. otherwise, SECSuccess is returned.
+ */
+extern SECStatus
+SECKEY_CopyPrivateKeyInfo(PRArenaPool *poolp,
+ SECKEYPrivateKeyInfo *to,
+ SECKEYPrivateKeyInfo *from);
+
+/* Copy encrypted private key info structure.
+ * poolp is the arena into which the contents of from is to be copied.
+ * NULL is a valid entry.
+ * to is the destination encrypted private key info
+ * from is the source encrypted private key info
+ * if either from or to is NULL or an error occurs, SECFailure is
+ * returned. otherwise, SECSuccess is returned.
+ */
+extern SECStatus
+SECKEY_CopyEncryptedPrivateKeyInfo(PRArenaPool *poolp,
+ SECKEYEncryptedPrivateKeyInfo *to,
+ SECKEYEncryptedPrivateKeyInfo *from);
+/*
+ * Accessor functions for key type of public and private keys.
+ */
+KeyType SECKEY_GetPrivateKeyType(SECKEYPrivateKey *privKey);
+KeyType SECKEY_GetPublicKeyType(SECKEYPublicKey *pubKey);
+
+
+SEC_END_PROTOS
+
+#endif /* _KEYHI_H_ */
diff --git a/security/nss/lib/cryptohi/keyt.h b/security/nss/lib/cryptohi/keyt.h
new file mode 100644
index 000000000..f102c8a26
--- /dev/null
+++ b/security/nss/lib/cryptohi/keyt.h
@@ -0,0 +1,46 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ * keyt.h - public data structures for the private key library
+ *
+ * $Id$
+ */
+
+#ifndef _KEYT_H_
+#define _KEYT_H_
+
+#include "keytlow.h"
+#include "keytboth.h"
+#include "keythi.h"
+#include "keydbt.h"
+
+#endif /* _KEYT_H_ */
diff --git a/security/nss/lib/cryptohi/keythi.h b/security/nss/lib/cryptohi/keythi.h
new file mode 100644
index 000000000..ba1aec401
--- /dev/null
+++ b/security/nss/lib/cryptohi/keythi.h
@@ -0,0 +1,83 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#ifndef _KEYTHI_H_
+#define _KEYTHI_H_ 1
+
+#include "keytlow.h"
+#include "keytboth.h"
+#include "plarena.h"
+#include "pkcs11t.h"
+#include "secmodt.h"
+
+/*
+** A Generic public key object.
+*/
+struct SECKEYPublicKeyStr {
+ PLArenaPool *arena;
+ KeyType keyType;
+ PK11SlotInfo *pkcs11Slot;
+ CK_OBJECT_HANDLE pkcs11ID;
+ union {
+ RSAPublicKey rsa;
+ DSAPublicKey dsa;
+ DHPublicKey dh;
+ KEAPublicKey kea;
+ FortezzaPublicKey fortezza;
+ } u;
+};
+typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
+
+/*
+** A generic key structure
+*/
+struct SECKEYPrivateKeyStr {
+ PLArenaPool *arena;
+ KeyType keyType;
+ PK11SlotInfo *pkcs11Slot; /* pkcs11 slot this key lives in */
+ CK_OBJECT_HANDLE pkcs11ID; /* ID of pkcs11 object */
+ PRBool pkcs11IsTemp; /* temp pkcs11 object, delete it when done */
+ void *wincx; /* context for errors and pw prompts */
+};
+typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey;
+
+/* Despite the name, this struct isn't used by any pkcs5 code.
+** It's used by pkcs7 and pkcs12 code.
+*/
+typedef struct {
+ SECItem *pwitem;
+ PK11SymKey *key;
+ PK11SlotInfo *slot;
+ void *wincx;
+} SEC_PKCS5KeyAndPassword;
+
+#endif /* _KEYTHI_H_ */
diff --git a/security/nss/lib/cryptohi/manifest.mn b/security/nss/lib/cryptohi/manifest.mn
new file mode 100644
index 000000000..a4a76a7df
--- /dev/null
+++ b/security/nss/lib/cryptohi/manifest.mn
@@ -0,0 +1,64 @@
+#
+# 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 Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+CORE_DEPTH = ../../..
+
+MODULE = security
+
+REQUIRES = dbm
+
+LIBRARY_NAME = cryptohi
+
+EXPORTS = \
+ cryptohi.h \
+ cryptoht.h \
+ hasht.h \
+ key.h \
+ keyhi.h \
+ keyt.h \
+ keythi.h \
+ sechash.h \
+ $(NULL)
+
+PRIVATE_EXPORTS = \
+ $(NULL)
+
+LIBSRCS = \
+ sechash.c \
+ seckey.c \
+ secsign.c \
+ secvfy.c \
+ dsautil.c \
+ $(NULL)
+
+CSRCS = $(LIBSRCS)
+
diff --git a/security/nss/lib/cryptohi/sechash.c b/security/nss/lib/cryptohi/sechash.c
new file mode 100644
index 000000000..94000f543
--- /dev/null
+++ b/security/nss/lib/cryptohi/sechash.c
@@ -0,0 +1,274 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#include "sechash.h"
+#include "secoidt.h"
+#include "blapi.h"
+#include "pk11func.h" /* for the PK11_ calls below. */
+
+static void *
+null_hash_new_context(void)
+{
+ return NULL;
+}
+
+static void *
+null_hash_clone_context(void *v)
+{
+ PORT_Assert(v == NULL);
+ return NULL;
+}
+
+static void
+null_hash_begin(void *v)
+{
+}
+
+static void
+null_hash_update(void *v, const unsigned char *input, unsigned int length)
+{
+}
+
+static void
+null_hash_end(void *v, unsigned char *output, unsigned int *outLen,
+ unsigned int maxOut)
+{
+ *outLen = 0;
+}
+
+static void
+null_hash_destroy_context(void *v, PRBool b)
+{
+ PORT_Assert(v == NULL);
+}
+
+
+static void *
+md2_NewContext(void) {
+ return (void *) PK11_CreateDigestContext(SEC_OID_MD2);
+}
+
+static void *
+md5_NewContext(void) {
+ return (void *) PK11_CreateDigestContext(SEC_OID_MD5);
+}
+
+static void *
+sha1_NewContext(void) {
+ return (void *) PK11_CreateDigestContext(SEC_OID_SHA1);
+}
+
+SECHashObject SECHashObjects[] = {
+ { 0,
+ (void * (*)(void)) null_hash_new_context,
+ (void * (*)(void *)) null_hash_clone_context,
+ (void (*)(void *, PRBool)) null_hash_destroy_context,
+ (void (*)(void *)) null_hash_begin,
+ (void (*)(void *, const unsigned char *, unsigned int)) null_hash_update,
+ (void (*)(void *, unsigned char *, unsigned int *,
+ unsigned int)) null_hash_end
+ },
+ { MD2_LENGTH,
+ (void * (*)(void)) md2_NewContext,
+ (void * (*)(void *)) PK11_CloneContext,
+ (void (*)(void *, PRBool)) PK11_DestroyContext,
+ (void (*)(void *)) PK11_DigestBegin,
+ (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp,
+ (void (*)(void *, unsigned char *, unsigned int *, unsigned int))
+ PK11_DigestFinal
+ },
+ { MD5_LENGTH,
+ (void * (*)(void)) md5_NewContext,
+ (void * (*)(void *)) PK11_CloneContext,
+ (void (*)(void *, PRBool)) PK11_DestroyContext,
+ (void (*)(void *)) PK11_DigestBegin,
+ (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp,
+ (void (*)(void *, unsigned char *, unsigned int *, unsigned int))
+ PK11_DigestFinal
+ },
+ { SHA1_LENGTH,
+ (void * (*)(void)) sha1_NewContext,
+ (void * (*)(void *)) PK11_CloneContext,
+ (void (*)(void *, PRBool)) PK11_DestroyContext,
+ (void (*)(void *)) PK11_DigestBegin,
+ (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp,
+ (void (*)(void *, unsigned char *, unsigned int *, unsigned int))
+ PK11_DigestFinal
+ },
+};
+
+unsigned int
+HASH_ResultLen(HASH_HashType type)
+{
+ if ( ( type < HASH_AlgNULL ) || ( type >= HASH_AlgTOTAL ) ) {
+ return(0);
+ }
+
+ return(SECHashObjects[type].length);
+}
+
+unsigned int
+HASH_ResultLenContext(HASHContext *context)
+{
+ return(context->hashobj->length);
+}
+
+
+
+SECStatus
+HASH_HashBuf(HASH_HashType type,
+ unsigned char *dest,
+ unsigned char *src,
+ uint32 src_len)
+{
+ HASHContext *cx;
+ unsigned int part;
+
+ if ( ( type < HASH_AlgNULL ) || ( type >= HASH_AlgTOTAL ) ) {
+ return(SECFailure);
+ }
+
+ cx = HASH_Create(type);
+ if ( cx == NULL ) {
+ return(SECFailure);
+ }
+ HASH_Begin(cx);
+ HASH_Update(cx, src, src_len);
+ HASH_End(cx, dest, &part, HASH_ResultLenContext(cx));
+ HASH_Destroy(cx);
+
+ return(SECSuccess);
+}
+
+HASHContext *
+HASH_Create(HASH_HashType type)
+{
+ void *hash_context = NULL;
+ HASHContext *ret = NULL;
+
+ if ( ( type < HASH_AlgNULL ) || ( type >= HASH_AlgTOTAL ) ) {
+ return(NULL);
+ }
+
+ hash_context = (* SECHashObjects[type].create)();
+ if ( hash_context == NULL ) {
+ goto loser;
+ }
+
+ ret = (HASHContext *)PORT_Alloc(sizeof(HASHContext));
+ if ( ret == NULL ) {
+ goto loser;
+ }
+
+ ret->hash_context = hash_context;
+ ret->hashobj = &SECHashObjects[type];
+
+ return(ret);
+
+loser:
+ if ( hash_context != NULL ) {
+ (* SECHashObjects[type].destroy)(hash_context, PR_TRUE);
+ }
+
+ return(NULL);
+}
+
+
+HASHContext *
+HASH_Clone(HASHContext *context)
+{
+ void *hash_context = NULL;
+ HASHContext *ret = NULL;
+
+ hash_context = (* context->hashobj->clone)(context->hash_context);
+ if ( hash_context == NULL ) {
+ goto loser;
+ }
+
+ ret = (HASHContext *)PORT_Alloc(sizeof(HASHContext));
+ if ( ret == NULL ) {
+ goto loser;
+ }
+
+ ret->hash_context = hash_context;
+ ret->hashobj = context->hashobj;
+
+ return(ret);
+
+loser:
+ if ( hash_context != NULL ) {
+ (* context->hashobj->destroy)(hash_context, PR_TRUE);
+ }
+
+ return(NULL);
+
+}
+
+void
+HASH_Destroy(HASHContext *context)
+{
+ (* context->hashobj->destroy)(context->hash_context, PR_TRUE);
+ PORT_Free(context);
+ return;
+}
+
+
+void
+HASH_Begin(HASHContext *context)
+{
+ (* context->hashobj->begin)(context->hash_context);
+ return;
+}
+
+
+void
+HASH_Update(HASHContext *context,
+ const unsigned char *src,
+ unsigned int len)
+{
+ (* context->hashobj->update)(context->hash_context, src, len);
+ return;
+}
+
+void
+HASH_End(HASHContext *context,
+ unsigned char *result,
+ unsigned int *result_len,
+ unsigned int max_result_len)
+{
+ (* context->hashobj->end)(context->hash_context, result, result_len,
+ max_result_len);
+ return;
+}
+
+
+
diff --git a/security/nss/lib/cryptohi/sechash.h b/security/nss/lib/cryptohi/sechash.h
new file mode 100644
index 000000000..6a4fb3e40
--- /dev/null
+++ b/security/nss/lib/cryptohi/sechash.h
@@ -0,0 +1,77 @@
+#ifndef _HASH_H_
+#define _HASH_H_
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ * hash.h - public data structures and prototypes for the hashing library
+ *
+ * $Id$
+ */
+
+#include "seccomon.h"
+#include "hasht.h"
+
+SEC_BEGIN_PROTOS
+
+/*
+** Generic hash api.
+*/
+
+extern unsigned int HASH_ResultLen(HASH_HashType type);
+
+extern unsigned int HASH_ResultLenContext(HASHContext *context);
+
+extern SECStatus HASH_HashBuf(HASH_HashType type,
+ unsigned char *dest,
+ unsigned char *src,
+ uint32 src_len);
+
+extern HASHContext * HASH_Create(HASH_HashType type);
+
+extern HASHContext * HASH_Clone(HASHContext *context);
+
+extern void HASH_Destroy(HASHContext *context);
+
+extern void HASH_Begin(HASHContext *context);
+
+extern void HASH_Update(HASHContext *context,
+ const unsigned char *src,
+ unsigned int len);
+
+extern void HASH_End(HASHContext *context,
+ unsigned char *result,
+ unsigned int *result_len,
+ unsigned int max_result_len);
+
+SEC_END_PROTOS
+
+#endif /* _HASH_H_ */
diff --git a/security/nss/lib/cryptohi/seckey.c b/security/nss/lib/cryptohi/seckey.c
new file mode 100644
index 000000000..4e1ba6734
--- /dev/null
+++ b/security/nss/lib/cryptohi/seckey.c
@@ -0,0 +1,1649 @@
+/*
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#include "cryptohi.h"
+#include "keyhi.h"
+#include "secrng.h"
+#include "secoid.h"
+#include "secitem.h"
+#include "secder.h"
+#include "base64.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "pk11func.h"
+#include "secerr.h"
+#include "secdig.h"
+#include "prtime.h"
+
+const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTSubjectPublicKeyInfo) },
+ { SEC_ASN1_INLINE,
+ offsetof(CERTSubjectPublicKeyInfo,algorithm),
+ SECOID_AlgorithmIDTemplate },
+ { SEC_ASN1_BIT_STRING,
+ offsetof(CERTSubjectPublicKeyInfo,subjectPublicKey), },
+ { 0, }
+};
+
+const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[] =
+{
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) },
+ { SEC_ASN1_ANY, offsetof(CERTPublicKeyAndChallenge,spki) },
+ { SEC_ASN1_IA5_STRING, offsetof(CERTPublicKeyAndChallenge,challenge) },
+ { 0 }
+};
+
+const SEC_ASN1Template SECKEY_RSAPublicKeyTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.modulus), },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.rsa.publicExponent), },
+ { 0, }
+};
+
+const SEC_ASN1Template SECKEY_DSAPublicKeyTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dsa.publicValue), },
+ { 0, }
+};
+
+const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
+ { SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },
+ { SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) },
+ { SEC_ASN1_INTEGER, offsetof(PQGParams,base) },
+ { 0, }
+};
+
+const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.publicValue), },
+ { 0, }
+};
+
+const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.prime), },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.dh.base), },
+ { 0, }
+};
+
+const SEC_ASN1Template SECKEY_FortezzaParameterTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
+ { SEC_ASN1_OCTET_STRING, offsetof(PQGParams,prime), },
+ { SEC_ASN1_OCTET_STRING, offsetof(PQGParams,subPrime), },
+ { SEC_ASN1_OCTET_STRING, offsetof(PQGParams,base), },
+ { 0 },
+};
+
+const SEC_ASN1Template SECKEY_FortezzaDiffParameterTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(DiffPQGParams) },
+ { SEC_ASN1_INLINE, offsetof(DiffPQGParams,DiffKEAParams),
+ SECKEY_FortezzaParameterTemplate},
+ { SEC_ASN1_INLINE, offsetof(DiffPQGParams,DiffDSAParams),
+ SECKEY_FortezzaParameterTemplate},
+ { 0 },
+};
+
+const SEC_ASN1Template SECKEY_FortezzaPreParamTemplate[] = {
+ { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
+ SEC_ASN1_CONTEXT_SPECIFIC | 1, offsetof(PQGDualParams,CommParams),
+ SECKEY_FortezzaParameterTemplate},
+ { 0, }
+};
+
+const SEC_ASN1Template SECKEY_FortezzaAltPreParamTemplate[] = {
+ { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
+ SEC_ASN1_CONTEXT_SPECIFIC | 0, offsetof(PQGDualParams,DiffParams),
+ SECKEY_FortezzaDiffParameterTemplate},
+ { 0, }
+};
+
+const SEC_ASN1Template SECKEY_KEAPublicKeyTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey,u.kea.publicValue), },
+ { 0, }
+};
+
+const SEC_ASN1Template SECKEY_KEAParamsTemplate[] = {
+ { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPublicKey,u.kea.params.hash), },
+ { 0, }
+};
+
+
+/*
+ * NOTE: This only generates RSA Private Key's. If you need more,
+ * We need to pass in some more params...
+ */
+SECKEYPrivateKey *
+SECKEY_CreateRSAPrivateKey(int keySizeInBits,SECKEYPublicKey **pubk, void *cx)
+{
+ SECKEYPrivateKey *privk;
+ PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN,cx);
+ PK11RSAGenParams param;
+
+ param.keySizeInBits = keySizeInBits;
+ param.pe = 65537L;
+
+ privk = PK11_GenerateKeyPair(slot,CKM_RSA_PKCS_KEY_PAIR_GEN,&param,pubk,
+ PR_FALSE, PR_TRUE, cx);
+ PK11_FreeSlot(slot);
+ return(privk);
+}
+
+void
+SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk)
+{
+ if (privk) {
+ if (privk->pkcs11Slot) {
+ if (privk->pkcs11IsTemp) {
+ PK11_DestroyObject(privk->pkcs11Slot,privk->pkcs11ID);
+ }
+ PK11_FreeSlot(privk->pkcs11Slot);
+
+ }
+ if (privk->arena) {
+ PORT_FreeArena(privk->arena, PR_TRUE);
+ }
+ }
+}
+
+void
+SECKEY_DestroyPublicKey(SECKEYPublicKey *pubk)
+{
+ if (pubk) {
+ if (pubk->pkcs11Slot) {
+ PK11_DestroyObject(pubk->pkcs11Slot,pubk->pkcs11ID);
+ PK11_FreeSlot(pubk->pkcs11Slot);
+ }
+ if (pubk->arena) {
+ PORT_FreeArena(pubk->arena, PR_FALSE);
+ }
+ }
+}
+
+SECStatus
+SECKEY_CopySubjectPublicKeyInfo(PRArenaPool *arena,
+ CERTSubjectPublicKeyInfo *to,
+ CERTSubjectPublicKeyInfo *from)
+{
+ SECStatus rv;
+
+ rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm);
+ if (rv == SECSuccess)
+ rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &from->subjectPublicKey);
+
+ return rv;
+}
+
+SECStatus
+SECKEY_KEASetParams(KEAParams * params, SECKEYPublicKey * pubKey) {
+
+ if (pubKey->keyType == fortezzaKey) {
+ /* the key is a fortezza V1 public key */
+
+ /* obtain hash of pubkey->u.fortezza.params.prime.data +
+ pubkey->u.fortezza.params.subPrime.data +
+ pubkey->u.fortezza.params.base.data */
+
+ /* store hash in params->hash */
+
+ } else if (pubKey->keyType == keaKey) {
+
+ /* the key is a new fortezza KEA public key. */
+ SECITEM_CopyItem(pubKey->arena, &params->hash,
+ &pubKey->u.kea.params.hash );
+
+ } else {
+
+ /* the key has no KEA parameters */
+ return SECFailure;
+ }
+
+}
+
+
+SECStatus
+SECKEY_KEAParamCompare(CERTCertificate *cert1,CERTCertificate *cert2)
+{
+
+ SECStatus rv;
+ SECOidData *oid=NULL;
+ CERTSubjectPublicKeyInfo * subjectSpki=NULL;
+ CERTSubjectPublicKeyInfo * issuerSpki=NULL;
+ CERTCertificate *issuerCert = NULL;
+
+ SECKEYPublicKey *pubKey1 = 0;
+ SECKEYPublicKey *pubKey2 = 0;
+
+ KEAParams params1;
+ KEAParams params2;
+
+
+ rv = SECFailure;
+
+ /* get cert1's public key */
+ pubKey1 = CERT_ExtractPublicKey(cert1);
+ if ( !pubKey1 ) {
+ return(SECFailure);
+ }
+
+
+ /* get cert2's public key */
+ pubKey2 = CERT_ExtractPublicKey(cert2);
+ if ( !pubKey2 ) {
+ return(SECFailure);
+ }
+
+ /* handle the case when both public keys are new
+ * fortezza KEA public keys. */
+
+ if ((pubKey1->keyType == keaKey) &&
+ (pubKey2->keyType == keaKey) ) {
+
+ rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.kea.params.hash,
+ &pubKey2->u.kea.params.hash);
+ goto done;
+ }
+
+ /* handle the case when both public keys are old fortezza
+ * public keys. */
+
+ if ((pubKey1->keyType == fortezzaKey) &&
+ (pubKey2->keyType == fortezzaKey) ) {
+
+ rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.fortezza.keaParams.prime,
+ &pubKey2->u.fortezza.keaParams.prime);
+
+ if (rv == SECEqual) {
+ rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.fortezza.keaParams.subPrime,
+ &pubKey2->u.fortezza.keaParams.subPrime);
+ }
+
+ if (rv == SECEqual) {
+ rv = (SECStatus)SECITEM_CompareItem(&pubKey1->u.fortezza.keaParams.base,
+ &pubKey2->u.fortezza.keaParams.base);
+ }
+
+ goto done;
+ }
+
+
+ /* handle the case when the public keys are a mixture of
+ * old and new. */
+
+ rv = SECKEY_KEASetParams(&params1, pubKey1);
+ if (rv != SECSuccess) return rv;
+
+ rv = SECKEY_KEASetParams(&params2, pubKey2);
+ if (rv != SECSuccess) return rv;
+
+ rv = (SECStatus)SECITEM_CompareItem(&params1.hash, &params2.hash);
+
+done:
+ SECKEY_DestroyPublicKey(pubKey1);
+ SECKEY_DestroyPublicKey(pubKey2);
+
+ return rv; /* returns SECEqual if parameters are equal */
+
+}
+
+
+/* Procedure to update the pqg parameters for a cert's public key.
+ * pqg parameters only need to be updated for DSA and fortezza certificates.
+ * The procedure uses calls to itself recursively to update a certificate
+ * issuer's pqg parameters. Some important rules are:
+ * - Do nothing if the cert already has PQG parameters.
+ * - If the cert does not have PQG parameters, obtain them from the issuer.
+ * - A valid cert chain cannot have a DSA or Fortezza cert without
+ * pqg parameters that has a parent that is not a DSA or Fortezza cert.
+ * - pqg paramters are stored in two different formats: the standard
+ * DER encoded format and the fortezza-only wrapped format. The params
+ * should be copied from issuer to subject cert without modifying the
+ * formats. The public key extraction code will deal with the different
+ * formats at the time of extraction. */
+
+SECStatus
+seckey_UpdateCertPQGChain(CERTCertificate * subjectCert, int count)
+{
+ SECStatus rv, rvCompare;
+ SECOidData *oid=NULL;
+ int tag;
+ CERTSubjectPublicKeyInfo * subjectSpki=NULL;
+ CERTSubjectPublicKeyInfo * issuerSpki=NULL;
+ CERTCertificate *issuerCert = NULL;
+
+ rv = SECSuccess;
+
+ /* increment cert chain length counter*/
+ count++;
+
+ /* check if cert chain length exceeds the maximum length*/
+ if (count > CERT_MAX_CERT_CHAIN) {
+ return SECFailure;
+ }
+
+ oid = SECOID_FindOID(&subjectCert->subjectPublicKeyInfo.algorithm.algorithm);
+ if (oid != NULL) {
+ tag = oid->offset;
+
+ /* Check if cert has a DSA or Fortezza public key. If not, return
+ * success since no PQG params need to be updated. */
+
+ if ( (tag != SEC_OID_MISSI_KEA_DSS_OLD) &&
+ (tag != SEC_OID_MISSI_DSS_OLD) &&
+ (tag != SEC_OID_MISSI_KEA_DSS) &&
+ (tag != SEC_OID_MISSI_DSS) &&
+ (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
+ (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
+ (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) ) {
+
+ return SECSuccess;
+ }
+ } else {
+ return SECFailure; /* return failure if oid is NULL */
+ }
+
+ /* if cert has PQG parameters, return success */
+
+ subjectSpki=&subjectCert->subjectPublicKeyInfo;
+
+ if (subjectSpki->algorithm.parameters.len != 0) {
+ return SECSuccess;
+ }
+
+ /* check if the cert is self-signed */
+ rvCompare = (SECStatus)SECITEM_CompareItem(&subjectCert->derSubject,
+ &subjectCert->derIssuer);
+ if (rvCompare == SECEqual) {
+ /* fail since cert is self-signed and has no pqg params. */
+ return SECFailure;
+ }
+
+ /* get issuer cert */
+ issuerCert = CERT_FindCertIssuer(subjectCert, PR_Now(), certUsageAnyCA);
+ if ( ! issuerCert ) {
+ return SECFailure;
+ }
+
+ /* if parent is not DSA or fortezza, return failure since
+ we don't allow this case. */
+
+ oid = SECOID_FindOID(&issuerCert->subjectPublicKeyInfo.algorithm.algorithm);
+ if (oid != NULL) {
+ tag = oid->offset;
+
+ /* Check if issuer cert has a DSA or Fortezza public key. If not,
+ * return failure. */
+
+ if ( (tag != SEC_OID_MISSI_KEA_DSS_OLD) &&
+ (tag != SEC_OID_MISSI_DSS_OLD) &&
+ (tag != SEC_OID_MISSI_KEA_DSS) &&
+ (tag != SEC_OID_MISSI_DSS) &&
+ (tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
+ (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
+ (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) ) {
+
+ return SECFailure;
+ }
+ } else {
+ return SECFailure; /* return failure if oid is NULL */
+ }
+
+
+ /* at this point the subject cert has no pqg parameters and the
+ * issuer cert has a DSA or fortezza public key. Update the issuer's
+ * pqg parameters with a recursive call to this same function. */
+
+ rv = seckey_UpdateCertPQGChain(issuerCert, count);
+ if (rv != SECSuccess) return rv;
+
+ /* ensure issuer has pqg parameters */
+
+ issuerSpki=&issuerCert->subjectPublicKeyInfo;
+ if (issuerSpki->algorithm.parameters.len == 0) {
+ rv = SECFailure;
+ }
+
+ /* if update was successful and pqg params present, then copy the
+ * parameters to the subject cert's key. */
+
+ if (rv == SECSuccess) {
+ rv = SECITEM_CopyItem(subjectCert->arena,
+ &subjectSpki->algorithm.parameters,
+ &issuerSpki->algorithm.parameters);
+ }
+
+ return rv;
+
+}
+
+
+SECStatus
+SECKEY_UpdateCertPQG(CERTCertificate * subjectCert)
+{
+ return(seckey_UpdateCertPQGChain(subjectCert,0));
+}
+
+
+/* Decode the PQG parameters. The params could be stored in two
+ * possible formats, the old fortezza-only wrapped format or
+ * the standard DER encoded format. Store the decoded parameters in an
+ * old fortezza cert data structure */
+
+SECStatus
+SECKEY_FortezzaDecodePQGtoOld(PRArenaPool *arena, SECKEYPublicKey *pubk,
+ SECItem *params) {
+ SECStatus rv;
+ PQGDualParams dual_params;
+
+ if (params == NULL) return SECFailure;
+
+ if (params->data == NULL) return SECFailure;
+
+ /* Check if params use the standard format.
+ * The value 0xa1 will appear in the first byte of the parameter data
+ * if the PQG parameters are not using the standard format. This
+ * code should be changed to use a better method to detect non-standard
+ * parameters. */
+
+ if ((params->data[0] != 0xa1) &&
+ (params->data[0] != 0xa0)) {
+
+ /* PQG params are in the standard format */
+
+ /* Store DSA PQG parameters */
+ rv = SEC_ASN1DecodeItem(arena, &pubk->u.fortezza.params,
+ SECKEY_PQGParamsTemplate,
+ params);
+
+ if (rv == SECSuccess) {
+
+ /* Copy the DSA PQG parameters to the KEA PQG parameters. */
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.prime,
+ &pubk->u.fortezza.params.prime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.subPrime,
+ &pubk->u.fortezza.params.subPrime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.base,
+ &pubk->u.fortezza.params.base);
+ if (rv != SECSuccess) return rv;
+ }
+
+ } else {
+
+ dual_params.CommParams.prime.len = 0;
+ dual_params.CommParams.subPrime.len = 0;
+ dual_params.CommParams.base.len = 0;
+ dual_params.DiffParams.DiffDSAParams.prime.len = 0;
+ dual_params.DiffParams.DiffDSAParams.subPrime.len = 0;
+ dual_params.DiffParams.DiffDSAParams.base.len = 0;
+
+ /* else the old fortezza-only wrapped format is used. */
+
+ if (params->data[0] == 0xa1) {
+ rv = SEC_ASN1DecodeItem(arena, &dual_params,
+ SECKEY_FortezzaPreParamTemplate, params);
+ } else {
+ rv = SEC_ASN1DecodeItem(arena, &dual_params,
+ SECKEY_FortezzaAltPreParamTemplate, params);
+ }
+
+ if (rv < 0) return rv;
+
+ if ( (dual_params.CommParams.prime.len > 0) &&
+ (dual_params.CommParams.subPrime.len > 0) &&
+ (dual_params.CommParams.base.len > 0) ) {
+ /* copy in common params */
+
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.prime,
+ &dual_params.CommParams.prime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.subPrime,
+ &dual_params.CommParams.subPrime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.base,
+ &dual_params.CommParams.base);
+
+ /* Copy the DSA PQG parameters to the KEA PQG parameters. */
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.prime,
+ &pubk->u.fortezza.params.prime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.subPrime,
+ &pubk->u.fortezza.params.subPrime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.base,
+ &pubk->u.fortezza.params.base);
+ if (rv != SECSuccess) return rv;
+
+ } else {
+
+ /* else copy in different params */
+
+ /* copy DSA PQG parameters */
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.prime,
+ &dual_params.DiffParams.DiffDSAParams.prime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.subPrime,
+ &dual_params.DiffParams.DiffDSAParams.subPrime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.params.base,
+ &dual_params.DiffParams.DiffDSAParams.base);
+
+ /* copy KEA PQG parameters */
+
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.prime,
+ &dual_params.DiffParams.DiffKEAParams.prime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.subPrime,
+ &dual_params.DiffParams.DiffKEAParams.subPrime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.keaParams.base,
+ &dual_params.DiffParams.DiffKEAParams.base);
+ }
+
+ }
+ return rv;
+}
+
+
+/* Decode the DSA PQG parameters. The params could be stored in two
+ * possible formats, the old fortezza-only wrapped format or
+ * the normal standard format. Store the decoded parameters in
+ * a V3 certificate data structure. */
+
+SECStatus
+SECKEY_DSADecodePQG(PRArenaPool *arena, SECKEYPublicKey *pubk, SECItem *params) {
+ SECStatus rv;
+ PQGDualParams dual_params;
+
+ if (params == NULL) return SECFailure;
+
+ if (params->data == NULL) return SECFailure;
+
+ /* Check if params use the standard format.
+ * The value 0xa1 will appear in the first byte of the parameter data
+ * if the PQG parameters are not using the standard format. This
+ * code should be changed to use a better method to detect non-standard
+ * parameters. */
+
+ if ((params->data[0] != 0xa1) &&
+ (params->data[0] != 0xa0)) {
+
+ /* PQG params are in the standard format */
+ rv = SEC_ASN1DecodeItem(arena, &pubk->u.dsa.params,
+ SECKEY_PQGParamsTemplate,
+ params);
+ } else {
+
+ dual_params.CommParams.prime.len = 0;
+ dual_params.CommParams.subPrime.len = 0;
+ dual_params.CommParams.base.len = 0;
+ dual_params.DiffParams.DiffDSAParams.prime.len = 0;
+ dual_params.DiffParams.DiffDSAParams.subPrime.len = 0;
+ dual_params.DiffParams.DiffDSAParams.base.len = 0;
+
+ /* else the old fortezza-only wrapped format is used. */
+ if (params->data[0] == 0xa1) {
+ rv = SEC_ASN1DecodeItem(arena, &dual_params,
+ SECKEY_FortezzaPreParamTemplate, params);
+ } else {
+ rv = SEC_ASN1DecodeItem(arena, &dual_params,
+ SECKEY_FortezzaAltPreParamTemplate, params);
+ }
+
+ if (rv < 0) return rv;
+
+ if ( (dual_params.CommParams.prime.len > 0) &&
+ (dual_params.CommParams.subPrime.len > 0) &&
+ (dual_params.CommParams.base.len > 0) ) {
+ /* copy in common params */
+
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
+ &dual_params.CommParams.prime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
+ &dual_params.CommParams.subPrime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
+ &dual_params.CommParams.base);
+
+ } else {
+
+ /* else copy in different params */
+
+ /* copy DSA PQG parameters */
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
+ &dual_params.DiffParams.DiffDSAParams.prime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
+ &dual_params.DiffParams.DiffDSAParams.subPrime);
+ if (rv != SECSuccess) return rv;
+ rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
+ &dual_params.DiffParams.DiffDSAParams.base);
+
+ }
+ }
+ return rv;
+}
+
+
+
+/* Decodes the DER encoded fortezza public key and stores the results in a
+ * structure of type SECKEYPublicKey. */
+
+SECStatus
+SECKEY_FortezzaDecodeCertKey(PRArenaPool *arena, SECKEYPublicKey *pubk,
+ SECItem *rawkey, SECItem *params) {
+
+ unsigned char *rawptr = rawkey->data;
+ unsigned char *end = rawkey->data + rawkey->len;
+ unsigned char *clearptr;
+
+ /* first march down and decode the raw key data */
+
+ /* version */
+ pubk->u.fortezza.KEAversion = *rawptr++;
+ if (*rawptr++ != 0x01) {
+ return SECFailure;
+ }
+
+ /* KMID */
+ PORT_Memcpy(pubk->u.fortezza.KMID,rawptr,
+ sizeof(pubk->u.fortezza.KMID));
+ rawptr += sizeof(pubk->u.fortezza.KMID);
+
+ /* clearance (the string up to the first byte with the hi-bit on */
+ clearptr = rawptr;
+ while ((rawptr < end) && (*rawptr++ & 0x80));
+
+ if (rawptr >= end) { return SECFailure; }
+ pubk->u.fortezza.clearance.len = rawptr - clearptr;
+ pubk->u.fortezza.clearance.data =
+ (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.clearance.len);
+ if (pubk->u.fortezza.clearance.data == NULL) {
+ return SECFailure;
+ }
+ PORT_Memcpy(pubk->u.fortezza.clearance.data,clearptr,
+ pubk->u.fortezza.clearance.len);
+
+ /* KEAPrivilege (the string up to the first byte with the hi-bit on */
+ clearptr = rawptr;
+ while ((rawptr < end) && (*rawptr++ & 0x80));
+ if (rawptr >= end) { return SECFailure; }
+ pubk->u.fortezza.KEApriviledge.len = rawptr - clearptr;
+ pubk->u.fortezza.KEApriviledge.data =
+ (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.KEApriviledge.len);
+ if (pubk->u.fortezza.KEApriviledge.data == NULL) {
+ return SECFailure;
+ }
+ PORT_Memcpy(pubk->u.fortezza.KEApriviledge.data,clearptr,
+ pubk->u.fortezza.KEApriviledge.len);
+
+
+ /* now copy the key. The next to bytes are the key length, and the
+ * key follows */
+ pubk->u.fortezza.KEAKey.len = (*rawptr << 8) | rawptr[1];
+
+ rawptr += 2;
+ if (rawptr+pubk->u.fortezza.KEAKey.len > end) { return SECFailure; }
+ pubk->u.fortezza.KEAKey.data =
+ (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.KEAKey.len);
+ if (pubk->u.fortezza.KEAKey.data == NULL) {
+ return SECFailure;
+ }
+ PORT_Memcpy(pubk->u.fortezza.KEAKey.data,rawptr,
+ pubk->u.fortezza.KEAKey.len);
+ rawptr += pubk->u.fortezza.KEAKey.len;
+
+ /* shared key */
+ if (rawptr >= end) {
+ pubk->u.fortezza.DSSKey.len = pubk->u.fortezza.KEAKey.len;
+ /* this depends on the fact that we are going to get freed with an
+ * ArenaFree call. We cannot free DSSKey and KEAKey separately */
+ pubk->u.fortezza.DSSKey.data=
+ pubk->u.fortezza.KEAKey.data;
+ pubk->u.fortezza.DSSpriviledge.len =
+ pubk->u.fortezza.KEApriviledge.len;
+ pubk->u.fortezza.DSSpriviledge.data =
+ pubk->u.fortezza.DSSpriviledge.data;
+ goto done;
+ }
+
+
+ /* DSS Version is next */
+ pubk->u.fortezza.DSSversion = *rawptr++;
+
+ if (*rawptr++ != 2) {
+ return SECFailure;
+ }
+
+ /* DSSPrivilege (the string up to the first byte with the hi-bit on */
+ clearptr = rawptr;
+ while ((rawptr < end) && (*rawptr++ & 0x80));
+ if (rawptr >= end) { return SECFailure; }
+ pubk->u.fortezza.DSSpriviledge.len = rawptr - clearptr;
+ pubk->u.fortezza.DSSpriviledge.data =
+ (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.DSSpriviledge.len);
+ if (pubk->u.fortezza.DSSpriviledge.data == NULL) {
+ return SECFailure;
+ }
+ PORT_Memcpy(pubk->u.fortezza.DSSpriviledge.data,clearptr,
+ pubk->u.fortezza.DSSpriviledge.len);
+
+ /* finally copy the DSS key. The next to bytes are the key length,
+ * and the key follows */
+ pubk->u.fortezza.DSSKey.len = (*rawptr << 8) | rawptr[1];
+
+ rawptr += 2;
+ if (rawptr+pubk->u.fortezza.DSSKey.len > end){ return SECFailure; }
+ pubk->u.fortezza.DSSKey.data =
+ (unsigned char*)PORT_ArenaZAlloc(arena,pubk->u.fortezza.DSSKey.len);
+ if (pubk->u.fortezza.DSSKey.data == NULL) {
+ return SECFailure;
+ }
+ PORT_Memcpy(pubk->u.fortezza.DSSKey.data,rawptr,
+ pubk->u.fortezza.DSSKey.len);
+
+ /* ok, now we decode the parameters */
+done:
+
+ return SECKEY_FortezzaDecodePQGtoOld(arena, pubk, params);
+}
+
+
+/* Function used to determine what kind of cert we are dealing with. */
+KeyType
+CERT_GetCertKeyType (CERTSubjectPublicKeyInfo *spki) {
+ int tag;
+ KeyType keyType;
+
+ tag = SECOID_GetAlgorithmTag(&spki->algorithm);
+ switch (tag) {
+ case SEC_OID_X500_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_RSA_ENCRYPTION:
+ keyType = rsaKey;
+ break;
+ case SEC_OID_ANSIX9_DSA_SIGNATURE:
+ keyType = dsaKey;
+ break;
+ case SEC_OID_MISSI_KEA_DSS_OLD:
+ case SEC_OID_MISSI_KEA_DSS:
+ case SEC_OID_MISSI_DSS_OLD:
+ case SEC_OID_MISSI_DSS:
+ keyType = fortezzaKey;
+ break;
+ case SEC_OID_MISSI_KEA:
+ case SEC_OID_MISSI_ALT_KEA:
+ keyType = keaKey;
+ break;
+ case SEC_OID_X942_DIFFIE_HELMAN_KEY:
+ keyType = dhKey;
+ default:
+ keyType = nullKey;
+ }
+ return keyType;
+}
+
+static SECKEYPublicKey *
+seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
+{
+ SECKEYPublicKey *pubk;
+ SECItem os;
+ SECStatus rv;
+ PRArenaPool *arena;
+ int tag;
+
+ arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL)
+ return NULL;
+
+ pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
+ if (pubk == NULL) {
+ PORT_FreeArena (arena, PR_FALSE);
+ return NULL;
+ }
+
+ pubk->arena = arena;
+ pubk->pkcs11Slot = 0;
+ pubk->pkcs11ID = CK_INVALID_KEY;
+
+
+ /* Convert bit string length from bits to bytes */
+ os = spki->subjectPublicKey;
+ DER_ConvertBitString (&os);
+
+ tag = SECOID_GetAlgorithmTag(&spki->algorithm);
+ switch ( tag ) {
+ case SEC_OID_X500_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_RSA_ENCRYPTION:
+ pubk->keyType = rsaKey;
+ rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &os);
+ if (rv == SECSuccess)
+ return pubk;
+ break;
+ case SEC_OID_ANSIX9_DSA_SIGNATURE:
+ pubk->keyType = dsaKey;
+ rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &os);
+ if (rv != SECSuccess) break;
+
+ rv = SECKEY_DSADecodePQG(arena, pubk,
+ &spki->algorithm.parameters);
+
+ if (rv == SECSuccess) return pubk;
+ break;
+ case SEC_OID_X942_DIFFIE_HELMAN_KEY:
+ pubk->keyType = dhKey;
+ rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &os);
+ if (rv != SECSuccess) break;
+
+ rv = SEC_ASN1DecodeItem(arena, &pubk->u.dh,
+ SECKEY_DHParamKeyTemplate,
+ &spki->algorithm.parameters);
+
+ if (rv == SECSuccess) return pubk;
+ break;
+ case SEC_OID_MISSI_KEA_DSS_OLD:
+ case SEC_OID_MISSI_KEA_DSS:
+ case SEC_OID_MISSI_DSS_OLD:
+ case SEC_OID_MISSI_DSS:
+ pubk->keyType = fortezzaKey;
+ rv = SECKEY_FortezzaDecodeCertKey(arena, pubk, &os,
+ &spki->algorithm.parameters);
+ if (rv == SECSuccess)
+ return pubk;
+ break;
+
+ case SEC_OID_MISSI_KEA:
+ pubk->keyType = keaKey;
+
+ rv = SEC_ASN1DecodeItem(arena, pubk,
+ SECKEY_KEAPublicKeyTemplate, &os);
+ if (rv != SECSuccess) break;
+
+
+ rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_KEAParamsTemplate,
+ &spki->algorithm.parameters);
+
+ if (rv == SECSuccess)
+ return pubk;
+
+ break;
+
+ case SEC_OID_MISSI_ALT_KEA:
+ pubk->keyType = keaKey;
+
+ rv = SECITEM_CopyItem(arena,&pubk->u.kea.publicValue,&os);
+ if (rv != SECSuccess) break;
+
+ rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_KEAParamsTemplate,
+ &spki->algorithm.parameters);
+
+ if (rv == SECSuccess)
+ return pubk;
+
+ break;
+
+
+ default:
+ rv = SECFailure;
+ break;
+ }
+
+ SECKEY_DestroyPublicKey (pubk);
+ return NULL;
+}
+
+SECKEYPublicKey *
+CERT_ExtractPublicKey(CERTCertificate *cert)
+{
+ SECStatus rv;
+
+ rv = SECKEY_UpdateCertPQG(cert);
+ if (rv != SECSuccess) return NULL;
+
+ return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo);
+}
+
+/*
+ * Get the public key for the fortezza KMID. NOTE this requires the
+ * PQG paramters to be set. We probably should have a fortezza call that
+ * just extracts the kmid for us directly so this function can work
+ * without having the whole cert chain
+ */
+SECKEYPublicKey *
+CERT_KMIDPublicKey(CERTCertificate *cert)
+{
+ return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo);
+}
+
+/* returns key strength in bytes (not bits) */
+unsigned
+SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk)
+{
+ unsigned char b0;
+
+ /* interpret modulus length as key strength... in
+ * fortezza that's the public key length */
+
+ switch (pubk->keyType) {
+ case rsaKey:
+ b0 = pubk->u.rsa.modulus.data[0];
+ return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
+ case dsaKey:
+ b0 = pubk->u.dsa.publicValue.data[0];
+ return b0 ? pubk->u.dsa.publicValue.len :
+ pubk->u.dsa.publicValue.len - 1;
+ case dhKey:
+ b0 = pubk->u.dh.publicValue.data[0];
+ return b0 ? pubk->u.dh.publicValue.len :
+ pubk->u.dh.publicValue.len - 1;
+ case fortezzaKey:
+ return MAX(pubk->u.fortezza.KEAKey.len, pubk->u.fortezza.DSSKey.len);
+ default:
+ break;
+ }
+ return 0;
+}
+
+SECKEYPrivateKey *
+SECKEY_CopyPrivateKey(SECKEYPrivateKey *privk)
+{
+ SECKEYPrivateKey *copyk;
+ PRArenaPool *arena;
+
+ if (privk == NULL) {
+ return NULL;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PORT_SetError (SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+
+ copyk = (SECKEYPrivateKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPrivateKey));
+ if (copyk) {
+ copyk->arena = arena;
+ copyk->keyType = privk->keyType;
+
+ /* copy the PKCS #11 parameters */
+ copyk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot);
+ /* if the key we're referencing was a temparary key we have just
+ * created, that we want to go away when we're through, we need
+ * to make a copy of it */
+ if (privk->pkcs11IsTemp) {
+ copyk->pkcs11ID =
+ PK11_CopyKey(privk->pkcs11Slot,privk->pkcs11ID);
+ if (copyk->pkcs11ID == CK_INVALID_KEY) goto fail;
+ } else {
+ copyk->pkcs11ID = privk->pkcs11ID;
+ }
+ copyk->pkcs11IsTemp = privk->pkcs11IsTemp;
+ copyk->wincx = privk->wincx;
+ return copyk;
+ } else {
+ PORT_SetError (SEC_ERROR_NO_MEMORY);
+ }
+
+fail:
+ PORT_FreeArena (arena, PR_FALSE);
+ return NULL;
+}
+
+SECKEYPublicKey *
+SECKEY_CopyPublicKey(SECKEYPublicKey *pubk)
+{
+ SECKEYPublicKey *copyk;
+ PRArenaPool *arena;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PORT_SetError (SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+
+ copyk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey));
+ if (copyk != NULL) {
+ SECStatus rv = SECSuccess;
+
+ copyk->arena = arena;
+ copyk->keyType = pubk->keyType;
+ copyk->pkcs11Slot = NULL; /* go get own reference */
+ copyk->pkcs11ID = CK_INVALID_KEY;
+ switch (pubk->keyType) {
+ case rsaKey:
+ rv = SECITEM_CopyItem(arena, &copyk->u.rsa.modulus,
+ &pubk->u.rsa.modulus);
+ if (rv == SECSuccess) {
+ rv = SECITEM_CopyItem (arena, &copyk->u.rsa.publicExponent,
+ &pubk->u.rsa.publicExponent);
+ if (rv == SECSuccess)
+ return copyk;
+ }
+ break;
+ case dsaKey:
+ rv = SECITEM_CopyItem(arena, &copyk->u.dsa.publicValue,
+ &pubk->u.dsa.publicValue);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.prime,
+ &pubk->u.dsa.params.prime);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.subPrime,
+ &pubk->u.dsa.params.subPrime);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.base,
+ &pubk->u.dsa.params.base);
+ break;
+ case keaKey:
+ rv = SECITEM_CopyItem(arena, &copyk->u.kea.publicValue,
+ &pubk->u.kea.publicValue);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.kea.params.hash,
+ &pubk->u.kea.params.hash);
+ break;
+ case fortezzaKey:
+ copyk->u.fortezza.KEAversion = pubk->u.fortezza.KEAversion;
+ copyk->u.fortezza.DSSversion = pubk->u.fortezza.DSSversion;
+ PORT_Memcpy(copyk->u.fortezza.KMID, pubk->u.fortezza.KMID,
+ sizeof(pubk->u.fortezza.KMID));
+ rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.clearance,
+ &pubk->u.fortezza.clearance);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.KEApriviledge,
+ &pubk->u.fortezza.KEApriviledge);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.DSSpriviledge,
+ &pubk->u.fortezza.DSSpriviledge);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.KEAKey,
+ &pubk->u.fortezza.KEAKey);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.DSSKey,
+ &pubk->u.fortezza.DSSKey);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.params.prime,
+ &pubk->u.fortezza.params.prime);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.params.subPrime,
+ &pubk->u.fortezza.params.subPrime);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.params.base,
+ &pubk->u.fortezza.params.base);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.keaParams.prime,
+ &pubk->u.fortezza.keaParams.prime);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.keaParams.subPrime,
+ &pubk->u.fortezza.keaParams.subPrime);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.fortezza.keaParams.base,
+ &pubk->u.fortezza.keaParams.base);
+ break;
+ case dhKey:
+ rv = SECITEM_CopyItem(arena,&copyk->u.dh.prime,&pubk->u.dh.prime);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena,&copyk->u.dh.base,&pubk->u.dh.base);
+ if (rv != SECSuccess) break;
+ rv = SECITEM_CopyItem(arena, &copyk->u.dh.publicValue,
+ &pubk->u.dh.publicValue);
+ break;
+ case nullKey:
+ return copyk;
+ default:
+ rv = SECFailure;
+ break;
+ }
+ if (rv == SECSuccess)
+ return copyk;
+
+ SECKEY_DestroyPublicKey (copyk);
+ } else {
+ PORT_SetError (SEC_ERROR_NO_MEMORY);
+ }
+
+ PORT_FreeArena (arena, PR_FALSE);
+ return NULL;
+}
+
+
+SECKEYPublicKey *
+SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
+{
+ SECKEYPublicKey *pubk;
+ PRArenaPool *arena;
+ CERTCertificate *cert;
+ SECStatus rv;
+
+ /*
+ * First try to look up the cert.
+ */
+ cert = PK11_GetCertFromPrivateKey(privk);
+ if (cert) {
+ pubk = CERT_ExtractPublicKey(cert);
+ CERT_DestroyCertificate(cert);
+ return pubk;
+ }
+
+ /* couldn't find the cert, build pub key by hand */
+ arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PORT_SetError (SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+ pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena,
+ sizeof (SECKEYPublicKey));
+ if (pubk == NULL) {
+ PORT_FreeArena(arena,PR_FALSE);
+ return NULL;
+ }
+ pubk->keyType = privk->keyType;
+ pubk->pkcs11Slot = NULL;
+ pubk->pkcs11ID = CK_INVALID_KEY;
+ pubk->arena = arena;
+
+ /*
+ * fortezza is at the head of this switch, since we don't want to
+ * allocate an arena... CERT_ExtractPublicKey will to that for us.
+ */
+ switch(privk->keyType) {
+ case fortezzaKey:
+ case nullKey:
+ case dhKey:
+ case dsaKey:
+ /* Nothing to query, if the cert isn't there, we're done -- no way
+ * to get the public key */
+ break;
+ case rsaKey:
+ rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID,
+ CKA_MODULUS,arena,&pubk->u.rsa.modulus);
+ if (rv != SECSuccess) break;
+ rv = PK11_ReadAttribute(privk->pkcs11Slot,privk->pkcs11ID,
+ CKA_PUBLIC_EXPONENT,arena,&pubk->u.rsa.publicExponent);
+ if (rv != SECSuccess) break;
+ return pubk;
+ break;
+ default:
+ break;
+ }
+
+ PORT_FreeArena (arena, PR_FALSE);
+ return NULL;
+}
+
+CERTSubjectPublicKeyInfo *
+SECKEY_CreateSubjectPublicKeyInfo(SECKEYPublicKey *pubk)
+{
+ CERTSubjectPublicKeyInfo *spki;
+ PRArenaPool *arena;
+ SECItem params = { siBuffer, NULL, 0 };
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+
+ spki = (CERTSubjectPublicKeyInfo *) PORT_ArenaZAlloc(arena, sizeof (*spki));
+ if (spki != NULL) {
+ SECStatus rv;
+ SECItem *rv_item;
+
+ spki->arena = arena;
+ switch(pubk->keyType) {
+ case rsaKey:
+ rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
+ SEC_OID_PKCS1_RSA_ENCRYPTION, 0);
+ if (rv == SECSuccess) {
+ /*
+ * DER encode the public key into the subjectPublicKeyInfo.
+ */
+ rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
+ pubk, SECKEY_RSAPublicKeyTemplate);
+ if (rv_item != NULL) {
+ /*
+ * The stored value is supposed to be a BIT_STRING,
+ * so convert the length.
+ */
+ spki->subjectPublicKey.len <<= 3;
+ /*
+ * We got a good one; return it.
+ */
+ return spki;
+ }
+ }
+ break;
+ case dsaKey:
+ /* DER encode the params. */
+ rv_item = SEC_ASN1EncodeItem(arena, &params, &pubk->u.dsa.params,
+ SECKEY_PQGParamsTemplate);
+ if (rv_item != NULL) {
+ rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
+ SEC_OID_ANSIX9_DSA_SIGNATURE,
+ &params);
+ if (rv == SECSuccess) {
+ /*
+ * DER encode the public key into the subjectPublicKeyInfo.
+ */
+ rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
+ pubk,
+ SECKEY_DSAPublicKeyTemplate);
+ if (rv_item != NULL) {
+ /*
+ * The stored value is supposed to be a BIT_STRING,
+ * so convert the length.
+ */
+ spki->subjectPublicKey.len <<= 3;
+ /*
+ * We got a good one; return it.
+ */
+ return spki;
+ }
+ }
+ }
+ SECITEM_FreeItem(&params, PR_FALSE);
+ break;
+ case keaKey:
+ case dhKey: /* later... */
+
+ break;
+ case fortezzaKey:
+#ifdef notdef
+ /* encode the DSS parameters (PQG) */
+ rv = FortezzaBuildParams(&params,pubk);
+ if (rv != SECSuccess) break;
+
+ /* set the algorithm */
+ rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
+ SEC_OID_MISSI_KEA_DSS, &params);
+ PORT_Free(params.data);
+ if (rv == SECSuccess) {
+ /*
+ * Encode the public key into the subjectPublicKeyInfo.
+ * Fortezza key material is not standard DER
+ */
+ rv = FortezzaEncodeCertKey(arena,&spki->subjectPublicKey,pubk);
+ if (rv == SECSuccess) {
+ /*
+ * The stored value is supposed to be a BIT_STRING,
+ * so convert the length.
+ */
+ spki->subjectPublicKey.len <<= 3;
+
+ /*
+ * We got a good one; return it.
+ */
+ return spki;
+ }
+ }
+#endif
+ break;
+ default:
+ break;
+ }
+ } else {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return NULL;
+}
+
+void
+SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki)
+{
+ if (spki && spki->arena) {
+ PORT_FreeArena(spki->arena, PR_FALSE);
+ }
+}
+
+/*
+ * this only works for RSA keys... need to do something
+ * similiar to CERT_ExtractPublicKey for other key times.
+ */
+SECKEYPublicKey *
+SECKEY_DecodeDERPublicKey(SECItem *pubkder)
+{
+ PRArenaPool *arena;
+ SECKEYPublicKey *pubk;
+ SECStatus rv;
+
+ arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PORT_SetError (SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+
+ pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc (arena, sizeof (SECKEYPublicKey));
+ if (pubk != NULL) {
+ pubk->arena = arena;
+ pubk->pkcs11Slot = NULL;
+ pubk->pkcs11ID = 0;
+ rv = SEC_ASN1DecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate,
+ pubkder);
+ if (rv == SECSuccess)
+ return pubk;
+ SECKEY_DestroyPublicKey (pubk);
+ } else {
+ PORT_SetError (SEC_ERROR_NO_MEMORY);
+ }
+
+ PORT_FreeArena (arena, PR_FALSE);
+ return NULL;
+}
+
+/*
+ * Decode a base64 ascii encoded DER encoded public key.
+ */
+SECKEYPublicKey *
+SECKEY_ConvertAndDecodePublicKey(char *pubkstr)
+{
+ SECKEYPublicKey *pubk;
+ SECStatus rv;
+ SECItem der;
+
+ rv = ATOB_ConvertAsciiToItem (&der, pubkstr);
+ if (rv != SECSuccess)
+ return NULL;
+
+ pubk = SECKEY_DecodeDERPublicKey (&der);
+
+ PORT_Free (der.data);
+ return pubk;
+}
+
+CERTSubjectPublicKeyInfo *
+SECKEY_DecodeDERSubjectPublicKeyInfo(SECItem *spkider)
+{
+ PRArenaPool *arena;
+ CERTSubjectPublicKeyInfo *spki;
+ SECStatus rv;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+
+ spki = (CERTSubjectPublicKeyInfo *)
+ PORT_ArenaZAlloc(arena, sizeof (CERTSubjectPublicKeyInfo));
+ if (spki != NULL) {
+ spki->arena = arena;
+ rv = SEC_ASN1DecodeItem(arena,spki,
+ CERT_SubjectPublicKeyInfoTemplate,spkider);
+ if (rv == SECSuccess)
+ return spki;
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ } else {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return NULL;
+}
+
+/*
+ * Decode a base64 ascii encoded DER encoded subject public key info.
+ */
+CERTSubjectPublicKeyInfo *
+SECKEY_ConvertAndDecodeSubjectPublicKeyInfo(char *spkistr)
+{
+ CERTSubjectPublicKeyInfo *spki;
+ SECStatus rv;
+ SECItem der;
+
+ rv = ATOB_ConvertAsciiToItem(&der, spkistr);
+ if (rv != SECSuccess)
+ return NULL;
+
+ spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der);
+
+ PORT_Free(der.data);
+ return spki;
+}
+
+/*
+ * Decode a base64 ascii encoded DER encoded public key and challenge
+ * Verify digital signature and make sure challenge matches
+ */
+CERTSubjectPublicKeyInfo *
+SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge,
+ void *wincx)
+{
+ CERTSubjectPublicKeyInfo *spki = NULL;
+ CERTPublicKeyAndChallenge pkac;
+ SECStatus rv;
+ SECItem signedItem;
+ PRArenaPool *arena = NULL;
+ CERTSignedData sd;
+ SECItem sig;
+ SECKEYPublicKey *pubKey = NULL;
+ int len;
+
+ signedItem.data = NULL;
+
+ /* convert the base64 encoded data to binary */
+ rv = ATOB_ConvertAsciiToItem(&signedItem, pkacstr);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ /* create an arena */
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ goto loser;
+ }
+
+ /* decode the outer wrapping of signed data */
+ PORT_Memset(&sd, 0, sizeof(CERTSignedData));
+ rv = SEC_ASN1DecodeItem(arena, &sd, CERT_SignedDataTemplate, &signedItem );
+ if ( rv ) {
+ goto loser;
+ }
+
+ /* decode the public key and challenge wrapper */
+ PORT_Memset(&pkac, 0, sizeof(CERTPublicKeyAndChallenge));
+ rv = SEC_ASN1DecodeItem(arena, &pkac, CERT_PublicKeyAndChallengeTemplate,
+ &sd.data);
+ if ( rv ) {
+ goto loser;
+ }
+
+ /* decode the subject public key info */
+ spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&pkac.spki);
+ if ( spki == NULL ) {
+ goto loser;
+ }
+
+ /* get the public key */
+ pubKey = seckey_ExtractPublicKey(spki);
+ if ( pubKey == NULL ) {
+ goto loser;
+ }
+
+ /* check the signature */
+ sig = sd.signature;
+ DER_ConvertBitString(&sig);
+ rv = VFY_VerifyData(sd.data.data, sd.data.len, pubKey, &sig,
+ SECOID_GetAlgorithmTag(&(sd.signatureAlgorithm)), wincx);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* check the challenge */
+ if ( challenge ) {
+ len = PORT_Strlen(challenge);
+ /* length is right */
+ if ( len != pkac.challenge.len ) {
+ goto loser;
+ }
+ /* actual data is right */
+ if ( PORT_Memcmp(challenge, pkac.challenge.data, len) != 0 ) {
+ goto loser;
+ }
+ }
+ goto done;
+
+loser:
+ /* make sure that we return null if we got an error */
+ if ( spki ) {
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ }
+ spki = NULL;
+
+done:
+ if ( signedItem.data ) {
+ PORT_Free(signedItem.data);
+ }
+ if ( arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ if ( pubKey ) {
+ SECKEY_DestroyPublicKey(pubKey);
+ }
+
+ return spki;
+}
+
+void
+SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk,
+ PRBool freeit)
+{
+ PRArenaPool *poolp;
+
+ if(pvk != NULL) {
+ if(pvk->arena) {
+ poolp = pvk->arena;
+ /* zero structure since PORT_FreeArena does not support
+ * this yet.
+ */
+ PORT_Memset(pvk->privateKey.data, 0, pvk->privateKey.len);
+ PORT_Memset((char *)pvk, 0, sizeof(*pvk));
+ if(freeit == PR_TRUE) {
+ PORT_FreeArena(poolp, PR_TRUE);
+ } else {
+ pvk->arena = poolp;
+ }
+ } else {
+ SECITEM_ZfreeItem(&pvk->version, PR_FALSE);
+ SECITEM_ZfreeItem(&pvk->privateKey, PR_FALSE);
+ SECOID_DestroyAlgorithmID(&pvk->algorithm, PR_FALSE);
+ PORT_Memset((char *)pvk, 0, sizeof(pvk));
+ if(freeit == PR_TRUE) {
+ PORT_Free(pvk);
+ }
+ }
+ }
+}
+
+void
+SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki,
+ PRBool freeit)
+{
+ PRArenaPool *poolp;
+
+ if(epki != NULL) {
+ if(epki->arena) {
+ poolp = epki->arena;
+ /* zero structure since PORT_FreeArena does not support
+ * this yet.
+ */
+ PORT_Memset(epki->encryptedData.data, 0, epki->encryptedData.len);
+ PORT_Memset((char *)epki, 0, sizeof(*epki));
+ if(freeit == PR_TRUE) {
+ PORT_FreeArena(poolp, PR_TRUE);
+ } else {
+ epki->arena = poolp;
+ }
+ } else {
+ SECITEM_ZfreeItem(&epki->encryptedData, PR_FALSE);
+ SECOID_DestroyAlgorithmID(&epki->algorithm, PR_FALSE);
+ PORT_Memset((char *)epki, 0, sizeof(epki));
+ if(freeit == PR_TRUE) {
+ PORT_Free(epki);
+ }
+ }
+ }
+}
+
+SECStatus
+SECKEY_CopyPrivateKeyInfo(PRArenaPool *poolp,
+ SECKEYPrivateKeyInfo *to,
+ SECKEYPrivateKeyInfo *from)
+{
+ SECStatus rv = SECFailure;
+
+ if((to == NULL) || (from == NULL)) {
+ return SECFailure;
+ }
+
+ rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
+ if(rv != SECSuccess) {
+ return SECFailure;
+ }
+ rv = SECITEM_CopyItem(poolp, &to->privateKey, &from->privateKey);
+ if(rv != SECSuccess) {
+ return SECFailure;
+ }
+ rv = SECITEM_CopyItem(poolp, &to->version, &from->version);
+
+ return rv;
+}
+
+SECStatus
+SECKEY_CopyEncryptedPrivateKeyInfo(PRArenaPool *poolp,
+ SECKEYEncryptedPrivateKeyInfo *to,
+ SECKEYEncryptedPrivateKeyInfo *from)
+{
+ SECStatus rv = SECFailure;
+
+ if((to == NULL) || (from == NULL)) {
+ return SECFailure;
+ }
+
+ rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
+ if(rv != SECSuccess) {
+ return SECFailure;
+ }
+ rv = SECITEM_CopyItem(poolp, &to->encryptedData, &from->encryptedData);
+
+ return rv;
+}
+
+KeyType
+SECKEY_GetPrivateKeyType(SECKEYPrivateKey *privKey)
+{
+ return privKey->keyType;
+}
+
+KeyType
+SECKEY_GetPublicKeyType(SECKEYPublicKey *pubKey)
+{
+ return pubKey->keyType;
+}
diff --git a/security/nss/lib/cryptohi/secsign.c b/security/nss/lib/cryptohi/secsign.c
new file mode 100644
index 000000000..35af3f701
--- /dev/null
+++ b/security/nss/lib/cryptohi/secsign.c
@@ -0,0 +1,497 @@
+/*
+ * Signature stuff.
+ *
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include "cryptohi.h"
+#include "sechash.h"
+#include "secder.h"
+#include "keyhi.h"
+#include "secoid.h"
+#include "secdig.h"
+#include "pk11func.h"
+#include "secerr.h"
+
+struct SGNContextStr {
+ SECOidTag signalg;
+ SECOidTag hashalg;
+ void *hashcx;
+ SECHashObject *hashobj;
+ SECKEYPrivateKey *key;
+};
+
+SGNContext *
+SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key)
+{
+ SGNContext *cx;
+ SECOidTag hashalg, signalg;
+ KeyType keyType;
+
+ /* OK, map a PKCS #7 hash and encrypt algorithm into
+ * a standard hashing algorithm. Why did we pass in the whole
+ * PKCS #7 algTag if we were just going to change here you might
+ * ask. Well the answer is for some cards we may have to do the
+ * hashing on card. It may not support CKM_RSA_PKCS sign algorithm,
+ * it may just support CKM_RSA_PKCS_WITH_SHA1 and/or CKM_RSA_PKCS_WITH_MD5.
+ */
+ switch (alg) {
+ /* We probably shouldn't be generating MD2 signatures either */
+ case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
+ hashalg = SEC_OID_MD2;
+ signalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
+ keyType = rsaKey;
+ break;
+ case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
+ hashalg = SEC_OID_MD5;
+ signalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
+ keyType = rsaKey;
+ break;
+ case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
+ case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
+ hashalg = SEC_OID_SHA1;
+ signalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
+ keyType = rsaKey;
+ break;
+ /* what about normal DSA? */
+ case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
+ case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
+ hashalg = SEC_OID_SHA1;
+ signalg = SEC_OID_ANSIX9_DSA_SIGNATURE;
+ keyType = dsaKey;
+ break;
+ case SEC_OID_MISSI_DSS:
+ case SEC_OID_MISSI_KEA_DSS:
+ case SEC_OID_MISSI_KEA_DSS_OLD:
+ case SEC_OID_MISSI_DSS_OLD:
+ hashalg = SEC_OID_SHA1;
+ signalg = SEC_OID_MISSI_DSS; /* XXX Is there a better algid? */
+ keyType = fortezzaKey;
+ break;
+ /* we don't implement MD4 hashes.
+ * we *CERTAINLY* don't want to sign one! */
+ case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return 0;
+ }
+
+ /* verify our key type */
+ if (key->keyType != keyType &&
+ !((key->keyType == dsaKey) && (keyType == fortezzaKey)) &&
+ !((key->keyType == fortezzaKey) && (keyType == dsaKey)) ) {
+ PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+ return 0;
+ }
+
+ cx = (SGNContext*) PORT_ZAlloc(sizeof(SGNContext));
+ if (cx) {
+ cx->hashalg = hashalg;
+ cx->signalg = signalg;
+ cx->key = key;
+ }
+ return cx;
+}
+
+void
+SGN_DestroyContext(SGNContext *cx, PRBool freeit)
+{
+ if (cx) {
+ if (cx->hashcx != NULL) {
+ (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
+ cx->hashcx = NULL;
+ }
+ if (freeit) {
+ PORT_ZFree(cx, sizeof(SGNContext));
+ }
+ }
+}
+
+SECStatus
+SGN_Begin(SGNContext *cx)
+{
+ if (cx->hashcx != NULL) {
+ (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
+ cx->hashcx = NULL;
+ }
+
+ switch (cx->hashalg) {
+ case SEC_OID_MD2:
+ cx->hashobj = &SECHashObjects[HASH_AlgMD2];
+ break;
+ case SEC_OID_MD5:
+ cx->hashobj = &SECHashObjects[HASH_AlgMD5];
+ break;
+ case SEC_OID_SHA1:
+ cx->hashobj = &SECHashObjects[HASH_AlgSHA1];
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+ return SECFailure;
+ }
+
+ cx->hashcx = (*cx->hashobj->create)();
+ if (cx->hashcx == NULL)
+ return SECFailure;
+
+ (*cx->hashobj->begin)(cx->hashcx);
+ return SECSuccess;
+}
+
+SECStatus
+SGN_Update(SGNContext *cx, unsigned char *input, unsigned inputLen)
+{
+ if (cx->hashcx == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ (*cx->hashobj->update)(cx->hashcx, input, inputLen);
+ return SECSuccess;
+}
+
+SECStatus
+SGN_End(SGNContext *cx, SECItem *result)
+{
+ unsigned char digest[32];
+ unsigned part1, signatureLen;
+ SECStatus rv;
+ SECItem digder, sigitem;
+ PRArenaPool *arena = 0;
+ SECKEYPrivateKey *privKey = cx->key;
+ SGNDigestInfo *di = 0;
+
+
+ result->data = 0;
+ digder.data = 0;
+
+ /* Finish up digest function */
+ if (cx->hashcx == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ (*cx->hashobj->end)(cx->hashcx, digest, &part1, sizeof(digest));
+
+
+ if (privKey->keyType == rsaKey) {
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( !arena ) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ /* Construct digest info */
+ di = SGN_CreateDigestInfo(cx->hashalg, digest, part1);
+ if (!di) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ /* Der encode the digest as a DigestInfo */
+ rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ } else {
+ digder.data = digest;
+ digder.len = part1;
+ }
+
+ /*
+ ** Encrypt signature after constructing appropriate PKCS#1 signature
+ ** block
+ */
+ signatureLen = PK11_SignatureLen(privKey);
+ sigitem.len = signatureLen;
+ sigitem.data = (unsigned char*) PORT_Alloc(signatureLen);
+
+ if (sigitem.data == NULL) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ rv = PK11_Sign(privKey, &sigitem, &digder);
+ if (rv != SECSuccess) {
+ PORT_Free(sigitem.data);
+ sigitem.data = NULL;
+ }
+
+ if (cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) {
+ rv = DSAU_EncodeDerSig(result, &sigitem);
+ PORT_Free(sigitem.data);
+ if (rv != SECSuccess)
+ goto loser;
+ } else {
+ result->len = sigitem.len;
+ result->data = sigitem.data;
+ }
+
+ loser:
+ SGN_DestroyDigestInfo(di);
+ if (arena != NULL) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ return rv;
+}
+
+/************************************************************************/
+
+/*
+** Sign a block of data returning in result a bunch of bytes that are the
+** signature. Returns zero on success, an error code on failure.
+*/
+SECStatus
+SEC_SignData(SECItem *res, unsigned char *buf, int len,
+ SECKEYPrivateKey *pk, SECOidTag algid)
+{
+ SECStatus rv;
+ SGNContext *sgn;
+
+
+ sgn = SGN_NewContext(algid, pk);
+
+ if (sgn == NULL)
+ return SECFailure;
+
+ rv = SGN_Begin(sgn);
+ if (rv != SECSuccess)
+ goto loser;
+
+ rv = SGN_Update(sgn, buf, len);
+ if (rv != SECSuccess)
+ goto loser;
+
+ rv = SGN_End(sgn, res);
+
+ loser:
+ SGN_DestroyContext(sgn, PR_TRUE);
+ return rv;
+}
+
+/*
+** Sign the input file's contents returning in result a bunch of bytes
+** that are the signature. Returns zero on success, an error code on
+** failure.
+*/
+SECStatus
+SEC_SignFile(SECItem *result, FILE *input,
+ SECKEYPrivateKey *pk, SECOidTag algid)
+{
+ unsigned char buf[1024];
+ SECStatus rv;
+ int nb;
+ SGNContext *sgn;
+
+ sgn = SGN_NewContext(algid, pk);
+ if (sgn == NULL)
+ return SECFailure;
+ rv = SGN_Begin(sgn);
+ if (rv != SECSuccess)
+ goto loser;
+
+ /*
+ ** Now feed the contents of the input file into the digest
+ ** algorithm, one chunk at a time, until we have exhausted the
+ ** input
+ */
+ for (;;) {
+ if (feof(input)) break;
+ nb = fread(buf, 1, sizeof(buf), input);
+ if (nb == 0) {
+ if (ferror(input)) {
+ PORT_SetError(SEC_ERROR_IO);
+ rv = SECFailure;
+ goto loser;
+ }
+ break;
+ }
+ rv = SGN_Update(sgn, buf, nb);
+ if (rv != SECSuccess)
+ goto loser;
+ }
+
+ /* Sign the digest */
+ rv = SGN_End(sgn, result);
+ /* FALL THROUGH */
+
+ loser:
+ SGN_DestroyContext(sgn, PR_TRUE);
+ return rv;
+}
+
+/************************************************************************/
+
+DERTemplate CERTSignedDataTemplate[] =
+{
+ { DER_SEQUENCE,
+ 0, NULL, sizeof(CERTSignedData) },
+ { DER_ANY,
+ offsetof(CERTSignedData,data), },
+ { DER_INLINE,
+ offsetof(CERTSignedData,signatureAlgorithm),
+ SECAlgorithmIDTemplate, },
+ { DER_BIT_STRING,
+ offsetof(CERTSignedData,signature), },
+ { 0, }
+};
+
+const SEC_ASN1Template CERT_SignedDataTemplate[] =
+{
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTSignedData) },
+ { SEC_ASN1_ANY,
+ offsetof(CERTSignedData,data), },
+ { SEC_ASN1_INLINE,
+ offsetof(CERTSignedData,signatureAlgorithm),
+ SECOID_AlgorithmIDTemplate, },
+ { SEC_ASN1_BIT_STRING,
+ offsetof(CERTSignedData,signature), },
+ { 0, }
+};
+
+SECStatus
+SEC_DerSignData(PRArenaPool *arena, SECItem *result,
+ unsigned char *buf, int len, SECKEYPrivateKey *pk, SECOidTag algID)
+{
+ SECItem it;
+ CERTSignedData sd;
+ SECStatus rv;
+
+ it.data = 0;
+
+ /* XXX We should probably have some asserts here to make sure the key type
+ * and algID match
+ */
+
+ if (algID == SEC_OID_UNKNOWN) {
+ switch(pk->keyType) {
+ case rsaKey:
+ algID = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
+ break;
+ case dsaKey:
+ algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
+ break;
+ default:
+ return SECFailure;
+ break;
+ }
+ }
+
+ /* Sign input buffer */
+ rv = SEC_SignData(&it, buf, len, pk, algID);
+ if (rv) goto loser;
+
+ /* Fill out SignedData object */
+ PORT_Memset(&sd, 0, sizeof(sd));
+ sd.data.data = buf;
+ sd.data.len = len;
+ sd.signature.data = it.data;
+ sd.signature.len = it.len << 3; /* convert to bit string */
+ rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algID, 0);
+ if (rv) goto loser;
+
+ /* DER encode the signed data object */
+ rv = DER_Encode(arena, result, CERTSignedDataTemplate, &sd);
+ /* FALL THROUGH */
+
+ loser:
+ PORT_Free(it.data);
+ return rv;
+}
+
+SECStatus
+SGN_Digest(SECKEYPrivateKey *privKey,
+ SECOidTag algtag, SECItem *result, SECItem *digest)
+{
+ unsigned modulusLen;
+ SECStatus rv;
+ SECItem digder;
+ PRArenaPool *arena = 0;
+ SGNDigestInfo *di = 0;
+
+
+ result->data = 0;
+
+ if (privKey->keyType == rsaKey) {
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( !arena ) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ /* Construct digest info */
+ di = SGN_CreateDigestInfo(algtag, digest->data, digest->len);
+ if (!di) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ /* Der encode the digest as a DigestInfo */
+ rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ } else {
+ digder.data = digest->data;
+ digder.len = digest->len;
+ }
+
+ /*
+ ** Encrypt signature after constructing appropriate PKCS#1 signature
+ ** block
+ */
+ modulusLen = PK11_SignatureLen(privKey);
+ result->len = modulusLen;
+ result->data = (unsigned char*) PORT_Alloc(modulusLen);
+
+ if (result->data == NULL) {
+ rv = SECFailure;
+ goto loser;
+ }
+
+ rv = PK11_Sign(privKey, result, &digder);
+ if (rv != SECSuccess) {
+ PORT_Free(result->data);
+ result->data = NULL;
+ }
+
+ loser:
+ SGN_DestroyDigestInfo(di);
+ if (arena != NULL) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ return rv;
+}
diff --git a/security/nss/lib/cryptohi/secvfy.c b/security/nss/lib/cryptohi/secvfy.c
new file mode 100644
index 000000000..6bd3fdc2e
--- /dev/null
+++ b/security/nss/lib/cryptohi/secvfy.c
@@ -0,0 +1,389 @@
+/*
+ * Verification stuff.
+ *
+ * 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 Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include "cryptohi.h"
+#include "sechash.h"
+#include "keyhi.h"
+#include "secasn1.h"
+#include "secoid.h"
+#include "pk11func.h"
+#include "secdig.h"
+#include "secerr.h"
+
+/*
+** Decrypt signature block using public key (in place)
+** XXX this is assuming that the signature algorithm has WITH_RSA_ENCRYPTION
+*/
+static SECStatus
+DecryptSigBlock(int *tagp, unsigned char *digest, SECKEYPublicKey *key,
+ SECItem *sig, char *wincx)
+{
+ SGNDigestInfo *di = NULL;
+ unsigned char *dsig = NULL;
+ unsigned char *buf = NULL;
+ SECStatus rv;
+ SECOidTag tag;
+ SECItem it;
+
+ if (key == NULL) goto loser;
+
+ it.len = SECKEY_PublicKeyStrength(key);
+ if (!it.len) goto loser;
+ it.data = buf = (unsigned char *)PORT_Alloc(it.len);
+ if (!buf) goto loser;
+
+ /* Decrypt signature block */
+ dsig = (unsigned char*) PORT_Alloc(sig->len);
+ if (dsig == NULL) goto loser;
+
+ /* decrypt the block */
+ rv = PK11_VerifyRecover(key, sig, &it, wincx);
+ if (rv != SECSuccess) goto loser;
+
+ di = SGN_DecodeDigestInfo(&it);
+ if (di == NULL) goto sigloser;
+
+ /*
+ ** Finally we have the digest info; now we can extract the algorithm
+ ** ID and the signature block
+ */
+ tag = SECOID_GetAlgorithmTag(&di->digestAlgorithm);
+ /* XXX Check that tag is an appropriate algorithm? */
+ if (di->digest.len > 32) {
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ goto loser;
+ }
+ PORT_Memcpy(digest, di->digest.data, di->digest.len);
+ *tagp = tag;
+ goto done;
+
+ sigloser:
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+
+ loser:
+ rv = SECFailure;
+
+ done:
+ if (di != NULL) SGN_DestroyDigestInfo(di);
+ if (dsig != NULL) PORT_Free(dsig);
+ if (buf != NULL) PORT_Free(buf);
+
+ return rv;
+}
+
+typedef enum { VFY_RSA, VFY_DSA} VerifyType;
+
+struct VFYContextStr {
+ int alg;
+ VerifyType type;
+ SECKEYPublicKey *key;
+ /* digest holds the full dsa signature... 40 bytes */
+ unsigned char digest[DSA_SIGNATURE_LEN];
+ void * wincx;
+ void *hashcx;
+ SECHashObject *hashobj;
+};
+
+VFYContext *
+VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag algid,
+ void *wincx)
+{
+ VFYContext *cx;
+ SECStatus rv;
+ SECItem *dsasig = NULL;
+
+ cx = (VFYContext*) PORT_ZAlloc(sizeof(VFYContext));
+ if (cx) {
+ cx->wincx = cx;
+ switch (key->keyType) {
+ case rsaKey:
+ cx->type = VFY_RSA;
+ cx->key = NULL; /* extra safety precautions */
+ rv = DecryptSigBlock(&cx->alg, &cx->digest[0], key, sig, (char*)wincx);
+ break;
+ case fortezzaKey:
+ case dsaKey:
+ cx->type = VFY_DSA;
+ cx->alg = SEC_OID_SHA1;
+ cx->key = SECKEY_CopyPublicKey(key);
+ /* if this is a DER encoded signature, decode it first */
+ if ((algid == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) ||
+ (algid == SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) ||
+ (algid == SEC_OID_ANSIX9_DSA_SIGNATURE)) {
+ dsasig = DSAU_DecodeDerSig(sig);
+ if ((dsasig == NULL) || (dsasig->len != DSA_SIGNATURE_LEN)) {
+ goto loser;
+ }
+ PORT_Memcpy(&cx->digest[0], dsasig->data, dsasig->len);
+ } else {
+ if (sig->len != DSA_SIGNATURE_LEN) {
+ goto loser;
+ }
+ PORT_Memcpy(&cx->digest[0], sig->data, sig->len);
+ }
+ rv = SECSuccess;
+ break;
+ default:
+ rv = SECFailure;
+ break;
+ }
+ if (rv) goto loser;
+ switch (cx->alg) {
+ case SEC_OID_MD2:
+ case SEC_OID_MD5:
+ case SEC_OID_SHA1:
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+ goto loser;
+ }
+ }
+ return cx;
+
+ loser:
+ if (dsasig != NULL)
+ SECITEM_FreeItem(dsasig, PR_TRUE);
+ VFY_DestroyContext(cx, PR_TRUE);
+ return 0;
+}
+
+void
+VFY_DestroyContext(VFYContext *cx, PRBool freeit)
+{
+ if (cx) {
+ if (cx->hashcx != NULL) {
+ (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
+ cx->hashcx = NULL;
+ }
+ if (cx->key) {
+ SECKEY_DestroyPublicKey(cx->key);
+ }
+ if (freeit) {
+ PORT_ZFree(cx, sizeof(VFYContext));
+ }
+ }
+}
+
+SECStatus
+VFY_Begin(VFYContext *cx)
+{
+ if (cx->hashcx != NULL) {
+ (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
+ cx->hashcx = NULL;
+ }
+
+ switch (cx->alg) {
+ case SEC_OID_MD2:
+ cx->hashobj = &SECHashObjects[HASH_AlgMD2];
+ break;
+ case SEC_OID_MD5:
+ cx->hashobj = &SECHashObjects[HASH_AlgMD5];
+ break;
+ case SEC_OID_SHA1:
+ cx->hashobj = &SECHashObjects[HASH_AlgSHA1];
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+ return SECFailure;
+ }
+
+ cx->hashcx = (*cx->hashobj->create)();
+ if (cx->hashcx == NULL)
+ return SECFailure;
+
+ (*cx->hashobj->begin)(cx->hashcx);
+ return SECSuccess;
+}
+
+SECStatus
+VFY_Update(VFYContext *cx, unsigned char *input, unsigned inputLen)
+{
+ if (cx->hashcx == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ (*cx->hashobj->update)(cx->hashcx, input, inputLen);
+ return SECSuccess;
+}
+
+SECStatus
+VFY_End(VFYContext *cx)
+{
+ unsigned char final[32];
+ unsigned part;
+ SECItem hash,sig;
+
+ if (cx->hashcx == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final));
+ switch (cx->type) {
+ case VFY_DSA:
+ sig.data = cx->digest;
+ sig.len = DSA_SIGNATURE_LEN; /* magic size of dsa signature */
+ hash.data = final;
+ hash.len = part;
+ if (PK11_Verify(cx->key,&sig,&hash,cx->wincx) != SECSuccess) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ return SECFailure;
+ }
+ break;
+ case VFY_RSA:
+ if (PORT_Memcmp(final, cx->digest, part)) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ return SECFailure;
+ }
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ return SECFailure; /* shouldn't happen */
+ }
+ return SECSuccess;
+}
+
+/************************************************************************/
+/*
+ * Verify that a previously-computed digest matches a signature.
+ * XXX This should take a parameter that specifies the digest algorithm,
+ * and we should compare that the algorithm found in the DigestInfo
+ * matches it!
+ */
+SECStatus
+VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
+ SECOidTag algid, void *wincx)
+{
+ SECStatus rv;
+ VFYContext *cx;
+
+ rv = SECFailure;
+
+ cx = VFY_CreateContext(key, sig, algid, wincx);
+ if (cx != NULL) {
+ switch (key->keyType) {
+ case rsaKey:
+ if (PORT_Memcmp(digest->data, cx->digest, digest->len)) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ } else {
+ rv = SECSuccess;
+ }
+ break;
+ case fortezzaKey:
+ case dsaKey:
+ if (PK11_Verify(cx->key,sig,digest,wincx) != SECSuccess) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ } else {
+ rv = SECSuccess;
+ }
+ break;
+ default:
+ break;
+ }
+
+ VFY_DestroyContext(cx, PR_TRUE);
+ }
+ return rv;
+}
+
+SECStatus
+VFY_VerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
+ SECItem *sig, SECOidTag algid, void *wincx)
+{
+ SECStatus rv;
+ VFYContext *cx;
+
+ cx = VFY_CreateContext(key, sig, algid, wincx);
+ if (cx == NULL)
+ return SECFailure;
+
+ rv = VFY_Begin(cx);
+ if (rv == SECSuccess) {
+ rv = VFY_Update(cx, buf, len);
+ if (rv == SECSuccess)
+ rv = VFY_End(cx);
+ }
+
+ VFY_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+SEC_VerifyFile(FILE *input, SECKEYPublicKey *key, SECItem *sig,
+ SECOidTag algid, void *wincx)
+{
+ unsigned char buf[1024];
+ SECStatus rv;
+ int nb;
+ VFYContext *cx;
+
+ cx = VFY_CreateContext(key, sig, algid, wincx);
+ if (cx == NULL)
+ rv = SECFailure;
+
+ rv = VFY_Begin(cx);
+ if (rv == SECSuccess) {
+ /*
+ * Now feed the contents of the input file into the digest algorithm,
+ * one chunk at a time, until we have exhausted the input.
+ */
+ for (;;) {
+ if (feof(input))
+ break;
+ nb = fread(buf, 1, sizeof(buf), input);
+ if (nb == 0) {
+ if (ferror(input)) {
+ PORT_SetError(SEC_ERROR_IO);
+ VFY_DestroyContext(cx, PR_TRUE);
+ return SECFailure;
+ }
+ break;
+ }
+ rv = VFY_Update(cx, buf, nb);
+ if (rv != SECSuccess)
+ goto loser;
+ }
+ }
+
+ /* Verify the digest */
+ rv = VFY_End(cx);
+ /* FALL THROUGH */
+
+ loser:
+ VFY_DestroyContext(cx, PR_TRUE);
+ return rv;
+}