summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/botan/botan_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/botan/botan_util.c')
-rw-r--r--src/libstrongswan/plugins/botan/botan_util.c280
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;
+}