xref: /openbsd-src/sbin/isakmpd/cert.c (revision 82bad92d22350e34329aa62caabc59c254f928fb)
1*82bad92dSderaadt /* $OpenBSD: cert.c,v 1.33 2013/03/21 04:30:14 deraadt Exp $	 */
223d41768Sniklas /* $EOM: cert.c,v 1.18 2000/09/28 12:53:27 niklas Exp $	 */
36e55b688Sniklas 
46e55b688Sniklas /*
5fb1921ccSniklas  * Copyright (c) 1998, 1999 Niels Provos.  All rights reserved.
602005a80Sniklas  * Copyright (c) 1999, 2000 Niklas Hallqvist.  All rights reserved.
76e55b688Sniklas  *
86e55b688Sniklas  * Redistribution and use in source and binary forms, with or without
96e55b688Sniklas  * modification, are permitted provided that the following conditions
106e55b688Sniklas  * are met:
116e55b688Sniklas  * 1. Redistributions of source code must retain the above copyright
126e55b688Sniklas  *    notice, this list of conditions and the following disclaimer.
136e55b688Sniklas  * 2. Redistributions in binary form must reproduce the above copyright
146e55b688Sniklas  *    notice, this list of conditions and the following disclaimer in the
156e55b688Sniklas  *    documentation and/or other materials provided with the distribution.
166e55b688Sniklas  *
176e55b688Sniklas  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
186e55b688Sniklas  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
196e55b688Sniklas  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
206e55b688Sniklas  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
216e55b688Sniklas  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
226e55b688Sniklas  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236e55b688Sniklas  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246e55b688Sniklas  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256e55b688Sniklas  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
266e55b688Sniklas  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276e55b688Sniklas  */
286e55b688Sniklas 
296e55b688Sniklas /*
306e55b688Sniklas  * This code was written under funding by Ericsson Radio Systems.
316e55b688Sniklas  */
326e55b688Sniklas 
33*82bad92dSderaadt #include <sys/types.h>
34fb1921ccSniklas #include <stdio.h>
356e55b688Sniklas #include <stdlib.h>
366e55b688Sniklas #include <string.h>
376e55b688Sniklas 
38f1763a88Sniklas #include "isakmp_num.h"
39f1763a88Sniklas #include "log.h"
40f1763a88Sniklas #include "cert.h"
41f1763a88Sniklas #include "x509.h"
426e55b688Sniklas 
43c4090adbSniklas #include "policy.h"
44c4090adbSniklas 
456e55b688Sniklas struct cert_handler cert_handler[] = {
4657240511Sniklas     {
4757240511Sniklas 	ISAKMP_CERTENC_X509_SIG,
489dbe9fb4Sho 	x509_cert_init, x509_crl_init, x509_cert_get, x509_cert_validate,
49fb1921ccSniklas 	x509_cert_insert, x509_cert_free,
506e55b688Sniklas 	x509_certreq_validate, x509_certreq_decode, x509_free_aca,
51adfef16cSangelos 	x509_cert_obtain, x509_cert_get_key, x509_cert_get_subjects,
5205442ddfStom 	x509_cert_dup, x509_serialize, x509_printable, x509_from_printable,
5305442ddfStom 	x509_ca_count
54c4090adbSniklas     },
55c4090adbSniklas     {
56c4090adbSniklas 	ISAKMP_CERTENC_KEYNOTE,
579dbe9fb4Sho 	keynote_cert_init, NULL, keynote_cert_get, keynote_cert_validate,
58c4090adbSniklas 	keynote_cert_insert, keynote_cert_free,
59c4090adbSniklas 	keynote_certreq_validate, keynote_certreq_decode, keynote_free_aca,
60adfef16cSangelos 	keynote_cert_obtain, keynote_cert_get_key, keynote_cert_get_subjects,
61adfef16cSangelos 	keynote_cert_dup, keynote_serialize, keynote_printable,
6205442ddfStom 	keynote_from_printable, keynote_ca_count
63c4090adbSniklas     },
646e55b688Sniklas };
656e55b688Sniklas 
66fb1921ccSniklas /* Initialize all certificate handlers */
67fb1921ccSniklas int
cert_init(void)68fb1921ccSniklas cert_init(void)
69fb1921ccSniklas {
70c7c448f9Sho 	size_t	i;
71c7c448f9Sho 	int	err = 1;
72fb1921ccSniklas 
73fb1921ccSniklas 	for (i = 0; i < sizeof cert_handler / sizeof cert_handler[0]; i++)
7450eea14cSho 		if (cert_handler[i].cert_init &&
7550eea14cSho 		    !(*cert_handler[i].cert_init)())
76fb1921ccSniklas 			err = 0;
77fb1921ccSniklas 
78fb1921ccSniklas 	return err;
79fb1921ccSniklas }
80fb1921ccSniklas 
819dbe9fb4Sho int
crl_init(void)829dbe9fb4Sho crl_init(void)
839dbe9fb4Sho {
84c7c448f9Sho 	size_t	i;
85c7c448f9Sho 	int	err = 1;
869dbe9fb4Sho 
879dbe9fb4Sho 	for (i = 0; i < sizeof cert_handler / sizeof cert_handler[0]; i++)
889dbe9fb4Sho 		if (cert_handler[i].crl_init && !(*cert_handler[i].crl_init)())
899dbe9fb4Sho 			err = 0;
909dbe9fb4Sho 
919dbe9fb4Sho 	return err;
929dbe9fb4Sho }
939dbe9fb4Sho 
946e55b688Sniklas struct cert_handler *
cert_get(u_int16_t id)956e55b688Sniklas cert_get(u_int16_t id)
966e55b688Sniklas {
97c7c448f9Sho 	size_t	i;
986e55b688Sniklas 
996e55b688Sniklas 	for (i = 0; i < sizeof cert_handler / sizeof cert_handler[0]; i++)
1006e55b688Sniklas 		if (id == cert_handler[i].id)
1016e55b688Sniklas 			return &cert_handler[i];
10257240511Sniklas 	return 0;
1036e55b688Sniklas }
1046e55b688Sniklas 
105a7b8c2e4Sniklas /*
106a7b8c2e4Sniklas  * Decode the certificate request of type TYPE contained in DATA extending
107a7b8c2e4Sniklas  * DATALEN bytes.  Return a certreq_aca structure which the caller is
108a7b8c2e4Sniklas  * responsible for deallocating.
109a7b8c2e4Sniklas  */
1106e55b688Sniklas struct certreq_aca *
certreq_decode(u_int16_t type,u_int8_t * data,u_int32_t datalen)1116e55b688Sniklas certreq_decode(u_int16_t type, u_int8_t *data, u_int32_t datalen)
1126e55b688Sniklas {
1136e55b688Sniklas 	struct cert_handler *handler;
1146e55b688Sniklas 	struct certreq_aca aca, *ret;
1156e55b688Sniklas 
11657240511Sniklas 	handler = cert_get(type);
11757240511Sniklas 	if (!handler)
11857240511Sniklas 		return 0;
1196e55b688Sniklas 
1206e55b688Sniklas 	aca.id = type;
1216e55b688Sniklas 	aca.handler = handler;
12205442ddfStom 	aca.data = aca.raw_ca = NULL;
1236e55b688Sniklas 
124fb9475d6Sderaadt 	if (datalen > 0) {
12505442ddfStom 		int rc;
12605442ddfStom 
12705442ddfStom 		rc = handler->certreq_decode(&aca.data, data, datalen);
12805442ddfStom 		if (!rc)
12957240511Sniklas 			return 0;
13005442ddfStom 
13105442ddfStom 		aca.raw_ca = malloc(datalen);
13205442ddfStom 		if (aca.raw_ca == NULL) {
13305442ddfStom 			log_error("certreq_decode: malloc (%lu) failed",
13405442ddfStom 			    (unsigned long)datalen);
13505442ddfStom 			handler->free_aca(aca.data);
13605442ddfStom 			return 0;
13705442ddfStom 		}
13805442ddfStom 
13905442ddfStom 		memcpy(aca.raw_ca, data, datalen);
14005442ddfStom 	}
14105442ddfStom 	aca.raw_ca_len = datalen;
1426e55b688Sniklas 
14357240511Sniklas 	ret = malloc(sizeof aca);
144fb9475d6Sderaadt 	if (!ret) {
1450cd3ca40Sho 		log_error("certreq_decode: malloc (%lu) failed",
1460cd3ca40Sho 		    (unsigned long)sizeof aca);
14705442ddfStom 		free(aca.raw_ca);
1486e55b688Sniklas 		handler->free_aca(aca.data);
14957240511Sniklas 		return 0;
1506e55b688Sniklas 	}
15157240511Sniklas 	memcpy(ret, &aca, sizeof aca);
1526e55b688Sniklas 	return ret;
1536e55b688Sniklas }
15423d41768Sniklas 
15523d41768Sniklas void
cert_free_subjects(int n,u_int8_t ** id,u_int32_t * len)15623d41768Sniklas cert_free_subjects(int n, u_int8_t **id, u_int32_t *len)
15723d41768Sniklas {
15823d41768Sniklas 	int	i;
15923d41768Sniklas 
16023d41768Sniklas 	for (i = 0; i < n; i++)
16123d41768Sniklas 		free(id[i]);
16223d41768Sniklas 	free(id);
16323d41768Sniklas 	free(len);
16423d41768Sniklas }
165