summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/isakmpd/DESIGN-NOTES16
-rw-r--r--sbin/isakmpd/Makefile11
-rw-r--r--sbin/isakmpd/README.PKI59
-rw-r--r--sbin/isakmpd/cert.c28
-rw-r--r--sbin/isakmpd/cert.h28
-rw-r--r--sbin/isakmpd/exchange.c20
-rw-r--r--sbin/isakmpd/exchange.h12
-rw-r--r--sbin/isakmpd/ike_auth.c313
-rw-r--r--sbin/isakmpd/ike_phase_1.c6
-rw-r--r--sbin/isakmpd/init.c8
-rw-r--r--sbin/isakmpd/isakmpd.conf.527
-rw-r--r--sbin/isakmpd/regress/Makefile8
-rw-r--r--sbin/isakmpd/regress/rsakeygen/Makefile41
-rw-r--r--sbin/isakmpd/regress/rsakeygen/rsakeygen.c68
-rw-r--r--sbin/isakmpd/regress/x509/Makefile44
-rw-r--r--sbin/isakmpd/regress/x509/x509test.c191
-rw-r--r--sbin/isakmpd/samples/VPN-east.conf14
-rw-r--r--sbin/isakmpd/samples/VPN-west.conf14
-rw-r--r--sbin/isakmpd/samples/singlehost-east.conf41
-rw-r--r--sbin/isakmpd/samples/singlehost-west.conf43
-rw-r--r--sbin/isakmpd/sysdep/openbsd/Makefile.sysdep10
-rw-r--r--sbin/isakmpd/x509.c1155
-rw-r--r--sbin/isakmpd/x509.h64
23 files changed, 1262 insertions, 959 deletions
diff --git a/sbin/isakmpd/DESIGN-NOTES b/sbin/isakmpd/DESIGN-NOTES
index c4bb8934062..5937064de16 100644
--- a/sbin/isakmpd/DESIGN-NOTES
+++ b/sbin/isakmpd/DESIGN-NOTES
@@ -1,5 +1,5 @@
-$OpenBSD: DESIGN-NOTES,v 1.12 1999/07/07 22:14:56 niklas Exp $
-$EOM: DESIGN-NOTES,v 1.45 1999/06/15 11:33:37 niklas Exp $
+$OpenBSD: DESIGN-NOTES,v 1.13 1999/07/17 21:54:39 niklas Exp $
+$EOM: DESIGN-NOTES,v 1.46 1999/07/17 20:44:07 niklas Exp $
General coding conventions
--------------------------
@@ -334,6 +334,18 @@ In quick mode the identities are implicitly the IP addresses of the peers,
which must mean the IP addresses actually used for the ISAKMP tunnel.
Otherwise we today support IPV4_ADDR & IPV4_ADDR_SUBNET as ID types.
+X509-Certificates
+-----------------
+To use RSA Signature mode you are required to generate certificates.
+This can be done with ssleay, see man ssl. But the X509 certificates
+require a subjectAltname extension that can either be an IPV4 address,
+a User-FQDN or just FQDN. ssleay can not create those extension,
+insead use the x509test program in regress/x509 to modify an existing
+certificate. It will insert the subjectAltname extension and sign it
+with the provided private Key. The resulting certificate then needs
+to be stored in the directory pointed to by "Certs-directory" in
+section "X509-certificates".
+
License to use
--------------
/*
diff --git a/sbin/isakmpd/Makefile b/sbin/isakmpd/Makefile
index e14fef3bfca..caefedb7810 100644
--- a/sbin/isakmpd/Makefile
+++ b/sbin/isakmpd/Makefile
@@ -1,5 +1,5 @@
-# $OpenBSD: Makefile,v 1.18 1999/07/07 22:07:33 niklas Exp $
-# $EOM: Makefile,v 1.54 1999/06/07 00:00:49 ho Exp $
+# $OpenBSD: Makefile,v 1.19 1999/07/17 21:54:39 niklas Exp $
+# $EOM: Makefile,v 1.55 1999/07/17 20:44:07 niklas Exp $
#
# Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
@@ -50,14 +50,14 @@ OS= openbsd
PROG= isakmpd
BINDIR?= /sbin
-SRCS= app.c asn.c asn_useful.c attribute.c cert.c connection.c \
+SRCS= app.c attribute.c cert.c connection.c \
constants.c conf.c cookie.c crypto.c dh.c doi.c exchange.c \
exchange_num.c field.c gmp_util.c hash.c if.c ike_auth.c \
ike_aggressive.c ike_main_mode.c ike_phase_1.c \
ike_quick_mode.c init.c ipsec.c ipsec_fld.c ipsec_num.c \
isakmpd.c isakmp_doi.c isakmp_fld.c isakmp_num.c log.c \
message.c math_2n.c math_ec2n.c math_group.c \
- pkcs.c prf.c sa.c sysdep.c timer.c transport.c udp.c ui.c \
+ prf.c sa.c sysdep.c timer.c transport.c udp.c ui.c \
util.c x509.c
GENERATED= exchange_num.h ipsec_fld.h ipsec_num.h isakmp_fld.h \
@@ -111,8 +111,9 @@ DEBUG= -g
# strcpy (_y_, _x_); \
# })'
+SUBDIR= apps
.if !make(install)
-SUBDIR= regress
+SUBDIR+= regress
.endif
.include "sysdep/${OS}/Makefile.sysdep"
diff --git a/sbin/isakmpd/README.PKI b/sbin/isakmpd/README.PKI
new file mode 100644
index 00000000000..0021525487e
--- /dev/null
+++ b/sbin/isakmpd/README.PKI
@@ -0,0 +1,59 @@
+$OpenBSD: README.PKI,v 1.1 1999/07/17 21:54:39 niklas Exp $
+
+1 Create your own CA as root.
+
+ ssleay genrsa -out /etc/ssl/private/ca.key 1024
+ ssleay req -new -key /etc/ssl/private/ca.key \
+ -out /etc/ssl/private/ca.csr
+
+ You are now being asked to enter information that will be incorporated
+ into your certificate request. What you are about to enter is what is
+ called a Distinguished Name or a DN. There are quite a few fields but
+ you can leave some blank. For some fields there will be a default
+ value, if you enter '.', the field will be left blank.
+
+ ssleay x509 -req -days 365 -in /etc/ssl/private/ca.csr \
+ -signkey /etc/ssl/private/ca.key \
+ -out /etc/ssl/ca.crt
+
+2 Create keys and certificates for your isakmpd peers. This step as well
+ as the next one, needs to be done for every peer. Furthermore the
+ last step will need to be done once for each ID you want the peer
+ to have. The 10.0.0.1 below symbolizes that ID, and should be
+ changed for each invocation. You will be asked for a DN for each
+ run too. See to encode the ID in the common name too, so it gets
+ unique.
+
+ mkdir -p /etc/isakmpd/private /etc/isakmpd/ca /etc/isakmpd/certs
+ chmod 600 /etc/isakmpd/private
+ ssleay genrsa -out /etc/isakmpd/private/local.key 1024
+ ssleay req -new -key /etc/isakmpd/private/local.key \
+ -out /etc/isakmpd/private/10.0.0.1.csr
+
+ Now take these certificate signing requests to your CA and process
+ them like below. You have to add some extensions to the certificate
+ in order to make it usable for isakmpd, which is why you will need
+ to run certpatch. Replace 10.0.0.1 with the IP-address which isakmpd
+ will be using for identity.
+
+ ssleay x509 -req -days 365 -in 10.0.0.1.csr -CA /etc/ssl/ca.crt \
+ -CAkey /etc/ssl/private/ca.key -CAcreateserial \
+ -out 10.0.0.1.crt
+ certpatch -i 10.0.0.1 -k /etc/ssl/private/ca.key \
+ 10.0.0.1.crt 10.0.0.1.crt
+
+ Put the certificate (the file ending in .crt) in /etc/isakmpd/certs/
+ on your local system. Also carry over the CA cert /etc/ssl/ca.crt
+ and put it in /etc/isakmpd/ca/.
+
+3 See to that your config files will point out the directories where
+ you keep certificates. I.e. add something like this to
+ /etc/isakmp/conf:
+
+ # Certificates stored in PEM format
+ [X509-certificates]
+ CA-directory= /etc/isakmpd/ca/
+ Cert-directory= /etc/isakmpd/certs/
+
+ [RSA_SIG]
+ PRIVKEY= /etc/isakmpd/private/local.key
diff --git a/sbin/isakmpd/cert.c b/sbin/isakmpd/cert.c
index 3836bb8375e..c5e88c8155d 100644
--- a/sbin/isakmpd/cert.c
+++ b/sbin/isakmpd/cert.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: cert.c,v 1.9 1999/04/19 19:57:29 niklas Exp $ */
-/* $EOM: cert.c,v 1.10 1999/04/18 15:17:23 niklas Exp $ */
+/* $OpenBSD: cert.c,v 1.10 1999/07/17 21:54:39 niklas Exp $ */
+/* $EOM: cert.c,v 1.11 1999/07/17 20:44:09 niklas Exp $ */
/*
- * Copyright (c) 1998 Niels Provos. All rights reserved.
+ * Copyright (c) 1998, 1999 Niels Provos. All rights reserved.
* Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,9 +36,12 @@
*/
#include <sys/param.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ssl/ssl.h>
+
#include "sysdep.h"
#include "cert.h"
@@ -49,11 +52,30 @@
struct cert_handler cert_handler[] = {
{
ISAKMP_CERTENC_X509_SIG,
+ x509_cert_init, x509_cert_get, x509_cert_validate,
+ x509_cert_insert, x509_cert_free,
x509_certreq_validate, x509_certreq_decode, x509_free_aca,
x509_cert_obtain, x509_cert_get_key, x509_cert_get_subject
}
};
+/* Initialize all certificate handlers */
+
+int
+cert_init (void)
+{
+ int i, err = 1;
+
+ /* Add all algorithms know by SSL */
+ SSLeay_add_all_algorithms ();
+
+ for (i = 0; i < sizeof cert_handler / sizeof cert_handler[0]; i++)
+ if (cert_handler[i].cert_init && !(*cert_handler[i].cert_init) ())
+ err = 0;
+
+ return err;
+}
+
struct cert_handler *
cert_get (u_int16_t id)
{
diff --git a/sbin/isakmpd/cert.h b/sbin/isakmpd/cert.h
index c60909c6446..f083c7827be 100644
--- a/sbin/isakmpd/cert.h
+++ b/sbin/isakmpd/cert.h
@@ -1,8 +1,8 @@
-/* $OpenBSD: cert.h,v 1.3 1998/11/17 11:10:08 niklas Exp $ */
-/* $EOM: cert.h,v 1.5 1998/08/21 13:47:51 provos Exp $ */
+/* $OpenBSD: cert.h,v 1.4 1999/07/17 21:54:39 niklas Exp $ */
+/* $EOM: cert.h,v 1.6 1999/07/17 20:44:09 niklas Exp $ */
/*
- * Copyright (c) 1998 Niels Provos. All rights reserved.
+ * Copyright (c) 1998, 1999 Niels Provos. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -41,16 +41,29 @@
#include <sys/types.h>
#include <sys/queue.h>
-struct exchange;
+/*
+ * CERT handler for each kind of certificate:
+ *
+ * cert_init - Initialize CERT handler - called only once
+ * cert_get - Get a certificate in internal representation from raw data
+ * cert_validate - validated a certificate, if it returns != 0 we can use it.
+ * cert_insert - inserts cert into memory storage, we can retrieve with
+ * cert_obtain.
+ */
struct cert_handler {
u_int16_t id; /* ISAKMP Cert Encoding ID */
+ int (*cert_init) (void);
+ void *(*cert_get) (u_int8_t *, u_int32_t);
+ int (*cert_validate) (void *);
+ int (*cert_insert) (void *);
+ void (*cert_free) (void *);
int (*certreq_validate) (u_int8_t *, u_int32_t);
void *(*certreq_decode) (u_int8_t *, u_int32_t);
void (*free_aca) (void *);
- int (*cert_obtain) (struct exchange *, void *, u_int8_t **, u_int32_t *);
- int (*cert_get_key) (u_int8_t *, u_int32_t, void *);
- int (*cert_get_subject) (u_int8_t *, u_int32_t, u_int8_t **, u_int32_t *);
+ int (*cert_obtain) (u_int8_t *, size_t, void *, u_int8_t **, u_int32_t *);
+ int (*cert_get_key) (void *, void *);
+ int (*cert_get_subject) (void *, u_int8_t **, u_int32_t *);
};
/* the acceptable authority of cert request */
@@ -65,5 +78,6 @@ struct certreq_aca {
struct cert_handler *cert_get (u_int16_t);
struct certreq_aca *certreq_decode (u_int16_t, u_int8_t *, u_int32_t);
+int cert_init (void);
#endif /* _CERT_H_ */
diff --git a/sbin/isakmpd/exchange.c b/sbin/isakmpd/exchange.c
index cdc1ae59f05..a6d47e9580c 100644
--- a/sbin/isakmpd/exchange.c
+++ b/sbin/isakmpd/exchange.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: exchange.c,v 1.22 1999/07/07 22:05:06 niklas Exp $ */
-/* $EOM: exchange.c,v 1.108 1999/06/06 17:48:30 ho Exp $ */
+/* $OpenBSD: exchange.c,v 1.23 1999/07/17 21:54:39 niklas Exp $ */
+/* $EOM: exchange.c,v 1.109 1999/07/17 20:44:09 niklas Exp $ */
/*
* Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
@@ -1140,6 +1140,7 @@ exchange_free_aux (void *v_exch)
{
struct exchange *exchange = v_exch;
struct sa *sa, *next_sa;
+ struct cert_handler *handler;
log_debug (LOG_EXCHANGE, 80, "exchange_free_aux: freeing exchange %p",
exchange);
@@ -1166,6 +1167,14 @@ exchange_free_aux (void *v_exch)
free (exchange->data);
if (exchange->name)
free (exchange->name);
+ if (exchange->recv_cert)
+ {
+ handler = cert_get (exchange->recv_certtype);
+ if (handler)
+ handler->cert_free (exchange->recv_cert);
+ else if (exchange->recv_certtype == ISAKMP_CERTENC_NONE)
+ free (exchange->recv_cert);
+ }
exchange_free_aca_list (exchange);
LIST_REMOVE (exchange, link);
@@ -1430,12 +1439,17 @@ exchange_add_certs (struct message *msg)
struct certreq_aca *aca;
u_int8_t *cert;
u_int32_t certlen;
+ u_int8_t *id;
+ size_t id_len;
+
+ id = exchange->initiator ? exchange->id_r : exchange->id_i;
+ id_len = exchange->initiator ? exchange->id_r_len : exchange->id_i_len;
for (aca = TAILQ_FIRST (&exchange->aca_list); aca;
aca = TAILQ_NEXT (aca, link))
{
/* XXX? If we can not satisfy a CERTREQ we drop the message */
- if (!aca->handler->cert_obtain (exchange, aca->data, &cert, &certlen))
+ if (!aca->handler->cert_obtain (id, id_len, aca->data, &cert, &certlen))
{
log_print ("exchange_add_certs: could not obtain cert for a type %d "
"cert request", aca->id);
diff --git a/sbin/isakmpd/exchange.h b/sbin/isakmpd/exchange.h
index 3ef5d6e609a..ff5fe84f7d7 100644
--- a/sbin/isakmpd/exchange.h
+++ b/sbin/isakmpd/exchange.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: exchange.h,v 1.12 1999/07/07 22:09:53 niklas Exp $ */
-/* $EOM: exchange.h,v 1.25 1999/06/07 00:02:11 ho Exp $ */
+/* $OpenBSD: exchange.h,v 1.13 1999/07/17 21:54:39 niklas Exp $ */
+/* $EOM: exchange.h,v 1.26 1999/07/17 20:44:10 niklas Exp $ */
/*
* Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
@@ -150,6 +150,14 @@ struct exchange {
int key_length;
struct keystate *keystate;
+ /*
+ * Received certificate - used to verify signatures on packet,
+ * stored here for later policy processing.
+ * a type of ISAKMP_CERTENC_NONE implies pre-shared key.
+ */
+ int recv_certtype, recv_certlen;
+ void *recv_cert;
+
/* XXX This is no longer necessary, it is covered by policy. */
/* Acceptable authorities for cert requests */
diff --git a/sbin/isakmpd/ike_auth.c b/sbin/isakmpd/ike_auth.c
index d2c48e575b3..5b9859e309c 100644
--- a/sbin/isakmpd/ike_auth.c
+++ b/sbin/isakmpd/ike_auth.c
@@ -1,8 +1,9 @@
-/* $OpenBSD: ike_auth.c,v 1.14 1999/07/07 22:04:08 niklas Exp $ */
-/* $EOM: ike_auth.c,v 1.31 1999/06/10 13:29:02 niklas Exp $ */
+/* $OpenBSD: ike_auth.c,v 1.15 1999/07/17 21:54:39 niklas Exp $ */
+/* $EOM: ike_auth.c,v 1.32 1999/07/17 20:44:10 niklas Exp $ */
/*
* Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
+ * Copyright (c) 1999 Niels Provos. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -40,9 +41,12 @@
#include <stdlib.h>
#include <string.h>
+#include <ssl/evp.h>
+#include <ssl/pem.h>
+#include <ssl/x509.h>
+
#include "sysdep.h"
-#include "asn.h"
#include "cert.h"
#include "conf.h"
#include "constants.h"
@@ -55,7 +59,6 @@
#include "ipsec_doi.h"
#include "log.h"
#include "message.h"
-#include "pkcs.h"
#include "prf.h"
#include "transport.h"
#include "util.h"
@@ -109,39 +112,79 @@ ike_auth_get (u_int16_t id)
* Find and decode the configured key (pre-shared or public) for the
* peer denoted by ID. Stash the len in KEYLEN.
*/
-static char *
-ike_auth_get_key (char *id, size_t *keylen)
+static void *
+ike_auth_get_key (int type, char *id, size_t *keylen)
{
char *key, *buf;
+ char *keyfile;
+ BIO *keyh;
+ RSA *rsakey;
- /* Get the pre-shared key for our peer. */
- key = conf_get_str (id, "Authentication");
- if (!key)
+ switch (type)
{
- log_print ("ike_auth_get_key: no key found for peer \"%s\"", id);
- return 0;
- }
+ case IKE_AUTH_PRE_SHARED:
+ /* Get the pre-shared key for our peer. */
+ key = conf_get_str (id, "Authentication");
+ if (!key)
+ {
+ log_print ("ike_auth_get_key: no key found for peer \"%s\"", id);
+ return 0;
+ }
+
+ /* If the key starts with 0x it is in hex format. */
+ if (strncasecmp (key, "0x", 2) == 0)
+ {
+ *keylen = (strlen (key) - 1) / 2;
+ buf = malloc (*keylen);
+ if (!buf)
+ {
+ log_print ("ike_auth_get_key: malloc (%d) failed", *keylen);
+ return 0;
+ }
+ if (hex2raw (key + 2, buf, *keylen))
+ {
+ free (buf);
+ log_print ("ike_auth_get_key: invalid hex key %s", key);
+ return 0;
+ }
+ key = buf;
+ }
+ else
+ *keylen = strlen (key);
+ break;
- /* If the key starts with 0x it is in hex format. */
- if (strncasecmp (key, "0x", 2) == 0)
- {
- *keylen = (strlen (key) - 1) / 2;
- buf = malloc (*keylen);
- if (!buf)
+ case IKE_AUTH_RSA_SIG:
+ keyfile = conf_get_str ("RSA_sig", "privkey");
+
+ if ((keyh = BIO_new (BIO_s_file ())) == NULL)
{
- log_print ("ike_auth_get_key: malloc (%d) failed", *keylen);
+ log_print ("ike_auth_get_key: BIO_new() failed");
return 0;
}
- if (hex2raw (key + 2, buf, *keylen))
+ if (BIO_read_filename (keyh, keyfile) == -1)
{
- free (buf);
- log_print ("ike_auth_get_key: invalid hex key %s", key);
+ log_print ("ike_auth_get_key: BIO_read_filename(%s) failed",
+ keyfile);
+ BIO_free (keyh);
return 0;
}
- key = buf;
+
+ rsakey = PEM_read_bio_RSAPrivateKey (keyh, NULL, NULL);
+ if (!rsakey)
+ {
+ log_print ("ike_auth_get_key: PEM_read_bio_RSAPrivateKey failed",
+ keyfile);
+ BIO_free (keyh);
+ return 0;
+ }
+
+ BIO_free (keyh);
+ return rsakey;
+
+ default:
+ log_print ("ike_auth_get_key: unknown key type %d", type);
+ return 0;
}
- else
- *keylen = strlen (key);
return key;
}
@@ -157,10 +200,20 @@ pre_shared_gen_skeyid (struct exchange *exchange, size_t *sz)
size_t keylen;
/* Get the pre-shared key for our peer. */
- key = ike_auth_get_key (exchange->name, &keylen);
+ key = ike_auth_get_key (IKE_AUTH_PRE_SHARED, exchange->name, &keylen);
if (!key)
return 0;
+ /* Store the secret key for later policy processing */
+ exchange->recv_cert = malloc (keylen);
+ if (!exchange->recv_cert)
+ {
+ log_error ("pre_shared_gen_skeyid: malloc (%d) failed", keylen);
+ return 0;
+ }
+ exchange->recv_certlen = keylen;
+ exchange->recv_certtype = ISAKMP_CERTENC_NONE;
+
prf = prf_alloc (ie->prf_type, ie->hash->type, key, keylen);
if (buf)
free (buf);
@@ -310,12 +363,15 @@ rsa_sig_decode_hash (struct message *msg)
struct exchange *exchange = msg->exchange;
struct ipsec_exch *ie = exchange->data;
struct payload *p;
- struct rsa_public_key key;
+ void *cert;
+ u_int8_t *rawcert;
+ u_int32_t rawlen;
+ RSA *key;
size_t hashsize = ie->hash->hashsize;
char header[80];
int initiator = exchange->initiator;
u_int8_t **hash_p, *id_cert, *id;
- u_int16_t len;
+ int len;
u_int32_t id_cert_len;
size_t id_len;
int found = 0;
@@ -327,14 +383,50 @@ rsa_sig_decode_hash (struct message *msg)
if (!id || id_len == 0)
{
- log_print ("rsa_sig_decode_hash: no ID in sa");
+ log_print ("rsa_sig_decode_hash: ID is missing");
+ return -1;
+ }
+
+ /* XXX This needs to be configureable. */
+ handler = cert_get (ISAKMP_CERTENC_X509_SIG);
+ if (!handler)
+ {
+ log_print ("rsa_sig_decode_hash: "
+ "cert_get (ISAKMP_CERTENC_X509_SIG) failed");
return -1;
}
- /* Just bother with the ID data field. */
- id += ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
- id_len -= ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
+ /* Obtain a certificate from our certificate storage */
+ if (handler->cert_obtain (id, id_len, 0, &rawcert, &rawlen))
+ {
+ cert = handler->cert_get (rawcert, rawlen);
+ if (!cert)
+ log_debug (LOG_CRYPTO, 50,
+ "rsa_sig_decode_hash: certificate malformed");
+ else
+ {
+ if (!handler->cert_get_key (cert, &key))
+ {
+ log_print ("rsa_sig_decode_hash: decoding certificate failed");
+ handler->cert_free (cert);
+ }
+ else
+ {
+ found++;
+ log_debug (LOG_CRYPTO, 40,
+ "rsa_sig_decode_hash: using cert from X509_STORE");
+ exchange->recv_cert = cert;
+ exchange->recv_certtype = handler->id;
+ }
+ }
+ free (rawcert);
+ }
+ /*
+ * Walk over potential CERT payloads in this message.
+ * XXX I believe this is the wrong spot for this. CERTs can appear
+ * anytime.
+ */
for (p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_CERT]); p;
p = TAILQ_NEXT (p, link))
{
@@ -354,32 +446,51 @@ rsa_sig_decode_hash (struct message *msg)
continue;
}
- if (!handler->cert_get_subject (p->p + ISAKMP_CERT_DATA_OFF,
- GET_ISAKMP_GEN_LENGTH (p->p) -
- ISAKMP_CERT_DATA_OFF,
- &id_cert, &id_cert_len))
+ cert = handler->cert_get (p->p + ISAKMP_CERT_DATA_OFF,
+ GET_ISAKMP_GEN_LENGTH (p->p)
+ - ISAKMP_CERT_DATA_OFF);
+ if (!cert)
{
+ log_print ("rsa_sig_decode_hash: can not get data from CERT");
+ continue;
+ }
+
+ if (!handler->cert_validate (cert))
+ {
+ handler->cert_free (cert);
+ log_print ("rsa_sig_decode_hash: received CERT can't be validated");
+ continue;
+ }
+
+ if (!handler->cert_get_subject (cert, &id_cert, &id_cert_len))
+ {
+ handler->cert_free (cert);
log_print ("rsa_sig_decode_hash: can not get subject from CERT");
continue;
}
if (id_cert_len != id_len || memcmp (id, id_cert, id_len) != 0)
{
+ handler->cert_free (cert);
log_print ("rsa_sig_decode_hash: CERT subject does not match ID");
free (id_cert);
continue;
}
free (id_cert);
- if (!handler->cert_get_key (p->p + ISAKMP_CERT_DATA_OFF,
- GET_ISAKMP_GEN_LENGTH (p->p) -
- ISAKMP_CERT_DATA_OFF,
- &key))
+ if (!handler->cert_get_key (cert, &key))
{
+ handler->cert_free (cert);
log_print ("rsa_sig_decode_hash: decoding payload CERT failed");
continue;
}
+ /* We validated the cert, cache it for later use. */
+ handler->cert_insert (cert);
+
+ exchange->recv_cert = cert;
+ exchange->recv_certtype = GET_ISAKMP_CERT_ENCODING (p->p);
+
found++;
}
@@ -387,7 +498,7 @@ rsa_sig_decode_hash (struct message *msg)
if (!found)
{
#ifdef notyet
- rawkey = ike_auth_get_key (exchange->name, &keylen);
+ rawkey = ike_auth_get_key (IKE_AUTH_RSA_SIG, exchange->name, &keylen);
if (!rawkey)
{
log_print ("rsa_sig_decode_hash: no public key found");
@@ -403,32 +514,44 @@ rsa_sig_decode_hash (struct message *msg)
if (!p)
{
log_print ("rsa_sig_decode_hash: missing signature payload");
- pkcs_free_public_key (&key);
+ RSA_free (key);
return -1;
}
/* Check that the sig is of the correct size. */
- if (GET_ISAKMP_GEN_LENGTH (p->p) - ISAKMP_SIG_SZ != mpz_sizeinoctets (key.n))
+ len = GET_ISAKMP_GEN_LENGTH (p->p) - ISAKMP_SIG_SZ;
+ if (len != RSA_size (key))
{
- pkcs_free_public_key (&key);
+ RSA_free (key);
log_print ("rsa_sig_decode_hash: "
"SIG payload length does not match public key");
return -1;
}
- if (!pkcs_rsa_decrypt (PKCS_PRIVATE, &key, 0, p->p + ISAKMP_SIG_DATA_OFF,
- hash_p, &len))
+ *hash_p = malloc (len);
+ if (!*hash_p)
{
- pkcs_free_public_key (&key);
+ RSA_free (key);
+ log_error ("rsa_sig_decode_hash: malloc (%d) failed", len);
return -1;
}
- pkcs_free_public_key (&key);
+ len = RSA_public_decrypt (len, p->p + ISAKMP_SIG_DATA_OFF, *hash_p, key,
+ RSA_PKCS1_PADDING);
+ if (len == -1)
+ {
+ RSA_free (key);
+ log_print ("rsa_sig_decode_hash: RSA_public_decrypt () failed");
+ return -1;
+ }
+
+ RSA_free (key);
if (len != hashsize)
{
free (*hash_p);
*hash_p = 0;
+ log_print ("rsa_sig_decode_hash: len %d != hashsize %d", len, hashsize);
return -1;
}
@@ -472,87 +595,93 @@ rsa_sig_encode_hash (struct message *msg)
struct ipsec_exch *ie = exchange->data;
size_t hashsize = ie->hash->hashsize;
struct cert_handler *handler;
- struct rsa_private_key key;
+ RSA *key;
char header[80];
int initiator = exchange->initiator;
- u_int8_t *buf, *asn, *data;
- u_int32_t asnlen, datalen;
- char *keyfile;
+ u_int8_t *buf, *data;
+ u_int32_t datalen;
+ u_int8_t *id;
+ size_t id_len;
+
+ id = initiator ? exchange->id_i : exchange->id_r;
+ id_len = initiator ? exchange->id_i_len : exchange->id_r_len;
/* XXX This needs to be configureable. */
handler = cert_get (ISAKMP_CERTENC_X509_SIG);
if (!handler)
{
- /* XXX Log? */
- return -1;
- }
- /* XXX Implicitly uses exchange->id_{i,r}. */
- if (!handler->cert_obtain (exchange, 0, &data, &datalen))
- {
- /* XXX Log? */
+ log_print ("rsa_sig_decode_hash: "
+ "cert_get(ISAKMP_CERTENC_X509_SIG) failed");
return -1;
}
- buf = realloc (data, ISAKMP_CERT_SZ + datalen);
- if (!buf)
- {
- log_error ("rsa_sig_encode_hash: realloc (%p, %d) failed", data,
- ISAKMP_CERT_SZ + datalen);
- free (data);
- return -1;
- }
- memmove (buf + ISAKMP_CERT_SZ, buf, datalen);
- SET_ISAKMP_CERT_ENCODING (buf, ISAKMP_CERTENC_X509_SIG);
- if (message_add_payload (msg, ISAKMP_PAYLOAD_CERT, buf,
- ISAKMP_CERT_SZ + datalen, 1))
+ /* Find a certificate with subjectAltName = id. */
+ if (handler->cert_obtain (id, id_len, 0, &data, &datalen))
{
- free (buf);
- return -1;
+ buf = realloc (data, ISAKMP_CERT_SZ + datalen);
+ if (!buf)
+ {
+ log_error ("rsa_sig_encode_hash: realloc (%p, %d) failed", data,
+ ISAKMP_CERT_SZ + datalen);
+ free (data);
+ return -1;
+ }
+ memmove (buf + ISAKMP_CERT_SZ, buf, datalen);
+ SET_ISAKMP_CERT_ENCODING (buf, ISAKMP_CERTENC_X509_SIG);
+ if (message_add_payload (msg, ISAKMP_PAYLOAD_CERT, buf,
+ ISAKMP_CERT_SZ + datalen, 1))
+ {
+ free (buf);
+ return -1;
+ }
}
+ else
+ log_debug (LOG_MISC, 10, "rsa_sig_decode_hash: no certificate to send");
- /* XXX Do we want to store our files in ASN.1? */
- keyfile = conf_get_str ("RSA_sig", "privkey");
- if (!asn_get_from_file (keyfile, &asn, &asnlen))
- {
- /* XXX Log? */
- return -1;
- }
-
- if (!pkcs_private_key_from_asn (&key, asn, asnlen))
+ key = ike_auth_get_key (IKE_AUTH_RSA_SIG, exchange->name, NULL);
+ if (key == NULL)
{
- /* XXX Log? */
- free (asn);
+ log_error ("rsa_sig_encode_hash: could not get private key");
return -1;
}
- free (asn);
- /* XXX hashsize is not necessarily prf->blocksize */
+ /* XXX hashsize is not necessarily prf->blocksize. */
buf = malloc (hashsize);
if (!buf)
{
log_error ("rsa_sig_encode_hash: malloc (%d) failed", hashsize);
- pkcs_free_private_key (&key);
+ RSA_free (key);
return -1;
}
if (ike_auth_hash (exchange, buf) == -1)
{
free (buf);
- pkcs_free_private_key (&key);
+ RSA_free (key);
return -1;
}
snprintf (header, 80, "rsa_sig_encode_hash: HASH_%c", initiator ? 'I' : 'R');
log_debug_buf (LOG_MISC, 80, header, buf, hashsize);
- if (!pkcs_rsa_encrypt (PKCS_PRIVATE, 0, &key, buf, hashsize, &data,
- &datalen))
+ data = malloc (RSA_size (key));
+ if (!data)
{
+ log_error ("rsa_sig_encode_hash: malloc (%d) failed", RSA_size (key));
+ RSA_free (key);
+ return -1;
+ }
+
+ datalen = RSA_private_encrypt (hashsize, buf, data, key, RSA_PKCS1_PADDING);
+ if (datalen == -1)
+ {
+ log_error ("rsa_sig_encode_hash: RSA_private_encrypt () failed");
free (buf);
- pkcs_free_private_key (&key);
+ RSA_free (key);
return -1;
}
- pkcs_free_private_key (&key);
+
+ RSA_free (key);
free (buf);
buf = realloc (data, ISAKMP_SIG_SZ + datalen);
diff --git a/sbin/isakmpd/ike_phase_1.c b/sbin/isakmpd/ike_phase_1.c
index f605a77d96e..13c1f1656d5 100644
--- a/sbin/isakmpd/ike_phase_1.c
+++ b/sbin/isakmpd/ike_phase_1.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ike_phase_1.c,v 1.5 1999/07/16 02:01:59 niklas Exp $ */
-/* $EOM: ike_phase_1.c,v 1.6 1999/07/16 02:01:52 niklas Exp $ */
+/* $OpenBSD: ike_phase_1.c,v 1.6 1999/07/17 21:54:39 niklas Exp $ */
+/* $EOM: ike_phase_1.c,v 1.7 1999/07/17 20:44:10 niklas Exp $ */
/*
* Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
@@ -925,7 +925,7 @@ ike_phase_1_recv_AUTH (struct message *msg)
/* The decoded hash will be in ie->hash_r or ie->hash_i */
if (ie->ike_auth->decode_hash (msg))
{
- message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0);
+ message_drop (msg, ISAKMP_NOTIFY_INVALID_ID_INFORMATION, 0, 1, 0);
return -1;
}
diff --git a/sbin/isakmpd/init.c b/sbin/isakmpd/init.c
index bfcb5d97868..94d7a22917e 100644
--- a/sbin/isakmpd/init.c
+++ b/sbin/isakmpd/init.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: init.c,v 1.8 1999/07/07 22:09:54 niklas Exp $ */
-/* $EOM: init.c,v 1.15 1999/06/07 00:02:14 ho Exp $ */
+/* $OpenBSD: init.c,v 1.9 1999/07/17 21:54:39 niklas Exp $ */
+/* $EOM: init.c,v 1.16 1999/07/17 20:44:10 niklas Exp $ */
/*
* Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
@@ -39,6 +39,7 @@
#include "sysdep.h"
#include "app.h"
+#include "cert.h"
#include "conf.h"
#include "connection.h"
#include "cookie.h"
@@ -74,6 +75,9 @@ init ()
connection_init ();
cookie_init ();
+ /* Depends on conf_init having run */
+ cert_init ();
+
sa_init ();
transport_init ();
udp_init ();
diff --git a/sbin/isakmpd/isakmpd.conf.5 b/sbin/isakmpd/isakmpd.conf.5
index 8ce40029b2b..0060d151e23 100644
--- a/sbin/isakmpd/isakmpd.conf.5
+++ b/sbin/isakmpd/isakmpd.conf.5
@@ -1,5 +1,5 @@
-.\" $OpenBSD: isakmpd.conf.5,v 1.21 1999/07/09 13:35:49 aaron Exp $
-.\" $EOM: isakmpd.conf.5,v 1.26 1999/07/07 19:17:31 niklas Exp $
+.\" $OpenBSD: isakmpd.conf.5,v 1.22 1999/07/17 21:54:39 niklas Exp $
+.\" $EOM: isakmpd.conf.5,v 1.27 1999/07/17 20:44:11 niklas Exp $
.\"
.\" Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
.\"
@@ -130,6 +130,20 @@ at <IPSec-connection> below. Currently only the Local-ID and Remote-ID tags
are looked at in those sections, as they are matched against the IDs given
by the initiator.
.El
+.It Em X509-Certificates
+.Bl -tag -width 12n
+.It Em Ca-directory
+A directory containing PEM certificates of certification authorities
+that we trust to sign other certificates.
+.It Em Cert-directory
+A directory containing PEM certificates that we trust to be valid.
+These certificates are used in preference to those passed in messages and
+are required to have a SubjectAltName extension.
+.It Em Accept-self-signed
+If this tag is defined, whatever the value is, certificates that
+do not originate from a trusted CA but are self-signed will be
+accepted.
+.El
.El
.Ss Referred-to sections
.Bl -hang -width 12n
@@ -389,6 +403,11 @@ DOI= IPSEC
EXCHANGE_TYPE= ID_PROT
Transforms= 3DES-SHA
+# Certificates stored in PEM format
+[X509-certificates]
+CA-directory= /etc/isakmpd/ca/
+Cert-directory= /etc/isakmpd/certs/
+
# Main mode transforms
######################
@@ -644,9 +663,7 @@ LIFE_TYPE= KILOBYTES
LIFE_DURATION= 4608000,4096000:8192000
[RSA_SIG]
-CERT= /etc/isakmpd_cert
-PRIVKEY= /etc/isakmpd_key
-PUBKEY= /etc/isakmpd_key.pub
+PRIVKEY= /etc/isakmpd/private/local.key
.Ed
.Sh SEE ALSO
.Xr ipsec 4 ,
diff --git a/sbin/isakmpd/regress/Makefile b/sbin/isakmpd/regress/Makefile
index 0253e40ec24..23c845ae88d 100644
--- a/sbin/isakmpd/regress/Makefile
+++ b/sbin/isakmpd/regress/Makefile
@@ -1,8 +1,8 @@
-# $OpenBSD: Makefile,v 1.6 1999/02/26 03:28:59 niklas Exp $
-# $EOM: Makefile,v 1.7 1998/08/11 20:32:01 provos Exp $
+# $OpenBSD: Makefile,v 1.7 1999/07/17 21:54:38 niklas Exp $
+# $EOM: Makefile,v 1.8 1999/07/17 20:44:13 niklas Exp $
#
-# Copyright (c) 1998 Niklas Hallqvist. All rights reserved.
+# Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -34,6 +34,6 @@
# This code was written under funding by Ericsson Radio Systems.
#
-SUBDIR= asn b2n crypto dh ec2n exchange group hmac pkcs prf rsakeygen x509
+SUBDIR= b2n crypto dh ec2n exchange group hmac prf rsakeygen x509
.include <bsd.subdir.mk>
diff --git a/sbin/isakmpd/regress/rsakeygen/Makefile b/sbin/isakmpd/regress/rsakeygen/Makefile
index 92f7a4a10f6..b9868e57767 100644
--- a/sbin/isakmpd/regress/rsakeygen/Makefile
+++ b/sbin/isakmpd/regress/rsakeygen/Makefile
@@ -1,16 +1,49 @@
-# $OpenBSD: Makefile,v 1.5 1999/03/02 15:27:36 niklas Exp $
-# $EOM: Makefile,v 1.3 1999/02/25 15:12:01 niklas Exp $
+# $OpenBSD: Makefile,v 1.6 1999/07/17 21:54:38 niklas Exp $
+# $EOM: Makefile,v 1.4 1999/07/17 20:44:13 niklas Exp $
+
+#
+# Copyright (c) 1999 Niels Provos. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by Ericsson Radio Systems.
+# 4. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+#
+# This code was written under funding by Ericsson Radio Systems.
+#
# RSA Key Generation
PROG= rsakeygen
-SRCS= log.c asn.c gmp_util.c pkcs.c rsakeygen.c sysdep.c
+SRCS= log.c rsakeygen.c sysdep.c
TOPSRC= ${.CURDIR}/../..
TOPOBJ!= cd ${TOPSRC}; printf "all:\n\t@pwd\n" |${MAKE} -f-
OS!= awk '/^OS=/ { print $$2 }' ${.CURDIR}/../../Makefile
.PATH: ${TOPSRC} ${TOPSRC}/sysdep/${OS} ${TOPOBJ}
CFLAGS+= -I${TOPSRC} -I${TOPSRC}/sysdep/${OS} -I${TOPOBJ} -Wall
-LDADD+= -lgmp
+LDADD+= -lgmp -lcrypto
DPADD+= ${LIBDES}
NOMAN=
DEBUG= -g
diff --git a/sbin/isakmpd/regress/rsakeygen/rsakeygen.c b/sbin/isakmpd/regress/rsakeygen/rsakeygen.c
index fbc4be408c1..684896c3297 100644
--- a/sbin/isakmpd/regress/rsakeygen/rsakeygen.c
+++ b/sbin/isakmpd/regress/rsakeygen/rsakeygen.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: rsakeygen.c,v 1.7 1999/04/27 21:02:56 niklas Exp $ */
-/* $EOM: rsakeygen.c,v 1.7 1999/04/05 18:27:38 niklas Exp $ */
+/* $OpenBSD: rsakeygen.c,v 1.8 1999/07/17 21:54:38 niklas Exp $ */
+/* $EOM: rsakeygen.c,v 1.8 1999/07/17 20:44:13 niklas Exp $ */
/*
- * Copyright (c) 1998 Niels Provos. All rights reserved.
+ * Copyright (c) 1998, 1999 Niels Provos. All rights reserved.
* Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,15 +42,16 @@
#include <string.h>
#include <gmp.h>
+#include <ssl/rsa.h>
+
#include "log.h"
-#include "gmp_util.h"
-#include "asn.h"
-#include "pkcs.h"
#define nibble2bin(y) (tolower((y)) < 'a' ? (y) - '0': tolower((y)) - 'a' + 10)
#define hexchar2bin(x) ((nibble2bin((x)[0]) << 4) + nibble2bin((x)[1]))
#define nibble2c(x) ((x) >= 10 ? ('a'-10+(x)) : ('0' + (x)))
+#define TEST_STRING "!Dies ist ein Test"
+
void asc2bin (u_int8_t *bin, u_int8_t *asc, u_int16_t len)
{
int i;
@@ -64,60 +65,67 @@ void asc2bin (u_int8_t *bin, u_int8_t *asc, u_int16_t len)
int
main (void)
{
- char *data = "Niels ist ein Luser!";
- u_int8_t *enc, *dec, *asn;
- u_int32_t enclen;
- u_int16_t len;
+ u_int8_t enc[256], dec[256], *asn, *foo;
+ int len;
FILE *fd;
int erg = 0;
- struct rsa_public_key key;
- struct rsa_private_key priv;
+ RSA *key;
log_debug_cmd ((enum log_classes)LOG_CRYPTO, 99);
- pkcs_generate_rsa_keypair (&key, &priv, 1024);
+ strcpy(dec, TEST_STRING);
+
+ key = RSA_generate_key(1024, RSA_F4, NULL, NULL);
+ if (key == NULL)
+ {
+ printf("Failed to generate key\n");
+ return 0;
+ }
- printf ("n: 0x"); mpz_out_str (stdout, 16, key.n);
- printf ("\ne: 0x"); mpz_out_str (stdout, 16, key.e);
+ printf ("n: 0x"); BN_print_fp(stdout, key->n);
+ printf ("\ne: 0x"); BN_print_fp (stdout, key->e);
printf ("\n");
- printf ("n: 0x"); mpz_out_str (stdout, 16, priv.n);
- printf ("\ne: 0x"); mpz_out_str (stdout, 16, priv.e);
- printf ("\nd: 0x"); mpz_out_str (stdout, 16, priv.d);
- printf ("\np: 0x"); mpz_out_str (stdout, 16, priv.p);
- printf ("\nq: 0x"); mpz_out_str (stdout, 16, priv.q);
+ printf ("n: 0x"); BN_print_fp (stdout, key->n);
+ printf ("\ne: 0x"); BN_print_fp (stdout, key->e);
+ printf ("\nd: 0x"); BN_print_fp (stdout, key->d);
+ printf ("\np: 0x"); BN_print_fp (stdout, key->p);
+ printf ("\nq: 0x"); BN_print_fp (stdout, key->q);
printf ("\n");
printf ("Testing Signing/Verifying: ");
/* Sign with Private Key */
- if (!pkcs_rsa_encrypt (PKCS_PRIVATE, NULL, &priv, data, strlen(data)+1,
- &enc, &enclen))
+ if ((len = RSA_private_encrypt (strlen(dec)+1, dec, enc, key,
+ RSA_PKCS1_PADDING)) == -1)
printf ("FAILED ");
else
/* Decrypt/Verify with Public Key */
- erg = pkcs_rsa_decrypt (PKCS_PRIVATE, &key, NULL, enc, &dec, &len);
+ erg = RSA_public_decrypt (len, enc, dec, key, RSA_PKCS1_PADDING);
- if (!erg || strcmp(data,dec))
+ if (erg == -1 || strcmp(dec, TEST_STRING))
printf ("FAILED ");
else
printf ("OKAY ");
printf ("\n");
- asn = pkcs_public_key_to_asn (&key);
+ len = i2d_RSAPublicKey(key, NULL);
+ foo = asn = malloc(len);
+ len = i2d_RSAPublicKey(key, &foo);
fd = fopen ("isakmpd_key.pub", "w");
- fwrite (asn, asn_get_len (asn), 1, fd);
+ fwrite (asn, len, 1, fd);
fclose (fd);
free (asn);
- asn = pkcs_private_key_to_asn (&priv);
+ len = i2d_RSAPrivateKey(key, NULL);
+ foo = asn = malloc(len);
+ len = i2d_RSAPrivateKey(key, &foo);
fd = fopen ("isakmpd_key", "w");
- fwrite (asn, asn_get_len (asn), 1, fd);
+ fwrite (asn, len, 1, fd);
fclose (fd);
free (asn);
- pkcs_free_public_key (&key);
- pkcs_free_private_key (&priv);
+ RSA_free(key);
return 1;
}
diff --git a/sbin/isakmpd/regress/x509/Makefile b/sbin/isakmpd/regress/x509/Makefile
index 0097e050cee..27a8f11784f 100644
--- a/sbin/isakmpd/regress/x509/Makefile
+++ b/sbin/isakmpd/regress/x509/Makefile
@@ -1,17 +1,51 @@
-# $OpenBSD: Makefile,v 1.5 1999/03/02 15:27:36 niklas Exp $
-# $EOM: Makefile,v 1.5 1999/02/25 15:10:11 niklas Exp $
+# $OpenBSD: Makefile,v 1.6 1999/07/17 21:54:38 niklas Exp $
+# $EOM: Makefile,v 1.6 1999/07/17 20:44:13 niklas Exp $
+
+#
+# Copyright (c) 1999 Niels Provos. All rights reserved.
+# Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by Ericsson Radio Systems.
+# 4. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+#
+# This code was written under funding by Ericsson Radio Systems.
+#
# Test X509
PROG= x509test
-SRCS= x509test.c conf.c asn.c asn_useful.c gmp_util.c log.c pkcs.c \
- sysdep.c hash.c x509.c
+SRCS= x509test.c conf.c log.c sysdep.c x509.c field.c util.c \
+ isakmp_fld.c ipsec_fld.c ipsec_num.c isakmp_num.c constants.c
TOPSRC= ${.CURDIR}/../..
TOPOBJ!= cd ${TOPSRC}; printf "all:\n\t@pwd\n" |${MAKE} -f-
OS!= awk '/^OS=/ { print $$2 }' ${.CURDIR}/../../Makefile
.PATH: ${TOPSRC} ${TOPSRC}/sysdep/${OS} ${TOPOBJ}
CFLAGS+= -I${TOPSRC} -I${TOPSRC}/sysdep/${OS} -I${TOPOBJ} -Wall
-LDADD+= -lgmp
+LDADD+= -lgmp -lcrypto
DPADD+= ${LIBDES}
NOMAN=
DEBUG= -g
diff --git a/sbin/isakmpd/regress/x509/x509test.c b/sbin/isakmpd/regress/x509/x509test.c
index 8ee150e979a..2c070dc6788 100644
--- a/sbin/isakmpd/regress/x509/x509test.c
+++ b/sbin/isakmpd/regress/x509/x509test.c
@@ -1,8 +1,9 @@
-/* $OpenBSD: x509test.c,v 1.7 1999/07/07 22:14:31 niklas Exp $ */
-/* $EOM: x509test.c,v 1.5 1999/06/10 13:39:20 niklas Exp $ */
+/* $OpenBSD: x509test.c,v 1.8 1999/07/17 21:54:38 niklas Exp $ */
+/* $EOM: x509test.c,v 1.6 1999/07/17 20:44:14 niklas Exp $ */
/*
- * Copyright (c) 1998 Niels Provos. All rights reserved.
+ * Copyright (c) 1998, 1999 Niels Provos. All rights reserved.
+ * Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,6 +35,14 @@
* This code was written under funding by Ericsson Radio Systems.
*/
+/*
+ * This program takes a certificate generated by ssleay and a key pair
+ * from rsakeygen. It reads the IP address from certificate.txt and
+ * includes this as subject alt name extension into the certifcate.
+ * The result gets written as new certificate that can be used by
+ * isakmpd.
+ */
+
#include <sys/param.h>
#include <sys/types.h>
#include <sys/mman.h>
@@ -43,23 +52,25 @@
#include <stdio.h>
#include <gmp.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ssl/rsa.h>
+#include <ssl/x509.h>
+#include <ssl/pem.h>
+
#include "conf.h"
-#include "asn.h"
-#include "asn_useful.h"
-#include "pkcs.h"
-#include "x509.h"
#include "log.h"
+#include "ipsec_num.h"
+#include "x509.h"
u_int32_t file_sz;
-#define LINECOL(x,y) (x) = strsep (&(y), "\n\r"); \
- (x) = strchr ((x), ':') + 1; \
- while (isspace((x)[0])) (x)++; \
-
-
u_int8_t *
open_file (char *name)
{
@@ -84,83 +95,123 @@ open_file (char *name)
}
int
-main (void)
+main (int argc, char *argv[])
{
- struct rsa_private_key priv;
- struct x509_certificate cert;
- FILE *fd;
- char *p, *p2;
- u_int8_t *addr, *asn;
- u_int32_t asnlen, len;
-
- addr = open_file ("isakmpd_key");
- if (!pkcs_private_key_from_asn (&priv, addr, asn_get_len (addr)))
+ RSA *pub_key, *priv_key;
+ X509 *cert;
+ BIO *certfile, *keyfile;
+ EVP_PKEY *pkey_pub;
+ u_char ipaddr[6];
+ struct in_addr saddr;
+ char enc[256], dec[256];
+ u_int8_t idpayload[8];
+ int err, len;
+
+ if (argc < 3 || argc > 4)
{
- munmap (addr, file_sz);
+ fprintf (stderr, "usage: x509test private-key certificate ip-address\n");
exit (1);
}
- munmap (addr, file_sz);
- addr = open_file ("isakmpd_key.pub");
- if (!pkcs_public_key_from_asn (&cert.key, addr, asn_get_len (addr)))
+ /*
+ * X509_verify will fail, as will all other functions that call
+ * EVP_get_digest_byname.
+ */
+
+ SSLeay_add_all_algorithms ();
+
+ printf ("Reading private key %s\n", argv[1]);
+ keyfile = BIO_new (BIO_s_file ());
+ if (BIO_read_filename (keyfile, argv[1]) == -1)
{
- munmap (addr, file_sz);
+ perror ("read");
exit (1);
}
- munmap (addr, file_sz);
-
- cert.signaturetype = strdup (ASN_ID_MD5WITHRSAENC);
- cert.issuer1.type = strdup (ASN_ID_COUNTRY_NAME);
- cert.issuer2.type = strdup (ASN_ID_ORGANIZATION_NAME);
- cert.subject1.type = strdup (ASN_ID_COUNTRY_NAME);
- cert.subject2.type = strdup (ASN_ID_ORGANIZATION_NAME);
-
- addr = open_file ("certificate.txt");
- p = addr;
-
- LINECOL (p2, p); cert.version = atoi (p2);
- LINECOL (p2, p); cert.serialnumber = atoi (p2);
- LINECOL (p2, p); cert.issuer1.val = strdup (p2);
- LINECOL (p2, p); cert.issuer2.val = strdup (p2);
- LINECOL (p2, p); cert.subject1.val = strdup (p2);
- LINECOL (p2, p); cert.subject2.val = strdup (p2);
- LINECOL (p2, p); cert.start = strdup (p2);
- LINECOL (p2, p); cert.end = strdup (p2);
- munmap (addr, file_sz);
-
- /* XXX Just put any IP number in there. */
- cert.extension.type = strdup (ASN_ID_SUBJECT_ALT_NAME);
- cert.extension.val = p = malloc (8);
- /* XXX This could also be encoded as norm_type, but time is lacking. */
- p[0] = 0x30; p[1] = 0x06; p[2] = 0x87; p[3] = 0x04;
- memset (p + 4, 0, 4);
-
- printf ("Encoding Certificate: ");
- if (!x509_encode_certificate(&cert, &asn, &asnlen))
- printf ("FAILED ");
+ priv_key = PEM_read_bio_RSAPrivateKey (keyfile, NULL, NULL);
+ BIO_free (keyfile);
+ if (priv_key == NULL)
+ {
+ printf("PEM_read_bio_RSAPrivateKey () failed\n");
+ exit (1);
+ }
+
+ /* Use a certificate created by ssleay. */
+ printf ("Reading ssleay created certificate %s\n", argv[2]);
+ certfile = BIO_new (BIO_s_file ());
+ if (BIO_read_filename (certfile, argv[2]) == -1)
+ {
+ perror ("read");
+ exit (1);
+ }
+ cert = PEM_read_bio_X509 (certfile, NULL, NULL);
+ BIO_free (certfile);
+ if (cert == NULL)
+ {
+ printf("PEM_read_bio_X509 () failed\n");
+ exit (1);
+ }
+
+ pkey_pub = X509_get_pubkey (cert);
+ /* XXX Violation of the interface? */
+ pub_key = pkey_pub->pkey.rsa;
+ if (pub_key == NULL)
+ {
+ exit (1);
+ }
+
+ printf ("Testing RSA keys: ");
+
+ err = 0;
+ strcpy (dec, "Eine kleine Testmeldung");
+ if ((len = RSA_private_encrypt (strlen (dec), dec, enc, priv_key,
+ RSA_PKCS1_PADDING)) == -1)
+
+ printf ("SIGN FAILED ");
else
- printf ("OKAY ");
- printf ("\n");
+ err = RSA_public_decrypt (len, enc, dec, pub_key, RSA_PKCS1_PADDING);
- printf ("Creating Signature: ");
- if (!x509_create_signed (asn, asnlen, &priv, &addr, &len))
- printf ("FAILED ");
+ if (err == -1 || strcmp (dec, "Eine kleine Testmeldung"))
+ printf ("SIGN/VERIFY FAILED");
else
- printf ("OKAY ");
+ printf ("OKAY");
printf ("\n");
+
printf ("Validate SIGNED: ");
- if (!x509_validate_signed (addr, len, &cert.key, &asn, &asnlen))
+ err = X509_verify (cert, pkey_pub);
+ printf ("X509 verify: %d ", err);
+ if (err == -1)
printf ("FAILED ");
else
printf ("OKAY ");
printf ("\n");
- fd = fopen ("cert.asn", "w");
- fwrite (addr, len, 1, fd);
- fclose (fd);
-
- free (addr);
+ if (argc == 4)
+ {
+ printf ("Verifying extension: ");
+ if (inet_aton (argv[3], &saddr) == -1)
+ {
+ printf ("inet_aton () failed\n");
+ exit (1);
+ }
+
+ saddr.s_addr = htonl (saddr.s_addr);
+ ipaddr[0] = 0x87;
+ ipaddr[1] = 0x04;
+ ipaddr[2] = saddr.s_addr >> 24;
+ ipaddr[3] = (saddr.s_addr >> 16) & 0xff;
+ ipaddr[4] = (saddr.s_addr >> 8) & 0xff;
+ ipaddr[5] = saddr.s_addr & 0xff;
+ bzero (idpayload, sizeof idpayload);
+ idpayload[0] = IPSEC_ID_IPV4_ADDR;
+ bcopy (ipaddr + 2, idpayload + 4, 4);
+
+ if (!x509_check_subjectaltname (idpayload, sizeof idpayload, cert))
+ printf("FAILED ");
+ else
+ printf("OKAY ");
+ printf ("\n");
+ }
return 1;
}
diff --git a/sbin/isakmpd/samples/VPN-east.conf b/sbin/isakmpd/samples/VPN-east.conf
index 1a04a5b0e5b..f5a457a7982 100644
--- a/sbin/isakmpd/samples/VPN-east.conf
+++ b/sbin/isakmpd/samples/VPN-east.conf
@@ -1,5 +1,5 @@
-# $OpenBSD: VPN-east.conf,v 1.4 1999/04/05 21:07:43 niklas Exp $
-# $EOM: VPN-east.conf,v 1.5 1999/04/05 21:01:45 niklas Exp $
+# $OpenBSD: VPN-east.conf,v 1.5 1999/07/17 21:54:38 niklas Exp $
+# $EOM: VPN-east.conf,v 1.6 1999/07/17 20:44:14 niklas Exp $
# A configuration sample for the isakmpd ISAKMP/Oakley (aka IKE) daemon.
@@ -309,7 +309,11 @@ LIFE_DURATION= 32768,16384:65536
LIFE_TYPE= KILOBYTES
LIFE_DURATION= 4608000,4096000:8192000
+# Certificates stored in PEM format
+[X509-certificates]
+CA-directory= /etc/isakmpd/ca/
+Cert-directory= /etc/isakmpd/certs/
+#Accept-self-signed=
+
[RSA_SIG]
-CERT= /etc/isakmpd_cert
-PRIVKEY= /etc/isakmpd_key
-PUBKEY= /etc/isakmpd_key.pub
+PRIVKEY= /etc/isakmpd/private/local.key
diff --git a/sbin/isakmpd/samples/VPN-west.conf b/sbin/isakmpd/samples/VPN-west.conf
index c8b68d17fab..c4ff9e69c49 100644
--- a/sbin/isakmpd/samples/VPN-west.conf
+++ b/sbin/isakmpd/samples/VPN-west.conf
@@ -1,5 +1,5 @@
-# $OpenBSD: VPN-west.conf,v 1.4 1999/04/05 21:08:11 niklas Exp $
-# $EOM: VPN-west.conf,v 1.5 1999/04/05 21:01:46 niklas Exp $
+# $OpenBSD: VPN-west.conf,v 1.5 1999/07/17 21:54:38 niklas Exp $
+# $EOM: VPN-west.conf,v 1.6 1999/07/17 20:44:14 niklas Exp $
# A configuration sample for the isakmpd ISAKMP/Oakley (aka IKE) daemon.
@@ -309,7 +309,11 @@ LIFE_DURATION= 32768,16384:65536
LIFE_TYPE= KILOBYTES
LIFE_DURATION= 4608000,4096000:8192000
+# Certificates stored in PEM format
+[X509-certificates]
+CA-directory= /etc/isakmpd/ca/
+Cert-directory= /etc/isakmpd/certs/
+#Accept-self-signed=
+
[RSA_SIG]
-CERT= /etc/isakmpd_cert
-PRIVKEY= /etc/isakmpd_key
-PUBKEY= /etc/isakmpd_key.pub
+PRIVKEY= /etc/isakmpd/private/local.key
diff --git a/sbin/isakmpd/samples/singlehost-east.conf b/sbin/isakmpd/samples/singlehost-east.conf
index bac9f34666c..3c7263b4a59 100644
--- a/sbin/isakmpd/samples/singlehost-east.conf
+++ b/sbin/isakmpd/samples/singlehost-east.conf
@@ -1,5 +1,5 @@
-# $OpenBSD: singlehost-east.conf,v 1.2 1999/04/05 20:57:13 niklas Exp $
-# $EOM: singlehost-east.conf,v 1.2 1999/04/05 18:32:48 niklas Exp $
+# $OpenBSD: singlehost-east.conf,v 1.3 1999/07/17 21:54:38 niklas Exp $
+# $EOM: singlehost-east.conf,v 1.3 1999/07/17 20:44:16 niklas Exp $
# A configuration sample for the isakmpd ISAKMP/Oakley (aka IKE) daemon.
@@ -12,6 +12,7 @@ Shared-SADB= Defined
# Incoming phase 1 negotiations are multiplexed on the source IP address
[Phase 1]
10.1.0.1= ISAKMP-peer-west
+Default= ISAKMP-peer-west-aggressive
# These connections are walked over after config file parsing and told
# to the application layer so that it will inform us when traffic wants to
@@ -31,6 +32,18 @@ Configuration= Default-main-mode
Authentication= mekmitasdigoat
Flags= Stayalive
+[ISAKMP-peer-west-aggressive]
+Phase= 1
+Transport= udp
+Local-address= 10.1.0.2
+Address= 10.1.0.1
+# Default values for "Port" commented out
+#Port= isakmp
+#Port= 500
+Configuration= Default-aggressive-mode
+Authentication= mekmitasdigoat
+Flags= Stayalive
+
[IPsec-east-west]
Phase= 2
ISAKMP-peer= ISAKMP-peer-west
@@ -49,13 +62,18 @@ ID-type= IPV4_ADDR_SUBNET
Network= 192.168.2.0
Netmask= 255.255.255.0
-# Main mode descriptions
+# Phase 1 descriptions
[Default-main-mode]
DOI= IPSEC
EXCHANGE_TYPE= ID_PROT
Transforms= 3DES-SHA
+[Default-aggressive-mode]
+DOI= IPSEC
+EXCHANGE_TYPE= AGGRESSIVE
+Transforms= 3DES-SHA-RSA
+
# Main mode transforms
######################
@@ -91,6 +109,13 @@ AUTHENTICATION_METHOD= PRE_SHARED
GROUP_DESCRIPTION= MODP_1024
Life= LIFE_180_SECS
+[3DES-SHA-RSA]
+ENCRYPTION_ALGORITHM= 3DES_CBC
+HASH_ALGORITHM= SHA
+AUTHENTICATION_METHOD= RSA_SIG
+GROUP_DESCRIPTION= MODP_1024
+Life= LIFE_180_SECS
+
# Blowfish
[BLF-SHA-M1024]
@@ -318,7 +343,11 @@ LIFE_DURATION= 32768,16384:65536
LIFE_TYPE= KILOBYTES
LIFE_DURATION= 4608000,4096000:8192000
+# Certificates stored in PEM format
+[X509-certificates]
+CA-directory= /etc/isakmpd/ca/
+Cert-directory= /etc/isakmpd/certs/
+#Accept-self-signed=
+
[RSA_SIG]
-CERT= /etc/isakmpd_cert
-PRIVKEY= /etc/isakmpd_key
-PUBKEY= /etc/isakmpd_key.pub
+PRIVKEY= /etc/isakmpd/private/local.key
diff --git a/sbin/isakmpd/samples/singlehost-west.conf b/sbin/isakmpd/samples/singlehost-west.conf
index 0cce7fd092d..ce501155355 100644
--- a/sbin/isakmpd/samples/singlehost-west.conf
+++ b/sbin/isakmpd/samples/singlehost-west.conf
@@ -1,5 +1,5 @@
-# $OpenBSD: singlehost-west.conf,v 1.2 1999/04/05 20:57:25 niklas Exp $
-# $EOM: singlehost-west.conf,v 1.2 1999/04/05 18:32:49 niklas Exp $
+# $OpenBSD: singlehost-west.conf,v 1.3 1999/07/17 21:54:38 niklas Exp $
+# $EOM: singlehost-west.conf,v 1.3 1999/07/17 20:44:16 niklas Exp $
# A configuration sample for the isakmpd ISAKMP/Oakley (aka IKE) daemon.
@@ -12,6 +12,7 @@ Shared-SADB= Defined
# Incoming phase 1 negotiations are multiplexed on the source IP address
[Phase 1]
10.1.0.2= ISAKMP-peer-east
+Default= ISAKMP-peer-east-aggressive
# These connections are walked over after config file parsing and told
# to the application layer so that it will inform us when traffic wants to
@@ -28,6 +29,20 @@ Address= 10.1.0.2
#Port= isakmp
#Port= 500
Configuration= Default-main-mode
+Identification= IPV4_ADDR/10.1.0.1
+Authentication= mekmitasdigoat
+Flags= Stayalive
+
+[ISAKMP-peer-east-aggressive]
+Phase= 1
+Transport= udp
+Local-address= 10.1.0.1
+Address= 10.1.0.2
+# Default values for "Port" commented out
+#Port= isakmp
+#Port= 500
+Configuration= Default-aggressive-mode
+Identification= FQDN/diego.niklas.hallqvist.se
Authentication= mekmitasdigoat
Flags= Stayalive
@@ -49,13 +64,18 @@ ID-type= IPV4_ADDR_SUBNET
Network= 192.168.2.0
Netmask= 255.255.255.0
-# Main mode descriptions
+# Phase 1 descriptions
[Default-main-mode]
DOI= IPSEC
EXCHANGE_TYPE= ID_PROT
Transforms= 3DES-SHA
+[Default-aggressive-mode]
+DOI= IPSEC
+EXCHANGE_TYPE= AGGRESSIVE
+Transforms= 3DES-SHA-RSA
+
# Main mode transforms
######################
@@ -91,6 +111,13 @@ AUTHENTICATION_METHOD= PRE_SHARED
GROUP_DESCRIPTION= MODP_1024
Life= LIFE_180_SECS
+[3DES-SHA-RSA]
+ENCRYPTION_ALGORITHM= 3DES_CBC
+HASH_ALGORITHM= SHA
+AUTHENTICATION_METHOD= RSA_SIG
+GROUP_DESCRIPTION= MODP_1024
+Life= LIFE_180_SECS
+
# Blowfish
[BLF-SHA-M1024]
@@ -318,7 +345,11 @@ LIFE_DURATION= 32768,16384:65536
LIFE_TYPE= KILOBYTES
LIFE_DURATION= 4608000,4096000:8192000
+# Certificates stored in PEM format
+[X509-certificates]
+CA-directory= /etc/isakmpd/ca/
+Cert-directory= /etc/isakmpd/certs/
+#Accept-self-signed=
+
[RSA_SIG]
-CERT= /etc/isakmpd_cert
-PRIVKEY= /etc/isakmpd_key
-PUBKEY= /etc/isakmpd_key.pub
+PRIVKEY= /etc/isakmpd/private/local.key
diff --git a/sbin/isakmpd/sysdep/openbsd/Makefile.sysdep b/sbin/isakmpd/sysdep/openbsd/Makefile.sysdep
index 403974c7d73..95de74742e0 100644
--- a/sbin/isakmpd/sysdep/openbsd/Makefile.sysdep
+++ b/sbin/isakmpd/sysdep/openbsd/Makefile.sysdep
@@ -1,5 +1,5 @@
-# $OpenBSD: Makefile.sysdep,v 1.4 1999/07/07 22:05:48 niklas Exp $
-# $EOM: Makefile.sysdep,v 1.4 1999/06/07 00:02:49 ho Exp $
+# $OpenBSD: Makefile.sysdep,v 1.5 1999/07/17 21:54:39 niklas Exp $
+# $EOM: Makefile.sysdep,v 1.5 1999/07/17 20:44:16 niklas Exp $
#
# Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
@@ -25,7 +25,7 @@
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# THEORY OF LIABILITY, WHETHER INN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
@@ -34,8 +34,8 @@
# This code was written under funding by Ericsson Radio Systems.
#
-LDADD+= -lgmp -ldes
-DPADD+= ${LIBGMP} ${LIBDES}
+LDADD+= -lgmp -ldes -lcrypto
+DPADD+= ${LIBGMP} ${LIBDES} ${LIBCRYPTO}
SRCS+= pf_key_v2.c
CFLAGS+= -DUSE_PF_KEY_V2
diff --git a/sbin/isakmpd/x509.c b/sbin/isakmpd/x509.c
index 548f22cf31f..9ecf5c76cd0 100644
--- a/sbin/isakmpd/x509.c
+++ b/sbin/isakmpd/x509.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: x509.c,v 1.11 1999/07/07 22:15:42 niklas Exp $ */
-/* $EOM: x509.c,v 1.16 1999/06/15 11:21:19 niklas Exp $ */
+/* $OpenBSD: x509.c,v 1.12 1999/07/17 21:54:39 niklas Exp $ */
+/* $EOM: x509.c,v 1.17 1999/07/17 20:44:12 niklas Exp $ */
/*
- * Copyright (c) 1998 Niels Provos. All rights reserved.
+ * Copyright (c) 1998, 1999 Niels Provos. All rights reserved.
* Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,12 +38,18 @@
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <dirent.h>
#include <fcntl.h>
#include <gmp.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <ssl/x509.h>
+#include <ssl/x509_vfy.h>
+#include <ssl/pem.h>
+
#include "sysdep.h"
#include "conf.h"
@@ -53,842 +59,679 @@
#include "sa.h"
#include "ipsec.h"
#include "log.h"
-#include "asn.h"
-#include "asn_useful.h"
-#include "pkcs.h"
#include "x509.h"
-/* X509 Certificate Handling functions */
+/*
+ * X509_STOREs do not support subjectAltNames, so we have to build
+ * our own hash table.
+ */
-/* Validate the BER Encoding of a RDNSequence in the CERT_REQ payload. */
-int
-x509_certreq_validate (u_int8_t *asn, u_int32_t len)
-{
- struct norm_type name = SEQOF ("issuer", RDNSequence);
- int res = 1;
+/*
+ * XXX Actually this store is not really useful, we never use it as we have
+ * our own hash table. It also gets collisons if we have several certificates
+ * only differing in subjectAltName.
+ */
+static X509_STORE *x509_certs;
+static X509_STORE *x509_cas;
- if (!asn_template_clone (&name, 1)
- || (asn = asn_decode_sequence (asn, len, &name)) == 0)
- {
- log_print ("x509_certreq_validate: can not decode 'acceptable CA' info");
- res = 0;
- }
- asn_free (&name);
+/* Initial number of bits used as hash. */
+#define INITIAL_BUCKET_BITS 6
- return res;
-}
+struct x509_hash {
+ LIST_ENTRY (x509_hash) link;
-/* Decode the BER Encoding of a RDNSequence in the CERT_REQ payload. */
-void *
-x509_certreq_decode (u_int8_t *asn, u_int32_t len)
-{
- struct norm_type aca = SEQOF ("aca", RDNSequence);
- struct norm_type *tmp;
- struct x509_aca naca, *ret;
+ X509 *cert;
+};
- if (!asn_template_clone (&aca, 1)
- || (asn = asn_decode_sequence (asn, len, &aca)) == 0)
- {
- log_print ("x509_certreq_validate: can not decode 'acceptable CA' info");
- goto fail;
- }
- memset (&naca, 0, sizeof (naca));
+static LIST_HEAD (x509_list, x509_hash) *x509_tab;
- tmp = asn_decompose ("aca.RelativeDistinguishedName.AttributeValueAssertion",
- &aca);
- if (!tmp)
- goto fail;
- x509_get_attribval (tmp, &naca.name1);
+/* Works both as a maximum index and a mask. */
+static int bucket_mask;
- tmp = asn_decompose ("aca.RelativeDistinguishedName[1]"
- ".AttributeValueAssertion", &aca);
- if (tmp)
- x509_get_attribval (tmp, &naca.name2);
-
- asn_free (&aca);
+u_int16_t
+x509_hash (u_int8_t *id, size_t len)
+{
+ int i;
+ u_int16_t bucket = 0;
- ret = malloc (sizeof (struct x509_aca));
- if (ret)
- memcpy (ret, &naca, sizeof (struct x509_aca));
- else
+ /* XXX We might resize if we are crossing a certain threshold. */
+ len &= ~2;
+ for (i = 0; i < len; i += 2)
{
- log_error ("x509_certreq_decode: malloc (%d) failed",
- sizeof (struct x509_aca));
- x509_free_aca (&aca);
+ /* Doing it this way avoids alignment problems. */
+ bucket ^= (id[i] + 1) * (id[i + 1] + 257);
}
- return ret;
+ bucket &= bucket_mask;
- fail:
- asn_free (&aca);
- return 0;
+ return bucket;
}
void
-x509_free_aca (void *blob)
+x509_hash_init ()
{
- struct x509_aca *aca = blob;
+ int i;
+
+ bucket_mask = (1 << INITIAL_BUCKET_BITS) - 1;
+ x509_tab = malloc ((bucket_mask + 1) * sizeof (struct x509_list));
+ if (!x509_tab)
+ log_fatal ("x509_hash_init: malloc (%d) failed",
+ (bucket_mask + 1) * sizeof (struct x509_list));
+ for (i = 0; i <= bucket_mask; i++)
+ {
+ LIST_INIT (&x509_tab[i]);
+ }
+}
- if (aca->name1.type)
- free (aca->name1.type);
- if (aca->name1.val)
- free (aca->name1.val);
+/* Lookup a certificate by an ID blob. */
+X509 *
+x509_hash_find (u_int8_t *id, size_t len)
+{
+ struct x509_hash *cert;
+ u_int8_t *cid;
+ size_t clen;
- if (aca->name2.type)
- free (aca->name2.type);
- if (aca->name2.val)
- free (aca->name2.val);
+ for (cert = LIST_FIRST (&x509_tab[x509_hash (id, len)]); cert;
+ cert = LIST_NEXT (cert, link))
+ {
+ if (!x509_cert_get_subject (cert->cert, &cid, &clen))
+ continue;
+
+ if (clen != len || memcmp (id, cid, len) != 0)
+ {
+ free (cid);
+ continue;
+ }
+ free (cid);
+
+ log_debug (LOG_CRYPTO, 70, "x509_hash_find: return X509 %p", cert->cert);
+ return cert->cert;
+ }
+
+ log_debug (LOG_CRYPTO, 70, "x509_hash_find: no certificate matched query");
+ return 0;
}
-/*
- * Obtain a Certificate from an acceptable Certification Authority.
- * XXX This is where all the magic should happen, but yet here
- * you will find nothing.
- */
int
-x509_cert_obtain (struct exchange *exchange, void *data, u_int8_t **cert,
- u_int32_t *certlen)
+x509_hash_enter (X509 *cert)
{
- struct x509_aca *aca = data;
- struct ipsec_exch *ie = exchange->data;
- char *certfile;
- int fd, res = 0;
- struct stat st;
- u_int8_t *id_cert, *asn, *id;
- size_t id_len;
- u_int32_t id_cert_len;
-
- if (aca)
- log_debug (LOG_CRYPTO, 60, "x509_cert_obtain: (%s) %s, (%s) %s",
- asn_parse_objectid (asn_ids, aca->name1.type), aca->name1.val,
- asn_parse_objectid (asn_ids, aca->name2.type), aca->name2.val);
+ u_int16_t bucket = 0;
+ u_int8_t *id;
+ u_int32_t len;
+ struct x509_hash *certh;
- /* XXX This needs to be changed - but how else would I know? */
- switch (ie->ike_auth->id)
+ if (!x509_cert_get_subject (cert, &id, &len))
{
- case IKE_AUTH_RSA_SIG:
- certfile = conf_get_str ("RSA_sig", "cert");
- if (!certfile)
- return 0;
- break;
- default:
+ log_print ("x509_hash_enter: can not retrieve subjectAltName");
return 0;
}
- if (stat (certfile, &st) == -1)
+ certh = malloc (sizeof *certh);
+ if (!certh)
{
- log_error ("x509_cert_obtain: failed to state %s", certfile);
+ free (id);
+ log_error ("x509_hash_enter: malloc (%d) failed", sizeof *certh);
return 0;
}
+ memset (certh, 0, sizeof *certh);
+
+ certh->cert = cert;
- *certlen = st.st_size;
+ bucket = x509_hash (id, len);
+ free (id);
+
+ LIST_INSERT_HEAD (&x509_tab[bucket], certh, link);
+ log_debug (LOG_CRYPTO, 70, "x509_hash_enter: cert %p added to bucket %d",
+ cert, bucket);
+ return 1;
+}
- if ((fd = open (certfile, O_RDONLY)) == -1)
+/* X509 Certificate Handling functions. */
+
+int
+x509_read_from_dir (X509_STORE *ctx, char *name, int hash)
+{
+ DIR *dir;
+ struct dirent *file;
+ BIO *certh;
+ X509 *cert;
+ char fullname[PATH_MAX];
+ int off, size;
+
+ if (strlen (name) >= sizeof fullname - 1)
{
- log_error ("x509_cert_obtain: failed to open %s", certfile);
+ log_print ("x509_read_from_dir: directory name too long");
return 0;
}
-
- *cert = malloc (st.st_size);
- if (!*cert)
- {
- log_error ("x509_cert_obtain: malloc (%d) failed", st.st_size);
- res = 0;
- goto done;
- }
- if (read (fd, *cert, st.st_size) != st.st_size)
+ log_debug (LOG_CRYPTO, 40, "x509_read_from_dir: reading certs from %s",
+ name);
+
+ dir = opendir (name);
+ if (!dir)
{
- log_print ("x509_cert_obtain: cert file ended early");
- free (*cert);
- res = 0;
- goto done;
+ log_error ("x509_read_from_dir: opendir (\"%s\") failed", name);
+ return 0;
}
- /*
- * XXX We assume IPv4 here and a certificate with an extension
- * type of subjectAltName at the end. This can go once the saved
- * certificate is only used with one host with a fixed IP address.
- */
- id = exchange->initiator ? exchange->id_i : exchange->id_r;
- id_len = exchange->initiator ? exchange->id_i_len : exchange->id_r_len;
+ strncpy (fullname, name, sizeof fullname - 1);
+ fullname[sizeof fullname - 1] = 0;
+ off = strlen (fullname);
+ size = sizeof fullname - off - 1;
- /* XXX We need our ID to set that in the cert. */
- if (id)
+ while ((file = readdir (dir)) != NULL)
{
- id += ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
- id_len -= ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
+ if (file->d_type != DT_REG && file->d_type != DT_LNK)
+ continue;
- /* Get offset into data structure where the IP is saved. */
- asn = *cert;
- id_cert_len = asn_get_data_len (0, &asn, &id_cert);
- asn = id_cert;
- id_cert_len = asn_get_data_len (0, &asn, &id_cert);
- id_cert += id_cert_len - 4;
- memcpy (id_cert, id, 4);
- }
+ log_debug (LOG_CRYPTO, 60, "x509_read_from_dir: reading certificate %s",
+ file->d_name);
- res = 1;
+ certh = BIO_new (BIO_s_file ());
+ if (!certh)
+ {
+ log_error ("x509_read_from_dir: BIO_new (BIO_s_file ()) failed");
+ continue;
+ }
- done:
- close (fd);
+ strncpy (fullname + off, file->d_name, size);
+ fullname[off + size] = 0;
- return res;
-}
+ if (BIO_read_filename (certh, fullname) == -1)
+ {
+ BIO_free (certh);
+ log_error ("x509_read_from_dir: BIO_read_filename () failed");
+ continue;
+ }
-/* Retrieve the public key from a X509 certificate. */
-int
-x509_cert_get_key (u_int8_t *asn, u_int32_t asnlen, void *blob)
-{
- struct rsa_public_key *key = blob;
- struct x509_certificate cert;
+ cert = PEM_read_bio_X509 (certh, NULL, NULL);
+ BIO_free (certh);
+ if (cert == NULL)
+ {
+ log_error ("x509_read_from_dir: PEM_read_bio_X509 (%s) failed",
+ file->d_name);
+ continue;
+ }
- if (!x509_decode_certificate (asn, asnlen, &cert))
- return 0;
+ if (!X509_STORE_add_cert (ctx, cert))
+ {
+ /*
+ * This is actually expected if we have several certificates only
+ * differing in subjectAltName, which is not an something that is
+ * strange. Consider multi-homed machines.
+ */
+ log_debug (LOG_CRYPTO, 50,
+ "x509_read_from_dir: X509_STORE_add_cert (%s) failed",
+ file->d_name);
+ }
- /* XXX Perhaps put into pkcs? */
- mpz_init_set (key->n, cert.key.n);
- mpz_init_set (key->e, cert.key.e);
+ if (hash && !x509_hash_enter (cert))
+ log_print ("x509_read_from_dir: X509_hash_enter (%s) failed",
+ file->d_name);
+ }
- x509_free_certificate (&cert);
+ closedir (dir);
return 1;
}
-/* Retrieve the public key from a X509 certificate. */
+/* Initialize our databases and load our own certificates. */
int
-x509_cert_get_subject (u_int8_t *asn, u_int32_t asnlen,
- u_int8_t **subject, u_int32_t *subjectlen)
+x509_cert_init (void)
{
- struct x509_certificate cert;
+ char *dirname;
- if (!x509_decode_certificate (asn, asnlen, &cert))
- return 0;
+ x509_hash_init ();
- if (!cert.extension.type || !cert.extension.val)
- goto fail;
+ /* Process client certificates we will accept. */
+ dirname = conf_get_str ("X509-certificates", "Cert-directory");
+ if (!dirname)
+ {
+ log_print ("x509_cert_init: no Cert-directory");
+ return 0;
+ }
- log_debug (LOG_CRYPTO, 60, "x509_cert_get_subject: Extension Type %s = %s",
- cert.extension.type,
- asn_parse_objectid (asn_ids, cert.extension.type));
+ x509_certs = X509_STORE_new ();
+ if (!x509_certs)
+ {
+ log_print ("x509_cert_init: creating new X509_STORE failed");
+ return 0;
+ }
- if (strcmp (ASN_ID_SUBJECT_ALT_NAME, cert.extension.type))
+ if (!x509_read_from_dir (x509_certs, dirname, 1))
{
- log_print ("x509_cert_get_subject: extension type != subjectAltName");
- goto fail;
+ log_print ("x509_cert_init: x509_read_from_dir failed");
+ return 0;
}
- /*
- * XXX Evil**3, due to lack of time the IP encoding of subjectAltName
- * is supposed to be: 0x30 0x06 0x087 0x04 aa bb cc dd, where the IPV4
- * IP number is aa.bb.cc.dd.
- */
- if (asn_get_len (cert.extension.val) != 8 || cert.extension.val[3] != 4)
+ /* Process CA certificates we will trust. */
+ dirname = conf_get_str ("X509-certificates", "CA-directory");
+ if (!dirname)
{
- log_print ("x509_cert_get_subject: "
- "subjectAltName uses unhandled encoding");
- goto fail;
+ log_print ("x509_cert_init: no CA-directory");
+ return 0;
}
- /* XXX IPV4 address. */
- *subject = malloc (sizeof (in_addr_t));
- if (!*subject)
+ x509_cas = X509_STORE_new ();
+ if (!x509_cas)
{
- log_error ("x509_cert_get_subject: malloc (%d) failed",
- sizeof (in_addr_t));
- goto fail;
+ log_print ("x509_cert_init: creating new X509_STORE failed");
+ return 0;
+ }
+
+ if (!x509_read_from_dir (x509_cas, dirname, 0))
+ {
+ log_print ("x509_cert_init: x509_read_from_dir failed");
+ return 0;
}
- *subjectlen = sizeof (in_addr_t);
- memcpy (*subject, cert.extension.val + 4, *subjectlen);
- x509_free_certificate (&cert);
return 1;
+}
- fail:
- x509_free_certificate (&cert);
- return 0;
+void *
+x509_cert_get (u_int8_t *asn, u_int32_t len)
+{
+ return x509_from_asn (asn, len);
}
-/*
- * Initalizes the struct x509_attribval from a AttributeValueAssertion.
- * XXX Error checking.
- */
-void
-x509_get_attribval (struct norm_type *obj, struct x509_attribval *a)
+int
+x509_cert_validate (void *scert)
{
- struct norm_type *tmp;
+ X509_STORE_CTX csc;
+ X509_NAME *issuer, *subject;
+ X509 *cert = (X509 *)scert;
+ EVP_PKEY *key;
+ int res;
- tmp = asn_decompose ("AttributeValueAssertion.AttributeType", obj);
- if (tmp && tmp->data)
- a->type = strdup ((char *)tmp->data);
+ /*
+ * Validate the peer certificate by checking with the CA certificates we
+ * trust.
+ */
+ X509_STORE_CTX_init (&csc, x509_cas, cert, NULL);
+ res = X509_verify_cert (&csc);
+ X509_STORE_CTX_cleanup (&csc);
- tmp = asn_decompose ("AttributeValueAssertion.AttributeValue", obj);
- if (tmp && tmp->data)
- a->val = strdup ((char *)tmp->data);
-}
+ /* Return if validation succeeded or self-signed certs are not accepted. */
+ if (res || !conf_get_str ("X509-certificates", "Accept-self-signed"))
+ return res;
-/* Set OBJ with values from A. XXX Error checking. */
-void
-x509_set_attribval (struct norm_type *obj, struct x509_attribval *a)
-{
- struct norm_type *tmp;
+ issuer = X509_get_issuer_name (cert);
+ subject = X509_get_subject_name (cert);
+
+ if (!issuer || !subject || X509_name_cmp (issuer, subject))
+ return 0;
+
+ key = X509_get_pubkey (cert);
+ if (!key)
+ return 0;
- tmp = asn_decompose ("AttributeValueAssertion.AttributeType", obj);
- tmp->data = strdup (a->type);
- tmp->len = strlen (tmp->data);
- tmp = asn_decompose ("AttributeValueAssertion.AttributeValue", obj);
- tmp->type = TAG_PRINTSTRING;
- tmp->data = strdup (a->val);
- tmp->len = strlen (tmp->data);
+ if (X509_verify (cert, key) == -1)
+ return 0;
+
+ return 1;
}
-void
-x509_free_attribval (struct x509_attribval *a)
+int
+x509_cert_insert (void *scert)
{
- if (a->type)
- free (a->type);
- if (a->val)
- free (a->val);
+ X509 *cert = X509_dup ((X509 *)scert);
+ int res;
+
+ if (!cert)
+ {
+ log_print ("x509_cert_insert: X509_dup failed");
+ return 0;
+ }
+
+ res = x509_hash_enter (cert);
+ if (!res)
+ X509_free (cert);
+
+ return res;
}
void
-x509_free_certificate (struct x509_certificate *cert)
+x509_cert_free (void *cert)
{
- pkcs_free_public_key (&cert->key);
- if (cert->signaturetype)
- free (cert->signaturetype);
- if (cert->start)
- free (cert->start);
- if (cert->end)
- free (cert->end);
-
- x509_free_attribval (&cert->issuer1);
- x509_free_attribval (&cert->issuer2);
- x509_free_attribval (&cert->subject1);
- x509_free_attribval (&cert->subject2);
- x509_free_attribval (&cert->extension);
+ X509_free ((X509 *)cert);
}
+/* Validate the BER Encoding of a RDNSequence in the CERT_REQ payload. */
int
-x509_decode_certificate (u_int8_t *asn, u_int32_t asnlen,
- struct x509_certificate *rcert)
+x509_certreq_validate (u_int8_t *asn, u_int32_t len)
{
- struct norm_type cert = SEQ ("cert", Certificate);
- struct norm_type *tmp;
- u_int8_t *data;
- u_int32_t datalen;
+ int res = 1;
+ /* struct norm_type name = SEQOF ("issuer", RDNSequence);
- /*
- * Get access to the inner Certificate.
- * XXX We don't know how to get at the CA's public key yet.
- */
- if (!x509_validate_signed (asn, asnlen, 0, &data, &datalen))
- return 0;
-
- memset (rcert, 0, sizeof *rcert);
+ if (!asn_template_clone (&name, 1)
+ || (asn = asn_decode_sequence (asn, len, &name)) == 0)
+ {
+ log_print ("x509_certreq_validate: can not decode 'acceptable CA' info");
+ res = 0;
+ }
+ asn_free (&name); */
- if (!asn_template_clone (&cert, 1)
- || !asn_decode_sequence (data, datalen, &cert))
- goto fail;
+ /* XXX - not supported directly in SSL - later */
- tmp = asn_decompose ("cert.subjectPublicKeyInfo.subjectPublicKey", &cert);
- if (!tmp || !tmp->data)
- goto fail;
- if (!pkcs_public_key_from_asn (&rcert->key, tmp->data + 1, tmp->len - 1))
- goto fail;
-
- tmp = asn_decompose ("cert.version", &cert);
- if (!tmp || !tmp->data)
- goto fail;
- rcert->version = mpz_get_ui (tmp->data);
+ return res;
+}
- tmp = asn_decompose ("cert.serialNumber", &cert);
- if (!tmp || !tmp->data)
- goto fail;
- rcert->serialnumber = mpz_get_ui (tmp->data);
+/* Decode the BER Encoding of a RDNSequence in the CERT_REQ payload. */
+void *
+x509_certreq_decode (u_int8_t *asn, u_int32_t len)
+{
+ /* XXX This needs to be done later.
+ struct norm_type aca = SEQOF ("aca", RDNSequence);
+ struct norm_type *tmp;
+ struct x509_aca naca, *ret;
- tmp = asn_decompose ("cert.signature.algorithm", &cert);
- if (!tmp || !tmp->data)
- goto fail;
- rcert->signaturetype = strdup ((char *)tmp->data);
+ if (!asn_template_clone (&aca, 1)
+ || (asn = asn_decode_sequence (asn, len, &aca)) == 0)
+ {
+ log_print ("x509_certreq_validate: can not decode 'acceptable CA' info");
+ goto fail;
+ }
+ memset (&naca, 0, sizeof (naca));
- tmp = asn_decompose ("cert.issuer.RelativeDistinguishedName."
- "AttributeValueAssertion", &cert);
+ tmp = asn_decompose ("aca.RelativeDistinguishedName.AttributeValueAssertion",
+ &aca);
if (!tmp)
goto fail;
- x509_get_attribval (tmp, &rcert->issuer1);
+ x509_get_attribval (tmp, &naca.name1);
- tmp = asn_decompose ("cert.issuer.RelativeDistinguishedName[1]."
- "AttributeValueAssertion", &cert);
+ tmp = asn_decompose ("aca.RelativeDistinguishedName[1]"
+ ".AttributeValueAssertion", &aca);
if (tmp)
- x509_get_attribval (tmp, &rcert->issuer2);
- else
- rcert->issuer2.type = 0;
-
- tmp = asn_decompose ("cert.subject.RelativeDistinguishedName."
- "AttributeValueAssertion", &cert);
- if (!tmp)
- goto fail;
- x509_get_attribval (tmp, &rcert->subject1);
+ x509_get_attribval (tmp, &naca.name2);
+
+ asn_free (&aca);
- tmp = asn_decompose ("cert.subject.RelativeDistinguishedName[1]."
- "AttributeValueAssertion", &cert);
- if (tmp)
- x509_get_attribval (tmp, &rcert->subject2);
+ ret = malloc (sizeof (struct x509_aca));
+ if (ret)
+ memcpy (ret, &naca, sizeof (struct x509_aca));
else
- rcert->subject2.type = 0;
-
- tmp = asn_decompose ("cert.validity.notBefore", &cert);
- if (!tmp || !tmp->data)
- goto fail;
- rcert->start = strdup ((char *)tmp->data);
- if (!rcert->start)
{
- log_error ("x509_decode_certificate: strdup(\"%s\") failed", tmp->data);
- goto fail;
- }
-
- tmp = asn_decompose ("cert.validity.notAfter", &cert);
- if (!tmp || !tmp->data)
- goto fail;
- rcert->end = strdup ((char *)tmp->data);
- if (!rcert->end)
- {
- log_error ("x509_decode_certificate: strdup(\"%s\") failed", tmp->data);
- goto fail;
+ log_error ("x509_certreq_decode: malloc (%d) failed",
+ sizeof (struct x509_aca));
+ x509_free_aca (&aca);
}
- /* For x509v3 there might be an extension, try to decode it. */
- tmp = asn_decompose ("cert.extension", &cert);
- if (tmp && tmp->data && rcert->version == 2)
- x509_decode_cert_extension (tmp->data, tmp->len, rcert);
-
- asn_free (&cert);
- return 1;
+ return ret;
fail:
- x509_free_certificate (rcert);
- asn_free (&cert);
+ asn_free (&aca); */
return 0;
}
-int
-x509_encode_certificate (struct x509_certificate *rcert,
- u_int8_t **asn, u_int32_t *asnlen)
+void
+x509_free_aca (void *blob)
{
- struct norm_type cert = SEQ ("cert", Certificate);
- struct norm_type *tmp;
- u_int8_t *data, *new_buf;
- mpz_t num;
- u_int8_t *tmpasn;
- u_int32_t tmpasnlen;
-
-
- if (!asn_template_clone (&cert, 1))
- goto fail;
+ struct x509_aca *aca = blob;
- if (rcert->extension.type && rcert->extension.val)
- {
- tmp = asn_decompose ("cert.extension", &cert);
- if (x509_encode_cert_extension (rcert, &tmpasn, &tmpasnlen))
- {
- tmp->data = tmpasn;
- tmp->len = tmpasnlen;
- }
- }
+ if (aca->name1.type)
+ free (aca->name1.type);
+ if (aca->name1.val)
+ free (aca->name1.val);
- tmp = asn_decompose ("cert.subjectPublicKeyInfo.algorithm.parameters",
- &cert);
- tmp->type = TAG_NULL;
- tmp = asn_decompose ("cert.subjectPublicKeyInfo.algorithm.algorithm",
- &cert);
- tmp->data = strdup (ASN_ID_RSAENCRYPTION);
- tmp->len = strlen (tmp->data);
+ if (aca->name2.type)
+ free (aca->name2.type);
+ if (aca->name2.val)
+ free (aca->name2.val);
+}
- tmp = asn_decompose ("cert.subjectPublicKeyInfo.subjectPublicKey", &cert);
- data = pkcs_public_key_to_asn (&rcert->key);
- if (!data)
- goto fail;
+X509 *
+x509_from_asn (u_char *asn, u_int len)
+{
+ BIO *certh;
+ X509 *scert = NULL;
- /* This is a BITSTRING, add 0 octet for padding. */
- tmp->len = asn_get_len (data);
- new_buf = realloc (data, tmp->len + 1);
- if (!new_buf)
+ certh = BIO_new (BIO_s_mem ());
+ if (!certh)
{
- log_error ("x509_encode_certificate: realloc (%p, %d) failed", data,
- tmp->len + 1);
- free (data);
- goto fail;
+ log_error ("X509_from_asn: BIO_new (BIO_s_mem ()) failed");
+ return NULL;
}
- data = new_buf;
- memmove (data + 1, data, tmp->len);
- data[0] = 0;
- tmp->data = data;
- tmp->len++;
-
- mpz_init (num);
- tmp = asn_decompose ("cert.version", &cert);
- mpz_set_ui (num, rcert->version);
- if (!pkcs_mpz_to_norm_type (tmp, num))
+
+ if (BIO_write (certh, asn, len) == -1)
{
- mpz_clear (num);
- goto fail;
+ log_error ("X509_from_asn: BIO_write failed\n");
+ goto end;
}
- tmp = asn_decompose ("cert.serialNumber", &cert);
- mpz_set_ui (num, rcert->serialnumber);
- if (!pkcs_mpz_to_norm_type (tmp, num))
+ scert = d2i_X509_bio (certh, NULL);
+ if (!scert)
{
- mpz_clear (num);
- goto fail;
+ log_print ("X509_from_asn: d2i_X509_bio failed\n");
+ goto end;
}
- mpz_clear (num);
-
- tmp = asn_decompose ("cert.signature.parameters", &cert);
- tmp->type = TAG_NULL;
- tmp = asn_decompose ("cert.signature.algorithm", &cert);
- tmp->data = strdup (rcert->signaturetype);
- tmp->len = strlen ((char *)tmp->data);
-
- tmp = asn_decompose ("cert.issuer.RelativeDistinguishedName."
- "AttributeValueAssertion", &cert);
- x509_set_attribval (tmp, &rcert->issuer1);
- tmp = asn_decompose ("cert.issuer.RelativeDistinguishedName[1]."
- "AttributeValueAssertion", &cert);
- x509_set_attribval (tmp, &rcert->issuer2);
-
- tmp = asn_decompose ("cert.subject.RelativeDistinguishedName."
- "AttributeValueAssertion", &cert);
- x509_set_attribval (tmp, &rcert->subject1);
- tmp = asn_decompose ("cert.subject.RelativeDistinguishedName[1]."
- "AttributeValueAssertion", &cert);
- x509_set_attribval (tmp, &rcert->subject2);
-
- tmp = asn_decompose ("cert.validity.notBefore", &cert);
- tmp->data = strdup (rcert->start);
- tmp->len = strlen ((char *)tmp->data);
-
- tmp = asn_decompose ("cert.validity.notAfter", &cert);
- tmp->data = strdup (rcert->end);
- tmp->len = strlen ((char *)tmp->data);
-
- *asn = asn_encode_sequence (&cert, 0);
- if (!*asn)
- goto fail;
-
- *asnlen = asn_get_len (*asn);
- asn_free (&cert);
- return 1;
-
- fail:
- asn_free (&cert);
- return 0;
+ end:
+ BIO_free (certh);
+ return scert;
}
/*
- * Decode an Extension to a X509 certificate.
- * XXX We ignore the critical boolean.
+ * Check that a certificate has a subjectAltName and that it matches our ID.
*/
-
int
-x509_decode_cert_extension (u_int8_t *asn, u_int32_t asnlen,
- struct x509_certificate *cert)
+x509_check_subjectaltname (u_char *id, u_int id_len, X509 *scert)
{
- struct norm_type *tmp;
- struct norm_type ex = SEQOF ("ex", Extensions);
+ u_int8_t *altname;
+ u_int32_t altlen;
+ int type, idtype, ret;
- /* Implicit tagging for extension. */
- ex.class = ADD_EXP (3, UNIVERSAL);
-
- if (!asn_template_clone (&ex, 1) || !asn_decode_sequence (asn, asnlen, &ex))
+ type = x509_cert_subjectaltname (scert, &altname, &altlen);
+ if (!type)
{
- asn_free (&ex);
+ log_print ("x509_check_subjectaltname: can't access subjectAltName");
return 0;
}
- tmp = asn_decompose ("ex.extension.extnValue", &ex);
- if (!tmp || !tmp->data || asn_get_len (tmp->data) != tmp->len)
- goto fail;
- cert->extension.val = malloc (tmp->len);
- if (cert->extension.val == 0)
- goto fail;
- memcpy (cert->extension.val, tmp->data, tmp->len);
+ /*
+ * Now that we have the X509 certicate in native form, get the
+ * subjectAltName extension and verify that it matches our ID.
+ */
- tmp = asn_decompose ("ex.extension.extnId", &ex);
- if (!tmp || !tmp->data)
- goto fail;
- cert->extension.type = strdup (tmp->data);
- if (!cert->extension.type)
+ /* XXX Get type of ID. */
+ idtype = id[0];
+ id += ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
+ id_len -= ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
+
+ ret = 0;
+ switch (idtype)
{
- free (cert->extension.val);
- cert->extension.val = 0;
- goto fail;
+ case IPSEC_ID_IPV4_ADDR:
+ if (type == X509v3_IPV4_ADDR)
+ ret = 1;
+ break;
+ case IPSEC_ID_FQDN:
+ if (type == X509v3_DNS_NAME)
+ ret = 1;
+ break;
+ case IPSEC_ID_USER_FQDN:
+ if (type == X509v3_RFC_NAME)
+ ret = 1;
+ break;
+ default:
+ ret = 0;
+ break;
}
- asn_free (&ex);
- return 1;
+ if (!ret)
+ {
+ log_debug (LOG_CRYPTO, 50,
+ "X509_check_subjectaltname: "
+ "our ID type does not match X509 cert ID type");
+ return 0;
+ }
- fail:
- asn_free (&ex);
- return 0;
+ if (altlen != id_len || memcmp (altname, id, id_len) != 0)
+ {
+ log_debug (LOG_CRYPTO, 50,
+ "X509_check_subjectaltname: "
+ "our ID does not match X509 cert ID");
+ return 0;
+ }
+
+ return 1;
}
-/*
- * Encode a Cert Extension.
- * XXX Only one extension per certificate.
- * XXX We tag everything as critical.
+/*
+ * Obtain a certificate from an acceptable CA.
+ * XXX We don't check if the certificate we find is from an accepted CA.
*/
int
-x509_encode_cert_extension (struct x509_certificate *cert,
- u_int8_t **asn, u_int32_t *asnlen)
+x509_cert_obtain (u_int8_t *id, size_t id_len, void *data, u_int8_t **cert,
+ u_int32_t *certlen)
{
- struct norm_type ex = SEQ ("ex", Extensions);
- struct norm_type *tmp;
- ex.class = ADD_EXP (3, UNIVERSAL);
-
- if (!asn_template_clone (&ex ,1))
- goto fail;
+ struct x509_aca *aca = data;
+ X509 *scert;
+ u_char *p;
- tmp = asn_decompose ("ex.extension.extnId", &ex);
- tmp->data = strdup (cert->extension.type);
- tmp->len = strlen (tmp->data);
+ if (aca)
+ log_debug (LOG_CRYPTO, 60,
+ "x509_cert_obtain: acceptable certificate authorities here");
- /* XXX We mark every extension as critical. */
- tmp = asn_decompose ("ex.extension.critical", &ex);
- tmp->data = malloc (1);
- if (!tmp->data)
+ /* We need our ID to find a certificate. */
+ if (!id)
{
- log_error ("x509_encode_cert_extension: malloc (1) failed");
- goto fail;
+ log_print ("X509_cert_obtain: ID is missing");
+ return 0;
}
- *(u_int8_t *)tmp->data = 0xff;
- tmp->len = 1;
- tmp = asn_decompose ("ex.extension.extnValue", &ex);
- tmp->data = malloc (asn_get_len (cert->extension.val));
- if (!tmp->data)
+ scert = x509_hash_find (id, id_len);
+ if (!scert)
+ return 0;
+
+ if (!x509_check_subjectaltname (id, id_len, scert))
{
- log_error ("x509_encode_cert_extension: malloc (%d) failed",
- asn_get_len (cert->extension.val));
- goto fail;
+ log_print ("X509_cert_obtain: subjectAltName does not match id");
+ free (*cert);
+ return 0;
}
- tmp->len = asn_get_len (cert->extension.val);
- memcpy (tmp->data, cert->extension.val, tmp->len);
- *asn = asn_encode_sequence (&ex, 0);
- if (!*asn)
- goto fail;
+ *certlen = i2d_X509 (scert, NULL);
+ p = *cert = malloc (*certlen);
+ if (!p)
+ {
+ log_error ("X509_cert_obtain: malloc (%d) failed", *certlen);
+ return 0;
+ }
+ *certlen = i2d_X509 (scert, &p);
- *asnlen = asn_get_len (*asn);
-
- asn_free (&ex);
return 1;
- fail:
- asn_free (&ex);
- return 0;
}
-/*
- * Checks the signature on an ASN.1 Signed Type. If the passed KEY is
- * NULL we just unwrap the inner object and return it.
- */
+/* Returns a pointer to the subjectAltName information of X509 certificate. */
int
-x509_validate_signed (u_int8_t *asn, u_int32_t asnlen,
- struct rsa_public_key *key, u_int8_t **data,
- u_int32_t *datalen)
+x509_cert_subjectaltname (X509 *scert, u_int8_t **altname, u_int32_t *len)
{
- struct norm_type sig = SEQ ("signed", Signed);
- struct norm_type digest = SEQ ("digest", DigestInfo);
- struct norm_type *tmp;
- struct hash *hash = 0;
- int res;
- u_int8_t *dec;
- u_int16_t declen;
- char *id;
+ X509_EXTENSION *subjectaltname;
+ u_int8_t *sandata;
+ int extpos;
+ int santype, sanlen;
- if (!asn_template_clone (&sig, 1))
- /* Failed, probably memory allocation, free what we got anyway. */
- goto fail;
-
- if (!asn_decode_sequence (asn, asnlen, &sig))
+ extpos = X509_get_ext_by_NID (scert, NID_subject_alt_name, -1);
+ if (extpos == -1)
{
- log_print ("x509_validate_signed: input data could not be decoded");
- goto fail;
+ log_print ("X509_cert_subjectaltname: "
+ "certificate does not contain subjectAltName");
+ return 0;
}
- tmp = asn_decompose ("signed.algorithm.algorithm", &sig);
+ subjectaltname = X509_get_ext (scert, extpos);
- if (strcmp ((char *)tmp->data, ASN_ID_MD5WITHRSAENC) == 0)
- hash = hash_get (HASH_MD5);
- else
+ if (!subjectaltname || !subjectaltname->value
+ || !subjectaltname->value->data || subjectaltname->value->length < 4)
{
- id = asn_parse_objectid (asn_ids, tmp->data);
- log_print ("x509_validate_signed: can not handle SigType %s",
- id ? id : tmp->data);
- goto fail;
+ log_print ("X509_check_subjectaltname: "
+ "invalid subjectaltname extension");
+ return 0;
}
- if (!hash)
- goto fail;
-
- tmp = asn_decompose ("signed.data", &sig);
-
- /* Hash the data. */
- hash->Init (hash->ctx);
- hash->Update (hash->ctx, tmp->data, tmp->len);
- hash->Final (hash->digest, hash->ctx);
-
- *data = tmp->data;
- *datalen = tmp->len;
+ /* SSL does not handle unknown ASN stuff well, do it by hand. */
+ sandata = subjectaltname->value->data;
+ santype = sandata[2] & 0x3f;
+ sanlen = sandata[3];
+ sandata += 4;
- /* Used to unwrap the SIGNED object around the Certificate. */
- if (!key)
+ if (sanlen + 4 != subjectaltname->value->length)
{
- asn_free (&sig);
- return 1;
+ log_print ("X509_check_subjectaltname: subjectaltname invalid length");
+ return 0;
}
+
+ *len = sanlen;
+ *altname = sandata;
- tmp = asn_decompose ("signed.encrypted", &sig);
+ return santype;
+}
- /*
- * tmp->data is a BITSTRING, the first octet in the BITSTRING gives
- * the padding bits at the end. Per definition there are no padding
- * bits at the end in this case, so just skip it.
- */
- if (!pkcs_rsa_decrypt (PKCS_PRIVATE, key, 0, tmp->data + 1, &dec, &declen))
- goto fail;
+int
+x509_cert_get_subject (void *scert, u_int8_t **id, u_int32_t *id_len)
+{
+ X509 *cert = scert;
+ int type;
+ u_int8_t *altname;
+ u_int32_t altlen;
- if (!asn_template_clone (&digest, 1)
- || !asn_decode_sequence (dec, declen, &digest))
- {
- asn_free (&digest);
- goto fail;
- }
- tmp = asn_decompose ("digest.digestAlgorithm.algorithm", &digest);
- if (strcmp (ASN_ID_MD5, (char *)tmp->data))
- {
- log_print ("x509_validate_signed: DigestAlgorithm is not MD5");
- res = 0;
- }
- else
+ type = x509_cert_subjectaltname (cert, &altname, &altlen);
+
+ switch (type)
{
- tmp = asn_decompose ("digest.digest", &digest);
- if (tmp->len != hash->hashsize
- || memcmp (tmp->data, hash->digest, tmp->len))
- {
- log_print ("x509_validate_signed: Digest does not match Data");
- res = 0;
- }
- else
- res = 1;
+ case X509v3_IPV4_ADDR:
+ {
+ char buf[ISAKMP_ID_DATA_OFF + 4];
+
+ /* XXX sizeof IPV4_ADDR, how any better? */
+ if (altlen != 4)
+ {
+ log_print ("x509_cert_get_subject: length != IP4addr: %d",
+ altlen);
+ return 0;
+ }
+
+ SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_IPV4_ADDR);
+ SET_IPSEC_ID_PROTO (buf + ISAKMP_ID_DOI_DATA_OFF, 0);
+ SET_IPSEC_ID_PORT (buf + ISAKMP_ID_DOI_DATA_OFF, 0);
+ memcpy (buf + ISAKMP_ID_DATA_OFF, altname, altlen);
+
+ *id_len = ISAKMP_ID_DATA_OFF + 4 - ISAKMP_GEN_SZ;
+ *id = malloc (*id_len);
+ if (!*id)
+ {
+ log_print ("x509_cert_get_subject: malloc (%d) failed", *id_len);
+ return 0;
+ }
+ memcpy (*id, buf + ISAKMP_GEN_SZ, *id_len);
+ }
+ break;
+ default:
+ log_print ("x509_cert_get_subject: unsupported subjectAltName type: %d",
+ type);
+ return 0;
}
- asn_free (&digest);
- asn_free (&sig);
- return res;
-
- fail:
- asn_free (&sig);
- return 0;
+ return 1;
}
-/*
- * Create an ASN Signed Structure from the data passed in data
- * and return the result in asn.
- * At the moment the used hash is MD5, this is the only common
- * hash between us and X509.
- */
int
-x509_create_signed (u_int8_t *data, u_int32_t datalen,
- struct rsa_private_key *key, u_int8_t **asn,
- u_int32_t *asnlen)
+x509_cert_get_key (void *scert, void *keyp)
{
- struct norm_type digest = SEQ ("digest", DigestInfo);
- struct norm_type sig = SEQ ("signed", Signed);
- struct norm_type *tmp;
- struct hash *hash;
- u_int8_t *diginfo, *enc;
- u_int32_t enclen;
- int res = 0;
-
- /* Hash the Data. */
- hash = hash_get (HASH_MD5);
- hash->Init (hash->ctx);
- hash->Update (hash->ctx, data, datalen);
- hash->Final (hash->digest, hash->ctx);
+ X509 *cert = scert;
+ EVP_PKEY *key;
- if (!asn_template_clone (&digest, 1))
- goto fail;
+ key = X509_get_pubkey (cert);
- tmp = asn_decompose ("digest.digest", &digest);
- tmp->len = hash->hashsize;
- tmp->data = malloc (hash->hashsize);
- if (!tmp->data)
+ /* Check if we got the right key type */
+ if (key->type != EVP_PKEY_RSA)
{
- log_error ("x509_create_signed: malloc (%d) failed", hash->hashsize);
- goto fail;
+ log_print ("x509_cert_get_key: public key is not a RSA key");
+ X509_free (cert);
+ return 0;
}
- memcpy (tmp->data, hash->digest, hash->hashsize);
- tmp = asn_decompose ("digest.digestAlgorithm.parameters", &digest);
- tmp->type = TAG_NULL;
- tmp = asn_decompose ("digest.digestAlgorithm.algorithm", &digest);
- tmp->data = strdup (ASN_ID_MD5);
- tmp->len = strlen (tmp->data);
+ *(RSA **)keyp = RSAPublicKey_dup (key->pkey.rsa);
- /* ASN encode Digest Information. */
- diginfo = asn_encode_sequence (&digest, 0);
- if (!diginfo)
- goto fail;
-
- /* Encrypt the Digest Info with Private Key. */
- res = pkcs_rsa_encrypt (PKCS_PRIVATE, 0, key, diginfo, asn_get_len (diginfo),
- &enc, &enclen);
- free (diginfo);
- if (!res)
- goto fail;
- res = 0;
-
- if (!asn_template_clone (&sig, 1))
- goto fail2;
-
- tmp = asn_decompose ("signed.algorithm.parameters", &sig);
- tmp->type = TAG_NULL;
- tmp = asn_decompose ("signed.algorithm.algorithm", &sig);
- tmp->data = strdup (ASN_ID_MD5WITHRSAENC);
- tmp->len = strlen (tmp->data);
-
- /* The type is BITSTRING, i.e. first octet need to be zero. */
- tmp = asn_decompose ("signed.encrypted", &sig);
- tmp->data = malloc (enclen + 1);
- if (!tmp->data)
- {
- log_error ("x509_create_signed: malloc (%d) failed", enclen + 1);
- free (enc);
- goto fail2;
- }
- tmp->len = enclen + 1;
- memcpy (tmp->data + 1, enc, enclen);
- *(char *)tmp->data = 0;
- free (enc);
-
- tmp = asn_decompose ("signed.data", &sig);
- tmp->data = data;
- tmp->len = datalen;
-
- *asn = asn_encode_sequence (&sig, 0);
- if (!*asn)
- goto fail2;
- *asnlen = asn_get_len (*asn);
-
- /* This is the data we have been given, we can not free it in asn_free. */
- tmp->data = 0;
- res = 1; /* Successful. */
-
- fail2:
- asn_free (&sig);
- fail:
- asn_free (&digest);
- return res;
+ return *(RSA **)keyp == NULL ? 0 : 1;
}
diff --git a/sbin/isakmpd/x509.h b/sbin/isakmpd/x509.h
index a0c92cf95d2..3325b27fcda 100644
--- a/sbin/isakmpd/x509.h
+++ b/sbin/isakmpd/x509.h
@@ -1,8 +1,8 @@
-/* $OpenBSD: x509.h,v 1.3 1998/11/17 11:10:22 niklas Exp $ */
-/* $EOM: x509.h,v 1.5 1998/08/21 13:47:54 provos Exp $ */
+/* $OpenBSD: x509.h,v 1.4 1999/07/17 21:54:39 niklas Exp $ */
+/* $EOM: x509.h,v 1.6 1999/07/17 20:44:12 niklas Exp $ */
/*
- * Copyright (c) 1998 Niels Provos. All rights reserved.
+ * Copyright (c) 1998, 1999 Niels Provos. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,7 +37,10 @@
#ifndef _X509_H_
#define _X509_H_
-#include "pkcs.h" /* for struct rsa_public_key */
+#define X509v3_RFC_NAME 1
+#define X509v3_DNS_NAME 2
+#define X509v3_IPV4_ADDR 7
+
struct x509_attribval {
char *type;
@@ -45,9 +48,9 @@ struct x509_attribval {
};
/*
- * The acceptable certification authority
- * XXX we only support two names at the moment, as of ASN this can
- * be dynamic but we dont care for now.
+ * The acceptable certification authority.
+ * XXX We only support two names at the moment, as of ASN this can
+ * be dynamic but we don't care for now.
*/
struct x509_aca {
@@ -55,45 +58,28 @@ struct x509_aca {
struct x509_attribval name2;
};
-struct exchange;
+struct X509;
-struct x509_certificate {
- u_int32_t version;
- u_int32_t serialnumber;
- char *signaturetype;
- struct x509_attribval issuer1; /* At the moment Country */
- struct x509_attribval issuer2; /* At the moment Organization */
- struct x509_attribval subject1; /* At the moment Country */
- struct x509_attribval subject2; /* At the moment Organization */
- struct x509_attribval extension; /* Raw Extension */
- char *start; /* Certificate Validity Start and End */
- char *end;
- struct rsa_public_key key;
-};
+/* Functions provided by cert handler. */
+int x509_cert_init (void);
+void *x509_cert_get (u_int8_t *, u_int32_t);
+int x509_cert_validate (void *);
+void x509_cert_free (void *);
int x509_certreq_validate (u_int8_t *, u_int32_t);
void *x509_certreq_decode (u_int8_t *, u_int32_t);
void x509_free_aca (void *);
-int x509_cert_obtain (struct exchange *, void *, u_int8_t **, u_int32_t *);
-int x509_cert_get_key (u_int8_t *, u_int32_t, void *);
-int x509_cert_get_subject (u_int8_t *, u_int32_t, u_int8_t **, u_int32_t *);
+int x509_cert_obtain (u_int8_t *, size_t, void *, u_int8_t **, u_int32_t *);
+int x509_cert_get_key (void *, void *);
+int x509_cert_get_subject (void *, u_int8_t **, u_int32_t *);
-void x509_get_attribval (struct norm_type *, struct x509_attribval *);
-void x509_set_attribval (struct norm_type *, struct x509_attribval *);
-void x509_free_attrbival (struct x509_attribval *);
+/* Misc. X509 certificate functions. */
-int x509_validate_signed (u_int8_t *, u_int32_t, struct rsa_public_key *,
- u_int8_t **, u_int32_t *);
-int x509_create_signed (u_int8_t *, u_int32_t, struct rsa_private_key *,
- u_int8_t **, u_int32_t *);
-int x509_decode_certificate (u_int8_t *, u_int32_t, struct x509_certificate *);
-int x509_encode_certificate (struct x509_certificate *, u_int8_t **,
- u_int32_t *);
-void x509_free_certificate (struct x509_certificate *);
+int x509_cert_insert (void *);
+int x509_read_from_dir (X509_STORE *, char *, int);
-int x509_decode_cert_extension (u_int8_t *, u_int32_t,
- struct x509_certificate *);
-int x509_encode_cert_extension (struct x509_certificate *, u_int8_t **,
- u_int32_t *);
+int x509_cert_subjectaltname (X509 *cert, u_char **, u_int *);
+int x509_check_subjectaltname (u_char *, u_int, X509 *);
+X509 *x509_from_asn (u_char *, u_int);
#endif /* _X509_H_ */