Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/nss/lib/pkcs7/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 19 kB image not shown  

Quelle  p7common.c   Sprache: C

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


/*
 * PKCS7 implementation -- the exported parts that are used whether
 * creating or decoding.
 */


#include "p7local.h"

#include "cert.h"
#include "secitem.h"
#include "secoid.h"
#include "pk11func.h"

/*
 * Find out (saving pointer to lookup result for future reference)
 * and return the inner content type.
 */

SECOidTag
SEC_PKCS7ContentType(SEC_PKCS7ContentInfo *cinfo)
{
    if (cinfo->contentTypeTag == NULL)
        cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));

    if (cinfo->contentTypeTag == NULL)
        return SEC_OID_UNKNOWN;

    return cinfo->contentTypeTag->offset;
}

/*
 * Destroy a PKCS7 contentInfo and all of its sub-pieces.
 */

void
SEC_PKCS7DestroyContentInfo(SEC_PKCS7ContentInfo *cinfo)
{
    SECOidTag kind;
    CERTCertificate **certs;
    CERTCertificateList **certlists;
    SEC_PKCS7SignerInfo **signerinfos;
    SEC_PKCS7RecipientInfo **recipientinfos;

    PORT_Assert(cinfo->refCount > 0);
    if (cinfo->refCount <= 0)
        return;

    cinfo->refCount--;
    if (cinfo->refCount > 0)
        return;

    certs = NULL;
    certlists = NULL;
    recipientinfos = NULL;
    signerinfos = NULL;

    kind = SEC_PKCS7ContentType(cinfo);
    switch (kind) {
        case SEC_OID_PKCS7_ENVELOPED_DATA: {
            SEC_PKCS7EnvelopedData *edp;

            edp = cinfo->content.envelopedData;
            if (edp != NULL) {
                recipientinfos = edp->recipientInfos;
            }
        } break;
        case SEC_OID_PKCS7_SIGNED_DATA: {
            SEC_PKCS7SignedData *sdp;

            sdp = cinfo->content.signedData;
            if (sdp != NULL) {
                certs = sdp->certs;
                certlists = sdp->certLists;
                signerinfos = sdp->signerInfos;
            }
        } break;
        case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: {
            SEC_PKCS7SignedAndEnvelopedData *saedp;

            saedp = cinfo->content.signedAndEnvelopedData;
            if (saedp != NULL) {
                certs = saedp->certs;
                certlists = saedp->certLists;
                recipientinfos = saedp->recipientInfos;
                signerinfos = saedp->signerInfos;
                if (saedp->sigKey != NULL)
                    PK11_FreeSymKey(saedp->sigKey);
            }
        } break;
        default:
            /* XXX Anything else that needs to be "manually" freed/destroyed? */
            break;
    }

    if (certs != NULL) {
        CERTCertificate *cert;

        while ((cert = *certs++) != NULL) {
            CERT_DestroyCertificate(cert);
        }
    }

    if (certlists != NULL) {
        CERTCertificateList *certlist;

        while ((certlist = *certlists++) != NULL) {
            CERT_DestroyCertificateList(certlist);
        }
    }

    if (recipientinfos != NULL) {
        SEC_PKCS7RecipientInfo *ri;

        while ((ri = *recipientinfos++) != NULL) {
            if (ri->cert != NULL)
                CERT_DestroyCertificate(ri->cert);
        }
    }

    if (signerinfos != NULL) {
        SEC_PKCS7SignerInfo *si;

        while ((si = *signerinfos++) != NULL) {
            if (si->cert != NULL)
                CERT_DestroyCertificate(si->cert);
            if (si->certList != NULL)
                CERT_DestroyCertificateList(si->certList);
        }
    }

    if (cinfo->poolp != NULL) {
        PORT_FreeArena(cinfo->poolp, PR_FALSE); /* XXX clear it? */
    }
}

/*
 * Return a copy of the given contentInfo.  The copy may be virtual
 * or may be real -- either way, the result needs to be passed to
 * SEC_PKCS7DestroyContentInfo later (as does the original).
 */

SEC_PKCS7ContentInfo *
SEC_PKCS7CopyContentInfo(SEC_PKCS7ContentInfo *cinfo)
{
    if (cinfo == NULL)
        return NULL;

    PORT_Assert(cinfo->refCount > 0);

    if (cinfo->created) {
        /*
         * Want to do a real copy of these; otherwise subsequent
         * changes made to either copy are likely to be a surprise.
         * XXX I suspect that this will not actually be called for yet,
         * which is why the assert, so to notice if it is...
         */

        PORT_Assert(0);
        /*
         * XXX Create a new pool here, and copy everything from
         * within.  For cert stuff, need to call the appropriate
         * copy functions, etc.
         */

    }

    cinfo->refCount++;
    return cinfo;
}

/*
 * Return a pointer to the actual content.  In the case of those types
 * which are encrypted, this returns the *plain* content.
 * XXX Needs revisiting if/when we handle nested encrypted types.
 */

SECItem *
SEC_PKCS7GetContent(SEC_PKCS7ContentInfo *cinfo)
{
    SECOidTag kind;

    kind = SEC_PKCS7ContentType(cinfo);
    switch (kind) {
        case SEC_OID_PKCS7_DATA:
            return cinfo->content.data;
        case SEC_OID_PKCS7_DIGESTED_DATA: {
            SEC_PKCS7DigestedData *digd;

            digd = cinfo->content.digestedData;
            if (digd == NULL)
                break;
            return SEC_PKCS7GetContent(&(digd->contentInfo));
        }
        case SEC_OID_PKCS7_ENCRYPTED_DATA: {
            SEC_PKCS7EncryptedData *encd;

            encd = cinfo->content.encryptedData;
            if (encd == NULL)
                break;
            return &(encd->encContentInfo.plainContent);
        }
        case SEC_OID_PKCS7_ENVELOPED_DATA: {
            SEC_PKCS7EnvelopedData *envd;

            envd = cinfo->content.envelopedData;
            if (envd == NULL)
                break;
            return &(envd->encContentInfo.plainContent);
        }
        case SEC_OID_PKCS7_SIGNED_DATA: {
            SEC_PKCS7SignedData *sigd;

            sigd = cinfo->content.signedData;
            if (sigd == NULL)
                break;
            return SEC_PKCS7GetContent(&(sigd->contentInfo));
        }
        case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: {
            SEC_PKCS7SignedAndEnvelopedData *saed;

            saed = cinfo->content.signedAndEnvelopedData;
            if (saed == NULL)
                break;
            return &(saed->encContentInfo.plainContent);
        }
        default:
            PORT_Assert(0);
            break;
    }

    return NULL;
}

/*
 * XXX Fix the placement and formatting of the
 * following routines (i.e. make them consistent with the rest of
 * the pkcs7 code -- I think some/many belong in other files and
 * they all need a formatting/style rehaul)
 */


/* retrieve the algorithm identifier for encrypted data.
 * the identifier returned is a copy of the algorithm identifier
 * in the content info and needs to be freed after being used.
 *
 *   cinfo is the content info for which to retrieve the
 *     encryption algorithm.
 *
 * if the content info is not encrypted data or an error
 * occurs NULL is returned.
 */

SECAlgorithmID *
SEC_PKCS7GetEncryptionAlgorithm(SEC_PKCS7ContentInfo *cinfo)
{
    SECAlgorithmID *alg = 0;
    switch (SEC_PKCS7ContentType(cinfo)) {
        case SEC_OID_PKCS7_ENCRYPTED_DATA:
            alg = &cinfo->content.encryptedData->encContentInfo.contentEncAlg;
            break;
        case SEC_OID_PKCS7_ENVELOPED_DATA:
            alg = &cinfo->content.envelopedData->encContentInfo.contentEncAlg;
            break;
        case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
            alg = &cinfo->content.signedAndEnvelopedData
                       ->encContentInfo.contentEncAlg;
            break;
        default:
            alg = 0;
            break;
    }

    return alg;
}

/* set the content of the content info.  For data content infos,
 * the data is set.  For encrytped content infos, the plainContent
 * is set, and is expected to be encrypted later.
 *
 * cinfo is the content info where the data will be set
 *
 * buf is a buffer of the data to set
 *
 * len is the length of the data being set.
 *
 * in the event of an error, SECFailure is returned.  SECSuccess
 * indicates the content was successfully set.
 */

SECStatus
SEC_PKCS7SetContent(SEC_PKCS7ContentInfo *cinfo,
                    const char *buf,
                    unsigned long len)
{
    SECOidTag cinfo_type;
    SECStatus rv;
    SECItem content;
    SECOidData *contentTypeTag = NULL;

    content.type = siBuffer;
    content.data = (unsigned char *)buf;
    content.len = len;

    cinfo_type = SEC_PKCS7ContentType(cinfo);

    /* set inner content */
    switch (cinfo_type) {
        case SEC_OID_PKCS7_SIGNED_DATA:
            if (content.len > 0) {
                /* we "leak" the old content here, but as it's all in the pool */
                /* it does not really matter */

                /* create content item if necessary */
                if (cinfo->content.signedData->contentInfo.content.data == NULL)
                    cinfo->content.signedData->contentInfo.content.data = SECITEM_AllocItem(cinfo->poolp, NULL, 0);
                rv = SECITEM_CopyItem(cinfo->poolp,
                                      cinfo->content.signedData->contentInfo.content.data,
                                      &content);
            } else {
                cinfo->content.signedData->contentInfo.content.data->data = NULL;
                cinfo->content.signedData->contentInfo.content.data->len = 0;
                rv = SECSuccess;
            }
            if (rv == SECFailure)
                goto loser;

            break;
        case SEC_OID_PKCS7_ENCRYPTED_DATA:
            /* XXX this forces the inner content type to be "data" */
            /* do we really want to override without asking or reason? */
            contentTypeTag = SECOID_FindOIDByTag(SEC_OID_PKCS7_DATA);
            if (contentTypeTag == NULL)
                goto loser;
            rv = SECITEM_CopyItem(cinfo->poolp,
                                  &(cinfo->content.encryptedData->encContentInfo.contentType),
                                  &(contentTypeTag->oid));
            if (rv == SECFailure)
                goto loser;
            if (content.len > 0) {
                rv = SECITEM_CopyItem(cinfo->poolp,
                                      &(cinfo->content.encryptedData->encContentInfo.plainContent),
                                      &content);
            } else {
                cinfo->content.encryptedData->encContentInfo.plainContent.data = NULL;
                cinfo->content.encryptedData->encContentInfo.encContent.data = NULL;
                cinfo->content.encryptedData->encContentInfo.plainContent.len = 0;
                cinfo->content.encryptedData->encContentInfo.encContent.len = 0;
                rv = SECSuccess;
            }
            if (rv == SECFailure)
                goto loser;
            break;
        case SEC_OID_PKCS7_DATA:
            cinfo->content.data = (SECItem *)PORT_ArenaZAlloc(cinfo->poolp,
                                                              sizeof(SECItem));
            if (cinfo->content.data == NULL)
                goto loser;
            if (content.len > 0) {
                rv = SECITEM_CopyItem(cinfo->poolp,
                                      cinfo->content.data, &content);
            } else {
                /* handle case with NULL content */
                rv = SECSuccess;
            }
            if (rv == SECFailure)
                goto loser;
            break;
        default:
            goto loser;
    }

    return SECSuccess;

loser:

    return SECFailure;
}

/* the content of an encrypted data content info is encrypted.
 * it is assumed that for encrypted data, that the data has already
 * been set and is in the "plainContent" field of the content info.
 *
 * cinfo is the content info to encrypt
 *
 * key is the key with which to perform the encryption.  if the
 *     algorithm is a password based encryption algorithm, the
 *     key is actually a password which will be processed per
 *     PKCS #5.
 *
 * in the event of an error, SECFailure is returned.  SECSuccess
 * indicates a success.
 */

SECStatus
SEC_PKCS7EncryptContents(PLArenaPool *poolp,
                         SEC_PKCS7ContentInfo *cinfo,
                         SECItem *key,
                         void *wincx)
{
    SECAlgorithmID *algid = NULL;
    SECItem *src;
    SECItem *dest;
    SECItem *blocked_data = NULL;
    void *mark;
    void *cx;
    PK11SymKey *eKey = NULL;
    PK11SlotInfo *slot = NULL;

    CK_MECHANISM_TYPE cryptoMechType;
    int bs;
    SECStatus rv = SECFailure;
    SECItem *c_param = NULL;

    if ((cinfo == NULL) || (key == NULL))
        return SECFailure;

    if (SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA)
        return SECFailure;

    algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo);
    if (algid == NULL)
        return SECFailure;

    if (poolp == NULL)
        poolp = cinfo->poolp;

    mark = PORT_ArenaMark(poolp);

    src = &cinfo->content.encryptedData->encContentInfo.plainContent;
    dest = &cinfo->content.encryptedData->encContentInfo.encContent;
    dest->data = (unsigned char *)PORT_ArenaZAlloc(poolp, (src->len + 64));
    dest->len = (src->len + 64);
    if (dest->data == NULL) {
        rv = SECFailure;
        goto loser;
    }

    slot = PK11_GetInternalKeySlot();
    if (slot == NULL) {
        rv = SECFailure;
        goto loser;
    }

    eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx);
    if (eKey == NULL) {
        rv = SECFailure;
        goto loser;
    }

    cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key);
    if (cryptoMechType == CKM_INVALID_MECHANISM) {
        rv = SECFailure;
        goto loser;
    }

    /* block according to PKCS 8 */
    bs = PK11_GetBlockSize(cryptoMechType, c_param);
    rv = SECSuccess;
    if (bs) {
        char pad_char;
        pad_char = (char)(bs - (src->len % bs));
        if (src->len % bs) {
            rv = SECSuccess;
            blocked_data = PK11_BlockData(src, bs);
            if (blocked_data) {
                PORT_Memset((blocked_data->data + blocked_data->len - (int)pad_char),
                            pad_char, (int)pad_char);
            } else {
                rv = SECFailure;
                goto loser;
            }
        } else {
            blocked_data = SECITEM_DupItem(src);
            if (blocked_data) {
                blocked_data->data = (unsigned char *)PORT_Realloc(
                    blocked_data->data,
                    blocked_data->len + bs);
                if (blocked_data->data) {
                    blocked_data->len += bs;
                    PORT_Memset((blocked_data->data + src->len), (char)bs, bs);
                } else {
                    rv = SECFailure;
                    goto loser;
                }
            } else {
                rv = SECFailure;
                goto loser;
            }
        }
    } else {
        blocked_data = SECITEM_DupItem(src);
        if (!blocked_data) {
            rv = SECFailure;
            goto loser;
        }
    }

    cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT,
                                    eKey, c_param);
    if (cx == NULL) {
        rv = SECFailure;
        goto loser;
    }

    rv = PK11_CipherOp((PK11Context *)cx, dest->data, (int *)(&dest->len),
                       (int)(src->len + 64), blocked_data->data,
                       (int)blocked_data->len);
    PK11_DestroyContext((PK11Context *)cx, PR_TRUE);

loser:
    /* let success fall through */
    if (blocked_data != NULL)
        SECITEM_ZfreeItem(blocked_data, PR_TRUE);

    if (rv == SECFailure)
        PORT_ArenaRelease(poolp, mark);
    else
        PORT_ArenaUnmark(poolp, mark);

    if (eKey != NULL)
        PK11_FreeSymKey(eKey);

    if (slot != NULL)
        PK11_FreeSlot(slot);

    if (c_param != NULL)
        SECITEM_ZfreeItem(c_param, PR_TRUE);

    return rv;
}

/* the content of an encrypted data content info is decrypted.
 * it is assumed that for encrypted data, that the data has already
 * been set and is in the "encContent" field of the content info.
 *
 * cinfo is the content info to decrypt
 *
 * key is the key with which to perform the decryption.  if the
 *     algorithm is a password based encryption algorithm, the
 *     key is actually a password which will be processed per
 *     PKCS #5.
 *
 * in the event of an error, SECFailure is returned.  SECSuccess
 * indicates a success.
 */

SECStatus
SEC_PKCS7DecryptContents(PLArenaPool *poolp,
                         SEC_PKCS7ContentInfo *cinfo,
                         SECItem *key,
                         void *wincx)
{
    SECAlgorithmID *algid = NULL;
    SECStatus rv = SECFailure;
    SECItem *dest, *src;
    void *mark;

    PK11SymKey *eKey = NULL;
    PK11SlotInfo *slot = NULL;
    CK_MECHANISM_TYPE cryptoMechType;
    void *cx;
    SECItem *c_param = NULL;
    int bs;

    if ((cinfo == NULL) || (key == NULL))
        return SECFailure;

    if (SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA)
        return SECFailure;

    algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo);
    if (algid == NULL)
        return SECFailure;

    if (poolp == NULL)
        poolp = cinfo->poolp;

    mark = PORT_ArenaMark(poolp);

    src = &cinfo->content.encryptedData->encContentInfo.encContent;
    dest = &cinfo->content.encryptedData->encContentInfo.plainContent;
    dest->data = (unsigned char *)PORT_ArenaZAlloc(poolp, (src->len + 64));
    dest->len = (src->len + 64);
    if (dest->data == NULL) {
        rv = SECFailure;
        goto loser;
    }

    slot = PK11_GetInternalKeySlot();
    if (slot == NULL) {
        rv = SECFailure;
        goto loser;
    }

    eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx);
    if (eKey == NULL) {
        rv = SECFailure;
        goto loser;
    }

    cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key);
    if (cryptoMechType == CKM_INVALID_MECHANISM) {
        rv = SECFailure;
        goto loser;
    }

    cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT,
                                    eKey, c_param);
    if (cx == NULL) {
        rv = SECFailure;
        goto loser;
    }

    rv = PK11_CipherOp((PK11Context *)cx, dest->data, (int *)(&dest->len),
                       (int)(src->len + 64), src->data, (int)src->len);
    PK11_DestroyContext((PK11Context *)cx, PR_TRUE);

    bs = PK11_GetBlockSize(cryptoMechType, c_param);
    if (bs) {
        /* check for proper badding in block algorithms.  this assumes
         * RC2 cbc or a DES cbc variant.  and the padding is thus defined
         */

        if (((int)dest->data[dest->len - 1] <= bs) &&
            ((int)dest->data[dest->len - 1] > 0)) {
            dest->len -= (int)dest->data[dest->len - 1];
        } else {
            rv = SECFailure;
            /* set an error ? */
        }
    }

loser:
    /* let success fall through */
    if (rv == SECFailure)
        PORT_ArenaRelease(poolp, mark);
    else
        PORT_ArenaUnmark(poolp, mark);

    if (eKey != NULL)
        PK11_FreeSymKey(eKey);

    if (slot != NULL)
        PK11_FreeSlot(slot);

    if (c_param != NULL)
        SECITEM_ZfreeItem(c_param, PR_TRUE);

    return rv;
}

SECItem **
SEC_PKCS7GetCertificateList(SEC_PKCS7ContentInfo *cinfo)
{
    switch (SEC_PKCS7ContentType(cinfo)) {
        case SEC_OID_PKCS7_SIGNED_DATA:
            return cinfo->content.signedData->rawCerts;
            break;
        default:
            return NULL;
            break;
    }
}

int
SEC_PKCS7GetKeyLength(SEC_PKCS7ContentInfo *cinfo)
{
    if (cinfo->contentTypeTag->offset == SEC_OID_PKCS7_ENVELOPED_DATA)
        return cinfo->content.envelopedData->encContentInfo.keysize;
    else
        return 0;
}

Messung V0.5
C=97 H=77 G=87

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