diff options
-rw-r--r-- | src/libstrongswan/plugins/padlock/Makefile.am | 3 | ||||
-rw-r--r-- | src/libstrongswan/plugins/padlock/padlock_plugin.c | 19 | ||||
-rw-r--r-- | src/libstrongswan/plugins/padlock/padlock_rng.c | 136 | ||||
-rw-r--r-- | src/libstrongswan/plugins/padlock/padlock_rng.h | 49 |
4 files changed, 206 insertions, 1 deletions
diff --git a/src/libstrongswan/plugins/padlock/Makefile.am b/src/libstrongswan/plugins/padlock/Makefile.am index e2e76e9e6..e7c3ba486 100644 --- a/src/libstrongswan/plugins/padlock/Makefile.am +++ b/src/libstrongswan/plugins/padlock/Makefile.am @@ -7,6 +7,7 @@ plugin_LTLIBRARIES = libstrongswan-padlock.la libstrongswan_padlock_la_SOURCES = padlock_plugin.h padlock_plugin.c \ padlock_aes_crypter.c padlock_aes_crypter.h \ - padlock_sha1_hasher.c padlock_sha1_hasher.h + padlock_sha1_hasher.c padlock_sha1_hasher.h \ + padlock_rng.c padlock_rng.h libstrongswan_padlock_la_LDFLAGS = -module diff --git a/src/libstrongswan/plugins/padlock/padlock_plugin.c b/src/libstrongswan/plugins/padlock/padlock_plugin.c index b6e2b7c59..d0b55bcd9 100644 --- a/src/libstrongswan/plugins/padlock/padlock_plugin.c +++ b/src/libstrongswan/plugins/padlock/padlock_plugin.c @@ -18,6 +18,7 @@ #include "padlock_plugin.h" #include "padlock_aes_crypter.h" #include "padlock_sha1_hasher.h" +#include "padlock_rng.h" #include <stdio.h> @@ -107,6 +108,15 @@ static padlock_feature_t get_padlock_features() */ static void destroy(private_padlock_plugin_t *this) { + if (this->features & PADLOCK_RNG_ENABLED) + { + lib->crypto->remove_rng(lib->crypto, + (rng_constructor_t)padlock_rng_create); + lib->crypto->remove_rng(lib->crypto, + (rng_constructor_t)padlock_rng_create); + lib->crypto->remove_rng(lib->crypto, + (rng_constructor_t)padlock_rng_create); + } if (this->features & PADLOCK_ACE2_ENABLED) { lib->crypto->remove_crypter(lib->crypto, @@ -147,6 +157,15 @@ plugin_t *plugin_create() this->features & PADLOCK_PHE_ENABLED ? " PHE" : "", this->features & PADLOCK_PMM_ENABLED ? " PMM" : ""); + if (this->features & PADLOCK_RNG_ENABLED) + { + lib->crypto->add_rng(lib->crypto, RNG_REAL, + (rng_constructor_t)padlock_rng_create); + lib->crypto->add_rng(lib->crypto, RNG_STRONG, + (rng_constructor_t)padlock_rng_create); + lib->crypto->add_rng(lib->crypto, RNG_WEAK, + (rng_constructor_t)padlock_rng_create); + } if (this->features & PADLOCK_ACE2_ENABLED) { lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, diff --git a/src/libstrongswan/plugins/padlock/padlock_rng.c b/src/libstrongswan/plugins/padlock/padlock_rng.c new file mode 100644 index 000000000..50d9f0c43 --- /dev/null +++ b/src/libstrongswan/plugins/padlock/padlock_rng.c @@ -0,0 +1,136 @@ +/* + * 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 "padlock_rng.h" + +typedef struct private_padlock_rng_t private_padlock_rng_t; +typedef enum padlock_quality_factor_t padlock_quality_factor_t; + +/** + * Padlock RNG quality factors + */ +enum padlock_quality_factor_t { + /* Lowest quality: Reads 8 bytes */ + PADLOCK_QF0 = 0x00, + /* Medium quality: Reads 4 bytes */ + PADLOCK_QF1 = 0x01, + /* Better quality: Reads 2 bytes */ + PADLOCK_QF2 = 0x10, + /* Highest quality: Reads 1 byte */ + PADLOCK_QF3 = 0x11, +}; + +/** + * Private data of an padlock_rng_t object. + */ +struct private_padlock_rng_t { + + /** + * Public padlock_rng_t interface. + */ + padlock_rng_t public; + + /** + * Padlock quality factor + */ + padlock_quality_factor_t quality; +}; + +/** + * Get bytes from Padlock RNG. buf should have space for (len + 7) + */ +static void rng(char *buf, int len, int quality) +{ + while (len > 0)
+ { + int status; + + /* run XSTORE until we have all bytes needed. We do not use REP, as + * this should not be performance critical and it's easier this way. */ + asm volatile ( + ".byte 0x0F,0xA7,0xC0 \n\t"
+ : "=D"(buf), "=a"(status)
+ : "d"(quality), "D"(buf)); + + /* bits[0..4] of status word contains the number of bytes read */ + len -= status & 0x1F; + } +} + +/** + * Implementation of padlock_rng_t.allocate_bytes. + */ +static void allocate_bytes(private_padlock_rng_t *this, size_t bytes, + chunk_t *chunk) +{ + chunk->len = bytes; + /* padlock requires some additional bytes */ + chunk->ptr = malloc(bytes + 7); + + rng(chunk->ptr, chunk->len, this->quality); +} + +/** + * Implementation of padlock_rng_t.get_bytes. + */ +static void get_bytes(private_padlock_rng_t *this, size_t bytes, + u_int8_t *buffer) +{ + chunk_t chunk; + + /* Padlock needs a larger buffer than "bytes", we need a new buffer */ + allocate_bytes(this, bytes, &chunk); + memcpy(buffer, chunk.ptr, bytes); + chunk_clear(&chunk); +} + +/** + * Implementation of padlock_rng_t.destroy. + */ +static void destroy(private_padlock_rng_t *this) +{ + free(this); +} + +/* + * Described in header. + */ +padlock_rng_t *padlock_rng_create(rng_quality_t quality) +{ + private_padlock_rng_t *this = malloc_thing(private_padlock_rng_t); + + this->public.rng.get_bytes = (void (*) (rng_t *, size_t, u_int8_t*)) get_bytes; + this->public.rng.allocate_bytes = (void (*) (rng_t *, size_t, chunk_t*)) allocate_bytes; + this->public.rng.destroy = (void (*) (rng_t *))destroy; + + /* map RNG quality to Padlock quality factor */ + switch (quality) + { + case RNG_WEAK: + this->quality = PADLOCK_QF0; + break; + case RNG_STRONG: + this->quality = PADLOCK_QF1; + break; + case RNG_REAL: + this->quality = PADLOCK_QF3; + break; + } + + return &this->public; +} + diff --git a/src/libstrongswan/plugins/padlock/padlock_rng.h b/src/libstrongswan/plugins/padlock/padlock_rng.h new file mode 100644 index 000000000..a76ecd296 --- /dev/null +++ b/src/libstrongswan/plugins/padlock/padlock_rng.h @@ -0,0 +1,49 @@ +/* + * 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$ + */ + +/** + * @defgroup padlock_rng padlock_rng + * @{ @ingroup padlock + */ + +#ifndef PADLOCK_RNG_H_ +#define PADLOCK_RNG_H_ + +#include <crypto/rngs/rng.h> + +typedef struct padlock_rng_t padlock_rng_t; + +/** + * Hardware-RNG based on via Padlock. + */ +struct padlock_rng_t { + + /** + * Implements rng_t interface. + */ + rng_t rng; +}; + +/** + * Create a padlock_rng instance. + * + * @param quality required quality of randomness + * @return created random_rng_t + */ +padlock_rng_t *padlock_rng_create(rng_quality_t quality); + +#endif /* PADLOCK_RNG_ @}*/ |