diff options
Diffstat (limited to 'src/crypto')
-rw-r--r-- | src/crypto/x509.c | 55 |
1 files changed, 55 insertions, 0 deletions
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 <ipxe/rsa.h> #include <ipxe/rootcert.h> #include <ipxe/certstore.h> +#include <ipxe/socket.h> +#include <ipxe/in.h> #include <ipxe/x509.h> #include <config/crypto.h> @@ -1418,6 +1420,57 @@ static int x509_check_dnsname ( struct x509_certificate *cert, } /** + * 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 * * @v cert X.509 certificate @@ -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 ); |