⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 x509.c

📁 Netscape公司提供的安全套接字层
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  *********************************************************************
    File: x509.c

    SSLRef 3.0 Final -- 11/19/96

    Copyright (c)1996 by Netscape Communications Corp.

    By retrieving this software you are bound by the licensing terms
    disclosed in the file "LICENSE.txt". Please read it, and if you don't
    accept the terms, delete this software.

    SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
    View, California <http://home.netscape.com/> and Consensus Development
    Corporation of Berkeley, California <http://www.consensus.com/>.

    *********************************************************************

    File: x509.c       Certificate decoding support

    Decodes X.509 certificates, versions 1-3.

    ****************************************************************** */

#ifndef _ASN1UTIL_H_
#include "asn1util.h"
#endif

#ifndef _X509_H_
#include "x509.h"
#endif

#ifndef _SSLCTX_H_
#include "sslctx.h"
#endif

#ifndef _CRYPTYPE_H_
#include "cryptype.h"
#endif

#ifndef _SSLCRYPT_H_
#include "sslcrypt.h"
#endif

#include <string.h>
#include <stdlib.h>

ASNErr
ASNParseX509Certificate(SSLBuffer certData, X509Cert *certResult, SSLContext *ctx)
{   ASN1Type        certASN,
                    certParts[3],
                    scratchTypes[3],
                    moreScratch[2],
                    certInfo[10],
                    *extensionList;
    SSLBuffer       allocScratch;
    X509Extension   *curExt, *lastExt;
    X509Cert        cert;
    ASNErr          err;
    int             i, j, t, certInfoCount, extensionCount, hasVersion;
    
/* Zero cert so we can free a half-initialized one cleanly */
    memset (&cert, 0, sizeof(cert));
    extensionList = 0;
    
/* Interpret the enclosing structure */
    i = 1;
    if ((err = ASNParseBER(certData, &certASN, &i)) != 0)
        goto fail;
    
/* Interpret the SIGNED macro sequence [cert, algorithm, sig] */
    i = sizeof(certParts) / sizeof(ASN1Type);
    if ((err = ASNParseBER(certASN.contents, certParts, &i)) != 0)
        goto fail;
    if (i != 3)             /* certInfo, algorithm, signature */
        goto badEncoding;
    if (certParts[0].identifier != (ASN_CONSTRUCTED | ASN_SEQUENCE))
        goto badEncoding;
    if (certParts[1].identifier != (ASN_CONSTRUCTED | ASN_SEQUENCE))
        goto badEncoding;
    if (certParts[2].identifier != ASN_BIT_STRING)
        goto badEncoding;
    
    cert.signature = certParts[2].contents;
    
    /* Parse the SIGNED macro's algorithm type */
    i = sizeof(scratchTypes) / sizeof(ASN1Type);
    if ((err = ASNParseBER(certParts[1].contents, scratchTypes, &i)) != 0)
        goto fail;
    /* Either 1 or 2 entries in an AlgorithmIdentifier are OK */
    
    if (scratchTypes[0].identifier != ASN_OBJECT_IDENTIFIER)
        goto badEncoding;
    if ((err = ASNDecodeObjectID(scratchTypes[0].contents,
                        &cert.sigAlgorithm.algorithm)) != 0)
        goto fail;
    if (i > 1)
        cert.sigAlgorithm.parameters = scratchTypes[1];
    else
        cert.sigAlgorithm.parameters.identifier = 0;
    
/* Recover the buffer specification for the signed portion of the certificate */
    cert.signedData.data = certASN.contents.data;
    cert.signedData.length = certParts[0].contents.length + 2;  /* data + identifier + one byte of length */
    if (certParts[0].contents.length >= 0x80)
        cert.signedData.length ++;  /* length requires length byte + one byte of length */
    if (certParts[0].contents.length >= 0x100)
        cert.signedData.length ++;  /* length requires length byte + two bytes of length */
    if (certParts[0].contents.length >= 0x10000)
        cert.signedData.length ++;  /* length requires length byte + three bytes of length */
    if (certParts[0].contents.length >= 0x1000000)
        cert.signedData.length ++;  /* length requires length byte + four bytes of length */

/* Parse the certificate info */
    i = 8;
    if ((err = ASNParseBER(certParts[0].contents, certInfo, &i)) != 0)
        goto fail;
    certInfoCount = i;
    if (certInfoCount < 6)
        goto badEncoding;
    
/* Does this cert have a version? If so, it will be an EXPLICIT 0-tagged integer */
    cert.version = 0;
    hasVersion = 0;
    if (certInfo[0].identifier == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
    {   hasVersion = 1;
        i = 1;
        if ((err = ASNParseBER(certInfo[0].contents, &scratchTypes[0], &i)) != 0)
        goto fail;
        if (scratchTypes[0].identifier != ASN_INTEGER)
            goto badEncoding;
        err = ASNDecodeInteger(scratchTypes[0].contents, &cert.version);
        if (err != 0 || (cert.version != 0 && cert.version != 2))
        {   if (err == ASNIntegerTooBigErr || err == 0)
                err = SSLUnsupportedErr;
            goto fail;
        }
    }
    if (cert.version == 0 && certInfoCount - hasVersion != 6)
        goto badEncoding;
    
/* Record pointer to serial number; it's an integer, but we can
 *  treat it as an octet string (we're only concerned with uniqueness)
 */
    if (certInfo[0 + hasVersion].identifier != ASN_INTEGER)
        goto badEncoding;
    cert.serialNumber = certInfo[0 + hasVersion].contents;
    
/* Parse the certificates's algorithm type */
    if (certInfo[1 + hasVersion].identifier != (ASN_CONSTRUCTED | ASN_SEQUENCE))
        goto badEncoding;
    i = sizeof(scratchTypes) / sizeof(ASN1Type);
    if ((err = ASNParseBER(certInfo[1 + hasVersion].contents, scratchTypes, &i)) != 0)
        goto fail;
    /* Either 1 or 2 entries in an AlgorithmIdentifier are OK */
    
    if (scratchTypes[0].identifier != ASN_OBJECT_IDENTIFIER)
        goto badEncoding;
    if ((err = ASNDecodeObjectID(scratchTypes[0].contents,
                        &cert.algorithm.algorithm)) != 0)
        goto fail;
    if (i > 1)
        cert.algorithm.parameters = scratchTypes[1];
    else
        cert.algorithm.parameters.identifier = 0;
    
/* Get the issuer name */
    if (certInfo[2 + hasVersion].identifier != (ASN_CONSTRUCTED | ASN_SEQUENCE))
        goto badEncoding;
    if ((err = X509DecodeName(certInfo[2 + hasVersion].contents, &cert.issuer, &ctx->sysCtx)) != 0)
        goto fail;
        
/* Get the validity times */
    if (certInfo[3 + hasVersion].identifier != (ASN_CONSTRUCTED | ASN_SEQUENCE))
        goto badEncoding;
    i = 2;
    if ((err = ASNParseBER(certInfo[3 + hasVersion].contents, scratchTypes, &i)) != 0)
        goto fail;
    if (i < 2 || scratchTypes[0].identifier != ASN_UTCTime || scratchTypes[1].identifier != ASN_UTCTime)
        goto badEncoding;
    if ((err = ASNDecodeUTCTime(scratchTypes[0].contents, &cert.startTime)) != 0)
        goto fail;
    if ((err = ASNDecodeUTCTime(scratchTypes[1].contents, &cert.endTime)) != 0)
        goto fail;
    
/* Get the subject name */
    if (certInfo[4 + hasVersion].identifier != (ASN_CONSTRUCTED | ASN_SEQUENCE))
        goto badEncoding;
    if ((err = X509DecodeName(certInfo[4 + hasVersion].contents, &cert.subject, &ctx->sysCtx)) != 0)
        goto fail;
    
/* Parse the public key */
    if (certInfo[5 + hasVersion].identifier != (ASN_CONSTRUCTED | ASN_SEQUENCE))
        goto badEncoding;
    i = sizeof(scratchTypes) / sizeof(ASN1Type);
    if ((err = ASNParseBER(certInfo[5 + hasVersion].contents, scratchTypes, &i)) != 0)
        goto fail;
    if (i < 2)
        goto badEncoding;
    
    if (scratchTypes[0].identifier != (ASN_CONSTRUCTED | ASN_SEQUENCE)
            || scratchTypes[1].identifier != ASN_BIT_STRING)
        goto badEncoding;
    
/* The public key's algorithm */
    i = 2;
    if ((err = ASNParseBER(scratchTypes[0].contents, moreScratch, &i)) != 0)
        goto fail;
    
    if (moreScratch[0].identifier != ASN_OBJECT_IDENTIFIER)
        goto badEncoding;
    if ((err = ASNDecodeObjectID(moreScratch[0].contents,
                        &cert.pubKey.algorithm.algorithm)) != 0)
        goto fail;
    if (i > 1)
        cert.pubKey.algorithm.parameters = scratchTypes[1];
    else
        cert.pubKey.algorithm.parameters.identifier = 0;

/* The actual public key */
    cert.pubKey.publicKey = scratchTypes[1].contents;
    
/* Parse OPTIONAL additions to the Certificate structure for v2 and v3 certs.
    Technically, these must be in order, but we're a little lax */
    t = 6 + hasVersion;
    while (t < certInfoCount)
    {   switch (certInfo[t].identifier)
        {   case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED) + 1:
                if (cert.version < 1)
                    goto badEncoding;
                cert.issuerUniqueID = certInfo[t].contents;
                break;
            case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED) + 2:
                if (cert.version < 1)
                    goto badEncoding;
                cert.subjectUniqueID = certInfo[t].contents;
                break;
            case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED) + 3:
                if (cert.version < 2)
                    goto badEncoding;
                i = 1;
                if ((err = ASNParseBER(certInfo[t].contents, scratchTypes, &i)) != 0)
                    goto fail;
                if ((err = ASNCountBERElements(scratchTypes[0].contents, &extensionCount)) != 0)
                    goto fail;
                if ((err = SSLAllocBuffer(&allocScratch, extensionCount * sizeof(X509Extension), &ctx->sysCtx)) != 0)
                    goto fail;
                extensionList = (ASN1Type*)allocScratch.data;
                i = extensionCount;
                if ((err = ASNParseBER(scratchTypes[0].contents, extensionList, &i)) != 0)
                    goto fail;
                lastExt = 0;
                for (i = 0; i < extensionCount; i++)
                {   if ((err = SSLAllocBuffer(&allocScratch, sizeof(X509Extension), &ctx->sysCtx)) != 0)
                        goto fail;
                    curExt = (X509Extension*)allocScratch.data;
                    curExt->next = 0;
                    if (lastExt == 0)
                        cert.extensions = curExt;
                    else
                        lastExt->next = curExt;
                    lastExt = curExt;
                    
                    j = 3;
                    if ((err = ASNParseBER(extensionList[i].contents, scratchTypes, &j)) != 0)
                        goto fail;
                    if (j < 2)
                        goto badEncoding;
                    /* For the moment, assume that if the criticality field is
                     *  there, it's critical, because the default is false.
                     */
                    if (j == 3)
                        curExt->critical = 1;
                    else
                        curExt->critical = 0;
                    if (scratchTypes[0].identifier != ASN_OBJECT_IDENTIFIER)
                        goto badEncoding;
                    if ((err = ASNDecodeObjectID(scratchTypes[0].contents, &curExt->id)) != 0)
                        goto fail;
                    if (scratchTypes[j-1].identifier != ASN_OCTET_STRING)
                        goto badEncoding;
                    curExt->contents = scratchTypes[j-1].contents;

                }
                break;
            default:
                goto badEncoding;
        }
        ++t;
    }
    
    *certResult = cert;
    
    return SSLNoErr;
    
badEncoding:
    err = ASNBadEncodingErr;
fail:
    ASNFreeX509Cert(&cert, &ctx->sysCtx);
    if (extensionList != 0)
    {   allocScratch.data = (uint8*)extensionList;
        allocScratch.length = extensionCount * sizeof(X509Extension);
        SSLFreeBuffer(&allocScratch, &ctx->sysCtx);
    }
    return err;
}

ASNErr
ASNFreeX509Cert(X509Cert *cert, SystemContext *sysCtx)
{   ASNErr          err;
    X509Extension   *ext, *nextExt;
    SSLBuffer       allocScratch;
    
    if ((err = FreeNameList(&cert->subject, sysCtx)) != 0)
        return err;
    if ((err = FreeNameList(&cert->issuer, sysCtx)) != 0)
        return err;
    ext = cert->extensions;
    while (ext)
    {   nextExt = ext->next;
        allocScratch.data = (uint8*)ext;
        allocScratch.length = sizeof(X509Extension);
        SSLFreeBuffer(&allocScratch, sysCtx);
        ext = nextExt;
    }
    cert->extensions = 0;
    
    return SSLNoErr;
}

ASNErr
FreeNameList(X509Name *name, SystemContext *sysCtx)
{   SSLBuffer       allocScratch;
    X509RDName      *rdn, *nextRDN;
    X509AVA         *ava, *nextAVA;
    
    nextRDN = name->rdNameList;
    while (nextRDN)
    {   rdn = nextRDN;
        nextRDN = rdn->next;
        
        nextAVA = rdn->avaList;
        while (nextAVA)
        {   ava = nextAVA;
            nextAVA = ava->next;
            allocScratch.data = (uint8*)ava;
            allocScratch.length = sizeof(X509AVA);
            SSLFreeBuffer(&allocScratch, sysCtx);
        }
        allocScratch.data = (uint8*)rdn;
        allocScratch.length = sizeof(X509RDName);
        SSLFreeBuffer(&allocScratch, sysCtx);
    }
    name->rdNameList = 0;
    
    return SSLNoErr;
}

ASNErr
X509DecodeName(SSLBuffer nameStructure, X509Name *name, SystemContext *sysCtx)
{   ASNErr      err;
    SSLBuffer   allocScratch;
    int         rdnCount, avaCount, i, j, qq;
    ASN1Type    *rdnList = 0, *avaList = 0;
    ASN1Type    typeValue[2];
    X509RDName  *rdn = 0, *lastRDN;
    X509AVA     *ava = 0, *lastAVA, *nextAVA;
    
    if ((err = ASNCountBERElements(nameStructure, &rdnCount)) != 0)
        return err;
    if ((err = SSLAllocBuffer(&allocScratch, sizeof(ASN1Type) * rdnCount, sysCtx)) != 0)
        return err;
    rdnList = (ASN1Type*)allocScratch.data;
    name->rdNameCount = rdnCount;
    if ((err = ASNParseBER(nameStructure, rdnList, &rdnCount)) != 0)
        goto errorExit;
    
    for (i = 0; i < rdnCount; i++)
    {   if ((err = ASNCountBERElements(rdnList[i].contents, &avaCount)) != 0)
            goto errorExit;
        if ((err = SSLAllocBuffer(&allocScratch, sizeof(ASN1Type) * avaCount, sysCtx)) != 0)
            goto errorExit;
        avaList = (ASN1Type*)allocScratch.data;
        if ((err = ASNParseBER(rdnList[i].contents, avaList, &avaCount)) != 0)
            goto errorExit;
        if ((err = SSLAllocBuffer(&allocScratch, sizeof(X509RDName), sysCtx)) != 0)
            goto errorExit;
        rdn = (X509RDName*)allocScratch.data;
        rdn->next = 0;
        rdn->avaList = 0;
        rdn->avaCount = avaCount;
        for (j = 0; j < avaCount; j++)
        {   qq = 2;
            if ((err = ASNParseBER(avaList[j].contents, typeValue, &qq)) != 0)
                goto errorExit;
            if (qq != 2 || typeValue[0].identifier != ASN_OBJECT_IDENTIFIER)
            {   err = ASNBadEncodingErr;
                goto errorExit;
            }
            if ((err = SSLAllocBuffer(&allocScratch, sizeof(X509AVA), sysCtx)) != 0)
                goto errorExit;
            ava = (X509AVA*)allocScratch.data;
            ava->next = 0;
            if ((err = ASNDecodeObjectID(typeValue[0].contents, &ava->type)) != 0)
                goto errorExit;
            ava->value = typeValue[1];
            
            if (j == 0)
                rdn->avaList = ava;
            else
                lastAVA->next = ava;
            lastAVA = ava;
            ava = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -