jarsign.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 378 行

C
378
字号
/* * 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"/* from libevent.h */typedef void (*ETVoidPtrFunc) (void * data);#ifdef MOZILLA_CLIENT_OLDextern 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 * */SECKEYKeyDBHandle *jar_open_key_database (void)  {  SECKEYKeyDBHandle *keydb;  keydb = SECKEY_GetDefaultKeyDB();  if (keydb == NULL)    { /* open by file if this fails, if jartool is to call this */ ; }  return keydb;  }int jar_close_key_database (SECKEYKeyDBHandle *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, SECKEYKeyDBHandle *keydb,        CERTCertificate *cert, char *password, JAR_FILE infp, JAR_FILE outfp)  {  int nb;  unsigned char buffer [4096], digestdata[32];  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 = &SECHashObjects [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;  }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?