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

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


/*
 * Certificate handling code
 */


#include "seccomon.h"
#include "secder.h"
#include "nssilock.h"
#include "lowkeyi.h"
#include "secasn1.h"
#include "secoid.h"
#include "secerr.h"
#include "pcert.h"

SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)

static const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSubjectPublicKeyInfo) },
    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
      offsetof(NSSLOWCERTSubjectPublicKeyInfo, algorithm),
      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
    { SEC_ASN1_BIT_STRING,
      offsetof(NSSLOWCERTSubjectPublicKeyInfo, subjectPublicKey) },
    { 0 }
};

static const SEC_ASN1Template nsslowcert_RSAPublicKeyTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) },
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey, u.rsa.modulus) },
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey, u.rsa.publicExponent) },
    { 0 }
};
static const SEC_ASN1Template nsslowcert_DSAPublicKeyTemplate[] = {
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey, u.dsa.publicValue) },
    { 0 }
};
static const SEC_ASN1Template nsslowcert_DHPublicKeyTemplate[] = {
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey, u.dh.publicValue) },
    { 0 }
};

/*
 * See bugzilla bug 125359
 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
 * all of the templates above that en/decode into integers must be converted
 * from ASN.1's signed integer type.  This is done by marking either the
 * source or destination (encoding or decoding, respectively) type as
 * siUnsignedInteger.
 */


static void
prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
{
    pubk->u.rsa.modulus.type = siUnsignedInteger;
    pubk->u.rsa.publicExponent.type = siUnsignedInteger;
}

static void
prepare_low_dsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
{
    pubk->u.dsa.publicValue.type = siUnsignedInteger;
    pubk->u.dsa.params.prime.type = siUnsignedInteger;
    pubk->u.dsa.params.subPrime.type = siUnsignedInteger;
    pubk->u.dsa.params.base.type = siUnsignedInteger;
}

static void
prepare_low_dh_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
{
    pubk->u.dh.prime.type = siUnsignedInteger;
    pubk->u.dh.base.type = siUnsignedInteger;
    pubk->u.dh.publicValue.type = siUnsignedInteger;
}

/*
 * simple cert decoder to avoid the cost of asn1 engine
 */

static unsigned char *
nsslowcert_dataStart(unsigned char *buf, unsigned int length,
                     unsigned int *data_length, PRBool includeTag,
                     unsigned char *rettag)
{
    unsigned char tag;
    unsigned int used_length = 0;

    /* need at least a tag and a 1 byte length */
    if (length < 2) {
        return NULL;
    }

    tag = buf[used_length++];

    if (rettag) {
        *rettag = tag;
    }

    /* blow out when we come to the end */
    if (tag == 0) {
        return NULL;
    }

    *data_length = buf[used_length++];

    if (*data_length & 0x80) {
        int len_count = *data_length & 0x7f;

        if (len_count + used_length > length) {
            return NULL;
        }

        *data_length = 0;

        while (len_count-- > 0) {
            *data_length = (*data_length << 8) | buf[used_length++];
        }
    }

    if (*data_length > (length - used_length)) {
        *data_length = length - used_length;
        return NULL;
    }
    if (includeTag)
        *data_length += used_length;

    return (buf + (includeTag ? 0 : used_length));
}

static void
SetTimeType(SECItem *item, unsigned char tagtype)
{
    switch (tagtype) {
        case SEC_ASN1_UTC_TIME:
            item->type = siUTCTime;
            break;

        case SEC_ASN1_GENERALIZED_TIME:
            item->type = siGeneralizedTime;
            break;

        default:
            PORT_Assert(0);
            break;
    }
}

static int
nsslowcert_GetValidityFields(unsigned char *buf, int buf_length,
                             SECItem *notBefore, SECItem *notAfter)
{
    unsigned char tagtype;
    notBefore->data = nsslowcert_dataStart(buf, buf_length,
                                           ¬Before->len, PR_FALSE, &tagtype);
    if (notBefore->data == NULL)
        return SECFailure;
    SetTimeType(notBefore, tagtype);
    buf_length -= (notBefore->data - buf) + notBefore->len;
    buf = notBefore->data + notBefore->len;
    notAfter->data = nsslowcert_dataStart(buf, buf_length,
                                          ¬After->len, PR_FALSE, &tagtype);
    if (notAfter->data == NULL)
        return SECFailure;
    SetTimeType(notAfter, tagtype);
    return SECSuccess;
}

static int
nsslowcert_GetCertFields(unsigned char *cert, int cert_length,
                         SECItem *issuer, SECItem *serial, SECItem *derSN, SECItem *subject,
                         SECItem *valid, SECItem *subjkey, SECItem *extensions)
{
    unsigned char *buf;
    unsigned int buf_length;
    unsigned char *dummy;
    unsigned int dummylen;

    /* get past the signature wrap */
    buf = nsslowcert_dataStart(cert, cert_length, &buf_length, PR_FALSE, NULL);
    if (buf == NULL)
        return SECFailure;
    /* get into the raw cert data */
    buf = nsslowcert_dataStart(buf, buf_length, &buf_length, PR_FALSE, NULL);
    if (buf == NULL)
        return SECFailure;
    /* skip past any optional version number */
    if ((buf[0] & 0xa0) == 0xa0) {
        dummy = nsslowcert_dataStart(buf, buf_length, &dummylen, PR_FALSE, NULL);
        if (dummy == NULL)
            return SECFailure;
        buf_length -= (dummy - buf) + dummylen;
        buf = dummy + dummylen;
    }
    /* serial number */
    if (derSN) {
        derSN->data = nsslowcert_dataStart(buf, buf_length, &derSN->len, PR_TRUE, NULL);
        /* derSN->data  doesn't need to be checked because if it fails so will
         * serial->data below. The only difference between the two calls is
         * whether or not the tags are included in the returned buffer */

    }
    serial->data = nsslowcert_dataStart(buf, buf_length, &serial->len, PR_FALSE, NULL);
    if (serial->data == NULL)
        return SECFailure;
    buf_length -= (serial->data - buf) + serial->len;
    buf = serial->data + serial->len;
    /* skip the OID */
    dummy = nsslowcert_dataStart(buf, buf_length, &dummylen, PR_FALSE, NULL);
    if (dummy == NULL)
        return SECFailure;
    buf_length -= (dummy - buf) + dummylen;
    buf = dummy + dummylen;
    /* issuer */
    issuer->data = nsslowcert_dataStart(buf, buf_length, &issuer->len, PR_TRUE, NULL);
    if (issuer->data == NULL)
        return SECFailure;
    buf_length -= (issuer->data - buf) + issuer->len;
    buf = issuer->data + issuer->len;

    /* only wanted issuer/SN */
    if (valid == NULL) {
        return SECSuccess;
    }
    /* validity */
    valid->data = nsslowcert_dataStart(buf, buf_length, &valid->len, PR_FALSE, NULL);
    if (valid->data == NULL)
        return SECFailure;
    buf_length -= (valid->data - buf) + valid->len;
    buf = valid->data + valid->len;
    /*subject */
    subject->data = nsslowcert_dataStart(buf, buf_length, &subject->len, PR_TRUE, NULL);
    if (subject->data == NULL)
        return SECFailure;
    buf_length -= (subject->data - buf) + subject->len;
    buf = subject->data + subject->len;
    /* subject  key info */
    subjkey->data = nsslowcert_dataStart(buf, buf_length, &subjkey->len, PR_TRUE, NULL);
    if (subjkey->data == NULL)
        return SECFailure;
    buf_length -= (subjkey->data - buf) + subjkey->len;
    buf = subjkey->data + subjkey->len;

    extensions->data = NULL;
    extensions->len = 0;
    while (buf_length > 0) {
        /* EXTENSIONS */
        if (buf[0] == 0xa3) {
            extensions->data = nsslowcert_dataStart(buf, buf_length,
                                                    &extensions->len, PR_FALSE, NULL);
            /* if the DER is bad, we should fail. Previously we accepted
             * bad DER here and treated the extension as missin */

            if (extensions->data == NULL ||
                (extensions->data - buf) + extensions->len != buf_length)
                return SECFailure;
            buf = extensions->data;
            buf_length = extensions->len;
            /* now parse the SEQUENCE holding the extensions. */
            dummy = nsslowcert_dataStart(buf, buf_length, &dummylen, PR_FALSE, NULL);
            if (dummy == NULL ||
                (dummy - buf) + dummylen != buf_length)
                return SECFailure;
            buf_length -= (dummy - buf);
            buf = dummy;
            /* Now parse the extensions inside this sequence */
        }
        dummy = nsslowcert_dataStart(buf, buf_length, &dummylen, PR_FALSE, NULL);
        if (dummy == NULL)
            return SECFailure;
        buf_length -= (dummy - buf) + dummylen;
        buf = dummy + dummylen;
    }
    return SECSuccess;
}

static SECStatus
nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
{
    int rv;
    NSSLOWCERTValidity validity;

    rv = nsslowcert_GetValidityFields(c->validity.data, c->validity.len,
                                      &validity.notBefore, &validity.notAfter);
    if (rv != SECSuccess) {
        return rv;
    }

    /* convert DER not-before time */
    rv = DER_DecodeTimeChoice(notBefore, &validity.notBefore);
    if (rv) {
        return (SECFailure);
    }

    /* convert DER not-after time */
    rv = DER_DecodeTimeChoice(notAfter, &validity.notAfter);
    if (rv) {
        return (SECFailure);
    }

    return (SECSuccess);
}

/*
 * is certa newer than certb?  If one is expired, pick the other one.
 */

PRBool
nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb)
{
    PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now;
    SECStatus rv;
    PRBool newerbefore, newerafter;

    rv = nsslowcert_GetCertTimes(certa, ¬BeforeA, ¬AfterA);
    if (rv != SECSuccess) {
        return (PR_FALSE);
    }

    rv = nsslowcert_GetCertTimes(certb, ¬BeforeB, ¬AfterB);
    if (rv != SECSuccess) {
        return (PR_TRUE);
    }

    newerbefore = PR_FALSE;
    if (LL_CMP(notBeforeA, >, notBeforeB)) {
        newerbefore = PR_TRUE;
    }

    newerafter = PR_FALSE;
    if (LL_CMP(notAfterA, >, notAfterB)) {
        newerafter = PR_TRUE;
    }

    if (newerbefore && newerafter) {
        return (PR_TRUE);
    }

    if ((!newerbefore) && (!newerafter)) {
        return (PR_FALSE);
    }

    /* get current time */
    now = PR_Now();

    if (newerbefore) {
        /* cert A was issued after cert B, but expires sooner */
        /* if A is expired, then pick B */
        if (LL_CMP(notAfterA, <, now)) {
            return (PR_FALSE);
        }
        return (PR_TRUE);
    } else {
        /* cert B was issued after cert A, but expires sooner */
        /* if B is expired, then pick A */
        if (LL_CMP(notAfterB, <, now)) {
            return (PR_TRUE);
        }
        return (PR_FALSE);
    }
}

#define SOFT_DEFAULT_CHUNKSIZE 2048

static SECStatus
nsslowcert_KeyFromIssuerAndSN(PLArenaPool *arena,
                              SECItem *issuer, SECItem *sn, SECItem *key)
{
    unsigned int len = sn->len + issuer->len;

    if (!arena) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        goto loser;
    }
    if (len > NSS_MAX_LEGACY_DB_KEY_SIZE) {
        PORT_SetError(SEC_ERROR_INPUT_LEN);
        goto loser;
    }
    key->data = (unsigned char *)PORT_ArenaAlloc(arena, len);
    if (!key->data) {
        goto loser;
    }

    key->len = len;
    /* copy the serialNumber */
    PORT_Memcpy(key->data, sn->data, sn->len);

    /* copy the issuer */
    PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);

    return (SECSuccess);

loser:
    return (SECFailure);
}

static SECStatus
nsslowcert_KeyFromIssuerAndSNStatic(unsigned char *space,
                                    int spaceLen, SECItem *issuer, SECItem *sn, SECItem *key)
{
    unsigned int len = sn->len + issuer->len;

    key->data = pkcs11_allocStaticData(len, space, spaceLen);
    if (!key->data) {
        goto loser;
    }

    key->len = len;
    /* copy the serialNumber */
    PORT_Memcpy(key->data, sn->data, sn->len);

    /* copy the issuer */
    PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);

    return (SECSuccess);

loser:
    return (SECFailure);
}

static char *
nsslowcert_EmailName(SECItem *derDN, char *space, unsigned int len)
{
    unsigned char *buf;
    unsigned int buf_length;

    /* unwrap outer sequence */
    buf = nsslowcert_dataStart(derDN->data, derDN->len, &buf_length, PR_FALSE, NULL);
    if (buf == NULL)
        return NULL;

    /* Walk each RDN */
    while (buf_length > 0) {
        unsigned char *rdn;
        unsigned int rdn_length;

        /* grab next rdn */
        rdn = nsslowcert_dataStart(buf, buf_length, &rdn_length, PR_FALSE, NULL);
        if (rdn == NULL) {
            return NULL;
        }
        buf_length -= (rdn - buf) + rdn_length;
        buf = rdn + rdn_length;

        while (rdn_length > 0) {
            unsigned char *ava;
            unsigned int ava_length;
            unsigned char *oid;
            unsigned int oid_length;
            unsigned char *name;
            unsigned int name_length;
            SECItem oidItem;
            SECOidTag type;

            /* unwrap the ava */
            ava = nsslowcert_dataStart(rdn, rdn_length, &ava_length, PR_FALSE,
                                       NULL);
            if (ava == NULL)
                return NULL;
            rdn_length -= (ava - rdn) + ava_length;
            rdn = ava + ava_length;

            oid = nsslowcert_dataStart(ava, ava_length, &oid_length, PR_FALSE,
                                       NULL);
            if (oid == NULL) {
                return NULL;
            }
            ava_length -= (oid - ava) + oid_length;
            ava = oid + oid_length;

            name = nsslowcert_dataStart(ava, ava_length, &name_length, PR_FALSE,
                                        NULL);
            if (name == NULL) {
                return NULL;
            }
            ava_length -= (name - ava) + name_length;
            ava = name + name_length;

            oidItem.data = oid;
            oidItem.len = oid_length;
            type = SECOID_FindOIDTag(&oidItem);
            if ((type == SEC_OID_PKCS9_EMAIL_ADDRESS) ||
                (type == SEC_OID_RFC1274_MAIL)) {
                /* Email is supposed to be IA5String, so no
                 * translation necessary */

                char *emailAddr;
                emailAddr = (char *)pkcs11_copyStaticData(name, name_length + 1,
                                                          (unsigned char *)space, len);
                if (emailAddr) {
                    emailAddr[name_length] = 0;
                }
                return emailAddr;
            }
        }
    }
    return NULL;
}

static char *
nsslowcert_EmailAltName(NSSLOWCERTCertificate *cert, char *space,
                        unsigned int len)
{
    unsigned char *exts;
    unsigned int exts_length;

    /* unwrap the sequence */
    exts = nsslowcert_dataStart(cert->extensions.data, cert->extensions.len,
                                &exts_length, PR_FALSE, NULL);
    /* loop through extension */
    while (exts && exts_length > 0) {
        unsigned char *ext;
        unsigned int ext_length;
        unsigned char *oid;
        unsigned int oid_length;
        unsigned char *nameList;
        unsigned int nameList_length;
        SECItem oidItem;
        SECOidTag type;

        ext = nsslowcert_dataStart(exts, exts_length, &ext_length,
                                   PR_FALSE, NULL);
        if (ext == NULL) {
            break;
        }
        exts_length -= (ext - exts) + ext_length;
        exts = ext + ext_length;

        oid = nsslowcert_dataStart(ext, ext_length, &oid_length, PR_FALSE, NULL);
        if (oid == NULL) {
            break;
        }
        ext_length -= (oid - ext) + oid_length;
        ext = oid + oid_length;
        oidItem.data = oid;
        oidItem.len = oid_length;
        type = SECOID_FindOIDTag(&oidItem);

        /* get Alt Extension */
        if (type != SEC_OID_X509_SUBJECT_ALT_NAME) {
            continue;
        }

        /* skip passed the critical flag */
        if (ext[0] == 0x01) { /* BOOLEAN */
            unsigned char *dummy;
            unsigned int dummy_length;
            dummy = nsslowcert_dataStart(ext, ext_length, &dummy_length,
                                         PR_FALSE, NULL);
            if (dummy == NULL) {
                break;
            }
            ext_length -= (dummy - ext) + dummy_length;
            ext = dummy + dummy_length;
        }

        /* unwrap the name list */
        nameList = nsslowcert_dataStart(ext, ext_length, &nameList_length,
                                        PR_FALSE, NULL);
        if (nameList == NULL) {
            break;
        }
        ext_length -= (nameList - ext) + nameList_length;
        ext = nameList + nameList_length;
        nameList = nsslowcert_dataStart(nameList, nameList_length,
                                        &nameList_length, PR_FALSE, NULL);
        /* loop through the name list */
        while (nameList && nameList_length > 0) {
            unsigned char *thisName;
            unsigned int thisName_length;

            thisName = nsslowcert_dataStart(nameList, nameList_length,
                                            &thisName_length, PR_FALSE, NULL);
            if (thisName == NULL) {
                break;
            }
            if (nameList[0] == 0xa2) { /* DNS Name */
                SECItem dn;
                char *emailAddr;

                dn.data = thisName;
                dn.len = thisName_length;
                emailAddr = nsslowcert_EmailName(&dn, space, len);
                if (emailAddr) {
                    return emailAddr;
                }
            }
            if (nameList[0] == 0x81) { /* RFC 822name */
                char *emailAddr;
                emailAddr = (char *)pkcs11_copyStaticData(thisName,
                                                          thisName_length + 1, (unsigned char *)space, len);
                if (emailAddr) {
                    emailAddr[thisName_length] = 0;
                }
                return emailAddr;
            }
            nameList_length -= (thisName - nameList) + thisName_length;
            nameList = thisName + thisName_length;
        }
        break;
    }
    return NULL;
}

static char *
nsslowcert_GetCertificateEmailAddress(NSSLOWCERTCertificate *cert)
{
    char *emailAddr = NULL;
    char *str;

    emailAddr = nsslowcert_EmailName(&cert->derSubject, cert->emailAddrSpace,
                                     sizeof(cert->emailAddrSpace));
    /* couldn't find the email address in the DN, check the subject Alt name */
    if (!emailAddr && cert->extensions.data) {
        emailAddr = nsslowcert_EmailAltName(cert, cert->emailAddrSpace,
                                            sizeof(cert->emailAddrSpace));
    }

    /* make it lower case */
    str = emailAddr;
    while (str && *str) {
        *str = tolower((unsigned char)*str);
        str++;
    }
    return emailAddr;
}

/*
 * take a DER certificate and decode it into a certificate structure
 */

NSSLOWCERTCertificate *
nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
{
    NSSLOWCERTCertificate *cert;
    int rv;

    /* allocate the certificate structure */
    cert = nsslowcert_CreateCert();

    if (!cert) {
        goto loser;
    }

    /* point to passed in DER data */
    cert->derCert = *derSignedCert;
    cert->nickname = NULL;
    cert->certKey.data = NULL;
    cert->referenceCount = 1;

    /* decode the certificate info */
    rv = nsslowcert_GetCertFields(cert->derCert.data, cert->derCert.len,
                                  &cert->derIssuer, &cert->serialNumber, &cert->derSN, &cert->derSubject,
                                  &cert->validity, &cert->derSubjKeyInfo, &cert->extensions);

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

    /* cert->subjectKeyID;   x509v3 subject key identifier */
    cert->subjectKeyID.data = NULL;
    cert->subjectKeyID.len = 0;
    cert->dbEntry = NULL;
    cert->trust = NULL;
    cert->dbhandle = NULL;

    /* generate and save the database key for the cert */
    rv = nsslowcert_KeyFromIssuerAndSNStatic(cert->certKeySpace,
                                             sizeof(cert->certKeySpace), &cert->derIssuer,
                                             &cert->serialNumber, &cert->certKey);
    if (rv) {
        goto loser;
    }

    /* set the nickname */
    if (nickname == NULL) {
        cert->nickname = NULL;
    } else {
        /* copy and install the nickname */
        cert->nickname = pkcs11_copyNickname(nickname, cert->nicknameSpace,
                                             sizeof(cert->nicknameSpace));
    }

#ifdef FIXME
    /* initialize the subjectKeyID */
    rv = cert_GetKeyID(cert);
    if (rv != SECSuccess) {
        goto loser;
    }
#endif

    /* set the email address */
    cert->emailAddr = nsslowcert_GetCertificateEmailAddress(cert);

    cert->referenceCount = 1;

    return (cert);

loser:
    if (cert) {
        nsslowcert_DestroyCertificate(cert);
    }

    return (0);
}

char *
nsslowcert_FixupEmailAddr(char *emailAddr)
{
    char *retaddr;
    char *str;

    if (emailAddr == NULL) {
        return (NULL);
    }

    /* copy the string */
    str = retaddr = PORT_Strdup(emailAddr);
    if (str == NULL) {
        return (NULL);
    }

    /* make it lower case */
    while (*str) {
        *str = tolower((unsigned char)*str);
        str++;
    }

    return (retaddr);
}

/*
 * Generate a database key, based on serial number and issuer, from a
 * DER certificate.
 */

SECStatus
nsslowcert_KeyFromDERCert(PLArenaPool *arena, SECItem *derCert, SECItem *key)
{
    int rv;
    NSSLOWCERTCertKey certkey;

    PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));

    rv = nsslowcert_GetCertFields(derCert->data, derCert->len,
                                  &certkey.derIssuer, &certkey.serialNumber, NULL, NULL,
                                  NULL, NULL, NULL);

    if (rv) {
        goto loser;
    }

    return (nsslowcert_KeyFromIssuerAndSN(arena, &certkey.derIssuer,
                                          &certkey.serialNumber, key));
loser:
    return (SECFailure);
}

NSSLOWKEYPublicKey *
nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
{
    NSSLOWCERTSubjectPublicKeyInfo spki;
    NSSLOWKEYPublicKey *pubk;
    SECItem os;
    SECStatus rv;
    PLArenaPool *arena;
    SECOidTag tag;
    SECItem newDerSubjKeyInfo;

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

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

    pubk->arena = arena;
    PORT_Memset(&spki, 0, sizeof(spki));

    /* copy the DER into the arena, since Quick DER returns data that points
       into the DER input, which may get freed by the caller */

    rv = SECITEM_CopyItem(arena, &newDerSubjKeyInfo, &cert->derSubjKeyInfo);
    if (rv != SECSuccess) {
        PORT_FreeArena(arena, PR_FALSE);
        return NULL;
    }

    /* we haven't bothered decoding the spki struct yet, do it now */
    rv = SEC_QuickDERDecodeItem(arena, &spki,
                                nsslowcert_SubjectPublicKeyInfoTemplate, &newDerSubjKeyInfo);
    if (rv != SECSuccess) {
        PORT_FreeArena(arena, PR_FALSE);
        return NULL;
    }

    /* Convert bit string length from bits to bytes */
    os = spki.subjectPublicKey;
    DER_ConvertBitString(&os);

    tag = SECOID_GetAlgorithmTag(&spki.algorithm);
    switch (tag) {
        case SEC_OID_X500_RSA_ENCRYPTION:
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
            pubk->keyType = NSSLOWKEYRSAKey;
            prepare_low_rsa_pub_key_for_asn1(pubk);
            rv = SEC_QuickDERDecodeItem(arena, pubk,
                                        nsslowcert_RSAPublicKeyTemplate, &os);
            if (rv == SECSuccess)
                return pubk;
            break;
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
            pubk->keyType = NSSLOWKEYDSAKey;
            prepare_low_dsa_pub_key_for_asn1(pubk);
            rv = SEC_QuickDERDecodeItem(arena, pubk,
                                        nsslowcert_DSAPublicKeyTemplate, &os);
            if (rv == SECSuccess)
                return pubk;
            break;
        case SEC_OID_X942_DIFFIE_HELMAN_KEY:
            pubk->keyType = NSSLOWKEYDHKey;
            prepare_low_dh_pub_key_for_asn1(pubk);
            rv = SEC_QuickDERDecodeItem(arena, pubk,
                                        nsslowcert_DHPublicKeyTemplate, &os);
            if (rv == SECSuccess)
                return pubk;
            break;
        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
            pubk->keyType = NSSLOWKEYECKey;
            /* Since PKCS#11 directly takes the DER encoding of EC params
             * and public value, we don't need any decoding here.
             */

            rv = SECITEM_CopyItem(arena, &pubk->u.ec.ecParams.DEREncoding,
                                  &spki.algorithm.parameters);
            if (rv != SECSuccess)
                break;

            /* Fill out the rest of the ecParams structure
             * based on the encoded params
             */

            if (LGEC_FillParams(arena, &pubk->u.ec.ecParams.DEREncoding,
                                &pubk->u.ec.ecParams) != SECSuccess)
                break;

            rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &os);
            if (rv == SECSuccess)
                return pubk;
            break;
        default:
            rv = SECFailure;
            break;
    }

    lg_nsslowkey_DestroyPublicKey(pubk);
    return NULL;
}

Messung V0.5
C=93 H=95 G=93

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