Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  crmfdec.c   Sprache: C

 
/* -*- 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/. */


#include "crmf.h"
#include "crmfi.h"
#include "secitem.h"

static CRMFPOPChoice
crmf_get_popchoice_from_der(SECItem *derPOP)
{
    CRMFPOPChoice retChoice;

    switch (derPOP->data[0] & 0x0f) {
        case 0:
            retChoice = crmfRAVerified;
            break;
        case 1:
            retChoice = crmfSignature;
            break;
        case 2:
            retChoice = crmfKeyEncipherment;
            break;
        case 3:
            retChoice = crmfKeyAgreement;
            break;
        default:
            retChoice = crmfNoPOPChoice;
            break;
    }
    return retChoice;
}

static SECStatus
crmf_decode_process_raverified(CRMFCertReqMsg *inCertReqMsg)
{
    CRMFProofOfPossession *pop;
    /* Just set up the structure so that the message structure
     * looks like one that was created using the API
     */

    pop = inCertReqMsg->pop;
    pop->popChoice.raVerified.data = NULL;
    pop->popChoice.raVerified.len = 0;
    return SECSuccess;
}

static SECStatus
crmf_decode_process_signature(CRMFCertReqMsg *inCertReqMsg)
{
    PORT_Assert(inCertReqMsg->poolp);
    if (!inCertReqMsg->poolp) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    return SEC_ASN1Decode(inCertReqMsg->poolp,
                          &inCertReqMsg->pop->popChoice.signature,
                          CRMFPOPOSigningKeyTemplate,
                          (const char *)inCertReqMsg->derPOP.data,
                          inCertReqMsg->derPOP.len);
}

static CRMFPOPOPrivKeyChoice
crmf_get_messagechoice_from_der(SECItem *derPOP)
{
    CRMFPOPOPrivKeyChoice retChoice;

    switch (derPOP->data[2] & 0x0f) {
        case 0:
            retChoice = crmfThisMessage;
            break;
        case 1:
            retChoice = crmfSubsequentMessage;
            break;
        case 2:
            retChoice = crmfDHMAC;
            break;
        default:
            retChoice = crmfNoMessage;
    }
    return retChoice;
}

static SECStatus
crmf_decode_process_popoprivkey(CRMFCertReqMsg *inCertReqMsg)
{
    /* We've got a union, so a pointer to one POPOPrivKey
     * struct is the same as having a pointer to the other
     * one.
     */

    CRMFPOPOPrivKey *popoPrivKey =
        &inCertReqMsg->pop->popChoice.keyEncipherment;
    SECItem *derPOP, privKeyDer;
    SECStatus rv;

    derPOP = &inCertReqMsg->derPOP;
    popoPrivKey->messageChoice = crmf_get_messagechoice_from_der(derPOP);
    if (popoPrivKey->messageChoice == crmfNoMessage) {
        return SECFailure;
    }
    /* If we ever encounter BER encodings of this, we'll get in trouble*/
    switch (popoPrivKey->messageChoice) {
        case crmfThisMessage:
        case crmfDHMAC:
            privKeyDer.type = derPOP->type;
            privKeyDer.data = &derPOP->data[5];
            privKeyDer.len = derPOP->len - 5;
            break;
        case crmfSubsequentMessage:
            privKeyDer.type = derPOP->type;
            privKeyDer.data = &derPOP->data[4];
            privKeyDer.len = derPOP->len - 4;
            break;
        default:
            return SECFailure;
    }

    rv = SECITEM_CopyItem(inCertReqMsg->poolp,
                          &popoPrivKey->message.subsequentMessage,
                          &privKeyDer);

    if (rv != SECSuccess) {
        return rv;
    }

    if (popoPrivKey->messageChoice == crmfThisMessage ||
        popoPrivKey->messageChoice == crmfDHMAC) {

        popoPrivKey->message.thisMessage.len =
            CRMF_BYTES_TO_BITS(privKeyDer.len) - (int)derPOP->data[4];
    }
    return SECSuccess;
}

static SECStatus
crmf_decode_process_keyagreement(CRMFCertReqMsg *inCertReqMsg)
{
    return crmf_decode_process_popoprivkey(inCertReqMsg);
}

static SECStatus
crmf_decode_process_keyencipherment(CRMFCertReqMsg *inCertReqMsg)
{
    SECStatus rv;

    rv = crmf_decode_process_popoprivkey(inCertReqMsg);
    if (rv != SECSuccess) {
        return rv;
    }
    if (inCertReqMsg->pop->popChoice.keyEncipherment.messageChoice ==
        crmfDHMAC) {
        /* Key Encipherment can not use the dhMAC option for
         * POPOPrivKey.
         */

        return SECFailure;
    }
    return SECSuccess;
}

static SECStatus
crmf_decode_process_pop(CRMFCertReqMsg *inCertReqMsg)
{
    SECItem *derPOP;
    PLArenaPool *poolp;
    CRMFProofOfPossession *pop;
    void *mark;
    SECStatus rv;

    derPOP = &inCertReqMsg->derPOP;
    poolp = inCertReqMsg->poolp;
    if (derPOP->data == NULL) {
        /* There is no Proof of Possession field in this message. */
        return SECSuccess;
    }
    mark = PORT_ArenaMark(poolp);
    pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
    if (pop == NULL) {
        goto loser;
    }
    pop->popUsed = crmf_get_popchoice_from_der(derPOP);
    if (pop->popUsed == crmfNoPOPChoice) {
        /* A bad encoding of CRMF.  Not a valid tag was given to the
         * Proof Of Possession field.
         */

        goto loser;
    }
    inCertReqMsg->pop = pop;
    switch (pop->popUsed) {
        case crmfRAVerified:
            rv = crmf_decode_process_raverified(inCertReqMsg);
            break;
        case crmfSignature:
            rv = crmf_decode_process_signature(inCertReqMsg);
            break;
        case crmfKeyEncipherment:
            rv = crmf_decode_process_keyencipherment(inCertReqMsg);
            break;
        case crmfKeyAgreement:
            rv = crmf_decode_process_keyagreement(inCertReqMsg);
            break;
        default:
            rv = SECFailure;
    }
    if (rv != SECSuccess) {
        goto loser;
    }
    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

loser:
    PORT_ArenaRelease(poolp, mark);
    inCertReqMsg->pop = NULL;
    return SECFailure;
}

static SECStatus
crmf_decode_process_single_control(PLArenaPool *poolp,
                                   CRMFControl *inControl)
{
    const SEC_ASN1Template *asn1Template = NULL;

    inControl->tag = SECOID_FindOIDTag(&inControl->derTag);
    asn1Template = crmf_get_pkiarchiveoptions_subtemplate(inControl);

    PORT_Assert(asn1Template != NULL);
    PORT_Assert(poolp != NULL);
    if (!asn1Template || !poolp) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    /* We've got a union, so passing a pointer to one element of the
     * union is the same as passing a pointer to any of the other
     * members of the union.
     */

    return SEC_ASN1Decode(poolp, &inControl->value.archiveOptions,
                          asn1Template, (const char *)inControl->derValue.data,
                          inControl->derValue.len);
}

static SECStatus
crmf_decode_process_controls(CRMFCertReqMsg *inCertReqMsg)
{
    int i, numControls;
    SECStatus rv;
    PLArenaPool *poolp;
    CRMFControl **controls;

    numControls = CRMF_CertRequestGetNumControls(inCertReqMsg->certReq);
    controls = inCertReqMsg->certReq->controls;
    poolp = inCertReqMsg->poolp;
    for (i = 0; i < numControls; i++) {
        rv = crmf_decode_process_single_control(poolp, controls[i]);
        if (rv != SECSuccess) {
            return SECFailure;
        }
    }
    return SECSuccess;
}

static SECStatus
crmf_decode_process_single_reqmsg(CRMFCertReqMsg *inCertReqMsg)
{
    SECStatus rv;

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

    rv = crmf_decode_process_controls(inCertReqMsg);
    if (rv != SECSuccess) {
        goto loser;
    }
    inCertReqMsg->certReq->certTemplate.numExtensions =
        CRMF_CertRequestGetNumberOfExtensions(inCertReqMsg->certReq);
    inCertReqMsg->isDecoded = PR_TRUE;
    rv = SECSuccess;
loser:
    return rv;
}

CRMFCertReqMsg *
CRMF_CreateCertReqMsgFromDER(const char *buf, long len)
{
    PLArenaPool *poolp;
    CRMFCertReqMsg *certReqMsg;
    SECStatus rv;

    poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
    if (poolp == NULL) {
        goto loser;
    }
    certReqMsg = PORT_ArenaZNew(poolp, CRMFCertReqMsg);
    if (certReqMsg == NULL) {
        goto loser;
    }
    certReqMsg->poolp = poolp;
    rv = SEC_ASN1Decode(poolp, certReqMsg, CRMFCertReqMsgTemplate, buf, len);
    if (rv != SECSuccess) {
        goto loser;
    }

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

    return certReqMsg;
loser:
    if (poolp != NULL) {
        PORT_FreeArena(poolp, PR_FALSE);
    }
    return NULL;
}

CRMFCertReqMessages *
CRMF_CreateCertReqMessagesFromDER(const char *buf, long len)
{
    long arenaSize;
    int i;
    SECStatus rv;
    PLArenaPool *poolp;
    CRMFCertReqMessages *certReqMsgs;

    PORT_Assert(buf != NULL);
    /* Wanna make sure the arena is big enough to store all of the requests
     * coming in.  We'll guestimate according to the length of the buffer.
     */

    arenaSize = len + len / 2;
    poolp = PORT_NewArena(arenaSize);
    if (poolp == NULL) {
        return NULL;
    }
    certReqMsgs = PORT_ArenaZNew(poolp, CRMFCertReqMessages);
    if (certReqMsgs == NULL) {
        goto loser;
    }
    certReqMsgs->poolp = poolp;
    rv = SEC_ASN1Decode(poolp, certReqMsgs, CRMFCertReqMessagesTemplate,
                        buf, len);
    if (rv != SECSuccess) {
        goto loser;
    }
    for (i = 0; certReqMsgs->messages[i] != NULL; i++) {
        /* The sub-routines expect the individual messages to have
         * an arena.  We'll give them one temporarily.
         */

        certReqMsgs->messages[i]->poolp = poolp;
        rv = crmf_decode_process_single_reqmsg(certReqMsgs->messages[i]);
        if (rv != SECSuccess) {
            goto loser;
        }
        certReqMsgs->messages[i]->poolp = NULL;
    }
    return certReqMsgs;

loser:
    PORT_FreeArena(poolp, PR_FALSE);
    return NULL;
}

Messung V0.5
C=98 H=78 G=88

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge