summaryrefslogtreecommitdiff
path: root/src/libstrongswan/crypto
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2013-01-02 14:18:20 +0100
committerYves-Alexis Perez <corsac@debian.org>2013-01-02 14:18:20 +0100
commitc1343b3278cdf99533b7902744d15969f9d6fdc1 (patch)
treed5ed3dc5677a59260ec41cd39bb284d3e94c91b3 /src/libstrongswan/crypto
parentb34738ed08c2227300d554b139e2495ca5da97d6 (diff)
downloadvyos-strongswan-c1343b3278cdf99533b7902744d15969f9d6fdc1.tar.gz
vyos-strongswan-c1343b3278cdf99533b7902744d15969f9d6fdc1.zip
Imported Upstream version 5.0.1
Diffstat (limited to 'src/libstrongswan/crypto')
-rw-r--r--src/libstrongswan/crypto/aead.c45
-rw-r--r--src/libstrongswan/crypto/aead.h9
-rw-r--r--src/libstrongswan/crypto/crypters/crypter.h20
-rw-r--r--src/libstrongswan/crypto/crypto_factory.c104
-rw-r--r--src/libstrongswan/crypto/crypto_factory.h51
-rw-r--r--src/libstrongswan/crypto/crypto_tester.c371
-rw-r--r--src/libstrongswan/crypto/hashers/hasher.c116
-rw-r--r--src/libstrongswan/crypto/hashers/hasher.h53
-rw-r--r--src/libstrongswan/crypto/mac.h76
-rw-r--r--src/libstrongswan/crypto/nonce_gen.h59
-rw-r--r--src/libstrongswan/crypto/pkcs7.c1061
-rw-r--r--src/libstrongswan/crypto/pkcs7.h178
-rw-r--r--src/libstrongswan/crypto/pkcs9.c101
-rw-r--r--src/libstrongswan/crypto/pkcs9.h19
-rw-r--r--src/libstrongswan/crypto/prf_plus.c126
-rw-r--r--src/libstrongswan/crypto/prf_plus.h34
-rw-r--r--src/libstrongswan/crypto/prfs/mac_prf.c101
-rw-r--r--src/libstrongswan/crypto/prfs/mac_prf.h36
-rw-r--r--src/libstrongswan/crypto/prfs/prf.h19
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords.c416
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords.h109
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords_static.c324
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords_static.h25
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords_static.txt (renamed from src/libstrongswan/crypto/proposal/proposal_keywords.txt)8
-rw-r--r--src/libstrongswan/crypto/rngs/rng.c41
-rw-r--r--src/libstrongswan/crypto/rngs/rng.h39
-rw-r--r--src/libstrongswan/crypto/signers/mac_signer.c139
-rw-r--r--src/libstrongswan/crypto/signers/mac_signer.h41
-rw-r--r--src/libstrongswan/crypto/signers/signer.h20
-rw-r--r--src/libstrongswan/crypto/transform.c7
-rw-r--r--src/libstrongswan/crypto/transform.h3
31 files changed, 3060 insertions, 691 deletions
diff --git a/src/libstrongswan/crypto/aead.c b/src/libstrongswan/crypto/aead.c
index 51cb05909..02fb8d50a 100644
--- a/src/libstrongswan/crypto/aead.c
+++ b/src/libstrongswan/crypto/aead.c
@@ -40,26 +40,41 @@ struct private_aead_t {
signer_t *signer;
};
-METHOD(aead_t, encrypt, void,
+METHOD(aead_t, encrypt, bool,
private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
chunk_t *encrypted)
{
chunk_t encr, sig;
- this->signer->get_signature(this->signer, assoc, NULL);
- this->signer->get_signature(this->signer, iv, NULL);
+ if (!this->signer->get_signature(this->signer, assoc, NULL) ||
+ !this->signer->get_signature(this->signer, iv, NULL))
+ {
+ return FALSE;
+ }
if (encrypted)
{
- this->crypter->encrypt(this->crypter, plain, iv, &encr);
- this->signer->allocate_signature(this->signer, encr, &sig);
+ if (!this->crypter->encrypt(this->crypter, plain, iv, &encr))
+ {
+ return FALSE;
+ }
+ if (!this->signer->allocate_signature(this->signer, encr, &sig))
+ {
+ free(encr.ptr);
+ return FALSE;
+ }
*encrypted = chunk_cat("cmm", iv, encr, sig);
}
else
{
- this->crypter->encrypt(this->crypter, plain, iv, NULL);
- this->signer->get_signature(this->signer, plain, plain.ptr + plain.len);
+ if (!this->crypter->encrypt(this->crypter, plain, iv, NULL) ||
+ !this->signer->get_signature(this->signer,
+ plain, plain.ptr + plain.len))
+ {
+ return FALSE;
+ }
}
+ return TRUE;
}
METHOD(aead_t, decrypt, bool,
@@ -80,15 +95,17 @@ METHOD(aead_t, decrypt, bool,
chunk_split(encrypted, "mm", encrypted.len - sig.len,
&encrypted, sig.len, &sig);
- this->signer->get_signature(this->signer, assoc, NULL);
- this->signer->get_signature(this->signer, iv, NULL);
+ if (!this->signer->get_signature(this->signer, assoc, NULL) ||
+ !this->signer->get_signature(this->signer, iv, NULL))
+ {
+ return FALSE;
+ }
if (!this->signer->verify_signature(this->signer, encrypted, sig))
{
DBG1(DBG_LIB, "MAC verification failed");
return FALSE;
}
- this->crypter->decrypt(this->crypter, encrypted, iv, plain);
- return TRUE;
+ return this->crypter->decrypt(this->crypter, encrypted, iv, plain);
}
METHOD(aead_t, get_block_size, size_t,
@@ -116,7 +133,7 @@ METHOD(aead_t, get_key_size, size_t,
this->signer->get_key_size(this->signer);
}
-METHOD(aead_t, set_key, void,
+METHOD(aead_t, set_key, bool,
private_aead_t *this, chunk_t key)
{
chunk_t sig, enc;
@@ -124,8 +141,8 @@ METHOD(aead_t, set_key, void,
chunk_split(key, "mm", this->signer->get_key_size(this->signer), &sig,
this->crypter->get_key_size(this->crypter), &enc);
- this->signer->set_key(this->signer, sig);
- this->crypter->set_key(this->crypter, enc);
+ return this->signer->set_key(this->signer, sig) &&
+ this->crypter->set_key(this->crypter, enc);
}
METHOD(aead_t, destroy, void,
diff --git a/src/libstrongswan/crypto/aead.h b/src/libstrongswan/crypto/aead.h
index 3f6abb4f9..ec526a3d9 100644
--- a/src/libstrongswan/crypto/aead.h
+++ b/src/libstrongswan/crypto/aead.h
@@ -45,9 +45,10 @@ struct aead_t {
* @param assoc associated data to sign
* @param iv initialization vector
* @param encrypted allocated encryption result
+ * @return TRUE if successfully encrypted
*/
- void (*encrypt)(aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
- chunk_t *encrypted);
+ bool (*encrypt)(aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
+ chunk_t *encrypted) __attribute__((warn_unused_result));
/**
* Decrypt and verify data, verify associated data.
@@ -98,8 +99,10 @@ struct aead_t {
* Set the key for encryption and authentication.
*
* @param key encryption and authentication key
+ * @return TRUE if key set successfully
*/
- void (*set_key)(aead_t *this, chunk_t key);
+ bool (*set_key)(aead_t *this,
+ chunk_t key) __attribute__((warn_unused_result));
/**
* Destroy a aead_t.
diff --git a/src/libstrongswan/crypto/crypters/crypter.h b/src/libstrongswan/crypto/crypters/crypter.h
index 3bf039681..fe854f53d 100644
--- a/src/libstrongswan/crypto/crypters/crypter.h
+++ b/src/libstrongswan/crypto/crypters/crypter.h
@@ -90,9 +90,10 @@ struct crypter_t {
* @param data data to encrypt
* @param iv initializing vector
* @param encrypted chunk to allocate encrypted data, or NULL
+ * @return TRUE if encryption successful
*/
- void (*encrypt) (crypter_t *this, chunk_t data, chunk_t iv,
- chunk_t *encrypted);
+ bool (*encrypt)(crypter_t *this, chunk_t data, chunk_t iv,
+ chunk_t *encrypted) __attribute__((warn_unused_result));
/**
* Decrypt a chunk of data and allocate space for the decrypted value.
@@ -104,9 +105,10 @@ struct crypter_t {
* @param data data to decrypt
* @param iv initializing vector
* @param encrypted chunk to allocate decrypted data, or NULL
+ * @return TRUE if decryption successful
*/
- void (*decrypt) (crypter_t *this, chunk_t data, chunk_t iv,
- chunk_t *decrypted);
+ bool (*decrypt)(crypter_t *this, chunk_t data, chunk_t iv,
+ chunk_t *decrypted) __attribute__((warn_unused_result));
/**
* Get the block size of the crypto algorithm.
@@ -117,7 +119,7 @@ struct crypter_t {
*
* @return block size in bytes
*/
- size_t (*get_block_size) (crypter_t *this);
+ size_t (*get_block_size)(crypter_t *this);
/**
* Get the IV size of the crypto algorithm.
@@ -135,7 +137,7 @@ struct crypter_t {
*
* @return key size in bytes
*/
- size_t (*get_key_size) (crypter_t *this);
+ size_t (*get_key_size)(crypter_t *this);
/**
* Set the key.
@@ -143,13 +145,15 @@ struct crypter_t {
* The length of the key must match get_key_size().
*
* @param key key to set
+ * @return TRUE if key set successfully
*/
- void (*set_key) (crypter_t *this, chunk_t key);
+ bool (*set_key)(crypter_t *this,
+ chunk_t key) __attribute__((warn_unused_result));
/**
* Destroys a crypter_t object.
*/
- void (*destroy) (crypter_t *this);
+ void (*destroy)(crypter_t *this);
};
/**
diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c
index 2d13896d6..3736ae38f 100644
--- a/src/libstrongswan/crypto/crypto_factory.c
+++ b/src/libstrongswan/crypto/crypto_factory.c
@@ -50,6 +50,7 @@ struct entry_t {
hasher_constructor_t create_hasher;
prf_constructor_t create_prf;
rng_constructor_t create_rng;
+ nonce_gen_constructor_t create_nonce_gen;
dh_constructor_t create_dh;
void *create;
};
@@ -98,6 +99,11 @@ struct private_crypto_factory_t {
linked_list_t *rngs;
/**
+ * registered nonce generators, as entry_t
+ */
+ linked_list_t *nonce_gens;
+
+ /**
* registered diffie hellman, as entry_t
*/
linked_list_t *dhs;
@@ -329,34 +335,49 @@ METHOD(crypto_factory_t, create_rng, rng_t*,
return NULL;
}
+METHOD(crypto_factory_t, create_nonce_gen, nonce_gen_t*,
+ private_crypto_factory_t *this)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ nonce_gen_t *nonce_gen = NULL;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->nonce_gens->create_enumerator(this->nonce_gens);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ nonce_gen = entry->create_nonce_gen();
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return nonce_gen;
+}
+
METHOD(crypto_factory_t, create_dh, diffie_hellman_t*,
private_crypto_factory_t *this, diffie_hellman_group_t group, ...)
{
enumerator_t *enumerator;
entry_t *entry;
+ va_list args;
+ chunk_t g = chunk_empty, p = chunk_empty;
diffie_hellman_t *diffie_hellman = NULL;
+ if (group == MODP_CUSTOM)
+ {
+ va_start(args, group);
+ g = va_arg(args, chunk_t);
+ p = va_arg(args, chunk_t);
+ va_end(args);
+ }
+
this->lock->read_lock(this->lock);
enumerator = this->dhs->create_enumerator(this->dhs);
while (enumerator->enumerate(enumerator, &entry))
{
if (entry->algo == group)
{
- if (group == MODP_CUSTOM)
- {
- va_list args;
- chunk_t g, p;
-
- va_start(args, group);
- g = va_arg(args, chunk_t);
- p = va_arg(args, chunk_t);
- va_end(args);
- diffie_hellman = entry->create_dh(MODP_CUSTOM, g, p);
- }
- else
- {
- diffie_hellman = entry->create_dh(group);
- }
+ diffie_hellman = entry->create_dh(group, g, p);
if (diffie_hellman)
{
break;
@@ -618,6 +639,33 @@ METHOD(crypto_factory_t, remove_rng, void,
this->lock->unlock(this->lock);
}
+METHOD(crypto_factory_t, add_nonce_gen, void,
+ private_crypto_factory_t *this, const char *plugin_name,
+ nonce_gen_constructor_t create)
+{
+ add_entry(this, this->nonce_gens, 0, plugin_name, 0, create);
+}
+
+METHOD(crypto_factory_t, remove_nonce_gen, void,
+ private_crypto_factory_t *this, nonce_gen_constructor_t create)
+{
+ entry_t *entry;
+ enumerator_t *enumerator;
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->nonce_gens->create_enumerator(this->nonce_gens);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->create_nonce_gen == create)
+ {
+ this->nonce_gens->remove_at(this->nonce_gens, enumerator);
+ free(entry);
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
METHOD(crypto_factory_t, add_dh, void,
private_crypto_factory_t *this, diffie_hellman_group_t group,
const char *plugin_name, dh_constructor_t create)
@@ -756,7 +804,7 @@ METHOD(crypto_factory_t, create_prf_enumerator, enumerator_t*,
}
/**
- * Filter function to enumerate algorithm, not entry
+ * Filter function to enumerate group, not entry
*/
static bool dh_filter(void *n, entry_t **entry, diffie_hellman_group_t *group,
void *i2, const char **plugin_name)
@@ -773,7 +821,7 @@ METHOD(crypto_factory_t, create_dh_enumerator, enumerator_t*,
}
/**
- * Filter function to enumerate algorithm, not entry
+ * Filter function to enumerate strength, not entry
*/
static bool rng_filter(void *n, entry_t **entry, rng_quality_t *quality,
void *i2, const char **plugin_name)
@@ -788,6 +836,22 @@ METHOD(crypto_factory_t, create_rng_enumerator, enumerator_t*,
{
return create_enumerator(this, this->rngs, rng_filter);
}
+
+/**
+ * Filter function to enumerate plugin name, not entry
+ */
+static bool nonce_gen_filter(void *n, entry_t **entry, const char **plugin_name)
+{
+ *plugin_name = (*entry)->plugin_name;
+ return TRUE;
+}
+
+METHOD(crypto_factory_t, create_nonce_gen_enumerator, enumerator_t*,
+ private_crypto_factory_t *this)
+{
+ return create_enumerator(this, this->nonce_gens, nonce_gen_filter);
+}
+
METHOD(crypto_factory_t, add_test_vector, void,
private_crypto_factory_t *this, transform_type_t type, void *vector)
{
@@ -820,6 +884,7 @@ METHOD(crypto_factory_t, destroy, void,
this->hashers->destroy(this->hashers);
this->prfs->destroy(this->prfs);
this->rngs->destroy(this->rngs);
+ this->nonce_gens->destroy(this->nonce_gens);
this->dhs->destroy(this->dhs);
this->tester->destroy(this->tester);
this->lock->destroy(this->lock);
@@ -841,6 +906,7 @@ crypto_factory_t *crypto_factory_create()
.create_hasher = _create_hasher,
.create_prf = _create_prf,
.create_rng = _create_rng,
+ .create_nonce_gen = _create_nonce_gen,
.create_dh = _create_dh,
.add_crypter = _add_crypter,
.remove_crypter = _remove_crypter,
@@ -854,6 +920,8 @@ crypto_factory_t *crypto_factory_create()
.remove_prf = _remove_prf,
.add_rng = _add_rng,
.remove_rng = _remove_rng,
+ .add_nonce_gen = _add_nonce_gen,
+ .remove_nonce_gen = _remove_nonce_gen,
.add_dh = _add_dh,
.remove_dh = _remove_dh,
.create_crypter_enumerator = _create_crypter_enumerator,
@@ -863,6 +931,7 @@ crypto_factory_t *crypto_factory_create()
.create_prf_enumerator = _create_prf_enumerator,
.create_dh_enumerator = _create_dh_enumerator,
.create_rng_enumerator = _create_rng_enumerator,
+ .create_nonce_gen_enumerator = _create_nonce_gen_enumerator,
.add_test_vector = _add_test_vector,
.destroy = _destroy,
},
@@ -872,6 +941,7 @@ crypto_factory_t *crypto_factory_create()
.hashers = linked_list_create(),
.prfs = linked_list_create(),
.rngs = linked_list_create(),
+ .nonce_gens = linked_list_create(),
.dhs = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
.tester = crypto_tester_create(),
diff --git a/src/libstrongswan/crypto/crypto_factory.h b/src/libstrongswan/crypto/crypto_factory.h
index 8e5db6355..611ca0bbb 100644
--- a/src/libstrongswan/crypto/crypto_factory.h
+++ b/src/libstrongswan/crypto/crypto_factory.h
@@ -30,6 +30,7 @@ typedef struct crypto_factory_t crypto_factory_t;
#include <crypto/hashers/hasher.h>
#include <crypto/prfs/prf.h>
#include <crypto/rngs/rng.h>
+#include <crypto/nonce_gen.h>
#include <crypto/diffie_hellman.h>
#include <crypto/transform.h>
@@ -66,6 +67,11 @@ typedef prf_t* (*prf_constructor_t)(pseudo_random_function_t algo);
typedef rng_t* (*rng_constructor_t)(rng_quality_t quality);
/**
+ * Constructor function for nonce generators
+ */
+typedef nonce_gen_t* (*nonce_gen_constructor_t)();
+
+/**
* Constructor function for diffie hellman
*
* The DH constructor accepts additional arguments for:
@@ -132,6 +138,13 @@ struct crypto_factory_t {
rng_t* (*create_rng)(crypto_factory_t *this, rng_quality_t quality);
/**
+ * Create a nonce generator instance.
+ *
+ * @return nonce_gen_t instance, NULL if not supported
+ */
+ nonce_gen_t* (*create_nonce_gen)(crypto_factory_t *this);
+
+ /**
* Create a diffie hellman instance.
*
* Additional arguments are passed to the DH constructor.
@@ -253,6 +266,23 @@ struct crypto_factory_t {
void (*remove_rng)(crypto_factory_t *this, rng_constructor_t create);
/**
+ * Register a nonce generator.
+ *
+ * @param plugin_name plugin that registered this algorithm
+ * @param create constructor function for that nonce generator
+ */
+ void (*add_nonce_gen)(crypto_factory_t *this, const char *plugin_name,
+ nonce_gen_constructor_t create);
+
+ /**
+ * Unregister a nonce generator.
+ *
+ * @param create constructor function to unregister
+ */
+ void (*remove_nonce_gen)(crypto_factory_t *this,
+ nonce_gen_constructor_t create);
+
+ /**
* Register a diffie hellman constructor.
*
* @param group dh group to constructor
@@ -273,53 +303,60 @@ struct crypto_factory_t {
/**
* Create an enumerator over all registered crypter algorithms.
*
- * @return enumerator over encryption_algorithm_t
+ * @return enumerator over encryption_algorithm_t, plugin
*/
enumerator_t* (*create_crypter_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered aead algorithms.
*
- * @return enumerator over encryption_algorithm_t
+ * @return enumerator over encryption_algorithm_t, plugin
*/
enumerator_t* (*create_aead_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered signer algorithms.
*
- * @return enumerator over integrity_algorithm_t
+ * @return enumerator over integrity_algorithm_t, plugin
*/
enumerator_t* (*create_signer_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered hasher algorithms.
*
- * @return enumerator over hash_algorithm_t
+ * @return enumerator over hash_algorithm_t, plugin
*/
enumerator_t* (*create_hasher_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered PRFs.
*
- * @return enumerator over pseudo_random_function_t
+ * @return enumerator over pseudo_random_function_t, plugin
*/
enumerator_t* (*create_prf_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered diffie hellman groups.
*
- * @return enumerator over diffie_hellman_group_t
+ * @return enumerator over diffie_hellman_group_t, plugin
*/
enumerator_t* (*create_dh_enumerator)(crypto_factory_t *this);
/**
* Create an enumerator over all registered random generators.
*
- * @return enumerator over rng_quality_t
+ * @return enumerator over rng_quality_t, plugin
*/
enumerator_t* (*create_rng_enumerator)(crypto_factory_t *this);
/**
+ * Create an enumerator over all registered nonce generators.
+ *
+ * @return enumerator over plugin
+ */
+ enumerator_t* (*create_nonce_gen_enumerator)(crypto_factory_t *this);
+
+ /**
* Add a test vector to the crypto factory.
*
* @param type type of the test vector
diff --git a/src/libstrongswan/crypto/crypto_tester.c b/src/libstrongswan/crypto/crypto_tester.c
index 8b1daa885..01e84a133 100644
--- a/src/libstrongswan/crypto/crypto_tester.c
+++ b/src/libstrongswan/crypto/crypto_tester.c
@@ -151,7 +151,10 @@ static u_int bench_crypter(private_crypto_tester_t *this,
memset(iv, 0x56, sizeof(iv));
memset(key, 0x12, sizeof(key));
- crypter->set_key(crypter, chunk_from_thing(key));
+ if (!crypter->set_key(crypter, chunk_from_thing(key)))
+ {
+ return 0;
+ }
buf = chunk_alloc(this->bench_size);
memset(buf.ptr, 0x34, buf.len);
@@ -160,10 +163,14 @@ static u_int bench_crypter(private_crypto_tester_t *this,
start_timing(&start);
while (end_timing(&start) < this->bench_time)
{
- crypter->encrypt(crypter, buf, chunk_from_thing(iv), NULL);
- runs++;
- crypter->decrypt(crypter, buf, chunk_from_thing(iv), NULL);
- runs++;
+ if (crypter->encrypt(crypter, buf, chunk_from_thing(iv), NULL))
+ {
+ runs++;
+ }
+ if (crypter->decrypt(crypter, buf, chunk_from_thing(iv), NULL))
+ {
+ runs++;
+ }
}
free(buf.ptr);
crypter->destroy(crypter);
@@ -186,7 +193,7 @@ METHOD(crypto_tester_t, test_crypter, bool,
while (enumerator->enumerate(enumerator, &vector))
{
crypter_t *crypter;
- chunk_t key, plain, cipher, iv;
+ chunk_t key, iv, plain = chunk_empty, cipher = chunk_empty;
if (vector->alg != alg)
{
@@ -196,53 +203,69 @@ METHOD(crypto_tester_t, test_crypter, bool,
{ /* test only vectors with a specific key size, if key size given */
continue;
}
+
+ tested++;
+ failed = TRUE;
crypter = create(alg, vector->key_size);
if (!crypter)
{
DBG1(DBG_LIB, "%N[%s]: %u bit key size not supported",
encryption_algorithm_names, alg, plugin_name,
BITS_PER_BYTE * vector->key_size);
- failed = TRUE;
continue;
}
- failed = FALSE;
- tested++;
-
key = chunk_create(vector->key, crypter->get_key_size(crypter));
- crypter->set_key(crypter, key);
+ if (!crypter->set_key(crypter, key))
+ {
+ goto failure;
+ }
iv = chunk_create(vector->iv, crypter->get_iv_size(crypter));
/* allocated encryption */
plain = chunk_create(vector->plain, vector->len);
- crypter->encrypt(crypter, plain, iv, &cipher);
+ if (!crypter->encrypt(crypter, plain, iv, &cipher))
+ {
+ goto failure;
+ }
if (!memeq(vector->cipher, cipher.ptr, cipher.len))
{
- failed = TRUE;
+ goto failure;
}
/* inline decryption */
- crypter->decrypt(crypter, cipher, iv, NULL);
+ if (!crypter->decrypt(crypter, cipher, iv, NULL))
+ {
+ goto failure;
+ }
if (!memeq(vector->plain, cipher.ptr, cipher.len))
{
- failed = TRUE;
+ goto failure;
}
- free(cipher.ptr);
/* allocated decryption */
- cipher = chunk_create(vector->cipher, vector->len);
- crypter->decrypt(crypter, cipher, iv, &plain);
+ if (!crypter->decrypt(crypter,
+ chunk_create(vector->cipher, vector->len), iv, &plain))
+ {
+ goto failure;
+ }
if (!memeq(vector->plain, plain.ptr, plain.len))
{
- failed = TRUE;
+ goto failure;
}
/* inline encryption */
- crypter->encrypt(crypter, plain, iv, NULL);
+ if (!crypter->encrypt(crypter, plain, iv, NULL))
+ {
+ goto failure;
+ }
if (!memeq(vector->cipher, plain.ptr, plain.len))
{
- failed = TRUE;
+ goto failure;
}
- free(plain.ptr);
+ failed = FALSE;
+failure:
crypter->destroy(crypter);
+ chunk_free(&cipher);
+ chunk_free(&plain);
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
@@ -306,7 +329,10 @@ static u_int bench_aead(private_crypto_tester_t *this,
memset(iv, 0x56, sizeof(iv));
memset(key, 0x12, sizeof(key));
memset(assoc, 0x78, sizeof(assoc));
- aead->set_key(aead, chunk_from_thing(key));
+ if (!aead->set_key(aead, chunk_from_thing(key)))
+ {
+ return 0;
+ }
icv = aead->get_icv_size(aead);
buf = chunk_alloc(this->bench_size + icv);
@@ -317,12 +343,16 @@ static u_int bench_aead(private_crypto_tester_t *this,
start_timing(&start);
while (end_timing(&start) < this->bench_time)
{
- aead->encrypt(aead, buf, chunk_from_thing(assoc),
- chunk_from_thing(iv), NULL);
- runs += 2;
- aead->decrypt(aead, chunk_create(buf.ptr, buf.len + icv),
- chunk_from_thing(assoc), chunk_from_thing(iv), NULL);
- runs += 2;
+ if (aead->encrypt(aead, buf, chunk_from_thing(assoc),
+ chunk_from_thing(iv), NULL))
+ {
+ runs += 2;
+ }
+ if (aead->decrypt(aead, chunk_create(buf.ptr, buf.len + icv),
+ chunk_from_thing(assoc), chunk_from_thing(iv), NULL))
+ {
+ runs += 2;
+ }
}
free(buf.ptr);
aead->destroy(aead);
@@ -345,7 +375,7 @@ METHOD(crypto_tester_t, test_aead, bool,
while (enumerator->enumerate(enumerator, &vector))
{
aead_t *aead;
- chunk_t key, plain, cipher, iv, assoc;
+ chunk_t key, iv, assoc, plain = chunk_empty, cipher = chunk_empty;
size_t icv;
if (vector->alg != alg)
@@ -356,63 +386,72 @@ METHOD(crypto_tester_t, test_aead, bool,
{ /* test only vectors with a specific key size, if key size given */
continue;
}
+
+ tested++;
+ failed = TRUE;
aead = create(alg, vector->key_size);
if (!aead)
{
DBG1(DBG_LIB, "%N[%s]: %u bit key size not supported",
encryption_algorithm_names, alg, plugin_name,
BITS_PER_BYTE * vector->key_size);
- failed = TRUE;
continue;
}
- failed = FALSE;
- tested++;
-
key = chunk_create(vector->key, aead->get_key_size(aead));
- aead->set_key(aead, key);
+ if (!aead->set_key(aead, key))
+ {
+ goto failure;
+ }
iv = chunk_create(vector->iv, aead->get_iv_size(aead));
assoc = chunk_create(vector->adata, vector->alen);
icv = aead->get_icv_size(aead);
/* allocated encryption */
plain = chunk_create(vector->plain, vector->len);
- aead->encrypt(aead, plain, assoc, iv, &cipher);
+ if (!aead->encrypt(aead, plain, assoc, iv, &cipher))
+ {
+ goto failure;
+ }
if (!memeq(vector->cipher, cipher.ptr, cipher.len))
{
- failed = TRUE;
+ goto failure;
}
/* inline decryption */
if (!aead->decrypt(aead, cipher, assoc, iv, NULL))
{
- failed = TRUE;
+ goto failure;
}
if (!memeq(vector->plain, cipher.ptr, cipher.len - icv))
{
- failed = TRUE;
+ goto failure;
}
- free(cipher.ptr);
/* allocated decryption */
- cipher = chunk_create(vector->cipher, vector->len + icv);
- if (!aead->decrypt(aead, cipher, assoc, iv, &plain))
+ if (!aead->decrypt(aead, chunk_create(vector->cipher, vector->len + icv),
+ assoc, iv, &plain))
{
- plain = chunk_empty;
- failed = TRUE;
+ goto failure;
}
- else if (!memeq(vector->plain, plain.ptr, plain.len))
+ if (!memeq(vector->plain, plain.ptr, plain.len))
{
- failed = TRUE;
+ goto failure;
}
plain.ptr = realloc(plain.ptr, plain.len + icv);
/* inline encryption */
- aead->encrypt(aead, plain, assoc, iv, NULL);
+ if (!aead->encrypt(aead, plain, assoc, iv, NULL))
+ {
+ goto failure;
+ }
if (!memeq(vector->cipher, plain.ptr, plain.len + icv))
{
- failed = TRUE;
+ goto failure;
}
- free(plain.ptr);
+ failed = FALSE;
+failure:
aead->destroy(aead);
+ chunk_free(&cipher);
+ chunk_free(&plain);
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
@@ -458,7 +497,7 @@ METHOD(crypto_tester_t, test_aead, bool,
* Benchmark a signer
*/
static u_int bench_signer(private_crypto_tester_t *this,
- encryption_algorithm_t alg, signer_constructor_t create)
+ integrity_algorithm_t alg, signer_constructor_t create)
{
signer_t *signer;
@@ -472,7 +511,10 @@ static u_int bench_signer(private_crypto_tester_t *this,
u_int runs;
memset(key, 0x12, sizeof(key));
- signer->set_key(signer, chunk_from_thing(key));
+ if (!signer->set_key(signer, chunk_from_thing(key)))
+ {
+ return 0;
+ }
buf = chunk_alloc(this->bench_size);
memset(buf.ptr, 0x34, buf.len);
@@ -481,10 +523,14 @@ static u_int bench_signer(private_crypto_tester_t *this,
start_timing(&start);
while (end_timing(&start) < this->bench_time)
{
- signer->get_signature(signer, buf, mac);
- runs++;
- signer->verify_signature(signer, buf, chunk_from_thing(mac));
- runs++;
+ if (signer->get_signature(signer, buf, mac))
+ {
+ runs++;
+ }
+ if (signer->verify_signature(signer, buf, chunk_from_thing(mac)))
+ {
+ runs++;
+ }
}
free(buf.ptr);
signer->destroy(signer);
@@ -507,7 +553,7 @@ METHOD(crypto_tester_t, test_signer, bool,
while (enumerator->enumerate(enumerator, &vector))
{
signer_t *signer;
- chunk_t key, data, mac;
+ chunk_t key, data, mac = chunk_empty;
if (vector->alg != alg)
{
@@ -515,63 +561,79 @@ METHOD(crypto_tester_t, test_signer, bool,
}
tested++;
+ failed = TRUE;
signer = create(alg);
if (!signer)
{
DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
integrity_algorithm_names, alg, plugin_name);
- failed = TRUE;
break;
}
- failed = FALSE;
-
key = chunk_create(vector->key, signer->get_key_size(signer));
- signer->set_key(signer, key);
-
+ if (!signer->set_key(signer, key))
+ {
+ goto failure;
+ }
/* allocated signature */
data = chunk_create(vector->data, vector->len);
- signer->allocate_signature(signer, data, &mac);
+ if (!signer->allocate_signature(signer, data, &mac))
+ {
+ goto failure;
+ }
if (mac.len != signer->get_block_size(signer))
{
- failed = TRUE;
+ goto failure;
}
if (!memeq(vector->mac, mac.ptr, mac.len))
{
- failed = TRUE;
+ goto failure;
}
/* signature to existing buffer */
memset(mac.ptr, 0, mac.len);
- signer->get_signature(signer, data, mac.ptr);
+ if (!signer->get_signature(signer, data, mac.ptr))
+ {
+ goto failure;
+ }
if (!memeq(vector->mac, mac.ptr, mac.len))
{
- failed = TRUE;
+ goto failure;
}
/* signature verification, good case */
if (!signer->verify_signature(signer, data, mac))
{
- failed = TRUE;
+ goto failure;
}
/* signature verification, bad case */
*(mac.ptr + mac.len - 1) += 1;
if (signer->verify_signature(signer, data, mac))
{
- failed = TRUE;
+ goto failure;
}
/* signature to existing buffer, using append mode */
if (data.len > 2)
{
- signer->allocate_signature(signer, chunk_create(data.ptr, 1), NULL);
- signer->get_signature(signer, chunk_create(data.ptr + 1, 1), NULL);
+ if (!signer->allocate_signature(signer,
+ chunk_create(data.ptr, 1), NULL))
+ {
+ goto failure;
+ }
+ if (!signer->get_signature(signer,
+ chunk_create(data.ptr + 1, 1), NULL))
+ {
+ goto failure;
+ }
if (!signer->verify_signature(signer, chunk_skip(data, 2),
chunk_create(vector->mac, mac.len)))
{
- failed = TRUE;
+ goto failure;
}
}
- free(mac.ptr);
+ failed = FALSE;
+failure:
signer->destroy(signer);
+ chunk_free(&mac);
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
@@ -627,8 +689,10 @@ static u_int bench_hasher(private_crypto_tester_t *this,
start_timing(&start);
while (end_timing(&start) < this->bench_time)
{
- hasher->get_hash(hasher, buf, hash);
- runs++;
+ if (hasher->get_hash(hasher, buf, hash))
+ {
+ runs++;
+ }
}
free(buf.ptr);
hasher->destroy(hasher);
@@ -659,50 +723,73 @@ METHOD(crypto_tester_t, test_hasher, bool,
}
tested++;
+ failed = TRUE;
hasher = create(alg);
if (!hasher)
{
DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
hash_algorithm_names, alg, plugin_name);
- failed = TRUE;
break;
}
- failed = FALSE;
-
/* allocated hash */
data = chunk_create(vector->data, vector->len);
- hasher->allocate_hash(hasher, data, &hash);
+ if (!hasher->allocate_hash(hasher, data, &hash))
+ {
+ goto failure;
+ }
if (hash.len != hasher->get_hash_size(hasher))
{
- failed = TRUE;
+ goto failure;
}
if (!memeq(vector->hash, hash.ptr, hash.len))
{
- failed = TRUE;
+ goto failure;
}
- /* hash to existing buffer */
+ /* hash to existing buffer, with a reset */
memset(hash.ptr, 0, hash.len);
- hasher->get_hash(hasher, data, hash.ptr);
+ if (!hasher->get_hash(hasher, data, NULL))
+ {
+ goto failure;
+ }
+ if (!hasher->reset(hasher))
+ {
+ goto failure;
+ }
+ if (!hasher->get_hash(hasher, data, hash.ptr))
+ {
+ goto failure;
+ }
if (!memeq(vector->hash, hash.ptr, hash.len))
{
- failed = TRUE;
+ goto failure;
}
/* hasher to existing buffer, using append mode */
if (data.len > 2)
{
memset(hash.ptr, 0, hash.len);
- hasher->allocate_hash(hasher, chunk_create(data.ptr, 1), NULL);
- hasher->get_hash(hasher, chunk_create(data.ptr + 1, 1), NULL);
- hasher->get_hash(hasher, chunk_skip(data, 2), hash.ptr);
+ if (!hasher->allocate_hash(hasher, chunk_create(data.ptr, 1), NULL))
+ {
+ goto failure;
+ }
+ if (!hasher->get_hash(hasher, chunk_create(data.ptr + 1, 1), NULL))
+ {
+ goto failure;
+ }
+ if (!hasher->get_hash(hasher, chunk_skip(data, 2), hash.ptr))
+ {
+ goto failure;
+ }
if (!memeq(vector->hash, hash.ptr, hash.len))
{
- failed = TRUE;
+ goto failure;
}
}
- free(hash.ptr);
+ failed = FALSE;
+failure:
hasher->destroy(hasher);
+ chunk_free(&hash);
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
@@ -746,11 +833,18 @@ static u_int bench_prf(private_crypto_tester_t *this,
prf = create(alg);
if (prf)
{
- char bytes[prf->get_block_size(prf)];
+ char bytes[prf->get_block_size(prf)], key[prf->get_block_size(prf)];
chunk_t buf;
struct timespec start;
u_int runs;
+ memset(key, 0x56, prf->get_block_size(prf));
+ if (!prf->set_key(prf, chunk_create(key, prf->get_block_size(prf))))
+ {
+ prf->destroy(prf);
+ return 0;
+ }
+
buf = chunk_alloc(this->bench_size);
memset(buf.ptr, 0x34, buf.len);
@@ -758,8 +852,10 @@ static u_int bench_prf(private_crypto_tester_t *this,
start_timing(&start);
while (end_timing(&start) < this->bench_time)
{
- prf->get_bytes(prf, buf, bytes);
- runs++;
+ if (prf->get_bytes(prf, buf, bytes))
+ {
+ runs++;
+ }
}
free(buf.ptr);
prf->destroy(prf);
@@ -782,7 +878,7 @@ METHOD(crypto_tester_t, test_prf, bool,
while (enumerator->enumerate(enumerator, &vector))
{
prf_t *prf;
- chunk_t key, seed, out;
+ chunk_t key, seed, out = chunk_empty;
if (vector->alg != alg)
{
@@ -790,41 +886,50 @@ METHOD(crypto_tester_t, test_prf, bool,
}
tested++;
+ failed = TRUE;
prf = create(alg);
if (!prf)
{
DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
pseudo_random_function_names, alg, plugin_name);
- failed = TRUE;
break;
}
- failed = FALSE;
-
key = chunk_create(vector->key, vector->key_size);
- prf->set_key(prf, key);
-
+ if (!prf->set_key(prf, key))
+ {
+ goto failure;
+ }
/* allocated bytes */
seed = chunk_create(vector->seed, vector->len);
- prf->allocate_bytes(prf, seed, &out);
+ if (!prf->allocate_bytes(prf, seed, &out))
+ {
+ goto failure;
+ }
if (out.len != prf->get_block_size(prf))
{
- failed = TRUE;
+ goto failure;
}
if (!memeq(vector->out, out.ptr, out.len))
{
- failed = TRUE;
+ goto failure;
}
/* bytes to existing buffer */
memset(out.ptr, 0, out.len);
if (vector->stateful)
{
- prf->set_key(prf, key);
+ if (!prf->set_key(prf, key))
+ {
+ goto failure;
+ }
+ }
+ if (!prf->get_bytes(prf, seed, out.ptr))
+ {
+ goto failure;
}
- prf->get_bytes(prf, seed, out.ptr);
if (!memeq(vector->out, out.ptr, out.len))
{
- failed = TRUE;
+ goto failure;
}
/* bytes to existing buffer, using append mode */
if (seed.len > 2)
@@ -832,19 +937,33 @@ METHOD(crypto_tester_t, test_prf, bool,
memset(out.ptr, 0, out.len);
if (vector->stateful)
{
- prf->set_key(prf, key);
+ if (!prf->set_key(prf, key))
+ {
+ goto failure;
+ }
+ }
+ if (!prf->allocate_bytes(prf, chunk_create(seed.ptr, 1), NULL))
+ {
+ goto failure;
+ }
+ if (!prf->get_bytes(prf, chunk_create(seed.ptr + 1, 1), NULL))
+ {
+ goto failure;
+ }
+ if (!prf->get_bytes(prf, chunk_skip(seed, 2), out.ptr))
+ {
+ goto failure;
}
- prf->allocate_bytes(prf, chunk_create(seed.ptr, 1), NULL);
- prf->get_bytes(prf, chunk_create(seed.ptr + 1, 1), NULL);
- prf->get_bytes(prf, chunk_skip(seed, 2), out.ptr);
if (!memeq(vector->out, out.ptr, out.len))
{
- failed = TRUE;
+ goto failure;
}
}
- free(out.ptr);
+ failed = FALSE;
+failure:
prf->destroy(prf);
+ chunk_free(&out);
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
@@ -897,7 +1016,11 @@ static u_int bench_rng(private_crypto_tester_t *this,
start_timing(&start);
while (end_timing(&start) < this->bench_time)
{
- rng->get_bytes(rng, buf.len, buf.ptr);
+ if (!rng->get_bytes(rng, buf.len, buf.ptr))
+ {
+ runs = 0;
+ break;
+ }
runs++;
}
free(buf.ptr);
@@ -927,8 +1050,8 @@ METHOD(crypto_tester_t, test_rng, bool,
enumerator = this->rng->create_enumerator(this->rng);
while (enumerator->enumerate(enumerator, &vector))
{
+ chunk_t data = chunk_empty;
rng_t *rng;
- chunk_t data;
if (vector->quality != quality)
{
@@ -936,37 +1059,37 @@ METHOD(crypto_tester_t, test_rng, bool,
}
tested++;
+ failed = TRUE;
rng = create(quality);
if (!rng)
{
DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
rng_quality_names, quality, plugin_name);
- failed = TRUE;
break;
}
- failed = FALSE;
-
/* allocated bytes */
- rng->allocate_bytes(rng, vector->len, &data);
- if (data.len != vector->len)
+ if (!rng->allocate_bytes(rng, vector->len, &data) ||
+ data.len != vector->len ||
+ !vector->test(vector->user, data))
{
- failed = TRUE;
+ goto failure;
}
- if (!vector->test(vector->user, data))
+ /* write bytes into existing buffer */
+ memset(data.ptr, 0, data.len);
+ if (!rng->get_bytes(rng, vector->len, data.ptr))
{
- failed = TRUE;
+ goto failure;
}
- /* bytes to existing buffer */
- memset(data.ptr, 0, data.len);
- rng->get_bytes(rng, vector->len, data.ptr);
if (!vector->test(vector->user, data))
{
- failed = TRUE;
+ goto failure;
}
- free(data.ptr);
+ failed = FALSE;
+failure:
rng->destroy(rng);
+ chunk_free(&data);
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
diff --git a/src/libstrongswan/crypto/hashers/hasher.c b/src/libstrongswan/crypto/hashers/hasher.c
index 81750a519..dc73d5223 100644
--- a/src/libstrongswan/crypto/hashers/hasher.c
+++ b/src/libstrongswan/crypto/hashers/hasher.c
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
- *
+ * Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -32,6 +32,19 @@ ENUM(hash_algorithm_names, HASH_UNKNOWN, HASH_SHA512,
"HASH_SHA512"
);
+ENUM(hash_algorithm_short_names, HASH_UNKNOWN, HASH_SHA512,
+ "unknown",
+ "preferred",
+ "md2",
+ "md4",
+ "md5",
+ "sha1",
+ "sha224",
+ "sha256",
+ "sha384",
+ "sha512"
+);
+
/*
* Described in header.
*/
@@ -68,6 +81,105 @@ hash_algorithm_t hasher_algorithm_from_oid(int oid)
/*
* Described in header.
*/
+hash_algorithm_t hasher_algorithm_from_prf(pseudo_random_function_t alg)
+{
+ switch (alg)
+ {
+ case PRF_HMAC_MD5:
+ return HASH_MD5;
+ case PRF_HMAC_SHA1:
+ case PRF_FIPS_SHA1_160:
+ case PRF_KEYED_SHA1:
+ return HASH_SHA1;
+ case PRF_HMAC_SHA2_256:
+ return HASH_SHA256;
+ case PRF_HMAC_SHA2_384:
+ return HASH_SHA384;
+ case PRF_HMAC_SHA2_512:
+ return HASH_SHA512;
+ case PRF_HMAC_TIGER:
+ case PRF_AES128_XCBC:
+ case PRF_AES128_CMAC:
+ case PRF_FIPS_DES:
+ case PRF_CAMELLIA128_XCBC:
+ case PRF_UNDEFINED:
+ break;
+ }
+ return HASH_UNKNOWN;
+}
+
+/*
+ * Described in header.
+ */
+hash_algorithm_t hasher_algorithm_from_integrity(integrity_algorithm_t alg,
+ size_t *length)
+{
+ if (length)
+ {
+ switch (alg)
+ {
+ case AUTH_HMAC_MD5_96:
+ case AUTH_HMAC_SHA1_96:
+ case AUTH_HMAC_SHA2_256_96:
+ *length = 12;
+ break;
+ case AUTH_HMAC_MD5_128:
+ case AUTH_HMAC_SHA1_128:
+ case AUTH_HMAC_SHA2_256_128:
+ *length = 16;
+ break;
+ case AUTH_HMAC_SHA1_160:
+ *length = 20;
+ break;
+ case AUTH_HMAC_SHA2_384_192:
+ *length = 24;
+ break;
+ case AUTH_HMAC_SHA2_256_256:
+ case AUTH_HMAC_SHA2_512_256:
+ *length = 32;
+ break;
+ case AUTH_HMAC_SHA2_384_384:
+ *length = 48;
+ break;
+ default:
+ break;
+ }
+ }
+ switch (alg)
+ {
+ case AUTH_HMAC_MD5_96:
+ case AUTH_HMAC_MD5_128:
+ case AUTH_KPDK_MD5:
+ return HASH_MD5;
+ case AUTH_HMAC_SHA1_96:
+ case AUTH_HMAC_SHA1_128:
+ case AUTH_HMAC_SHA1_160:
+ return HASH_SHA1;
+ case AUTH_HMAC_SHA2_256_96:
+ case AUTH_HMAC_SHA2_256_128:
+ case AUTH_HMAC_SHA2_256_256:
+ return HASH_SHA256;
+ case AUTH_HMAC_SHA2_384_192:
+ case AUTH_HMAC_SHA2_384_384:
+ return HASH_SHA384;
+ case AUTH_HMAC_SHA2_512_256:
+ return HASH_SHA512;
+ case AUTH_AES_CMAC_96:
+ case AUTH_AES_128_GMAC:
+ case AUTH_AES_192_GMAC:
+ case AUTH_AES_256_GMAC:
+ case AUTH_AES_XCBC_96:
+ case AUTH_DES_MAC:
+ case AUTH_CAMELLIA_XCBC_96:
+ case AUTH_UNDEFINED:
+ break;
+ }
+ return HASH_UNKNOWN;
+}
+
+/*
+ * Described in header.
+ */
int hasher_algorithm_to_oid(hash_algorithm_t alg)
{
int oid;
diff --git a/src/libstrongswan/crypto/hashers/hasher.h b/src/libstrongswan/crypto/hashers/hasher.h
index 9fa043c7e..759f6a23c 100644
--- a/src/libstrongswan/crypto/hashers/hasher.h
+++ b/src/libstrongswan/crypto/hashers/hasher.h
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
- *
+ * Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -27,6 +27,8 @@ typedef enum hash_algorithm_t hash_algorithm_t;
typedef struct hasher_t hasher_t;
#include <library.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/signers/signer.h>
#include <credentials/keys/public_key.h>
/**
@@ -62,9 +64,15 @@ enum hash_algorithm_t {
extern enum_name_t *hash_algorithm_names;
/**
+ * Short names for hash_algorithm_names
+ */
+extern enum_name_t *hash_algorithm_short_names;
+
+/**
* Generic interface for all hash functions.
*/
struct hasher_t {
+
/**
* Hash data and write it in the buffer.
*
@@ -77,8 +85,10 @@ struct hasher_t {
*
* @param data data to hash
* @param hash pointer where the hash will be written
+ * @return TRUE if hash created successfully
*/
- void (*get_hash) (hasher_t *this, chunk_t data, u_int8_t *hash);
+ bool (*get_hash)(hasher_t *this, chunk_t data,
+ u_int8_t *hash) __attribute__((warn_unused_result));
/**
* Hash data and allocate space for the hash.
@@ -89,36 +99,61 @@ struct hasher_t {
*
* @param data chunk with data to hash
* @param hash chunk which will hold allocated hash
+ * @return TRUE if hash allocated successfully
*/
- void (*allocate_hash) (hasher_t *this, chunk_t data, chunk_t *hash);
+ bool (*allocate_hash)(hasher_t *this, chunk_t data,
+ chunk_t *hash) __attribute__((warn_unused_result));
/**
* Get the size of the resulting hash.
*
* @return hash size in bytes
*/
- size_t (*get_hash_size) (hasher_t *this);
+ size_t (*get_hash_size)(hasher_t *this);
/**
- * Resets the hashers state.
+ * Resets the hasher's state.
+ *
+ * @return TRUE if hasher reset successfully
*/
- void (*reset) (hasher_t *this);
+ bool (*reset)(hasher_t *this) __attribute__((warn_unused_result));
/**
* Destroys a hasher object.
*/
- void (*destroy) (hasher_t *this);
+ void (*destroy)(hasher_t *this);
};
/**
* Conversion of ASN.1 OID to hash algorithm.
*
* @param oid ASN.1 OID
- * @return hash algorithm, HASH_UNKNOWN if OID unsuported
+ * @return hash algorithm, HASH_UNKNOWN if OID unsupported
*/
hash_algorithm_t hasher_algorithm_from_oid(int oid);
/**
+ * Conversion of PRF algorithm to hash algorithm (if based on one).
+ *
+ * @param alg prf algorithm
+ * @return hash algorithm, HASH_UNKNOWN if not based on a hash
+ */
+hash_algorithm_t hasher_algorithm_from_prf(pseudo_random_function_t alg);
+
+/**
+ * Conversion of integrity algorithm to hash algorithm (if based on one).
+ *
+ * If length is not NULL the length of the resulting signature is returned,
+ * which might be smaller than the output size of the underlying hash.
+ *
+ * @param alg integrity algorithm
+ * @param length returns signature length, if not NULL
+ * @return hash algorithm, HASH_UNKNOWN if not based on a hash
+ */
+hash_algorithm_t hasher_algorithm_from_integrity(integrity_algorithm_t alg,
+ size_t *length);
+
+/**
* Conversion of hash algorithm into ASN.1 OID.
*
* @param alg hash algorithm
diff --git a/src/libstrongswan/crypto/mac.h b/src/libstrongswan/crypto/mac.h
new file mode 100644
index 000000000..f7b43ba39
--- /dev/null
+++ b/src/libstrongswan/crypto/mac.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 mac mac
+ * @{ @ingroup crypto
+ */
+
+#ifndef MAC_H_
+#define MAC_H_
+
+typedef struct mac_t mac_t;
+
+#include <library.h>
+
+/**
+ * Generic interface for message authentication codes.
+ *
+ * Classes implementing this interface can use the PRF and signer wrappers.
+ */
+struct mac_t {
+
+ /**
+ * Generate message authentication code.
+ *
+ * If out is NULL, no result is given back. A next call will
+ * append the data to already supplied data. If out is not NULL,
+ * the mac of all apended data is calculated, written to out and the
+ * internal state is reset.
+ *
+ * @param data chunk of data to authenticate
+ * @param out pointer where the generated bytes will be written
+ * @return TRUE if mac generated successfully
+ */
+ bool (*get_mac)(mac_t *this, chunk_t data,
+ u_int8_t *out) __attribute__((warn_unused_result));
+
+ /**
+ * Get the size of the resulting MAC.
+ *
+ * @return block size in bytes
+ */
+ size_t (*get_mac_size)(mac_t *this);
+
+ /**
+ * Set the key to be used for the MAC.
+ *
+ * Any key length must be accepted.
+ *
+ * @param key key to set
+ * @return TRUE if key set successfully
+ */
+ bool (*set_key)(mac_t *this,
+ chunk_t key) __attribute__((warn_unused_result));
+
+ /**
+ * Destroys a mac_t object.
+ */
+ void (*destroy) (mac_t *this);
+};
+
+#endif /** MAC_H_ @}*/
diff --git a/src/libstrongswan/crypto/nonce_gen.h b/src/libstrongswan/crypto/nonce_gen.h
new file mode 100644
index 000000000..50f3c0090
--- /dev/null
+++ b/src/libstrongswan/crypto/nonce_gen.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 Adrian-Ken Rueegsegger
+ * 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 nonce_gen nonce_gen
+ * @{ @ingroup crypto
+ */
+
+#ifndef NONCE_GEN_H_
+#define NONCE_GEN_H_
+
+typedef struct nonce_gen_t nonce_gen_t;
+
+#include <library.h>
+
+/**
+ * Generic interface for nonce generators.
+ */
+struct nonce_gen_t {
+
+ /**
+ * Generates a nonce and writes it into the buffer.
+ *
+ * @param size size of nonce in bytes
+ * @param buffer pointer where the generated nonce will be written
+ * @return TRUE if nonce allocation was succesful, FALSE otherwise
+ */
+ bool (*get_nonce)(nonce_gen_t *this, size_t size,
+ u_int8_t *buffer) __attribute__((warn_unused_result));
+
+ /**
+ * Generates a nonce and allocates space for it.
+ *
+ * @param size size of nonce in bytes
+ * @param chunk chunk which will hold the generated nonce
+ * @return TRUE if nonce allocation was succesful, FALSE otherwise
+ */
+ bool (*allocate_nonce)(nonce_gen_t *this, size_t size,
+ chunk_t *chunk) __attribute__((warn_unused_result));
+
+ /**
+ * Destroys a nonce generator object.
+ */
+ void (*destroy)(nonce_gen_t *this);
+};
+
+#endif /** NONCE_GEN_H_ @}*/
diff --git a/src/libstrongswan/crypto/pkcs7.c b/src/libstrongswan/crypto/pkcs7.c
new file mode 100644
index 000000000..0ec19f2cd
--- /dev/null
+++ b/src/libstrongswan/crypto/pkcs7.c
@@ -0,0 +1,1061 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2002-2008 Andreas Steffen
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <library.h>
+#include <debug.h>
+
+#include <asn1/oid.h>
+#include <asn1/asn1.h>
+#include <asn1/asn1_parser.h>
+#include <credentials/certificates/x509.h>
+#include <credentials/keys/public_key.h>
+#include <crypto/pkcs9.h>
+#include <crypto/hashers/hasher.h>
+#include <crypto/crypters/crypter.h>
+#include <utils/linked_list.h>
+
+#include "pkcs7.h"
+
+typedef struct private_pkcs7_t private_pkcs7_t;
+
+/**
+ * Private data of a pkcs7_t object.
+ */
+struct private_pkcs7_t {
+ /**
+ * Public interface for this certificate.
+ */
+ pkcs7_t public;
+
+ /**
+ * contentInfo type
+ */
+ int type;
+
+ /**
+ * ASN.1 encoded content
+ */
+ chunk_t content;
+
+ /**
+ * ASN.1 parsing start level
+ */
+ u_int level;
+
+ /**
+ * retrieved data
+ */
+ chunk_t data;
+
+ /**
+ * ASN.1 encoded attributes
+ */
+ pkcs9_t *attributes;
+
+ /**
+ * Linked list of X.509 certificates
+ */
+ linked_list_t *certs;
+};
+
+METHOD(pkcs7_t, is_data, bool,
+ private_pkcs7_t *this)
+{
+ return this->type == OID_PKCS7_DATA;
+}
+
+METHOD(pkcs7_t, is_signedData, bool,
+ private_pkcs7_t *this)
+{
+ return this->type == OID_PKCS7_SIGNED_DATA;
+}
+
+METHOD(pkcs7_t, is_envelopedData, bool,
+ private_pkcs7_t *this)
+{
+ return this->type == OID_PKCS7_ENVELOPED_DATA;
+}
+
+/**
+ * ASN.1 definition of the PKCS#7 ContentInfo type
+ */
+static const asn1Object_t contentInfoObjects[] = {
+ { 0, "contentInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "contentType", ASN1_OID, ASN1_BODY }, /* 1 */
+ { 1, "content", ASN1_CONTEXT_C_0, ASN1_OPT |
+ ASN1_BODY }, /* 2 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
+};
+#define PKCS7_INFO_TYPE 1
+#define PKCS7_INFO_CONTENT 2
+
+/**
+ * Parse PKCS#7 contentInfo object
+ */
+static bool parse_contentInfo(private_pkcs7_t *this)
+{
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
+ bool success = FALSE;
+
+ if (!this->data.ptr)
+ {
+ return FALSE;
+ }
+
+ parser = asn1_parser_create(contentInfoObjects, this->data);
+ parser->set_top_level(parser, this->level);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ if (objectID == PKCS7_INFO_TYPE)
+ {
+ this->type = asn1_known_oid(object);
+ if (this->type < OID_PKCS7_DATA ||
+ this->type > OID_PKCS7_ENCRYPTED_DATA)
+ {
+ DBG1(DBG_LIB, "unknown pkcs7 content type");
+ goto end;
+ }
+ }
+ else if (objectID == PKCS7_INFO_CONTENT && object.len > 0)
+ {
+ chunk_free(&this->content);
+ this->content = chunk_clone(object);
+ }
+ }
+ success = parser->success(parser);
+
+ if (success)
+ {
+ this->level += 2;
+ chunk_free(&this->data);
+ }
+
+end:
+ parser->destroy(parser);
+ return success;
+}
+
+/**
+ * Check whether to abort the requested parsing
+ */
+static bool abort_parsing(private_pkcs7_t *this, int type)
+{
+ if (this->type != type)
+ {
+ DBG1(DBG_LIB, "pkcs7 content to be parsed is not of type '%s'",
+ oid_names[type].name);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+METHOD(pkcs7_t, parse_data, bool,
+ private_pkcs7_t *this)
+{
+ chunk_t data;
+
+ if (!parse_contentInfo(this) ||
+ abort_parsing(this, OID_PKCS7_DATA))
+ {
+ return FALSE;
+ }
+ data = this->content;
+ if (data.len == 0)
+ {
+ this->data = chunk_empty;
+ return TRUE;
+ }
+ if (asn1_parse_simple_object(&data, ASN1_OCTET_STRING,
+ this->level, "data"))
+ {
+ this->data = chunk_clone(data);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * ASN.1 definition of the PKCS#7 signedData type
+ */
+static const asn1Object_t signedDataObjects[] = {
+ { 0, "signedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
+ { 1, "digestAlgorithms", ASN1_SET, ASN1_LOOP }, /* 2 */
+ { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 3 */
+ { 1, "end loop", ASN1_EOC, ASN1_END }, /* 4 */
+ { 1, "contentInfo", ASN1_EOC, ASN1_RAW }, /* 5 */
+ { 1, "certificates", ASN1_CONTEXT_C_0, ASN1_OPT |
+ ASN1_LOOP }, /* 6 */
+ { 2, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 7 */
+ { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 8 */
+ { 1, "crls", ASN1_CONTEXT_C_1, ASN1_OPT |
+ ASN1_LOOP }, /* 9 */
+ { 2, "crl", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
+ { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 11 */
+ { 1, "signerInfos", ASN1_SET, ASN1_LOOP }, /* 12 */
+ { 2, "signerInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
+ { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 14 */
+ { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 15 */
+ { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 16 */
+ { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 17 */
+ { 3, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 18 */
+ { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT |
+ ASN1_OBJ }, /* 19 */
+ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
+ { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */
+ { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */
+ { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */
+ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */
+ { 1, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
+};
+#define PKCS7_SIGNED_VERSION 1
+#define PKCS7_DIGEST_ALG 3
+#define PKCS7_SIGNED_CONTENT_INFO 5
+#define PKCS7_SIGNED_CERT 7
+#define PKCS7_SIGNER_INFO 13
+#define PKCS7_SIGNER_INFO_VERSION 14
+#define PKCS7_SIGNED_ISSUER 16
+#define PKCS7_SIGNED_SERIAL_NUMBER 17
+#define PKCS7_DIGEST_ALGORITHM 18
+#define PKCS7_AUTH_ATTRIBUTES 19
+#define PKCS7_DIGEST_ENC_ALGORITHM 21
+#define PKCS7_ENCRYPTED_DIGEST 22
+
+METHOD(pkcs7_t, parse_signedData, bool,
+ private_pkcs7_t *this, certificate_t *cacert)
+{
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID, version;
+ int digest_alg = OID_UNKNOWN;
+ int enc_alg = OID_UNKNOWN;
+ int signerInfos = 0;
+ bool success = FALSE;
+
+ chunk_t encrypted_digest = chunk_empty;
+
+ if (!parse_contentInfo(this) ||
+ abort_parsing(this, OID_PKCS7_SIGNED_DATA))
+ {
+ return FALSE;
+ }
+
+ parser = asn1_parser_create(signedDataObjects, this->content);
+ parser->set_top_level(parser, this->level);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ u_int level = parser->get_level(parser);
+
+ switch (objectID)
+ {
+ case PKCS7_SIGNED_VERSION:
+ version = object.len ? (int)*object.ptr : 0;
+ DBG2(DBG_LIB, " v%d", version);
+ break;
+ case PKCS7_DIGEST_ALG:
+ digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case PKCS7_SIGNED_CONTENT_INFO:
+ {
+ pkcs7_t *data = pkcs7_create_from_chunk(object, level+1);
+
+ if (!data || !data->parse_data(data))
+ {
+ DESTROY_IF(data);
+ goto end;
+ }
+ this->data = chunk_clone(data->get_data(data));
+ data->destroy(data);
+ break;
+ }
+ case PKCS7_SIGNED_CERT:
+ {
+ certificate_t *cert;
+
+ DBG2(DBG_LIB, " parsing pkcs7-wrapped certificate");
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, object,
+ BUILD_END);
+ if (cert)
+ {
+ this->certs->insert_last(this->certs, cert);
+ }
+ break;
+ }
+ case PKCS7_SIGNER_INFO:
+ signerInfos++;
+ DBG2(DBG_LIB, " signer #%d", signerInfos);
+ break;
+ case PKCS7_SIGNER_INFO_VERSION:
+ version = object.len ? (int)*object.ptr : 0;
+ DBG2(DBG_LIB, " v%d", version);
+ break;
+ case PKCS7_SIGNED_ISSUER:
+ {
+ identification_t *issuer;
+
+ issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
+ DBG2(DBG_LIB, " '%Y'", issuer);
+ issuer->destroy(issuer);
+ break;
+ }
+ case PKCS7_AUTH_ATTRIBUTES:
+ *object.ptr = ASN1_SET;
+ this->attributes = pkcs9_create_from_chunk(object, level+1);
+ *object.ptr = ASN1_CONTEXT_C_0;
+ break;
+ case PKCS7_DIGEST_ALGORITHM:
+ digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case PKCS7_DIGEST_ENC_ALGORITHM:
+ enc_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ break;
+ case PKCS7_ENCRYPTED_DIGEST:
+ encrypted_digest = object;
+ }
+ }
+ success = parser->success(parser);
+
+end:
+ parser->destroy(parser);
+ if (!success)
+ {
+ return FALSE;
+ }
+
+ /* check the signature only if a cacert is available */
+ if (cacert != NULL)
+ {
+ signature_scheme_t scheme;
+ public_key_t *key;
+
+ scheme = signature_scheme_from_oid(digest_alg);
+ if (scheme == SIGN_UNKNOWN)
+ {
+ DBG1(DBG_LIB, "unsupported signature scheme");
+ return FALSE;
+ }
+ if (signerInfos == 0)
+ {
+ DBG1(DBG_LIB, "no signerInfo object found");
+ return FALSE;
+ }
+ else if (signerInfos > 1)
+ {
+ DBG1(DBG_LIB, "more than one signerInfo object found");
+ return FALSE;
+ }
+ if (this->attributes == NULL)
+ {
+ DBG1(DBG_LIB, "no authenticatedAttributes object found");
+ return FALSE;
+ }
+ if (enc_alg != OID_RSA_ENCRYPTION)
+ {
+ DBG1(DBG_LIB, "only RSA digest encryption supported");
+ return FALSE;
+ }
+
+ /* verify the signature */
+ key = cacert->get_public_key(cacert);
+ if (key == NULL)
+ {
+ DBG1(DBG_LIB, "no public key found in CA certificate");
+ return FALSE;
+ }
+ if (key->verify(key, scheme,
+ this->attributes->get_encoding(this->attributes), encrypted_digest))
+ {
+ DBG2(DBG_LIB, "signature is valid");
+ }
+ else
+ {
+ DBG1(DBG_LIB, "invalid signature");
+ key->destroy(key);
+ return FALSE;
+ }
+ key->destroy(key);
+
+ if (this->data.ptr != NULL)
+ {
+ chunk_t messageDigest;
+
+ messageDigest = this->attributes->get_attribute(this->attributes,
+ OID_PKCS9_MESSAGE_DIGEST);
+ if (messageDigest.ptr == NULL)
+ {
+ DBG1(DBG_LIB, "messageDigest attribute not found");
+ return FALSE;
+ }
+ else
+ {
+ hash_algorithm_t algorithm;
+ hasher_t *hasher;
+ chunk_t hash;
+ bool valid;
+
+ algorithm = hasher_algorithm_from_oid(digest_alg);
+ hasher = lib->crypto->create_hasher(lib->crypto, algorithm);
+ if (!hasher || !hasher->allocate_hash(hasher, this->data, &hash))
+ {
+ DESTROY_IF(hasher);
+ DBG1(DBG_LIB, "hash algorithm %N not supported",
+ hash_algorithm_names, algorithm);
+ return FALSE;
+ }
+ hasher->destroy(hasher);
+ DBG3(DBG_LIB, "hash: %B", &hash);
+
+ valid = chunk_equals(messageDigest, hash);
+ free(hash.ptr);
+ if (valid)
+ {
+ DBG2(DBG_LIB, "messageDigest is valid");
+ }
+ else
+ {
+ DBG1(DBG_LIB, "invalid messageDigest");
+ return FALSE;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * ASN.1 definition of the PKCS#7 envelopedData type
+ */
+static const asn1Object_t envelopedDataObjects[] = {
+ { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
+ { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */
+ { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */
+ { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */
+ { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */
+ { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
+ { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */
+ { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */
+ { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */
+ { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
+ { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
+ { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */
+ { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */
+ { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY }, /* 14 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
+};
+#define PKCS7_ENVELOPED_VERSION 1
+#define PKCS7_RECIPIENT_INFO_VERSION 4
+#define PKCS7_ISSUER 6
+#define PKCS7_SERIAL_NUMBER 7
+#define PKCS7_ENCRYPTION_ALG 8
+#define PKCS7_ENCRYPTED_KEY 9
+#define PKCS7_CONTENT_TYPE 12
+#define PKCS7_CONTENT_ENC_ALGORITHM 13
+#define PKCS7_ENCRYPTED_CONTENT 14
+
+METHOD(pkcs7_t, parse_envelopedData, bool,
+ private_pkcs7_t *this, chunk_t serialNumber, private_key_t *key)
+{
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID, version;
+ bool success = FALSE;
+
+ chunk_t iv = chunk_empty;
+ chunk_t symmetric_key = chunk_empty;
+ chunk_t encrypted_content = chunk_empty;
+
+ crypter_t *crypter = NULL;
+
+ if (!parse_contentInfo(this) ||
+ abort_parsing(this, OID_PKCS7_ENVELOPED_DATA))
+ {
+ return FALSE;
+ }
+
+ parser = asn1_parser_create(envelopedDataObjects, this->content);
+ parser->set_top_level(parser, this->level);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ u_int level = parser->get_level(parser);
+
+ switch (objectID)
+ {
+ case PKCS7_ENVELOPED_VERSION:
+ {
+ version = object.len ? (int)*object.ptr : 0;
+ DBG2(DBG_LIB, " v%d", version);
+ if (version != 0)
+ {
+ DBG1(DBG_LIB, "envelopedData version is not 0");
+ goto end;
+ }
+ break;
+ }
+ case PKCS7_RECIPIENT_INFO_VERSION:
+ {
+ version = object.len ? (int)*object.ptr : 0;
+ DBG2(DBG_LIB, " v%d", version);
+ if (version != 0)
+ {
+ DBG1(DBG_LIB, "recipient info version is not 0");
+ goto end;
+ }
+ break;
+ }
+ case PKCS7_ISSUER:
+ {
+ identification_t *issuer;
+
+ issuer = identification_create_from_encoding(ID_DER_ASN1_DN,
+ object);
+ DBG2(DBG_LIB, " '%Y'", issuer);
+ issuer->destroy(issuer);
+ break;
+ }
+ case PKCS7_SERIAL_NUMBER:
+ {
+ if (!chunk_equals(serialNumber, object))
+ {
+ DBG1(DBG_LIB, "serial numbers do not match");
+ goto end;
+ }
+ break;
+ }
+ case PKCS7_ENCRYPTION_ALG:
+ {
+ int alg;
+
+ alg = asn1_parse_algorithmIdentifier(object, level, NULL);
+ if (alg != OID_RSA_ENCRYPTION)
+ {
+ DBG1(DBG_LIB, "only rsa encryption supported");
+ goto end;
+ }
+ break;
+ }
+ case PKCS7_ENCRYPTED_KEY:
+ {
+ if (!key->decrypt(key, ENCRYPT_RSA_PKCS1, object, &symmetric_key))
+ {
+ DBG1(DBG_LIB, "symmetric key could not be decrypted with rsa");
+ goto end;
+ }
+ DBG4(DBG_LIB, "symmetric key %B", &symmetric_key);
+ break;
+ }
+ case PKCS7_CONTENT_TYPE:
+ {
+ if (asn1_known_oid(object) != OID_PKCS7_DATA)
+ {
+ DBG1(DBG_LIB, "encrypted content not of type pkcs7 data");
+ goto end;
+ }
+ break;
+ }
+ case PKCS7_CONTENT_ENC_ALGORITHM:
+ {
+ encryption_algorithm_t enc_alg;
+ size_t key_size;
+ int alg;
+
+ alg = asn1_parse_algorithmIdentifier(object, level, &iv);
+ enc_alg = encryption_algorithm_from_oid(alg, &key_size);
+ if (enc_alg == ENCR_UNDEFINED)
+ {
+ DBG1(DBG_LIB, "unsupported content encryption algorithm");
+ goto end;
+ }
+ crypter = lib->crypto->create_crypter(lib->crypto, enc_alg,
+ key_size);
+ if (crypter == NULL)
+ {
+ DBG1(DBG_LIB, "crypter %N not available",
+ encryption_algorithm_names, enc_alg);
+ goto end;
+ }
+ if (symmetric_key.len != crypter->get_key_size(crypter))
+ {
+ DBG1(DBG_LIB, "symmetric key length %d is wrong",
+ symmetric_key.len);
+ goto end;
+ }
+ if (!asn1_parse_simple_object(&iv, ASN1_OCTET_STRING,
+ level + 1, "IV"))
+ {
+ DBG1(DBG_LIB, "IV could not be parsed");
+ goto end;
+ }
+ if (iv.len != crypter->get_iv_size(crypter))
+ {
+ DBG1(DBG_LIB, "IV length %d is wrong", iv.len);
+ goto end;
+ }
+ break;
+ }
+ case PKCS7_ENCRYPTED_CONTENT:
+ {
+ encrypted_content = object;
+ break;
+ }
+ }
+ }
+ success = parser->success(parser);
+
+end:
+ parser->destroy(parser);
+ if (!success)
+ {
+ goto failed;
+ }
+ success = FALSE;
+
+ /* decrypt the content */
+ if (!crypter->set_key(crypter, symmetric_key) ||
+ !crypter->decrypt(crypter, encrypted_content, iv, &this->data))
+ {
+ success = FALSE;
+ goto failed;
+ }
+ DBG4(DBG_LIB, "decrypted content with padding: %B", &this->data);
+
+ /* remove the padding */
+ {
+ u_char *pos = this->data.ptr + this->data.len - 1;
+ u_char pattern = *pos;
+ size_t padding = pattern;
+
+ if (padding > this->data.len)
+ {
+ DBG1(DBG_LIB, "padding greater than data length");
+ goto failed;
+ }
+ this->data.len -= padding;
+
+ while (padding-- > 0)
+ {
+ if (*pos-- != pattern)
+ {
+ DBG1(DBG_LIB, "wrong padding pattern");
+ goto failed;
+ }
+ }
+ }
+ success = TRUE;
+
+failed:
+ DESTROY_IF(crypter);
+ chunk_clear(&symmetric_key);
+ if (!success)
+ {
+ chunk_free(&this->data);
+ }
+ return success;
+}
+
+METHOD(pkcs7_t, get_data, chunk_t,
+ private_pkcs7_t *this)
+{
+ return this->data;
+}
+
+METHOD(pkcs7_t, get_contentInfo, chunk_t,
+ private_pkcs7_t *this)
+{
+ chunk_t content_type;
+
+ /* create DER-encoded OID for pkcs7_contentInfo type */
+ switch(this->type)
+ {
+ case OID_PKCS7_DATA:
+ case OID_PKCS7_SIGNED_DATA:
+ case OID_PKCS7_ENVELOPED_DATA:
+ case OID_PKCS7_SIGNED_ENVELOPED_DATA:
+ case OID_PKCS7_DIGESTED_DATA:
+ case OID_PKCS7_ENCRYPTED_DATA:
+ content_type = asn1_build_known_oid(this->type);
+ break;
+ case OID_UNKNOWN:
+ default:
+ DBG1(DBG_LIB, "invalid pkcs7 contentInfo type");
+ return chunk_empty;
+ }
+
+ return this->content.ptr == NULL
+ ? asn1_wrap(ASN1_SEQUENCE, "m", content_type)
+ : asn1_wrap(ASN1_SEQUENCE, "mm", content_type,
+ asn1_simple_object(ASN1_CONTEXT_C_0, this->content));
+}
+
+METHOD(pkcs7_t, create_certificate_enumerator, enumerator_t*,
+ private_pkcs7_t *this)
+{
+ return this->certs->create_enumerator(this->certs);
+}
+
+METHOD(pkcs7_t, set_certificate, void,
+ private_pkcs7_t *this, certificate_t *cert)
+{
+ if (cert)
+ {
+ this->certs->insert_last(this->certs, cert);
+ }
+}
+
+METHOD(pkcs7_t, set_attributes, void,
+ private_pkcs7_t *this, pkcs9_t *attributes)
+{
+ this->attributes = attributes;
+}
+
+METHOD(pkcs7_t, get_attributes, pkcs9_t*,
+ private_pkcs7_t *this)
+{
+ return this->attributes;
+}
+
+/**
+ * build a DER-encoded issuerAndSerialNumber object
+ */
+chunk_t pkcs7_build_issuerAndSerialNumber(certificate_t *cert)
+{
+ identification_t *issuer = cert->get_issuer(cert);
+ chunk_t serial = chunk_empty;
+
+ if (cert->get_type(cert) == CERT_X509)
+ {
+ x509_t *x509 = (x509_t*)cert;
+ serial = x509->get_serial(x509);
+ }
+
+ return asn1_wrap(ASN1_SEQUENCE, "cm",
+ issuer->get_encoding(issuer),
+ asn1_integer("c", serial));
+}
+
+METHOD(pkcs7_t, build_envelopedData, bool,
+ private_pkcs7_t *this, certificate_t *cert, encryption_algorithm_t alg,
+ size_t key_size)
+{
+ chunk_t iv, symmetricKey, protectedKey, in, out;
+ crypter_t *crypter;
+ int alg_oid;
+
+ /* select OID of symmetric encryption algorithm */
+ alg_oid = encryption_algorithm_to_oid(alg, key_size);
+ if (alg_oid == OID_UNKNOWN)
+ {
+ DBG1(DBG_LIB, " encryption algorithm %N not supported",
+ encryption_algorithm_names, alg);
+ return FALSE;
+ }
+ crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8);
+ if (crypter == NULL)
+ {
+ DBG1(DBG_LIB, " could not create crypter for algorithm %N",
+ encryption_algorithm_names, alg);
+ return FALSE;
+ }
+
+ /* generate a true random symmetric encryption key
+ * and a pseudo-random iv
+ */
+ {
+ rng_t *rng;
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
+ if (!rng || !rng->allocate_bytes(rng, crypter->get_key_size(crypter),
+ &symmetricKey))
+ {
+ DBG1(DBG_LIB, " failed to allocate symmetric encryption key");
+ DESTROY_IF(rng);
+ return FALSE;
+ }
+ DBG4(DBG_LIB, " symmetric encryption key: %B", &symmetricKey);
+ rng->destroy(rng);
+
+ rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+ if (!rng || !rng->allocate_bytes(rng, crypter->get_iv_size(crypter),
+ &iv))
+ {
+ DBG1(DBG_LIB, " failed to allocate initialization vector");
+ DESTROY_IF(rng);
+ return FALSE;
+ }
+ DBG4(DBG_LIB, " initialization vector: %B", &iv);
+ rng->destroy(rng);
+ }
+
+ /* pad the data so that the total length becomes
+ * a multiple of the block size
+ */
+ {
+ size_t block_size = crypter->get_block_size(crypter);
+ size_t padding = block_size - this->data.len % block_size;
+
+ in.len = this->data.len + padding;
+ in.ptr = malloc(in.len);
+
+ DBG2(DBG_LIB, " padding %d bytes of data to multiple block size of %d bytes",
+ (int)this->data.len, (int)in.len);
+
+ /* copy data */
+ memcpy(in.ptr, this->data.ptr, this->data.len);
+ /* append padding */
+ memset(in.ptr + this->data.len, padding, padding);
+ }
+ DBG3(DBG_LIB, " padded unencrypted data: %B", &in);
+
+ /* symmetric encryption of data object */
+ if (!crypter->set_key(crypter, symmetricKey) ||
+ !crypter->encrypt(crypter, in, iv, &out))
+ {
+ crypter->destroy(crypter);
+ chunk_clear(&in);
+ chunk_clear(&symmetricKey);
+ chunk_free(&iv);
+ return FALSE;
+ }
+ crypter->destroy(crypter);
+ chunk_clear(&in);
+ DBG3(DBG_LIB, " encrypted data: %B", &out);
+
+ /* protect symmetric key by public key encryption */
+ {
+ public_key_t *key = cert->get_public_key(cert);
+
+ if (key == NULL)
+ {
+ DBG1(DBG_LIB, " public key not found in encryption certificate");
+ chunk_clear(&symmetricKey);
+ chunk_free(&iv);
+ chunk_free(&out);
+ return FALSE;
+ }
+ key->encrypt(key, ENCRYPT_RSA_PKCS1, symmetricKey, &protectedKey);
+ key->destroy(key);
+ chunk_clear(&symmetricKey);
+ }
+
+ /* build pkcs7 enveloped data object */
+ {
+ chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(alg_oid),
+ asn1_wrap(ASN1_OCTET_STRING, "m", iv));
+
+ chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "mmm",
+ asn1_build_known_oid(OID_PKCS7_DATA),
+ contentEncryptionAlgorithm,
+ asn1_wrap(ASN1_CONTEXT_S_0, "m", out));
+
+ chunk_t encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m", protectedKey);
+
+ chunk_t recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmmm",
+ ASN1_INTEGER_0,
+ pkcs7_build_issuerAndSerialNumber(cert),
+ asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+ encryptedKey);
+
+ this->content = asn1_wrap(ASN1_SEQUENCE, "cmm",
+ ASN1_INTEGER_0,
+ asn1_wrap(ASN1_SET, "m", recipientInfo),
+ encryptedContentInfo);
+ chunk_free(&this->data);
+ this->type = OID_PKCS7_ENVELOPED_DATA;
+ this->data = get_contentInfo(this);
+ }
+ return TRUE;
+}
+
+METHOD(pkcs7_t, build_signedData, bool,
+ private_pkcs7_t *this, private_key_t *private_key, hash_algorithm_t alg)
+{
+ chunk_t authenticatedAttributes = chunk_empty;
+ chunk_t encryptedDigest = chunk_empty;
+ chunk_t signerInfo, encoding = chunk_empty;
+ signature_scheme_t scheme;
+ int digest_oid;
+ certificate_t *cert;
+
+ if (this->certs->get_first(this->certs, (void**)&cert) != SUCCESS)
+ {
+ DBG1(DBG_LIB, " no pkcs7 signer certificate found");
+ return FALSE;
+ }
+ digest_oid = hasher_algorithm_to_oid(alg);
+ scheme = signature_scheme_from_oid(digest_oid);
+
+ if (this->attributes != NULL)
+ {
+ if (this->data.ptr != NULL)
+ {
+ chunk_t messageDigest, signingTime, attributes;
+ hasher_t *hasher;
+ time_t now;
+
+ hasher = lib->crypto->create_hasher(lib->crypto, alg);
+ if (!hasher ||
+ !hasher->allocate_hash(hasher, this->data, &messageDigest))
+ {
+ DESTROY_IF(hasher);
+ DBG1(DBG_LIB, " hash algorithm %N not support",
+ hash_algorithm_names, alg);
+ return FALSE;
+ }
+ hasher->destroy(hasher);
+ this->attributes->set_attribute(this->attributes,
+ OID_PKCS9_MESSAGE_DIGEST,
+ messageDigest);
+ free(messageDigest.ptr);
+
+ /* take the current time as signingTime */
+ now = time(NULL);
+ signingTime = asn1_from_time(&now, ASN1_UTCTIME);
+ this->attributes->set_attribute_raw(this->attributes,
+ OID_PKCS9_SIGNING_TIME, signingTime);
+ this->attributes->set_attribute_raw(this->attributes,
+ OID_PKCS9_CONTENT_TYPE,
+ asn1_build_known_oid(OID_PKCS7_DATA));
+
+ attributes = this->attributes->get_encoding(this->attributes);
+
+ private_key->sign(private_key, scheme, attributes, &encryptedDigest);
+ authenticatedAttributes = chunk_clone(attributes);
+ *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
+ }
+ }
+ else if (this->data.ptr != NULL)
+ {
+ private_key->sign(private_key, scheme, this->data, &encryptedDigest);
+ }
+ if (encryptedDigest.ptr)
+ {
+ encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", encryptedDigest);
+ }
+ signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmmmmm",
+ ASN1_INTEGER_1,
+ pkcs7_build_issuerAndSerialNumber(cert),
+ asn1_algorithmIdentifier(digest_oid),
+ authenticatedAttributes,
+ asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+ encryptedDigest);
+
+ if (this->data.ptr != NULL)
+ {
+ chunk_free(&this->content);
+ this->content = asn1_simple_object(ASN1_OCTET_STRING, this->data);
+ chunk_free(&this->data);
+ }
+ this->type = OID_PKCS7_DATA;
+ this->data = get_contentInfo(this);
+ chunk_free(&this->content);
+
+ cert->get_encoding(cert, CERT_ASN1_DER, &encoding);
+
+ this->content = asn1_wrap(ASN1_SEQUENCE, "cmcmm",
+ ASN1_INTEGER_1,
+ asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_oid)),
+ this->data,
+ asn1_wrap(ASN1_CONTEXT_C_0, "m", encoding),
+ asn1_wrap(ASN1_SET, "m", signerInfo));
+ chunk_free(&this->data);
+ this->type = OID_PKCS7_SIGNED_DATA;
+ this->data = get_contentInfo(this);
+
+ return TRUE;
+}
+
+METHOD(pkcs7_t, destroy, void,
+ private_pkcs7_t *this)
+{
+ DESTROY_IF(this->attributes);
+ this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy));
+ free(this->content.ptr);
+ free(this->data.ptr);
+ free(this);
+}
+
+/**
+ * Generic private constructor
+ */
+static private_pkcs7_t *pkcs7_create_empty(void)
+{
+ private_pkcs7_t *this;
+
+ INIT(this,
+ .public = {
+ .is_data = _is_data,
+ .is_signedData = _is_signedData,
+ .is_envelopedData = _is_envelopedData,
+ .parse_data = _parse_data,
+ .parse_signedData = _parse_signedData,
+ .parse_envelopedData = _parse_envelopedData,
+ .get_data = _get_data,
+ .get_contentInfo = _get_contentInfo,
+ .create_certificate_enumerator = _create_certificate_enumerator,
+ .set_certificate = _set_certificate,
+ .set_attributes = _set_attributes,
+ .get_attributes = _get_attributes,
+ .build_envelopedData = _build_envelopedData,
+ .build_signedData = _build_signedData,
+ .destroy = _destroy,
+ },
+ .type = OID_UNKNOWN,
+ .certs = linked_list_create(),
+ );
+
+ return this;
+}
+
+/*
+ * Described in header.
+ */
+pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
+{
+ private_pkcs7_t *this = pkcs7_create_empty();
+
+ this->level = level;
+ this->data = chunk_clone(chunk);
+
+ return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+pkcs7_t *pkcs7_create_from_data(chunk_t data)
+{
+ private_pkcs7_t *this = pkcs7_create_empty();
+
+ this->data = chunk_clone(data);
+
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/crypto/pkcs7.h b/src/libstrongswan/crypto/pkcs7.h
new file mode 100644
index 000000000..7c9a6b037
--- /dev/null
+++ b/src/libstrongswan/crypto/pkcs7.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2005 Jan Hutter, Martin Willi
+ * Copyright (C) 2002-2008 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * 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 pkcs7 pkcs7
+ * @{ @ingroup crypto
+ */
+
+#ifndef PKCS7_H_
+#define PKCS7_H_
+
+typedef struct pkcs7_t pkcs7_t;
+
+#include <library.h>
+#include <credentials/keys/private_key.h>
+#include <crypto/pkcs9.h>
+#include <crypto/crypters/crypter.h>
+#include <utils/enumerator.h>
+
+/**
+ * PKCS#7 contentInfo object.
+ */
+struct pkcs7_t {
+
+ /**
+ * Check if the PKCS#7 contentType is data
+ *
+ * @return TRUE if the contentType is data
+ */
+ bool (*is_data) (pkcs7_t *this);
+
+ /**
+ * Check if the PKCS#7 contentType is signedData
+ *
+ * @return TRUE if the contentType is signedData
+ */
+ bool (*is_signedData) (pkcs7_t *this);
+
+ /**
+ * Check if the PKCS#7 contentType is envelopedData
+ *
+ * @return TRUE if the contentType is envelopedData
+ */
+ bool (*is_envelopedData) (pkcs7_t *this);
+
+ /**
+ * Parse a PKCS#7 data content.
+ *
+ * @return TRUE if parsing was successful
+ */
+ bool (*parse_data) (pkcs7_t *this);
+
+ /**
+ * Parse a PKCS#7 signedData content. The contained PKCS#7 data is parsed
+ * and verified.
+ *
+ * @param cacert cacert used to verify the signature
+ * @return TRUE if parsing was successful
+ */
+ bool (*parse_signedData) (pkcs7_t *this, certificate_t *cacert);
+
+ /**
+ * Parse a PKCS#7 envelopedData content.
+ *
+ * @param serialNumber serialNumber of the request
+ * @param key private key used to decrypt the symmetric key
+ * @return TRUE if parsing was successful
+ */
+ bool (*parse_envelopedData) (pkcs7_t *this, chunk_t serialNumber,
+ private_key_t *key);
+
+ /**
+ * Returns the parsed data object
+ *
+ * @return chunk containing the data object
+ */
+ chunk_t (*get_data) (pkcs7_t *this);
+
+ /**
+ * Returns the a DER-encoded contentInfo object
+ *
+ * @return chunk containing the contentInfo object
+ */
+ chunk_t (*get_contentInfo) (pkcs7_t *this);
+
+ /**
+ * Create an enumerator for the certificates.
+ *
+ * @return enumerator for the certificates
+ */
+ enumerator_t *(*create_certificate_enumerator) (pkcs7_t *this);
+
+ /**
+ * Add a certificate.
+ *
+ * @param cert certificate to be included (gets adopted)
+ */
+ void (*set_certificate) (pkcs7_t *this, certificate_t *cert);
+
+ /**
+ * Add authenticated attributes.
+ *
+ * @param attributes attributes to be included (gets adopted)
+ */
+ void (*set_attributes) (pkcs7_t *this, pkcs9_t *attributes);
+
+ /**
+ * Get attributes.
+ *
+ * @return attributes (internal data)
+ */
+ pkcs9_t *(*get_attributes) (pkcs7_t *this);
+
+ /**
+ * Build a data object
+ *
+ * @return TRUE if build was successful
+ */
+ bool (*build_data) (pkcs7_t *this);
+
+ /**
+ * Build an envelopedData object
+ *
+ * @param cert receivers's certificate
+ * @param alg encryption algorithm
+ * @param key_size key size to use
+ * @return TRUE if build was successful
+ */
+ bool (*build_envelopedData) (pkcs7_t *this, certificate_t *cert,
+ encryption_algorithm_t alg, size_t key_size);
+
+ /**
+ * Build an signedData object
+ *
+ * @param key signer's private key
+ * @param alg digest algorithm used for signature
+ * @return TRUE if build was successful
+ */
+ bool (*build_signedData) (pkcs7_t *this, private_key_t *key,
+ hash_algorithm_t alg);
+
+ /**
+ * Destroys the contentInfo object.
+ */
+ void (*destroy) (pkcs7_t *this);
+};
+
+/**
+ * Read a PKCS#7 contentInfo object from a DER encoded chunk.
+ *
+ * @param chunk chunk containing DER encoded data
+ * @param level ASN.1 parsing start level
+ * @return created pkcs7_contentInfo object, or NULL if invalid.
+ */
+pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level);
+
+/**
+ * Create a PKCS#7 contentInfo object
+ *
+ * @param data chunk containing data
+ * @return created pkcs7_contentInfo object.
+ */
+pkcs7_t *pkcs7_create_from_data(chunk_t data);
+
+#endif /** PKCS7_H_ @}*/
diff --git a/src/libstrongswan/crypto/pkcs9.c b/src/libstrongswan/crypto/pkcs9.c
index 63a615238..d24ab1b80 100644
--- a/src/libstrongswan/crypto/pkcs9.c
+++ b/src/libstrongswan/crypto/pkcs9.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C)2008 Andreas Steffen
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2008 Andreas Steffen
* Hochschule fuer Technik Rapperswil, Switzerland
*
* This program is free software; you can redistribute it and/or modify it
@@ -74,58 +75,6 @@ struct attribute_t {
};
/**
- * PKCS#9 attribute type OIDs
- */
-static chunk_t ASN1_contentType_oid = chunk_from_chars(
- 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03
-);
-static chunk_t ASN1_messageDigest_oid = chunk_from_chars(
- 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04
-);
-static chunk_t ASN1_signingTime_oid = chunk_from_chars(
- 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x05
-);
-static chunk_t ASN1_messageType_oid = chunk_from_chars(
- 0x06, 0x0A,
- 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x02
-);
-static chunk_t ASN1_senderNonce_oid = chunk_from_chars(
- 0x06, 0x0A,
- 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x05
-);
-static chunk_t ASN1_transId_oid = chunk_from_chars(
- 0x06, 0x0A,
- 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x07
-);
-
-/**
- * return the ASN.1 encoded OID of a PKCS#9 attribute
- */
-static chunk_t asn1_attributeIdentifier(int oid)
-{
- switch (oid)
- {
- case OID_PKCS9_CONTENT_TYPE:
- return ASN1_contentType_oid;
- case OID_PKCS9_MESSAGE_DIGEST:
- return ASN1_messageDigest_oid;
- case OID_PKCS9_SIGNING_TIME:
- return ASN1_signingTime_oid;
- case OID_PKI_MESSAGE_TYPE:
- return ASN1_messageType_oid;
- case OID_PKI_SENDER_NONCE:
- return ASN1_senderNonce_oid;
- case OID_PKI_TRANS_ID:
- return ASN1_transId_oid;;
- default:
- return chunk_empty;
- }
-}
-
-/**
* return the ASN.1 encoding of a PKCS#9 attribute
*/
static asn1_t asn1_attributeType(int oid)
@@ -188,8 +137,8 @@ static attribute_t *attribute_create(int oid, chunk_t value)
.destroy = attribute_destroy,
.oid = oid,
.value = chunk_clone(value),
- .encoding = asn1_wrap(ASN1_SEQUENCE, "cm",
- asn1_attributeIdentifier(oid),
+ .encoding = asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(oid),
asn1_simple_object(ASN1_SET, value)),
);
@@ -263,43 +212,30 @@ METHOD(pkcs9_t, get_attribute, chunk_t,
}
}
enumerator->destroy(enumerator);
+ if (value.ptr &&
+ !asn1_parse_simple_object(&value, asn1_attributeType(oid), 0,
+ oid_names[oid].name))
+ {
+ return chunk_empty;
+ }
return value;
}
-METHOD(pkcs9_t, set_attribute, void,
+METHOD(pkcs9_t, set_attribute_raw, void,
private_pkcs9_t *this, int oid, chunk_t value)
{
attribute_t *attribute = attribute_create(oid, value);
- this->attributes->insert_last(this->attributes, (void*)attribute);
-}
-
-METHOD(pkcs9_t, get_messageDigest, chunk_t,
- private_pkcs9_t *this)
-{
- const int oid = OID_PKCS9_MESSAGE_DIGEST;
- chunk_t value = get_attribute(this, oid);
-
- if (value.ptr == NULL)
- {
- return chunk_empty;
- }
- if (!asn1_parse_simple_object(&value, asn1_attributeType(oid), 0,
- oid_names[oid].name))
- {
- return chunk_empty;
- }
- return chunk_clone(value);
+ this->attributes->insert_last(this->attributes, attribute);
+ chunk_free(&value);
}
-METHOD(pkcs9_t, set_messageDigest, void,
- private_pkcs9_t *this, chunk_t value)
+METHOD(pkcs9_t, set_attribute, void,
+ private_pkcs9_t *this, int oid, chunk_t value)
{
- const int oid = OID_PKCS9_MESSAGE_DIGEST;
- chunk_t messageDigest = asn1_simple_object(asn1_attributeType(oid), value);
+ chunk_t attr = asn1_simple_object(asn1_attributeType(oid), value);
- set_attribute(this, oid, messageDigest);
- free(messageDigest.ptr);
+ set_attribute_raw(this, oid, attr);
}
METHOD(pkcs9_t, destroy, void,
@@ -323,8 +259,7 @@ static private_pkcs9_t *pkcs9_create_empty(void)
.get_encoding = _get_encoding,
.get_attribute = _get_attribute,
.set_attribute = _set_attribute,
- .get_messageDigest = _get_messageDigest,
- .set_messageDigest = _set_messageDigest,
+ .set_attribute_raw = _set_attribute_raw,
.destroy = _destroy,
},
.attributes = linked_list_create(),
diff --git a/src/libstrongswan/crypto/pkcs9.h b/src/libstrongswan/crypto/pkcs9.h
index 5b85692d6..c442d4441 100644
--- a/src/libstrongswan/crypto/pkcs9.h
+++ b/src/libstrongswan/crypto/pkcs9.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Andreas Steffen
* Hochschule fuer Technik Rapperswil, Switzerland
*
@@ -46,7 +47,7 @@ struct pkcs9_t {
* Gets a PKCS#9 attribute
*
* @param oid OID of the attribute
- * @return ASN.1 encoded value of the attribute
+ * @return value of the attribute (internal data)
*/
chunk_t (*get_attribute) (pkcs9_t *this, int oid);
@@ -54,23 +55,17 @@ struct pkcs9_t {
* Adds a PKCS#9 attribute
*
* @param oid OID of the attribute
- * @param value ASN.1 encoded value of the attribute
+ * @param value value of the attribute (gets cloned)
*/
void (*set_attribute) (pkcs9_t *this, int oid, chunk_t value);
/**
- * Gets a PKCS#9 messageDigest attribute
+ * Adds a ASN.1 encoded PKCS#9 attribute
*
- * @return messageDigest
- */
- chunk_t (*get_messageDigest) (pkcs9_t *this);
-
- /**
- * Add a PKCS#9 messageDigest attribute
- *
- * @param value messageDigest
+ * @param oid OID of the attribute
+ * @param value ASN.1 encoded value of the attribute (gets adopted)
*/
- void (*set_messageDigest) (pkcs9_t *this, chunk_t value);
+ void (*set_attribute_raw) (pkcs9_t *this, int oid, chunk_t value);
/**
* Destroys the PKCS#9 attribute list.
diff --git a/src/libstrongswan/crypto/prf_plus.c b/src/libstrongswan/crypto/prf_plus.c
index 8e815e608..94be1d5bf 100644
--- a/src/libstrongswan/crypto/prf_plus.c
+++ b/src/libstrongswan/crypto/prf_plus.c
@@ -25,6 +25,7 @@ typedef struct private_prf_plus_t private_prf_plus_t;
*
*/
struct private_prf_plus_t {
+
/**
* Public interface of prf_plus_t.
*/
@@ -41,65 +42,74 @@ struct private_prf_plus_t {
chunk_t seed;
/**
- * Buffer to store current PRF result.
+ * Octet which will be appended to the seed, 0 if not used
*/
- chunk_t buffer;
+ u_int8_t counter;
/**
* Already given out bytes in current buffer.
*/
- size_t given_out;
+ size_t used;
/**
- * Octet which will be appended to the seed.
+ * Buffer to store current PRF result.
*/
- u_int8_t appending_octet;
+ chunk_t buffer;
};
-METHOD(prf_plus_t, get_bytes, void,
+METHOD(prf_plus_t, get_bytes, bool,
private_prf_plus_t *this, size_t length, u_int8_t *buffer)
{
- chunk_t appending_chunk;
- size_t bytes_in_round;
- size_t total_bytes_written = 0;
-
- appending_chunk.ptr = &(this->appending_octet);
- appending_chunk.len = 1;
+ size_t round, written = 0;
while (length > 0)
- { /* still more to do... */
- if (this->buffer.len == this->given_out)
- { /* no bytes left in buffer, get next*/
- this->prf->get_bytes(this->prf, this->buffer, NULL);
- this->prf->get_bytes(this->prf, this->seed, NULL);
- this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr);
- this->given_out = 0;
- this->appending_octet++;
+ {
+ if (this->buffer.len == this->used)
+ { /* buffer used, get next round */
+ if (!this->prf->get_bytes(this->prf, this->buffer, NULL))
+ {
+ return FALSE;
+ }
+ if (this->counter)
+ {
+ if (!this->prf->get_bytes(this->prf, this->seed, NULL) ||
+ !this->prf->get_bytes(this->prf,
+ chunk_from_thing(this->counter), this->buffer.ptr))
+ {
+ return FALSE;
+ }
+ this->counter++;
+ }
+ else
+ {
+ if (!this->prf->get_bytes(this->prf, this->seed,
+ this->buffer.ptr))
+ {
+ return FALSE;
+ }
+ }
+ this->used = 0;
}
- /* how many bytes can we write in this round ? */
- bytes_in_round = min(length, this->buffer.len - this->given_out);
- /* copy bytes from buffer with offset */
- memcpy(buffer + total_bytes_written, this->buffer.ptr + this->given_out, bytes_in_round);
-
- length -= bytes_in_round;
- this->given_out += bytes_in_round;
- total_bytes_written += bytes_in_round;
+ round = min(length, this->buffer.len - this->used);
+ memcpy(buffer + written, this->buffer.ptr + this->used, round);
+
+ length -= round;
+ this->used += round;
+ written += round;
}
+ return TRUE;
}
-METHOD(prf_plus_t, allocate_bytes, void,
+METHOD(prf_plus_t, allocate_bytes, bool,
private_prf_plus_t *this, size_t length, chunk_t *chunk)
{
if (length)
{
- chunk->ptr = malloc(length);
- chunk->len = length;
- get_bytes(this, length, chunk->ptr);
- }
- else
- {
- *chunk = chunk_empty;
+ *chunk = chunk_alloc(length);
+ return get_bytes(this, length, chunk->ptr);
}
+ *chunk = chunk_empty;
+ return TRUE;
}
METHOD(prf_plus_t, destroy, void,
@@ -113,10 +123,9 @@ METHOD(prf_plus_t, destroy, void,
/*
* Description in header.
*/
-prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed)
+prf_plus_t *prf_plus_create(prf_t *prf, bool counter, chunk_t seed)
{
private_prf_plus_t *this;
- chunk_t appending_chunk;
INIT(this,
.public = {
@@ -125,25 +134,30 @@ prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed)
.destroy = _destroy,
},
.prf = prf,
+ .seed = chunk_clone(seed),
+ .buffer = chunk_alloc(prf->get_block_size(prf)),
);
- /* allocate buffer for prf output */
- this->buffer.len = prf->get_block_size(prf);
- this->buffer.ptr = malloc(this->buffer.len);
-
- this->appending_octet = 0x01;
-
- /* clone seed */
- this->seed.ptr = clalloc(seed.ptr, seed.len);
- this->seed.len = seed.len;
-
- /* do the first run */
- appending_chunk.ptr = &(this->appending_octet);
- appending_chunk.len = 1;
- this->prf->get_bytes(this->prf, this->seed, NULL);
- this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr);
- this->given_out = 0;
- this->appending_octet++;
+ if (counter)
+ {
+ this->counter = 0x01;
+ if (!this->prf->get_bytes(this->prf, this->seed, NULL) ||
+ !this->prf->get_bytes(this->prf, chunk_from_thing(this->counter),
+ this->buffer.ptr))
+ {
+ destroy(this);
+ return NULL;
+ }
+ this->counter++;
+ }
+ else
+ {
+ if (!this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr))
+ {
+ destroy(this);
+ return NULL;
+ }
+ }
- return &(this->public);
+ return &this->public;
}
diff --git a/src/libstrongswan/crypto/prf_plus.h b/src/libstrongswan/crypto/prf_plus.h
index 4179f2695..f994dce16 100644
--- a/src/libstrongswan/crypto/prf_plus.h
+++ b/src/libstrongswan/crypto/prf_plus.h
@@ -27,52 +27,44 @@ typedef struct prf_plus_t prf_plus_t;
#include <crypto/prfs/prf.h>
/**
- * Implementation of the prf+ function described in IKEv2 RFC.
- *
- * This class implements the prf+ algorithm. Internally it uses a pseudo random
- * function, which implements the prf_t interface.
- * See IKEv2 RFC 2.13.
+ * Implementation of the prf+ function used in IKEv1/IKEv2 keymat extension.
*/
struct prf_plus_t {
+
/**
* Get pseudo random bytes.
*
- * Get the next few bytes of the prf+ output. Space
- * must be allocated by the caller.
- *
* @param length number of bytes to get
* @param buffer pointer where the generated bytes will be written
+ * @return TRUE if bytes generated successfully
*/
- void (*get_bytes) (prf_plus_t *this, size_t length, u_int8_t *buffer);
+ bool (*get_bytes)(prf_plus_t *this, size_t length,
+ u_int8_t *buffer) __attribute__((warn_unused_result));
/**
* Allocate pseudo random bytes.
*
- * Get the next few bytes of the prf+ output. This function
- * will allocate the required space.
- *
* @param length number of bytes to get
* @param chunk chunk which will hold generated bytes
+ * @return TRUE if bytes allocated successfully
*/
- void (*allocate_bytes) (prf_plus_t *this, size_t length, chunk_t *chunk);
+ bool (*allocate_bytes)(prf_plus_t *this, size_t length,
+ chunk_t *chunk) __attribute__((warn_unused_result));
/**
* Destroys a prf_plus_t object.
*/
- void (*destroy) (prf_plus_t *this);
+ void (*destroy)(prf_plus_t *this);
};
/**
* Creates a new prf_plus_t object.
*
- * Seed will be cloned. prf will
- * not be cloned, must be destroyed outside after
- * prf_plus_t usage.
- *
- * @param prf prf object to use
+ * @param prf prf object to use, must be destroyd after prf+.
+ * @param counter use an appending counter byte (for IKEv2 variant)
* @param seed input seed for prf
- * @return prf_plus_t object
+ * @return prf_plus_t object, NULL on failure
*/
-prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed);
+prf_plus_t *prf_plus_create(prf_t *prf, bool counter, chunk_t seed);
#endif /** PRF_PLUS_H_ @}*/
diff --git a/src/libstrongswan/crypto/prfs/mac_prf.c b/src/libstrongswan/crypto/prfs/mac_prf.c
new file mode 100644
index 000000000..b5f6be982
--- /dev/null
+++ b/src/libstrongswan/crypto/prfs/mac_prf.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+#include "mac_prf.h"
+
+typedef struct private_prf_t private_prf_t;
+
+/**
+ * Private data of a mac_prf_t object.
+ */
+struct private_prf_t {
+
+ /**
+ * Public interface
+ */
+ prf_t public;
+
+ /**
+ * MAC to use
+ */
+ mac_t *mac;
+};
+
+METHOD(prf_t, get_bytes, bool,
+ private_prf_t *this, chunk_t seed, u_int8_t *buffer)
+{
+ return this->mac->get_mac(this->mac, seed, buffer);
+}
+
+METHOD(prf_t, allocate_bytes, bool,
+ private_prf_t *this, chunk_t seed, chunk_t *chunk)
+{
+ if (chunk)
+ {
+ *chunk = chunk_alloc(this->mac->get_mac_size(this->mac));
+ return this->mac->get_mac(this->mac, seed, chunk->ptr);
+ }
+ return this->mac->get_mac(this->mac, seed, NULL);
+}
+
+METHOD(prf_t, get_block_size, size_t,
+ private_prf_t *this)
+{
+ return this->mac->get_mac_size(this->mac);
+}
+
+METHOD(prf_t, get_key_size, size_t,
+ private_prf_t *this)
+{
+ /* IKEv2 uses MAC size as key size */
+ return this->mac->get_mac_size(this->mac);
+}
+
+METHOD(prf_t, set_key, bool,
+ private_prf_t *this, chunk_t key)
+{
+ return this->mac->set_key(this->mac, key);
+}
+
+METHOD(prf_t, destroy, void,
+ private_prf_t *this)
+{
+ this->mac->destroy(this->mac);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+prf_t *mac_prf_create(mac_t *mac)
+{
+ private_prf_t *this;
+
+ INIT(this,
+ .public = {
+ .get_bytes = _get_bytes,
+ .allocate_bytes = _allocate_bytes,
+ .get_block_size = _get_block_size,
+ .get_key_size = _get_key_size,
+ .set_key = _set_key,
+ .destroy = _destroy,
+ },
+ .mac = mac,
+ );
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/crypto/prfs/mac_prf.h b/src/libstrongswan/crypto/prfs/mac_prf.h
new file mode 100644
index 000000000..b2c0c6e17
--- /dev/null
+++ b/src/libstrongswan/crypto/prfs/mac_prf.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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 mac_prf mac_prf
+ * @{ @ingroup crypto
+ */
+
+#ifndef MAC_PRF_H_
+#define MAC_PRF_H_
+
+#include <crypto/mac.h>
+#include <crypto/prfs/prf.h>
+
+/**
+ * Creates an implementation of the prf_t interface using the provided mac_t
+ * implementation. Basically a simple wrapper to map the interface.
+ *
+ * @param mac mac_t implementation
+ * @return prf_t object
+ */
+prf_t *mac_prf_create(mac_t *mac);
+
+#endif /** MAC_PRF_H_ @}*/
diff --git a/src/libstrongswan/crypto/prfs/prf.h b/src/libstrongswan/crypto/prfs/prf.h
index ad15205d3..46e23b244 100644
--- a/src/libstrongswan/crypto/prfs/prf.h
+++ b/src/libstrongswan/crypto/prfs/prf.h
@@ -71,28 +71,33 @@ extern enum_name_t *pseudo_random_function_names;
* Generic interface for pseudo-random-functions.
*/
struct prf_t {
+
/**
* Generates pseudo random bytes and writes them in the buffer.
*
* @param seed a chunk containing the seed for the next bytes
* @param buffer pointer where the generated bytes will be written
+ * @return TRUE if bytes generated successfully
*/
- void (*get_bytes) (prf_t *this, chunk_t seed, u_int8_t *buffer);
+ bool (*get_bytes)(prf_t *this, chunk_t seed,
+ u_int8_t *buffer) __attribute__((warn_unused_result));
/**
* Generates pseudo random bytes and allocate space for them.
*
* @param seed a chunk containing the seed for the next bytes
* @param chunk chunk which will hold generated bytes
+ * @return TRUE if bytes allocated and generated successfully
*/
- void (*allocate_bytes) (prf_t *this, chunk_t seed, chunk_t *chunk);
+ bool (*allocate_bytes)(prf_t *this, chunk_t seed,
+ chunk_t *chunk) __attribute__((warn_unused_result));
/**
* Get the block size of this prf_t object.
*
* @return block size in bytes
*/
- size_t (*get_block_size) (prf_t *this);
+ size_t (*get_block_size)(prf_t *this);
/**
* Get the key size of this prf_t object.
@@ -102,19 +107,21 @@ struct prf_t {
*
* @return key size in bytes
*/
- size_t (*get_key_size) (prf_t *this);
+ size_t (*get_key_size)(prf_t *this);
/**
* Set the key for this prf_t object.
*
* @param key key to set
+ * @return TRUE if key set successfully
*/
- void (*set_key) (prf_t *this, chunk_t key);
+ bool (*set_key)(prf_t *this,
+ chunk_t key) __attribute__((warn_unused_result));
/**
* Destroys a prf object.
*/
- void (*destroy) (prf_t *this);
+ void (*destroy)(prf_t *this);
};
#endif /** PRF_H_ @}*/
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords.c b/src/libstrongswan/crypto/proposal/proposal_keywords.c
index 2060864a5..7356dc367 100644
--- a/src/libstrongswan/crypto/proposal/proposal_keywords.c
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords.c
@@ -1,38 +1,6 @@
-/* C code produced by gperf version 3.0.3 */
-/* Command-line: /usr/bin/gperf -N proposal_get_token -m 10 -C -G -c -t -D */
-/* Computed positions: -k'1,5,7,10,15,$' */
-
-#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
- && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
- && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
- && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
- && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
- && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
- && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
- && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
- && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
- && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
- && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
- && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
- && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
- && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
- && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
- && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
- && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
- && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
- && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
- && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
- && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
- && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
- && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
-/* The character set is not based on ISO-646. */
-error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
-#endif
-
-
-/* proposal keywords
- * Copyright (C) 2009 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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
@@ -45,280 +13,134 @@ error "gperf generated tables don't work with this execution character set. Plea
* for more details.
*/
-#include <string.h>
+/*
+ * Copyright (c) 2012 Nanoteq Pty Ltd
+ *
+ * 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 "proposal_keywords.h"
+#include "proposal_keywords_static.h"
-#include <crypto/transform.h>
-#include <crypto/crypters/crypter.h>
-#include <crypto/signers/signer.h>
-#include <crypto/diffie_hellman.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
-struct proposal_token {
- char *name;
- transform_type_t type;
- u_int16_t algorithm;
- u_int16_t keysize;
-};
+typedef struct private_proposal_keywords_t private_proposal_keywords_t;
+
+struct private_proposal_keywords_t {
+
+ /**
+ * public interface
+ */
+ proposal_keywords_t public;
+
+ /**
+ * registered tokens, as proposal_token_t
+ */
+ linked_list_t * tokens;
-#define TOTAL_KEYWORDS 122
-#define MIN_WORD_LENGTH 3
-#define MAX_WORD_LENGTH 17
-#define MIN_HASH_VALUE 9
-#define MAX_HASH_VALUE 213
-/* maximum key range = 205, duplicates = 0 */
+ /**
+ * rwlock to lock access to modules
+ */
+ rwlock_t *lock;
+};
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-static unsigned int
-hash (str, len)
- register const char *str;
- register unsigned int len;
+/**
+ * Find the token object for the algorithm specified.
+ */
+static const proposal_token_t* find_token(private_proposal_keywords_t *this,
+ const char *str)
{
- static const unsigned char asso_values[] =
- {
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 14, 9,
- 4, 34, 66, 19, 8, 4, 5, 3, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 131, 214, 3, 22, 21,
- 3, 1, 101, 48, 3, 4, 214, 214, 3, 10,
- 57, 4, 214, 214, 94, 6, 3, 32, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, 214, 214, 214, 214
- };
- register int hval = len;
+ proposal_token_t *token, *found = NULL;
+ enumerator_t *enumerator;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->tokens->create_enumerator(this->tokens);
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (streq(token->name, str))
+ {
+ found = token;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ return found;
+}
- switch (hval)
- {
- default:
- hval += asso_values[(unsigned char)str[14]];
- /*FALLTHROUGH*/
- case 14:
- case 13:
- case 12:
- case 11:
- case 10:
- hval += asso_values[(unsigned char)str[9]];
- /*FALLTHROUGH*/
- case 9:
- case 8:
- case 7:
- hval += asso_values[(unsigned char)str[6]];
- /*FALLTHROUGH*/
- case 6:
- case 5:
- hval += asso_values[(unsigned char)str[4]];
- /*FALLTHROUGH*/
- case 4:
- case 3:
- case 2:
- case 1:
- hval += asso_values[(unsigned char)str[0]+1];
- break;
- }
- return hval + asso_values[(unsigned char)str[len - 1]];
+METHOD(proposal_keywords_t, get_token, const proposal_token_t*,
+ private_proposal_keywords_t *this, const char *str)
+{
+ const proposal_token_t *token = proposal_get_token_static(str, strlen(str));
+ return token ?: find_token(this, str);
}
-static const struct proposal_token wordlist[] =
- {
- {"sha", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
- {"des", ENCRYPTION_ALGORITHM, ENCR_DES, 0},
- {"null", ENCRYPTION_ALGORITHM, ENCR_NULL, 0},
- {"sha1", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
- {"serpent", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
- {"camellia", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
- {"sha512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
- {"serpent192", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 192},
- {"serpent128", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
- {"camellia192", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 192},
- {"cast128", ENCRYPTION_ALGORITHM, ENCR_CAST, 128},
- {"camellia128", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
- {"aes", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
- {"serpent256", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 256},
- {"aes192", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192},
- {"sha256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
- {"aes128", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
- {"camellia192ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 192},
- {"camellia128ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 128},
- {"camellia192ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 192},
- {"camellia128ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 128},
- {"camellia192ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 192},
- {"camellia128ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 128},
- {"camellia192ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 192},
- {"camellia128ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 128},
- {"camellia192ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 192},
- {"camellia128ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 128},
- {"camellia256", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 256},
- {"twofish", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
- {"camellia256ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 256},
- {"aes256", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256},
- {"camellia256ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 256},
- {"twofish192", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 192},
- {"camellia256ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 256},
- {"twofish128", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
- {"camellia256ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 256},
- {"camellia256ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 256},
- {"camelliaxcbc", INTEGRITY_ALGORITHM, AUTH_CAMELLIA_XCBC_96, 0},
- {"twofish256", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 256},
- {"aes192ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
- {"aes128ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
- {"aes192ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
- {"aes128ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
- {"aes192ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
- {"aes128ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
- {"aes192ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
- {"aes128ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
- {"aes192ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
- {"aes128ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
- {"3des", ENCRYPTION_ALGORITHM, ENCR_3DES, 0},
- {"modp8192", DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0},
- {"modp768", DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0},
- {"md5", INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0},
- {"sha384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0},
- {"aescmac", INTEGRITY_ALGORITHM, AUTH_AES_CMAC_96, 0},
- {"aes256ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
- {"md5_128", INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_128, 0},
- {"aes256ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
- {"aes256ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
- {"aes256ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
- {"aes256ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
- {"aesxcbc", INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0},
- {"aes192gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
- {"aes128gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
- {"aes192gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
- {"aes128gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
- {"aes192gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
- {"aes128gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
- {"aes192gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
- {"aes128gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
- {"aes192gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
- {"aes128gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
- {"camellia192ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 192},
- {"camellia128ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 128},
- {"modp1024s160", DIFFIE_HELLMAN_GROUP, MODP_1024_160, 0},
- {"modp3072", DIFFIE_HELLMAN_GROUP, MODP_3072_BIT, 0},
- {"aes256gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
- {"aes256gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
- {"aes256gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
- {"ecp192", DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0},
- {"aes256gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
- {"modp1536", DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0},
- {"aes256gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
- {"camellia256ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 256},
- {"ecp521", DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0},
- {"camellia192ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 192},
- {"camellia128ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 128},
- {"noesn", EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0},
- {"aes192gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 192},
- {"aes128gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 128},
- {"modpnull", DIFFIE_HELLMAN_GROUP, MODP_NULL, 0},
- {"aes192ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
- {"aes128ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
- {"ecp256", DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0},
- {"camellia256ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 256},
- {"blowfish", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
- {"modp2048", DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0},
- {"aes256gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 256},
- {"modp4096", DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0},
- {"modp1024", DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0},
- {"blowfish192", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192},
- {"aes256ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
- {"blowfish128", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
- {"aes192ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 192},
- {"aes128ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 128},
- {"modp2048s256", DIFFIE_HELLMAN_GROUP, MODP_2048_256, 0},
- {"sha2_512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
- {"aes192gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
- {"aes128gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
- {"esn", EXTENDED_SEQUENCE_NUMBERS, EXT_SEQ_NUMBERS, 0},
- {"sha1_160", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_160, 0},
- {"aes256ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 256},
- {"blowfish256", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256},
- {"sha2_256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
- {"sha256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
- {"aes256gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
- {"sha2_256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
- {"ecp224", DIFFIE_HELLMAN_GROUP, ECP_224_BIT, 0},
- {"ecp384", DIFFIE_HELLMAN_GROUP, ECP_384_BIT, 0},
- {"modp6144", DIFFIE_HELLMAN_GROUP, MODP_6144_BIT, 0},
- {"modp2048s224", DIFFIE_HELLMAN_GROUP, MODP_2048_224, 0},
- {"sha2_384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0}
- };
+METHOD(proposal_keywords_t, register_token, void,
+ private_proposal_keywords_t *this, const char *name, transform_type_t type,
+ u_int16_t algorithm, u_int16_t keysize)
+{
+ proposal_token_t *token;
+
+ INIT(token,
+ .name = strdup(name),
+ .type = type,
+ .algorithm = algorithm,
+ .keysize = keysize,
+ );
-static const short lookup[] =
- {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,
- 1, 2, -1, -1, -1, -1, 3, 4, -1, -1,
- -1, 5, 6, -1, -1, 7, -1, 8, 9, 10,
- 11, 12, -1, 13, -1, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
- -1, -1, -1, -1, 29, 30, 31, 32, 33, 34,
- 35, -1, 36, -1, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- 53, 54, 55, 56, 57, -1, 58, -1, 59, -1,
- 60, -1, 61, 62, 63, 64, 65, 66, 67, 68,
- 69, 70, 71, 72, 73, 74, -1, 75, -1, 76,
- -1, 77, -1, 78, 79, 80, 81, 82, -1, 83,
- 84, 85, 86, 87, -1, 88, 89, -1, 90, -1,
- -1, 91, 92, -1, 93, -1, -1, 94, -1, 95,
- 96, 97, 98, -1, 99, -1, 100, 101, 102, 103,
- 104, 105, -1, -1, -1, 106, -1, -1, 107, 108,
- -1, 109, -1, -1, 110, 111, 112, -1, -1, 113,
- 114, -1, -1, -1, 115, 116, -1, 117, 118, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 119, -1, -1, -1, 120,
- -1, -1, -1, 121
- };
+ this->lock->write_lock(this->lock);
+ this->tokens->insert_first(this->tokens, token);
+ this->lock->unlock(this->lock);
+}
-#ifdef __GNUC__
-__inline
-#ifdef __GNUC_STDC_INLINE__
-__attribute__ ((__gnu_inline__))
-#endif
-#endif
-const struct proposal_token *
-proposal_get_token (str, len)
- register const char *str;
- register unsigned int len;
+METHOD(proposal_keywords_t, destroy, void,
+ private_proposal_keywords_t *this)
{
- if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
- {
- register int key = hash (str, len);
+ proposal_token_t *token;
+
+ while (this->tokens->remove_first(this->tokens, (void**)&token) == SUCCESS)
+ {
+ free(token->name);
+ free(token);
+ }
+ this->tokens->destroy(this->tokens);
+ this->lock->destroy(this->lock);
+ free(this);
+}
- if (key <= MAX_HASH_VALUE && key >= 0)
- {
- register int index = lookup[key];
+/*
+ * Described in header.
+ */
+proposal_keywords_t *proposal_keywords_create()
+{
+ private_proposal_keywords_t *this;
- if (index >= 0)
- {
- register const char *s = wordlist[index].name;
+ INIT(this,
+ .public = {
+ .get_token = _get_token,
+ .register_token = _register_token,
+ .destroy = _destroy,
+ },
+ .tokens = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
- if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
- return &wordlist[index];
- }
- }
- }
- return 0;
+ return &this->public;
}
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords.h b/src/libstrongswan/crypto/proposal/proposal_keywords.h
index 53fa1728f..d6107abc0 100644
--- a/src/libstrongswan/crypto/proposal/proposal_keywords.h
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords.h
@@ -1,6 +1,6 @@
-/* proposal keywords
- * Copyright (C) 2009 Andreas Steffen
- * Hochschule fuer Technik Rapperswil, Switzerland
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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
@@ -13,22 +13,103 @@
* for more details.
*/
-#ifndef _PROPOSAL_KEYWORDS_H_
-#define _PROPOSAL_KEYWORDS_H_
+/*
+ * Copyright (c) 2012 Nanoteq Pty Ltd
+ *
+ * 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 proposal_keywords proposal_keywords
+ * @{ @ingroup crypto
+ */
+
+#ifndef PROPOSAL_KEYWORDS_H_
+#define PROPOSAL_KEYWORDS_H_
+
+typedef struct proposal_token_t proposal_token_t;
+typedef struct proposal_keywords_t proposal_keywords_t;
+
+#include <library.h>
#include <crypto/transform.h>
-typedef struct proposal_token proposal_token_t;
+/**
+ * Class representing a proposal token.
+ */
+struct proposal_token_t {
+
+ /**
+ * The name of the token.
+ */
+ char *name;
+
+ /**
+ * The type of transform in the token.
+ */
+ transform_type_t type;
+
+ /**
+ * The IKE id of the algorithm.
+ */
+ u_int16_t algorithm;
-struct proposal_token {
- char *name;
- transform_type_t type;
- u_int16_t algorithm;
- u_int16_t keysize;
+ /**
+ * The key size associated with the specific algorithm.
+ */
+ u_int16_t keysize;
};
-extern const proposal_token_t* proposal_get_token(register const char *str,
- register unsigned int len);
+/**
+ * Class to manage proposal keywords
+ */
+struct proposal_keywords_t {
+
+ /**
+ * Returns the proposal token for the specified string if a token exists.
+ *
+ * @param str the string containing the name of the token
+ * @return proposal_token if found, NULL otherwise
+ */
+ const proposal_token_t *(*get_token)(proposal_keywords_t *this,
+ const char *str);
-#endif /* _PROPOSAL_KEYWORDS_H_ */
+ /**
+ * Register a new proposal token for an algorithm.
+ *
+ * @param name the string containing the name of the token
+ * @param type the transform_type_t for the token
+ * @param algorithm the IKE id of the algorithm
+ * @param keysize the key size associated with the specific algorithm
+ */
+ void (*register_token)(proposal_keywords_t *this, const char *name,
+ transform_type_t type, u_int16_t algorithm,
+ u_int16_t keysize);
+
+ /**
+ * Destroy a proposal_keywords_t instance.
+ */
+ void (*destroy)(proposal_keywords_t *this);
+};
+
+/**
+ * Create a proposal_keywords_t instance.
+ */
+proposal_keywords_t *proposal_keywords_create();
+#endif /** PROPOSAL_KEYWORDS_H_ @}*/
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords_static.c b/src/libstrongswan/crypto/proposal/proposal_keywords_static.c
new file mode 100644
index 000000000..ce52bc2ce
--- /dev/null
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords_static.c
@@ -0,0 +1,324 @@
+/* C code produced by gperf version 3.0.3 */
+/* Command-line: /usr/bin/gperf -N proposal_get_token_static -m 10 -C -G -c -t -D */
+/* Computed positions: -k'1,5,7,10,15,$' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
+#endif
+
+
+/*
+ * Copyright (C) 2009 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * 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.
+ */
+
+#include <string.h>
+
+#include <crypto/transform.h>
+#include <crypto/crypters/crypter.h>
+#include <crypto/signers/signer.h>
+#include <crypto/diffie_hellman.h>
+
+struct proposal_token {
+ char *name;
+ transform_type_t type;
+ u_int16_t algorithm;
+ u_int16_t keysize;
+};
+
+#define TOTAL_KEYWORDS 122
+#define MIN_WORD_LENGTH 3
+#define MAX_WORD_LENGTH 17
+#define MIN_HASH_VALUE 9
+#define MAX_HASH_VALUE 213
+/* maximum key range = 205, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+hash (str, len)
+ register const char *str;
+ register unsigned int len;
+{
+ static const unsigned char asso_values[] =
+ {
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 14, 9,
+ 4, 34, 66, 19, 8, 4, 5, 3, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 131, 214, 3, 22, 21,
+ 3, 1, 101, 48, 3, 4, 214, 214, 3, 10,
+ 57, 4, 214, 214, 94, 6, 3, 32, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214
+ };
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ hval += asso_values[(unsigned char)str[14]];
+ /*FALLTHROUGH*/
+ case 14:
+ case 13:
+ case 12:
+ case 11:
+ case 10:
+ hval += asso_values[(unsigned char)str[9]];
+ /*FALLTHROUGH*/
+ case 9:
+ case 8:
+ case 7:
+ hval += asso_values[(unsigned char)str[6]];
+ /*FALLTHROUGH*/
+ case 6:
+ case 5:
+ hval += asso_values[(unsigned char)str[4]];
+ /*FALLTHROUGH*/
+ case 4:
+ case 3:
+ case 2:
+ case 1:
+ hval += asso_values[(unsigned char)str[0]+1];
+ break;
+ }
+ return hval + asso_values[(unsigned char)str[len - 1]];
+}
+
+static const struct proposal_token wordlist[] =
+ {
+ {"sha", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
+ {"des", ENCRYPTION_ALGORITHM, ENCR_DES, 0},
+ {"null", ENCRYPTION_ALGORITHM, ENCR_NULL, 0},
+ {"sha1", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
+ {"serpent", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
+ {"camellia", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
+ {"sha512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
+ {"serpent192", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 192},
+ {"serpent128", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
+ {"camellia192", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 192},
+ {"cast128", ENCRYPTION_ALGORITHM, ENCR_CAST, 128},
+ {"camellia128", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
+ {"aes", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
+ {"serpent256", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 256},
+ {"aes192", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192},
+ {"sha256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
+ {"aes128", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
+ {"camellia192ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 192},
+ {"camellia128ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 128},
+ {"camellia192ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 192},
+ {"camellia128ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 128},
+ {"camellia192ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 192},
+ {"camellia128ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 128},
+ {"camellia192ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 192},
+ {"camellia128ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 128},
+ {"camellia192ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 192},
+ {"camellia128ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 128},
+ {"camellia256", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 256},
+ {"twofish", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
+ {"camellia256ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 256},
+ {"aes256", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256},
+ {"camellia256ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 256},
+ {"twofish192", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 192},
+ {"camellia256ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 256},
+ {"twofish128", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
+ {"camellia256ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 256},
+ {"camellia256ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 256},
+ {"camelliaxcbc", INTEGRITY_ALGORITHM, AUTH_CAMELLIA_XCBC_96, 0},
+ {"twofish256", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 256},
+ {"aes192ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
+ {"aes128ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
+ {"aes192ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
+ {"aes128ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
+ {"aes192ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
+ {"aes128ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
+ {"aes192ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
+ {"aes128ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
+ {"aes192ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
+ {"aes128ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
+ {"3des", ENCRYPTION_ALGORITHM, ENCR_3DES, 0},
+ {"modp8192", DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0},
+ {"modp768", DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0},
+ {"md5", INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0},
+ {"sha384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0},
+ {"aescmac", INTEGRITY_ALGORITHM, AUTH_AES_CMAC_96, 0},
+ {"aes256ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
+ {"md5_128", INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_128, 0},
+ {"aes256ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
+ {"aes256ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
+ {"aes256ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
+ {"aes256ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
+ {"aesxcbc", INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0},
+ {"aes192gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
+ {"aes128gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
+ {"aes192gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
+ {"aes128gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
+ {"aes192gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
+ {"aes128gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
+ {"aes192gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
+ {"aes128gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
+ {"aes192gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
+ {"aes128gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
+ {"camellia192ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 192},
+ {"camellia128ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 128},
+ {"modp1024s160", DIFFIE_HELLMAN_GROUP, MODP_1024_160, 0},
+ {"modp3072", DIFFIE_HELLMAN_GROUP, MODP_3072_BIT, 0},
+ {"aes256gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
+ {"aes256gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
+ {"aes256gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
+ {"ecp192", DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0},
+ {"aes256gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
+ {"modp1536", DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0},
+ {"aes256gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
+ {"camellia256ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 256},
+ {"ecp521", DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0},
+ {"camellia192ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 192},
+ {"camellia128ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 128},
+ {"noesn", EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0},
+ {"aes192gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 192},
+ {"aes128gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 128},
+ {"modpnull", DIFFIE_HELLMAN_GROUP, MODP_NULL, 0},
+ {"aes192ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
+ {"aes128ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
+ {"ecp256", DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0},
+ {"camellia256ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 256},
+ {"blowfish", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
+ {"modp2048", DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0},
+ {"aes256gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 256},
+ {"modp4096", DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0},
+ {"modp1024", DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0},
+ {"blowfish192", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192},
+ {"aes256ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
+ {"blowfish128", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
+ {"aes192ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 192},
+ {"aes128ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 128},
+ {"modp2048s256", DIFFIE_HELLMAN_GROUP, MODP_2048_256, 0},
+ {"sha2_512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
+ {"aes192gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
+ {"aes128gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
+ {"esn", EXTENDED_SEQUENCE_NUMBERS, EXT_SEQ_NUMBERS, 0},
+ {"sha1_160", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_160, 0},
+ {"aes256ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 256},
+ {"blowfish256", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256},
+ {"sha2_256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
+ {"sha256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
+ {"aes256gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
+ {"sha2_256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
+ {"ecp224", DIFFIE_HELLMAN_GROUP, ECP_224_BIT, 0},
+ {"ecp384", DIFFIE_HELLMAN_GROUP, ECP_384_BIT, 0},
+ {"modp6144", DIFFIE_HELLMAN_GROUP, MODP_6144_BIT, 0},
+ {"modp2048s224", DIFFIE_HELLMAN_GROUP, MODP_2048_224, 0},
+ {"sha2_384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0}
+ };
+
+static const short lookup[] =
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,
+ 1, 2, -1, -1, -1, -1, 3, 4, -1, -1,
+ -1, 5, 6, -1, -1, 7, -1, 8, 9, 10,
+ 11, 12, -1, 13, -1, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ -1, -1, -1, -1, 29, 30, 31, 32, 33, 34,
+ 35, -1, 36, -1, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, -1, 58, -1, 59, -1,
+ 60, -1, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, -1, 75, -1, 76,
+ -1, 77, -1, 78, 79, 80, 81, 82, -1, 83,
+ 84, 85, 86, 87, -1, 88, 89, -1, 90, -1,
+ -1, 91, 92, -1, 93, -1, -1, 94, -1, 95,
+ 96, 97, 98, -1, 99, -1, 100, 101, 102, 103,
+ 104, 105, -1, -1, -1, 106, -1, -1, 107, 108,
+ -1, 109, -1, -1, 110, 111, 112, -1, -1, 113,
+ 114, -1, -1, -1, 115, 116, -1, 117, 118, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 119, -1, -1, -1, 120,
+ -1, -1, -1, 121
+ };
+
+#ifdef __GNUC__
+__inline
+#ifdef __GNUC_STDC_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const struct proposal_token *
+proposal_get_token_static (str, len)
+ register const char *str;
+ register unsigned int len;
+{
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = hash (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register int index = lookup[key];
+
+ if (index >= 0)
+ {
+ register const char *s = wordlist[index].name;
+
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
+ return &wordlist[index];
+ }
+ }
+ }
+ return 0;
+}
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords_static.h b/src/libstrongswan/crypto/proposal/proposal_keywords_static.h
new file mode 100644
index 000000000..bc421dcc5
--- /dev/null
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords_static.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * 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.
+ */
+
+#ifndef PROPOSAL_KEYWORDS_STATIC_H_
+#define PROPOSAL_KEYWORDS_STATIC_H_
+
+#include "proposal_keywords.h"
+
+const proposal_token_t* proposal_get_token_static(register const char *str,
+ register unsigned int len);
+
+#endif /* PROPOSAL_KEYWORDS_STATIC_H_ */
+
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords.txt b/src/libstrongswan/crypto/proposal/proposal_keywords_static.txt
index 1d04f2dc4..7f8c95757 100644
--- a/src/libstrongswan/crypto/proposal/proposal_keywords.txt
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords_static.txt
@@ -1,5 +1,5 @@
%{
-/* proposal keywords
+/*
* Copyright (C) 2009 Andreas Steffen
* Hochschule fuer Technik Rapperswil, Switzerland
*
@@ -23,10 +23,10 @@
%}
struct proposal_token {
- char *name;
- transform_type_t type;
+ char *name;
+ transform_type_t type;
u_int16_t algorithm;
- u_int16_t keysize;
+ u_int16_t keysize;
};
%%
null, ENCRYPTION_ALGORITHM, ENCR_NULL, 0
diff --git a/src/libstrongswan/crypto/rngs/rng.c b/src/libstrongswan/crypto/rngs/rng.c
index 67fd76910..f8fd50d3f 100644
--- a/src/libstrongswan/crypto/rngs/rng.c
+++ b/src/libstrongswan/crypto/rngs/rng.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -20,3 +21,43 @@ ENUM(rng_quality_names, RNG_WEAK, RNG_TRUE,
"RNG_STRONG",
"RNG_TRUE",
);
+
+/*
+ * Described in header.
+ */
+bool rng_get_bytes_not_zero(rng_t *rng, size_t len, u_int8_t *buffer, bool all)
+{
+ u_int8_t *pos = buffer, *check = buffer + (all ? len : min(1, len));
+
+ if (!rng->get_bytes(rng, len, pos))
+ {
+ return FALSE;
+ }
+
+ for (; pos < check; pos++)
+ {
+ while (*pos == 0)
+ {
+ if (!rng->get_bytes(rng, 1, pos))
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * Described in header.
+ */
+bool rng_allocate_bytes_not_zero(rng_t *rng, size_t len, chunk_t *chunk,
+ bool all)
+{
+ *chunk = chunk_alloc(len);
+ if (!rng_get_bytes_not_zero(rng, len, chunk->ptr, all))
+ {
+ chunk_clear(chunk);
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/src/libstrongswan/crypto/rngs/rng.h b/src/libstrongswan/crypto/rngs/rng.h
index 36ef52bb4..aee829d71 100644
--- a/src/libstrongswan/crypto/rngs/rng.h
+++ b/src/libstrongswan/crypto/rngs/rng.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -53,21 +54,53 @@ struct rng_t {
*
* @param len number of bytes to get
* @param buffer pointer where the generated bytes will be written
+ * @return TRUE if bytes successfully written
*/
- void (*get_bytes) (rng_t *this, size_t len, u_int8_t *buffer);
+ bool (*get_bytes)(rng_t *this, size_t len,
+ u_int8_t *buffer) __attribute__((warn_unused_result));
/**
* Generates random bytes and allocate space for them.
*
* @param len number of bytes to get
* @param chunk chunk which will hold generated bytes
+ * @return TRUE if allocation succeeded
*/
- void (*allocate_bytes) (rng_t *this, size_t len, chunk_t *chunk);
+ bool (*allocate_bytes)(rng_t *this, size_t len,
+ chunk_t *chunk) __attribute__((warn_unused_result));
/**
* Destroys a rng object.
*/
- void (*destroy) (rng_t *this);
+ void (*destroy)(rng_t *this);
};
+/**
+ * Wrapper around rng_t.get_bytes() ensuring that either all bytes or at least
+ * the first byte is not zero.
+ *
+ * @param rng rng_t object
+ * @param len number of bytes to get
+ * @param buffer pointer where the generated bytes will be written
+ * @param all TRUE if all bytes have to be non-zero, FALSE for first
+ * @return TRUE if bytes successfully written
+ */
+bool rng_get_bytes_not_zero(rng_t *rng, size_t len, u_int8_t *buffer,
+ bool all) __attribute__((warn_unused_result));
+
+/**
+ * Wrapper around rng_t.allocate_bytes() ensuring that either all bytes or at
+ * least the first byte is not zero.
+ *
+ * @param rng rng_t object
+ * @param len number of bytes to get
+ * @param chunk chunk that stores the generated bytes (allocated)
+ * @param all TRUE if all bytes have to be non-zero, FALSE for first
+ * @return TRUE if bytes successfully written
+ */
+bool rng_allocate_bytes_not_zero(rng_t *rng, size_t len, chunk_t *chunk,
+ bool all) __attribute__((warn_unused_result));
+
+
+
#endif /** RNG_H_ @}*/
diff --git a/src/libstrongswan/crypto/signers/mac_signer.c b/src/libstrongswan/crypto/signers/mac_signer.c
new file mode 100644
index 000000000..7c52aa305
--- /dev/null
+++ b/src/libstrongswan/crypto/signers/mac_signer.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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.
+ */
+
+#include "mac_signer.h"
+
+typedef struct private_signer_t private_signer_t;
+
+/**
+ * Private data of a mac_signer_t object.
+ */
+struct private_signer_t {
+
+ /**
+ * Public interface
+ */
+ signer_t public;
+
+ /**
+ * MAC to use
+ */
+ mac_t *mac;
+
+ /**
+ * Truncation of MAC output
+ */
+ size_t truncation;
+};
+
+METHOD(signer_t, get_signature, bool,
+ private_signer_t *this, chunk_t data, u_int8_t *buffer)
+{
+ if (buffer)
+ {
+ u_int8_t mac[this->mac->get_mac_size(this->mac)];
+
+ if (!this->mac->get_mac(this->mac, data, mac))
+ {
+ return FALSE;
+ }
+ memcpy(buffer, mac, this->truncation);
+ return TRUE;
+ }
+ return this->mac->get_mac(this->mac, data, NULL);
+}
+
+METHOD(signer_t, allocate_signature, bool,
+ private_signer_t *this, chunk_t data, chunk_t *chunk)
+{
+ if (chunk)
+ {
+ u_int8_t mac[this->mac->get_mac_size(this->mac)];
+
+ if (!this->mac->get_mac(this->mac, data, mac))
+ {
+ return FALSE;
+ }
+ *chunk = chunk_alloc(this->truncation);
+ memcpy(chunk->ptr, mac, this->truncation);
+ return TRUE;
+ }
+ return this->mac->get_mac(this->mac, data, NULL);
+}
+
+METHOD(signer_t, verify_signature, bool,
+ private_signer_t *this, chunk_t data, chunk_t signature)
+{
+ u_int8_t mac[this->mac->get_mac_size(this->mac)];
+
+ if (signature.len != this->truncation)
+ {
+ return FALSE;
+ }
+ return this->mac->get_mac(this->mac, data, mac) &&
+ memeq(signature.ptr, mac, this->truncation);
+}
+
+METHOD(signer_t, get_key_size, size_t,
+ private_signer_t *this)
+{
+ return this->mac->get_mac_size(this->mac);
+}
+
+METHOD(signer_t, get_block_size, size_t,
+ private_signer_t *this)
+{
+ return this->truncation;
+}
+
+METHOD(signer_t, set_key, bool,
+ private_signer_t *this, chunk_t key)
+{
+ return this->mac->set_key(this->mac, key);
+}
+
+METHOD(signer_t, destroy, void,
+ private_signer_t *this)
+{
+ this->mac->destroy(this->mac);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+signer_t *mac_signer_create(mac_t *mac, size_t len)
+{
+ private_signer_t *this;
+
+ INIT(this,
+ .public = {
+ .get_signature = _get_signature,
+ .allocate_signature = _allocate_signature,
+ .verify_signature = _verify_signature,
+ .get_block_size = _get_block_size,
+ .get_key_size = _get_key_size,
+ .set_key = _set_key,
+ .destroy = _destroy,
+ },
+ .truncation = min(len, mac->get_mac_size(mac)),
+ .mac = mac,
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/crypto/signers/mac_signer.h b/src/libstrongswan/crypto/signers/mac_signer.h
new file mode 100644
index 000000000..a50c8cadf
--- /dev/null
+++ b/src/libstrongswan/crypto/signers/mac_signer.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * 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 mac_signer mac_signer
+ * @{ @ingroup crypto
+ */
+
+#ifndef MAC_SIGNER_H_
+#define MAC_SIGNER_H_
+
+typedef struct mac_signer_t mac_signer_t;
+
+#include <crypto/mac.h>
+#include <crypto/signers/signer.h>
+
+/**
+ * Creates an implementation of the signer_t interface using the provided mac_t
+ * implementation and truncation length.
+ *
+ * @note len will be set to mac_t.get_mac_size() if it is greater than that.
+ *
+ * @param mac mac_t implementation
+ * @param len length of resulting signature
+ * @return mac_signer_t
+ */
+signer_t *mac_signer_create(mac_t *mac, size_t len);
+
+#endif /** MAC_SIGNER_H_ @}*/
diff --git a/src/libstrongswan/crypto/signers/signer.h b/src/libstrongswan/crypto/signers/signer.h
index c6870e475..9b6bd479a 100644
--- a/src/libstrongswan/crypto/signers/signer.h
+++ b/src/libstrongswan/crypto/signers/signer.h
@@ -91,8 +91,10 @@ struct signer_t {
*
* @param data a chunk containing the data to sign
* @param buffer pointer where the signature will be written
+ * @return TRUE if signature created successfully
*/
- void (*get_signature) (signer_t *this, chunk_t data, u_int8_t *buffer);
+ bool (*get_signature)(signer_t *this, chunk_t data,
+ u_int8_t *buffer) __attribute__((warn_unused_result));
/**
* Generate a signature and allocate space for it.
@@ -102,8 +104,10 @@ struct signer_t {
*
* @param data a chunk containing the data to sign
* @param chunk chunk which will hold the allocated signature
+ * @return TRUE if signature allocated successfully
*/
- void (*allocate_signature) (signer_t *this, chunk_t data, chunk_t *chunk);
+ bool (*allocate_signature)(signer_t *this, chunk_t data,
+ chunk_t *chunk) __attribute__((warn_unused_result));
/**
* Verify a signature.
@@ -116,33 +120,35 @@ struct signer_t {
* @param signature a chunk containing the signature
* @return TRUE, if signature is valid, FALSE otherwise
*/
- bool (*verify_signature) (signer_t *this, chunk_t data, chunk_t signature);
+ bool (*verify_signature)(signer_t *this, chunk_t data, chunk_t signature);
/**
* Get the block size of this signature algorithm.
*
* @return block size in bytes
*/
- size_t (*get_block_size) (signer_t *this);
+ size_t (*get_block_size)(signer_t *this);
/**
* Get the key size of the signature algorithm.
*
* @return key size in bytes
*/
- size_t (*get_key_size) (signer_t *this);
+ size_t (*get_key_size)(signer_t *this);
/**
* Set the key for this object.
*
* @param key key to set
+ * @return TRUE if key set
*/
- void (*set_key) (signer_t *this, chunk_t key);
+ bool (*set_key)(signer_t *this,
+ chunk_t key) __attribute__((warn_unused_result));
/**
* Destroys a signer_t object.
*/
- void (*destroy) (signer_t *this);
+ void (*destroy)(signer_t *this);
};
#endif /** SIGNER_H_ @}*/
diff --git a/src/libstrongswan/crypto/transform.c b/src/libstrongswan/crypto/transform.c
index 1e108f1de..56252971a 100644
--- a/src/libstrongswan/crypto/transform.c
+++ b/src/libstrongswan/crypto/transform.c
@@ -15,12 +15,13 @@
#include <crypto/transform.h>
-ENUM_BEGIN(transform_type_names, UNDEFINED_TRANSFORM_TYPE, AEAD_ALGORITHM,
+ENUM_BEGIN(transform_type_names, UNDEFINED_TRANSFORM_TYPE, COMPRESSION_ALGORITHM,
"UNDEFINED_TRANSFORM_TYPE",
"HASH_ALGORITHM",
"RANDOM_NUMBER_GENERATOR",
- "AEAD_ALGORITHM");
-ENUM_NEXT(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS, AEAD_ALGORITHM,
+ "AEAD_ALGORITHM",
+ "COMPRESSION_ALGORITHM");
+ENUM_NEXT(transform_type_names, ENCRYPTION_ALGORITHM, EXTENDED_SEQUENCE_NUMBERS, COMPRESSION_ALGORITHM,
"ENCRYPTION_ALGORITHM",
"PSEUDO_RANDOM_FUNCTION",
"INTEGRITY_ALGORITHM",
diff --git a/src/libstrongswan/crypto/transform.h b/src/libstrongswan/crypto/transform.h
index 1393c674c..311df068f 100644
--- a/src/libstrongswan/crypto/transform.h
+++ b/src/libstrongswan/crypto/transform.h
@@ -23,7 +23,7 @@
typedef enum transform_type_t transform_type_t;
-#include <library.h>
+#include <enum.h>
/**
* Type of a transform, as in IKEv2 RFC 3.3.2.
@@ -33,6 +33,7 @@ enum transform_type_t {
HASH_ALGORITHM = 242,
RANDOM_NUMBER_GENERATOR = 243,
AEAD_ALGORITHM = 244,
+ COMPRESSION_ALGORITHM = 245,
ENCRYPTION_ALGORITHM = 1,
PSEUDO_RANDOM_FUNCTION = 2,
INTEGRITY_ALGORITHM = 3,