x509: add parse/print support for IPs in SAN

RFC 5280 defines many type of names to be used in the subjectAltName
extension of certificate. So far we only supported dNSName, but there is
demand for IP addresses too.

This is the first step, support for verification will be added in the next
commit.
This commit is contained in:
Manuel Pégourié-Gonnard 2016-01-28 10:50:58 +01:00
parent 803183f5fe
commit 3ad9437923
5 changed files with 113 additions and 14 deletions

View file

@ -1318,6 +1318,18 @@
*/
#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
/**
* \def MBEDTLS_X509_SAN_IP_ADDRESS_SUPPORT
*
* Enable support for IP addresses (IPv4 and IPv6) in subjectAltName in
* certificates. This includes parsing, printing with
* \c mbedtls_x509_crt_info(), and verification - see the documentation of
* \c mbedtls_x509_crt_verify_with_profile()
*
* Comment this macro to disallow using IP addresses in
*/
#define MBEDTLS_X509_SAN_IP_ADDRESS_SUPPORT
/**
* \def MBEDTLS_ZLIB_SUPPORT
*

View file

@ -414,6 +414,9 @@ static const char *features[] = {
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
"MBEDTLS_X509_RSASSA_PSS_SUPPORT",
#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
#if defined(MBEDTLS_X509_SAN_IP_ADDRESS_SUPPORT)
"MBEDTLS_X509_SAN_IP_ADDRESS_SUPPORT",
#endif /* MBEDTLS_X509_SAN_IP_ADDRESS_SUPPORT */
#if defined(MBEDTLS_ZLIB_SUPPORT)
"MBEDTLS_ZLIB_SUPPORT",
#endif /* MBEDTLS_ZLIB_SUPPORT */

View file

@ -438,8 +438,13 @@ static int x509_get_ext_key_usage( unsigned char **p,
* nameAssigner [0] DirectoryString OPTIONAL,
* partyName [1] DirectoryString }
*
* NOTE: we only parse and use dNSName at this point.
* NOTE: we only parse and use dNSName and iPAddress at this point.
* NOTE: update x509_info_subject_alt_name() and x509_crt_verify() if and when
* adding support for more name types.
*/
#define X509_CRT_SAN_DNS_NAME 2
#define X509_CRT_SAN_IP_ADDRESS 7
static int x509_get_subject_alt_name( unsigned char **p,
const unsigned char *end,
mbedtls_x509_sequence *subject_alt_name )
@ -474,8 +479,17 @@ static int x509_get_subject_alt_name( unsigned char **p,
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
/* Skip everything but DNS name */
if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) )
/* Skip everything but DNS name and IP address */
#if defined(MBEDTLS_X509_SAN_IP_ADDRESS_SUPPORT)
if( tag == ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | X509_CRT_SAN_IP_ADDRESS ) )
{
/* If IP adress, only valid lengths are 4 and 16 */
if( tag_len != 4 && tag_len != 16 )
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
}
else
#endif
if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | X509_CRT_SAN_DNS_NAME ) )
{
*p += tag_len;
continue;
@ -1213,20 +1227,74 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
const mbedtls_x509_sequence *cur = subject_alt_name;
const char *sep = "";
size_t sep_len = 0;
int ret;
while( cur != NULL )
{
if( cur->buf.len + sep_len >= n )
if( cur->buf.tag == ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | X509_CRT_SAN_DNS_NAME ) )
{
*p = '\0';
return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
}
if( cur->buf.len + sep_len >= n )
{
*p = '\0';
return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
}
n -= cur->buf.len + sep_len;
for( i = 0; i < sep_len; i++ )
*p++ = sep[i];
for( i = 0; i < cur->buf.len; i++ )
*p++ = cur->buf.p[i];
n -= cur->buf.len + sep_len;
for( i = 0; i < sep_len; i++ )
*p++ = sep[i];
for( i = 0; i < cur->buf.len; i++ )
*p++ = cur->buf.p[i];
}
#if defined(MBEDTLS_X509_SAN_IP_ADDRESS_SUPPORT)
else if( cur->buf.tag == ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | X509_CRT_SAN_IP_ADDRESS ) )
{
if( cur->buf.len == 4 )
{
ret = mbedtls_snprintf( p, n, "%sIP:%d.%d.%d.%d", sep,
cur->buf.p[0], cur->buf.p[1],
cur->buf.p[2], cur->buf.p[4] );
MBEDTLS_X509_SAFE_SNPRINTF;
}
else if( cur->buf.len == 16 )
{
if( sep_len + 2 >= n )
{
*p = '\0';
return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
}
memcpy( p, sep, sep_len );
p += sep_len;
n -= sep_len;
memcpy( p, "IP", 2 );
p += 2;
n -= 2;
for( i = 0; i < 8; i++ )
{
ret = mbedtls_snprintf( p, n, ":%02x%02x",
cur->buf.p[2 * i],
cur->buf.p[2 * i + 1] );
MBEDTLS_X509_SAFE_SNPRINTF;
}
}
else
{
ret = mbedtls_snprintf( p, n, "IP:???" );
MBEDTLS_X509_SAFE_SNPRINTF;
}
}
#endif /* MBEDTLS_X509_SAN_IP_ADDRESS_SUPPORT */
/*
* tag == 0 happens when the extension is present but with only unknow
* types: we get a list with one uninitialized element
*/
else if( cur->buf.tag != 0 )
{
ret = mbedtls_snprintf( p, n, "???unknown name type???" );
MBEDTLS_X509_SAFE_SNPRINTF;
}
sep = ", ";
sep_len = 2;

View file

@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIBrjCCATOgAwIBAgIBUDAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G
A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN
MTYwMTI3MTYzNDQzWhcNMjYwMTI0MTYzNDQzWjAPMQ0wCwYDVQQDEwRUZXN0MFkw
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCt
FLX3aCJZYpJO5QDYIxH/6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/6NRME8wTQYD
VR0RBEYwRIIIZm9vLnRlc3SCCGJhci50ZXN0hwR/AAABhwTAqAAqhxD+gAAAAAAA
AAAAAAAAAAABhxASNFZ4mrze8A/ey6mHZUMhMAoGCCqGSM49BAMCA2kAMGYCMQCI
TJvNYovxkfjoMcNqHMbrSSNAity3RSqrAA/loKCiw6kpsEOAItjXwxkHj0WH/4kC
MQDhdrbfoTxxD6AqNelMlpk2oE4c5ewsA2s53CLICqEy951jw47MqI+LYMmlsS/A
T5A=
-----END CERTIFICATE-----

View file

@ -99,8 +99,8 @@ depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C
x509_cert_info:"data_files/cert_example_multi.crt":"cert. version \: 3\nserial number \: 11\nissuer name \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nsubject name \: C=NL, O=PolarSSL, CN=www.example.com\nissued on \: 2012-05-10 13\:23\:41\nexpires on \: 2022-05-11 13\:23\:41\nsigned using \: RSA with SHA1\nRSA key size \: 2048 bits\nbasic constraints \: CA=false\nsubject alt name \: example.com, example.net, *.example.org\n"
X509 Certificate information, Subject Alt Name + Key Usage
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C
x509_cert_info:"data_files/cert_example_multi_nocn.crt":"cert. version \: 3\nserial number \: F7\:C6\:7F\:F8\:E9\:A9\:63\:F9\nissuer name \: C=NL\nsubject name \: C=NL\nissued on \: 2014-01-22 10\:04\:33\nexpires on \: 2024-01-22 10\:04\:33\nsigned using \: RSA with SHA1\nRSA key size \: 1024 bits\nbasic constraints \: CA=false\nsubject alt name \: www.shotokan-braunschweig.de, www.massimo-abate.eu\nkey usage \: Digital Signature, Non Repudiation, Key Encipherment\n"
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_X509_SAN_IP_ADDRESS_SUPPORT
x509_cert_info:"data_files/cert_example_multi_nocn.crt":"cert. version \: 3\nserial number \: F7\:C6\:7F\:F8\:E9\:A9\:63\:F9\nissuer name \: C=NL\nsubject name \: C=NL\nissued on \: 2014-01-22 10\:04\:33\nexpires on \: 2024-01-22 10\:04\:33\nsigned using \: RSA with SHA1\nRSA key size \: 1024 bits\nbasic constraints \: CA=false\nsubject alt name \: www.shotokan-braunschweig.de, www.massimo-abate.eu, IP\:192.168.1.135, IP\:192.168.69.48\nkey usage \: Digital Signature, Non Repudiation, Key Encipherment\n"
X509 Certificate information, Key Usage + Extended Key Usage
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C
@ -118,6 +118,10 @@ X509 Certificate information Bitstring in subject name
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C
x509_cert_info:"data_files/bitstring-in-dn.pem":"cert. version \: 3\nserial number \: 02\nissuer name \: CN=Test CA 01, ST=Ecnivorp, C=XX, emailAddress=tca@example.com, O=Test CA Authority\nsubject name \: C=XX, O=tca, ST=Ecnivorp, OU=TCA, CN=Client, emailAddress=client@example.com, serialNumber=7101012255, uniqueIdentifier=?7101012255\nissued on \: 2015-03-11 12\:06\:51\nexpires on \: 2025-03-08 12\:06\:51\nsigned using \: RSA with SHA1\nRSA key size \: 2048 bits\nbasic constraints \: CA=false\nsubject alt name \: \next key usage \: TLS Web Client Authentication\n"
X509 Certificate information SAN with IP
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_X509_SAN_IP_ADDRESS_SUPPORT
x509_cert_info:"data_files/server5-san-ip.crt":"cert. version \: 3\nserial number \: 50\nissuer name \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nsubject name \: CN=Test\nissued on \: 2016-01-27 16\:34\:43\nexpires on \: 2026-01-24 16\:34\:43\nsigned using \: ECDSA with SHA256\nEC key size \: 256 bits\nsubject alt name \: foo.test, bar.test, IP\:127.0.0.135, IP\:192.168.0.135, IP\:fe80\:0000\:0000\:0000\:0000\:0000\:0000\:0001, IP\:1234\:5678\:9abc\:def0\:0fde\:cba9\:8765\:4321\n"
X509 certificate v1 with extension
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
x509_cert_info:"data_files/cert_v1_with_ext.crt":"cert. version \: 1\nserial number \: BD\:ED\:44\:C7\:D2\:3E\:C2\:A4\nissuer name \: C=XX, ST=XX, L=XX, O=XX, OU=XX, emailAddress=admin@identity-check.org, CN=identity-check.org\nsubject name \: C=XX, ST=XX, L=XX, O=XX, OU=XX, emailAddress=admin@identity-check.org, CN=identity-check.org\nissued on \: 2013-07-04 16\:17\:02\nexpires on \: 2014-07-04 16\:17\:02\nsigned using \: RSA with SHA1\nRSA key size \: 2048 bits\nsubject alt name \: identity-check.org, www.identity-check.org\n"