1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-30 16:24:09 +03:00

Can handle SSL chains which are out of order (thanks Paul Johnstone)

git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@254 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
cameronrich
2016-07-05 07:07:45 +00:00
committed by Yasuki Ikeuchi
parent 0d6e51aae4
commit acc38e3ab3

View File

@ -1855,32 +1855,97 @@ int process_certificate(SSL *ssl, X509_CTX **x509_ctx)
int ret = SSL_OK;
uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
int pkt_size = ssl->bm_index;
int cert_size, offset = 5;
int cert_size, offset = 5, offset_start;
int total_cert_size = (buf[offset]<<8) + buf[offset+1];
int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
X509_CTX **chain = x509_ctx;
X509_CTX *chain = 0;
X509_CTX **certs = 0;
int *cert_used = 0;
int num_certs = 0;
int i = 0;
offset += 2;
PARANOIA_CHECK(total_cert_size, offset);
// record the start point for the second pass
offset_start = offset;
// first pass - count the certificates
while (offset < total_cert_size)
{
offset++; /* skip empty char */
cert_size = (buf[offset]<<8) + buf[offset+1];
offset += 2;
offset += cert_size;
num_certs++;
}
PARANOIA_CHECK(pkt_size, offset);
certs = (X509_CTX**) calloc(num_certs, sizeof(void*));
cert_used = (int*) calloc(num_certs, sizeof(int));
num_certs = 0;
// restore the offset from the saved value
offset = offset_start;
// second pass - load the certificates
while (offset < total_cert_size)
{
offset++; /* skip empty char */
cert_size = (buf[offset]<<8) + buf[offset+1];
offset += 2;
if (x509_new(&buf[offset], NULL, chain))
if (x509_new(&buf[offset], NULL, certs+num_certs))
{
ret = SSL_ERROR_BAD_CERTIFICATE;
goto error;
}
chain = &((*chain)->next);
num_certs++;
offset += cert_size;
}
PARANOIA_CHECK(pkt_size, offset);
// third pass - link certs together, assume server cert is the first
*x509_ctx = certs[0];
chain = certs[0];
cert_used[0] = 1;
// repeat until the end of the chain is found
while (1)
{
// look for CA cert
for( i = 1; i < num_certs; i++ )
{
if (certs[i] == chain)
continue;
if (cert_used[i])
continue; // don't allow loops
if (asn1_compare_dn(chain->ca_cert_dn, certs[i]->cert_dn) == 0)
{
// CA cert found, add it to the chain
cert_used[i] = 1;
chain->next = certs[i];
chain = certs[i];
break;
}
}
// no CA cert found, reached the end of the chain
if (i >= num_certs)
break;
}
// clean up any certs that aren't part of the chain
for (i = 1; i < num_certs; i++)
{
if (cert_used[i] == 0)
x509_free(certs[i]);
}
/* if we are client we can do the verify now or later */
if (is_client && !IS_SET_SSL_FLAG(SSL_SERVER_VERIFY_LATER))
{
@ -1890,6 +1955,13 @@ int process_certificate(SSL *ssl, X509_CTX **x509_ctx)
ssl->next_state = is_client ? HS_SERVER_HELLO_DONE : HS_CLIENT_KEY_XCHG;
ssl->dc->bm_proc_index += offset;
error:
// clean up arrays
if (certs)
free(certs);
if (cert_used)
free(cert_used);
return ret;
}