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


Quelle  crmfpop.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 "secasn1.h"
#include "keyhi.h"
#include "cryptohi.h"

#define CRMF_DEFAULT_ALLOC_SIZE 1024U

SECStatus
crmf_init_encoder_callback_arg(struct crmfEncoderArg *encoderArg,
                               SECItem *derDest)
{
    derDest->data = PORT_ZNewArray(unsigned char, CRMF_DEFAULT_ALLOC_SIZE);
    if (derDest->data == NULL) {
        return SECFailure;
    }
    derDest->len = 0;
    encoderArg->allocatedLen = CRMF_DEFAULT_ALLOC_SIZE;
    encoderArg->buffer = derDest;
    return SECSuccess;
}

/* Caller should release or unmark the pool, instead of doing it here.
** But there are NO callers of this function at present...
*/

SECStatus
CRMF_CertReqMsgSetRAVerifiedPOP(CRMFCertReqMsg *inCertReqMsg)
{
    CRMFProofOfPossession *pop;
    PLArenaPool *poolp;
    void *mark;

    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
    poolp = inCertReqMsg->poolp;
    mark = PORT_ArenaMark(poolp);
    if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice) {
        return SECFailure;
    }
    pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
    if (pop == NULL) {
        goto loser;
    }
    pop->popUsed = crmfRAVerified;
    pop->popChoice.raVerified.data = NULL;
    pop->popChoice.raVerified.len = 0;
    inCertReqMsg->pop = pop;
    (void)SEC_ASN1EncodeItem(poolp, &(inCertReqMsg->derPOP),
                             &(pop->popChoice.raVerified),
                             CRMFRAVerifiedTemplate);
    return SECSuccess;
loser:
    PORT_ArenaRelease(poolp, mark);
    return SECFailure;
}

static SECOidTag
crmf_get_key_sign_tag(SECKEYPublicKey *inPubKey)
{
    /* maintain backward compatibility with older
     * implementations */

    if (inPubKey->keyType == rsaKey) {
        return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
    }
    return SEC_GetSignatureAlgorithmOidTag(inPubKey->keyType, SEC_OID_UNKNOWN);
}

static SECAlgorithmID *
crmf_create_poposignkey_algid(PLArenaPool *poolp,
                              SECKEYPublicKey *inPubKey)
{
    SECAlgorithmID *algID;
    SECOidTag tag;
    SECStatus rv;
    void *mark;

    mark = PORT_ArenaMark(poolp);
    algID = PORT_ArenaZNew(poolp, SECAlgorithmID);
    if (algID == NULL) {
        goto loser;
    }
    tag = crmf_get_key_sign_tag(inPubKey);
    if (tag == SEC_OID_UNKNOWN) {
        goto loser;
    }
    rv = SECOID_SetAlgorithmID(poolp, algID, tag, NULL);
    if (rv != SECSuccess) {
        goto loser;
    }
    PORT_ArenaUnmark(poolp, mark);
    return algID;
loser:
    PORT_ArenaRelease(poolp, mark);
    return NULL;
}

static CRMFPOPOSigningKeyInput *
crmf_create_poposigningkeyinput(PLArenaPool *poolp, CERTCertificate *inCert,
                                CRMFMACPasswordCallback fn, void *arg)
{
    /* PSM isn't going to do this, so we'll fail here for now.*/
    return NULL;
}

void
crmf_generic_encoder_callback(void *arg, const char *buf, unsigned long len,
                              int depth, SEC_ASN1EncodingPart data_kind)
{
    struct crmfEncoderArg *encoderArg = (struct crmfEncoderArg *)arg;
    unsigned char *cursor;

    if (encoderArg->buffer->len + len > encoderArg->allocatedLen) {
        int newSize = encoderArg->buffer->len + CRMF_DEFAULT_ALLOC_SIZE;
        void *dummy = PORT_Realloc(encoderArg->buffer->data, newSize);
        if (dummy == NULL) {
            /* I really want to return an error code here */
            PORT_Assert(0);
            return;
        }
        encoderArg->buffer->data = dummy;
        encoderArg->allocatedLen = newSize;
    }
    cursor = &(encoderArg->buffer->data[encoderArg->buffer->len]);
    if (len) {
        PORT_Memcpy(cursor, buf, len);
    }
    encoderArg->buffer->len += len;
}

static SECStatus
crmf_encode_certreq(CRMFCertRequest *inCertReq, SECItem *derDest)
{
    struct crmfEncoderArg encoderArg;
    SECStatus rv;

    rv = crmf_init_encoder_callback_arg(&encoderArg, derDest);
    if (rv != SECSuccess) {
        return SECFailure;
    }
    return SEC_ASN1Encode(inCertReq, CRMFCertRequestTemplate,
                          crmf_generic_encoder_callback, &encoderArg);
}

static SECStatus
crmf_sign_certreq(PLArenaPool *poolp,
                  CRMFPOPOSigningKey *crmfSignKey,
                  CRMFCertRequest *certReq,
                  SECKEYPrivateKey *inKey,
                  SECAlgorithmID *inAlgId)
{
    SECItem derCertReq = { siBuffer, NULL, 0 };
    SECItem certReqSig = { siBuffer, NULL, 0 };
    SECStatus rv = SECSuccess;

    rv = crmf_encode_certreq(certReq, &derCertReq);
    if (rv != SECSuccess) {
        goto loser;
    }
    rv = SEC_SignData(&certReqSig, derCertReq.data, derCertReq.len,
                      inKey, SECOID_GetAlgorithmTag(inAlgId));
    if (rv != SECSuccess) {
        goto loser;
    }

    /* Now make it a part of the POPOSigningKey */
    rv = SECITEM_CopyItem(poolp, &(crmfSignKey->signature), &certReqSig);
    /* Convert this length to number of bits */
    crmfSignKey->signature.len <<= 3;

loser:
    if (derCertReq.data != NULL) {
        PORT_Free(derCertReq.data);
    }
    if (certReqSig.data != NULL) {
        PORT_Free(certReqSig.data);
    }
    return rv;
}

static SECStatus
crmf_create_poposignkey(PLArenaPool *poolp,
                        CRMFCertReqMsg *inCertReqMsg,
                        CRMFPOPOSigningKeyInput *signKeyInput,
                        SECKEYPrivateKey *inPrivKey,
                        SECAlgorithmID *inAlgID,
                        CRMFPOPOSigningKey *signKey)
{
    CRMFCertRequest *certReq;
    void *mark;
    PRBool useSignKeyInput;
    SECStatus rv;

    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL);
    mark = PORT_ArenaMark(poolp);
    if (signKey == NULL) {
        goto loser;
    }
    certReq = inCertReqMsg->certReq;
    useSignKeyInput = !(CRMF_DoesRequestHaveField(certReq, crmfSubject) &&
                        CRMF_DoesRequestHaveField(certReq, crmfPublicKey));

    if (useSignKeyInput) {
        goto loser;
    } else {
        rv = crmf_sign_certreq(poolp, signKey, certReq, inPrivKey, inAlgID);
        if (rv != SECSuccess) {
            goto loser;
        }
    }
    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;
loser:
    PORT_ArenaRelease(poolp, mark);
    return SECFailure;
}

SECStatus
CRMF_CertReqMsgSetSignaturePOP(CRMFCertReqMsg *inCertReqMsg,
                               SECKEYPrivateKey *inPrivKey,
                               SECKEYPublicKey *inPubKey,
                               CERTCertificate *inCertForInput,
                               CRMFMACPasswordCallback fn,
                               void *arg)
{
    SECAlgorithmID *algID;
    PLArenaPool *poolp;
    SECItem derTemp = { siBuffer, NULL, 0 };
    void *mark;
    SECStatus rv;
    CRMFPOPOSigningKeyInput *signKeyInput = NULL;
    CRMFCertRequest *certReq;
    CRMFProofOfPossession *pop;
    struct crmfEncoderArg encoderArg;

    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL &&
                inCertReqMsg->pop == NULL);
    certReq = inCertReqMsg->certReq;
    if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice ||
        !CRMF_DoesRequestHaveField(certReq, crmfPublicKey)) {
        return SECFailure;
    }
    poolp = inCertReqMsg->poolp;
    mark = PORT_ArenaMark(poolp);
    algID = crmf_create_poposignkey_algid(poolp, inPubKey);

    if (!CRMF_DoesRequestHaveField(certReq, crmfSubject)) {
        signKeyInput = crmf_create_poposigningkeyinput(poolp, inCertForInput,
                                                       fn, arg);
        if (signKeyInput == NULL) {
            goto loser;
        }
    }

    pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
    if (pop == NULL) {
        goto loser;
    }

    rv = crmf_create_poposignkey(poolp, inCertReqMsg,
                                 signKeyInput, inPrivKey, algID,
                                 &(pop->popChoice.signature));
    if (rv != SECSuccess) {
        goto loser;
    }

    pop->popUsed = crmfSignature;
    pop->popChoice.signature.algorithmIdentifier = algID;
    inCertReqMsg->pop = pop;

    rv = crmf_init_encoder_callback_arg(&encoderArg, &derTemp);
    if (rv != SECSuccess) {
        goto loser;
    }
    rv = SEC_ASN1Encode(&pop->popChoice.signature,
                        CRMFPOPOSigningKeyTemplate,
                        crmf_generic_encoder_callback, &encoderArg);
    if (rv != SECSuccess) {
        goto loser;
    }
    rv = SECITEM_CopyItem(poolp, &(inCertReqMsg->derPOP), &derTemp);
    if (rv != SECSuccess) {
        goto loser;
    }
    PORT_Free(derTemp.data);
    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

loser:
    PORT_ArenaRelease(poolp, mark);
    if (derTemp.data != NULL) {
        PORT_Free(derTemp.data);
    }
    return SECFailure;
}

static const SEC_ASN1Template *
crmf_get_popoprivkey_subtemplate(CRMFPOPOPrivKey *inPrivKey)
{
    const SEC_ASN1Template *retTemplate = NULL;

    switch (inPrivKey->messageChoice) {
        case crmfThisMessage:
            retTemplate = CRMFThisMessageTemplate;
            break;
        case crmfSubsequentMessage:
            retTemplate = CRMFSubsequentMessageTemplate;
            break;
        case crmfDHMAC:
            retTemplate = CRMFDHMACTemplate;
            break;
        default:
            retTemplate = NULL;
    }
    return retTemplate;
}

static SECStatus
crmf_encode_popoprivkey(PLArenaPool *poolp,
                        CRMFCertReqMsg *inCertReqMsg,
                        CRMFPOPOPrivKey *popoPrivKey,
                        const SEC_ASN1Template *privKeyTemplate)
{
    struct crmfEncoderArg encoderArg;
    SECItem derTemp = { siBuffer, NULL, 0 };
    SECStatus rv;
    void *mark;
    const SEC_ASN1Template *subDerTemplate;

    mark = PORT_ArenaMark(poolp);
    rv = crmf_init_encoder_callback_arg(&encoderArg, &derTemp);
    if (rv != SECSuccess) {
        goto loser;
    }
    subDerTemplate = crmf_get_popoprivkey_subtemplate(popoPrivKey);
    /* We've got a union, so a pointer to one item is a pointer to
     * all the items in the union.
     */

    rv = SEC_ASN1Encode(&popoPrivKey->message.thisMessage,
                        subDerTemplate,
                        crmf_generic_encoder_callback, &encoderArg);
    if (rv != SECSuccess) {
        goto loser;
    }
    if (encoderArg.allocatedLen > derTemp.len + 2) {
        void *dummy = PORT_Realloc(derTemp.data, derTemp.len + 2);
        if (dummy == NULL) {
            goto loser;
        }
        derTemp.data = dummy;
    }
    PORT_Memmove(&derTemp.data[2], &derTemp.data[0], derTemp.len);
    /* I couldn't figure out how to get the ASN1 encoder to implicitly
     * tag an implicitly tagged der blob.  So I'm putting in the outter-
     * most tag myself. -javi
     */

    derTemp.data[0] = (unsigned char)privKeyTemplate->kind;
    derTemp.data[1] = (unsigned char)derTemp.len;
    derTemp.len += 2;
    rv = SECITEM_CopyItem(poolp, &inCertReqMsg->derPOP, &derTemp);
    if (rv != SECSuccess) {
        goto loser;
    }
    PORT_Free(derTemp.data);
    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;
loser:
    PORT_ArenaRelease(poolp, mark);
    if (derTemp.data) {
        PORT_Free(derTemp.data);
    }
    return SECFailure;
}

static const SEC_ASN1Template *
crmf_get_template_for_privkey(CRMFPOPChoice inChoice)
{
    switch (inChoice) {
        case crmfKeyAgreement:
            return CRMFPOPOKeyAgreementTemplate;
        case crmfKeyEncipherment:
            return CRMFPOPOKeyEnciphermentTemplate;
        default:
            break;
    }
    return NULL;
}

static SECStatus
crmf_add_privkey_thismessage(CRMFCertReqMsg *inCertReqMsg, SECItem *encPrivKey,
                             CRMFPOPChoice inChoice)
{
    PLArenaPool *poolp;
    void *mark;
    CRMFPOPOPrivKey *popoPrivKey;
    CRMFProofOfPossession *pop;
    SECStatus rv;

    PORT_Assert(inCertReqMsg != NULL && encPrivKey != NULL);
    poolp = inCertReqMsg->poolp;
    mark = PORT_ArenaMark(poolp);
    pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
    if (pop == NULL) {
        goto loser;
    }
    pop->popUsed = inChoice;
    /* popChoice is a union, so getting a pointer to one
     * field gives me a pointer to the other fields as
     * well.  This in essence points to both
     * pop->popChoice.keyEncipherment and
     * pop->popChoice.keyAgreement
     */

    popoPrivKey = &pop->popChoice.keyEncipherment;

    rv = SECITEM_CopyItem(poolp, &(popoPrivKey->message.thisMessage),
                          encPrivKey);
    if (rv != SECSuccess) {
        goto loser;
    }
    popoPrivKey->message.thisMessage.len <<= 3;
    popoPrivKey->messageChoice = crmfThisMessage;
    inCertReqMsg->pop = pop;
    rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
                                 crmf_get_template_for_privkey(inChoice));
    if (rv != SECSuccess) {
        goto loser;
    }
    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

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

static SECStatus
crmf_add_privkey_dhmac(CRMFCertReqMsg *inCertReqMsg, SECItem *dhmac,
                       CRMFPOPChoice inChoice)
{
    PLArenaPool *poolp;
    void *mark;
    CRMFPOPOPrivKey *popoPrivKey;
    CRMFProofOfPossession *pop;
    SECStatus rv;

    PORT_Assert(inCertReqMsg != NULL && dhmac != NULL);
    poolp = inCertReqMsg->poolp;
    mark = PORT_ArenaMark(poolp);
    pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
    if (pop == NULL) {
        goto loser;
    }
    pop->popUsed = inChoice;
    popoPrivKey = &pop->popChoice.keyAgreement;

    rv = SECITEM_CopyItem(poolp, &(popoPrivKey->message.dhMAC),
                          dhmac);
    if (rv != SECSuccess) {
        goto loser;
    }
    popoPrivKey->message.dhMAC.len <<= 3;
    popoPrivKey->messageChoice = crmfDHMAC;
    inCertReqMsg->pop = pop;
    rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
                                 crmf_get_template_for_privkey(inChoice));
    if (rv != SECSuccess) {
        goto loser;
    }
    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;

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

static SECStatus
crmf_add_privkey_subseqmessage(CRMFCertReqMsg *inCertReqMsg,
                               CRMFSubseqMessOptions subsequentMessage,
                               CRMFPOPChoice inChoice)
{
    void *mark;
    PLArenaPool *poolp;
    CRMFProofOfPossession *pop;
    CRMFPOPOPrivKey *popoPrivKey;
    SECStatus rv;
    const SEC_ASN1Template *privKeyTemplate;

    if (subsequentMessage == crmfNoSubseqMess) {
        return SECFailure;
    }
    poolp = inCertReqMsg->poolp;
    mark = PORT_ArenaMark(poolp);
    pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
    if (pop == NULL) {
        goto loser;
    }

    pop->popUsed = inChoice;
    /*
     * We have a union, so a pointer to one member of the union
     * is also a member to another member of that same union.
     */

    popoPrivKey = &pop->popChoice.keyEncipherment;

    switch (subsequentMessage) {
        case crmfEncrCert:
            rv = crmf_encode_integer(poolp,
                                     &(popoPrivKey->message.subsequentMessage),
                                     0);
            break;
        case crmfChallengeResp:
            rv = crmf_encode_integer(poolp,
                                     &(popoPrivKey->message.subsequentMessage),
                                     1);
            break;
        default:
            goto loser;
    }
    if (rv != SECSuccess) {
        goto loser;
    }
    popoPrivKey->messageChoice = crmfSubsequentMessage;
    privKeyTemplate = crmf_get_template_for_privkey(inChoice);
    inCertReqMsg->pop = pop;
    rv = crmf_encode_popoprivkey(poolp, inCertReqMsg, popoPrivKey,
                                 privKeyTemplate);

    if (rv != SECSuccess) {
        goto loser;
    }
    PORT_ArenaUnmark(poolp, mark);
    return SECSuccess;
loser:
    PORT_ArenaRelease(poolp, mark);
    return SECFailure;
}

SECStatus
CRMF_CertReqMsgSetKeyEnciphermentPOP(CRMFCertReqMsg *inCertReqMsg,
                                     CRMFPOPOPrivKeyChoice inKeyChoice,
                                     CRMFSubseqMessOptions subseqMess,
                                     SECItem *encPrivKey)
{
    SECStatus rv;

    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
    if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice) {
        return SECFailure;
    }
    switch (inKeyChoice) {
        case crmfThisMessage:
            rv = crmf_add_privkey_thismessage(inCertReqMsg, encPrivKey,
                                              crmfKeyEncipherment);
            break;
        case crmfSubsequentMessage:
            rv = crmf_add_privkey_subseqmessage(inCertReqMsg, subseqMess,
                                                crmfKeyEncipherment);
            break;
        case crmfDHMAC:
        default:
            rv = SECFailure;
    }
    return rv;
}

SECStatus
CRMF_CertReqMsgSetKeyAgreementPOP(CRMFCertReqMsg *inCertReqMsg,
                                  CRMFPOPOPrivKeyChoice inKeyChoice,
                                  CRMFSubseqMessOptions subseqMess,
                                  SECItem *encPrivKey)
{
    SECStatus rv;

    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);
    switch (inKeyChoice) {
        case crmfThisMessage:
            rv = crmf_add_privkey_thismessage(inCertReqMsg, encPrivKey,
                                              crmfKeyAgreement);
            break;
        case crmfSubsequentMessage:
            rv = crmf_add_privkey_subseqmessage(inCertReqMsg, subseqMess,
                                                crmfKeyAgreement);
            break;
        case crmfDHMAC:
            /* In this case encPrivKey should be the calculated dhMac
             * as specified in RFC 2511 */

            rv = crmf_add_privkey_dhmac(inCertReqMsg, encPrivKey,
                                        crmfKeyAgreement);
            break;
        default:
            rv = SECFailure;
    }
    return rv;
}

Messung V0.5
C=98 H=71 G=85

¤ Dauer der Verarbeitung: 0.14 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