From 9d601af559af4e7ad7ed818da499fa22ebfa5ae6 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Sat, 8 Jul 2017 18:30:01 +0200 Subject: [PATCH] -add ABE crypto module --- configure.ac | 12 ++ src/include/gnunet_crypto_lib.h | 63 +++++++ src/util/Makefile.am | 15 ++ src/util/crypto_abe.c | 305 ++++++++++++++++++++++++++++++++ src/util/test_crypto_abe.c | 86 +++++++++ 5 files changed, 481 insertions(+) create mode 100644 src/util/crypto_abe.c create mode 100644 src/util/test_crypto_abe.c diff --git a/configure.ac b/configure.ac index c16fbdcba..30f5a823c 100644 --- a/configure.ac +++ b/configure.ac @@ -440,6 +440,18 @@ AC_CHECK_LIB(ogg, ogg_stream_flush_fill, AM_CONDITIONAL(HAVE_OGG, false) ogg=0) +PKG_CHECK_MODULES([ABE], [glib-2.0]) +# check for pbc library +pbc=0 +AC_CHECK_HEADER([pbc/pbc.h],pbc=1) +AM_CONDITIONAL(HAVE_PBC, [test "$pbc" = 1]) +if test "x$pbc" = x1 +then + AC_DEFINE([HAVE_PBC],[1],[Have pbc library]) +else + AC_DEFINE([HAVE_PBC],[0],[Lacking pbc library]) +fi + gst=0 diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index 07cade0e3..6f2870c37 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h @@ -395,6 +395,11 @@ struct GNUNET_CRYPTO_PaillierCiphertext unsigned char bits[GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8]; }; +/** + * @brief type for ABE master keys + */ +struct GNUNET_CRYPTO_AbeMasterKey; + /* **************** Functions and Macros ************* */ @@ -2125,6 +2130,64 @@ GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash, const struct GNUNET_CRYPTO_RsaPublicKey *public_key); +/** + * @ingroup crypto + * Create a new CP-ABE master key. Caller must free return value. + * + * @return fresh private key; free using #GNUNET_free + */ +struct GNUNET_CRYPTO_AbeMasterKey * +GNUNET_CRYPTO_cpabe_create_master_key (void); + +/** + * @ingroup crypto + * Create a new CP-ABE key. Caller must free return value. + * + * @return fresh private key; free using #GNUNET_free + */ +struct GNUNET_CRYPTO_AbeKey * +GNUNET_CRYPTO_cpabe_create_key (struct GNUNET_CRYPTO_AbeMasterKey *msk, + char **attrs); + + +/** + * @ingroup crypto + * Encrypt a block using sessionkey. + * + * @param block the block to encrypt + * @param size the size of the @a block + * @param sessionkey the key used to encrypt + * @param iv the initialization vector to use, use INITVALUE + * for streams. + * @return the size of the encrypted block, -1 for errors + */ +ssize_t +GNUNET_CRYPTO_cpabe_encrypt (const void *block, + size_t size, + char *policy, + const struct GNUNET_CRYPTO_AbeMasterKey *key, + void **result); + +/** + * @ingroup crypto + * Encrypt a block using sessionkey. + * + * @param block the block to encrypt + * @param size the size of the @a block + * @param sessionkey the key used to encrypt + * @param iv the initialization vector to use, use INITVALUE + * for streams. + * @return the size of the encrypted block, -1 for errors + */ +ssize_t +GNUNET_CRYPTO_cpabe_decrypt (const void *block, + size_t size, + const struct GNUNET_CRYPTO_AbeKey *key, + void **result); + + + + #if 0 /* keep Emacsens' auto-indent happy */ { #endif diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 9be572bb6..4b1e44503 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -87,6 +87,7 @@ libgnunetutil_la_SOURCES = \ crypto_paillier.c \ crypto_random.c \ crypto_rsa.c \ + crypto_abe.c \ disk.c \ disk.h \ getopt.c \ @@ -117,12 +118,20 @@ libgnunetutil_la_LIBADD = \ $(LIBGCRYPT_LIBS) \ $(LTLIBICONV) \ $(LTLIBINTL) \ + $(ABE_LIBADD) \ + -lbswabe \ + -lssl \ + -lpbc \ + -lglib-2.0 \ -lltdl $(Z_LIBS) -lunistring $(XLIB) libgnunetutil_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ + $(ABE_LDADD) \ -version-info 13:0:0 +libgnunetutil_la_CFLAGS = \ + $(ABE_CFLAGS) libgnunetutil_taler_wallet_la_SOURCES = \ common_allocation.c \ @@ -274,6 +283,7 @@ check_PROGRAMS = \ test_container_multipeermap \ test_container_heap \ test_crypto_symmetric \ + test_crypto_abe \ test_crypto_crc \ test_crypto_ecdsa \ test_crypto_eddsa \ @@ -406,6 +416,11 @@ test_crypto_symmetric_SOURCES = \ test_crypto_symmetric_LDADD = \ libgnunetutil.la +test_crypto_abe_SOURCES = \ + test_crypto_abe.c +test_crypto_abe_LDADD = \ + libgnunetutil.la + test_crypto_crc_SOURCES = \ test_crypto_crc.c test_crypto_crc_LDADD = \ diff --git a/src/util/crypto_abe.c b/src/util/crypto_abe.c new file mode 100644 index 000000000..d004220d1 --- /dev/null +++ b/src/util/crypto_abe.c @@ -0,0 +1,305 @@ +/* + This file is part of GNUnet. Copyright (C) 2001-2014 Christian Grothoff + (and other contributing authors) + + GNUnet 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 3, or (at your + option) any later version. + + GNUnet 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. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +/** + * @file util/crypto_random.c + * @brief functions to gather random numbers + * @author Christian Grothoff + */ + + +#include "platform.h" +#include +#include +#include +#include +#include + +#include "gnunet_crypto_lib.h" + +struct GNUNET_CRYPTO_AbeMasterKey +{ + GByteArray* pub; + + GByteArray* msk; +}; + +struct GNUNET_CRYPTO_AbeKey +{ + GByteArray* pub; + GByteArray* prv; +}; + +static void +init_aes( element_t k, int enc, AES_KEY* key, unsigned char* iv ) +{ + int key_len; + unsigned char* key_buf; + + key_len = element_length_in_bytes(k) < 17 ? 17 : element_length_in_bytes(k); + key_buf = (unsigned char*) malloc(key_len); + element_to_bytes(key_buf, k); + + if( enc ) + AES_set_encrypt_key(key_buf + 1, 128, key); + else + AES_set_decrypt_key(key_buf + 1, 128, key); + free(key_buf); + + memset(iv, 0, 16); +} + +static GByteArray* +aes_128_cbc_encrypt( GByteArray* pt, element_t k ) +{ + AES_KEY key; + unsigned char iv[16]; + GByteArray* ct; + guint8 len[4]; + guint8 zero; + + init_aes(k, 1, &key, iv); + + /* TODO make less crufty */ + + /* stuff in real length (big endian) before padding */ + len[0] = (pt->len & 0xff000000)>>24; + len[1] = (pt->len & 0xff0000)>>16; + len[2] = (pt->len & 0xff00)>>8; + len[3] = (pt->len & 0xff)>>0; + g_byte_array_prepend(pt, len, 4); + + /* pad out to multiple of 128 bit (16 byte) blocks */ + zero = 0; + while( pt->len % 16 ) + g_byte_array_append(pt, &zero, 1); + + ct = g_byte_array_new(); + g_byte_array_set_size(ct, pt->len); + + AES_cbc_encrypt(pt->data, ct->data, pt->len, &key, iv, AES_ENCRYPT); + + return ct; +} + +static GByteArray* +aes_128_cbc_decrypt( GByteArray* ct, element_t k ) +{ + AES_KEY key; + unsigned char iv[16]; + GByteArray* pt; + unsigned int len; + + init_aes(k, 0, &key, iv); + + pt = g_byte_array_new(); + g_byte_array_set_size(pt, ct->len); + + AES_cbc_encrypt(ct->data, pt->data, ct->len, &key, iv, AES_DECRYPT); + + /* TODO make less crufty */ + + /* get real length */ + len = 0; + len = len + | ((pt->data[0])<<24) | ((pt->data[1])<<16) + | ((pt->data[2])<<8) | ((pt->data[3])<<0); + g_byte_array_remove_index(pt, 0); + g_byte_array_remove_index(pt, 0); + g_byte_array_remove_index(pt, 0); + g_byte_array_remove_index(pt, 0); + + /* truncate any garbage from the padding */ + g_byte_array_set_size(pt, len); + + return pt; +} + +struct GNUNET_CRYPTO_AbeMasterKey* +GNUNET_CRYPTO_cpabe_create_master_key (void) +{ + struct GNUNET_CRYPTO_AbeMasterKey* key; + bswabe_msk_t* msk; + bswabe_pub_t* pub; + bswabe_setup(&pub, &msk); + key = GNUNET_new (struct GNUNET_CRYPTO_AbeMasterKey); + key->pub = bswabe_pub_serialize(pub); + key->msk = bswabe_msk_serialize(msk); + GNUNET_assert (NULL != key->pub); + GNUNET_assert (NULL != key->msk); + return key; +} + +struct GNUNET_CRYPTO_AbeKey* +GNUNET_CRYPTO_cpabe_create_key (struct GNUNET_CRYPTO_AbeMasterKey *key, + char **attrs) +{ + struct GNUNET_CRYPTO_AbeKey *prv_key; + bswabe_pub_t* pub; + bswabe_msk_t* msk; + bswabe_prv_t* prv; + gchar* pub_data; + gsize len; + + pub = bswabe_pub_unserialize(key->pub, 0); + msk = bswabe_msk_unserialize(pub, key->msk, 0); + prv = bswabe_keygen(pub, msk, attrs); + prv_key = GNUNET_new (struct GNUNET_CRYPTO_AbeKey); + prv_key->prv = bswabe_prv_serialize(prv); + pub_data = g_strndup ((gchar*)key->pub->data, + key->pub->len); + len = key->pub->len; + prv_key->pub = g_byte_array_new_take ((guint8*)pub_data, len); + GNUNET_assert (NULL != prv_key->prv); + return prv_key; +} + +ssize_t +write_cpabe (void **result, GByteArray* cph_buf, + int file_len, GByteArray* aes_buf) +{ + char *ptr; + int i; + ssize_t size; + size = aes_buf->len + cph_buf->len + 12; + *result = GNUNET_malloc (size); + ptr = *result; + for(i=3; i >= 0; i--) { + *ptr = (file_len & 0xff<<(i*8))>>(i*8); + ptr++; + } + for(i=3; i >= 0; i--) { + *ptr = (aes_buf->len & 0xff<<(i*8))>>(i*8); + ptr++; + } + memcpy (ptr, aes_buf->data, aes_buf->len); + ptr += aes_buf->len; + for(i=3; i >= 0; i--) { + *ptr = (cph_buf->len & 0xff<<(i*8))>>(i*8); + ptr++; + } + memcpy (ptr, cph_buf->data, cph_buf->len); + return size; +} + +ssize_t +read_cpabe (const void *data, GByteArray** cph_buf, GByteArray** aes_buf) +{ + int i; + ssize_t buf_len; + ssize_t tmp_len; + char *ptr; + + *cph_buf = g_byte_array_new(); + *aes_buf = g_byte_array_new(); + ptr = (char*)data; + + buf_len = 0; + for(i=3; i >= 0; i--) { + buf_len |= *ptr<<(i*8); + ptr++; + } + + tmp_len = 0; + for(i=3; i >= 0; i--) { + tmp_len |= *ptr<<(i*8); + ptr++; + } + g_byte_array_set_size(*aes_buf, tmp_len); + memcpy((*aes_buf)->data, ptr, tmp_len); + ptr += tmp_len; + tmp_len = 0; + for(i=3; i >= 0; i--) { + tmp_len |= *ptr<<(i*8); + ptr++; + } + g_byte_array_set_size(*cph_buf, tmp_len); + memcpy((*cph_buf)->data, ptr, tmp_len); + + return buf_len; +} + +ssize_t +GNUNET_CRYPTO_cpabe_encrypt (const void *block, + size_t size, + char *policy, + const struct GNUNET_CRYPTO_AbeMasterKey *key, + void **result) +{ + bswabe_pub_t* pub; + bswabe_cph_t* cph; + GByteArray* plt; + GByteArray* cph_buf; + GByteArray* aes_buf; + guint8 *data; + element_t m; + size_t payload_len; + ssize_t result_len; + pub = bswabe_pub_unserialize(key->pub, 0); + if( !(cph = bswabe_enc(pub, m, policy)) ) + return GNUNET_SYSERR; + cph_buf = bswabe_cph_serialize(cph); + bswabe_cph_free(cph); + data = g_memdup (block, size); + plt = g_byte_array_new_take (data, size); + payload_len = plt->len; + aes_buf = aes_128_cbc_encrypt(plt, m); + g_byte_array_free(plt, 1); + element_clear(m); + result_len = write_cpabe(result, cph_buf, payload_len, aes_buf); + g_byte_array_free(cph_buf, 1); + g_byte_array_free(aes_buf, 1); + return result_len; +} + +ssize_t +GNUNET_CRYPTO_cpabe_decrypt (const void *block, + size_t size, + const struct GNUNET_CRYPTO_AbeKey *key, + void **result) +{ + bswabe_pub_t* pub; + bswabe_prv_t* prv; + GByteArray* aes_buf; + GByteArray* plt; + GByteArray* cph_buf; + bswabe_cph_t* cph; + element_t m; + ssize_t pt_size; + + pub = bswabe_pub_unserialize(key->pub, 0); + prv = bswabe_prv_unserialize(pub, key->prv, 0); + pt_size = read_cpabe(block, &cph_buf, &aes_buf); + cph = bswabe_cph_unserialize(pub, cph_buf, 0); + if( !bswabe_dec(pub, prv, cph, m) ) { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "%s\n", bswabe_error()); + return GNUNET_SYSERR; + } + bswabe_cph_free(cph); + plt = aes_128_cbc_decrypt(aes_buf, m); + g_byte_array_set_size(plt, size); + g_byte_array_free(aes_buf, 1); + *result = GNUNET_malloc (plt->len); + GNUNET_memcpy (*result, plt->data, plt->len); + + return pt_size; +} diff --git a/src/util/test_crypto_abe.c b/src/util/test_crypto_abe.c new file mode 100644 index 000000000..cb36dccae --- /dev/null +++ b/src/util/test_crypto_abe.c @@ -0,0 +1,86 @@ +/* + This file is part of GNUnet. + Copyright (C) 2002, 2003, 2004, 2006 GNUnet e.V. + + GNUnet 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 3, or (at your + option) any later version. + + GNUnet 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. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +/** + * @author Martin Schanzenbach + * @file util/test_crypto_abe.c + * @brief test for ABE ciphers + */ +#include "platform.h" +#include "gnunet_util_lib.h" + +#define TESTSTRING "Hello World!" + +static int +testAbecipher () +{ + struct GNUNET_CRYPTO_AbeMasterKey *msk; + struct GNUNET_CRYPTO_AbeKey *key; + char *result; + char **attrs; + int size; + char *res; + msk = GNUNET_CRYPTO_cpabe_create_master_key (); + size = GNUNET_CRYPTO_cpabe_encrypt (TESTSTRING, strlen (TESTSTRING) + 1, + "testattr", //Policy + msk, + (void*)&result); + GNUNET_assert (-1 != size); + attrs = GNUNET_malloc (2 * sizeof (char*)); + attrs[0] = "testattr"; + attrs[1] = NULL; + key = GNUNET_CRYPTO_cpabe_create_key (msk, + attrs); + + size = GNUNET_CRYPTO_cpabe_decrypt (result, size, + key, + (void*)&res); + if (strlen (TESTSTRING) + 1 != size) + { + printf ("abeciphertest failed: decryptBlock returned %d\n", size); + return 1; + } + if (0 != strcmp (res, TESTSTRING)) + { + printf ("abeciphertest failed: %s != %s\n", res, TESTSTRING); + return 1; + } + else + return 0; +} + + +int +main (int argc, char *argv[]) +{ + int failureCount = 0; + + GNUNET_log_setup ("test-crypto-abe", "WARNING", NULL); + failureCount += testAbecipher (); + + if (failureCount != 0) + { + printf ("%d TESTS FAILED!\n", failureCount); + return -1; + } + return 0; +} + +/* end of test_crypto_aes.c */ -- 2.25.1