summaryrefslogtreecommitdiff
path: root/sbin/isakmpd
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1998-11-15 00:52:27 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1998-11-15 00:52:27 +0000
commit3188811a671a46dfde63d2145b9fc672861b573e (patch)
tree49cf89510a304d29909fb99bc089f24e3d7d70fa /sbin/isakmpd
parentf69f398919124d8c650874dab35467927df84ecf (diff)
Not clean enough yet
Diffstat (limited to 'sbin/isakmpd')
-rw-r--r--sbin/isakmpd/asn.c1155
-rw-r--r--sbin/isakmpd/asn_useful.c128
-rw-r--r--sbin/isakmpd/cert.c94
-rw-r--r--sbin/isakmpd/x509.c844
4 files changed, 0 insertions, 2221 deletions
diff --git a/sbin/isakmpd/asn.c b/sbin/isakmpd/asn.c
deleted file mode 100644
index 611579e3108..00000000000
--- a/sbin/isakmpd/asn.c
+++ /dev/null
@@ -1,1155 +0,0 @@
-/* $OpenBSD: asn.c,v 1.2 1998/11/15 00:43:49 niklas Exp $ */
-
-/*
- * Copyright (c) 1998 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.
- */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <gmp.h>
-#include <unistd.h>
-
-#include "log.h"
-#include "asn.h"
-#include "gmp_util.h"
-
-struct asn_handler table[] = {
- {TAG_INTEGER, asn_free_integer,
- asn_get_encoded_len_integer, asn_decode_integer, asn_encode_integer},
- {TAG_OBJECTID, asn_free_objectid,
- asn_get_encoded_len_objectid, asn_decode_objectid, asn_encode_objectid},
- {TAG_SEQUENCE, asn_free_sequence,
- asn_get_encoded_len_sequence, asn_decode_sequence, asn_encode_sequence},
- {TAG_SET, asn_free_sequence,
- asn_get_encoded_len_sequence, asn_decode_sequence, asn_encode_sequence},
- {TAG_UTCTIME, asn_free_string,
- asn_get_encoded_len_string, asn_decode_string, asn_encode_string},
- {TAG_BITSTRING, asn_free_string,
- asn_get_encoded_len_string, asn_decode_string, asn_encode_string},
- {TAG_OCTETSTRING, asn_free_string,
- asn_get_encoded_len_string, asn_decode_string, asn_encode_string},
- {TAG_BOOL, asn_free_string,
- asn_get_encoded_len_string, asn_decode_string, asn_encode_string},
- {TAG_PRINTSTRING, asn_free_string,
- asn_get_encoded_len_string, asn_decode_string, asn_encode_string},
- {TAG_RAW, asn_free_raw,
- asn_get_encoded_len_raw, asn_decode_raw, asn_encode_raw},
- {TAG_NULL, asn_free_null,
- asn_get_encoded_len_null, asn_decode_null, asn_encode_null},
- {TAG_ANY, asn_free_null,
- NULL, asn_decode_any, NULL},
- {TAG_STOP, NULL, NULL, NULL, NULL}
-};
-
-int
-asn_get_from_file (char *name, u_int8_t **asn, u_int32_t *asnlen)
-{
- int fd, res = 0;
- struct stat st;
-
- if (stat (name, &st) == -1)
- {
- log_error ("asn_get_from_file: failed to state %s", name);
- return 0;
- }
-
- *asnlen = st.st_size;
-
- if ((fd = open (name, O_RDONLY)) == -1)
- {
- log_error ("asn_get_from_file: failed to open %s", name);
- return 0;
- }
-
- if ((*asn = malloc (st.st_size)) == NULL)
- {
- log_print ("asn_get_from_file: out of memory");
- res = 0;
- goto done;
- }
-
- if (read (fd, *asn, st.st_size) != st.st_size ||
- asn_get_len (*asn) != *asnlen)
- {
- log_print ("x509_asn_obtain: asn file ended early");
- free (*asn);
- res = 0;
- goto done;
- }
-
- res = 1;
-
- done:
- close (fd);
-
- return res;
-}
-
-struct norm_type *
-asn_template_clone (struct norm_type *obj, int constructed)
-{
- struct norm_type *p;
- u_int32_t i;
-
- if (!constructed)
- {
- p = malloc (sizeof (struct norm_type));
- if (p == NULL)
- return NULL;
-
- memcpy (p, obj, sizeof (struct norm_type));
-
- obj = p;
- }
-
- if (obj->type != TAG_SEQUENCE && obj->type != TAG_SET)
- {
- obj->len = 0;
- obj->data = NULL;
- }
- else if (obj->type == TAG_SEQUENCE || obj->type == TAG_SET)
- {
- p = obj;
- obj = obj->data;
- i = 0;
- while (obj[i++].type != TAG_STOP);
-
- p->data = malloc (i * sizeof (struct norm_type));
- if (p->data == NULL)
- return NULL;
-
- memcpy (p->data, obj, i * sizeof (struct norm_type));
- obj = p->data;
-
- i = 0;
- while (obj[i].type != TAG_STOP)
- {
- obj[i].len = 0;
- if (asn_template_clone (&obj[i], 1) == NULL)
- return NULL;
-
- i++;
- }
- }
-
- return obj;
-}
-
-/* Associates a human readable name to an OBJECT IDENTIFIER */
-
-char *
-asn_parse_objectid (struct asn_objectid *table, char *id)
-{
- u_int32_t len = 0;
- char *p = NULL;
- static char buf[LINE_MAX];
-
- if (id == NULL)
- return NULL;
-
- while (table->name != NULL)
- {
- if (!strcmp (table->objectid, id))
- return table->name;
- if (!strncmp (table->objectid, id, strlen (table->objectid)) &&
- strlen (table->objectid) > len)
- {
- len = strlen (table->objectid);
- p = table->name;
- }
-
- table++;
- }
-
- if (len == 0)
- return NULL;
-
- strncpy (buf, p, sizeof (buf) - 1);
- buf[sizeof (buf) - 1] = 0;
- strncat (buf + strlen (buf), id + len, sizeof (buf) -1 - strlen (buf));
- buf[sizeof (buf) - 1] = 0;
-
- return buf;
-}
-
-/* Retrieves the pointer to a data type referenced by the path name */
-
-struct norm_type *
-asn_decompose (char *path, struct norm_type *obj)
-{
- char *p, *p2, *tmp;
- int counter;
-
- if (!strcasecmp (path, obj->name))
- return obj->data;
-
- p = path = strdup (path);
- p2 = strsep (&p, ".");
-
- if (strcasecmp (p2, obj->name) || p == NULL)
- goto fail;
-
- while (p != NULL)
- {
- obj = obj->data;
- if (obj == NULL)
- break;
-
- p2 = strsep (&p, ".");
-
- /*
- * For SEQUENCE OF or SET OF, we want to be able to say
- * AttributeValueAssertion[1] for the 2nd value.
- */
- tmp = strchr (p2, '[');
- if (tmp != NULL)
- {
- counter = atoi (tmp+1);
- *tmp = 0;
- }
- else
- counter = 0;
-
- /* Find the Tag */
- while (obj->type != TAG_STOP)
- {
- if (!strcasecmp (p2, obj->name) && counter-- == 0)
- break;
- obj++;
- }
-
- if (obj->type == TAG_STOP)
- goto fail;
-
- if (p == NULL)
- goto done;
-
- if (obj->type != TAG_SEQUENCE && obj->type != TAG_SET)
- goto fail;
- }
-
- done:
- free (path);
- return obj;
-
- fail:
- free (path);
- return NULL;
-}
-
-/* Gets an entry from the ASN.1 tag switch table */
-
-struct asn_handler *
-asn_get (enum asn_tags type)
-{
- struct asn_handler *h = table;
-
- while (h->type != TAG_STOP)
- if (h->type == type)
- return h;
- else
- h++;
-
- return NULL;
-}
-
-/*
- * For the long form of BER encoding we need to know in how many
- * octets the length can be encoded.
- */
-
-u_int32_t
-asn_sizeinoctets (u_int32_t len)
-{
- u_int32_t log = 0;
-
- while (len)
- {
- log++;
- len >>= 8;
- }
-
- return log;
-}
-
-u_int8_t *
-asn_format_header (struct norm_type *obj, u_int8_t *asn, u_int8_t **data)
-{
- u_int8_t *buf = NULL, type;
- u_int16_t len_off, len;
- struct asn_handler *h;
-
- h = asn_get (obj->type);
- if (h == NULL)
- return NULL;
-
- if (asn != NULL)
- buf = asn;
-
- /* We only do low tag at the moment */
- len_off = 1;
-
- len = h->get_encoded_len (obj, &type);
-
- if (buf == NULL && (buf = malloc (len)) == NULL)
- return NULL;
-
- if (type != ASN_LONG_FORM)
- {
- len -= len_off + 1;
- buf[len_off] = len;
-
- *data = buf + len_off + 1;
- }
- else
- {
- u_int16_t tmp;
- int octets = asn_sizeinoctets (len);
-
- len -= len_off + 1 + octets;
- *data = buf + len_off + 1 + octets;
-
- buf[len_off] = octets | ASN_LONG_FORM;
-
- tmp = len;
- while (--octets >= 0)
- {
- buf[len_off + 1 + octets] = tmp;
- tmp >>= 8;
- }
- }
-
- if (ISEXPLICIT(obj))
- {
- u_int8_t *erg;
- /* Explicit tagging add an outer layer */
- struct norm_type tmp = {obj->type, obj->class&0x3, NULL, 0, obj->data};
-
- /* XXX - force the class to be CONTEXT */
- buf[0] = GET_EXP(obj) | (((enum asn_classes)CONTEXT & 0x3) << 6) |
- ASN_CONSTRUCTED;
- erg = asn_format_header (&tmp, *data, data);
-
- if (erg && (obj->type == TAG_SEQUENCE || obj->type == TAG_SET))
- erg[0] |= ASN_CONSTRUCTED;
- }
- else
- /* XXX low tag only */
- buf[0] = obj->type | (obj->class << 6);
-
- return buf;
-}
-
-u_int32_t
-asn_get_encoded_len (struct norm_type *obj, u_int32_t len, u_int8_t *type)
-{
- u_int32_t len_off = 1;
-
- if (len <= 127)
- {
- /* Short form */
- len = len + 1 + len_off;
- if (type != NULL)
- *type = 0;
- }
- else
- {
- /* Long Form */
- len = len + asn_sizeinoctets (len) + 1 + len_off;
- if (type != NULL)
- *type = ASN_LONG_FORM;
- }
-
- if (obj != NULL && ISEXPLICIT(obj))
- len = asn_get_encoded_len (NULL, len, NULL);
-
- return len;
-}
-
-/* Tries to decode an ANY tag, if we cant handle it we just raw encode it */
-
-u_int8_t *
-asn_decode_any (u_int8_t *asn, u_int32_t asnlen, struct norm_type *obj)
-{
- struct asn_handler *h;
- enum asn_tags type;
-
- type = TAG_TYPE (asn);
- if (type == TAG_SEQUENCE || type == TAG_SET)
- type = TAG_RAW;
-
- h = asn_get (type);
- if (h == NULL)
- {
- type = TAG_RAW;
- h = asn_get (type);
- }
-
- obj->type = type;
- return h->decode (asn, asnlen, obj);
-}
-
-u_int32_t
-asn_get_encoded_len_integer (struct norm_type *obj, u_int8_t *type)
-{
- u_int16_t len_off;
- u_int32_t len = obj->len;
- u_int32_t tmp;
- mpz_t a;
-
- /* XXX - We only do low tag at the moment */
- len_off = 1;
-
- obj->len = len = mpz_sizeinoctets ((mpz_ptr) obj->data);
- mpz_init_set (a, (mpz_ptr) obj->data);
-
- if (len > 1)
- mpz_fdiv_q_2exp (a, a, (len - 1) << 3);
-
- tmp = mpz_fdiv_r_ui (a, a, 256);
- mpz_clear (a);
-
- /*
- * We only need to encode positive integers, ASN.1 defines
- * negative integers to have the msb set, so if data[0] has
- * msb set we need to introduce a zero octet.
- */
- if (tmp & 0x80)
- len++;
-
- return asn_get_encoded_len (obj, len, type);
-}
-
-/*
- * Encode an integer value.
- * Input = obj, output = asn or return value.
- */
-
-u_int8_t *
-asn_encode_integer (struct norm_type *obj, u_int8_t *asn)
-{
- u_int8_t *buf, *data;
- u_int32_t len;
-
- buf = asn_format_header (obj, asn, &data);
-
- if (buf == NULL)
- return NULL;
-
- len = mpz_sizeinoctets ((mpz_ptr) obj->data);
- mpz_getraw (data, (mpz_ptr) obj->data, len);
-
- /* XXX - We only deal with unsigned integers at the moment */
- if (data[0] & 0x80)
- {
- memmove (data + 1, data, len);
- data[0] = 0;
- }
-
- return buf;
-}
-
-u_int8_t *
-asn_decode_integer (u_int8_t *asn, u_int32_t asnlen, struct norm_type *obj)
-{
- u_int8_t *data;
- u_int32_t len;
-
- if (asnlen < asn_get_len (asn))
- {
- log_print ("asn_decode_integer: ASN.1 content is bigger than buffer");
- return NULL;
- }
-
- len = asn_get_data_len (obj, &asn, &data);
-
- if (TAG_TYPE(asn) != TAG_INTEGER)
- {
- log_print ("asn_decode_integer: expected tag type INTEGER, got %d",
- TAG_TYPE(asn));
- return NULL;
- }
-
- obj->data = malloc (sizeof (mpz_ptr));
- if (obj->data == NULL)
- {
- log_print ("asn_decode_integer: out of memory.");
- return NULL;
- }
-
- mpz_init ((mpz_ptr) obj->data);
- mpz_setraw ((mpz_ptr) obj->data, data, len);
-
- obj->len = len;
-
- return data + len;
-}
-
-void
-asn_free_integer (struct norm_type *obj)
-{
- if (obj->data != NULL)
- {
- mpz_clear ((mpz_ptr) obj->data);
- free (obj->data);
- }
-}
-
-
-u_int32_t
-asn_get_encoded_len_string (struct norm_type *obj, u_int8_t *type)
-{
- return asn_get_encoded_len (obj, obj->len, type);
-}
-
-/*
- * Encode a String
- * Input = obj, output = asn or return value.
- */
-
-u_int8_t *
-asn_encode_string (struct norm_type *obj, u_int8_t *asn)
-{
- u_int8_t *buf, *data;
-
- buf = asn_format_header (obj, asn, &data);
-
- if (buf == NULL)
- return NULL;
-
- memcpy (data, obj->data, obj->len);
-
- return buf;
-}
-
-u_int8_t *
-asn_decode_string (u_int8_t *asn, u_int32_t asnlen, struct norm_type *obj)
-{
- u_int8_t *data;
- u_int32_t len;
-
- obj->len = len = asn_get_data_len (obj, &asn, &data);
-
- if (TAG_TYPE(asn) != obj->type)
- {
- log_print ("asn_decode_string: expected tag type STRING(%d), got %d",
- obj->type, TAG_TYPE(asn));
- return NULL;
- }
-
- if (asnlen < asn_get_len (asn))
- {
- log_print ("asn_decode_string: ASN.1 content is bigger than buffer");
- return NULL;
- }
-
- obj->data = malloc (obj->len + 1);
- if (obj->data == NULL)
- return NULL;
- memcpy ((char *)obj->data, data, obj->len);
- /*
- * Encode a terminating '0', this is irrelevant for OCTET strings
- * but nice for printable strings which do not include the terminating
- * zero.
- */
- ((char *)obj->data)[obj->len] = 0;
-
- return data + len;
-}
-
-void
-asn_free_string (struct norm_type *obj)
-{
- if (obj->data != NULL)
- free (obj->data);
-}
-
-
-u_int32_t
-asn_get_encoded_len_objectid (struct norm_type *obj, u_int8_t *type)
-{
- u_int16_t len_off;
- u_int32_t len;
- u_int32_t tmp;
- char *buf, *buf2;
-
- /* XXX - We only do low tag at the moment */
- len_off = 1;
-
- /* The first two numbers are encoded together */
- buf = obj->data;
- tmp = strtol (buf, &buf2, 10);
- buf = buf2;
- tmp = strtol (buf, &buf2, 10);
- buf = buf2;
-
- len = 1;
- while (*buf)
- {
- tmp = strtol (buf, &buf2, 10);
- if (buf == buf2)
- break;
-
- buf = buf2;
- do {
- tmp >>= 7;
- len++;
- } while (tmp);
- }
-
- /* The first two ids are encoded as one octet */
- obj->len = len - 1;
-
- return asn_get_encoded_len (obj, len, type);
-}
-
-/*
- * Encode an Object Identifier
- * Input = obj, output = asn or return value.
- */
-
-u_int8_t *
-asn_encode_objectid (struct norm_type *obj, u_int8_t *asn)
-{
- u_int8_t *buf, *data;
- char *enc, *enc2;
- u_int32_t tmp, tmp2;
- int flag = 0;
-
- buf = asn_format_header (obj, asn, &data);
-
- if (buf == NULL)
- return NULL;
-
- enc = obj->data;
- while (*enc)
- {
- /* First two ids are encoded as one octet */
- if (flag == 0)
- {
- tmp = strtol (enc, &enc2, 10);
- if (enc == enc2)
- return NULL;
- enc = enc2;
- tmp2 = strtol (enc, &enc2, 10) + 40 * tmp;
- flag = 1;
- }
- else
- tmp2 = strtol (enc, &enc2, 10);
-
- if (enc == enc2)
- break;
-
- /* Reverse the digits to base-128 */
- tmp = 0;
- do {
- tmp <<= 7;
- tmp += tmp2 & 0x7f;
- tmp2 >>= 7;
- } while (tmp2);
-
- enc = enc2;
- do {
- /* If the next octet still belongs to the data set msb */
- *data++ = (tmp & 0x7f) | ( tmp > 127 ? 0x80 : 0);
- tmp >>= 7;
- } while (tmp);
- }
-
- return buf;
-}
-
-u_int8_t *
-asn_decode_objectid (u_int8_t *asn, u_int32_t asnlen, struct norm_type *obj)
-{
- u_int8_t *data;
- u_int32_t len, c, tmp;
- int flag = 0;
- void *new_buf;
-
- len = asn_get_data_len (obj, &asn, &data);
-
- if (TAG_TYPE(asn) != TAG_OBJECTID)
- {
- log_print ("asn_decode_objectid: expected tag type OBJECTID, got %d",
- TAG_TYPE(asn));
- return NULL;
- }
-
- if (asnlen < asn_get_len (asn))
- {
- log_print ("asn_decode_objectid: ASN.1 content is bigger than buffer");
- return NULL;
- }
-
- obj->data = NULL;
- obj->len = 0;
- while (len > 0)
- {
- tmp = 0;
- do {
- tmp <<= 7;
- tmp += *data & 0x7f;
- } while (len-- > 0 && (*data++ & 0x80));
-
- if (flag == 0)
- c = snprintf (NULL, 0, "%d %d ", tmp/40, tmp % 40) + 1;
- else
- c = snprintf (NULL, 0, "%d ", tmp) + 1;
-
- new_buf = realloc (obj->data, obj->len + c);
- if (new_buf == NULL)
- {
- free (obj->data);
- obj->data = NULL;
- log_print ("asn_decode_objectid: out of memory.");
- return NULL;
- }
- obj->data = new_buf;
-
- if (flag == 0)
- {
- sprintf (obj->data + obj->len, "%d %d ", tmp/40, tmp % 40);
- flag = 1;
- }
- else
- sprintf (obj->data + obj->len, "%d ", tmp);
-
- obj->len = strlen (obj->data);
- }
-
- if (obj->data != NULL)
- ((char *)obj->data)[obj->len - 1] = 0;
-
- return data;
-}
-
-void
-asn_free_objectid (struct norm_type *obj)
-{
- if (obj->data != NULL)
- free (obj->data);
-}
-
-
-u_int32_t
-asn_get_encoded_len_raw (struct norm_type *obj, u_int8_t *type)
-{
- if (type != NULL)
- {
- if (obj->len > 127)
- *type = ASN_LONG_FORM;
- else
- *type = 0;
- }
-
- return obj->len;
-}
-
-u_int8_t *
-asn_encode_raw (struct norm_type *obj, u_int8_t *asn)
-{
- u_int8_t *buf = NULL;
-
- if (obj->len == 0)
- return asn;
-
- if (asn != NULL)
- buf = asn;
-
- if (buf == NULL && (buf = malloc (obj->len)) == NULL)
- return NULL;
-
- memcpy (buf, obj->data, obj->len);
-
- return buf;
-}
-
-u_int8_t *
-asn_decode_raw (u_int8_t *asn, u_int32_t asnlen, struct norm_type *obj)
-{
- obj->len = asn_get_len (asn);
- if (asnlen < obj->len)
- {
- log_print ("asn_decode_raw: ASN.1 content is bigger than buffer");
- return NULL;
- }
-
- obj->data = malloc (obj->len);
- if (obj->data == NULL)
- {
- log_print ("asn_decode_raw: out of memory");
- return NULL;
- }
-
- memcpy (obj->data, asn, obj->len);
-
- return asn + obj->len;
-}
-
-void
-asn_free_raw (struct norm_type *obj)
-{
- if (obj->data != NULL)
- free (obj->data);
-}
-
-u_int32_t
-asn_get_encoded_len_null (struct norm_type *obj, u_int8_t *type)
-{
- return asn_get_encoded_len (obj, 0, type);
-}
-
-u_int8_t *
-asn_encode_null (struct norm_type *obj, u_int8_t *asn)
-{
- u_int8_t *buf = NULL;
-
- if (asn != NULL)
- buf = asn;
-
- if (buf == NULL && (buf = malloc (2)) == NULL)
- return NULL;
-
- buf[0] = obj->type;
- buf[1] = 0;
-
- return buf;
-}
-
-u_int8_t *
-asn_decode_null (u_int8_t *asn, u_int32_t asnlen, struct norm_type *obj)
-{
- obj->data = NULL;
- obj->len = 0;
-
- return asn + asn_get_len (asn);
-}
-
-void
-asn_free_null (struct norm_type *obj)
-{
- obj->data = NULL;
-}
-
-void
-asn_free (struct norm_type *obj)
-{
- struct asn_handler *h = asn_get (obj->type);
-
- if (h == NULL)
- log_print ("asn_free: unkown ASN.1 type %d", obj->type);
- else
- h->free (obj);
-}
-
-/*
- * Returns the whole length of the BER encoded ASN.1 object.
- */
-
-u_int32_t
-asn_get_len (u_int8_t *asn)
-{
- u_int32_t len;
- u_int8_t *data;
- struct norm_type tmp = {TAG_RAW, UNIVERSAL, NULL, 0, NULL};
-
- len = asn_get_data_len (&tmp, &asn, &data);
-
- if (asn == NULL)
- return 0;
-
- return (data - asn) + len;
-}
-
-/*
- * Returns the length of the ASN content, and a pointer to the content
- * data itself.
- * For TAG_NULL the data length is zero, so we have to return an error
- * in asn, asn will be NULL in case of error.
- */
-
-u_int32_t
-asn_get_data_len (struct norm_type *obj, u_int8_t **asn, u_int8_t **data)
-{
- u_int32_t len;
- u_int16_t len_off = 1;
-
- if (obj != NULL && ISEXPLICIT(obj))
- {
- struct norm_type tmp = {TAG_RAW, UNIVERSAL, NULL, 0, NULL};
-
- if (TAG_TYPE(*asn) != GET_EXP(obj))
- {
- log_print ("asn_get_data_len: explict tagging was needed");
- *asn = NULL;
- return 0;
- }
-
- asn_get_data_len (&tmp, asn, data);
- *asn = *data;
- }
-
- if ((*asn)[len_off] & ASN_LONG_FORM)
- {
- int i, octets = (*asn)[len_off] & 0x7f;
-
- /* XXX - we only decode really small length */
- if (octets > sizeof (len))
- {
- log_print ("asn_get_data_len: long form length %d exceeds "
- "allowed maximum", octets);
- *asn = NULL;
- return 0;
- }
-
- for (len = 0, i = 0; i < octets; i++)
- {
- len = (len << 8) | (*asn)[len_off + 1 + i];
- }
-
- if (data != NULL)
- *data = *asn + len_off + 1 + octets;
- }
- else
- {
- /* Short form */
- len = (*asn)[len_off];
-
- if (data != NULL)
- *data = *asn + len_off + 1;
- }
-
- return len;
-}
-
-void
-asn_free_sequence (struct norm_type *obj)
-{
- struct norm_type *in = obj->data;
- struct asn_handler *h;
-
- if (in == NULL)
- return;
-
- while (in->type != TAG_STOP)
- {
- h = asn_get (in->type);
- if (h == NULL)
- break;
-
- h->free (in++);
- }
-
- free (obj->data);
-}
-
-u_int32_t
-asn_get_encoded_len_sequence (struct norm_type *seq, u_int8_t *type)
-{
- u_int32_t len, i;
- struct asn_handler *h;
- struct norm_type *obj = (struct norm_type *) seq->data;
-
- /* Get whole data length */
- for (len = 0, i = 0; obj[i].type != TAG_STOP; i++)
- {
- h = asn_get (obj[i].type);
- if (h == NULL)
- {
- log_print ("asn_encode_sequence: unkown type %d", obj[i].type);
- break;
- }
- len += h->get_encoded_len (&obj[i], NULL);
- }
-
- return asn_get_encoded_len (seq, len, type);
-}
-
-u_int8_t *
-asn_encode_sequence (struct norm_type *seq, u_int8_t *asn)
-{
- u_int32_t len;
- u_int8_t *erg, *data;
- struct norm_type *obj;
- struct asn_handler *h;
- int i;
-
- if ((h = asn_get (seq->type)) == NULL)
- return NULL;
-
- obj = (struct norm_type *) seq->data;
-
- erg = asn_format_header (seq, asn, &data);
- if (erg == NULL)
- return NULL;
-
- for (i = 0, len = 0; obj[i].type != TAG_STOP; i++)
- {
- h = asn_get (obj[i].type);
- if (h == NULL)
- {
- log_print ("asn_encode_sequence: unknown ASN.1 tag %d", obj[i].type);
- return NULL;
- }
-
- /* A structure can be optional, indicated by data == NULL */
- if (h->encode (&obj[i], data + len) == NULL && obj->data != NULL)
- {
- log_print ("asn_encode_sequence: encoding of %s failed",
- obj[i].name);
- return NULL;
- }
- len += h->get_encoded_len (&obj[i], NULL);
- }
-
- erg[0] |= ASN_CONSTRUCTED;
-
- return erg;
-}
-
-u_int8_t *
-asn_decode_sequence (u_int8_t *asn, u_int32_t asnlen, struct norm_type *obj)
-{
- u_int8_t *p, *data;
- u_int32_t len, flags, objects;
- struct asn_handler *h;
- void *new_buf;
-
- if (asnlen < asn_get_len (asn))
- {
- log_print ("asn_decode_sequence: ASN.1 content is bigger than buffer");
- return NULL;
- }
-
- len = asn_get_data_len (obj, &asn, &data);
-
- /* XXX - an empty sequence is that okay */
- if (len == 0)
- return data;
-
- if (TAG_TYPE(asn) != obj->type)
- {
- log_print ("asn_decode_sequence: expected tag type SEQUENCE/SET, got %d",
- TAG_TYPE(asn));
- return NULL;
- }
-
- /* Handle dynamic sized sets and sequences */
- flags = obj->flags;
-
- if (flags & ASN_FLAG_ZEROORMORE)
- {
- struct norm_type stop_tag = {TAG_STOP};
- struct norm_type *tmp;
-
- /* Zero occurences */
- if (len == 0)
- {
- asn_free (obj);
- obj->data = NULL;
- return data;
- }
-
- /* Count number of objects */
- p = data;
- objects = 0;
- while (p < data + len)
- {
- objects++;
- p += asn_get_len (p);
- }
- if (p != data + len)
- {
- log_print ("asn_decode_sequence: SEQ/SET OF too many elements");
- return NULL;
- }
-
- /*
- * Create new templates for dynamically added objects,
- * the ASN.1 tags SEQUENCE OF and SET OF, specify an unknown
- * number of elements.
- */
-
- new_buf = realloc (obj->data,
- (objects+1) * sizeof (struct norm_type));
- if (new_buf == NULL)
- {
- asn_free (obj);
- obj->data = NULL;
- log_print ("asn_decode_sequence: out of memory");
- return NULL;
- }
- obj->data = new_buf;
-
- tmp = obj->data;
-
- /* Copy TAG_STOP */
- memcpy (tmp + objects, &stop_tag, sizeof (struct norm_type));
- while (objects-- > 1)
- {
- memcpy (tmp + objects, tmp, sizeof (struct norm_type));
- if (asn_template_clone (tmp + objects, 1) == NULL)
- return NULL;
- }
- }
-
- obj = (struct norm_type *) obj->data;
-
- p = data;
- while (p < data + len)
- {
- if (obj->type == TAG_STOP)
- break;
- h = asn_get (obj->type);
- if (h == NULL)
- {
- log_print ("asn_decode_sequence: unknown ASN.1 tag %d", obj->type);
- return NULL;
- }
-
- if ((p = h->decode (p, (data - p) + len, obj++)) == NULL)
- break;
- }
-
- if (p < data + len)
- log_print ("asn_decode_sequence: ASN tag was not decoded completely");
-
- if (p == NULL)
- return NULL;
-
- return data + len;
-}
diff --git a/sbin/isakmpd/asn_useful.c b/sbin/isakmpd/asn_useful.c
deleted file mode 100644
index 1ec652d1b85..00000000000
--- a/sbin/isakmpd/asn_useful.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* $OpenBSD: asn_useful.c,v 1.2 1998/11/15 00:43:49 niklas Exp $ */
-
-/*
- * Copyright (c) 1998 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.
- */
-
-#include <sys/param.h>
-
-#include "asn.h"
-#include "asn_useful.h"
-
-struct norm_type AlgorithmIdentifier[] = {
- {TAG_OBJECTID, UNIVERSAL, "algorithm", 0, NULL},
- {TAG_ANY, UNIVERSAL, "parameters", 0, NULL},
- {TAG_STOP, UNIVERSAL, NULL, 0, NULL}};
-
-struct norm_type Signed[] = {
- {TAG_RAW, UNIVERSAL, "data", 0, NULL},
- SEQ("algorithm", AlgorithmIdentifier),
- {TAG_BITSTRING, UNIVERSAL, "encrypted", 0, NULL},
- {TAG_STOP, UNIVERSAL, NULL, 0, NULL}};
-
-struct norm_type Validity[] = {
- {TAG_UTCTIME, UNIVERSAL, "notBefore", 0, NULL},
- {TAG_UTCTIME, UNIVERSAL, "notAfter", 0, NULL},
- {TAG_STOP, UNIVERSAL, NULL, 0, NULL}};
-
-struct norm_type AttributeValueAssertion[] = {
- {TAG_OBJECTID, UNIVERSAL, "AttributeType", 0, NULL},
- {TAG_ANY, UNIVERSAL, "AttributeValue", 0, NULL},
- {TAG_STOP, UNIVERSAL, NULL, 0, NULL}};
-
-struct norm_type RelativeDistinguishedName[] = {
- SEQ ("AttributeValueAssertion", AttributeValueAssertion),
- {TAG_STOP}};
-
-/*
- * For decoding this structure is dynamically resized, we add two Names
- * only for encoding purposes.
- */
-struct norm_type RDNSequence[] = {
- SETOF ("RelativeDistinguishedName", RelativeDistinguishedName),
- SETOF ("RelativeDistinguishedName", RelativeDistinguishedName),
- {TAG_STOP}};
-
-struct norm_type SubjectPublicKeyInfo[] = {
- SEQ ("algorithm", AlgorithmIdentifier),
- {TAG_BITSTRING, UNIVERSAL, "subjectPublicKey", 0, NULL},
- {TAG_STOP}};
-
-struct norm_type Extension[] = {
- {TAG_OBJECTID, UNIVERSAL, "extnId", 0, NULL},
- {TAG_BOOL, UNIVERSAL, "critical", 0, NULL},
- {TAG_OCTETSTRING, UNIVERSAL, "extnValue", 0, NULL},
- {TAG_STOP}};
-
-struct norm_type Extensions[] = {
- SEQ ("extension", Extension),
- {TAG_STOP}};
-
-struct norm_type Certificate[] = {
- /* We need to add an explicit tag, HACK XXX */
- {TAG_INTEGER, ADD_EXP(0, UNIVERSAL), "version", 0, NULL},
- {TAG_INTEGER, UNIVERSAL, "serialNumber", 0, NULL},
- SEQ ("signature", AlgorithmIdentifier),
- SEQOF ("issuer", RDNSequence),
- SEQ ("validity", Validity),
- SEQOF ("subject", RDNSequence),
- SEQ ("subjectPublicKeyInfo", SubjectPublicKeyInfo),
- {TAG_RAW, UNIVERSAL, "extension", 0, NULL},
- {TAG_STOP}};
-
-struct norm_type DigestInfo[] = {
- SEQ ("digestAlgorithm", AlgorithmIdentifier),
- {TAG_OCTETSTRING, UNIVERSAL, "digest", 0, NULL},
- {TAG_STOP}};
-
-struct asn_objectid asn_ids[] = {
- {"AttributeType", ASN_ID_ATTRIBUTE_TYPE},
- {"CountryName", ASN_ID_COUNTRY_NAME},
- {"LocalityName", ASN_ID_LOCALITY_NAME},
- {"StateOrProvinceName", ASN_ID_STATE_NAME},
- {"OrganizationName", ASN_ID_ORGANIZATION_NAME},
- {"OrganizationUnitName", ASN_ID_ORGUNIT_NAME},
- {"CommonUnitName", ASN_ID_COMMONUNIT_NAME},
- {"pkcs-1", ASN_ID_PKCS},
- {"rsaEncryption", ASN_ID_RSAENCRYPTION},
- {"md2WithRSAEncryption", ASN_ID_MD2WITHRSAENC},
- {"md4WithRSAEncryption", ASN_ID_MD4WITHRSAENC},
- {"md5WithRSAEncryption", ASN_ID_MD5WITHRSAENC},
- {"md2", ASN_ID_MD2},
- {"md4", ASN_ID_MD4},
- {"md5", ASN_ID_MD5},
- {"emailAddress", ASN_ID_EMAILADDRESS},
- {"id-ce", ASN_ID_CE},
- {"subjectAltName", ASN_ID_SUBJECT_ALT_NAME},
- {"issuerAltName", ASN_ID_ISSUER_ALT_NAME},
- {"basicConstraints", ASN_ID_BASIC_CONSTRAINTS},
- {NULL, NULL} };
diff --git a/sbin/isakmpd/cert.c b/sbin/isakmpd/cert.c
deleted file mode 100644
index 9e53ec25795..00000000000
--- a/sbin/isakmpd/cert.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/* $OpenBSD: cert.c,v 1.2 1998/11/15 00:43:50 niklas Exp $ */
-
-/*
- * Copyright (c) 1998 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.
- */
-
-#include <sys/param.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "cert.h"
-#include "isakmp_num.h"
-#include "x509.h"
-
-struct cert_handler cert_handler[] = {
- {ISAKMP_CERTENC_X509_SIG,
- x509_certreq_validate, x509_certreq_decode, x509_free_aca,
- x509_cert_obtain, x509_cert_get_key, x509_cert_get_subject}
-};
-
-struct cert_handler *
-cert_get (u_int16_t id)
-{
- int i;
-
- for (i = 0; i < sizeof cert_handler / sizeof cert_handler[0]; i++)
- if (id == cert_handler[i].id)
- return &cert_handler[i];
- return NULL;
-}
-
-
-/* Decode a CERTREQ and return a parsed structure */
-
-struct certreq_aca *
-certreq_decode (u_int16_t type, u_int8_t *data, u_int32_t datalen)
-{
- struct cert_handler *handler;
- struct certreq_aca aca, *ret;
-
- if ((handler = cert_get (type)) == NULL)
- return NULL;
-
- aca.id = type;
- aca.handler = handler;
-
- if (datalen > 0)
- {
- aca.data = handler->certreq_decode (data, datalen);
- if (aca.data == NULL)
- return NULL;
- }
- else
- aca.data = NULL;
-
- if ((ret = malloc (sizeof (aca))) == NULL)
- {
- handler->free_aca (aca.data);
- return NULL;
- }
-
- memcpy (ret, &aca, sizeof (aca));
-
- return ret;
-}
diff --git a/sbin/isakmpd/x509.c b/sbin/isakmpd/x509.c
deleted file mode 100644
index 16b264ae126..00000000000
--- a/sbin/isakmpd/x509.c
+++ /dev/null
@@ -1,844 +0,0 @@
-/* $OpenBSD: x509.c,v 1.2 1998/11/15 00:44:05 niklas Exp $ */
-
-/*
- * Copyright (c) 1998 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.
- */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <gmp.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "conf.h"
-#include "exchange.h"
-#include "hash.h"
-#include "ike_auth.h"
-#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 */
-
-/* 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;
-
- if (asn_template_clone (&name, 1) == NULL ||
- (asn = asn_decode_sequence (asn, len, &name)) == NULL)
- {
- log_print ("x509_certreq_validate: can not decode 'acceptable CA' info");
- res = 0;
- }
- asn_free (&name);
-
- return res;
-}
-
-/* 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;
-
- if (asn_template_clone (&aca, 1) == NULL ||
- (asn = asn_decode_sequence (asn, len, &aca)) == NULL)
- {
- log_print ("x509_certreq_validate: can not decode 'acceptable CA' info");
- goto fail;
- }
- memset (&naca, 0, sizeof (naca));
-
- tmp = asn_decompose ("aca.RelativeDistinguishedName.AttributeValueAssertion", &aca);
- if (tmp == NULL)
- goto fail;
- x509_get_attribval (tmp, &naca.name1);
-
- tmp = asn_decompose ("aca.RelativeDistinguishedName[1].AttributeValueAssertion", &aca);
- if (tmp != NULL)
- x509_get_attribval (tmp, &naca.name2);
-
- asn_free (&aca);
-
- if ((ret = malloc (sizeof (struct x509_aca))) != NULL)
- memcpy (ret, &naca, sizeof (struct x509_aca));
- else
- x509_free_aca (&aca);
-
- return ret;
-
- fail:
- asn_free (&aca);
- return NULL;
-}
-
-void
-x509_free_aca (void *blob)
-{
- struct x509_aca *aca = blob;
-
- if (aca->name1.type != NULL)
- free (aca->name1.type);
- if (aca->name1.val != NULL)
- free (aca->name1.val);
-
- if (aca->name2.type != NULL)
- free (aca->name2.type);
- if (aca->name2.val != NULL)
- free (aca->name2.val);
-}
-
-/*
- * 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)
-{
- struct x509_aca *aca = data;
- struct ipsec_exch *ie = exchange->data;
- char *certfile;
- int fd, res = 0;
- struct stat st;
-
- if (aca != NULL)
- 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);
-
- /* XXX - this needs to be changed - but how else shoud I know */
- switch (ie->ike_auth->id)
- {
- case IKE_AUTH_RSA_SIG:
- if ((certfile = conf_get_str ("rsa_sig", "cert")) == NULL)
- return 0;
- break;
- default:
- return 0;
- }
-
- if (stat (certfile, &st) == -1)
- {
- log_error ("x509_cert_obtain: failed to state %s", certfile);
- return 0;
- }
-
- *certlen = st.st_size;
-
- if ((fd = open (certfile, O_RDONLY)) == -1)
- {
- log_error ("x509_cert_obtain: failed to open %s", certfile);
- return 0;
- }
-
- if ((*cert = malloc (st.st_size)) == NULL)
- {
- log_print ("x509_cert_obtain: out of memory");
- res = 0;
- goto done;
- }
-
- if (read (fd, *cert, st.st_size) != st.st_size)
- {
- log_print ("x509_cert_obtain: cert file ended early");
- free (*cert);
- res = 0;
- goto done;
- }
-
- {
- /*
- * XXX - assumes IPv4 here, assumes 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
- */
- u_int8_t *id_cert, *asn, *id;
- size_t id_len;
- u_int32_t id_cert_len;
-
- /* XXX - assumes IPv4 */
- id = exchange->initiator ? exchange->id_i : exchange->id_r;
- id_len = exchange->initiator ? exchange->id_i_len : exchange->id_r_len;
-
- /* XXX - we need our ID to set that in the cert */
- if (id != NULL)
- {
- /* XXX - get to address ? */
- id += 4; id_len -= 4;
-
- /* Get offset into data structure where the IP is saved */
- asn = *cert;
- id_cert_len = asn_get_data_len (NULL, &asn, &id_cert);
- asn = id_cert;
- id_cert_len = asn_get_data_len (NULL, &asn, &id_cert);
- id_cert += id_cert_len - 4;
- memcpy (id_cert, id, 4);
- }
- }
-
- res = 1;
-
- done:
- close (fd);
-
- return res;
-}
-
-/* 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;
-
- if (!x509_decode_certificate (asn, asnlen, &cert))
- return 0;
-
- /* XXX - perhaps put into pkcs ? */
- mpz_init_set (key->n, cert.key.n);
- mpz_init_set (key->e, cert.key.e);
-
- x509_free_certificate (&cert);
-
- return 1;
-}
-
-/*
- * Retrieve the public key from a X509 Certificate
- * XXX - look at XXX below.
- */
-
-int
-x509_cert_get_subject (u_int8_t *asn, u_int32_t asnlen,
- u_int8_t **subject, u_int32_t *subjectlen)
-{
- struct x509_certificate cert;
-
- if (!x509_decode_certificate (asn, asnlen, &cert))
- return 0;
-
- if (cert.extension.type == NULL || cert.extension.val == NULL)
- goto fail;
-
- log_debug (LOG_CRYPTO, 60, "x509_cert_get_subject: Extension Type %s = %s",
- cert.extension.type,
- asn_parse_objectid (asn_ids, cert.extension.type));
-
- if (strcmp (ASN_ID_SUBJECT_ALT_NAME, cert.extension.type))
- {
- log_print ("x509_cert_get_subject: extension type != subjectAltName");
- goto fail;
- }
-
- /*
- * 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)
- {
- log_print ("x509_cert_get_subject: subjectAltName uses "
- "unhandled encoding");
- goto fail;
- }
-
- /* XXX - 4 bytes for IPV4 address */
- *subject = malloc (4);
- if (*subject == NULL)
- {
- log_print ("x509_cert_get_subject: out of memory");
- goto fail;
- }
- *subjectlen = 4;
- memcpy (*subject, cert.extension.val + 4, *subjectlen);
-
- x509_free_certificate (&cert);
-
- return 1;
-
- fail:
- x509_free_certificate (&cert);
- return 0;
-}
-
-/* Initalizes the struct x509_attribval from a AtributeValueAssertion */
-
-void
-x509_get_attribval (struct norm_type *obj, struct x509_attribval *a)
-{
- struct norm_type *tmp;
-
- tmp = asn_decompose ("AttributeValueAssertion.AttributeType", obj);
- if (tmp != NULL && tmp->data != NULL)
- a->type = strdup ((char *)tmp->data);
-
- tmp = asn_decompose ("AttributeValueAssertion.AttributeValue", obj);
- if (tmp != NULL && tmp->data != NULL)
- a->val = strdup ((char *)tmp->data);
-}
-
-/* Set's norm_type with values from x509_attribval */
-
-void
-x509_set_attribval (struct norm_type *obj, struct x509_attribval *a)
-{
- struct norm_type *tmp;
-
- 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);
-}
-
-void
-x509_free_attribval (struct x509_attribval *a)
-{
- if (a->type != NULL)
- free (a->type);
- if (a->val != NULL)
- free (a->val);
-}
-
-void
-x509_free_certificate (struct x509_certificate *cert)
-{
- pkcs_free_public_key (&cert->key);
- if (cert->signaturetype != NULL)
- free (cert->signaturetype);
- if (cert->start != NULL)
- free (cert->start);
- if (cert->end != NULL)
- 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);
-}
-
-int
-x509_decode_certificate (u_int8_t *asn, u_int32_t asnlen,
- struct x509_certificate *rcert)
-{
- struct norm_type cert = SEQ ("cert", Certificate);
- struct norm_type *tmp;
- u_int8_t *data;
- u_int32_t datalen;
-
- /* Get access to the inner Certificate */
- if (!x509_validate_signed (asn, asnlen, NULL, &data, &datalen))
- return 0;
-
- memset (rcert, 0, sizeof (*rcert));
-
- if (asn_template_clone (&cert, 1) == NULL ||
- asn_decode_sequence (data, datalen, &cert) == NULL)
- goto fail;
-
- tmp = asn_decompose ("cert.subjectPublicKeyInfo.subjectPublicKey", &cert);
- if (!pkcs_public_key_from_asn (&rcert->key, tmp->data + 1, tmp->len - 1))
- goto fail;
-
- tmp = asn_decompose ("cert.version", &cert);
- rcert->version = mpz_get_ui (tmp->data);
- tmp = asn_decompose ("cert.serialNumber", &cert);
- rcert->serialnumber = mpz_get_ui (tmp->data);
- tmp = asn_decompose ("cert.signature.algorithm", &cert);
- rcert->signaturetype = strdup ((char *)tmp->data);
-
- tmp = asn_decompose ("cert.issuer.RelativeDistinguishedName."
- "AttributeValueAssertion", &cert);
- x509_get_attribval (tmp, &rcert->issuer1);
- tmp = asn_decompose ("cert.issuer.RelativeDistinguishedName[1]."
- "AttributeValueAssertion", &cert);
- if (tmp != NULL)
- x509_get_attribval (tmp, &rcert->issuer2);
- else
- rcert->issuer2.type = NULL;
-
- tmp = asn_decompose ("cert.subject.RelativeDistinguishedName."
- "AttributeValueAssertion", &cert);
- x509_get_attribval (tmp, &rcert->subject1);
- tmp = asn_decompose ("cert.subject.RelativeDistinguishedName[1]."
- "AttributeValueAssertion", &cert);
- if (tmp != NULL)
- x509_get_attribval (tmp, &rcert->subject2);
- else
- rcert->subject2.type = NULL;
-
- tmp = asn_decompose ("cert.validity.notBefore", &cert);
- rcert->start = strdup ((char *)tmp->data);
- tmp = asn_decompose ("cert.validity.notAfter", &cert);
- rcert->end = strdup ((char *)tmp->data);
-
- /* 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;
-
- fail:
- x509_free_certificate (rcert);
- asn_free (&cert);
- return 0;
-}
-
-int
-x509_encode_certificate (struct x509_certificate *rcert,
- u_int8_t **asn, u_int32_t *asnlen)
-{
- struct norm_type cert = SEQ ("cert", Certificate);
- struct norm_type *tmp;
- u_int8_t *data, *new_buf;
- mpz_t num;
-
- if (asn_template_clone (&cert, 1) == NULL)
- goto fail;
-
- if (rcert->extension.type != NULL && rcert->extension.val != NULL)
- {
- u_int8_t *asn;
- u_int32_t asnlen;
-
- tmp = asn_decompose ("cert.extension", &cert);
- if (x509_encode_cert_extension (rcert, &asn, &asnlen))
- {
- tmp->data = asn;
- tmp->len = asnlen;
- }
- }
-
- 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);
-
- tmp = asn_decompose ("cert.subjectPublicKeyInfo.subjectPublicKey", &cert);
- data = pkcs_public_key_to_asn (&rcert->key);
- if (data == NULL)
- goto fail;
-
- /* This is a BIT STRING add 0 octet for padding */
- tmp->len = asn_get_len (data);
- new_buf = realloc (data, tmp->len + 1);
- if (new_buf == NULL)
- {
- free (data);
- goto fail;
- }
- 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))
- {
- mpz_clear (num);
- goto fail;
- }
-
- tmp = asn_decompose ("cert.serialNumber", &cert);
- mpz_set_ui (num, rcert->serialnumber);
- if (!pkcs_mpz_to_norm_type (tmp, num))
- {
- mpz_clear (num);
- goto fail;
- }
- 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, NULL);
- if (*asn == NULL)
- goto fail;
-
- *asnlen = asn_get_len (*asn);
-
- asn_free (&cert);
- return 1;
-
- fail:
- asn_free (&cert);
- return 0;
-}
-
-/*
- * Decode an Extension to a X509 certificate.
- * XXX - We ignore the critical boolean
- */
-
-int
-x509_decode_cert_extension (u_int8_t *asn, u_int32_t asnlen,
- struct x509_certificate *cert)
-{
- struct norm_type *tmp;
- struct norm_type ex = SEQOF ("ex", Extensions);
-
- /* Implicit tagging for extension */
- ex.class = ADD_EXP (3, UNIVERSAL);
-
- if (asn_template_clone (&ex, 1) == NULL ||
- asn_decode_sequence (asn, asnlen, &ex) == NULL)
- {
- asn_free (&ex);
- return 0;
- }
-
- tmp = asn_decompose ("ex.extension.extnValue", &ex);
- if (!tmp || tmp->data == NULL || 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);
-
- tmp = asn_decompose ("ex.extension.extnId", &ex);
- if (!tmp || tmp->data == NULL)
- goto fail;
- cert->extension.type = strdup (tmp->data);
- if (cert->extension.type == NULL)
- {
- free (cert->extension.val);
- cert->extension.val = NULL;
- goto fail;
- }
-
- asn_free (&ex);
- return 1;
-
- fail:
- asn_free (&ex);
- return 0;
-}
-
-/*
- * Encode a Cert Extension - XXX - only one extension per certificate
- * XXX - We tag everything as critical
- */
-
-int
-x509_encode_cert_extension (struct x509_certificate *cert,
- u_int8_t **asn, u_int32_t *asnlen)
-{
- struct norm_type ex = SEQ ("ex", Extensions);
- struct norm_type *tmp;
- ex.class = ADD_EXP (3, UNIVERSAL);
-
- if (asn_template_clone (&ex ,1) == NULL)
- goto fail;
-
- tmp = asn_decompose ("ex.extension.extnId", &ex);
- tmp->data = strdup (cert->extension.type);
- tmp->len = strlen (tmp->data);
-
- /* XXX - we mark every extension as critical */
- tmp = asn_decompose ("ex.extension.critical", &ex);
- if ((tmp->data = malloc (1)) == NULL)
- goto fail;
- *(u_int8_t *)tmp->data = 0xFF;
- tmp->len = 1;
-
- tmp = asn_decompose ("ex.extension.extnValue", &ex);
- if ((tmp->data = malloc (asn_get_len (cert->extension.val))) == NULL)
- goto fail;
- tmp->len = asn_get_len (cert->extension.val);
- memcpy (tmp->data, cert->extension.val, tmp->len);
-
- *asn = asn_encode_sequence (&ex, NULL);
- if (*asn == NULL)
- goto fail;
-
- *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.
- */
-
-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)
-{
- struct norm_type sig = SEQ("signed", Signed);
- struct norm_type digest = SEQ("digest", DigestInfo);
- struct norm_type *tmp;
- struct hash *hash = NULL;
- int res;
- u_int8_t *dec;
- u_int16_t declen;
-
- if (asn_template_clone (&sig, 1) == NULL)
- /* Failed, probably memory allocation, free what we got anyway */
- goto fail;
-
- if (asn_decode_sequence (asn, asnlen, &sig) == NULL)
- {
- log_print ("x509_validate_signed: input data could not be decoded");
- goto fail;
- }
-
- tmp = asn_decompose ("signed.algorithm.algorithm", &sig);
-
- if (!strcmp ((char *)tmp->data, ASN_ID_MD5WITHRSAENC))
- {
- hash = hash_get (HASH_MD5);
- }
- else
- {
- char *id = asn_parse_objectid (asn_ids, tmp->data);
- log_print ("x509_validate_signed: can not handle SigType %s",
- id == NULL ? tmp->data : id);
- goto fail;
- }
-
- if (hash == NULL)
- 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;
-
- /* Used to unwrap the SIGNED object around the Certificate */
- if (key == NULL)
- {
- asn_free (&sig);
- return 1;
- }
-
- tmp = asn_decompose ("signed.encrypted", &sig);
- /*
- * tmp->data is a BIT STRING, the first octet in the BIT STRING 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->n, key->e, tmp->data + 1,
- &dec, &declen))
- goto fail;
-
- if (asn_template_clone (&digest, 1) == NULL ||
- asn_decode_sequence (dec, declen, &digest) == NULL)
- {
- 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
- {
- 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;
- }
-
- asn_free (&digest);
- asn_free (&sig);
- return res;
-
- fail:
- asn_free (&sig);
- return 0;
-}
-
-/*
- * 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)
-{
- 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);
-
- if (asn_template_clone (&digest, 1) == NULL)
- goto fail;
-
- tmp = asn_decompose ("digest.digest", &digest);
- tmp->len = hash->hashsize;
- tmp->data = malloc (hash->hashsize);
- if (tmp->data == NULL)
- goto fail;
- 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);
-
- /* ASN encode Digest Information */
- if ((diginfo = asn_encode_sequence (&digest, NULL)) == NULL)
- goto fail;
-
- /* Encrypt the Digest Info with Private Key */
- res = pkcs_rsa_encrypt (PKCS_PRIVATE, key->n, key->d, diginfo,
- asn_get_len (diginfo), &enc, &enclen);
- free (diginfo);
- if (!res)
- goto fail;
- res = 0;
-
- if (asn_template_clone (&sig, 1) == NULL)
- 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 BITSTING, i.e. first octet need to be zero */
- tmp = asn_decompose ("signed.encrypted", &sig);
- tmp->data = malloc (enclen + 1);
- if (tmp->data == NULL)
- {
- 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, NULL);
- if (*asn == NULL)
- 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 = NULL;
- res = 1; /* Successfull */
- fail2:
- asn_free (&sig);
- fail:
- asn_free (&digest);
- return res;
-}