/* 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/. */
#include "secdig.h"

#include "secoid.h"
#include "secasn1.h"
#include "secerr.h"

/*
 * XXX Want to have a SGN_DecodeDigestInfo, like:
 *  SGNDigestInfo *SGN_DecodeDigestInfo(SECItem *didata);
 * that creates a pool and allocates from it and decodes didata into
 * the newly allocated DigestInfo structure.  Then fix secvfy.c (it
 * will no longer need an arena itself) to call this and then call
 * DestroyDigestInfo when it is done, then can remove the old template
 * above and keep our new template static and "hidden".
 */

/*
 * XXX It might be nice to combine the following two functions (create
 * and encode).  I think that is all anybody ever wants to do anyway.
 */

SECItem *
SGN_EncodeDigestInfo(PLArenaPool *poolp, SECItem *dest, SGNDigestInfo *diginfo)
{
    return SEC_ASN1EncodeItem(poolp, dest, diginfo, sgn_DigestInfoTemplate);
}

SGNDigestInfo *
SGN_CreateDigestInfo(SECOidTag algorithm, const unsigned char *sig,
                     unsigned len)
{
    SGNDigestInfo *di;
    SECStatus rv;
    PLArenaPool *arena;
    SECItem *null_param;
    SECItem dummy_value;

    switch (algorithm) {
        case SEC_OID_MD2:
        case SEC_OID_MD5:
        case SEC_OID_SHA1:
        case SEC_OID_SHA224:
        case SEC_OID_SHA256:
        case SEC_OID_SHA384:
        case SEC_OID_SHA512:
            break;
        default:
            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
            return NULL;
    }

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
        return NULL;
    }

    di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
    if (di == NULL) {
        PORT_FreeArena(arena, PR_FALSE);
        return NULL;
    }

    di->arena = arena;

    /*
     * PKCS #1 specifies that the AlgorithmID must have a NULL parameter
     * (as opposed to no parameter at all).
     */
    dummy_value.data = NULL;
    dummy_value.len = 0;
    null_param = SEC_ASN1EncodeItem(NULL, NULL, &dummy_value, SEC_NullTemplate);
    if (null_param == NULL) {
        goto loser;
    }

    rv = SECOID_SetAlgorithmID(arena, &di->digestAlgorithm, algorithm,
                               null_param);

    SECITEM_FreeItem(null_param, PR_TRUE);

    if (rv != SECSuccess) {
        goto loser;
    }

    di->digest.data = (unsigned char *)PORT_ArenaAlloc(arena, len);
    if (di->digest.data == NULL) {
        goto loser;
    }

    di->digest.len = len;
    PORT_Memcpy(di->digest.data, sig, len);
    return di;

loser:
    SGN_DestroyDigestInfo(di);
    return NULL;
}

SGNDigestInfo *
SGN_DecodeDigestInfo(SECItem *didata)
{
    PLArenaPool *arena;
    SGNDigestInfo *di;
    SECStatus rv = SECFailure;
    SECItem diCopy = { siBuffer, NULL, 0 };

    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
    if (arena == NULL)
        return NULL;

    rv = SECITEM_CopyItem(arena, &diCopy, didata);
    if (rv != SECSuccess) {
        PORT_FreeArena(arena, PR_FALSE);
        return NULL;
    }

    di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
    if (di != NULL) {
        di->arena = arena;
        rv = SEC_QuickDERDecodeItem(arena, di, sgn_DigestInfoTemplate, &diCopy);
    }

    if ((di == NULL) || (rv != SECSuccess)) {
        PORT_FreeArena(arena, PR_FALSE);
        di = NULL;
    }

    return di;
}

void
SGN_DestroyDigestInfo(SGNDigestInfo *di)
{
    if (di && di->arena) {
        PORT_FreeArena(di->arena, PR_FALSE);
    }

    return;
}

SECStatus
SGN_CopyDigestInfo(PLArenaPool *poolp, SGNDigestInfo *a, SGNDigestInfo *b)
{
    SECStatus rv;
    void *mark;

    if ((poolp == NULL) || (a == NULL) || (b == NULL))
        return SECFailure;

    mark = PORT_ArenaMark(poolp);
    a->arena = poolp;
    rv = SECOID_CopyAlgorithmID(poolp, &a->digestAlgorithm,
                                &b->digestAlgorithm);
    if (rv == SECSuccess)
        rv = SECITEM_CopyItem(poolp, &a->digest, &b->digest);

    if (rv != SECSuccess) {
        PORT_ArenaRelease(poolp, mark);
    } else {
        PORT_ArenaUnmark(poolp, mark);
    }

    return rv;
}

SECComparison
SGN_CompareDigestInfo(SGNDigestInfo *a, SGNDigestInfo *b)
{
    SECComparison rv;

    /* Check signature algorithm's */
    rv = SECOID_CompareAlgorithmID(&a->digestAlgorithm, &b->digestAlgorithm);
    if (rv)
        return rv;

    /* Compare signature block length's */
    rv = SECITEM_CompareItem(&a->digest, &b->digest);
    return rv;
}
