aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2010-08-13 14:11:38 +0200
committerMartin Willi <martin@revosec.ch>2010-08-13 17:11:53 +0200
commit42cbe87fc7fc80e23d3941b712acfadc29e00a2c (patch)
treeb4826718551482e1319650440f0f557de438292f /src/libstrongswan
parent3b77c27a5b30f726bbc86f175439e1fcb3f36a31 (diff)
downloadstrongswan-42cbe87fc7fc80e23d3941b712acfadc29e00a2c.tar.bz2
strongswan-42cbe87fc7fc80e23d3941b712acfadc29e00a2c.tar.xz
Implemented AES/Camellia counter mode in gcrypt
Diffstat (limited to 'src/libstrongswan')
-rw-r--r--src/libstrongswan/crypto/crypters/crypter.h10
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c63
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c6
3 files changed, 73 insertions, 6 deletions
diff --git a/src/libstrongswan/crypto/crypters/crypter.h b/src/libstrongswan/crypto/crypters/crypter.h
index 70697e207..6596d469c 100644
--- a/src/libstrongswan/crypto/crypters/crypter.h
+++ b/src/libstrongswan/crypto/crypters/crypter.h
@@ -42,6 +42,7 @@ enum encryption_algorithm_t {
ENCR_DES_IV32 = 9,
ENCR_NULL = 11,
ENCR_AES_CBC = 12,
+ /** CTR as specified for IPsec (RFC5930/RFC3686), nonce appended to key */
ENCR_AES_CTR = 13,
ENCR_AES_CCM_ICV8 = 14,
ENCR_AES_CCM_ICV12 = 15,
@@ -51,6 +52,7 @@ enum encryption_algorithm_t {
ENCR_AES_GCM_ICV16 = 20,
ENCR_NULL_AUTH_AES_GMAC = 21,
ENCR_CAMELLIA_CBC = 23,
+ /* CTR as specified for IPsec (RFC5529), nonce appended to key */
ENCR_CAMELLIA_CTR = 24,
ENCR_CAMELLIA_CCM_ICV8 = 25,
ENCR_CAMELLIA_CCM_ICV12 = 26,
@@ -109,6 +111,10 @@ struct crypter_t {
/**
* Get the block size of the crypto algorithm.
*
+ * get_block_size() returns the smallest block the crypter can handle,
+ * not the block size of the underlying crypto algorithm. For counter mode,
+ * it is usually 1.
+ *
* @return block size in bytes
*/
size_t (*get_block_size) (crypter_t *this);
@@ -123,6 +129,10 @@ struct crypter_t {
/**
* Get the key size of the crypto algorithm.
*
+ * get_key_size() might return a key length different from the key
+ * size passed to the factory constructor. For Counter Mode, the nonce
+ * is handled as a part of the key material and is passed to set_key().
+ *
* @return key size in bytes
*/
size_t (*get_key_size) (crypter_t *this);
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c b/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c
index db8bfea36..1d849bc09 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c
@@ -40,12 +40,43 @@ struct private_gcrypt_crypter_t {
* gcrypt algorithm identifier
*/
int alg;
+
+ /**
+ * are we using counter mode?
+ */
+ bool ctr_mode;
+
+ /**
+ * counter state
+ */
+ struct {
+ char nonce[4];
+ char iv[8];
+ u_int32_t counter;
+ } __attribute__((packed)) ctr;
};
+/**
+ * Set the IV for en/decryption
+ */
+static void set_iv(private_gcrypt_crypter_t *this, chunk_t iv)
+{
+ if (this->ctr_mode)
+ {
+ memcpy(this->ctr.iv, iv.ptr, sizeof(this->ctr.iv));
+ this->ctr.counter = htonl(1);
+ gcry_cipher_setctr(this->h, &this->ctr, sizeof(this->ctr));
+ }
+ else
+ {
+ gcry_cipher_setiv(this->h, iv.ptr, iv.len);
+ }
+}
+
METHOD(crypter_t, decrypt, void,
private_gcrypt_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
{
- gcry_cipher_setiv(this->h, iv.ptr, iv.len);
+ set_iv(this, iv);
if (dst)
{
@@ -61,7 +92,7 @@ METHOD(crypter_t, decrypt, void,
METHOD(crypter_t, encrypt, void,
private_gcrypt_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
{
- gcry_cipher_setiv(this->h, iv.ptr, iv.len);
+ set_iv(this, iv);
if (dst)
{
@@ -79,6 +110,10 @@ METHOD(crypter_t, get_block_size, size_t,
{
size_t len = 0;
+ if (this->ctr_mode)
+ { /* counter mode does not need any padding */
+ return 1;
+ }
gcry_cipher_algo_info(this->alg, GCRYCTL_GET_BLKLEN, NULL, &len);
return len;
}
@@ -88,6 +123,10 @@ METHOD(crypter_t, get_iv_size, size_t,
{
size_t len = 0;
+ if (this->ctr_mode)
+ {
+ return sizeof(this->ctr.iv);
+ }
gcry_cipher_algo_info(this->alg, GCRYCTL_GET_BLKLEN, NULL, &len);
return len;
}
@@ -98,12 +137,23 @@ METHOD(crypter_t, get_key_size, size_t,
size_t len = 0;
gcry_cipher_algo_info(this->alg, GCRYCTL_GET_KEYLEN, NULL, &len);
+ if (this->ctr_mode)
+ {
+ return len + sizeof(this->ctr.nonce);
+ }
return len;
}
METHOD(crypter_t, set_key, void,
private_gcrypt_crypter_t *this, chunk_t key)
{
+ if (this->ctr_mode)
+ {
+ /* last 4 bytes are the nonce */
+ memcpy(this->ctr.nonce, key.ptr + key.len - sizeof(this->ctr.nonce),
+ sizeof(this->ctr.nonce));
+ key.len -= sizeof(this->ctr.nonce);
+ }
gcry_cipher_setkey(this->h, key.ptr, key.len);
}
@@ -150,8 +200,8 @@ gcrypt_crypter_t *gcrypt_crypter_create(encryption_algorithm_t algo,
}
gcrypt_alg = GCRY_CIPHER_BLOWFISH;
break;
- /* case ENCR_AES_CTR:
- mode = GCRY_CIPHER_MODE_CTR; */
+ case ENCR_AES_CTR:
+ mode = GCRY_CIPHER_MODE_CTR;
/* fall */
case ENCR_AES_CBC:
switch (key_size)
@@ -169,8 +219,8 @@ gcrypt_crypter_t *gcrypt_crypter_create(encryption_algorithm_t algo,
return NULL;
}
break;
- /* case ENCR_CAMELLIA_CTR:
- mode = GCRY_CIPHER_MODE_CTR; */
+ case ENCR_CAMELLIA_CTR:
+ mode = GCRY_CIPHER_MODE_CTR;
/* fall */
case ENCR_CAMELLIA_CBC:
switch (key_size)
@@ -234,6 +284,7 @@ gcrypt_crypter_t *gcrypt_crypter_create(encryption_algorithm_t algo,
.destroy = _destroy,
},
.alg = gcrypt_alg,
+ .ctr_mode = mode == GCRY_CIPHER_MODE_CTR,
);
err = gcry_cipher_open(&this->h, gcrypt_alg, mode, 0);
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
index 99f9f2fe4..cc13f5516 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
@@ -170,8 +170,14 @@ plugin_t *gcrypt_plugin_create()
(crypter_constructor_t)gcrypt_crypter_create);
lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC,
(crypter_constructor_t)gcrypt_crypter_create);
+ lib->crypto->add_crypter(lib->crypto, ENCR_AES_CTR,
+ (crypter_constructor_t)gcrypt_crypter_create);
+#ifdef HAVE_GCRY_CIPHER_CAMELLIA
lib->crypto->add_crypter(lib->crypto, ENCR_CAMELLIA_CBC,
(crypter_constructor_t)gcrypt_crypter_create);
+ lib->crypto->add_crypter(lib->crypto, ENCR_CAMELLIA_CTR,
+ (crypter_constructor_t)gcrypt_crypter_create);
+#endif /* HAVE_GCRY_CIPHER_CAMELLIA */
lib->crypto->add_crypter(lib->crypto, ENCR_SERPENT_CBC,
(crypter_constructor_t)gcrypt_crypter_create);
lib->crypto->add_crypter(lib->crypto, ENCR_TWOFISH_CBC,