Merge branch 'botan-plugin'
Adds a wrapper plugin for the Botan crypto library. Closes strongswan/strongswan#109.
This commit is contained in:
commit
c46a94e0cc
|
@ -7,9 +7,7 @@ compiler:
|
|||
- gcc
|
||||
- clang
|
||||
|
||||
addons:
|
||||
sonarcloud:
|
||||
organization: "strongswan"
|
||||
cache: ccache
|
||||
|
||||
before_install:
|
||||
- travis_retry ./scripts/test.sh deps
|
||||
|
@ -38,6 +36,8 @@ env:
|
|||
- TEST=default
|
||||
- TEST=default MONOLITHIC=yes
|
||||
- TEST=default LEAK_DETECTIVE=yes
|
||||
- TEST=botan
|
||||
- TEST=botan LEAK_DETECTIVE=yes
|
||||
- TEST=openssl
|
||||
- TEST=openssl LEAK_DETECTIVE=yes
|
||||
- TEST=gcrypt
|
||||
|
@ -61,6 +61,9 @@ matrix:
|
|||
env: TEST=sonarcloud
|
||||
git:
|
||||
depth: false
|
||||
addons:
|
||||
sonarcloud:
|
||||
organization: "strongswan"
|
||||
- compiler: gcc
|
||||
env: TEST=win64 MONOLITHIC=yes
|
||||
# this does not work on 14.04 due to a missing @4 decoration for
|
||||
|
|
10
configure.ac
10
configure.ac
|
@ -126,6 +126,7 @@ ARG_DISBL_SET([aes], [disable AES software implementation plugin.])
|
|||
ARG_ENABL_SET([af-alg], [enable AF_ALG crypto interface to Linux Crypto API.])
|
||||
ARG_ENABL_SET([bliss], [enable BLISS software implementation plugin.])
|
||||
ARG_ENABL_SET([blowfish], [enable Blowfish software implementation plugin.])
|
||||
ARG_ENABL_SET([botan], [enables the Botan crypto plugin.])
|
||||
ARG_ENABL_SET([ccm], [enables the CCM AEAD wrapper crypto plugin.])
|
||||
ARG_ENABL_SET([chapoly], [enables the ChaCha20/Poly1305 AEAD plugin.])
|
||||
ARG_DISBL_SET([cmac], [disable CMAC crypto implementation plugin.])
|
||||
|
@ -1149,6 +1150,12 @@ if test x$gcrypt = xtrue; then
|
|||
)
|
||||
fi
|
||||
|
||||
if test x$botan = xtrue; then
|
||||
PKG_CHECK_MODULES(botan, [botan-2])
|
||||
AC_SUBST(botan_CFLAGS)
|
||||
AC_SUBST(botan_LIBS)
|
||||
fi
|
||||
|
||||
if test x$uci = xtrue; then
|
||||
AC_CHECK_LIB([uci],[uci_alloc_context],[LIBS="$LIBS"],[AC_MSG_ERROR([UCI library libuci not found])],[])
|
||||
AC_CHECK_HEADER([uci.h],,[AC_MSG_ERROR([UCI header uci.h not found!])])
|
||||
|
@ -1399,6 +1406,7 @@ ADD_PLUGIN([pem], [s charon scepclient pki scripts manager meds
|
|||
ADD_PLUGIN([padlock], [s charon])
|
||||
ADD_PLUGIN([openssl], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([gcrypt], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([botan], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([af-alg], [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([fips-prf], [s charon nm cmd])
|
||||
ADD_PLUGIN([gmp], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen fuzz])
|
||||
|
@ -1568,6 +1576,7 @@ AM_CONDITIONAL(USE_SQLITE, test x$sqlite = xtrue)
|
|||
AM_CONDITIONAL(USE_PADLOCK, test x$padlock = xtrue)
|
||||
AM_CONDITIONAL(USE_OPENSSL, test x$openssl = xtrue)
|
||||
AM_CONDITIONAL(USE_GCRYPT, test x$gcrypt = xtrue)
|
||||
AM_CONDITIONAL(USE_BOTAN, test x$botan = xtrue)
|
||||
AM_CONDITIONAL(USE_AGENT, test x$agent = xtrue)
|
||||
AM_CONDITIONAL(USE_KEYCHAIN, test x$keychain = xtrue)
|
||||
AM_CONDITIONAL(USE_PKCS11, test x$pkcs11 = xtrue)
|
||||
|
@ -1846,6 +1855,7 @@ AC_CONFIG_FILES([
|
|||
src/libstrongswan/plugins/padlock/Makefile
|
||||
src/libstrongswan/plugins/openssl/Makefile
|
||||
src/libstrongswan/plugins/gcrypt/Makefile
|
||||
src/libstrongswan/plugins/botan/Makefile
|
||||
src/libstrongswan/plugins/agent/Makefile
|
||||
src/libstrongswan/plugins/keychain/Makefile
|
||||
src/libstrongswan/plugins/pkcs11/Makefile
|
||||
|
|
|
@ -1,6 +1,33 @@
|
|||
#!/bin/sh
|
||||
# Build script for Travis CI
|
||||
|
||||
build_botan()
|
||||
{
|
||||
# same revision used in the build recipe of the testing environment
|
||||
BOTAN_REV=1872f899716854927ecc68022fac318735be8824
|
||||
BOTAN_DIR=$TRAVIS_BUILD_DIR/../botan
|
||||
|
||||
# if the leak detective is enabled we have to disable threading support
|
||||
# (used for std::async) as that causes invalid frees somehow, the
|
||||
# locking allocator causes a static leak via the first function that
|
||||
# references it (e.g. crypter or hasher), so we disable that too
|
||||
if test "$LEAK_DETECTIVE" = "yes"; then
|
||||
BOTAN_CONFIG="--without-os-features=threads
|
||||
--disable-modules=locking_allocator"
|
||||
fi
|
||||
# disable some larger modules we don't need for the tests
|
||||
BOTAN_CONFIG="$BOTAN_CONFIG --disable-modules=pkcs11,tls,x509,xmss"
|
||||
|
||||
git clone https://github.com/randombit/botan.git $BOTAN_DIR &&
|
||||
cd $BOTAN_DIR &&
|
||||
git checkout $BOTAN_REV &&
|
||||
python ./configure.py --amalgamation $BOTAN_CONFIG &&
|
||||
make -j4 libs >/dev/null &&
|
||||
sudo make install >/dev/null &&
|
||||
sudo ldconfig || exit $?
|
||||
cd -
|
||||
}
|
||||
|
||||
if test -z $TRAVIS_BUILD_DIR; then
|
||||
TRAVIS_BUILD_DIR=$PWD
|
||||
fi
|
||||
|
@ -26,6 +53,17 @@ gcrypt)
|
|||
CONFIG="--disable-defaults --enable-pki --enable-gcrypt --enable-pkcs1"
|
||||
DEPS="libgcrypt11-dev"
|
||||
;;
|
||||
botan)
|
||||
CONFIG="--disable-defaults --enable-pki --enable-botan"
|
||||
# we can't use the old package that comes with Ubuntu so we build from
|
||||
# the current master until 2.8.0 is released and then probably switch to
|
||||
# that unless we need newer features (at least 2.7.0 plus PKCS#1 patch is
|
||||
# currently required)
|
||||
DEPS=""
|
||||
if test "$1" = "deps"; then
|
||||
build_botan
|
||||
fi
|
||||
;;
|
||||
printf-builtin)
|
||||
CONFIG="--with-printf-hooks=builtin"
|
||||
;;
|
||||
|
@ -54,6 +92,9 @@ all|coverage|sonarcloud)
|
|||
libpcsclite-dev libpam0g-dev binutils-dev libunwind8-dev
|
||||
libjson0-dev iptables-dev python-pip libtspi-dev"
|
||||
PYDEPS="pytest"
|
||||
if test "$1" = "deps"; then
|
||||
build_botan
|
||||
fi
|
||||
;;
|
||||
win*)
|
||||
CONFIG="--disable-defaults --enable-svc --enable-ikev2
|
||||
|
|
|
@ -362,8 +362,6 @@ static bool build_payloads(private_ike_init_t *this, message_t *message)
|
|||
}
|
||||
message->add_payload(message, (payload_t*)sa_payload);
|
||||
|
||||
nonce_payload = nonce_payload_create(PLV2_NONCE);
|
||||
nonce_payload->set_nonce(nonce_payload, this->my_nonce);
|
||||
ke_payload = ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE,
|
||||
this->dh);
|
||||
if (!ke_payload)
|
||||
|
@ -371,6 +369,8 @@ static bool build_payloads(private_ike_init_t *this, message_t *message)
|
|||
DBG1(DBG_IKE, "creating KE payload failed");
|
||||
return FALSE;
|
||||
}
|
||||
nonce_payload = nonce_payload_create(PLV2_NONCE);
|
||||
nonce_payload->set_nonce(nonce_payload, this->my_nonce);
|
||||
|
||||
if (this->old_sa)
|
||||
{ /* payload order differs if we are rekeying */
|
||||
|
|
|
@ -565,6 +565,13 @@ if MONOLITHIC
|
|||
endif
|
||||
endif
|
||||
|
||||
if USE_BOTAN
|
||||
SUBDIRS += plugins/botan
|
||||
if MONOLITHIC
|
||||
libstrongswan_la_LIBADD += plugins/botan/libstrongswan-botan.la
|
||||
endif
|
||||
endif
|
||||
|
||||
if USE_FIPS_PRF
|
||||
SUBDIRS += plugins/fips_prf
|
||||
if MONOLITHIC
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src/libstrongswan
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(PLUGIN_CFLAGS) \
|
||||
$(botan_CFLAGS)
|
||||
|
||||
if MONOLITHIC
|
||||
noinst_LTLIBRARIES = libstrongswan-botan.la
|
||||
else
|
||||
plugin_LTLIBRARIES = libstrongswan-botan.la
|
||||
endif
|
||||
|
||||
libstrongswan_botan_la_SOURCES = \
|
||||
botan_plugin.h botan_plugin.c \
|
||||
botan_rng.h botan_rng.c \
|
||||
botan_hasher.h botan_hasher.c \
|
||||
botan_hmac.h botan_hmac.c \
|
||||
botan_crypter.h botan_crypter.c \
|
||||
botan_rsa_public_key.h botan_rsa_public_key.c \
|
||||
botan_rsa_private_key.h botan_rsa_private_key.c \
|
||||
botan_diffie_hellman.h botan_diffie_hellman.c \
|
||||
botan_ec_diffie_hellman.h botan_ec_diffie_hellman.c \
|
||||
botan_ec_public_key.h botan_ec_public_key.c \
|
||||
botan_ec_private_key.h botan_ec_private_key.c \
|
||||
botan_util.h botan_util.c \
|
||||
botan_util_keys.h botan_util_keys.c \
|
||||
botan_gcm.h botan_gcm.c \
|
||||
botan_x25519.h botan_x25519.c
|
||||
|
||||
libstrongswan_botan_la_LDFLAGS = -module -avoid-version
|
||||
libstrongswan_botan_la_LIBADD = $(botan_LIBS)
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright (C) 2018 René Korthaus
|
||||
* Copyright (C) 2018 Konstantinos Kolelis
|
||||
* Copyright (C) 2018 Tobias Hommel
|
||||
* 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_crypter.h"
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
typedef struct private_botan_crypter_t private_botan_crypter_t;
|
||||
|
||||
/**
|
||||
* Private data of botan_crypter_t
|
||||
*/
|
||||
struct private_botan_crypter_t {
|
||||
|
||||
/**
|
||||
* Public part of this class
|
||||
*/
|
||||
botan_crypter_t public;
|
||||
|
||||
/**
|
||||
* The key
|
||||
*/
|
||||
chunk_t key;
|
||||
|
||||
/**
|
||||
* The cipher name
|
||||
*/
|
||||
const char* cipher_name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Do the actual en/decryption
|
||||
*/
|
||||
static bool crypt(private_botan_crypter_t *this, chunk_t data, chunk_t iv,
|
||||
chunk_t *dst, uint32_t init_flag)
|
||||
{
|
||||
botan_cipher_t cipher;
|
||||
size_t output_written = 0;
|
||||
size_t input_consumed = 0;
|
||||
uint8_t *in, *out;
|
||||
bool success = FALSE;
|
||||
|
||||
in = data.ptr;
|
||||
if (dst)
|
||||
{
|
||||
*dst = chunk_alloc(data.len);
|
||||
out = dst->ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
out = data.ptr;
|
||||
}
|
||||
|
||||
if (botan_cipher_init(&cipher, this->cipher_name, init_flag))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!botan_cipher_set_key(cipher, this->key.ptr, this->key.len) &&
|
||||
!botan_cipher_start(cipher, iv.ptr, iv.len) &&
|
||||
!botan_cipher_update(cipher, BOTAN_CIPHER_UPDATE_FLAG_FINAL, out,
|
||||
data.len, &output_written, in, data.len,
|
||||
&input_consumed) &&
|
||||
(output_written == input_consumed))
|
||||
{
|
||||
success = TRUE;
|
||||
}
|
||||
|
||||
botan_cipher_destroy(cipher);
|
||||
return success;
|
||||
}
|
||||
|
||||
METHOD(crypter_t, decrypt, bool,
|
||||
private_botan_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
|
||||
{
|
||||
return crypt(this, data, iv, dst, BOTAN_CIPHER_INIT_FLAG_DECRYPT);
|
||||
}
|
||||
|
||||
|
||||
METHOD(crypter_t, encrypt, bool,
|
||||
private_botan_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
|
||||
{
|
||||
return crypt(this, data, iv, dst, BOTAN_CIPHER_INIT_FLAG_ENCRYPT);
|
||||
}
|
||||
|
||||
METHOD(crypter_t, get_block_size, size_t,
|
||||
private_botan_crypter_t *this)
|
||||
{
|
||||
return AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
METHOD(crypter_t, get_iv_size, size_t,
|
||||
private_botan_crypter_t *this)
|
||||
{
|
||||
return AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
METHOD(crypter_t, get_key_size, size_t,
|
||||
private_botan_crypter_t *this)
|
||||
{
|
||||
return this->key.len;
|
||||
}
|
||||
|
||||
METHOD(crypter_t, set_key, bool,
|
||||
private_botan_crypter_t *this, chunk_t key)
|
||||
{
|
||||
memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(crypter_t, destroy, void,
|
||||
private_botan_crypter_t *this)
|
||||
{
|
||||
chunk_clear(&this->key);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
botan_crypter_t *botan_crypter_create(encryption_algorithm_t algo,
|
||||
size_t key_size)
|
||||
{
|
||||
private_botan_crypter_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.crypter = {
|
||||
.encrypt = _encrypt,
|
||||
.decrypt = _decrypt,
|
||||
.get_block_size = _get_block_size,
|
||||
.get_iv_size = _get_iv_size,
|
||||
.get_key_size = _get_key_size,
|
||||
.set_key = _set_key,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
switch (algo)
|
||||
{
|
||||
case ENCR_AES_CBC:
|
||||
switch (key_size)
|
||||
{
|
||||
case 16:
|
||||
/* AES 128 */
|
||||
this->cipher_name = "AES-128/CBC/NoPadding";
|
||||
break;
|
||||
case 24:
|
||||
/* AES-192 */
|
||||
this->cipher_name = "AES-192/CBC/NoPadding";
|
||||
break;
|
||||
case 32:
|
||||
/* AES-256 */
|
||||
this->cipher_name = "AES-256/CBC/NoPadding";
|
||||
break;
|
||||
default:
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
this->key = chunk_alloc(key_size);
|
||||
return &this->public;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2018 René Korthaus
|
||||
* Copyright (C) 2018 Konstantinos Kolelis
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup botan_crypter botan_crypter
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_CRYPTER_H_
|
||||
#define BOTAN_CRYPTER_H_
|
||||
|
||||
typedef struct botan_crypter_t botan_crypter_t;
|
||||
|
||||
#include <crypto/crypters/crypter.h>
|
||||
|
||||
/**
|
||||
* Implementation of crypters using Botan.
|
||||
*/
|
||||
struct botan_crypter_t {
|
||||
|
||||
/**
|
||||
* Implements crypter_t interface.
|
||||
*/
|
||||
crypter_t crypter;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor to create botan_crypter_t.
|
||||
*
|
||||
* @param algo algorithm to implement
|
||||
* @param key_size key size in bytes
|
||||
* @return botan_crypter_t, NULL if not supported
|
||||
*/
|
||||
botan_crypter_t *botan_crypter_create(encryption_algorithm_t algo,
|
||||
size_t key_size);
|
||||
|
||||
#endif /** BOTAN_CRYPTER_H_ @}*/
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* Copyright (C) 2018 René Korthaus
|
||||
* Copyright (C) 2018 Konstantinos Kolelis
|
||||
* 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_diffie_hellman.h"
|
||||
|
||||
#include <botan/build.h>
|
||||
|
||||
#ifdef BOTAN_HAS_DIFFIE_HELLMAN
|
||||
|
||||
#include "botan_util.h"
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_botan_diffie_hellman_t private_botan_diffie_hellman_t;
|
||||
|
||||
/**
|
||||
* Private data of an botan_diffie_hellman_t object.
|
||||
*/
|
||||
struct private_botan_diffie_hellman_t {
|
||||
|
||||
/**
|
||||
* Public botan_diffie_hellman_t interface
|
||||
*/
|
||||
botan_diffie_hellman_t public;
|
||||
|
||||
/**
|
||||
* Diffie Hellman group number
|
||||
*/
|
||||
diffie_hellman_group_t group;
|
||||
|
||||
/**
|
||||
* Private key
|
||||
*/
|
||||
botan_privkey_t dh_key;
|
||||
|
||||
/**
|
||||
* Diffie hellman shared secret
|
||||
*/
|
||||
chunk_t shared_secret;
|
||||
|
||||
/**
|
||||
* Generator value
|
||||
*/
|
||||
botan_mp_t g;
|
||||
|
||||
/**
|
||||
* Modulus
|
||||
*/
|
||||
botan_mp_t p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a DH private key
|
||||
*/
|
||||
bool load_private_key(private_botan_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
botan_mp_t xa;
|
||||
|
||||
if (!chunk_to_botan_mp(value, &xa))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_privkey_destroy(this->dh_key) ||
|
||||
botan_privkey_load_dh(&this->dh_key, this->p, this->g, xa))
|
||||
{
|
||||
botan_mp_destroy(xa);
|
||||
return FALSE;
|
||||
}
|
||||
botan_mp_destroy(xa);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, set_other_public_value, bool,
|
||||
private_botan_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
if (!diffie_hellman_verify_value(this->group, value))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
chunk_clear(&this->shared_secret);
|
||||
|
||||
return botan_dh_key_derivation(this->dh_key, value, &this->shared_secret);
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
private_botan_diffie_hellman_t *this, chunk_t *value)
|
||||
{
|
||||
*value = chunk_empty;
|
||||
|
||||
/* get key size of public key first */
|
||||
if (botan_pk_op_key_agreement_export_public(this->dh_key, NULL, &value->len)
|
||||
!= BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*value = chunk_alloc(value->len);
|
||||
if (botan_pk_op_key_agreement_export_public(this->dh_key, value->ptr,
|
||||
&value->len))
|
||||
{
|
||||
chunk_clear(value);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, set_private_value, bool,
|
||||
private_botan_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
chunk_clear(&this->shared_secret);
|
||||
return load_private_key(this, value);
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
private_botan_diffie_hellman_t *this, chunk_t *secret)
|
||||
{
|
||||
if (!this->shared_secret.len)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
*secret = chunk_clone(this->shared_secret);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
|
||||
private_botan_diffie_hellman_t *this)
|
||||
{
|
||||
return this->group;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, destroy, void,
|
||||
private_botan_diffie_hellman_t *this)
|
||||
{
|
||||
botan_mp_destroy(this->p);
|
||||
botan_mp_destroy(this->g);
|
||||
botan_privkey_destroy(this->dh_key);
|
||||
chunk_clear(&this->shared_secret);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic internal constructor
|
||||
*/
|
||||
static botan_diffie_hellman_t *create_generic(diffie_hellman_group_t group,
|
||||
chunk_t g, chunk_t p, size_t exp_len)
|
||||
{
|
||||
private_botan_diffie_hellman_t *this;
|
||||
chunk_t random;
|
||||
rng_t *rng;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.dh = {
|
||||
.get_shared_secret = _get_shared_secret,
|
||||
.set_other_public_value = _set_other_public_value,
|
||||
.get_my_public_value = _get_my_public_value,
|
||||
.set_private_value = _set_private_value,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.group = group,
|
||||
);
|
||||
|
||||
if (!chunk_to_botan_mp(p, &this->p))
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!chunk_to_botan_mp(g, &this->g))
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
|
||||
if (!rng || !rng->allocate_bytes(rng, exp_len, &random))
|
||||
{
|
||||
DESTROY_IF(rng);
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
rng->destroy(rng);
|
||||
|
||||
if (!load_private_key(this, random))
|
||||
{
|
||||
chunk_clear(&random);
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
chunk_clear(&random);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
botan_diffie_hellman_t *botan_diffie_hellman_create(
|
||||
diffie_hellman_group_t group, ...)
|
||||
{
|
||||
diffie_hellman_params_t *params;
|
||||
chunk_t g, p;
|
||||
|
||||
if (group == MODP_CUSTOM)
|
||||
{
|
||||
VA_ARGS_GET(group, g, p);
|
||||
return create_generic(group, g, p, p.len);
|
||||
}
|
||||
|
||||
params = diffie_hellman_get_params(group);
|
||||
if (!params)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return create_generic(group, params->generator, params->prime,
|
||||
params->exp_len);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (C) 2018 René Korthaus
|
||||
* Copyright (C) 2018 Konstantinos Kolelis
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup botan_diffie_hellman botan_diffie_hellman
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_DIFFIE_HELLMAN_H_
|
||||
#define BOTAN_DIFFIE_HELLMAN_H_
|
||||
|
||||
typedef struct botan_diffie_hellman_t botan_diffie_hellman_t;
|
||||
|
||||
#include <crypto/diffie_hellman.h>
|
||||
|
||||
/**
|
||||
* Implementation of the Diffie-Hellman algorithm using Botan.
|
||||
*/
|
||||
struct botan_diffie_hellman_t {
|
||||
|
||||
/**
|
||||
* Implements diffie_hellman_t interface.
|
||||
*/
|
||||
diffie_hellman_t dh;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new botan_diffie_hellman_t object.
|
||||
*
|
||||
* @param group Diffie Hellman group number to use
|
||||
* @param ... expects generator and prime as chunk_t if MODP_CUSTOM
|
||||
* @return botan_diffie_hellman_t object,
|
||||
* NULL if not supported
|
||||
*/
|
||||
botan_diffie_hellman_t *botan_diffie_hellman_create(
|
||||
diffie_hellman_group_t group, ...);
|
||||
|
||||
#endif /** BOTAN_DIFFIE_HELLMAN_H_ @}*/
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* 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_ec_diffie_hellman.h"
|
||||
|
||||
#include <botan/build.h>
|
||||
|
||||
#ifdef BOTAN_HAS_ECDH
|
||||
|
||||
#include "botan_util.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
typedef struct private_botan_ec_diffie_hellman_t private_botan_ec_diffie_hellman_t;
|
||||
|
||||
/**
|
||||
* Private data of a botan_ec_diffie_hellman_t object.
|
||||
*/
|
||||
struct private_botan_ec_diffie_hellman_t {
|
||||
|
||||
/**
|
||||
* Public interface
|
||||
*/
|
||||
botan_ec_diffie_hellman_t public;
|
||||
|
||||
/**
|
||||
* Diffie Hellman group
|
||||
*/
|
||||
diffie_hellman_group_t group;
|
||||
|
||||
/**
|
||||
* EC curve name
|
||||
*/
|
||||
const char* curve_name;
|
||||
|
||||
/**
|
||||
* EC private key
|
||||
*/
|
||||
botan_privkey_t key;
|
||||
|
||||
/**
|
||||
* Shared secret
|
||||
*/
|
||||
chunk_t shared_secret;
|
||||
};
|
||||
|
||||
METHOD(diffie_hellman_t, set_other_public_value, bool,
|
||||
private_botan_ec_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
if (!diffie_hellman_verify_value(this->group, value))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
chunk_clear(&this->shared_secret);
|
||||
|
||||
/* prepend 0x04 to indicate uncompressed point format */
|
||||
value = chunk_cata("cc", chunk_from_chars(0x04), value);
|
||||
|
||||
return botan_dh_key_derivation(this->key, value, &this->shared_secret);
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
private_botan_ec_diffie_hellman_t *this, chunk_t *value)
|
||||
{
|
||||
chunk_t pkey = chunk_empty;
|
||||
|
||||
if (botan_pk_op_key_agreement_export_public(this->key, NULL, &pkey.len)
|
||||
!= BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pkey = chunk_alloca(pkey.len);
|
||||
if (botan_pk_op_key_agreement_export_public(this->key, pkey.ptr, &pkey.len))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* skip 0x04 byte prepended by botan */
|
||||
*value = chunk_clone(chunk_skip(pkey, 1));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, set_private_value, bool,
|
||||
private_botan_ec_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
botan_mp_t scalar;
|
||||
|
||||
chunk_clear(&this->shared_secret);
|
||||
|
||||
if (!chunk_to_botan_mp(value, &scalar))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_privkey_destroy(this->key))
|
||||
{
|
||||
botan_mp_destroy(scalar);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_privkey_load_ecdh(&this->key, scalar, this->curve_name))
|
||||
{
|
||||
botan_mp_destroy(scalar);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
botan_mp_destroy(scalar);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
private_botan_ec_diffie_hellman_t *this, chunk_t *secret)
|
||||
{
|
||||
if (!this->shared_secret.len)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
*secret = chunk_clone(this->shared_secret);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
|
||||
private_botan_ec_diffie_hellman_t *this)
|
||||
{
|
||||
return this->group;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, destroy, void,
|
||||
private_botan_ec_diffie_hellman_t *this)
|
||||
{
|
||||
botan_privkey_destroy(this->key);
|
||||
chunk_clear(&this->shared_secret);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
botan_ec_diffie_hellman_t *botan_ec_diffie_hellman_create(
|
||||
diffie_hellman_group_t group)
|
||||
{
|
||||
private_botan_ec_diffie_hellman_t *this;
|
||||
botan_rng_t rng;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.dh = {
|
||||
.get_shared_secret = _get_shared_secret,
|
||||
.set_other_public_value = _set_other_public_value,
|
||||
.get_my_public_value = _get_my_public_value,
|
||||
.set_private_value = _set_private_value,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.group = group,
|
||||
);
|
||||
|
||||
switch (group)
|
||||
{
|
||||
case ECP_256_BIT:
|
||||
this->curve_name = "secp256r1";
|
||||
break;
|
||||
case ECP_384_BIT:
|
||||
this->curve_name = "secp384r1";
|
||||
break;
|
||||
case ECP_521_BIT:
|
||||
this->curve_name = "secp521r1";
|
||||
break;
|
||||
case ECP_256_BP:
|
||||
this->curve_name = "brainpool256r1";
|
||||
break;
|
||||
case ECP_384_BP:
|
||||
this->curve_name = "brainpool384r1";
|
||||
break;
|
||||
case ECP_512_BP:
|
||||
this->curve_name = "brainpool512r1";
|
||||
break;
|
||||
default:
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (botan_rng_init(&rng, "user"))
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (botan_privkey_create_ecdh(&this->key, rng, this->curve_name))
|
||||
{
|
||||
DBG1(DBG_LIB, "ECDH private key generation failed");
|
||||
botan_rng_destroy(rng);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
botan_rng_destroy(rng);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup botan_ec_diffie_hellman botan_ec_diffie_hellman
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_EC_DIFFIE_HELLMAN_H_
|
||||
#define BOTAN_EC_DIFFIE_HELLMAN_H_
|
||||
|
||||
typedef struct botan_ec_diffie_hellman_t botan_ec_diffie_hellman_t;
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* Implementation of the EC Diffie-Hellman algorithm using Botan.
|
||||
*/
|
||||
struct botan_ec_diffie_hellman_t {
|
||||
|
||||
/**
|
||||
* Implements diffie_hellman_t interface.
|
||||
*/
|
||||
diffie_hellman_t dh;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new botan_ec_diffie_hellman_t object.
|
||||
*
|
||||
* @param group EC Diffie Hellman group number to use
|
||||
* @return botan_ec_diffie_hellman_t object, NULL if not supported
|
||||
*/
|
||||
botan_ec_diffie_hellman_t *botan_ec_diffie_hellman_create(
|
||||
diffie_hellman_group_t group);
|
||||
|
||||
#endif /** BOTAN_EC_DIFFIE_HELLMAN_H_ @}*/
|
|
@ -0,0 +1,452 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Tobias Brunner
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* Copyright (C) 2018 René Korthaus
|
||||
* Copyright (C) 2018 Konstantinos Kolelis
|
||||
* 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_ec_private_key.h"
|
||||
#include "botan_ec_public_key.h"
|
||||
#include "botan_util.h"
|
||||
|
||||
#include <botan/build.h>
|
||||
|
||||
#ifdef BOTAN_HAS_ECDSA
|
||||
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/oid.h>
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
typedef struct private_botan_ec_private_key_t private_botan_ec_private_key_t;
|
||||
|
||||
/**
|
||||
* Private data of a botan_ec_private_key_t object.
|
||||
*/
|
||||
struct private_botan_ec_private_key_t {
|
||||
|
||||
/**
|
||||
* Public interface
|
||||
*/
|
||||
botan_ec_private_key_t public;
|
||||
|
||||
/**
|
||||
* Botan ec private key
|
||||
*/
|
||||
botan_privkey_t key;
|
||||
|
||||
/**
|
||||
* OID of the curve
|
||||
*/
|
||||
int oid;
|
||||
|
||||
/**
|
||||
* Reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
#define SIG_FORMAT_IEEE_1363 0
|
||||
#define SIG_FORMAT_DER_SEQUENCE 1
|
||||
|
||||
/**
|
||||
* Build a DER encoded signature as in RFC 3279 or as in RFC 4754
|
||||
*/
|
||||
static bool build_signature(botan_privkey_t key, const char *hash_and_padding,
|
||||
int signature_format, chunk_t data,
|
||||
chunk_t *signature)
|
||||
{
|
||||
if (!botan_get_signature(key, hash_and_padding, data, signature))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (signature_format == SIG_FORMAT_DER_SEQUENCE)
|
||||
{
|
||||
/* format as ASN.1 sequence of two integers r,s */
|
||||
chunk_t r = chunk_empty, s = chunk_empty;
|
||||
|
||||
chunk_split(*signature, "aa", signature->len / 2, &r,
|
||||
signature->len / 2, &s);
|
||||
|
||||
chunk_free(signature);
|
||||
*signature = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_integer("m", r),
|
||||
asn1_integer("m", s));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(private_key_t, sign, bool,
|
||||
private_botan_ec_private_key_t *this, signature_scheme_t scheme,
|
||||
void *params, chunk_t data, chunk_t *signature)
|
||||
{
|
||||
switch (scheme)
|
||||
{
|
||||
/* r||s -> Botan::IEEE_1363, data is the hash already */
|
||||
case SIGN_ECDSA_WITH_NULL:
|
||||
return build_signature(this->key, "Raw",
|
||||
SIG_FORMAT_IEEE_1363, data, signature);
|
||||
/* DER SEQUENCE of two INTEGERS r,s -> Botan::DER_SEQUENCE */
|
||||
case SIGN_ECDSA_WITH_SHA1_DER:
|
||||
return build_signature(this->key, "EMSA1(SHA-1)",
|
||||
SIG_FORMAT_DER_SEQUENCE, data, signature);
|
||||
case SIGN_ECDSA_WITH_SHA256_DER:
|
||||
return build_signature(this->key, "EMSA1(SHA-256)",
|
||||
SIG_FORMAT_DER_SEQUENCE, data, signature);
|
||||
case SIGN_ECDSA_WITH_SHA384_DER:
|
||||
return build_signature(this->key, "EMSA1(SHA-384)",
|
||||
SIG_FORMAT_DER_SEQUENCE, data, signature);
|
||||
case SIGN_ECDSA_WITH_SHA512_DER:
|
||||
return build_signature(this->key, "EMSA1(SHA-512)",
|
||||
SIG_FORMAT_DER_SEQUENCE, data, signature);
|
||||
/* r||s -> Botan::IEEE_1363 */
|
||||
case SIGN_ECDSA_256:
|
||||
return build_signature(this->key, "EMSA1(SHA-256)",
|
||||
SIG_FORMAT_IEEE_1363, data, signature);
|
||||
case SIGN_ECDSA_384:
|
||||
return build_signature(this->key, "EMSA1(SHA-384)",
|
||||
SIG_FORMAT_IEEE_1363, data, signature);
|
||||
case SIGN_ECDSA_521:
|
||||
return build_signature(this->key, "EMSA1(SHA-512)",
|
||||
SIG_FORMAT_IEEE_1363, data, signature);
|
||||
default:
|
||||
DBG1(DBG_LIB, "signature scheme %N not supported via botan",
|
||||
signature_scheme_names, scheme);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(private_key_t, decrypt, bool,
|
||||
private_botan_ec_private_key_t *this, encryption_scheme_t scheme,
|
||||
chunk_t crypto, chunk_t *plain)
|
||||
{
|
||||
DBG1(DBG_LIB, "EC private key decryption not implemented");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(private_key_t, get_keysize, int,
|
||||
private_botan_ec_private_key_t *this)
|
||||
{
|
||||
botan_mp_t p;
|
||||
size_t bits = 0;
|
||||
|
||||
if (botan_mp_init(&p))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (botan_privkey_get_field(p, this->key, "p") ||
|
||||
botan_mp_num_bits(p, &bits))
|
||||
{
|
||||
botan_mp_destroy(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
botan_mp_destroy(p);
|
||||
return bits;
|
||||
}
|
||||
|
||||
METHOD(private_key_t, get_type, key_type_t,
|
||||
private_botan_ec_private_key_t *this)
|
||||
{
|
||||
return KEY_ECDSA;
|
||||
}
|
||||
|
||||
METHOD(private_key_t, get_public_key, public_key_t*,
|
||||
private_botan_ec_private_key_t *this)
|
||||
{
|
||||
botan_pubkey_t pubkey;
|
||||
|
||||
if (botan_privkey_export_pubkey(&pubkey, this->key))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return (public_key_t*)botan_ec_public_key_adopt(pubkey);
|
||||
}
|
||||
|
||||
METHOD(private_key_t, get_fingerprint, bool,
|
||||
private_botan_ec_private_key_t *this, cred_encoding_type_t type,
|
||||
chunk_t *fingerprint)
|
||||
{
|
||||
botan_pubkey_t pubkey;
|
||||
bool success = FALSE;
|
||||
|
||||
/* check the cache before doing the export */
|
||||
if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (botan_privkey_export_pubkey(&pubkey, this->key))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
success = botan_get_fingerprint(pubkey, this, type, fingerprint);
|
||||
botan_pubkey_destroy(pubkey);
|
||||
return success;
|
||||
}
|
||||
|
||||
METHOD(private_key_t, get_encoding, bool,
|
||||
private_botan_ec_private_key_t *this, cred_encoding_type_t type,
|
||||
chunk_t *encoding)
|
||||
{
|
||||
return botan_get_privkey_encoding(this->key, type, encoding);
|
||||
}
|
||||
|
||||
METHOD(private_key_t, get_ref, private_key_t*,
|
||||
private_botan_ec_private_key_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public.key;
|
||||
}
|
||||
|
||||
METHOD(private_key_t, destroy, void,
|
||||
private_botan_ec_private_key_t *this)
|
||||
{
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
lib->encoding->clear_cache(lib->encoding, this);
|
||||
botan_privkey_destroy(this->key);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal generic constructor
|
||||
*/
|
||||
static private_botan_ec_private_key_t *create_empty(int oid)
|
||||
{
|
||||
private_botan_ec_private_key_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.key = {
|
||||
.get_type = _get_type,
|
||||
.sign = _sign,
|
||||
.decrypt = _decrypt,
|
||||
.get_keysize = _get_keysize,
|
||||
.get_public_key = _get_public_key,
|
||||
.equals = private_key_equals,
|
||||
.belongs_to = private_key_belongs_to,
|
||||
.get_fingerprint = _get_fingerprint,
|
||||
.has_fingerprint = private_key_has_fingerprint,
|
||||
.get_encoding = _get_encoding,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.oid = oid,
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
botan_ec_private_key_t *botan_ec_private_key_adopt(botan_privkey_t key, int oid)
|
||||
{
|
||||
private_botan_ec_private_key_t *this;
|
||||
|
||||
this = create_empty(oid);
|
||||
this->key = key;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
botan_ec_private_key_t *botan_ec_private_key_gen(key_type_t type, va_list args)
|
||||
{
|
||||
private_botan_ec_private_key_t *this;
|
||||
botan_rng_t rng;
|
||||
u_int key_size = 0;
|
||||
int oid;
|
||||
const char *curve;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (va_arg(args, builder_part_t))
|
||||
{
|
||||
case BUILD_KEY_SIZE:
|
||||
key_size = va_arg(args, u_int);
|
||||
continue;
|
||||
case BUILD_END:
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!key_size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (key_size)
|
||||
{
|
||||
case 256:
|
||||
curve = "secp256r1";
|
||||
oid = OID_PRIME256V1;
|
||||
break;
|
||||
case 384:
|
||||
curve = "secp384r1";
|
||||
oid = OID_SECT384R1;
|
||||
break;
|
||||
case 521:
|
||||
curve = "secp521r1";
|
||||
oid = OID_SECT521R1;
|
||||
break;
|
||||
default:
|
||||
DBG1(DBG_LIB, "EC private key size %d not supported via botan",
|
||||
key_size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (botan_rng_init(&rng, "system"))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
this = create_empty(oid);
|
||||
|
||||
if (botan_privkey_create_ecdsa(&this->key, rng, curve))
|
||||
{
|
||||
DBG1(DBG_LIB, "EC private key generation failed");
|
||||
botan_rng_destroy(rng);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
botan_rng_destroy(rng);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
botan_ec_private_key_t *botan_ec_private_key_load(key_type_t type, va_list args)
|
||||
{
|
||||
private_botan_ec_private_key_t *this;
|
||||
chunk_t params = chunk_empty, key = chunk_empty;
|
||||
chunk_t alg_id = chunk_empty, pkcs8 = chunk_empty;
|
||||
botan_rng_t rng;
|
||||
int oid = OID_UNKNOWN;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (va_arg(args, builder_part_t))
|
||||
{
|
||||
case BUILD_BLOB_ALGID_PARAMS:
|
||||
params = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_BLOB_ASN1_DER:
|
||||
key = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_END:
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Botan expects a PKCS#8 private key, so we build one, if necessary.
|
||||
* RFC 5480 mandates ECParameters as part of the algorithmIdentifier, which
|
||||
* we should get from e.g. the pkcs8 plugin.
|
||||
*/
|
||||
if (params.len != 0 && type == KEY_ECDSA)
|
||||
{
|
||||
/* if ECParameters is passed, just use it */
|
||||
alg_id = asn1_algorithmIdentifier_params(OID_EC_PUBLICKEY,
|
||||
chunk_clone(params));
|
||||
if (asn1_unwrap(¶ms, ¶ms) == ASN1_OID)
|
||||
{
|
||||
oid = asn1_known_oid(params);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* no explicit ECParameters passed, try to extract them from the
|
||||
* ECPrivateKey structure and create an algorithmIdentifier
|
||||
*/
|
||||
chunk_t unwrap = key, inner;
|
||||
|
||||
if (asn1_unwrap(&unwrap, &unwrap) == ASN1_SEQUENCE &&
|
||||
asn1_unwrap(&unwrap, &inner) == ASN1_INTEGER &&
|
||||
asn1_parse_integer_uint64(inner) == 1 &&
|
||||
asn1_unwrap(&unwrap, &inner) == ASN1_OCTET_STRING &&
|
||||
asn1_unwrap(&unwrap, &inner) == ASN1_CONTEXT_C_0 &&
|
||||
asn1_unwrap(&inner, &inner) == ASN1_OID)
|
||||
{
|
||||
oid = asn1_known_oid(inner);
|
||||
if (oid != OID_UNKNOWN)
|
||||
{
|
||||
alg_id = asn1_algorithmIdentifier_params(OID_EC_PUBLICKEY,
|
||||
asn1_simple_object(ASN1_OID, inner));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (oid == OID_UNKNOWN)
|
||||
{
|
||||
chunk_free(&alg_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pkcs8 = asn1_wrap(ASN1_SEQUENCE, "mms",
|
||||
asn1_integer("c", chunk_from_chars(0x00)),
|
||||
alg_id,
|
||||
asn1_wrap(ASN1_OCTET_STRING, "c", key));
|
||||
|
||||
this = create_empty(oid);
|
||||
|
||||
if (botan_rng_init(&rng, "user"))
|
||||
{
|
||||
chunk_clear(&pkcs8);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (botan_privkey_load(&this->key, rng, pkcs8.ptr, pkcs8.len, NULL))
|
||||
{
|
||||
chunk_clear(&pkcs8);
|
||||
botan_rng_destroy(rng);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chunk_clear(&pkcs8);
|
||||
botan_rng_destroy(rng);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Tobias Brunner
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* Copyright (C) 2018 René Korthaus
|
||||
* Copyright (C) 2018 Konstantinos Kolelis
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup botan_ec_private_key botan_ec_private_key
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_EC_PRIVATE_KEY_H_
|
||||
#define BOTAN_EC_PRIVATE_KEY_H_
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
#include <credentials/builder.h>
|
||||
#include <credentials/keys/private_key.h>
|
||||
|
||||
typedef struct botan_ec_private_key_t botan_ec_private_key_t;
|
||||
|
||||
/**
|
||||
* private_key_t implementation of ECDSA using Botan.
|
||||
*/
|
||||
struct botan_ec_private_key_t {
|
||||
|
||||
/**
|
||||
* Implements private_key_t interface
|
||||
*/
|
||||
private_key_t key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a ECDSA private key using Botan.
|
||||
*
|
||||
* Accepts the BUILD_KEY_SIZE argument.
|
||||
*
|
||||
* @param type type of the key, must be KEY_ECDSA
|
||||
* @param args builder_part_t argument list
|
||||
* @return generated key, NULL on failure
|
||||
*/
|
||||
botan_ec_private_key_t *botan_ec_private_key_gen(key_type_t type, va_list args);
|
||||
|
||||
/**
|
||||
* Load a ECDSA private key using Botan.
|
||||
*
|
||||
* Accepts a BUILD_BLOB_ASN1_DER argument.
|
||||
*
|
||||
* @param type type of the key, must be KEY_ECDSA
|
||||
* @param args builder_part_t argument list
|
||||
* @return loaded key, NULL on failure
|
||||
*/
|
||||
botan_ec_private_key_t *botan_ec_private_key_load(key_type_t type,
|
||||
va_list args);
|
||||
|
||||
/**
|
||||
* Load a ECDSA private key by adopting a botan_privkey_t object.
|
||||
*
|
||||
* @param key private key object (adopted)
|
||||
* @param oid EC curve OID
|
||||
* @return loaded key, NULL on failure
|
||||
*/
|
||||
botan_ec_private_key_t *botan_ec_private_key_adopt(botan_privkey_t key,
|
||||
int oid);
|
||||
|
||||
#endif /** BOTAN_EC_PRIVATE_KEY_H_ @}*/
|
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
* Copyright (C) 2018 René Korthaus
|
||||
* Copyright (C) 2018 Konstantinos Kolelis
|
||||
* 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_ec_public_key.h"
|
||||
#include "botan_util.h"
|
||||
|
||||
#include <botan/build.h>
|
||||
|
||||
#ifdef BOTAN_HAS_ECDSA
|
||||
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/asn1_parser.h>
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
typedef struct private_botan_ec_public_key_t private_botan_ec_public_key_t;
|
||||
|
||||
/**
|
||||
* Private data structure with signing context.
|
||||
*/
|
||||
struct private_botan_ec_public_key_t {
|
||||
|
||||
/**
|
||||
* Public interface for this signer
|
||||
*/
|
||||
botan_ec_public_key_t public;
|
||||
|
||||
/**
|
||||
* Botan ec public key
|
||||
*/
|
||||
botan_pubkey_t key;
|
||||
|
||||
/**
|
||||
* Reference counter
|
||||
*/
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
#define SIG_FORMAT_IEEE_1363 0
|
||||
#define SIG_FORMAT_DER_SEQUENCE 1
|
||||
|
||||
/**
|
||||
* Verification of a DER encoded signature as in RFC 3279 or as in RFC 4754
|
||||
*/
|
||||
static bool verify_signature(private_botan_ec_public_key_t *this,
|
||||
const char* hash_and_padding, int signature_format, size_t keylen,
|
||||
chunk_t data, chunk_t signature)
|
||||
{
|
||||
botan_pk_op_verify_t verify_op;
|
||||
chunk_t sig = signature;
|
||||
bool valid = FALSE;
|
||||
|
||||
if (signature_format == SIG_FORMAT_DER_SEQUENCE)
|
||||
{
|
||||
/*
|
||||
* botan requires a signature in IEEE 1363 format (r||s)
|
||||
* re-encode from ASN.1 sequence of two integers r,s
|
||||
*/
|
||||
chunk_t parse = signature, r, s;
|
||||
|
||||
if (asn1_unwrap(&parse, &parse) != ASN1_SEQUENCE ||
|
||||
asn1_unwrap(&parse, &r) != ASN1_INTEGER ||
|
||||
asn1_unwrap(&parse, &s) != ASN1_INTEGER)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
r = chunk_skip_zero(r);
|
||||
s = chunk_skip_zero(s);
|
||||
|
||||
/*
|
||||
* r and s must be of size m_order.bytes()/2 each
|
||||
*/
|
||||
if (r.len > keylen || s.len > keylen)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sig = chunk_alloca(2 * keylen);
|
||||
memset(sig.ptr, 0, sig.len);
|
||||
memcpy(sig.ptr + (keylen - r.len), r.ptr, r.len);
|
||||
memcpy(sig.ptr + keylen + (keylen - s.len), s.ptr, s.len);
|
||||
}
|
||||
|
||||
if (botan_pk_op_verify_create(&verify_op, this->key, hash_and_padding, 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_pk_op_verify_update(verify_op, data.ptr, data.len))
|
||||
{
|
||||
botan_pk_op_verify_destroy(verify_op);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
valid = !(botan_pk_op_verify_finish(verify_op, sig.ptr, sig.len));
|
||||
|
||||
botan_pk_op_verify_destroy(verify_op);
|
||||
return valid;
|
||||
}
|
||||
|
||||
METHOD(public_key_t, get_type, key_type_t,
|
||||
private_botan_ec_public_key_t *this)
|
||||
{
|
||||
return KEY_ECDSA;
|
||||
}
|
||||
|
||||
METHOD(public_key_t, get_keysize, int,
|
||||
private_botan_ec_public_key_t *this)
|
||||
{
|
||||
botan_mp_t p;
|
||||
size_t bits = 0;
|
||||
|
||||
if (botan_mp_init(&p))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (botan_pubkey_get_field(p, this->key, "p") ||
|
||||
botan_mp_num_bits(p, &bits))
|
||||
{
|
||||
botan_mp_destroy(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
botan_mp_destroy(p);
|
||||
return bits;
|
||||
}
|
||||
|
||||
METHOD(public_key_t, verify, bool,
|
||||
private_botan_ec_public_key_t *this, signature_scheme_t scheme,
|
||||
void *params, chunk_t data, chunk_t signature)
|
||||
{
|
||||
size_t keylen = (get_keysize(this) + 7) / 8;
|
||||
const char *hash_and_padding;
|
||||
int sig_format;
|
||||
|
||||
switch (scheme)
|
||||
{
|
||||
/* r||s -> Botan::IEEE_1363, data is the hash already */
|
||||
case SIGN_ECDSA_WITH_NULL:
|
||||
hash_and_padding = "Raw";
|
||||
sig_format = SIG_FORMAT_IEEE_1363;
|
||||
break;
|
||||
/* DER SEQUENCE of two INTEGERS r,s -> Botan::DER_SEQUENCE */
|
||||
case SIGN_ECDSA_WITH_SHA1_DER:
|
||||
hash_and_padding = "EMSA1(SHA-1)";
|
||||
sig_format = SIG_FORMAT_DER_SEQUENCE;
|
||||
break;
|
||||
case SIGN_ECDSA_WITH_SHA256_DER:
|
||||
hash_and_padding = "EMSA1(SHA-256)";
|
||||
sig_format = SIG_FORMAT_DER_SEQUENCE;
|
||||
break;
|
||||
case SIGN_ECDSA_WITH_SHA384_DER:
|
||||
hash_and_padding = "EMSA1(SHA-384)";
|
||||
sig_format = SIG_FORMAT_DER_SEQUENCE;
|
||||
break;
|
||||
case SIGN_ECDSA_WITH_SHA512_DER:
|
||||
hash_and_padding = "EMSA1(SHA-512)";
|
||||
sig_format = SIG_FORMAT_DER_SEQUENCE;
|
||||
break;
|
||||
/* r||s -> Botan::IEEE_1363 */
|
||||
case SIGN_ECDSA_256:
|
||||
hash_and_padding = "EMSA1(SHA-256)";
|
||||
sig_format = SIG_FORMAT_IEEE_1363;
|
||||
break;
|
||||
case SIGN_ECDSA_384:
|
||||
hash_and_padding = "EMSA1(SHA-384)";
|
||||
sig_format = SIG_FORMAT_IEEE_1363;
|
||||
break;
|
||||
case SIGN_ECDSA_521:
|
||||
hash_and_padding = "EMSA1(SHA-512)";
|
||||
sig_format = SIG_FORMAT_IEEE_1363;
|
||||
break;
|
||||
default:
|
||||
DBG1(DBG_LIB, "signature scheme %N not supported via botan",
|
||||
signature_scheme_names, scheme);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return verify_signature(this, hash_and_padding,
|
||||
sig_format, keylen, data, signature);
|
||||
}
|
||||
|
||||
METHOD(public_key_t, encrypt, bool,
|
||||
private_botan_ec_public_key_t *this, encryption_scheme_t scheme,
|
||||
chunk_t crypto, chunk_t *plain)
|
||||
{
|
||||
DBG1(DBG_LIB, "EC public key encryption not implemented");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(public_key_t, get_fingerprint, bool,
|
||||
private_botan_ec_public_key_t *this, cred_encoding_type_t type,
|
||||
chunk_t *fingerprint)
|
||||
{
|
||||
return botan_get_fingerprint(this->key, this, type, fingerprint);
|
||||
}
|
||||
|
||||
METHOD(public_key_t, get_encoding, bool,
|
||||
private_botan_ec_public_key_t *this, cred_encoding_type_t type,
|
||||
chunk_t *encoding)
|
||||
{
|
||||
return botan_get_encoding(this->key, type, encoding);
|
||||
}
|
||||
|
||||
METHOD(public_key_t, get_ref, public_key_t*,
|
||||
private_botan_ec_public_key_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public.key;
|
||||
}
|
||||
|
||||
METHOD(public_key_t, destroy, void,
|
||||
private_botan_ec_public_key_t *this)
|
||||
{
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
lib->encoding->clear_cache(lib->encoding, this);
|
||||
botan_pubkey_destroy(this->key);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
botan_ec_public_key_t *botan_ec_public_key_adopt(botan_pubkey_t key)
|
||||
{
|
||||
private_botan_ec_public_key_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.key = {
|
||||
.get_type = _get_type,
|
||||
.verify = _verify,
|
||||
.encrypt = _encrypt,
|
||||
.get_keysize = _get_keysize,
|
||||
.equals = public_key_equals,
|
||||
.get_fingerprint = _get_fingerprint,
|
||||
.has_fingerprint = public_key_has_fingerprint,
|
||||
.get_encoding = _get_encoding,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.key = key,
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (C) 2018 René Korthaus
|
||||
* Copyright (C) 2018 Konstantinos Kolelis
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_EC_PUBLIC_KEY_H_
|
||||
#define BOTAN_EC_PUBLIC_KEY_H_
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
#include <credentials/builder.h>
|
||||
#include <credentials/keys/public_key.h>
|
||||
|
||||
typedef struct botan_ec_public_key_t botan_ec_public_key_t;
|
||||
|
||||
/**
|
||||
* public_key_t implementation of ECDSA using botan.
|
||||
*/
|
||||
struct botan_ec_public_key_t {
|
||||
|
||||
/**
|
||||
* Implements the public_key_t interface
|
||||
*/
|
||||
public_key_t key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a ECDSA public key by adopting a botan_pubkey_t object.
|
||||
*
|
||||
* @param key public key object (adopted)
|
||||
* @return loaded key, NULL on failure
|
||||
*/
|
||||
botan_ec_public_key_t *botan_ec_public_key_adopt(botan_pubkey_t key);
|
||||
|
||||
#endif /** BOTAN_EC_PUBLIC_KEY_H_ @}*/
|
|
@ -0,0 +1,333 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Atanas Filyanov
|
||||
* 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_gcm.h"
|
||||
|
||||
#include <botan/build.h>
|
||||
|
||||
#ifdef BOTAN_HAS_AES
|
||||
#ifdef BOTAN_HAS_AEAD_GCM
|
||||
|
||||
#include <crypto/iv/iv_gen_seq.h>
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
/**
|
||||
* as defined in RFC 4106
|
||||
*/
|
||||
#define IV_LEN 8
|
||||
#define SALT_LEN 4
|
||||
#define NONCE_LEN (IV_LEN + SALT_LEN)
|
||||
|
||||
typedef struct private_aead_t private_aead_t;
|
||||
|
||||
struct private_aead_t {
|
||||
|
||||
/**
|
||||
* Public interface
|
||||
*/
|
||||
aead_t public;
|
||||
|
||||
/**
|
||||
* The encryption key
|
||||
*/
|
||||
chunk_t key;
|
||||
|
||||
/**
|
||||
* Salt value
|
||||
*/
|
||||
char salt[SALT_LEN];
|
||||
|
||||
/**
|
||||
* Size of the integrity check value
|
||||
*/
|
||||
size_t icv_size;
|
||||
|
||||
/**
|
||||
* IV generator
|
||||
*/
|
||||
iv_gen_t *iv_gen;
|
||||
|
||||
/**
|
||||
* The cipher to use
|
||||
*/
|
||||
const char* cipher_name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Do the actual en/decryption
|
||||
*/
|
||||
static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv,
|
||||
u_char *out, uint32_t init_flag)
|
||||
{
|
||||
botan_cipher_t cipher;
|
||||
uint8_t nonce[NONCE_LEN];
|
||||
size_t output_written = 0, input_consumed = 0;
|
||||
|
||||
memcpy(nonce, this->salt, SALT_LEN);
|
||||
memcpy(nonce + SALT_LEN, iv.ptr, IV_LEN);
|
||||
|
||||
if (botan_cipher_init(&cipher, this->cipher_name, init_flag))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_cipher_set_key(cipher, this->key.ptr, this->key.len))
|
||||
{
|
||||
botan_cipher_destroy(cipher);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (assoc.len &&
|
||||
botan_cipher_set_associated_data(cipher, assoc.ptr, assoc.len))
|
||||
{
|
||||
botan_cipher_destroy(cipher);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_cipher_start(cipher, nonce, NONCE_LEN))
|
||||
{
|
||||
botan_cipher_destroy(cipher);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (init_flag == BOTAN_CIPHER_INIT_FLAG_ENCRYPT)
|
||||
{
|
||||
if (botan_cipher_update(cipher, BOTAN_CIPHER_UPDATE_FLAG_FINAL,
|
||||
out, data.len + this->icv_size, &output_written,
|
||||
data.ptr, data.len, &input_consumed))
|
||||
{
|
||||
botan_cipher_destroy(cipher);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (init_flag == BOTAN_CIPHER_INIT_FLAG_DECRYPT)
|
||||
{
|
||||
if (botan_cipher_update(cipher, BOTAN_CIPHER_UPDATE_FLAG_FINAL,
|
||||
out, data.len, &output_written, data.ptr,
|
||||
data.len + this->icv_size, &input_consumed))
|
||||
{
|
||||
botan_cipher_destroy(cipher);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
botan_cipher_destroy(cipher);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(aead_t, encrypt, bool,
|
||||
private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
|
||||
chunk_t *encrypted)
|
||||
{
|
||||
u_char *out;
|
||||
|
||||
out = plain.ptr;
|
||||
if (encrypted)
|
||||
{
|
||||
*encrypted = chunk_alloc(plain.len + this->icv_size);
|
||||
out = encrypted->ptr;
|
||||
}
|
||||
return crypt(this, plain, assoc, iv, out, BOTAN_CIPHER_INIT_FLAG_ENCRYPT);
|
||||
}
|
||||
|
||||
METHOD(aead_t, decrypt, bool,
|
||||
private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
|
||||
chunk_t *plain)
|
||||
{
|
||||
u_char *out;
|
||||
|
||||
if (encrypted.len < this->icv_size)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
encrypted.len -= this->icv_size;
|
||||
|
||||
out = encrypted.ptr;
|
||||
if (plain)
|
||||
{
|
||||
*plain = chunk_alloc(encrypted.len);
|
||||
out = plain->ptr;
|
||||
}
|
||||
return crypt(this, encrypted, assoc, iv, out,
|
||||
BOTAN_CIPHER_INIT_FLAG_DECRYPT);
|
||||
}
|
||||
|
||||
METHOD(aead_t, get_block_size, size_t,
|
||||
private_aead_t *this)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
METHOD(aead_t, get_icv_size, size_t,
|
||||
private_aead_t *this)
|
||||
{
|
||||
return this->icv_size;
|
||||
}
|
||||
|
||||
METHOD(aead_t, get_iv_size, size_t,
|
||||
private_aead_t *this)
|
||||
{
|
||||
return IV_LEN;
|
||||
}
|
||||
|
||||
METHOD(aead_t, get_iv_gen, iv_gen_t*,
|
||||
private_aead_t *this)
|
||||
{
|
||||
return this->iv_gen;
|
||||
}
|
||||
|
||||
METHOD(aead_t, get_key_size, size_t,
|
||||
private_aead_t *this)
|
||||
{
|
||||
return this->key.len + SALT_LEN;
|
||||
}
|
||||
|
||||
METHOD(aead_t, set_key, bool,
|
||||
private_aead_t *this, chunk_t key)
|
||||
{
|
||||
if (key.len != get_key_size(this))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
memcpy(this->salt, key.ptr + key.len - SALT_LEN, SALT_LEN);
|
||||
memcpy(this->key.ptr, key.ptr, this->key.len);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(aead_t, destroy, void,
|
||||
private_aead_t *this)
|
||||
{
|
||||
chunk_clear(&this->key);
|
||||
this->iv_gen->destroy(this->iv_gen);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
aead_t *botan_gcm_create(encryption_algorithm_t algo, size_t key_size,
|
||||
size_t salt_size)
|
||||
{
|
||||
private_aead_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.encrypt = _encrypt,
|
||||
.decrypt = _decrypt,
|
||||
.get_block_size = _get_block_size,
|
||||
.get_icv_size = _get_icv_size,
|
||||
.get_iv_size = _get_iv_size,
|
||||
.get_iv_gen = _get_iv_gen,
|
||||
.get_key_size = _get_key_size,
|
||||
.set_key = _set_key,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
);
|
||||
|
||||
if (salt_size && salt_size != SALT_LEN)
|
||||
{
|
||||
/* currently not supported */
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (algo)
|
||||
{
|
||||
case ENCR_AES_GCM_ICV8:
|
||||
switch (key_size)
|
||||
{
|
||||
case 0:
|
||||
key_size = 16;
|
||||
/* FALL */
|
||||
case 16:
|
||||
this->cipher_name = "AES-128/GCM(8)";
|
||||
break;
|
||||
case 24:
|
||||
this->cipher_name = "AES-192/GCM(8)";
|
||||
break;
|
||||
case 32:
|
||||
this->cipher_name = "AES-256/GCM(8)";
|
||||
break;
|
||||
default:
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
this->icv_size = 8;
|
||||
break;
|
||||
case ENCR_AES_GCM_ICV12:
|
||||
switch (key_size)
|
||||
{
|
||||
case 0:
|
||||
key_size = 16;
|
||||
/* FALL */
|
||||
case 16:
|
||||
this->cipher_name = "AES-128/GCM(12)";
|
||||
break;
|
||||
case 24:
|
||||
this->cipher_name = "AES-192/GCM(12)";
|
||||
break;
|
||||
case 32:
|
||||
this->cipher_name = "AES-256/GCM(12)";
|
||||
break;
|
||||
default:
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
this->icv_size = 12;
|
||||
break;
|
||||
case ENCR_AES_GCM_ICV16:
|
||||
switch (key_size)
|
||||
{
|
||||
case 0:
|
||||
key_size = 16;
|
||||
/* FALL */
|
||||
case 16:
|
||||
this->cipher_name = "AES-128/GCM";
|
||||
break;
|
||||
case 24:
|
||||
this->cipher_name = "AES-192/GCM";
|
||||
break;
|
||||
case 32:
|
||||
this->cipher_name = "AES-256/GCM";
|
||||
break;
|
||||
default:
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
this->icv_size = 16;
|
||||
break;
|
||||
default:
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
this->key = chunk_alloc(key_size);
|
||||
this->iv_gen = iv_gen_seq_create();
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Atanas Filyanov
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements the aead_t interface using Botan in GCM mode.
|
||||
*
|
||||
* @defgroup botan_gcm botan_gcm
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_GCM_H_
|
||||
#define BOTAN_GCM_H_
|
||||
|
||||
#include <crypto/aead.h>
|
||||
|
||||
/**
|
||||
* Constructor to create aead_t implementation.
|
||||
*
|
||||
* @param algo algorithm to implement
|
||||
* @param key_size key size in bytes
|
||||
* @param salt_size size of implicit salt length
|
||||
* @return aead_t object, NULL if not supported
|
||||
*/
|
||||
aead_t *botan_gcm_create(encryption_algorithm_t algo, size_t key_size,
|
||||
size_t salt_size);
|
||||
|
||||
#endif /** BOTAN_GCM_H_ @}*/
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* 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_hasher.h"
|
||||
#include "botan_util.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
typedef struct private_botan_hasher_t private_botan_hasher_t;
|
||||
|
||||
/**
|
||||
* Private data of botan_hasher_t
|
||||
*/
|
||||
struct private_botan_hasher_t {
|
||||
|
||||
/**
|
||||
* Public part of this class.
|
||||
*/
|
||||
botan_hasher_t public;
|
||||
|
||||
/**
|
||||
* botan hash instance
|
||||
*/
|
||||
botan_hash_t hash;
|
||||
};
|
||||
|
||||
METHOD(hasher_t, get_hash_size, size_t,
|
||||
private_botan_hasher_t *this)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
if (botan_hash_output_length(this->hash, &len))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
METHOD(hasher_t, reset, bool,
|
||||
private_botan_hasher_t *this)
|
||||
{
|
||||
if (botan_hash_clear(this->hash))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(hasher_t, get_hash, bool,
|
||||
private_botan_hasher_t *this, chunk_t chunk, uint8_t *hash)
|
||||
{
|
||||
if (botan_hash_update(this->hash, chunk.ptr, chunk.len))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (hash && botan_hash_final(this->hash, hash))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(hasher_t, allocate_hash, bool,
|
||||
private_botan_hasher_t *this, chunk_t chunk, chunk_t *hash)
|
||||
{
|
||||
if (hash)
|
||||
{
|
||||
*hash = chunk_alloc(get_hash_size(this));
|
||||
return get_hash(this, chunk, hash->ptr);
|
||||
}
|
||||
return get_hash(this, chunk, NULL);
|
||||
}
|
||||
|
||||
METHOD(hasher_t, destroy, void,
|
||||
private_botan_hasher_t *this)
|
||||
{
|
||||
botan_hash_destroy(this->hash);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
botan_hasher_t *botan_hasher_create(hash_algorithm_t algo)
|
||||
{
|
||||
private_botan_hasher_t *this;
|
||||
const char* hash_name;
|
||||
|
||||
hash_name = botan_get_hash(algo);
|
||||
if (!hash_name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.hasher = {
|
||||
.get_hash = _get_hash,
|
||||
.allocate_hash = _allocate_hash,
|
||||
.get_hash_size = _get_hash_size,
|
||||
.reset = _reset,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (botan_hash_init(&this->hash, hash_name, 0))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return &this->public;
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup botan_hasher botan_hasher
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_HASHER_H_
|
||||
#define BOTAN_HASHER_H_
|
||||
|
||||
typedef struct botan_hasher_t botan_hasher_t;
|
||||
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
/**
|
||||
* Implementation of hashers using botan.
|
||||
*/
|
||||
struct botan_hasher_t {
|
||||
|
||||
/**
|
||||
* The hasher_t interface.
|
||||
*/
|
||||
hasher_t hasher;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor to create botan_hasher_t.
|
||||
*
|
||||
* @param algo algorithm
|
||||
* @return botan_hasher_t, NULL if not supported
|
||||
*/
|
||||
botan_hasher_t *botan_hasher_create(hash_algorithm_t algo);
|
||||
|
||||
#endif /** BOTAN_HASHER_H_ @}*/
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* 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_hmac.h"
|
||||
|
||||
#include <botan/build.h>
|
||||
|
||||
#ifdef BOTAN_HAS_HMAC
|
||||
|
||||
#include <crypto/mac.h>
|
||||
#include <crypto/prfs/mac_prf.h>
|
||||
#include <crypto/signers/mac_signer.h>
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
typedef struct private_botan_mac_t private_botan_mac_t;
|
||||
|
||||
/**
|
||||
* Private data of a mac_t object.
|
||||
*/
|
||||
struct private_botan_mac_t {
|
||||
|
||||
/**
|
||||
* Public interface
|
||||
*/
|
||||
mac_t public;
|
||||
|
||||
/**
|
||||
* HMAC
|
||||
*/
|
||||
botan_mac_t hmac;
|
||||
};
|
||||
|
||||
METHOD(mac_t, set_key, bool,
|
||||
private_botan_mac_t *this, chunk_t key)
|
||||
{
|
||||
if (botan_mac_set_key(this->hmac, key.ptr, key.len))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(mac_t, get_mac, bool,
|
||||
private_botan_mac_t *this, chunk_t data, uint8_t *out)
|
||||
{
|
||||
if (botan_mac_update(this->hmac, data.ptr, data.len))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (out && botan_mac_final(this->hmac, out))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(mac_t, get_mac_size, size_t,
|
||||
private_botan_mac_t *this)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
if (botan_mac_output_length(this->hmac, &len))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
METHOD(mac_t, destroy, void,
|
||||
private_botan_mac_t *this)
|
||||
{
|
||||
botan_mac_destroy(this->hmac);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a Botan-backed implementation of the mac_t interface
|
||||
*/
|
||||
static mac_t *hmac_create(hash_algorithm_t algo)
|
||||
{
|
||||
private_botan_mac_t *this;
|
||||
const char* hmac_name;
|
||||
|
||||
switch (algo)
|
||||
{
|
||||
case HASH_SHA1:
|
||||
hmac_name = "HMAC(SHA-1)";
|
||||
break;
|
||||
case HASH_SHA256:
|
||||
hmac_name = "HMAC(SHA-256)";
|
||||
break;
|
||||
case HASH_SHA384:
|
||||
hmac_name = "HMAC(SHA-384)";
|
||||
break;
|
||||
case HASH_SHA512:
|
||||
hmac_name = "HMAC(SHA-512)";
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_mac = _get_mac,
|
||||
.get_mac_size = _get_mac_size,
|
||||
.set_key = _set_key,
|
||||
.destroy = _destroy,
|
||||
}
|
||||
);
|
||||
|
||||
if (botan_mac_init(&this->hmac, hmac_name, 0))
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
prf_t *botan_hmac_prf_create(pseudo_random_function_t algo)
|
||||
{
|
||||
mac_t *hmac;
|
||||
|
||||
hmac = hmac_create(hasher_algorithm_from_prf(algo));
|
||||
if (hmac)
|
||||
{
|
||||
return mac_prf_create(hmac);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
signer_t *botan_hmac_signer_create(integrity_algorithm_t algo)
|
||||
{
|
||||
mac_t *hmac;
|
||||
size_t trunc;
|
||||
|
||||
hmac = hmac_create(hasher_algorithm_from_integrity(algo, &trunc));
|
||||
if (hmac)
|
||||
{
|
||||
return mac_signer_create(hmac, trunc);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements HMAC based PRF and signer using Botan's HMAC functions.
|
||||
*
|
||||
* @defgroup botan_hmac botan_hmac
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_HMAC_H_
|
||||
#define BOTAN_HMAC_H_
|
||||
|
||||
#include <crypto/prfs/prf.h>
|
||||
#include <crypto/signers/signer.h>
|
||||
|
||||
/**
|
||||
* Creates a new prf_t object based on an HMAC.
|
||||
*
|
||||
* @param algo algorithm to implement
|
||||
* @return prf_t object, NULL if not supported
|
||||
*/
|
||||
prf_t *botan_hmac_prf_create(pseudo_random_function_t algo);
|
||||
|
||||
/**
|
||||
* Creates a new signer_t object based on an HMAC.
|
||||
*
|
||||
* @param algo algorithm to implement
|
||||
* @return signer_t, NULL if not supported
|
||||
*/
|
||||
signer_t *botan_hmac_signer_create(integrity_algorithm_t algo);
|
||||
|
||||
#endif /** BOTAN_HMAC_H_ @}*/
|
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Tobias Brunner
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* Copyright (C) 2018 René Korthaus
|
||||
* Copyright (C) 2018 Konstantinos Kolelis
|
||||
* 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_plugin.h"
|
||||
#include "botan_rng.h"
|
||||
#include "botan_hasher.h"
|
||||
#include "botan_crypter.h"
|
||||
#include "botan_diffie_hellman.h"
|
||||
#include "botan_hmac.h"
|
||||
#include "botan_rsa_public_key.h"
|
||||
#include "botan_rsa_private_key.h"
|
||||
#include "botan_ec_diffie_hellman.h"
|
||||
#include "botan_ec_public_key.h"
|
||||
#include "botan_ec_private_key.h"
|
||||
#include "botan_gcm.h"
|
||||
#include "botan_util_keys.h"
|
||||
#include "botan_x25519.h"
|
||||
|
||||
#include <library.h>
|
||||
|
||||
#include <botan/build.h>
|
||||
#include <botan/ffi.h>
|
||||
|
||||
typedef struct private_botan_plugin_t private_botan_plugin_t;
|
||||
|
||||
/**
|
||||
* private data of botan_plugin
|
||||
*/
|
||||
struct private_botan_plugin_t {
|
||||
|
||||
/**
|
||||
* public functions
|
||||
*/
|
||||
botan_plugin_t public;
|
||||
};
|
||||
|
||||
METHOD(plugin_t, get_name, char*,
|
||||
private_botan_plugin_t *this)
|
||||
{
|
||||
return "botan";
|
||||
}
|
||||
|
||||
METHOD(plugin_t, get_features, int,
|
||||
private_botan_plugin_t *this, plugin_feature_t *features[])
|
||||
{
|
||||
static plugin_feature_t f[] = {
|
||||
|
||||
#ifdef BOTAN_HAS_DIFFIE_HELLMAN
|
||||
/* MODP DH groups */
|
||||
PLUGIN_REGISTER(DH, botan_diffie_hellman_create),
|
||||
PLUGIN_PROVIDE(DH, MODP_3072_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_4096_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_6144_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_8192_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_2048_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_2048_224),
|
||||
PLUGIN_PROVIDE(DH, MODP_2048_256),
|
||||
PLUGIN_PROVIDE(DH, MODP_1536_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_1024_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_1024_160),
|
||||
PLUGIN_PROVIDE(DH, MODP_768_BIT),
|
||||
PLUGIN_PROVIDE(DH, MODP_CUSTOM),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_ECDH
|
||||
/* EC DH groups */
|
||||
PLUGIN_REGISTER(DH, botan_ec_diffie_hellman_create),
|
||||
PLUGIN_PROVIDE(DH, ECP_256_BIT),
|
||||
PLUGIN_PROVIDE(DH, ECP_384_BIT),
|
||||
PLUGIN_PROVIDE(DH, ECP_521_BIT),
|
||||
PLUGIN_PROVIDE(DH, ECP_256_BP),
|
||||
PLUGIN_PROVIDE(DH, ECP_384_BP),
|
||||
PLUGIN_PROVIDE(DH, ECP_512_BP),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_X25519
|
||||
PLUGIN_REGISTER(DH, botan_x25519_create),
|
||||
PLUGIN_PROVIDE(DH, CURVE_25519),
|
||||
#endif
|
||||
|
||||
/* crypters */
|
||||
PLUGIN_REGISTER(CRYPTER, botan_crypter_create),
|
||||
#ifdef BOTAN_HAS_AES
|
||||
#ifdef BOTAN_HAS_MODE_CBC
|
||||
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 16),
|
||||
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 24),
|
||||
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 32),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_AEAD_GCM
|
||||
/* AES GCM */
|
||||
PLUGIN_REGISTER(AEAD, botan_gcm_create),
|
||||
PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 16),
|
||||
PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 24),
|
||||
PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 32),
|
||||
PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 16),
|
||||
PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 24),
|
||||
PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 32),
|
||||
#endif
|
||||
#endif
|
||||
/* hashers */
|
||||
PLUGIN_REGISTER(HASHER, botan_hasher_create),
|
||||
#ifdef BOTAN_HAS_MD5
|
||||
PLUGIN_PROVIDE(HASHER, HASH_MD5),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_SHA1
|
||||
PLUGIN_PROVIDE(HASHER, HASH_SHA1),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_SHA2_32
|
||||
PLUGIN_PROVIDE(HASHER, HASH_SHA224),
|
||||
PLUGIN_PROVIDE(HASHER, HASH_SHA256),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_SHA2_64
|
||||
PLUGIN_PROVIDE(HASHER, HASH_SHA384),
|
||||
PLUGIN_PROVIDE(HASHER, HASH_SHA512),
|
||||
#endif
|
||||
/* prfs */
|
||||
#ifdef BOTAN_HAS_HMAC
|
||||
PLUGIN_REGISTER(PRF, botan_hmac_prf_create),
|
||||
#ifdef BOTAN_HAS_SHA1
|
||||
PLUGIN_PROVIDE(PRF, PRF_HMAC_SHA1),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_SHA2_32
|
||||
PLUGIN_PROVIDE(PRF, PRF_HMAC_SHA2_256),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_SHA2_64
|
||||
PLUGIN_PROVIDE(PRF, PRF_HMAC_SHA2_384),
|
||||
PLUGIN_PROVIDE(PRF, PRF_HMAC_SHA2_512),
|
||||
#endif
|
||||
/* signer */
|
||||
PLUGIN_REGISTER(SIGNER, botan_hmac_signer_create),
|
||||
#ifdef BOTAN_HAS_SHA1
|
||||
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA1_96),
|
||||
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA1_128),
|
||||
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA1_160),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_SHA2_32
|
||||
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_256_128),
|
||||
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_256_256),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_SHA2_64
|
||||
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_384_192),
|
||||
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_384_384),
|
||||
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_256),
|
||||
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_512),
|
||||
#endif
|
||||
#endif /* BOTAN_HAS_HMAC */
|
||||
|
||||
/* generic key loaders */
|
||||
#if defined (BOTAN_HAS_RSA) || defined(BOTAN_HAS_ECDSA)
|
||||
PLUGIN_REGISTER(PUBKEY, botan_public_key_load, TRUE),
|
||||
PLUGIN_PROVIDE(PUBKEY, KEY_ANY),
|
||||
#ifdef BOTAN_HAS_RSA
|
||||
PLUGIN_PROVIDE(PUBKEY, KEY_RSA),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_ECDSA
|
||||
PLUGIN_PROVIDE(PUBKEY, KEY_ECDSA),
|
||||
#endif
|
||||
PLUGIN_REGISTER(PRIVKEY, botan_private_key_load, TRUE),
|
||||
PLUGIN_PROVIDE(PRIVKEY, KEY_ANY),
|
||||
#ifdef BOTAN_HAS_RSA
|
||||
PLUGIN_PROVIDE(PRIVKEY, KEY_RSA),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_ECDSA
|
||||
PLUGIN_PROVIDE(PRIVKEY, KEY_ECDSA),
|
||||
#endif
|
||||
#endif
|
||||
/* RSA */
|
||||
#ifdef BOTAN_HAS_RSA
|
||||
/* public/private key loading/generation */
|
||||
PLUGIN_REGISTER(PUBKEY, botan_rsa_public_key_load, TRUE),
|
||||
PLUGIN_PROVIDE(PUBKEY, KEY_RSA),
|
||||
PLUGIN_REGISTER(PRIVKEY, botan_rsa_private_key_load, TRUE),
|
||||
PLUGIN_PROVIDE(PRIVKEY, KEY_RSA),
|
||||
PLUGIN_PROVIDE(PRIVKEY, KEY_ANY),
|
||||
PLUGIN_REGISTER(PRIVKEY_GEN, botan_rsa_private_key_gen, FALSE),
|
||||
PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_RSA),
|
||||
/* encryption/signature schemes */
|
||||
#ifdef BOTAN_HAS_EMSA_PKCS1
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_NULL),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_NULL),
|
||||
#ifdef BOTAN_HAS_SHA1
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA1),
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA1),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA1),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA1),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_SHA2_32
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_224),
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_256),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_224),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_256),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_SHA2_64
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_384),
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_512),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_384),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_512),
|
||||
#endif
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_EMSA_PSSR
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PSS),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PSS),
|
||||
#endif
|
||||
PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_PKCS1),
|
||||
PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_PKCS1),
|
||||
#ifdef BOTAN_HAS_EME_OAEP
|
||||
#ifdef BOTAN_HAS_SHA2_32
|
||||
PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_OAEP_SHA224),
|
||||
PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_OAEP_SHA256),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_SHA2_64
|
||||
PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_OAEP_SHA384),
|
||||
PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_OAEP_SHA512),
|
||||
#endif
|
||||
#endif
|
||||
#endif /* BOTAN_HAS_RSA */
|
||||
|
||||
#ifdef BOTAN_HAS_ECDSA
|
||||
/* EC private/public key loading */
|
||||
PLUGIN_REGISTER(PRIVKEY, botan_ec_private_key_load, TRUE),
|
||||
PLUGIN_PROVIDE(PRIVKEY, KEY_ECDSA),
|
||||
PLUGIN_PROVIDE(PRIVKEY, KEY_ANY),
|
||||
PLUGIN_REGISTER(PRIVKEY_GEN, botan_ec_private_key_gen, FALSE),
|
||||
PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_ECDSA),
|
||||
#ifdef BOTAN_HAS_EMSA_RAW
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_ECDSA_WITH_NULL),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ECDSA_WITH_NULL),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_EMSA1
|
||||
#ifdef BOTAN_HAS_SHA1
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_ECDSA_WITH_SHA1_DER),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ECDSA_WITH_SHA1_DER),
|
||||
#endif
|
||||
#ifdef BOTAN_HAS_SHA2_32
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_ECDSA_WITH_SHA256_DER),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ECDSA_WITH_SHA256_DER),
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_ECDSA_256),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ECDSA_256),
|
||||
#endif
|
||||
#ifndef BOTAN_HAS_SHA2_64
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_ECDSA_WITH_SHA384_DER),
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_ECDSA_WITH_SHA512_DER),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ECDSA_WITH_SHA384_DER),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ECDSA_WITH_SHA512_DER),
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_ECDSA_384),
|
||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_ECDSA_521),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ECDSA_384),
|
||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ECDSA_521),
|
||||
#endif
|
||||
#endif /* BOTAN_HAS_EMSA1 */
|
||||
#endif /* BOTAN_HAS_ECDSA */
|
||||
|
||||
/* random numbers */
|
||||
#if BOTAN_HAS_SYSTEM_RNG
|
||||
#if BOTAN_HAS_HMAC_DRBG
|
||||
PLUGIN_REGISTER(RNG, botan_rng_create),
|
||||
PLUGIN_PROVIDE(RNG, RNG_WEAK),
|
||||
PLUGIN_PROVIDE(RNG, RNG_STRONG),
|
||||
PLUGIN_PROVIDE(RNG, RNG_TRUE)
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
*features = f;
|
||||
return countof(f);
|
||||
}
|
||||
|
||||
METHOD(plugin_t, destroy, void,
|
||||
private_botan_plugin_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
plugin_t *botan_plugin_create()
|
||||
{
|
||||
private_botan_plugin_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.plugin = {
|
||||
.get_name = _get_name,
|
||||
.get_features = _get_features,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
return &this->public.plugin;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup botan_p botan
|
||||
* @ingroup plugins
|
||||
*
|
||||
* @defgroup botan_plugin botan_plugin
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_PLUGIN_H_
|
||||
#define BOTAN_PLUGIN_H_
|
||||
|
||||
#include <plugins/plugin.h>
|
||||
|
||||
typedef struct botan_plugin_t botan_plugin_t;
|
||||
|
||||
/**
|
||||
* Plugin implementing crypto functions using Botan.
|
||||
*/
|
||||
struct botan_plugin_t {
|
||||
|
||||
/**
|
||||
* implements plugin interface
|
||||
*/
|
||||
plugin_t plugin;
|
||||
};
|
||||
|
||||
#endif /** BOTAN_PLUGIN_H_ @}*/
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* 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_rng.h"
|
||||
|
||||
#include <botan/build.h>
|
||||
|
||||
#ifdef BOTAN_HAS_HMAC_DRBG
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
typedef struct private_botan_random_t private_botan_random_t;
|
||||
|
||||
/**
|
||||
* Private data of an botan_rng_t object.
|
||||
*/
|
||||
struct private_botan_random_t {
|
||||
|
||||
/**
|
||||
* Public botan_rnd_t interface.
|
||||
*/
|
||||
botan_random_t public;
|
||||
|
||||
/**
|
||||
* RNG quality of this instance
|
||||
*/
|
||||
rng_quality_t quality;
|
||||
|
||||
/**
|
||||
* RNG instance
|
||||
*/
|
||||
botan_rng_t rng;
|
||||
};
|
||||
|
||||
METHOD(rng_t, get_bytes, bool,
|
||||
private_botan_random_t *this, size_t bytes, uint8_t *buffer)
|
||||
{
|
||||
return botan_rng_get(this->rng, buffer, bytes) == 0;
|
||||
}
|
||||
|
||||
METHOD(rng_t, allocate_bytes, bool,
|
||||
private_botan_random_t *this, size_t bytes, chunk_t *chunk)
|
||||
{
|
||||
*chunk = chunk_alloc(bytes);
|
||||
if (!get_bytes(this, chunk->len, chunk->ptr))
|
||||
{
|
||||
chunk_free(chunk);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(rng_t, destroy, void,
|
||||
private_botan_random_t *this)
|
||||
{
|
||||
botan_rng_destroy(this->rng);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
botan_random_t *botan_rng_create(rng_quality_t quality)
|
||||
{
|
||||
private_botan_random_t *this;
|
||||
const char* rng_name;
|
||||
|
||||
switch (quality)
|
||||
{
|
||||
case RNG_WEAK:
|
||||
case RNG_STRONG:
|
||||
/* some rng_t instances of this class (e.g. in the ike-sa-manager)
|
||||
* may be called concurrently by different threads. the Botan RNGs
|
||||
* are not reentrant, by default, so use the threadsafe version.
|
||||
* because we build without threading support when running tests
|
||||
* with leak-detective (lots of reports of frees of unknown memory)
|
||||
* there is a fallback to the default */
|
||||
#ifdef BOTAN_TARGET_OS_HAS_THREADS
|
||||
rng_name = "user-threadsafe";
|
||||
#else
|
||||
rng_name = "user";
|
||||
#endif
|
||||
break;
|
||||
case RNG_TRUE:
|
||||
rng_name = "system";
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.rng = {
|
||||
.get_bytes = _get_bytes,
|
||||
.allocate_bytes = _allocate_bytes,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.quality = quality,
|
||||
);
|
||||
|
||||
if (botan_rng_init(&this->rng, rng_name))
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup botan_rng botan_rng
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_RNG_H_
|
||||
#define BOTAN_RNG_H_
|
||||
|
||||
typedef struct botan_random_t botan_random_t;
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* rng_t implementation using botan.
|
||||
*
|
||||
* @note botan_rng_t is a botan reserved type.
|
||||
*/
|
||||
struct botan_random_t {
|
||||
|
||||
/**
|
||||
* Implements rng_t.
|
||||
*/
|
||||
rng_t rng;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a botan_random_t instance.
|
||||
*
|
||||
* @param quality required quality of randomness
|
||||
* @return botan_random_t instance
|
||||
*/
|
||||
botan_random_t *botan_rng_create(rng_quality_t quality);
|
||||
|
||||
#endif /** BOTAN_RNG_H_ @} */
|
|
@ -0,0 +1,685 @@
|
|||
/*
|
||||
* 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_rsa_private_key.h"
|
||||
#include "botan_rsa_public_key.h"
|
||||
|
||||
#include <botan/build.h>
|
||||
|
||||
#ifdef BOTAN_HAS_RSA
|
||||
|
||||
#include "botan_util.h"
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_botan_rsa_private_key_t private_botan_rsa_private_key_t;
|
||||
|
||||
/**
|
||||
* Private data of a botan_rsa_private_key_t object.
|
||||
*/
|
||||
struct private_botan_rsa_private_key_t {
|
||||
|
||||
/**
|
||||
* Public interface for this signer.
|
||||
*/
|
||||
botan_rsa_private_key_t public;
|
||||
|
||||
/**
|
||||
* Botan private key
|
||||
*/
|
||||
botan_privkey_t key;
|
||||
|
||||
/**
|
||||
* reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
/**
|
||||
* Build an EMSA PSS signature described in PKCS#1
|
||||
*/
|
||||
static bool build_emsa_pss_signature(private_botan_rsa_private_key_t *this,
|
||||
rsa_pss_params_t *params, chunk_t data,
|
||||
chunk_t *sig)
|
||||
{
|
||||
const char *hash;
|
||||
char hash_and_padding[BUF_LEN];
|
||||
|
||||
if (!params)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* botan currently does not support passing the mgf1 hash */
|
||||
if (params->hash != params->mgf1_hash)
|
||||
{
|
||||
DBG1(DBG_LIB, "passing mgf1 hash not supported via botan");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hash = botan_get_hash(params->hash);
|
||||
if (!hash)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
|
||||
{
|
||||
snprintf(hash_and_padding, sizeof(hash_and_padding),
|
||||
"EMSA-PSS(%s,MGF1,%u)", hash, params->salt_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(hash_and_padding, sizeof(hash_and_padding),
|
||||
"EMSA-PSS(%s,MGF1)", hash);
|
||||
}
|
||||
return botan_get_signature(this->key, hash_and_padding, data, sig);
|
||||
}
|
||||
|
||||
METHOD(private_key_t, get_type, key_type_t,
|
||||
private_botan_rsa_private_key_t *this)
|
||||
{
|
||||
return KEY_RSA;
|
||||
}
|
||||
|
||||
METHOD(private_key_t, sign, bool,
|
||||
private_botan_rsa_private_key_t *this, signature_scheme_t scheme,
|
||||
void *params, chunk_t data, chunk_t *signature)
|
||||
{
|
||||
switch (scheme)
|
||||
{
|
||||
case SIGN_RSA_EMSA_PKCS1_NULL:
|
||||
return botan_get_signature(this->key, "EMSA_PKCS1(Raw)", data,
|
||||
signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA1:
|
||||
return botan_get_signature(this->key, "EMSA_PKCS1(SHA-1)", data,
|
||||
signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA2_224:
|
||||
return botan_get_signature(this->key, "EMSA_PKCS1(SHA-224)", data,
|
||||
signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA2_256:
|
||||
return botan_get_signature(this->key, "EMSA_PKCS1(SHA-256)", data,
|
||||
signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA2_384:
|
||||
return botan_get_signature(this->key, "EMSA_PKCS1(SHA-384)", data,
|
||||
signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA2_512:
|
||||
return botan_get_signature(this->key, "EMSA_PKCS1(SHA-512)", data,
|
||||
signature);
|
||||
case SIGN_RSA_EMSA_PSS:
|
||||
return build_emsa_pss_signature(this, params, data, signature);
|
||||
default:
|
||||
DBG1(DBG_LIB, "signature scheme %N not supported via botan",
|
||||
signature_scheme_names, scheme);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(private_key_t, decrypt, bool,
|
||||
private_botan_rsa_private_key_t *this, encryption_scheme_t scheme,
|
||||
chunk_t crypto, chunk_t *plain)
|
||||
{
|
||||
botan_pk_op_decrypt_t decrypt_op;
|
||||
const char *padding;
|
||||
|
||||
switch (scheme)
|
||||
{
|
||||
case ENCRYPT_RSA_PKCS1:
|
||||
padding = "PKCS1v15";
|
||||
break;
|
||||
case ENCRYPT_RSA_OAEP_SHA1:
|
||||
padding = "OAEP(SHA-1)";
|
||||
break;
|
||||
case ENCRYPT_RSA_OAEP_SHA224:
|
||||
padding = "OAEP(SHA-224)";
|
||||
break;
|
||||
case ENCRYPT_RSA_OAEP_SHA256:
|
||||
padding = "OAEP(SHA-256)";
|
||||
break;
|
||||
case ENCRYPT_RSA_OAEP_SHA384:
|
||||
padding = "OAEP(SHA-384)";
|
||||
break;
|
||||
case ENCRYPT_RSA_OAEP_SHA512:
|
||||
padding = "OAEP(SHA-512)";
|
||||
break;
|
||||
default:
|
||||
DBG1(DBG_LIB, "encryption scheme %N not supported via botan",
|
||||
encryption_scheme_names, scheme);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_pk_op_decrypt_create(&decrypt_op, this->key, padding, 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
plain->len = 0;
|
||||
if (botan_pk_op_decrypt_output_length(decrypt_op, crypto.len, &plain->len))
|
||||
{
|
||||
botan_pk_op_decrypt_destroy(decrypt_op);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*plain = chunk_alloc(plain->len);
|
||||
if (botan_pk_op_decrypt(decrypt_op, plain->ptr, &plain->len, crypto.ptr,
|
||||
crypto.len))
|
||||
{
|
||||
chunk_free(plain);
|
||||
botan_pk_op_decrypt_destroy(decrypt_op);
|
||||
return FALSE;
|
||||
}
|
||||
botan_pk_op_decrypt_destroy(decrypt_op);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(private_key_t, get_keysize, int,
|
||||
private_botan_rsa_private_key_t *this)
|
||||
{
|
||||
botan_mp_t n;
|
||||
size_t bits = 0;
|
||||
|
||||
if (botan_mp_init(&n))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (botan_privkey_rsa_get_n(n, this->key) ||
|
||||
botan_mp_num_bits(n, &bits))
|
||||
{
|
||||
botan_mp_destroy(n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
botan_mp_destroy(n);
|
||||
return bits;
|
||||
}
|
||||
|
||||
METHOD(private_key_t, get_public_key, public_key_t*,
|
||||
private_botan_rsa_private_key_t *this)
|
||||
{
|
||||
botan_pubkey_t pubkey;
|
||||
|
||||
if (botan_privkey_export_pubkey(&pubkey, this->key))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return (public_key_t*)botan_rsa_public_key_adopt(pubkey);
|
||||
}
|
||||
|
||||
METHOD(private_key_t, get_fingerprint, bool,
|
||||
private_botan_rsa_private_key_t *this, cred_encoding_type_t type,
|
||||
chunk_t *fingerprint)
|
||||
{
|
||||
botan_pubkey_t pubkey;
|
||||
bool success = FALSE;
|
||||
|
||||
/* check the cache before doing the export */
|
||||
if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (botan_privkey_export_pubkey(&pubkey, this->key))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
success = botan_get_fingerprint(pubkey, this, type, fingerprint);
|
||||
botan_pubkey_destroy(pubkey);
|
||||
return success;
|
||||
}
|
||||
|
||||
METHOD(private_key_t, get_encoding, bool,
|
||||
private_botan_rsa_private_key_t *this, cred_encoding_type_t type,
|
||||
chunk_t *encoding)
|
||||
{
|
||||
return botan_get_privkey_encoding(this->key, type, encoding);
|
||||
}
|
||||
|
||||
METHOD(private_key_t, get_ref, private_key_t*,
|
||||
private_botan_rsa_private_key_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public.key;
|
||||
}
|
||||
|
||||
METHOD(private_key_t, destroy, void,
|
||||
private_botan_rsa_private_key_t *this)
|
||||
{
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
lib->encoding->clear_cache(lib->encoding, this);
|
||||
botan_privkey_destroy(this->key);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal generic constructor
|
||||
*/
|
||||
static private_botan_rsa_private_key_t *create_empty()
|
||||
{
|
||||
private_botan_rsa_private_key_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.key = {
|
||||
.get_type = _get_type,
|
||||
.sign = _sign,
|
||||
.decrypt = _decrypt,
|
||||
.get_keysize = _get_keysize,
|
||||
.get_public_key = _get_public_key,
|
||||
.equals = private_key_equals,
|
||||
.belongs_to = private_key_belongs_to,
|
||||
.get_fingerprint = _get_fingerprint,
|
||||
.has_fingerprint = private_key_has_fingerprint,
|
||||
.get_encoding = _get_encoding,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
botan_rsa_private_key_t *botan_rsa_private_key_adopt(botan_privkey_t key)
|
||||
{
|
||||
private_botan_rsa_private_key_t *this;
|
||||
|
||||
this = create_empty();
|
||||
this->key = key;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
botan_rsa_private_key_t *botan_rsa_private_key_gen(key_type_t type,
|
||||
va_list args)
|
||||
{
|
||||
private_botan_rsa_private_key_t *this;
|
||||
botan_rng_t rng;
|
||||
u_int key_size = 0;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (va_arg(args, builder_part_t))
|
||||
{
|
||||
case BUILD_KEY_SIZE:
|
||||
key_size = va_arg(args, u_int);
|
||||
continue;
|
||||
case BUILD_END:
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!key_size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (botan_rng_init(&rng, "system"))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
this = create_empty();
|
||||
|
||||
if (botan_privkey_create_rsa(&this->key, rng, key_size))
|
||||
{
|
||||
botan_rng_destroy(rng);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
botan_rng_destroy(rng);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recover the primes from n, e and d using the algorithm described in
|
||||
* Appendix C of NIST SP 800-56B.
|
||||
*/
|
||||
static bool calculate_pq(botan_mp_t *n, botan_mp_t *e, botan_mp_t *d,
|
||||
botan_mp_t *p, botan_mp_t *q)
|
||||
{
|
||||
botan_mp_t k = NULL, one = NULL, r = NULL, zero = NULL, two = NULL;
|
||||
botan_mp_t n1 = NULL, x = NULL, y = NULL, g = NULL, rem = NULL;
|
||||
botan_rng_t rng = NULL;
|
||||
int i, t, j;
|
||||
bool success = FALSE;
|
||||
|
||||
if (botan_mp_init(&k) ||
|
||||
botan_mp_init(&one) ||
|
||||
botan_mp_set_from_int(one, 1))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* 1. k = d * e - 1 */
|
||||
if (botan_mp_mul(k, *d, *e) || botan_mp_sub(k, k, one))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* k must be even */
|
||||
if (!botan_mp_is_even(k))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* 2. k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */
|
||||
if (botan_mp_init(&r) ||
|
||||
botan_mp_set_from_mp(r, k))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (t = 0; !botan_mp_is_odd(r); t++)
|
||||
{
|
||||
if (botan_mp_rshift(r, r, 1))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* need 0 and n-1 below */
|
||||
if (botan_mp_init(&zero) ||
|
||||
botan_mp_init(&n1) ||
|
||||
botan_mp_sub(n1, *n, one))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (botan_mp_init(&g))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (botan_rng_init(&rng, "user"))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (botan_mp_init(&two))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (botan_mp_set_from_int(two, 2))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (botan_mp_init(&y) ||
|
||||
botan_mp_init(&x))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
/* 3a. generate a random integer g in the range [0, n-1] */
|
||||
if (botan_mp_rand_range(g, rng, zero, n1))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
/* 3b. y = g^r mod n */
|
||||
if (botan_mp_powmod(y, g, r, *n))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* 3c. If y = 1 or y = n – 1, try again */
|
||||
if (botan_mp_equal(y, one) || botan_mp_equal(y, n1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < t; j++)
|
||||
{
|
||||
/* x = y^2 mod n */
|
||||
if (botan_mp_powmod(x, y, two, *n))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* stop if x == 1 */
|
||||
if (botan_mp_equal(x, one))
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* retry with new g if x = n-1 */
|
||||
if (botan_mp_equal(x, n1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* let y = x */
|
||||
if (botan_mp_set_from_mp(y, x))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
/* 5. p = GCD(y – 1, n) and q = n/p */
|
||||
if (botan_mp_sub(y, y, one))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (botan_mp_init(p) ||
|
||||
botan_mp_gcd(*p, y, *n))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (botan_mp_init(q) ||
|
||||
botan_mp_init(&rem) ||
|
||||
botan_mp_div(*q, rem, *n, *p))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!botan_mp_is_zero(rem))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
error:
|
||||
if (!success)
|
||||
{
|
||||
botan_mp_destroy(*p);
|
||||
botan_mp_destroy(*q);
|
||||
}
|
||||
botan_rng_destroy(rng);
|
||||
botan_mp_destroy(k);
|
||||
botan_mp_destroy(one);
|
||||
botan_mp_destroy(r);
|
||||
botan_mp_destroy(zero);
|
||||
botan_mp_destroy(two);
|
||||
botan_mp_destroy(n1);
|
||||
botan_mp_destroy(x);
|
||||
botan_mp_destroy(y);
|
||||
botan_mp_destroy(g);
|
||||
botan_mp_destroy(rem);
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
botan_rsa_private_key_t *botan_rsa_private_key_load(key_type_t type,
|
||||
va_list args)
|
||||
{
|
||||
private_botan_rsa_private_key_t *this;
|
||||
chunk_t n, e, d, p, q, blob;
|
||||
|
||||
n = e = d = p = q = blob = chunk_empty;
|
||||
while (TRUE)
|
||||
{
|
||||
switch (va_arg(args, builder_part_t))
|
||||
{
|
||||
case BUILD_BLOB_ASN1_DER:
|
||||
blob = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_RSA_MODULUS:
|
||||
n = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_RSA_PUB_EXP:
|
||||
e = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_RSA_PRIV_EXP:
|
||||
d = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_RSA_PRIME1:
|
||||
p = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_RSA_PRIME2:
|
||||
q = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_RSA_EXP1:
|
||||
case BUILD_RSA_EXP2:
|
||||
case BUILD_RSA_COEFF:
|
||||
/* not required for botan */
|
||||
va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_END:
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == KEY_ANY && !blob.ptr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (blob.ptr)
|
||||
{
|
||||
this = create_empty();
|
||||
|
||||
if (botan_privkey_load_rsa_pkcs1(&this->key, blob.ptr, blob.len))
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
if (n.ptr && e.ptr && d.ptr)
|
||||
{
|
||||
botan_mp_t n_mp, e_mp, d_mp, p_mp, q_mp;
|
||||
|
||||
if (!chunk_to_botan_mp(n, &n_mp))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!chunk_to_botan_mp(e, &e_mp))
|
||||
{
|
||||
botan_mp_destroy(n_mp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!chunk_to_botan_mp(d, &d_mp))
|
||||
{
|
||||
botan_mp_destroy(n_mp);
|
||||
botan_mp_destroy(e_mp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (p.ptr && q.ptr)
|
||||
{
|
||||
if (!chunk_to_botan_mp(p, &p_mp))
|
||||
{
|
||||
botan_mp_destroy(n_mp);
|
||||
botan_mp_destroy(e_mp);
|
||||
botan_mp_destroy(d_mp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!chunk_to_botan_mp(q, &q_mp))
|
||||
{
|
||||
botan_mp_destroy(n_mp);
|
||||
botan_mp_destroy(e_mp);
|
||||
botan_mp_destroy(d_mp);
|
||||
botan_mp_destroy(p_mp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* calculate p,q from n, e, d */
|
||||
if (!calculate_pq(&n_mp, &e_mp, &d_mp, &p_mp, &q_mp))
|
||||
{
|
||||
botan_mp_destroy(n_mp);
|
||||
botan_mp_destroy(e_mp);
|
||||
botan_mp_destroy(d_mp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
botan_mp_destroy(n_mp);
|
||||
botan_mp_destroy(d_mp);
|
||||
|
||||
this = create_empty();
|
||||
|
||||
if (botan_privkey_load_rsa(&this->key, p_mp, q_mp, e_mp))
|
||||
{
|
||||
botan_mp_destroy(e_mp);
|
||||
botan_mp_destroy(p_mp);
|
||||
botan_mp_destroy(q_mp);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
botan_mp_destroy(e_mp);
|
||||
botan_mp_destroy(p_mp);
|
||||
botan_mp_destroy(q_mp);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup botan_rsa_private_key botan_rsa_private_key
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_RSA_PRIVATE_KEY_H_
|
||||
#define BOTAN_RSA_PRIVATE_KEY_H_
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
#include <credentials/builder.h>
|
||||
#include <credentials/keys/private_key.h>
|
||||
|
||||
typedef struct botan_rsa_private_key_t botan_rsa_private_key_t;
|
||||
|
||||
/**
|
||||
* private_key_t implementation of RSA algorithm using Botan.
|
||||
*/
|
||||
struct botan_rsa_private_key_t {
|
||||
|
||||
/**
|
||||
* Implements private_key_t interface
|
||||
*/
|
||||
private_key_t key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a RSA private key using Botan.
|
||||
*
|
||||
* Accepts the BUILD_KEY_SIZE argument.
|
||||
*
|
||||
* @param type type of the key, must be KEY_RSA
|
||||
* @param args builder_part_t argument list
|
||||
* @return generated key, NULL on failure
|
||||
*/
|
||||
botan_rsa_private_key_t *botan_rsa_private_key_gen(key_type_t type,
|
||||
va_list args);
|
||||
|
||||
/**
|
||||
* Load a RSA private key using Botan.
|
||||
*
|
||||
* Accepts a BUILD_BLOB_ASN1_DER argument.
|
||||
*
|
||||
* @param type type of the key, must be KEY_RSA
|
||||
* @param args builder_part_t argument list
|
||||
* @return loaded key, NULL on failure
|
||||
*/
|
||||
botan_rsa_private_key_t *botan_rsa_private_key_load(key_type_t type,
|
||||
va_list args);
|
||||
|
||||
/**
|
||||
* Load a RSA private key by adopting a botan_privkey_t object.
|
||||
*
|
||||
* @param key private key object (adopted)
|
||||
* @return loaded key, NULL on failure
|
||||
*/
|
||||
botan_rsa_private_key_t *botan_rsa_private_key_adopt(botan_privkey_t key);
|
||||
|
||||
#endif /** BOTAN_RSA_PRIVATE_KEY_H_ @}*/
|
|
@ -0,0 +1,395 @@
|
|||
/*
|
||||
* 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_rsa_public_key.h"
|
||||
|
||||
#include <botan/build.h>
|
||||
|
||||
#ifdef BOTAN_HAS_RSA
|
||||
|
||||
#include "botan_util.h"
|
||||
|
||||
#include <asn1/oid.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/asn1_parser.h>
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
typedef struct private_botan_rsa_public_key_t private_botan_rsa_public_key_t;
|
||||
|
||||
/**
|
||||
* Private data structure with signing context.
|
||||
*/
|
||||
struct private_botan_rsa_public_key_t {
|
||||
|
||||
/**
|
||||
* Public interface for this signer
|
||||
*/
|
||||
botan_rsa_public_key_t public;
|
||||
|
||||
/**
|
||||
* Botan public key
|
||||
*/
|
||||
botan_pubkey_t key;
|
||||
|
||||
/**
|
||||
* Reference counter
|
||||
*/
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
/**
|
||||
* Verify RSA signature
|
||||
*/
|
||||
static bool verify_rsa_signature(private_botan_rsa_public_key_t *this,
|
||||
const char* hash_and_padding, chunk_t data,
|
||||
chunk_t signature)
|
||||
{
|
||||
botan_pk_op_verify_t verify_op;
|
||||
bool valid = FALSE;
|
||||
|
||||
if (botan_pk_op_verify_create(&verify_op, this->key, hash_and_padding, 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_pk_op_verify_update(verify_op, data.ptr, data.len))
|
||||
{
|
||||
botan_pk_op_verify_destroy(verify_op);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
valid = !botan_pk_op_verify_finish(verify_op, signature.ptr, signature.len);
|
||||
|
||||
botan_pk_op_verify_destroy(verify_op);
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verification of an EMSA PSS signature described in PKCS#1
|
||||
*/
|
||||
static bool verify_emsa_pss_signature(private_botan_rsa_public_key_t *this,
|
||||
rsa_pss_params_t *params, chunk_t data,
|
||||
chunk_t signature)
|
||||
{
|
||||
const char *hash;
|
||||
char hash_and_padding[BUF_LEN];
|
||||
|
||||
if (!params)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* botan currently does not support passing the mgf1 hash */
|
||||
if (params->hash != params->mgf1_hash)
|
||||
{
|
||||
DBG1(DBG_LIB, "passing mgf1 hash not supported via botan");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hash = botan_get_hash(params->hash);
|
||||
if (!hash)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
|
||||
{
|
||||
snprintf(hash_and_padding, sizeof(hash_and_padding),
|
||||
"EMSA-PSS(%s,MGF1,%u)", hash, params->salt_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(hash_and_padding, sizeof(hash_and_padding),
|
||||
"EMSA-PSS(%s,MGF1)", hash);
|
||||
}
|
||||
return verify_rsa_signature(this, hash_and_padding, data, signature);
|
||||
}
|
||||
|
||||
METHOD(public_key_t, get_type, key_type_t,
|
||||
private_botan_rsa_public_key_t *this)
|
||||
{
|
||||
return KEY_RSA;
|
||||
}
|
||||
|
||||
METHOD(public_key_t, verify, bool,
|
||||
private_botan_rsa_public_key_t *this, signature_scheme_t scheme,
|
||||
void *params, chunk_t data, chunk_t signature)
|
||||
{
|
||||
switch (scheme)
|
||||
{
|
||||
case SIGN_RSA_EMSA_PKCS1_NULL:
|
||||
return verify_rsa_signature(this, "EMSA_PKCS1(Raw)", data,
|
||||
signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA1:
|
||||
return verify_rsa_signature(this, "EMSA_PKCS1(SHA-1)", data,
|
||||
signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA2_224:
|
||||
return verify_rsa_signature(this, "EMSA_PKCS1(SHA-224)",
|
||||
data, signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA2_256:
|
||||
return verify_rsa_signature(this, "EMSA_PKCS1(SHA-256)",
|
||||
data, signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA2_384:
|
||||
return verify_rsa_signature(this, "EMSA_PKCS1(SHA-384)",
|
||||
data, signature);
|
||||
case SIGN_RSA_EMSA_PKCS1_SHA2_512:
|
||||
return verify_rsa_signature(this, "EMSA_PKCS1(SHA-512)",
|
||||
data, signature);
|
||||
case SIGN_RSA_EMSA_PSS:
|
||||
return verify_emsa_pss_signature(this, params, data, signature);
|
||||
default:
|
||||
DBG1(DBG_LIB, "signature scheme %N not supported via botan",
|
||||
signature_scheme_names, scheme);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(public_key_t, encrypt, bool,
|
||||
private_botan_rsa_public_key_t *this, encryption_scheme_t scheme,
|
||||
chunk_t plain, chunk_t *crypto)
|
||||
{
|
||||
botan_pk_op_encrypt_t encrypt_op;
|
||||
botan_rng_t rng;
|
||||
const char* padding;
|
||||
|
||||
switch (scheme)
|
||||
{
|
||||
case ENCRYPT_RSA_PKCS1:
|
||||
padding = "PKCS1v15";
|
||||
break;
|
||||
case ENCRYPT_RSA_OAEP_SHA1:
|
||||
padding = "OAEP(SHA-1)";
|
||||
break;
|
||||
case ENCRYPT_RSA_OAEP_SHA224:
|
||||
padding = "OAEP(SHA-224)";
|
||||
break;
|
||||
case ENCRYPT_RSA_OAEP_SHA256:
|
||||
padding = "OAEP(SHA-256)";
|
||||
break;
|
||||
case ENCRYPT_RSA_OAEP_SHA384:
|
||||
padding = "OAEP(SHA-384)";
|
||||
break;
|
||||
case ENCRYPT_RSA_OAEP_SHA512:
|
||||
padding = "OAEP(SHA-512)";
|
||||
break;
|
||||
default:
|
||||
DBG1(DBG_LIB, "encryption scheme %N not supported via botan",
|
||||
encryption_scheme_names, scheme);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_rng_init(&rng, "user"))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_pk_op_encrypt_create(&encrypt_op, this->key, padding, 0))
|
||||
{
|
||||
botan_rng_destroy(rng);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
crypto->len = 0;
|
||||
if (botan_pk_op_encrypt_output_length(encrypt_op, plain.len, &crypto->len))
|
||||
{
|
||||
botan_rng_destroy(rng);
|
||||
botan_pk_op_encrypt_destroy(encrypt_op);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*crypto = chunk_alloc(crypto->len);
|
||||
if (botan_pk_op_encrypt(encrypt_op, rng, crypto->ptr, &crypto->len,
|
||||
plain.ptr, plain.len))
|
||||
{
|
||||
chunk_free(crypto);
|
||||
botan_rng_destroy(rng);
|
||||
botan_pk_op_encrypt_destroy(encrypt_op);
|
||||
return FALSE;
|
||||
}
|
||||
botan_rng_destroy(rng);
|
||||
botan_pk_op_encrypt_destroy(encrypt_op);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(public_key_t, get_keysize, int,
|
||||
private_botan_rsa_public_key_t *this)
|
||||
{
|
||||
botan_mp_t n;
|
||||
size_t bits = 0;
|
||||
|
||||
if (botan_mp_init(&n))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (botan_pubkey_rsa_get_n(n, this->key) ||
|
||||
botan_mp_num_bits(n, &bits))
|
||||
{
|
||||
botan_mp_destroy(n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
botan_mp_destroy(n);
|
||||
return bits;
|
||||
}
|
||||
|
||||
METHOD(public_key_t, get_fingerprint, bool,
|
||||
private_botan_rsa_public_key_t *this, cred_encoding_type_t type,
|
||||
chunk_t *fp)
|
||||
{
|
||||
return botan_get_fingerprint(this->key, this, type, fp);
|
||||
}
|
||||
|
||||
METHOD(public_key_t, get_encoding, bool,
|
||||
private_botan_rsa_public_key_t *this, cred_encoding_type_t type,
|
||||
chunk_t *encoding)
|
||||
{
|
||||
return botan_get_encoding(this->key, type, encoding);
|
||||
}
|
||||
|
||||
METHOD(public_key_t, get_ref, public_key_t*,
|
||||
private_botan_rsa_public_key_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public.key;
|
||||
}
|
||||
|
||||
METHOD(public_key_t, destroy, void,
|
||||
private_botan_rsa_public_key_t *this)
|
||||
{
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
lib->encoding->clear_cache(lib->encoding, this);
|
||||
botan_pubkey_destroy(this->key);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal generic constructor
|
||||
*/
|
||||
static private_botan_rsa_public_key_t *create_empty()
|
||||
{
|
||||
private_botan_rsa_public_key_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.key = {
|
||||
.get_type = _get_type,
|
||||
.verify = _verify,
|
||||
.encrypt = _encrypt,
|
||||
.equals = public_key_equals,
|
||||
.get_keysize = _get_keysize,
|
||||
.get_fingerprint = _get_fingerprint,
|
||||
.has_fingerprint = public_key_has_fingerprint,
|
||||
.get_encoding = _get_encoding,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
botan_rsa_public_key_t *botan_rsa_public_key_adopt(botan_pubkey_t key)
|
||||
{
|
||||
private_botan_rsa_public_key_t *this;
|
||||
|
||||
this = create_empty();
|
||||
this->key = key;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
botan_rsa_public_key_t *botan_rsa_public_key_load(key_type_t type,
|
||||
va_list args)
|
||||
{
|
||||
private_botan_rsa_public_key_t *this = NULL;
|
||||
chunk_t n, e;
|
||||
|
||||
n = e = chunk_empty;
|
||||
while (TRUE)
|
||||
{
|
||||
switch (va_arg(args, builder_part_t))
|
||||
{
|
||||
case BUILD_RSA_MODULUS:
|
||||
n = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_RSA_PUB_EXP:
|
||||
e = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_END:
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (n.ptr && e.ptr && type == KEY_RSA)
|
||||
{
|
||||
botan_mp_t mp_n, mp_e;
|
||||
|
||||
if (!chunk_to_botan_mp(n, &mp_n))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!chunk_to_botan_mp(e, &mp_e))
|
||||
{
|
||||
botan_mp_destroy(mp_n);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
this = create_empty();
|
||||
|
||||
if (botan_pubkey_load_rsa(&this->key, mp_n, mp_e))
|
||||
{
|
||||
botan_mp_destroy(mp_n);
|
||||
botan_mp_destroy(mp_e);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
botan_mp_destroy(mp_n);
|
||||
botan_mp_destroy(mp_e);
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup botan_rsa_public_key botan_rsa_public_key
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_RSA_PUBLIC_KEY_H_
|
||||
#define BOTAN_RSA_PUBLIC_KEY_H_
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
#include <credentials/keys/public_key.h>
|
||||
|
||||
typedef struct botan_rsa_public_key_t botan_rsa_public_key_t;
|
||||
|
||||
/**
|
||||
* public_key_t implementation of RSA algorithm using Botan.
|
||||
*/
|
||||
struct botan_rsa_public_key_t {
|
||||
|
||||
/**
|
||||
* Implements the public_key_t interface
|
||||
*/
|
||||
public_key_t key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a RSA public key using Botan.
|
||||
*
|
||||
* Accepts a BUILD_RSA_MODULUS/BUILD_RSA_PUB_EXP arguments.
|
||||
*
|
||||
* @param type type of the key, must be KEY_RSA
|
||||
* @param args builder_part_t argument list
|
||||
* @return loaded key, NULL on failure
|
||||
*/
|
||||
botan_rsa_public_key_t *botan_rsa_public_key_load(key_type_t type,
|
||||
va_list args);
|
||||
|
||||
/**
|
||||
* Load a RSA public key by adopting a botan_pubkey_t object.
|
||||
*
|
||||
* @param key public key object (adopted)
|
||||
* @return loaded key, NULL on failure
|
||||
*/
|
||||
botan_rsa_public_key_t *botan_rsa_public_key_adopt(botan_pubkey_t key);
|
||||
|
||||
#endif /** BOTAN_RSA_PUBLIC_KEY_H_ @}*/
|
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* 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->len = 0;
|
||||
if (botan_pubkey_fingerprint(pubkey, "SHA-1", NULL, &fp->len)
|
||||
!= BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*fp = chunk_alloc(fp->len);
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup botan_util botan_util
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_UTIL_H_
|
||||
#define BOTAN_UTIL_H_
|
||||
|
||||
#include <library.h>
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
/**
|
||||
* Converts chunk_t to botan_mp_t.
|
||||
*
|
||||
* @param value chunk to convert
|
||||
* @param mp allocated botan_mp_t
|
||||
* @return TRUE if conversion successful
|
||||
*/
|
||||
bool chunk_to_botan_mp(chunk_t value, botan_mp_t *mp);
|
||||
|
||||
/**
|
||||
* Get the Botan string identifier for the given hash algorithm.
|
||||
*
|
||||
* @param hash hash algorithm
|
||||
* @return Botan string identifier, NULL if not found
|
||||
*/
|
||||
const char *botan_get_hash(hash_algorithm_t hash);
|
||||
|
||||
/**
|
||||
* Get the encoding of a botan_pubkey_t.
|
||||
*
|
||||
* @param pubkey public key object
|
||||
* @param type encoding type
|
||||
* @param encoding allocated encoding
|
||||
* @return TRUE if encoding successful
|
||||
*/
|
||||
bool botan_get_encoding(botan_pubkey_t pubkey, cred_encoding_type_t type,
|
||||
chunk_t *encoding);
|
||||
|
||||
/**
|
||||
* Get the encoding of a botan_privkey_t.
|
||||
*
|
||||
* @param key private key object
|
||||
* @param type encoding type
|
||||
* @param encoding allocated encoding
|
||||
* @return TRUE if encoding successful
|
||||
*/
|
||||
bool botan_get_privkey_encoding(botan_privkey_t key, cred_encoding_type_t type,
|
||||
chunk_t *encoding);
|
||||
|
||||
/**
|
||||
* Get the fingerprint of a botan_pubkey_t.
|
||||
*
|
||||
* @param pubkey public key object
|
||||
* @param cache key to use for caching, NULL to not cache
|
||||
* @param type fingerprint type
|
||||
* @param fp allocated fingerprint
|
||||
* @return TRUE if fingerprinting successful
|
||||
*/
|
||||
bool botan_get_fingerprint(botan_pubkey_t pubkey, void *cache,
|
||||
cred_encoding_type_t type, chunk_t *fp);
|
||||
|
||||
/**
|
||||
* Sign the given data using the provided key with the specified signature
|
||||
* scheme (hash/padding).
|
||||
*
|
||||
* @param key private key object
|
||||
* @param scheme hash/padding algorithm
|
||||
* @param data data to sign
|
||||
* @param signature allocated signature
|
||||
* @return TRUE if signature successfully created
|
||||
*/
|
||||
bool botan_get_signature(botan_privkey_t key, const char *scheme,
|
||||
chunk_t data, chunk_t *signature);
|
||||
|
||||
/**
|
||||
* Do the Diffie-Hellman key derivation using the given private key and public
|
||||
* value.
|
||||
*
|
||||
* Note that the public value is not verified in this function.
|
||||
*
|
||||
* @param key DH private key
|
||||
* @param pub other's public value
|
||||
* @param secret the derived secret (allocated on success)
|
||||
* @return TRUE if derivation was successful
|
||||
*/
|
||||
bool botan_dh_key_derivation(botan_privkey_t key, chunk_t pub, chunk_t *secret);
|
||||
|
||||
#endif /** BOTAN_UTIL_H_ @}*/
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Tobias Brunner
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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_keys.h"
|
||||
#include "botan_ec_public_key.h"
|
||||
#include "botan_ec_private_key.h"
|
||||
#include "botan_rsa_public_key.h"
|
||||
#include "botan_rsa_private_key.h"
|
||||
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/oid.h>
|
||||
|
||||
/**
|
||||
* Get the algorithm name of a public key
|
||||
*/
|
||||
static char *get_algo_name(botan_pubkey_t pubkey)
|
||||
{
|
||||
char *name;
|
||||
size_t len = 0;
|
||||
|
||||
if (botan_pubkey_algo_name(pubkey, NULL, &len)
|
||||
!= BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
name = malloc(len);
|
||||
if (botan_pubkey_algo_name(pubkey, name, &len))
|
||||
{
|
||||
free(name);
|
||||
return NULL;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
public_key_t *botan_public_key_load(key_type_t type, va_list args)
|
||||
{
|
||||
public_key_t *this = NULL;
|
||||
botan_pubkey_t pubkey;
|
||||
chunk_t blob = chunk_empty;
|
||||
botan_rng_t rng;
|
||||
char *name;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (va_arg(args, builder_part_t))
|
||||
{
|
||||
case BUILD_BLOB_ASN1_DER:
|
||||
blob = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_END:
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (botan_rng_init(&rng, "user"))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (botan_pubkey_load(&pubkey, blob.ptr, blob.len))
|
||||
{
|
||||
botan_rng_destroy(rng);
|
||||
return NULL;
|
||||
}
|
||||
if (botan_pubkey_check_key(pubkey, rng, BOTAN_CHECK_KEY_EXPENSIVE_TESTS))
|
||||
{
|
||||
DBG1(DBG_LIB, "public key failed key checks");
|
||||
botan_pubkey_destroy(pubkey);
|
||||
botan_rng_destroy(rng);
|
||||
return NULL;
|
||||
}
|
||||
botan_rng_destroy(rng);
|
||||
|
||||
name = get_algo_name(pubkey);
|
||||
if (!name)
|
||||
{
|
||||
botan_pubkey_destroy(pubkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (streq(name, "RSA") && (type == KEY_ANY || type == KEY_RSA))
|
||||
{
|
||||
this = (public_key_t*)botan_rsa_public_key_adopt(pubkey);
|
||||
}
|
||||
else if (streq(name, "ECDSA") && (type == KEY_ANY || type == KEY_ECDSA))
|
||||
{
|
||||
this = (public_key_t*)botan_ec_public_key_adopt(pubkey);
|
||||
}
|
||||
else
|
||||
{
|
||||
botan_pubkey_destroy(pubkey);
|
||||
}
|
||||
free(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the curve OID from a PKCS#8 structure
|
||||
*/
|
||||
static int determine_ec_oid(chunk_t pkcs8)
|
||||
{
|
||||
int oid = OID_UNKNOWN;
|
||||
chunk_t inner, params = chunk_empty;
|
||||
|
||||
if (asn1_unwrap(&pkcs8, &pkcs8) == ASN1_SEQUENCE &&
|
||||
asn1_unwrap(&pkcs8, &inner) == ASN1_INTEGER &&
|
||||
asn1_parse_integer_uint64(inner) == 0 &&
|
||||
asn1_parse_algorithmIdentifier(pkcs8, 0, ¶ms) == OID_EC_PUBLICKEY &&
|
||||
params.len &&
|
||||
asn1_unwrap(¶ms, ¶ms) == ASN1_OID)
|
||||
{
|
||||
oid = asn1_known_oid(params);
|
||||
}
|
||||
return oid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
private_key_t *botan_private_key_load(key_type_t type, va_list args)
|
||||
{
|
||||
private_key_t *this = NULL;
|
||||
botan_privkey_t key;
|
||||
botan_pubkey_t pubkey;
|
||||
chunk_t blob = chunk_empty;
|
||||
botan_rng_t rng;
|
||||
char *name;
|
||||
int oid;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (va_arg(args, builder_part_t))
|
||||
{
|
||||
case BUILD_BLOB_ASN1_DER:
|
||||
blob = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_END:
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (botan_rng_init(&rng, "user"))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (botan_privkey_load(&key, rng, blob.ptr, blob.len, NULL))
|
||||
{
|
||||
botan_rng_destroy(rng);
|
||||
return NULL;
|
||||
}
|
||||
botan_rng_destroy(rng);
|
||||
|
||||
if (botan_privkey_export_pubkey(&pubkey, key))
|
||||
{
|
||||
botan_privkey_destroy(key);
|
||||
return NULL;
|
||||
}
|
||||
name = get_algo_name(pubkey);
|
||||
botan_pubkey_destroy(pubkey);
|
||||
if (!name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (streq(name, "RSA") && (type == KEY_ANY || type == KEY_RSA))
|
||||
{
|
||||
this = (private_key_t*)botan_rsa_private_key_adopt(key);
|
||||
}
|
||||
else if (streq(name, "ECDSA") && (type == KEY_ANY || type == KEY_ECDSA))
|
||||
{
|
||||
oid = determine_ec_oid(blob);
|
||||
if (oid != OID_UNKNOWN)
|
||||
{
|
||||
this = (private_key_t*)botan_ec_private_key_adopt(key, oid);
|
||||
}
|
||||
}
|
||||
if (!this)
|
||||
{
|
||||
botan_privkey_destroy(key);
|
||||
}
|
||||
free(name);
|
||||
return this;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Tobias Brunner
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper functions to load public and private keys in a generic way
|
||||
*
|
||||
* @defgroup botan_util_keys botan_util_keys
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_UTIL_KEYS_H_
|
||||
#define BOTAN_UTIL_KEYS_H_
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
#include <credentials/keys/public_key.h>
|
||||
#include <credentials/keys/private_key.h>
|
||||
|
||||
/**
|
||||
* Load a public key in subjectPublicKeyInfo encoding
|
||||
*
|
||||
* Accepts a BUILD_BLOB_ASN1_DER argument.
|
||||
*
|
||||
* @param type type of the key
|
||||
* @param args builder_part_t argument list
|
||||
* @return loaded key, NULL on failure
|
||||
*/
|
||||
public_key_t *botan_public_key_load(key_type_t type, va_list args);
|
||||
|
||||
/**
|
||||
* Load a private key in PKCS#8 encoding
|
||||
*
|
||||
* Accepts a BUILD_BLOB_ASN1_DER argument.
|
||||
*
|
||||
* @param type type of the key
|
||||
* @param args builder_part_t argument list
|
||||
* @return loaded key, NULL on failure
|
||||
*/
|
||||
private_key_t *botan_private_key_load(key_type_t type, va_list args);
|
||||
|
||||
#endif /** BOTAN_UTIL_KEYS_H_ @}*/
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Tobias Brunner
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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_x25519.h"
|
||||
|
||||
#include <botan/build.h>
|
||||
|
||||
#ifdef BOTAN_HAS_X25519
|
||||
|
||||
#include "botan_util.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <botan/ffi.h>
|
||||
|
||||
typedef struct private_diffie_hellman_t private_diffie_hellman_t;
|
||||
|
||||
/**
|
||||
* Private data
|
||||
*/
|
||||
struct private_diffie_hellman_t {
|
||||
|
||||
/**
|
||||
* Public interface
|
||||
*/
|
||||
diffie_hellman_t public;
|
||||
|
||||
/**
|
||||
* Private key
|
||||
*/
|
||||
botan_privkey_t key;
|
||||
|
||||
/**
|
||||
* Shared secret
|
||||
*/
|
||||
chunk_t shared_secret;
|
||||
};
|
||||
|
||||
METHOD(diffie_hellman_t, set_other_public_value, bool,
|
||||
private_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
if (!diffie_hellman_verify_value(CURVE_25519, value))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
chunk_clear(&this->shared_secret);
|
||||
|
||||
return botan_dh_key_derivation(this->key, value, &this->shared_secret);
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_my_public_value, bool,
|
||||
private_diffie_hellman_t *this, chunk_t *value)
|
||||
{
|
||||
value->len = 0;
|
||||
if (botan_pk_op_key_agreement_export_public(this->key, NULL, &value->len)
|
||||
!= BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*value = chunk_alloc(value->len);
|
||||
if (botan_pk_op_key_agreement_export_public(this->key, value->ptr,
|
||||
&value->len))
|
||||
{
|
||||
chunk_free(value);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, set_private_value, bool,
|
||||
private_diffie_hellman_t *this, chunk_t value)
|
||||
{
|
||||
if (value.len != 32)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
chunk_clear(&this->shared_secret);
|
||||
|
||||
if (botan_privkey_destroy(this->key))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (botan_privkey_load_x25519(&this->key, value.ptr))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_shared_secret, bool,
|
||||
private_diffie_hellman_t *this, chunk_t *secret)
|
||||
{
|
||||
if (!this->shared_secret.len)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
*secret = chunk_clone(this->shared_secret);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
|
||||
private_diffie_hellman_t *this)
|
||||
{
|
||||
return CURVE_25519;
|
||||
}
|
||||
|
||||
METHOD(diffie_hellman_t, destroy, void,
|
||||
private_diffie_hellman_t *this)
|
||||
{
|
||||
botan_privkey_destroy(this->key);
|
||||
chunk_clear(&this->shared_secret);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
diffie_hellman_t *botan_x25519_create(diffie_hellman_group_t group)
|
||||
{
|
||||
private_diffie_hellman_t *this;
|
||||
botan_rng_t rng;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_shared_secret = _get_shared_secret,
|
||||
.set_other_public_value = _set_other_public_value,
|
||||
.get_my_public_value = _get_my_public_value,
|
||||
.set_private_value = _set_private_value,
|
||||
.get_dh_group = _get_dh_group,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
);
|
||||
|
||||
if (botan_rng_init(&rng, "user"))
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (botan_privkey_create_ecdh(&this->key, rng, "curve25519"))
|
||||
{
|
||||
DBG1(DBG_LIB, "x25519 private key generation failed");
|
||||
botan_rng_destroy(rng);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
botan_rng_destroy(rng);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Tobias Brunner
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup botan_x25519 botan_x25519
|
||||
* @{ @ingroup botan_p
|
||||
*/
|
||||
|
||||
#ifndef BOTAN_X25519_H_
|
||||
#define BOTAN_X25519_H_
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* Creates a new X25519 implementation using Botan.
|
||||
*
|
||||
* @param group DH group, must be CURVE_25519
|
||||
* @return object, NULL if not supported
|
||||
*/
|
||||
diffie_hellman_t *botan_x25519_create(diffie_hellman_group_t group);
|
||||
|
||||
#endif /** BOTAN_X25519_H_ @}*/
|
|
@ -195,8 +195,8 @@ METHOD(diffie_hellman_t, destroy, void,
|
|||
/*
|
||||
* Generic internal constructor
|
||||
*/
|
||||
gcrypt_dh_t *create_generic(diffie_hellman_group_t group, size_t exp_len,
|
||||
chunk_t g, chunk_t p)
|
||||
static gcrypt_dh_t *create_generic(diffie_hellman_group_t group, size_t exp_len,
|
||||
chunk_t g, chunk_t p)
|
||||
{
|
||||
private_gcrypt_dh_t *this;
|
||||
gcry_error_t err;
|
||||
|
|
|
@ -271,7 +271,8 @@ end:
|
|||
* }
|
||||
*
|
||||
* While the parameters and publicKey fields are OPTIONAL, RFC 5915 says that
|
||||
* parameters MUST be included and publicKey SHOULD be.
|
||||
* parameters MUST be included (an errata clarifies this, so this is only the
|
||||
* case for plain private keys, not encoded in PKCS#8) and publicKey SHOULD be.
|
||||
*/
|
||||
static bool is_ec_private_key(chunk_t blob)
|
||||
{
|
||||
|
@ -281,7 +282,8 @@ static bool is_ec_private_key(chunk_t blob)
|
|||
asn1_parse_integer_uint64(data) == 1 &&
|
||||
asn1_unwrap(&blob, &data) == ASN1_OCTET_STRING &&
|
||||
asn1_unwrap(&blob, &data) == ASN1_CONTEXT_C_0 &&
|
||||
asn1_unwrap(&blob, &data) == ASN1_CONTEXT_C_1;
|
||||
asn1_unwrap(&data, &data) == ASN1_OID &&
|
||||
(!blob.len || (asn1_unwrap(&blob, &data) == ASN1_CONTEXT_C_1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -303,4 +303,5 @@ TEST_VECTOR_DH(ecp224bp)
|
|||
TEST_VECTOR_DH(ecp256bp)
|
||||
TEST_VECTOR_DH(ecp384bp)
|
||||
TEST_VECTOR_DH(ecp512bp)
|
||||
TEST_VECTOR_DH(curve25519)
|
||||
TEST_VECTOR_DH(curve25519_1)
|
||||
TEST_VECTOR_DH(curve25519_2)
|
||||
|
|
|
@ -16,10 +16,9 @@
|
|||
#include <crypto/crypto_tester.h>
|
||||
|
||||
/**
|
||||
* From RFC 8031
|
||||
* From RFC 8037
|
||||
*/
|
||||
|
||||
dh_test_vector_t curve25519 = {
|
||||
dh_test_vector_t curve25519_1 = {
|
||||
.group = CURVE_25519, .priv_len = 32, .pub_len = 32, .shared_len = 32,
|
||||
.priv_a = "\x77\x07\x6d\x0a\x73\x18\xa5\x7d\x3c\x16\xc1\x72\x51\xb2\x66\x45"
|
||||
"\xdf\x4c\x2f\x87\xeb\xc0\x99\x2a\xb1\x77\xfb\xa5\x1d\xb9\x2c\x2a",
|
||||
|
@ -32,3 +31,20 @@ dh_test_vector_t curve25519 = {
|
|||
.shared = "\x4a\x5d\x9d\x5b\xa4\xce\x2d\xe1\x72\x8e\x3b\xf4\x80\x35\x0f\x25"
|
||||
"\xe0\x7e\x21\xc9\x47\xd1\x9e\x33\x76\xf0\x9b\x3c\x1e\x16\x17\x42",
|
||||
};
|
||||
|
||||
/**
|
||||
* From RFC 8031
|
||||
*/
|
||||
dh_test_vector_t curve25519_2 = {
|
||||
.group = CURVE_25519, .priv_len = 32, .pub_len = 32, .shared_len = 32,
|
||||
.priv_a = "\x75\x1f\xb4\x30\x86\x55\xb4\x76\xb6\x78\x9b\x73\x25\xf9\xea\x8c"
|
||||
"\xdd\xd1\x6a\x58\x53\x3f\xf6\xd9\xe6\x00\x09\x46\x4a\x5f\x9d\x94",
|
||||
.priv_b = "\x0a\x54\x64\x52\x53\x29\x0d\x60\xdd\xad\xd0\xe0\x30\xba\xcd\x9e"
|
||||
"\x55\x01\xef\xdc\x22\x07\x55\xa1\xe9\x78\xf1\xb8\x39\xa0\x56\x88",
|
||||
.pub_a = "\x48\xd5\xdd\xd4\x06\x12\x57\xba\x16\x6f\xa3\xf9\xbb\xdb\x74\xf1"
|
||||
"\xa4\xe8\x1c\x08\x93\x84\xfa\x77\xf7\x90\x70\x9f\x0d\xfb\xc7\x66",
|
||||
.pub_b = "\x0b\xe7\xc1\xf5\xaa\xd8\x7d\x7e\x44\x86\x62\x67\x32\x98\xa4\x43"
|
||||
"\x47\x8b\x85\x97\x45\x17\x9e\xaf\x56\x4c\x79\xc0\xef\x6e\xee\x25",
|
||||
.shared = "\xc7\x49\x50\x60\x7a\x12\x32\x7f\x32\x04\xd9\x4b\x68\x25\xbf\xb0"
|
||||
"\x68\xb7\xf8\x31\x9a\x9e\x37\x08\xed\x3d\x43\xce\x81\x30\xc9\x50",
|
||||
};
|
||||
|
|
|
@ -146,7 +146,7 @@ static void test_bad_sigs(public_key_t *pubkey)
|
|||
* RSA key sizes to test
|
||||
*/
|
||||
static int key_sizes[] = {
|
||||
768, 1024, 1536, 2048, 3072, 4096,
|
||||
1024, 1536, 2048, 3072, 4096,
|
||||
};
|
||||
|
||||
START_TEST(test_gen)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2013-2014 Tobias Brunner
|
||||
* Copyright (C) 2013-2018 Tobias Brunner
|
||||
* Copyright (C) 2006-2013 Martin Willi
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
|
@ -162,7 +162,12 @@ static spinlock_t *lock;
|
|||
/**
|
||||
* Is leak detection currently enabled?
|
||||
*/
|
||||
static bool enabled = FALSE;
|
||||
static bool enabled;
|
||||
|
||||
/**
|
||||
* Whether to report calls to free() with memory not allocated by us
|
||||
*/
|
||||
static bool ignore_unknown;
|
||||
|
||||
/**
|
||||
* Is leak detection disabled for the current thread?
|
||||
|
@ -609,6 +614,11 @@ static char *whitelist[] = {
|
|||
/* FHH IMCs and IMVs */
|
||||
"TNC_IMC_NotifyConnectionChange",
|
||||
"TNC_IMV_NotifyConnectionChange",
|
||||
/* Botan */
|
||||
"botan_public_key_load",
|
||||
"botan_privkey_create_ecdsa",
|
||||
"botan_privkey_create_ecdh",
|
||||
"botan_privkey_load_ecdh",
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -883,7 +893,7 @@ HOOK(void, free, void *ptr)
|
|||
return;
|
||||
}
|
||||
/* allow freeing of NULL */
|
||||
if (ptr == NULL)
|
||||
if (!ptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -894,21 +904,47 @@ HOOK(void, free, void *ptr)
|
|||
if (hdr->magic != MEMORY_HEADER_MAGIC ||
|
||||
tail->magic != MEMORY_TAIL_MAGIC)
|
||||
{
|
||||
bool bt = TRUE;
|
||||
|
||||
/* check if memory appears to be allocated by our hooks */
|
||||
if (has_hdr(hdr))
|
||||
{
|
||||
/* memory was allocated by our hooks but is corrupted */
|
||||
fprintf(stderr, "freeing corrupted memory (%p): "
|
||||
"header magic 0x%x, tail magic 0x%x:\n",
|
||||
ptr, hdr->magic, tail->magic);
|
||||
"%u bytes, header magic 0x%x, tail magic 0x%x:\n",
|
||||
ptr, hdr->bytes, hdr->magic, tail->magic);
|
||||
remove_hdr(hdr);
|
||||
|
||||
if (hdr->magic == MEMORY_HEADER_MAGIC)
|
||||
{ /* only access the old backtrace if header magic is valid */
|
||||
hdr->backtrace->log(hdr->backtrace, stderr, TRUE);
|
||||
hdr->backtrace->destroy(hdr->backtrace);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, " header magic invalid, ignore backtrace of "
|
||||
"allocation\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* memory was not allocated by our hooks */
|
||||
fprintf(stderr, "freeing invalid memory (%p)\n", ptr);
|
||||
/* just free this block of unknown memory */
|
||||
hdr = ptr;
|
||||
|
||||
if (ignore_unknown)
|
||||
{
|
||||
bt = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "freeing unknown memory (%p):\n", ptr);
|
||||
}
|
||||
}
|
||||
if (bt)
|
||||
{
|
||||
backtrace = backtrace_create(2);
|
||||
backtrace->log(backtrace, stderr, TRUE);
|
||||
backtrace->destroy(backtrace);
|
||||
}
|
||||
backtrace = backtrace_create(2);
|
||||
backtrace->log(backtrace, stderr, TRUE);
|
||||
backtrace->destroy(backtrace);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -916,12 +952,11 @@ HOOK(void, free, void *ptr)
|
|||
|
||||
hdr->backtrace->destroy(hdr->backtrace);
|
||||
|
||||
/* clear MAGIC, set mem to something remarkable */
|
||||
/* set mem to something remarkable */
|
||||
memset(hdr, MEMORY_FREE_PATTERN,
|
||||
sizeof(memory_header_t) + hdr->bytes + sizeof(memory_tail_t));
|
||||
|
||||
real_free(hdr);
|
||||
}
|
||||
real_free(hdr);
|
||||
enable_thread(before);
|
||||
}
|
||||
|
||||
|
@ -933,19 +968,19 @@ HOOK(void*, realloc, void *old, size_t bytes)
|
|||
memory_header_t *hdr;
|
||||
memory_tail_t *tail;
|
||||
backtrace_t *backtrace;
|
||||
bool before;
|
||||
bool before, have_backtrace = TRUE;
|
||||
|
||||
if (!enabled || thread_disabled->get(thread_disabled))
|
||||
{
|
||||
return real_realloc(old, bytes);
|
||||
}
|
||||
/* allow reallocation of NULL */
|
||||
if (old == NULL)
|
||||
if (!old)
|
||||
{
|
||||
return malloc(bytes);
|
||||
}
|
||||
/* handle zero size as a free() */
|
||||
if (bytes == 0)
|
||||
if (!bytes)
|
||||
{
|
||||
free(old);
|
||||
return NULL;
|
||||
|
@ -954,22 +989,64 @@ HOOK(void*, realloc, void *old, size_t bytes)
|
|||
hdr = old - sizeof(memory_header_t);
|
||||
tail = old + hdr->bytes;
|
||||
|
||||
remove_hdr(hdr);
|
||||
|
||||
before = enable_thread(FALSE);
|
||||
if (hdr->magic != MEMORY_HEADER_MAGIC ||
|
||||
tail->magic != MEMORY_TAIL_MAGIC)
|
||||
{
|
||||
fprintf(stderr, "reallocating invalid memory (%p):\n"
|
||||
"header magic 0x%x:\n", old, hdr->magic);
|
||||
backtrace = backtrace_create(2);
|
||||
backtrace->log(backtrace, stderr, TRUE);
|
||||
backtrace->destroy(backtrace);
|
||||
bool bt = TRUE;
|
||||
|
||||
/* check if memory appears to be allocated by our hooks */
|
||||
if (has_hdr(hdr))
|
||||
{
|
||||
fprintf(stderr, "reallocating corrupted memory (%p, %u bytes): "
|
||||
"%zu bytes, header magic 0x%x, tail magic 0x%x:\n",
|
||||
old, hdr->bytes, bytes, hdr->magic, tail->magic);
|
||||
remove_hdr(hdr);
|
||||
|
||||
if (hdr->magic == MEMORY_HEADER_MAGIC)
|
||||
{ /* only access header fields (backtrace, bytes) if header magic
|
||||
* is still valid */
|
||||
hdr->backtrace->log(hdr->backtrace, stderr, TRUE);
|
||||
memset(&tail->magic, MEMORY_ALLOC_PATTERN, sizeof(tail->magic));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, " header magic invalid, ignore backtrace of "
|
||||
"allocation\n");
|
||||
have_backtrace = FALSE;
|
||||
hdr->magic = MEMORY_HEADER_MAGIC;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* adopt this block of unknown memory */
|
||||
hdr = old;
|
||||
have_backtrace = FALSE;
|
||||
|
||||
if (ignore_unknown)
|
||||
{
|
||||
bt = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "reallocating unknown memory (%p): %zu bytes:\n",
|
||||
old, bytes);
|
||||
}
|
||||
}
|
||||
if (bt)
|
||||
{
|
||||
backtrace = backtrace_create(2);
|
||||
backtrace->log(backtrace, stderr, TRUE);
|
||||
backtrace->destroy(backtrace);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
remove_hdr(hdr);
|
||||
/* clear tail magic, allocate, set tail magic */
|
||||
memset(&tail->magic, MEMORY_ALLOC_PATTERN, sizeof(tail->magic));
|
||||
}
|
||||
|
||||
hdr = real_realloc(hdr,
|
||||
sizeof(memory_header_t) + bytes + sizeof(memory_tail_t));
|
||||
tail = ((void*)hdr) + bytes + sizeof(memory_header_t);
|
||||
|
@ -978,8 +1055,10 @@ HOOK(void*, realloc, void *old, size_t bytes)
|
|||
/* update statistics */
|
||||
hdr->bytes = bytes;
|
||||
|
||||
before = enable_thread(FALSE);
|
||||
hdr->backtrace->destroy(hdr->backtrace);
|
||||
if (have_backtrace)
|
||||
{
|
||||
hdr->backtrace->destroy(hdr->backtrace);
|
||||
}
|
||||
hdr->backtrace = backtrace_create(2);
|
||||
enable_thread(before);
|
||||
|
||||
|
@ -1022,6 +1101,7 @@ leak_detective_t *leak_detective_create()
|
|||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
ignore_unknown = getenv("LEAK_DETECTIVE_IGNORE_UNKNOWN") != NULL;
|
||||
|
||||
lock = spinlock_create();
|
||||
thread_disabled = thread_value_create(NULL);
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/make
|
||||
|
||||
PKG = botan
|
||||
SRC = https://github.com/randombit/$(PKG).git
|
||||
# will have to be changed to the 2.8.0 tag later
|
||||
REV = 1872f899716854927ecc68022fac318735be8824
|
||||
|
||||
NUM_CPUS := $(shell getconf _NPROCESSORS_ONLN)
|
||||
|
||||
# the first two are necessary due to LD, the others to reduce the build time
|
||||
CONFIG_OPTS = \
|
||||
--without-os-features=threads \
|
||||
--disable-modules=locking_allocator \
|
||||
--disable-modules=pkcs11,tls,x509,xmss \
|
||||
|
||||
all: install
|
||||
|
||||
$(PKG):
|
||||
git clone $(SRC) $(PKG)
|
||||
|
||||
.$(PKG)-cloned-$(REV): $(PKG)
|
||||
cd $(PKG) && git fetch && git checkout $(REV)
|
||||
@touch $@
|
||||
|
||||
.$(PKG)-built-$(REV): .$(PKG)-cloned-$(REV)
|
||||
cd $(PKG) && python ./configure.py $(CONFIG_OPTS) && make -j $(NUM_CPUS)
|
||||
@touch $@
|
||||
|
||||
install: .$(PKG)-built-$(REV)
|
||||
cd $(PKG) && make install && ldconfig
|
|
@ -62,6 +62,7 @@ CONFIG_OPTS = \
|
|||
--enable-sqlite \
|
||||
--enable-attr-sql \
|
||||
--enable-mediation \
|
||||
--enable-botan \
|
||||
--enable-openssl \
|
||||
--enable-blowfish \
|
||||
--enable-kernel-pfkey \
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
The roadwarrior <b>carol</b> and the gateway <b>moon</b> use the <b>botan</b>
|
||||
plugin based on the <b>Botan</b> library for all cryptographical functions whereas
|
||||
roadwarrior <b>dave</b> uses the default <b>strongSwan</b> cryptographical
|
||||
plugins. The authentication is based on <b>X.509 certificates</b>.
|
||||
<p/>
|
||||
Upon the successful establishment of the IPsec tunnels, the updown script
|
||||
automatically inserts iptables-based firewall rules that let pass the tunneled traffic.
|
||||
In order to test both tunnel and firewall, both <b>carol</b> and <b>dave</b> ping
|
||||
the client <b>alice</b> behind the gateway <b>moon</b>.
|
|
@ -0,0 +1,10 @@
|
|||
carol::swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.100 local-port=4500 local-id=carol@strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.100/32] remote-ts=\[10.1.0.0/16]::YES
|
||||
dave:: swanctl --list-sas --raw 2> /dev/null::home.*version=2 state=ESTABLISHED local-host=192.168.0.200 local-port=4500 local-id=dave@strongswan.org remote-host=192.168.0.1 remote-port=4500 remote-id=moon.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*home.*state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.200/32] remote-ts=\[10.1.0.0/16]::YES
|
||||
moon:: swanctl --list-sas --ike-id 1 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.100 remote-port=4500 remote-id=carol@strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=1 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.100/32]::YES
|
||||
moon:: swanctl --list-sas --ike-id 2 --raw 2> /dev/null::rw.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-port=4500 local-id=moon.strongswan.org remote-host=192.168.0.200 remote-port=4500 remote-id=dave@strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=MODP_3072.*child-sas.*net.*reqid=2 state=INSTALLED mode=TUNNEL.*ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[10.1.0.0/16] remote-ts=\[192.168.0.200/32]::YES
|
||||
alice::ping -c 1 192.168.0.100::64 bytes from 192.168.0.100: icmp_.eq=1::YES
|
||||
alice::ping -c 1 192.168.0.200::64 bytes from 192.168.0.200: icmp_.eq=1::YES
|
||||
moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
|
||||
moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
|
||||
moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES
|
||||
moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES
|
|
@ -0,0 +1,11 @@
|
|||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = botan pem x509 revocation constraints pubkey
|
||||
}
|
||||
|
||||
charon-systemd {
|
||||
load = nonce botan pem x509 revocation constraints pubkey curl kernel-netlink socket-default updown vici
|
||||
|
||||
rsa_pss = yes
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-128-CBC,7E1D40A7901772BA4D22AF58AA2DC76F
|
||||
|
||||
1jt4EsxtHvgpSLN8PA/kSVKgoAsBEBQb8RK6VGnZywMCnpJdLKdPisGGYKNPg53b
|
||||
/0AFBmQVE60M8icbSAIUrAtyKxaBkoc9A7ibNCjobi0UzXTm3GcZZ1EC4/lE9PQZ
|
||||
/2FbcPgQWN3kZraZDkeP9XBXl6PorES8xvQUxJ9pd4hL7/c28fIApGhEimkIZO8o
|
||||
Qb7bR2cNCLYQAR6PeDoqhV39gvWoh77wp1WB3tQVbkS6MI/xl3wY2QVdq3Sbszh+
|
||||
f6lDU/SZS8BU0f44FRoInPp0GasgJ7MCiuEIshjuNPa50QkMcnNJsSgVEuw2hjN6
|
||||
LvAXx7vPt9pKpQfnu7YSJUsXDYN6PyXt7sZ8hDqraYIcI6eMpEBaTpItPSV2eckv
|
||||
06KC24Oa66E1yufNFAY49S2OY+pJA0W5zmcCqCjdrfJ+wNQYKZpbrfGz4VRzlFJC
|
||||
e3VkmAFwA5rcZdlp/mU2XREy+TaWsHMnpL0NcMHGmsfkTgaJIkRWalrdxlNTeitr
|
||||
3boNHWk0ESyMcBYRpM3eNXsGpiYy93u0bhrPbnqJsV6miKqpbs1aBNjlJ9s1Y2fC
|
||||
sko5/v7uMjb5tLF3lWQZfTu+bYtpGxFrqHJjhd8yd4gL1cFi30JcjczhwRY3Dily
|
||||
c0BFekMGmPc1djn6tfIFu13X9xTxyidCpVaT9UGnOaQs9OF1u8XAnZDaQgPwjLiy
|
||||
UlOE8xQ60LrhWLD582FsFnZz56bZ+QOQRWDMsB8nJeqnFXKfcRlnr0qlG6lTfA8h
|
||||
XkK/qGpdVvivS+CpbhVP6ixdEfa91Rx4NjLj53LGqOYwFEkM/OAIuMJetBfx3v9T
|
||||
iQfv594KE32nv9besnKlmJr2cGQWBYg1pUOtFj/aZ00yuXacv8qwzbrt4xGGDYGO
|
||||
Aj5Yf93UEcVkTySO1xJ1yiC6GJv1lLm0i5StwykHypxFijKe/zOpgtHVa5v5igjO
|
||||
v6cfhfJGGgIPTYrtt+EDKXcayvy2e2U/3HYVCHYiiMPX8AvP/R6m7MGrzYxm/WyO
|
||||
t68EWXSDLfuR3qcIlpP4aSBxuSpKhY/dIkS/beKZ7Njx1s4jSuYDMbKuuCRFSU2H
|
||||
8ISHS0kh3FetiS8IyIYzxab+KQZwnVtiGj4oaAhgFTIIoH26Fv5+xka74JdzOSUA
|
||||
jR9puKuxaegVWQVBx4cCyg6hAdewRm64PAcbApZWrPvMPBfTZFnXeifmaurcdK8p
|
||||
p/1eLrrPnNM6+Fh6lcKdX74yHPz3eWP3K1njZegzWnChhEWElPhJr6qYNQjd+lAS
|
||||
7650RJ3CJLUxBffnRR9nTArxFNI5jGWg/plLJTaRT5x5qg1dGNMqntpoeiY++Ttk
|
||||
GFDGVIOICBze6SOvzkZBbuXLJSWmWj5g9J2cYsLoOvlwsDT7FzKl8p6VY4V+SQb+
|
||||
4PN8qZWmOeczaLEhZ1QLmTKFpz9+wUZsXeBd1s78bWJR0zhraMPa0UJ9GBGq6uQ0
|
||||
yZ4Xm5KHKcgoewCUQMekU9ECsmR5NuC7VFDaa1OdPEVnEYR1xtaWUY0lYKOiixnd
|
||||
+85fSq/yAXI/r0O4ISA55o9y1kDqVibTwJacb6xXGg8dHSH+TtigwD8fK9mekkDC
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,35 @@
|
|||
connections {
|
||||
|
||||
home {
|
||||
local_addrs = 192.168.0.100
|
||||
remote_addrs = 192.168.0.1
|
||||
|
||||
local {
|
||||
auth = pubkey
|
||||
certs = carolCert.pem
|
||||
id = carol@strongswan.org
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
id = moon.strongswan.org
|
||||
}
|
||||
children {
|
||||
home {
|
||||
remote_ts = 10.1.0.0/16
|
||||
|
||||
updown = /usr/local/libexec/ipsec/_updown iptables
|
||||
esp_proposals = aes128gcm128-modp3072
|
||||
}
|
||||
}
|
||||
version = 2
|
||||
proposals = aes128-sha256-modp3072
|
||||
}
|
||||
}
|
||||
|
||||
secrets {
|
||||
|
||||
rsa-carol {
|
||||
file = carolKey.pem
|
||||
secret = "nH5ZQEWtku0RJEZ6"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = pem pkcs1 x509 revocation constraints pubkey openssl random
|
||||
}
|
||||
|
||||
charon-systemd {
|
||||
load = random nonce sha1 sha2 aes hmac mgf1 pem pkcs1 x509 revocation constraints pubkey gmp curl kernel-netlink socket-default updown vici
|
||||
|
||||
rsa_pss = yes
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
connections {
|
||||
|
||||
home {
|
||||
local_addrs = 192.168.0.200
|
||||
remote_addrs = 192.168.0.1
|
||||
|
||||
local {
|
||||
auth = pubkey
|
||||
certs = daveCert.pem
|
||||
id = dave@strongswan.org
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
id = moon.strongswan.org
|
||||
}
|
||||
children {
|
||||
home {
|
||||
remote_ts = 10.1.0.0/16
|
||||
|
||||
updown = /usr/local/libexec/ipsec/_updown iptables
|
||||
esp_proposals = aes128gcm128-modp3072
|
||||
}
|
||||
}
|
||||
version = 2
|
||||
proposals = aes128-sha256-modp3072
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
swanctl {
|
||||
load = pem botan x509 revocation constraints pubkey
|
||||
}
|
||||
|
||||
charon-systemd {
|
||||
load = nonce test-vectors botan pem x509 revocation constraints pubkey curl kernel-netlink socket-default updown vici
|
||||
|
||||
rsa_pss = yes
|
||||
integrity_test = yes
|
||||
crypto_test {
|
||||
on_add = yes
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
connections {
|
||||
|
||||
rw {
|
||||
local_addrs = 192.168.0.1
|
||||
|
||||
local {
|
||||
auth = pubkey
|
||||
certs = moonCert.pem
|
||||
id = moon.strongswan.org
|
||||
}
|
||||
remote {
|
||||
auth = pubkey
|
||||
}
|
||||
children {
|
||||
net {
|
||||
local_ts = 10.1.0.0/16
|
||||
|
||||
updown = /usr/local/libexec/ipsec/_updown iptables
|
||||
esp_proposals = aes128gcm128-modp3072
|
||||
}
|
||||
}
|
||||
version = 2
|
||||
proposals = aes128-sha256-modp3072
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
carol::swanctl --terminate --ike home
|
||||
dave::swanctl --terminate --ike home
|
||||
carol::systemctl stop strongswan-swanctl
|
||||
dave::systemctl stop strongswan-swanctl
|
||||
moon::systemctl stop strongswan-swanctl
|
||||
moon::iptables-restore < /etc/iptables.flush
|
||||
carol::iptables-restore < /etc/iptables.flush
|
||||
dave::iptables-restore < /etc/iptables.flush
|
|
@ -0,0 +1,11 @@
|
|||
moon::iptables-restore < /etc/iptables.rules
|
||||
carol::iptables-restore < /etc/iptables.rules
|
||||
dave::iptables-restore < /etc/iptables.rules
|
||||
moon::systemctl start strongswan-swanctl
|
||||
carol::systemctl start strongswan-swanctl
|
||||
dave::systemctl start strongswan-swanctl
|
||||
moon::expect-connection rw
|
||||
carol::expect-connection home
|
||||
carol::swanctl --initiate --child home 2> /dev/null
|
||||
dave::expect-connection home
|
||||
dave::swanctl --initiate --child home 2> /dev/null
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# This configuration file provides information on the
|
||||
# guest instances used for this test
|
||||
|
||||
# All guest instances that are required for this test
|
||||
#
|
||||
VIRTHOSTS="alice moon carol winnetou dave"
|
||||
|
||||
# Corresponding block diagram
|
||||
#
|
||||
DIAGRAM="a-m-c-w-d.png"
|
||||
|
||||
# Guest instances on which tcpdump is to be started
|
||||
#
|
||||
TCPDUMPHOSTS="moon"
|
||||
|
||||
# Guest instances on which IPsec is started
|
||||
# Used for IPsec logging purposes
|
||||
#
|
||||
IPSECHOSTS="moon carol dave"
|
||||
|
||||
# charon controlled by swanctl
|
||||
#
|
||||
SWANCTL=1
|
Loading…
Reference in New Issue