summaryrefslogtreecommitdiff
path: root/security/nss/lib/jar/jarsign.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/jar/jarsign.c')
-rw-r--r--security/nss/lib/jar/jarsign.c371
1 files changed, 371 insertions, 0 deletions
diff --git a/security/nss/lib/jar/jarsign.c b/security/nss/lib/jar/jarsign.c
new file mode 100644
index 000000000..5ff7d55de
--- /dev/null
+++ b/security/nss/lib/jar/jarsign.c
@@ -0,0 +1,371 @@
+/*
+ * 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.
+ */
+
+/*
+ * JARSIGN
+ *
+ * Routines used in signing archives.
+ */
+
+
+#define USE_MOZ_THREAD
+
+#include "jar.h"
+#include "jarint.h"
+
+#ifdef USE_MOZ_THREAD
+#include "jarevil.h"
+#endif
+
+#include "pk11func.h"
+#include "sechash.h"
+
+/* from libevent.h */
+typedef void (*ETVoidPtrFunc) (void * data);
+
+#ifdef MOZILLA_CLIENT_OLD
+
+extern void ET_moz_CallFunction (ETVoidPtrFunc fn, void *data);
+
+/* from proto.h */
+/* extern MWContext *XP_FindSomeContext(void); */
+extern void *XP_FindSomeContext(void);
+
+#endif
+
+/* key database wrapper */
+
+/* static SECKEYKeyDBHandle *jar_open_key_database (void); */
+
+/* CHUNQ is our bite size */
+
+#define CHUNQ 64000
+#define FILECHUNQ 32768
+
+/*
+ * J A R _ c a l c u l a t e _ d i g e s t
+ *
+ * Quick calculation of a digest for
+ * the specified block of memory. Will calculate
+ * for all supported algorithms, now MD5.
+ *
+ * This version supports huge pointers for WIN16.
+ *
+ */
+
+JAR_Digest * PR_CALLBACK JAR_calculate_digest (void ZHUGEP *data, long length)
+ {
+ long chunq;
+ JAR_Digest *dig;
+
+ unsigned int md5_length, sha1_length;
+
+ PK11Context *md5 = 0;
+ PK11Context *sha1 = 0;
+
+ dig = (JAR_Digest *) PORT_ZAlloc (sizeof (JAR_Digest));
+
+ if (dig == NULL)
+ {
+ /* out of memory allocating digest */
+ return NULL;
+ }
+
+#if defined(XP_WIN16)
+ PORT_Assert ( !IsBadHugeReadPtr(data, length) );
+#endif
+
+ md5 = PK11_CreateDigestContext (SEC_OID_MD5);
+ sha1 = PK11_CreateDigestContext (SEC_OID_SHA1);
+
+ if (length >= 0)
+ {
+ PK11_DigestBegin (md5);
+ PK11_DigestBegin (sha1);
+
+ do {
+ chunq = length;
+
+#ifdef XP_WIN16
+ if (length > CHUNQ) chunq = CHUNQ;
+
+ /*
+ * If the block of data crosses one or more segment
+ * boundaries then only pass the chunk of data in the
+ * first segment.
+ *
+ * This allows the data to be treated as FAR by the
+ * PK11_DigestOp(...) routine.
+ *
+ */
+
+ if (OFFSETOF(data) + chunq >= 0x10000)
+ chunq = 0x10000 - OFFSETOF(data);
+#endif
+
+ PK11_DigestOp (md5, (unsigned char*)data, chunq);
+ PK11_DigestOp (sha1, (unsigned char*)data, chunq);
+
+ length -= chunq;
+ data = ((char ZHUGEP *) data + chunq);
+ }
+ while (length > 0);
+
+ PK11_DigestFinal (md5, dig->md5, &md5_length, MD5_LENGTH);
+ PK11_DigestFinal (sha1, dig->sha1, &sha1_length, SHA1_LENGTH);
+
+ PK11_DestroyContext (md5, PR_TRUE);
+ PK11_DestroyContext (sha1, PR_TRUE);
+ }
+
+ return dig;
+ }
+
+/*
+ * J A R _ d i g e s t _ f i l e
+ *
+ * Calculates the MD5 and SHA1 digests for a file
+ * present on disk, and returns these in JAR_Digest struct.
+ *
+ */
+
+int JAR_digest_file (char *filename, JAR_Digest *dig)
+ {
+ JAR_FILE fp;
+
+ int num;
+ unsigned char *buf;
+
+ PK11Context *md5 = 0;
+ PK11Context *sha1 = 0;
+
+ unsigned int md5_length, sha1_length;
+
+ buf = (unsigned char *) PORT_ZAlloc (FILECHUNQ);
+ if (buf == NULL)
+ {
+ /* out of memory */
+ return JAR_ERR_MEMORY;
+ }
+
+ if ((fp = JAR_FOPEN (filename, "rb")) == 0)
+ {
+ /* perror (filename); FIX XXX XXX XXX XXX XXX XXX */
+ PORT_Free (buf);
+ return JAR_ERR_FNF;
+ }
+
+ md5 = PK11_CreateDigestContext (SEC_OID_MD5);
+ sha1 = PK11_CreateDigestContext (SEC_OID_SHA1);
+
+ if (md5 == NULL || sha1 == NULL)
+ {
+ /* can't generate digest contexts */
+ PORT_Free (buf);
+ JAR_FCLOSE (fp);
+ return JAR_ERR_GENERAL;
+ }
+
+ PK11_DigestBegin (md5);
+ PK11_DigestBegin (sha1);
+
+ while (1)
+ {
+ if ((num = JAR_FREAD (fp, buf, FILECHUNQ)) == 0)
+ break;
+
+ PK11_DigestOp (md5, buf, num);
+ PK11_DigestOp (sha1, buf, num);
+ }
+
+ PK11_DigestFinal (md5, dig->md5, &md5_length, MD5_LENGTH);
+ PK11_DigestFinal (sha1, dig->sha1, &sha1_length, SHA1_LENGTH);
+
+ PK11_DestroyContext (md5, PR_TRUE);
+ PK11_DestroyContext (sha1, PR_TRUE);
+
+ PORT_Free (buf);
+ JAR_FCLOSE (fp);
+
+ return 0;
+ }
+
+/*
+ * J A R _ o p e n _ k e y _ d a t a b a s e
+ *
+ */
+
+void* jar_open_key_database (void)
+ {
+ return NULL;
+ }
+
+int jar_close_key_database (void *keydb)
+ {
+ /* We never do close it */
+ return 0;
+ }
+
+
+/*
+ * j a r _ c r e a t e _ p k 7
+ *
+ */
+
+static void jar_pk7_out (void *arg, const char *buf, unsigned long len)
+ {
+ JAR_FWRITE ((JAR_FILE) arg, buf, len);
+ }
+
+int jar_create_pk7
+ (CERTCertDBHandle *certdb, void *keydb,
+ CERTCertificate *cert, char *password, JAR_FILE infp, JAR_FILE outfp)
+ {
+ int nb;
+ unsigned char buffer [4096], digestdata[32];
+ const SECHashObject *hashObj;
+ void *hashcx;
+ unsigned int len;
+
+ int status = 0;
+ char *errstring;
+
+ SECItem digest;
+ SEC_PKCS7ContentInfo *cinfo;
+ SECStatus rv;
+
+ void /*MWContext*/ *mw;
+
+ if (outfp == NULL || infp == NULL || cert == NULL)
+ return JAR_ERR_GENERAL;
+
+ /* we sign with SHA */
+ hashObj = HASH_GetHashObject(HASH_AlgSHA1);
+
+ hashcx = (* hashObj->create)();
+ if (hashcx == NULL)
+ return JAR_ERR_GENERAL;
+
+ (* hashObj->begin)(hashcx);
+
+ while (1)
+ {
+ /* nspr2.0 doesn't support feof
+ if (feof (infp)) break; */
+
+ nb = JAR_FREAD (infp, buffer, sizeof (buffer));
+ if (nb == 0)
+ {
+#if 0
+ if (ferror(infp))
+ {
+ /* PORT_SetError(SEC_ERROR_IO); */ /* FIX */
+ (* hashObj->destroy) (hashcx, PR_TRUE);
+ return JAR_ERR_GENERAL;
+ }
+#endif
+ /* eof */
+ break;
+ }
+ (* hashObj->update) (hashcx, buffer, nb);
+ }
+
+ (* hashObj->end) (hashcx, digestdata, &len, 32);
+ (* hashObj->destroy) (hashcx, PR_TRUE);
+
+ digest.data = digestdata;
+ digest.len = len;
+
+ /* signtool must use any old context it can find since it's
+ calling from inside javaland. */
+
+#ifdef MOZILLA_CLIENT_OLD
+ mw = XP_FindSomeContext();
+#else
+ mw = NULL;
+#endif
+
+ PORT_SetError (0);
+
+ cinfo = SEC_PKCS7CreateSignedData
+ (cert, certUsageObjectSigner, NULL,
+ SEC_OID_SHA1, &digest, NULL, (void *) mw);
+
+ if (cinfo == NULL)
+ return JAR_ERR_PK7;
+
+ rv = SEC_PKCS7IncludeCertChain (cinfo, NULL);
+ if (rv != SECSuccess)
+ {
+ status = PORT_GetError();
+ SEC_PKCS7DestroyContentInfo (cinfo);
+ return status;
+ }
+
+ /* Having this here forces signtool to always include
+ signing time. */
+
+ rv = SEC_PKCS7AddSigningTime (cinfo);
+ if (rv != SECSuccess)
+ {
+ /* don't check error */
+ }
+
+ PORT_SetError (0);
+
+#ifdef USE_MOZ_THREAD
+ /* if calling from mozilla */
+ rv = jar_moz_encode
+ (cinfo, jar_pk7_out, outfp,
+ NULL, /* pwfn */ NULL, /* pwarg */ (void *) mw);
+#else
+ /* if calling from mozilla thread*/
+ rv = SEC_PKCS7Encode
+ (cinfo, jar_pk7_out, outfp,
+ NULL, /* pwfn */ NULL, /* pwarg */ (void *) mw):
+#endif
+
+ if (rv != SECSuccess)
+ status = PORT_GetError();
+
+ SEC_PKCS7DestroyContentInfo (cinfo);
+
+ if (rv != SECSuccess)
+ {
+ errstring = JAR_get_error (status);
+ /*XP_TRACE (("Jar signing failed (reason %d = %s)", status, errstring));*/
+ return status < 0 ? status : JAR_ERR_GENERAL;
+ }
+
+ return 0;
+ }