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