1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-12 01:53:07 +03:00

Added SAN ("Subject Alternative Name" support

git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@159 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
cameronrich
2009-09-23 12:38:23 +00:00
parent 95e8c7998f
commit 2cedd59384
6 changed files with 166 additions and 8 deletions

View File

@ -42,6 +42,7 @@
#define SIG_OID_PREFIX_SIZE 8
#define SIG_IIS6_OID_SIZE 5
#define SIG_SUBJECT_ALT_NAME_SIZE 3
/* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */
static const uint8_t sig_oid_prefix[SIG_OID_PREFIX_SIZE] =
@ -54,6 +55,11 @@ static const uint8_t sig_iis6_oid[SIG_IIS6_OID_SIZE] =
0x2b, 0x0e, 0x03, 0x02, 0x1d
};
static const uint8_t sig_subject_alt_name[SIG_SUBJECT_ALT_NAME_SIZE] =
{
0x55, 0x1d, 0x11
};
/* CN, O, OU */
static const uint8_t g_dn_types[] = { 3, 10, 11 };
@ -284,6 +290,7 @@ static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str)
/* some certs have this awful crud in them for some reason */
if (buf[*offset] != ASN1_PRINTABLE_STR &&
buf[*offset] != ASN1_PRINTABLE_STR2 &&
buf[*offset] != ASN1_TELETEX_STR &&
buf[*offset] != ASN1_IA5_STR &&
buf[*offset] != ASN1_UNICODE_STR)
@ -471,7 +478,52 @@ int asn1_compare_dn(char * const dn1[], char * const dn2[])
return 0; /* all good */
}
#endif
int asn1_find_oid(const uint8_t* cert, int* offset,
const uint8_t* oid, int oid_length)
{
int seqlen;
if ((seqlen = asn1_next_obj(cert, offset, ASN1_SEQUENCE))> 0)
{
int end = *offset + seqlen;
while (*offset < end)
{
int type = cert[(*offset)++];
int length = get_asn1_length(cert, offset);
int noffset = *offset + length;
if (type == ASN1_SEQUENCE)
{
type = cert[(*offset)++];
length = get_asn1_length(cert, offset);
if (type == ASN1_OID && length == oid_length &&
memcmp(cert + *offset, oid, oid_length) == 0)
{
*offset += oid_length;
return 1;
}
}
*offset = noffset;
}
}
return 0;
}
int asn1_find_subjectaltname(const uint8_t* cert, int offset)
{
if (asn1_find_oid(cert, &offset, sig_subject_alt_name,
SIG_SUBJECT_ALT_NAME_SIZE))
{
return offset;
}
return 0;
}
#endif /* CONFIG_SSL_CERT_VERIFICATION */
/**
* Read the signature type of the certificate. We only support RSA-MD5 and

View File

@ -68,6 +68,7 @@ struct _x509_ctx
{
char *ca_cert_dn[X509_NUM_DN_TYPES];
char *cert_dn[X509_NUM_DN_TYPES];
char **subject_alt_dnsnames;
time_t not_before;
time_t not_after;
uint8_t *signature;
@ -104,16 +105,22 @@ const char * x509_display_error(int error);
#define ASN1_BIT_STRING 0x03
#define ASN1_OCTET_STRING 0x04
#define ASN1_NULL 0x05
#define ASN1_PRINTABLE_STR2 0x0C
#define ASN1_OID 0x06
#define ASN1_PRINTABLE_STR2 0x0C
#define ASN1_PRINTABLE_STR 0x13
#define ASN1_TELETEX_STR 0x14
#define ASN1_IA5_STR 0x16
#define ASN1_UTC_TIME 0x17
#define ASN1_UNICODE_STR 0x1e
#define ASN1_SEQUENCE 0x30
#define ASN1_CONTEXT_DNSNAME 0x82
#define ASN1_SET 0x31
#define ASN1_V3_DATA 0xa3
#define ASN1_IMPLICIT_TAG 0x80
#define ASN1_CONTEXT_DNSNAME 0x82
#define ASN1_EXPLICIT_TAG 0xa0
#define ASN1_V3_DATA 0xa3
#define SIG_TYPE_MD2 0x02
#define SIG_TYPE_MD5 0x04
@ -130,8 +137,9 @@ int asn1_name(const uint8_t *cert, int *offset, char *dn[]);
int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
#ifdef CONFIG_SSL_CERT_VERIFICATION
int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
int asn1_find_subjectaltname(const uint8_t* cert, int offset);
int asn1_compare_dn(char * const dn1[], char * const dn2[]);
#endif
#endif /* CONFIG_SSL_CERT_VERIFICATION */
int asn1_signature_type(const uint8_t *cert,
int *offset, X509_CTX *x509_ctx);

View File

@ -384,6 +384,23 @@ EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl);
*/
EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component);
/**
* @brief Retrieve a Subject Alternative DNSName
*
* When a handshake is complete and a certificate has been exchanged, then the
* details of the remote certificate can be retrieved.
*
* This will usually be used by a client to check that the server's common
* name matches the URL.
*
* @param ssl [in] An SSL object reference.
* @param index [in] The index of the DNS name to retrieve.
* @return The appropriate string (or null if not defined)
* @note Verification build mode must be enabled.
*/
EXP_FUNC const char * STDCALL ssl_get_cert_subject_alt_dnsname(const SSL *ssl, int dnsindex);
/**
* @brief Force the client to perform its handshake again.
*

View File

@ -419,6 +419,7 @@ error:
return ret;
}
/*
* Retrieve an X.509 distinguished name component
*/
@ -452,7 +453,27 @@ EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component)
}
}
#endif
/*
* Retrieve a "Subject Alternative Name" from a v3 certificate
*/
EXP_FUNC const char * STDCALL ssl_get_cert_subject_alt_dnsname(const SSL *ssl,
int dnsindex)
{
int i;
if (ssl->x509_ctx == NULL || ssl->x509_ctx->subject_alt_dnsnames == NULL)
return NULL;
for (i = 0; i < dnsindex; ++i)
{
if (ssl->x509_ctx->subject_alt_dnsnames[i] == NULL)
return NULL;
}
return ssl->x509_ctx->subject_alt_dnsnames[dnsindex];
}
#endif /* CONFIG_SSL_CERT_VERIFICATION */
/*
* Find an ssl object based on the client's file descriptor.
@ -879,7 +900,6 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt)
return (void *)aes_ctx;
}
break;
case SSL_RC4_128_MD5:
#endif
@ -889,7 +909,6 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt)
RC4_setup(rc4_ctx, key, 16);
return (void *)rc4_ctx;
}
break;
}
return NULL; /* its all gone wrong */
@ -1505,7 +1524,7 @@ void disposable_free(SSL *ssl)
{
if (ssl->dc)
{
free(ssl->dc->key_block);
free(ssl->dc->key_block);
memset(ssl->dc, 0, sizeof(DISPOSABLE_CTX));
free(ssl->dc);
ssl->dc = NULL;
@ -2045,12 +2064,19 @@ EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl)
return -1;
}
EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component)
{
printf(unsupported_str);
return NULL;
}
EXP_FUNC const char * STDCALL ssl_get_cert_subject_alt_dnsname(const SSL *ssl, int index)
{
printf(unsupported_str);
return NULL;
}
#endif /* CONFIG_SSL_CERT_VERIFICATION */
#endif /* CONFIG_BINDINGS */

View File

@ -147,7 +147,53 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
x509_ctx->digest = bi_import(bi_ctx, md2_dgst, MD2_SIZE);
}
offset = end_tbs; /* skip the v3 data */
if (cert[offset] == ASN1_V3_DATA)
{
int suboffset;
++offset;
get_asn1_length(cert, &offset);
if ((suboffset = asn1_find_subjectaltname(cert, offset)) > 0)
{
if (asn1_next_obj(cert, &suboffset, ASN1_OCTET_STRING) > 0)
{
int altlen;
if ((altlen = asn1_next_obj(cert,
&suboffset, ASN1_SEQUENCE)) > 0)
{
int endalt = suboffset + altlen;
int totalnames = 0;
while (suboffset < endalt)
{
int type = cert[suboffset++];
int dnslen = get_asn1_length(cert, &suboffset);
if (type == ASN1_CONTEXT_DNSNAME)
{
x509_ctx->subject_alt_dnsnames = (char**)
realloc(x509_ctx->subject_alt_dnsnames,
(totalnames + 2) * sizeof(char*));
x509_ctx->subject_alt_dnsnames[totalnames] =
(char*)malloc(dnslen + 1);
x509_ctx->subject_alt_dnsnames[totalnames+1] = NULL;
memcpy(x509_ctx->subject_alt_dnsnames[totalnames],
cert + suboffset, dnslen);
x509_ctx->subject_alt_dnsnames[
totalnames][dnslen] = 0;
++totalnames;
}
suboffset += dnslen;
}
}
}
}
}
offset = end_tbs; /* skip the rest of v3 data */
if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) ||
asn1_signature(cert, &offset, x509_ctx))
goto end_cert;
@ -188,6 +234,7 @@ void x509_free(X509_CTX *x509_ctx)
free(x509_ctx->cert_dn[i]);
}
free(x509_ctx->signature);
#ifdef CONFIG_SSL_CERT_VERIFICATION
@ -195,6 +242,14 @@ void x509_free(X509_CTX *x509_ctx)
{
bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
}
if (x509_ctx->subject_alt_dnsnames)
{
for (i = 0; x509_ctx->subject_alt_dnsnames[i]; ++i)
free(x509_ctx->subject_alt_dnsnames[i]);
free(x509_ctx->subject_alt_dnsnames);
}
#endif
RSA_free(x509_ctx->rsa_ctx);