/* -*- Mode: C; tab-width: 8 -*-*/
/* 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/. */

/*
 * This file will contain all routines dealing with creating a
 * CMMFCertRepContent structure through Create/Set functions.
 */

#include "cmmf.h"
#include "cmmfi.h"
#include "crmf.h"
#include "crmfi.h"
#include "secitem.h"
#include "secder.h"

CMMFCertRepContent *
CMMF_CreateCertRepContent(void)
{
    CMMFCertRepContent *retCertRep;
    PLArenaPool *poolp;

    poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
    if (poolp == NULL) {
        goto loser;
    }
    retCertRep = PORT_ArenaZNew(poolp, CMMFCertRepContent);
    if (retCertRep == NULL) {
        goto loser;
    }
    retCertRep->poolp = poolp;
    return retCertRep;
loser:
    if (poolp != NULL) {
        PORT_FreeArena(poolp, PR_FALSE);
    }
    return NULL;
}

SECStatus
cmmf_CertOrEncCertSetCertificate(CMMFCertOrEncCert *certOrEncCert,
                                 PLArenaPool *poolp,
                                 CERTCertificate *inCert)
{
    SECItem *derDest = NULL;
    SECStatus rv = SECFailure;

    if (inCert->derCert.data == NULL) {
        derDest = SEC_ASN1EncodeItem(NULL, NULL, inCert,
                                     CMMFCertOrEncCertCertificateTemplate);
        if (derDest == NULL) {
            goto loser;
        }
    } else {
        derDest = SECITEM_DupItem(&inCert->derCert);
        if (derDest == NULL) {
            goto loser;
        }
    }
    PORT_Assert(certOrEncCert->cert.certificate == NULL);
    certOrEncCert->cert.certificate = CERT_DupCertificate(inCert);
    certOrEncCert->choice = cmmfCertificate;
    if (poolp != NULL) {
        rv = SECITEM_CopyItem(poolp, &certOrEncCert->derValue, derDest);
        if (rv != SECSuccess) {
            goto loser;
        }
    } else {
        certOrEncCert->derValue = *derDest;
    }
    PORT_Free(derDest);
    return SECSuccess;
loser:
    if (derDest != NULL) {
        SECITEM_FreeItem(derDest, PR_TRUE);
    }
    return rv;
}

SECStatus
cmmf_ExtractCertsFromList(CERTCertList *inCertList,
                          PLArenaPool *poolp,
                          CERTCertificate ***certArray)
{
    CERTCertificate **arrayLocalCopy;
    CERTCertListNode *node;
    int numNodes = 0, i;

    for (node = CERT_LIST_HEAD(inCertList); !CERT_LIST_END(node, inCertList);
         node = CERT_LIST_NEXT(node)) {
        numNodes++;
    }

    arrayLocalCopy = *certArray = (poolp == NULL) ? PORT_NewArray(CERTCertificate *, (numNodes + 1)) : PORT_ArenaNewArray(poolp, CERTCertificate *, (numNodes + 1));
    if (arrayLocalCopy == NULL) {
        return SECFailure;
    }
    for (node = CERT_LIST_HEAD(inCertList), i = 0;
         !CERT_LIST_END(node, inCertList);
         node = CERT_LIST_NEXT(node), i++) {
        arrayLocalCopy[i] = CERT_DupCertificate(node->cert);
        if (arrayLocalCopy[i] == NULL) {
            int j;

            for (j = 0; j < i; j++) {
                CERT_DestroyCertificate(arrayLocalCopy[j]);
            }
            if (poolp == NULL) {
                PORT_Free(arrayLocalCopy);
            }
            *certArray = NULL;
            return SECFailure;
        }
    }
    arrayLocalCopy[numNodes] = NULL;
    return SECSuccess;
}

SECStatus
CMMF_CertRepContentSetCertResponses(CMMFCertRepContent *inCertRepContent,
                                    CMMFCertResponse **inCertResponses,
                                    int inNumResponses)
{
    PLArenaPool *poolp;
    CMMFCertResponse **respArr, *newResp;
    void *mark;
    SECStatus rv;
    int i;

    PORT_Assert(inCertRepContent != NULL &&
                inCertResponses != NULL &&
                inNumResponses > 0);
    if (inCertRepContent == NULL ||
        inCertResponses == NULL ||
        inCertRepContent->response != NULL) {
        return SECFailure;
    }
    poolp = inCertRepContent->poolp;
    mark = PORT_ArenaMark(poolp);
    respArr = inCertRepContent->response =
        PORT_ArenaZNewArray(poolp, CMMFCertResponse *, (inNumResponses + 1));
    if (respArr == NULL) {
        goto loser;
    }
    for (i = 0; i < inNumResponses; i++) {
        newResp = PORT_ArenaZNew(poolp, CMMFCertResponse);
        if (newResp == NULL) {
            goto loser;
        }
        rv = cmmf_CopyCertResponse(poolp, newResp, inCertResponses[i]);
        if (rv != SECSuccess) {
            goto loser;
        }
        respArr[i] = newResp;
    }
    respArr[inNumResponses] = NULL;
    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

loser:
    PORT_ArenaRelease(poolp, mark);
    return SECFailure;
}

CMMFCertResponse *
CMMF_CreateCertResponse(long inCertReqId)
{
    SECItem *dummy;
    CMMFCertResponse *newResp;

    newResp = PORT_ZNew(CMMFCertResponse);
    if (newResp == NULL) {
        goto loser;
    }
    dummy = SEC_ASN1EncodeInteger(NULL, &newResp->certReqId, inCertReqId);
    if (dummy != &newResp->certReqId) {
        goto loser;
    }
    return newResp;

loser:
    if (newResp != NULL) {
        CMMF_DestroyCertResponse(newResp);
    }
    return NULL;
}

SECStatus
CMMF_CertResponseSetPKIStatusInfoStatus(CMMFCertResponse *inCertResp,
                                        CMMFPKIStatus inPKIStatus)
{
    PORT_Assert(inCertResp != NULL && inPKIStatus >= cmmfGranted &&
                inPKIStatus < cmmfNumPKIStatus);

    if (inCertResp == NULL) {
        return SECFailure;
    }
    return cmmf_PKIStatusInfoSetStatus(&inCertResp->status, NULL,
                                       inPKIStatus);
}

SECStatus
CMMF_CertResponseSetCertificate(CMMFCertResponse *inCertResp,
                                CERTCertificate *inCertificate)
{
    CMMFCertifiedKeyPair *keyPair = NULL;
    SECStatus rv = SECFailure;

    PORT_Assert(inCertResp != NULL && inCertificate != NULL);
    if (inCertResp == NULL || inCertificate == NULL) {
        return SECFailure;
    }
    if (inCertResp->certifiedKeyPair == NULL) {
        keyPair = inCertResp->certifiedKeyPair =
            PORT_ZNew(CMMFCertifiedKeyPair);
    } else {
        keyPair = inCertResp->certifiedKeyPair;
    }
    if (keyPair == NULL) {
        goto loser;
    }
    rv = cmmf_CertOrEncCertSetCertificate(&keyPair->certOrEncCert, NULL,
                                          inCertificate);
    if (rv != SECSuccess) {
        goto loser;
    }
    return SECSuccess;
loser:
    if (keyPair) {
        if (keyPair->certOrEncCert.derValue.data) {
            PORT_Free(keyPair->certOrEncCert.derValue.data);
        }
        PORT_Free(keyPair);
    }
    return rv;
}

SECStatus
CMMF_CertRepContentSetCAPubs(CMMFCertRepContent *inCertRepContent,
                             CERTCertList *inCAPubs)
{
    PLArenaPool *poolp;
    void *mark;
    SECStatus rv;

    PORT_Assert(inCertRepContent != NULL &&
                inCAPubs != NULL &&
                inCertRepContent->caPubs == NULL);

    if (inCertRepContent == NULL ||
        inCAPubs == NULL || inCertRepContent == NULL) {
        return SECFailure;
    }

    poolp = inCertRepContent->poolp;
    mark = PORT_ArenaMark(poolp);

    rv = cmmf_ExtractCertsFromList(inCAPubs, poolp,
                                   &inCertRepContent->caPubs);

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

CERTCertificate *
CMMF_CertifiedKeyPairGetCertificate(CMMFCertifiedKeyPair *inCertKeyPair,
                                    CERTCertDBHandle *inCertdb)
{
    PORT_Assert(inCertKeyPair != NULL);
    if (inCertKeyPair == NULL) {
        return NULL;
    }
    return cmmf_CertOrEncCertGetCertificate(&inCertKeyPair->certOrEncCert,
                                            inCertdb);
}
