diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2010-02-23 10:42:46 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2010-02-23 10:42:46 +0000 |
commit | de6b12502cdf42d5d92118f1c0e38dc31becf7c5 (patch) | |
tree | 0edac9c79f5a43e01913dd7f71c7abc487e5727b /src/libstrongswan/plugins/dnskey/dnskey_builder.c | |
parent | 172642669d4a23e17f1ed411fbc8629dcaa5fb46 (diff) | |
download | vyos-strongswan-de6b12502cdf42d5d92118f1c0e38dc31becf7c5.tar.gz vyos-strongswan-de6b12502cdf42d5d92118f1c0e38dc31becf7c5.zip |
Updated to new upstream release. interfaces Patch is not from upstream.
Diffstat (limited to 'src/libstrongswan/plugins/dnskey/dnskey_builder.c')
-rw-r--r-- | src/libstrongswan/plugins/dnskey/dnskey_builder.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/dnskey/dnskey_builder.c b/src/libstrongswan/plugins/dnskey/dnskey_builder.c new file mode 100644 index 000000000..ba20e7158 --- /dev/null +++ b/src/libstrongswan/plugins/dnskey/dnskey_builder.c @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2009 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "dnskey_builder.h" + +#include <debug.h> +#include <credentials/keys/private_key.h> + + +typedef struct dnskey_rr_t dnskey_rr_t; +typedef enum dnskey_algorithm_t dnskey_algorithm_t; + +/** + * Header of a DNSKEY resource record + */ +struct dnskey_rr_t { + u_int16_t flags; + u_int8_t protocol; + u_int8_t algorithm; + u_int8_t data[]; +} __attribute__((__packed__)); + +/** + * DNSSEC algorithms, RFC4034 Appendix A.1. + */ +enum dnskey_algorithm_t { + DNSKEY_ALG_RSA_MD5 = 1, + DNSKEY_ALG_DH = 2, + DNSKEY_ALG_DSA = 3, + DNSKEY_ALG_ECC = 4, + DNSKEY_ALG_RSA_SHA1 = 5, +}; + +/** + * Load a generic public key from a DNSKEY RR blob + */ +static dnskey_public_key_t *parse_public_key(chunk_t blob) +{ + dnskey_rr_t *rr = (dnskey_rr_t*)blob.ptr; + + if (blob.len < sizeof(dnskey_rr_t)) + { + DBG1("DNSKEY too short"); + return NULL; + } + blob = chunk_skip(blob, sizeof(dnskey_rr_t)); + + switch (rr->algorithm) + { + case DNSKEY_ALG_RSA_SHA1: + return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, + BUILD_BLOB_DNSKEY, blob, BUILD_END); + default: + DBG1("DNSKEY public key algorithm %d not supported", rr->algorithm); + return NULL; + } +} + +/** + * Load a RSA public key from DNSKEY RR data + */ +static dnskey_public_key_t *parse_rsa_public_key(chunk_t blob) +{ + chunk_t n, e; + + if (blob.len < 3) + { + DBG1("RFC 3110 public key blob too short for exponent length"); + return NULL; + } + + if (blob.ptr[0]) + { + e.len = blob.ptr[0]; + blob = chunk_skip(blob, 1); + } + else + { + e.len = blob.ptr[1] * 256 + blob.ptr[2]; + blob = chunk_skip(blob, 3); + } + e.ptr = blob.ptr; + if (e.len >= blob.len) + { + DBG1("RFC 3110 public key blob too short for exponent"); + return NULL; + } + n = chunk_skip(blob, e.len); + + return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, + BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, + BUILD_END); +} + +/** + * See header. + */ +dnskey_public_key_t *dnskey_public_key_load(key_type_t type, va_list args) +{ + chunk_t blob = chunk_empty; + + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_BLOB_DNSKEY: + blob = va_arg(args, chunk_t); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + if (!blob.ptr) + { + return NULL; + } + switch (type) + { + case KEY_ANY: + return parse_public_key(blob); + case KEY_RSA: + return parse_rsa_public_key(blob); + default: + return NULL; + } +} + |