diff options
Diffstat (limited to 'src/libstrongswan/plugins/botan/botan_util.c')
-rw-r--r-- | src/libstrongswan/plugins/botan/botan_util.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/botan/botan_util.c b/src/libstrongswan/plugins/botan/botan_util.c new file mode 100644 index 000000000..5e18405d7 --- /dev/null +++ b/src/libstrongswan/plugins/botan/botan_util.c @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2018 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * Copyright (C) 2018 René Korthaus + * Rohde & Schwarz Cybersecurity GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "botan_util.h" + +#include <utils/debug.h> + +#include <botan/ffi.h> + +/* + * Described in header + */ +bool chunk_to_botan_mp(chunk_t value, botan_mp_t *mp) +{ + if (botan_mp_init(mp)) + { + return FALSE; + } + + if (botan_mp_from_bin(*mp, value.ptr, value.len)) + { + botan_mp_destroy(*mp); + return FALSE; + } + return TRUE; +} + +/* + * Described in header + */ +const char *botan_get_hash(hash_algorithm_t hash) +{ + switch (hash) + { + case HASH_MD5: + return "MD5"; + case HASH_SHA1: + return "SHA-1"; + case HASH_SHA224: + return "SHA-224"; + case HASH_SHA256: + return "SHA-256"; + case HASH_SHA384: + return "SHA-384"; + case HASH_SHA512: + return "SHA-512"; + default: + return NULL; + } +} + +/* + * Described in header + */ +bool botan_get_encoding(botan_pubkey_t pubkey, cred_encoding_type_t type, + chunk_t *encoding) +{ + bool success = TRUE; + + encoding->len = 0; + if (botan_pubkey_export(pubkey, NULL, &encoding->len, + BOTAN_PRIVKEY_EXPORT_FLAG_DER) + != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE) + { + return FALSE; + } + + *encoding = chunk_alloc(encoding->len); + if (botan_pubkey_export(pubkey, encoding->ptr, &encoding->len, + BOTAN_PRIVKEY_EXPORT_FLAG_DER)) + { + chunk_free(encoding); + return FALSE; + } + + if (type != PUBKEY_SPKI_ASN1_DER) + { + chunk_t asn1_encoding = *encoding; + + success = lib->encoding->encode(lib->encoding, type, NULL, encoding, + CRED_PART_ECDSA_PUB_ASN1_DER, + asn1_encoding, CRED_PART_END); + chunk_free(&asn1_encoding); + } + return success; +} + +/* + * Described in header + */ +bool botan_get_privkey_encoding(botan_privkey_t key, cred_encoding_type_t type, + chunk_t *encoding) +{ + uint32_t format = BOTAN_PRIVKEY_EXPORT_FLAG_DER; + + switch (type) + { + case PRIVKEY_PEM: + format = BOTAN_PRIVKEY_EXPORT_FLAG_PEM; + /* fall-through */ + case PRIVKEY_ASN1_DER: + encoding->len = 0; + if (botan_privkey_export(key, NULL, &encoding->len, format) + != BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE) + { + return FALSE; + } + *encoding = chunk_alloc(encoding->len); + if (botan_privkey_export(key, encoding->ptr, &encoding->len, + format)) + { + chunk_free(encoding); + return FALSE; + } + return TRUE; + default: + return FALSE; + } +} + +/* + * Described in header + */ +bool botan_get_fingerprint(botan_pubkey_t pubkey, void *cache, + cred_encoding_type_t type, chunk_t *fp) +{ + hasher_t *hasher; + chunk_t key; + + if (cache && + lib->encoding->get_cache(lib->encoding, type, cache, fp)) + { + return TRUE; + } + + switch (type) + { + case KEYID_PUBKEY_SHA1: + /* subjectPublicKey -> use botan_pubkey_fingerprint() */ + *fp = chunk_alloc(HASH_SIZE_SHA1); + if (botan_pubkey_fingerprint(pubkey, "SHA-1", fp->ptr, &fp->len)) + { + chunk_free(fp); + return FALSE; + } + break; + case KEYID_PUBKEY_INFO_SHA1: + /* subjectPublicKeyInfo -> use botan_pubkey_export(), then hash */ + if (!botan_get_encoding(pubkey, PUBKEY_SPKI_ASN1_DER, &key)) + { + return FALSE; + } + + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (!hasher || !hasher->allocate_hash(hasher, key, fp)) + { + DBG1(DBG_LIB, "SHA1 hash algorithm not supported, " + "fingerprinting failed"); + DESTROY_IF(hasher); + chunk_free(&key); + return FALSE; + } + hasher->destroy(hasher); + chunk_free(&key); + break; + default: + return FALSE; + } + + if (cache) + { + lib->encoding->cache(lib->encoding, type, cache, *fp); + } + return TRUE; +} + +/* + * Described in header + */ +bool botan_get_signature(botan_privkey_t key, const char *scheme, + chunk_t data, chunk_t *signature) +{ + botan_pk_op_sign_t sign_op; + botan_rng_t rng; + + if (!scheme || !signature) + { + return FALSE; + } + + if (botan_pk_op_sign_create(&sign_op, key, scheme, 0)) + { + return FALSE; + } + + if (botan_pk_op_sign_update(sign_op, data.ptr, data.len)) + { + botan_pk_op_sign_destroy(sign_op); + return FALSE; + } + + signature->len = 0; + if (botan_pk_op_sign_output_length(sign_op, &signature->len)) + { + botan_pk_op_sign_destroy(sign_op); + return FALSE; + } + + if (botan_rng_init(&rng, "user")) + { + botan_pk_op_sign_destroy(sign_op); + return FALSE; + } + + *signature = chunk_alloc(signature->len); + if (botan_pk_op_sign_finish(sign_op, rng, signature->ptr, &signature->len)) + { + chunk_free(signature); + botan_rng_destroy(rng); + botan_pk_op_sign_destroy(sign_op); + return FALSE; + } + + botan_rng_destroy(rng); + botan_pk_op_sign_destroy(sign_op); + return TRUE; +} + +/* + * Described in header + */ +bool botan_dh_key_derivation(botan_privkey_t key, chunk_t pub, chunk_t *secret) +{ + botan_pk_op_ka_t ka; + + if (botan_pk_op_key_agreement_create(&ka, key, "Raw", 0)) + { + return FALSE; + } + + if (botan_pk_op_key_agreement_size(ka, &secret->len)) + { + botan_pk_op_key_agreement_destroy(ka); + return FALSE; + } + + *secret = chunk_alloc(secret->len); + if (botan_pk_op_key_agreement(ka, secret->ptr, &secret->len, pub.ptr, + pub.len, NULL, 0)) + { + chunk_clear(secret); + botan_pk_op_key_agreement_destroy(ka); + return FALSE; + } + botan_pk_op_key_agreement_destroy(ka); + return TRUE; +} |