summaryrefslogtreecommitdiffstats
path: root/src/crypto
diff options
context:
space:
mode:
authorMichael Brown2014-07-11 17:55:14 +0200
committerMichael Brown2014-07-11 17:55:14 +0200
commit8484e97f7c85e1c13d02951310d4f55bd3cb3323 (patch)
tree952e37d9ba99f0ae50961720798588c67089ecb1 /src/crypto
parent[efi] Include SNP NIC driver within the all-drivers target (diff)
downloadipxe-8484e97f7c85e1c13d02951310d4f55bd3cb3323.tar.gz
ipxe-8484e97f7c85e1c13d02951310d4f55bd3cb3323.tar.xz
ipxe-8484e97f7c85e1c13d02951310d4f55bd3cb3323.zip
[crypto] Add support for iPAddress subject alternative names
Originally-implemented-by: Jarrod Johnson <jarrod.b.johnson@gmail.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/x509.c55
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 );