From 8484e97f7c85e1c13d02951310d4f55bd3cb3323 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 11 Jul 2014 16:55:14 +0100 Subject: [crypto] Add support for iPAddress subject alternative names Originally-implemented-by: Jarrod Johnson Signed-off-by: Michael Brown --- src/crypto/x509.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'src/crypto') diff --git a/src/crypto/x509.c b/src/crypto/x509.c index 0502efa2..eeaf74bc 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -33,6 +33,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include +#include #include #include @@ -1417,6 +1419,57 @@ static int x509_check_dnsname ( struct x509_certificate *cert, return 0; } +/** + * Check X.509 certificate alternative iPAddress + * + * @v cert X.509 certificate + * @v raw ASN.1 cursor + * @v name Name + * @ret rc Return status code + */ +static int x509_check_ipaddress ( struct x509_certificate *cert, + const struct asn1_cursor *raw, + const char *name ) { + struct sockaddr sa; + sa_family_t family; + const void *address; + int rc; + + /* Determine address family */ + if ( raw->len == sizeof ( struct in_addr ) ) { + struct sockaddr_in *sin = ( ( struct sockaddr_in * ) &sa ); + family = AF_INET; + address = &sin->sin_addr; + } else if ( raw->len == sizeof ( struct in6_addr ) ) { + struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) &sa ); + family = AF_INET6; + address = &sin6->sin6_addr; + } else { + DBGC ( cert, "X509 %p \"%s\" has iPAddress with unexpected " + "length %zd\n", cert, x509_name ( cert ), raw->len ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return -EINVAL; + } + + /* Attempt to convert name to a socket address */ + if ( ( rc = sock_aton ( name, &sa ) ) != 0 ) { + DBGC2 ( cert, "X509 %p \"%s\" cannot parse \"%s\" as " + "iPAddress: %s\n", cert, x509_name ( cert ), name, + strerror ( rc ) ); + return rc; + } + if ( sa.sa_family != family ) + return -ENOENT; + + /* Compare addresses */ + if ( memcmp ( address, raw->data, raw->len ) != 0 ) + return -ENOENT; + + DBGC2 ( cert, "X509 %p \"%s\" found iPAddress match for \"%s\"\n", + cert, x509_name ( cert ), sock_ntoa ( &sa ) ); + return 0; +} + /** * Check X.509 certificate alternative name * @@ -1440,6 +1493,8 @@ static int x509_check_alt_name ( struct x509_certificate *cert, switch ( type ) { case X509_GENERAL_NAME_DNS : return x509_check_dnsname ( cert, &alt_name, name ); + case X509_GENERAL_NAME_IP : + return x509_check_ipaddress ( cert, &alt_name, name ); default: DBGC2 ( cert, "X509 %p \"%s\" unknown name of type %#02x:\n", cert, x509_name ( cert ), type ); -- cgit v1.2.3-55-g7522