implemented XCBC algorithms (signer, prf) for IKE on top of a crypter

supporting ike=...-aesxcbc-... in ipsec.conf 
added AUTH_AES_XCBC_96 and PRF_AES128_CBC to default IKE proposal
AES XCBC testcase
This commit is contained in:
Martin Willi 2008-04-30 14:26:24 +00:00
parent f5475fa440
commit 27d04e055d
14 changed files with 1099 additions and 2 deletions

View File

@ -257,6 +257,17 @@ AC_ARG_ENABLE(
hmac=true
)
AC_ARG_ENABLE(
[xcbc],
AS_HELP_STRING([--disable-xcbc],[disable xcbc crypto implementation plugin. (default is NO).]),
[if test x$enableval = xyes; then
xcbc=true
else
xcbc=false
fi],
xcbc=true
)
AC_ARG_ENABLE(
[mysql],
AS_HELP_STRING([--enable-mysql],[enable MySQL database support (default is NO). Requires libmysqlclient_r.]),
@ -635,6 +646,7 @@ AM_CONDITIONAL(USE_GMP, test x$gmp = xtrue)
AM_CONDITIONAL(USE_RANDOM, test x$random = xtrue)
AM_CONDITIONAL(USE_X509, test x$x509 = xtrue)
AM_CONDITIONAL(USE_HMAC, test x$hmac = xtrue)
AM_CONDITIONAL(USE_XCBC, test x$xcbc = xtrue)
AM_CONDITIONAL(USE_MYSQL, test x$mysql = xtrue)
AM_CONDITIONAL(USE_SQLITE, test x$sqlite = xtrue)
AM_CONDITIONAL(USE_STROKE, test x$stroke = xtrue)
@ -693,6 +705,7 @@ AC_OUTPUT(
src/libstrongswan/plugins/gmp/Makefile
src/libstrongswan/plugins/random/Makefile
src/libstrongswan/plugins/hmac/Makefile
src/libstrongswan/plugins/xcbc/Makefile
src/libstrongswan/plugins/x509/Makefile
src/libstrongswan/plugins/curl/Makefile
src/libstrongswan/plugins/ldap/Makefile

View File

@ -607,7 +607,7 @@ static status_t add_string_algo(private_proposal_t *this, chunk_t alg)
add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
if (this->protocol == PROTO_IKE)
{
add_algorithm(this, PSEUDO_RANDOM_FUNCTION, AUTH_AES_XCBC_96, 0);
add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_AES128_CBC, 0);
}
}
else if (strncmp(alg.ptr, "modp768", alg.len) == 0)
@ -700,11 +700,13 @@ proposal_t *proposal_create_default(protocol_id_t protocol)
add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192);
add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0);
add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0);
add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0);
add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0);
add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_AES128_CBC, 0);
add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_256, 0);
add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0);
add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0);

View File

@ -34,4 +34,5 @@ DEFINE_TEST("RSA key generation", test_rsa_gen, FALSE)
DEFINE_TEST("RSA subjectPublicKeyInfo loading", test_rsa_load_any, FALSE)
DEFINE_TEST("Mediation database key fetch", test_med_db, FALSE)
DEFINE_TEST("AES-128 encryption", test_aes128, FALSE)
DEFINE_TEST("Base64 converter", test_chunk_base64, TRUE)
DEFINE_TEST("AES-XCBC", test_aes_xcbc, TRUE)
DEFINE_TEST("Base64 converter", test_chunk_base64, FALSE)

View File

@ -13,6 +13,7 @@
* for more details.
*/
#include <daemon.h>
#include <library.h>
#include <utils/mutex.h>
@ -166,3 +167,242 @@ bool test_aes128()
}
return TRUE;
}
/**
* run a single xcbc test for prf and signer
*/
static bool do_xcbc_test(u_int8_t *key, size_t keylen, u_int8_t *mac,
u_int8_t *plain, size_t len)
{
signer_t *signer;
prf_t *prf;
u_int8_t res[16];
prf = lib->crypto->create_prf(lib->crypto, PRF_AES128_CBC);
if (!prf)
{
return FALSE;
}
prf->set_key(prf, chunk_create(key, keylen));
prf->get_bytes(prf, chunk_create(plain, len), res);
if (!memeq(res, mac, 16))
{
DBG1(DBG_CFG, "expected %b\ngot %b", mac, 16, res, 16);
prf->destroy(prf);
return FALSE;
}
prf->destroy(prf);
signer = lib->crypto->create_signer(lib->crypto, AUTH_AES_XCBC_96);
if (!signer)
{
return FALSE;
}
signer->set_key(signer, chunk_create(key, keylen));
if (!signer->verify_signature(signer, chunk_create(plain, len),
chunk_create(mac, 12)))
{
return FALSE;
}
signer->destroy(signer);
return TRUE;
}
/*******************************************************************************
* AES_XCBC mac test
******************************************************************************/
bool test_aes_xcbc()
{
/* Vectors from RFC 3566 */
/* Test Case #1 : AES-XCBC-MAC-96 with 0-byte input
* Key (K) : 000102030405060708090a0b0c0d0e0f
* Message (M) : <empty string>
* AES-XCBC-MAC : 75f0251d528ac01c4573dfd584d79f29
* AES-XCBC-MAC-96: 75f0251d528ac01c4573dfd5
*/
u_char key1[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
};
u_char plain1[] = {
};
u_char mac1[] = {
0x75,0xf0,0x25,0x1d,0x52,0x8a,0xc0,0x1c,
0x45,0x73,0xdf,0xd5,0x84,0xd7,0x9f,0x29
};
if (!do_xcbc_test(key1, 16, mac1, plain1, sizeof(plain1)))
{
return FALSE;
}
/*
* Test Case #2 : AES-XCBC-MAC-96 with 3-byte input
* Key (K) : 000102030405060708090a0b0c0d0e0f
* Message (M) : 000102
* AES-XCBC-MAC : 5b376580ae2f19afe7219ceef172756f
* AES-XCBC-MAC-96: 5b376580ae2f19afe7219cee
*/
u_char key2[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
};
u_char plain2[] = {
0x00,0x01,0x02
};
u_char mac2[] = {
0x5b,0x37,0x65,0x80,0xae,0x2f,0x19,0xaf,
0xe7,0x21,0x9c,0xee,0xf1,0x72,0x75,0x6f
};
if (!do_xcbc_test(key2, 16, mac2, plain2, sizeof(plain2)))
{
return FALSE;
}
/* Test Case #3 : AES-XCBC-MAC-96 with 16-byte input
* Key (K) : 000102030405060708090a0b0c0d0e0f
* Message (M) : 000102030405060708090a0b0c0d0e0f
* AES-XCBC-MAC : d2a246fa349b68a79998a4394ff7a263
* AES-XCBC-MAC-96: d2a246fa349b68a79998a439
*/
u_char key3[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
};
u_char plain3[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
};
u_char mac3[] = {
0xd2,0xa2,0x46,0xfa,0x34,0x9b,0x68,0xa7,
0x99,0x98,0xa4,0x39,0x4f,0xf7,0xa2,0x63
};
if (!do_xcbc_test(key3, 16, mac3, plain3, sizeof(plain3)))
{
return FALSE;
}
/* Test Case #4 : AES-XCBC-MAC-96 with 20-byte input
* Key (K) : 000102030405060708090a0b0c0d0e0f
* Message (M) : 000102030405060708090a0b0c0d0e0f10111213
* AES-XCBC-MAC : 47f51b4564966215b8985c63055ed308
* AES-XCBC-MAC-96: 47f51b4564966215b8985c63
*/
u_char key4[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
};
u_char plain4[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13
};
u_char mac4[] = {
0x47,0xf5,0x1b,0x45,0x64,0x96,0x62,0x15,
0xb8,0x98,0x5c,0x63,0x05,0x5e,0xd3,0x08
};
if (!do_xcbc_test(key4, 16, mac4, plain4, sizeof(plain4)))
{
return FALSE;
}
/* Test Case #5 : AES-XCBC-MAC-96 with 32-byte input
* Key (K) : 000102030405060708090a0b0c0d0e0f
* Message (M) : 000102030405060708090a0b0c0d0e0f10111213141516171819
* 1a1b1c1d1e1f
* AES-XCBC-MAC : f54f0ec8d2b9f3d36807734bd5283fd4
* AES-XCBC-MAC-96: f54f0ec8d2b9f3d36807734b
*/
u_char key5[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
};
u_char plain5[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
};
u_char mac5[] = {
0xf5,0x4f,0x0e,0xc8,0xd2,0xb9,0xf3,0xd3,
0x68,0x07,0x73,0x4b,0xd5,0x28,0x3f,0xd4
};
if (!do_xcbc_test(key5, 16, mac5, plain5, sizeof(plain5)))
{
return FALSE;
}
/* Test Case #7 : AES-XCBC-MAC-96 with 1000-byte input
* Key (K) : 000102030405060708090a0b0c0d0e0f
* Message (M) : 00000000000000000000 ... 00000000000000000000
* [1000 bytes]
* AES-XCBC-MAC : f0dafee895db30253761103b5d84528f
* AES-XCBC-MAC-96: f0dafee895db30253761103b
*/
u_char key7[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
};
u_char plain7[1000];
memset(plain7, 0, 1000);
u_char mac7[] = {
0xf0,0xda,0xfe,0xe8,0x95,0xdb,0x30,0x25,
0x37,0x61,0x10,0x3b,0x5d,0x84,0x52,0x8f
};
if (!do_xcbc_test(key7, 16, mac7, plain7, sizeof(plain7)))
{
return FALSE;
}
/* variable key test, RFC4434 */
/* Test Case AES-XCBC-PRF-128 with 20-byte input
* Key : 00010203040506070809
* Message : 000102030405060708090a0b0c0d0e0f10111213
* PRF Output : 0fa087af7d866e7653434e602fdde835
*/
u_char key8[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,
};
u_char plain8[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13
};
u_char mac8[] = {
0x0f,0xa0,0x87,0xaf,0x7d,0x86,0x6e,0x76,
0x53,0x43,0x4e,0x60,0x2f,0xdd,0xe8,0x35
};
if (!do_xcbc_test(key8, 10, mac8, plain8, sizeof(plain8)))
{
return FALSE;
}
/* Test Case AES-XCBC-PRF-128 with 20-byte input
* Key : 000102030405060708090a0b0c0d0e0fedcb
* Message : 000102030405060708090a0b0c0d0e0f10111213
* PRF Output : 8cd3c93ae598a9803006ffb67c40e9e4
*/
u_char key9[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0xed,0xcb
};
u_char plain9[] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13
};
u_char mac9[] = {
0x8c,0xd3,0xc9,0x3a,0xe5,0x98,0xa9,0x80,
0x30,0x06,0xff,0xb6,0x7c,0x40,0xe9,0xe4
};
if (!do_xcbc_test(key9, 18, mac9, plain9, sizeof(plain9)))
{
return FALSE;
}
return TRUE;
}

View File

@ -120,6 +120,10 @@ if USE_HMAC
SUBDIRS += plugins/hmac
endif
if USE_XCBC
SUBDIRS += plugins/xcbc
endif
if USE_X509
SUBDIRS += plugins/x509
endif

View File

@ -0,0 +1,11 @@
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libstrongswan-xcbc.la
libstrongswan_xcbc_la_SOURCES = xcbc_plugin.h xcbc_plugin.c xcbc.h xcbc.c \
xcbc_prf.h xcbc_prf.c xcbc_signer.h xcbc_signer.c
libstrongswan_xcbc_la_LDFLAGS = -module

View File

@ -0,0 +1,231 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General xcbc License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General xcbc License
* for more details.
*
* $Id: xcbc.c 3589 2008-03-13 14:14:44Z martin $
*/
#include <string.h>
#include "xcbc.h"
#include <debug.h>
typedef struct private_xcbc_t private_xcbc_t;
/**
* Private data of a xcbc_t object.
*
* The variable names are the same as in the RFC.
*/
struct private_xcbc_t {
/**
* Public xcbc_t interface.
*/
xcbc_t xcbc;
/**
* Block size, in bytes
*/
u_int8_t b;
/**
* crypter using k1
*/
crypter_t *k1;
/**
* k2
*/
u_int8_t *k2;
/**
* k3
*/
u_int8_t *k3;
};
/**
* Implementation of xcbc_t.get_mac.
*/
static void get_mac(private_xcbc_t *this, chunk_t data, u_int8_t *e)
{
int n, i, padding;
u_int8_t *m;
chunk_t iv;
if (e == NULL)
{
DBG1("XCBC append mode not implemented!");
/* TODO: append mode */
return;
}
n = data.len / this->b;
padding = data.len % this->b;
if (padding || data.len == 0)
{ /* do an additional block if we have padding or zero-length data */
n++;
}
iv = chunk_alloca(this->b);
memset(iv.ptr, 0, iv.len);
m = data.ptr;
/* (2) Define E[0] = 0x00000000000000000000000000000000 */
memset(e, 0, this->b);
/* (3) For each block M[i], where i = 1 ... n-1:
* XOR M[i] with E[i-1], then encrypt the result with Key K1,
* yielding E[i].
*/
for (i = 1; i < n; i++)
{
memxor(e, m + (i - 1) * this->b, this->b);
this->k1->encrypt(this->k1, chunk_create(e, this->b), iv, NULL);
}
/* (4) For block M[n]: */
if (data.len && padding == 0)
{
/* a) If the blocksize of M[n] is 128 bits:
* XOR M[n] with E[n-1] and Key K2, then encrypt the result with
* Key K1, yielding E[n].
*/
memxor(e, m + (i - 1) * this->b, this->b);
memxor(e, this->k2, this->b);
this->k1->encrypt(this->k1, chunk_create(e, this->b), iv, NULL);
}
else
{
/* b) If the blocksize of M[n] is less than 128 bits:
*
* i) Pad M[n] with a single "1" bit, followed by the number of
* "0" bits (possibly none) required to increase M[n]'s
* blocksize to 128 bits.
*/
u_int8_t *mn = alloca(this->b);
memcpy(mn, m + (n - 1) * this->b, padding);
mn[padding] = 0x80;
while (++padding < this->b)
{
mn[padding] = 0x00;
}
/* ii) XOR M[n] with E[n-1] and Key K3, then encrypt the result
* with Key K1, yielding E[n].
*/
memxor(e, mn, this->b);
memxor(e, this->k3, this->b);
this->k1->encrypt(this->k1, chunk_create(e, this->b), iv, NULL);
}
}
/**
* Implementation of xcbc_t.get_block_size.
*/
static size_t get_block_size(private_xcbc_t *this)
{
return this->b;
}
/**
* Implementation of xcbc_t.set_key.
*/
static void set_key(private_xcbc_t *this, chunk_t key)
{
chunk_t iv, k1, lengthened;
/* we support variable keys from RFC4434 */
if (key.len == this->b)
{
lengthened = key;
}
else if (key.len < this->b)
{ /* pad short keys */
lengthened = chunk_alloca(this->b);
memset(lengthened.ptr, 0, lengthened.len);
memcpy(lengthened.ptr, key.ptr, key.len);
}
else
{ /* shorten key using xcbc */
lengthened = chunk_alloca(this->b);
memset(lengthened.ptr, 0, lengthened.len);
set_key(this, lengthened);
get_mac(this, key, lengthened.ptr);
}
k1 = chunk_alloca(this->b);
iv = chunk_alloca(this->b);
memset(iv.ptr, 0, iv.len);
/*
* (1) Derive 3 128-bit keys (K1, K2 and K3) from the 128-bit secret
* key K, as follows:
* K1 = 0x01010101010101010101010101010101 encrypted with Key K
* K2 = 0x02020202020202020202020202020202 encrypted with Key K
* K3 = 0x03030303030303030303030303030303 encrypted with Key K
*/
this->k1->set_key(this->k1, lengthened);
memset(this->k2, 0x02, this->b);
this->k1->encrypt(this->k1, chunk_create(this->k2, this->b), iv, NULL);
memset(this->k3, 0x03, this->b);
this->k1->encrypt(this->k1, chunk_create(this->k3, this->b), iv, NULL);
memset(k1.ptr, 0x01, this->b);
this->k1->encrypt(this->k1, k1, iv, NULL);
this->k1->set_key(this->k1, k1);
}
/**
* Implementation of xcbc_t.destroy.
*/
static void destroy(private_xcbc_t *this)
{
this->k1->destroy(this->k1);
free(this->k2);
free(this->k3);
free(this);
}
/*
* Described in header
*/
xcbc_t *xcbc_create(encryption_algorithm_t algo, size_t key_size)
{
private_xcbc_t *this;
crypter_t *crypter;
crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size);
if (!crypter)
{
return NULL;
}
/* input and output of crypter must be equal for xcbc */
if (crypter->get_block_size(crypter) != key_size)
{
crypter->destroy(crypter);
return NULL;
}
this = malloc_thing(private_xcbc_t);
this->xcbc.get_mac = (void (*)(xcbc_t *,chunk_t,u_int8_t*))get_mac;
this->xcbc.get_block_size = (size_t (*)(xcbc_t *))get_block_size;
this->xcbc.set_key = (void (*)(xcbc_t *,chunk_t))set_key;
this->xcbc.destroy = (void (*)(xcbc_t *))destroy;
this->b = crypter->get_block_size(crypter);
this->k1 = crypter;
this->k2 = malloc(this->b);
this->k3 = malloc(this->b);
return &this->xcbc;
}

View File

@ -0,0 +1,78 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup xcbc xcbc
* @{ @ingroup xcbc_p
*/
#ifndef XCBC_H_
#define XCBC_H_
typedef struct xcbc_t xcbc_t;
#include <crypto/hashers/hasher.h>
/**
* Message authentication using CBC crypter.
*
* This class implements the message authenticaion algorithm
* described in RFC3566.
*/
struct xcbc_t {
/**
* Generate message authentication code.
*
* If buffer is NULL, no result is given back. A next call will
* append the data to already supplied data. If buffer is not NULL,
* the mac of all apended data is calculated, returned and the
* state of the xcbc_t is reseted.
*
* @param data chunk of data to authenticate
* @param buffer pointer where the generated bytes will be written
*/
void (*get_mac) (xcbc_t *this, chunk_t data, u_int8_t *buffer);
/**
* Get the block size of this xcbc_t object.
*
* @return block size in bytes
*/
size_t (*get_block_size) (xcbc_t *this);
/**
* Set the key for this xcbc_t object.
*
* @param key key to set
*/
void (*set_key) (xcbc_t *this, chunk_t key);
/**
* Destroys a xcbc_t object.
*/
void (*destroy) (xcbc_t *this);
};
/**
* Creates a new xcbc_t object.
*
* @param algo underlying crypto algorithm
* @param key_size key size to use, if required for algorithm
* @return xcbc_t object, NULL if not supported
*/
xcbc_t *xcbc_create(encryption_algorithm_t algo, size_t key_size);
#endif /*xcbc_H_ @}*/

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include "xcbc_plugin.h"
#include <library.h>
#include "xcbc_signer.h"
#include "xcbc_prf.h"
typedef struct private_xcbc_plugin_t private_xcbc_plugin_t;
/**
* private data of xcbc_plugin
*/
struct private_xcbc_plugin_t {
/**
* public functions
*/
xcbc_plugin_t public;
};
/**
* Implementation of xcbc_plugin_t.xcbctroy
*/
static void destroy(private_xcbc_plugin_t *this)
{
lib->crypto->remove_prf(lib->crypto,
(prf_constructor_t)xcbc_prf_create);
lib->crypto->remove_signer(lib->crypto,
(signer_constructor_t)xcbc_signer_create);
free(this);
}
/*
* see header file
*/
plugin_t *plugin_create()
{
private_xcbc_plugin_t *this = malloc_thing(private_xcbc_plugin_t);
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
lib->crypto->add_prf(lib->crypto, PRF_AES128_CBC,
(prf_constructor_t)xcbc_prf_create);
lib->crypto->add_signer(lib->crypto, AUTH_AES_XCBC_96,
(signer_constructor_t)xcbc_signer_create);
return &this->public.plugin;
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup xcbc_p xcbc
* @ingroup plugins
*
* @defgroup xcbc_plugin xcbc_plugin
* @{ @ingroup xcbc_p
*/
#ifndef XCBC_PLUGIN_H_
#define XCBC_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct xcbc_plugin_t xcbc_plugin_t;
/**
* Plugin implementing xcbc algorithm to provide crypter based PRF and signers.
*/
struct xcbc_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
/**
* Create a xcbc_plugin instance.
*/
plugin_t *plugin_create();
#endif /* XCBC_PLUGIN_H_ @}*/

View File

@ -0,0 +1,131 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include "xcbc_prf.h"
#include "xcbc.h"
typedef struct private_xcbc_prf_t private_xcbc_prf_t;
/**
* Private data of a xcbc_prf_t object.
*/
struct private_xcbc_prf_t {
/**
* Public xcbc_prf_t interface.
*/
xcbc_prf_t public;
/**
* xcbc to use for generation.
*/
xcbc_t *xcbc;
};
/**
* Implementation of prf_t.get_bytes.
*/
static void get_bytes(private_xcbc_prf_t *this, chunk_t seed, u_int8_t *buffer)
{
this->xcbc->get_mac(this->xcbc, seed, buffer);
}
/**
* Implementation of prf_t.allocate_bytes.
*/
static void allocate_bytes(private_xcbc_prf_t *this, chunk_t seed, chunk_t *chunk)
{
if (chunk)
{
*chunk = chunk_alloc(this->xcbc->get_block_size(this->xcbc));
get_bytes(this, seed, chunk->ptr);
}
else
{
get_bytes(this, seed, NULL);
}
}
/**
* Implementation of prf_t.get_block_size.
*/
static size_t get_block_size(private_xcbc_prf_t *this)
{
return this->xcbc->get_block_size(this->xcbc);
}
/**
* Implementation of prf_t.get_block_size.
*/
static size_t get_key_size(private_xcbc_prf_t *this)
{
/* in xcbc, block and key size are always equal */
return this->xcbc->get_block_size(this->xcbc);
}
/**
* Implementation of prf_t.set_key.
*/
static void set_key(private_xcbc_prf_t *this, chunk_t key)
{
this->xcbc->set_key(this->xcbc, key);
}
/**
* Implementation of prf_t.destroy.
*/
static void destroy(private_xcbc_prf_t *this)
{
this->xcbc->destroy(this->xcbc);
free(this);
}
/*
* Described in header.
*/
xcbc_prf_t *xcbc_prf_create(pseudo_random_function_t algo)
{
private_xcbc_prf_t *this;
xcbc_t *xcbc;
switch (algo)
{
case PRF_AES128_CBC:
xcbc = xcbc_create(ENCR_AES_CBC, 16);
break;
default:
return NULL;
}
if (!xcbc)
{
return NULL;
}
this = malloc_thing(private_xcbc_prf_t);
this->xcbc = xcbc;
this->public.prf_interface.get_bytes = (void (*) (prf_t *,chunk_t,u_int8_t*))get_bytes;
this->public.prf_interface.allocate_bytes = (void (*) (prf_t*,chunk_t,chunk_t*))allocate_bytes;
this->public.prf_interface.get_block_size = (size_t (*) (prf_t*))get_block_size;
this->public.prf_interface.get_key_size = (size_t (*) (prf_t*))get_key_size;
this->public.prf_interface.set_key = (void (*) (prf_t *,chunk_t))set_key;
this->public.prf_interface.destroy = (void (*) (prf_t *))destroy;
return &this->public;
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup xcbc_prf xcbc_prf
* @{ @ingroup xcbc_p
*/
#ifndef PRF_XCBC_H_
#define PRF_XCBC_H_
typedef struct xcbc_prf_t xcbc_prf_t;
#include <crypto/prfs/prf.h>
/**
* Implementation of prf_t on CBC block cipher using XCBC, RFC3664/RFC4434.
*
* This simply wraps a xcbc_t in a prf_t. More a question of
* interface matching.
*/
struct xcbc_prf_t {
/**
* Generic prf_t interface for this xcbc_prf_t class.
*/
prf_t prf_interface;
};
/**
* Creates a new xcbc_prf_t object.
*
* @param algo algorithm to implement
* @return xcbc_prf_t object, NULL if hash not supported
*/
xcbc_prf_t *xcbc_prf_create(pseudo_random_function_t algo);
#endif /*PRF_XCBC_SHA1_H_ @}*/

View File

@ -0,0 +1,177 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* $Id$
*/
#include <string.h>
#include "xcbc_signer.h"
#include "xcbc.h"
typedef struct private_xcbc_signer_t private_xcbc_signer_t;
/**
* Private data structure with signing context.
*/
struct private_xcbc_signer_t {
/**
* Public interface of xcbc_signer_t.
*/
xcbc_signer_t public;
/**
* Assigned xcbc function.
*/
xcbc_t *xcbc;
/**
* Block size (truncation of XCBC MAC)
*/
size_t block_size;
};
/**
* Implementation of signer_t.get_signature.
*/
static void get_signature(private_xcbc_signer_t *this,
chunk_t data, u_int8_t *buffer)
{
if (buffer == NULL)
{ /* append mode */
this->xcbc->get_mac(this->xcbc, data, NULL);
}
else
{
u_int8_t mac[this->xcbc->get_block_size(this->xcbc)];
this->xcbc->get_mac(this->xcbc, data, mac);
memcpy(buffer, mac, this->block_size);
}
}
/**
* Implementation of signer_t.allocate_signature.
*/
static void allocate_signature (private_xcbc_signer_t *this,
chunk_t data, chunk_t *chunk)
{
if (chunk == NULL)
{ /* append mode */
this->xcbc->get_mac(this->xcbc, data, NULL);
}
else
{
u_int8_t mac[this->xcbc->get_block_size(this->xcbc)];
this->xcbc->get_mac(this->xcbc, data, mac);
chunk->ptr = malloc(this->block_size);
chunk->len = this->block_size;
memcpy(chunk->ptr, mac, this->block_size);
}
}
/**
* Implementation of signer_t.verify_signature.
*/
static bool verify_signature(private_xcbc_signer_t *this,
chunk_t data, chunk_t signature)
{
u_int8_t mac[this->xcbc->get_block_size(this->xcbc)];
if (signature.len != this->block_size)
{
return FALSE;
}
this->xcbc->get_mac(this->xcbc, data, mac);
return memeq(signature.ptr, mac, this->block_size);
}
/**
* Implementation of signer_t.get_key_size.
*/
static size_t get_key_size(private_xcbc_signer_t *this)
{
return this->xcbc->get_block_size(this->xcbc);
}
/**
* Implementation of signer_t.get_block_size.
*/
static size_t get_block_size(private_xcbc_signer_t *this)
{
return this->block_size;
}
/**
* Implementation of signer_t.set_key.
*/
static void set_key(private_xcbc_signer_t *this, chunk_t key)
{
this->xcbc->set_key(this->xcbc, key);
}
/**
* Implementation of signer_t.destroy.
*/
static status_t destroy(private_xcbc_signer_t *this)
{
this->xcbc->destroy(this->xcbc);
free(this);
return SUCCESS;
}
/*
* Described in header
*/
xcbc_signer_t *xcbc_signer_create(integrity_algorithm_t algo)
{
private_xcbc_signer_t *this;
size_t trunc;
xcbc_t *xcbc;
switch (algo)
{
case AUTH_AES_XCBC_96:
xcbc = xcbc_create(ENCR_AES_CBC, 16);
trunc = 12;
break;
default:
return NULL;
}
if (xcbc == NULL)
{
return NULL;
}
this = malloc_thing(private_xcbc_signer_t);
this->xcbc = xcbc;
this->block_size = min(trunc, xcbc->get_block_size(xcbc));
/* interface functions */
this->public.signer_interface.get_signature = (void (*) (signer_t*, chunk_t, u_int8_t*))get_signature;
this->public.signer_interface.allocate_signature = (void (*) (signer_t*, chunk_t, chunk_t*))allocate_signature;
this->public.signer_interface.verify_signature = (bool (*) (signer_t*, chunk_t, chunk_t))verify_signature;
this->public.signer_interface.get_key_size = (size_t (*) (signer_t*))get_key_size;
this->public.signer_interface.get_block_size = (size_t (*) (signer_t*))get_block_size;
this->public.signer_interface.set_key = (void (*) (signer_t*,chunk_t))set_key;
this->public.signer_interface.destroy = (void (*) (signer_t*))destroy;
return &this->public;
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup xcbc_signer xcbc_signer
* @{ @ingroup xcbc_p
*/
#ifndef xcbc_SIGNER_H_
#define xcbc_SIGNER_H_
typedef struct xcbc_signer_t xcbc_signer_t;
#include <crypto/signers/signer.h>
/**
* Implementation of signer_t based on CBC symmetric cypher. XCBC, RFC3566.
*/
struct xcbc_signer_t {
/**
* generic signer_t interface for this signer
*/
signer_t signer_interface;
};
/**
* Creates a new xcbc_signer_t.
*
* @param algo algorithm to implement
* @return xcbc_signer_t, NULL if not supported
*/
xcbc_signer_t *xcbc_signer_create(integrity_algorithm_t algo);
#endif /*xcbc_SIGNER_H_ @}*/