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

📄 x509.c

📁 Netscape公司提供的安全套接字层
💻 C
📖 第 1 页 / 共 2 页
字号:
        }
        allocScratch.data = (uint8*)avaList;
        allocScratch.length = sizeof(ASN1Type) * avaCount;
        SSLFreeBuffer(&allocScratch, sysCtx);
        avaList = 0;
        
        if (i == 0)
            name->rdNameList = rdn;
        else
            lastRDN->next = rdn;
        lastRDN = rdn;
        rdn = 0;
    }
    allocScratch.data = (uint8*)rdnList;
    allocScratch.length = sizeof(ASN1Type) * rdnCount;
    SSLFreeBuffer(&allocScratch, sysCtx);
        
    return SSLNoErr;
    
/* Clean up all possible dangling allocated blocks.
 *  rdn's which have already been linked into the
 *  name are left; the client will presumably
 *  clean them up later.
 */
errorExit:
    if (ava)
    {   allocScratch.data = (uint8*)ava;
        allocScratch.length = sizeof(X509AVA);
        SSLFreeBuffer(&allocScratch, sysCtx);
    }
    if (rdn)
    {   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);
    }
    if (avaList)
    {   allocScratch.data = (uint8*)avaList;
        allocScratch.length = sizeof(ASN1Type) * avaCount;
        SSLFreeBuffer(&allocScratch, sysCtx);
    }
    if (rdnList)
    {   allocScratch.data = (uint8*)rdnList;
        allocScratch.length = sizeof(ASN1Type) * rdnCount;
        SSLFreeBuffer(&allocScratch, sysCtx);
    }
    
    return err;
}

SSLErr
X509VerifySignature(X509Cert *parent, X509Cert *child)
{   SSLErr              err;
    SSLRSAPublicKey     pubKey;
    int                 rsaResult;
    
    if ((err = X509CompareNames(&parent->subject, &child->issuer)) != 0)
        return err;
    
    if ((err = X509ExtractPublicKey(&parent->pubKey, &pubKey)) != 0)
        return err;
    
/* child->signature is the contents of a BER BIT STRING; we require that it have 0 bits
 *  of padding
 */
    if (child->signature.data[0] != 0)
        return ASNBadEncodingErr;
    
#if RSAREF
    {   R_SIGNATURE_CTX     context;
        int                 rsaRefHashAlg;
        
        switch (child->sigAlgorithm.algorithm.oidValue)
        {   case OID_md2WithRSA:
                rsaRefHashAlg = DA_MD2;
                break;
            case OID_md5WithRSA:
                rsaRefHashAlg = DA_MD5;
                break;
            default:
                return SSLUnsupportedErr;
        }
        
        if ((rsaResult = R_VerifyInit(&context, rsaRefHashAlg)) != 0)
            return SSLUnknownErr;
        if ((rsaResult = R_VerifyUpdate(&context, child->signedData.data, child->signedData.length)) != 0)
            return SSLUnknownErr;
        if ((rsaResult = R_VerifyFinal(&context, child->signature.data+1, child->signature.length-1,
                                &pubKey)) != 0)
            return X509CertChainInvalidErr;
    }
#elif BSAFE
    {   B_ALGORITHM_OBJ     md, rsa;
        B_INFO_TYPE         digestType;
        B_ALGORITHM_METHOD  *chooser[] = { &AM_MD2, &AM_MD5, &AM_RSA_DECRYPT, 0 };
        unsigned char       digest[16], digestInfo[100];
        unsigned int        digestLen, decryptLen;
        ITEM                decodedAlgorithmID, decodedDigest;
        
        switch (child->sigAlgorithm.algorithm.oidValue)
        {   case OID_md2WithRSA:
                digestType = AI_MD2;
                break;
            case OID_md5WithRSA:
                digestType = AI_MD5;
                break;
            default:
                return SSLUnsupportedErr;
        }
        
        if ((rsaResult = B_CreateAlgorithmObject(&md)) != 0)
            return SSLUnknownErr;
        if ((rsaResult = B_SetAlgorithmInfo(md, digestType, 0)) != 0)
            return SSLUnknownErr;
        if ((rsaResult = B_DigestInit(md, 0, chooser, NO_SURR)) != 0)
            return SSLUnknownErr;
        if ((rsaResult = B_DigestUpdate(md, child->signedData.data, child->signedData.length, NO_SURR)) != 0)
            return SSLUnknownErr;
        if ((rsaResult = B_DigestFinal(md, digest, &digestLen, 16, NO_SURR)) != 0)
            return SSLUnknownErr;
        B_DestroyAlgorithmObject(&md);
        
        if ((rsaResult = B_CreateAlgorithmObject(&rsa)) != 0)
            return SSLUnknownErr;
        if ((rsaResult = B_SetAlgorithmInfo(rsa, AI_PKCS_RSAPublic, 0)) != 0)
            return SSLUnknownErr;
        if ((rsaResult = B_DecryptInit(rsa, pubKey, chooser, NO_SURR)) != 0)
            return SSLUnknownErr;
        if ((rsaResult = B_DecryptUpdate(rsa, digestInfo, &digestLen, 100,
                    child->signature.data+1, child->signature.length-1,
                    0, NO_SURR)) != 0)
            return SSLUnknownErr;
        decryptLen = digestLen;
        if ((rsaResult = B_DecryptFinal(rsa, digestInfo+digestLen, &digestLen,
                    100-digestLen, 0, NO_SURR)) != 0)
            return SSLUnknownErr;
        decryptLen += digestLen;
        
        if ((rsaResult = B_DecodeDigestInfo(&decodedAlgorithmID, &decodedDigest,
                        digestInfo, decryptLen)) != 0)
            return SSLUnknownErr;
        
        if (decodedDigest.len != 16 || memcmp(digest, decodedDigest.data, 16) != 0)
            return X509CertChainInvalidErr;
        
        B_DestroyAlgorithmObject(&rsa);
        B_DestroyKeyObject(&pubKey);
    }
#endif /* RSAREF / BSAFE */
    return SSLNoErr;
}

SSLErr
X509ExtractPublicKey(X509PubKey *asnKey, SSLRSAPublicKey *pubKey)
{   SSLErr          err;
    SSLBuffer       pubKeyASN;
    ASN1Type        pubKeySeq, pubKeyParts[2];
    int             i;

    switch (asnKey->algorithm.algorithm.oidValue)
    {   case OID_rsaEncryption:
            break;
        default:
            return SSLUnsupportedErr;
    }
    
/* asnKey->publicKey is the contents of a BER BIT STRING; its first byte indicates
 *  how many bits of padding we've got; we require 0.
 */
    if (asnKey->publicKey.data[0] != 0)
        return ASNBadEncodingErr;
    
/* Set up an SSLBuffer that refers to the octets of the bit string */
    pubKeyASN.data = asnKey->publicKey.data + 1;
    pubKeyASN.length = asnKey->publicKey.length - 1;
    
    i = 1;
    if ((err = ASNParseBER(pubKeyASN, &pubKeySeq, &i)) != 0)
        return err;
    if (i != 1 || pubKeySeq.identifier != (ASN_CONSTRUCTED | ASN_SEQUENCE))
        return ASNBadEncodingErr;
    
    i = 2;
    if ((err = ASNParseBER(pubKeySeq.contents, pubKeyParts, &i)) != 0)
        return err;
    if (i != 2 || pubKeyParts[0].identifier != ASN_INTEGER
                || pubKeyParts[1].identifier != ASN_INTEGER)
        return ASNBadEncodingErr;
    
#if RSAREF
    {   unsigned char       c;
        int                 bitAdjust;
        SSLBuffer           exponent, modulus;
        
        memset(pubKey, 0, sizeof(R_RSA_PUBLIC_KEY));
        
        modulus = pubKeyParts[0].contents;
        exponent = pubKeyParts[1].contents;
        
        if (modulus.data[0] == 0)
        {   ++modulus.data;
            --modulus.length;
        }
        
        if (exponent.data[0] == 0)
        {   ++exponent.data;
            --exponent.length;
        }
        
        if (modulus.length > MAX_RSA_MODULUS_LEN || 
                exponent.length > MAX_RSA_MODULUS_LEN)
            return ERR(ASNBadEncodingErr);
        
/* Copy the INTEGERs into the public key fields, justified at the ends of the arrays */
        memcpy(pubKey->modulus + (MAX_RSA_MODULUS_LEN - pubKeyParts[0].contents.length),
                pubKeyParts[0].contents.data, pubKeyParts[0].contents.length);
        memcpy(pubKey->exponent + (MAX_RSA_MODULUS_LEN - pubKeyParts[1].contents.length),
                pubKeyParts[1].contents.data, pubKeyParts[1].contents.length);
        
/* Adjust bit length for leading zeros in value; assume no more than 8 leading zero bits */
        c =  pubKeyParts[0].contents.data[0];
        
        bitAdjust = 8;
        while (c != 0)
        {   --bitAdjust;
            c >>= 1;
        }
        pubKey->bits = pubKeyParts[0].contents.length * 8 - bitAdjust;
    }
#elif BSAFE
    {   A_RSA_KEY   pubKeyInfo;
        int         rsaErr;
        
        pubKeyInfo.modulus.data = pubKeyParts[0].contents.data;
        pubKeyInfo.modulus.len = pubKeyParts[0].contents.length;
        pubKeyInfo.exponent.data = pubKeyParts[1].contents.data;
        pubKeyInfo.exponent.len = pubKeyParts[1].contents.length;
        
        if ((rsaErr = B_CreateKeyObject(pubKey)) != 0)
            return SSLUnknownErr;
        if ((rsaErr = B_SetKeyInfo(*pubKey, KI_RSAPublic, (POINTER)&pubKeyInfo)) != 0)
            return SSLUnknownErr;
    }
#endif /* RSAREF / BSAFE */
    return SSLNoErr;
}

/* AVA are equal if they have the same type & value */
static SSLErr
CompareAVA(X509AVA *a1, X509AVA *a2)
{   
    if (a1->type.oidValue != a2->type.oidValue)
        return X509NamesNotEqualErr;
    
/* If both types are zero, we need to compare the actual OID descriptions;
 *  this is an object ID unknown to us
 */
    if (a1->type.oidValue == OID_noMatch)
    {   if (a1->type.objectID.length != a2->type.objectID.length)
            return X509NamesNotEqualErr;
        if (memcmp(a1->type.objectID.data, a2->type.objectID.data,
                    a1->type.objectID.length) != 0)
            return X509NamesNotEqualErr;
    }
    
    /* Types match */
    
    /* Identifiers have to match; we don't support treating two AVAs with the
     *  same type and values which are equal but have different encodings
     *  (such as T61String vs. IA5String) as the same. This may or may not
     *  be correct. I don't have X.501 here to determine the strict definition
     *  of equality of DNs.
     */
    if (a1->value.identifier != a2->value.identifier)
        return X509NamesNotEqualErr;
    if (a1->value.contents.length != a2->value.contents.length)
        return X509NamesNotEqualErr;
    if (memcmp(a1->value.contents.data, a2->value.contents.data,
                a1->value.contents.length) != 0)
        return X509NamesNotEqualErr;
    
    return SSLNoErr;        /* AVAs match in type & value */
}

/* We need to make sure that for each AVA in rdn1, one unique AVA in rdn2
 *  exactly matches it; we need to keep track of which AVAs we've used in
 *  rdn2 so someone can't attack the comparison by providing an rdn1 which
 *  has the right number of AVAs, all of which are the same and match a
 *  single AVA in rdn2; by not allowing an AVA in rdn2 to be used as a match
 *  more than once, we avoid this attack and guarantee a one-to-one mapping.
 *  By using a stack array to hold the flags for AVA comparison, I've
 *  artificially limited the number of AVAs at any level you can have, but
 *  I believe this is preferable to introducing a malloc/free here.
 */
static SSLErr
CompareRDNames(X509RDName *rdn1, X509RDName *rdn2)
{   SSLErr          err;
    uint8           compareFlags[128];          /* LIMITATION: No more than 1024 AVAs at a level */
    unsigned int    index, i;
    X509AVA         *ava, *search;
    
    ASSERT(rdn1->avaCount <= sizeof(compareFlags) * 8);
    if (rdn1->avaCount != rdn2->avaCount)
        return X509NamesNotEqualErr;
    
    for (i = 0; i < rdn1->avaCount/8 + 1; i++)
        compareFlags[i] = 0;
    
    ava = rdn1->avaList;
    while (ava)
    {   /* Locate a matching AVA with its compareFlag bit clear in rdn2 */
        search = rdn2->avaList;
        index = 0;
        while (search)
        {   if ((err = CompareAVA(ava, search)) == 0 &&
                    (compareFlags[index/8] & (1 << index%8)) == 0)
            {   /* We've found a match */
                compareFlags[index/8] |= (1 << index%8);    /* Set 'used' flag */
                break;      /* Out of while (search) loop */
            }
            search = search->next;
        }
        
        if (search == 0)    /* We left loop beacuse we reached the end of the list */
            return X509NamesNotEqualErr;
        
        ava = ava->next;    /* Match next AVA */
    }
    
    return SSLNoErr;
}

/* We require that they have the same number of RDNs, and that each RDN
 *  have identical AVAs in arbitrary order. I think this is correct, but
 *  I haven't seen a strict definition of equality of DN's.
 */
SSLErr
X509CompareNames(X509Name *n1, X509Name *n2)
{   SSLErr      err;
    X509RDName  *rdn1,*rdn2;
    
    if (n1->rdNameCount != n2->rdNameCount)
        return X509NamesNotEqualErr;
    
    rdn1 = n1->rdNameList;
    rdn2 = n2->rdNameList;
    
    while (rdn1 && rdn2)
    {   if ((err = CompareRDNames(rdn1, rdn2)) != 0)
            return err;
        
        rdn1 = rdn1->next;
        rdn2 = rdn2->next;
    }
    
    ASSERT(rdn1 == 0 && rdn2 == 0);     /* We should reach the end simultaneously */
    
    return SSLNoErr;    /* Names are equal */
}

SSLErr
X509VerifyCertChain(SSLCertificate *chain, SSLContext *ctx)
{   SSLErr      err;
    uint32      now, start, end;
    
    if ((err = ctx->sysCtx.time(&now, ctx->sysCtx.timeRef)) != 0)
        return err;
    
/* First cert is root, working down to last = peer */
    /* Verify self-signed root cert */
	if(chain ==NULL)
	{
		printf("X509VerifyCertChain: chain ==NULL\n");
		return -1;
	}

    start = chain->cert.startTime;
    end = chain->cert.endTime;
    if ((err = ctx->sysCtx.convertTime(&start, ctx->sysCtx.timeRef)) != 0 ||
        (err = ctx->sysCtx.convertTime(&end, ctx->sysCtx.timeRef)) != 0)
        return err;
    if (now < start || now > end)
        return X509CertChainInvalidErr;
    
    if ((err = X509VerifySignature(&chain->cert, &chain->cert)) != 0)
        return err;
    
    /* Verify the entire chain */
    while (chain->next != 0)
    {   start = chain->cert.startTime;
        end = chain->cert.endTime;
        if ((err = ctx->sysCtx.convertTime(&start, ctx->sysCtx.timeRef)) != 0 ||
            (err = ctx->sysCtx.convertTime(&end, ctx->sysCtx.timeRef)) != 0)
            return err;
        if (now < start || now > end)
            return X509CertChainInvalidErr;
        if ((err = X509VerifySignature(&chain->cert, &chain->next->cert)) != 0)
            return err;
        
        chain = chain->next;
    }
    
    return SSLNoErr;
}

⌨️ 快捷键说明

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