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