📄 x509.c
字号:
/* *********************************************************************
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 + -