/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 *  JARSIGN
 *
 *  Routines used in signing archives.
 */

#include "jar.h"
#include "jarint.h"
#include "secpkcs7.h"
#include "pk11func.h"
#include "sechash.h"

/* from libevent.h */
typedef void (*ETVoidPtrFunc)(void *data);

/* 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 *data, long length)
{
    PK11Context *md5 = 0;
    PK11Context *sha1 = 0;
    JAR_Digest *dig = PORT_ZNew(JAR_Digest);
    long chunq;
    unsigned int md5_length, sha1_length;

    if (dig == NULL) {
        /* out of memory allocating digest */
        return NULL;
    }

    md5 = PK11_CreateDigestContext(SEC_OID_MD5);
    if (md5 == NULL) {
        PORT_ZFree(dig, sizeof(JAR_Digest));
        return NULL;
    }
    sha1 = PK11_CreateDigestContext(SEC_OID_SHA1);
    if (sha1 == NULL) {
        PK11_DestroyContext(md5, PR_TRUE);
        /* added due to bug Bug 1250214 - prevent the 2nd memory leak */
        PORT_ZFree(dig, sizeof(JAR_Digest));
        return NULL;
    }

    if (length >= 0) {
        PK11_DigestBegin(md5);
        PK11_DigestBegin(sha1);

        do {
            chunq = length;

            PK11_DigestOp(md5, (unsigned char *)data, chunq);
            PK11_DigestOp(sha1, (unsigned char *)data, chunq);
            length -= chunq;
            data = ((char *)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;
    PK11Context *md5 = 0;
    PK11Context *sha1 = 0;
    unsigned char *buf = (unsigned char *)PORT_ZAlloc(FILECHUNQ);
    int num;
    unsigned int md5_length, sha1_length;

    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) {
        if (md5) {
            PK11_DestroyContext(md5, PR_TRUE);
        }
        if (sha1) {
            PK11_DestroyContext(sha1, PR_TRUE);
        }
        /* 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)
{
    SEC_PKCS7ContentInfo *cinfo;
    const SECHashObject *hashObj;
    void *mw = NULL;
    void *hashcx;
    unsigned int len;
    int status = 0;
    SECStatus rv;
    SECItem digest;
    unsigned char digestdata[32];
    unsigned char buffer[4096];

    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) {
        int nb = JAR_FREAD(infp, buffer, sizeof buffer);
        if (nb == 0) { /* 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. */
    PORT_SetError(0);
    cinfo = SEC_PKCS7CreateSignedData(cert, certUsageObjectSigner, NULL,
                                      SEC_OID_SHA1, &digest, NULL, 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);
    /* don't check error */
    PORT_SetError(0);

    /* if calling from mozilla thread*/
    rv = SEC_PKCS7Encode(cinfo, jar_pk7_out, outfp, NULL, NULL, mw);
    if (rv != SECSuccess)
        status = PORT_GetError();
    SEC_PKCS7DestroyContentInfo(cinfo);
    if (rv != SECSuccess) {
        return ((status < 0) ? status : JAR_ERR_GENERAL);
    }
    return 0;
}
