Implemented AES/Camellia counter mode in gcrypt
This commit is contained in:
@@ -42,6 +42,7 @@ enum encryption_algorithm_t {
|
|||||||
ENCR_DES_IV32 = 9,
|
ENCR_DES_IV32 = 9,
|
||||||
ENCR_NULL = 11,
|
ENCR_NULL = 11,
|
||||||
ENCR_AES_CBC = 12,
|
ENCR_AES_CBC = 12,
|
||||||
|
/** CTR as specified for IPsec (RFC5930/RFC3686), nonce appended to key */
|
||||||
ENCR_AES_CTR = 13,
|
ENCR_AES_CTR = 13,
|
||||||
ENCR_AES_CCM_ICV8 = 14,
|
ENCR_AES_CCM_ICV8 = 14,
|
||||||
ENCR_AES_CCM_ICV12 = 15,
|
ENCR_AES_CCM_ICV12 = 15,
|
||||||
@@ -51,6 +52,7 @@ enum encryption_algorithm_t {
|
|||||||
ENCR_AES_GCM_ICV16 = 20,
|
ENCR_AES_GCM_ICV16 = 20,
|
||||||
ENCR_NULL_AUTH_AES_GMAC = 21,
|
ENCR_NULL_AUTH_AES_GMAC = 21,
|
||||||
ENCR_CAMELLIA_CBC = 23,
|
ENCR_CAMELLIA_CBC = 23,
|
||||||
|
/* CTR as specified for IPsec (RFC5529), nonce appended to key */
|
||||||
ENCR_CAMELLIA_CTR = 24,
|
ENCR_CAMELLIA_CTR = 24,
|
||||||
ENCR_CAMELLIA_CCM_ICV8 = 25,
|
ENCR_CAMELLIA_CCM_ICV8 = 25,
|
||||||
ENCR_CAMELLIA_CCM_ICV12 = 26,
|
ENCR_CAMELLIA_CCM_ICV12 = 26,
|
||||||
@@ -109,6 +111,10 @@ struct crypter_t {
|
|||||||
/**
|
/**
|
||||||
* Get the block size of the crypto algorithm.
|
* 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
|
* @return block size in bytes
|
||||||
*/
|
*/
|
||||||
size_t (*get_block_size) (crypter_t *this);
|
size_t (*get_block_size) (crypter_t *this);
|
||||||
@@ -123,6 +129,10 @@ struct crypter_t {
|
|||||||
/**
|
/**
|
||||||
* Get the key size of the crypto algorithm.
|
* 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
|
* @return key size in bytes
|
||||||
*/
|
*/
|
||||||
size_t (*get_key_size) (crypter_t *this);
|
size_t (*get_key_size) (crypter_t *this);
|
||||||
|
|||||||
@@ -40,12 +40,43 @@ struct private_gcrypt_crypter_t {
|
|||||||
* gcrypt algorithm identifier
|
* gcrypt algorithm identifier
|
||||||
*/
|
*/
|
||||||
int alg;
|
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,
|
METHOD(crypter_t, decrypt, void,
|
||||||
private_gcrypt_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
|
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)
|
if (dst)
|
||||||
{
|
{
|
||||||
@@ -61,7 +92,7 @@ METHOD(crypter_t, decrypt, void,
|
|||||||
METHOD(crypter_t, encrypt, void,
|
METHOD(crypter_t, encrypt, void,
|
||||||
private_gcrypt_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
|
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)
|
if (dst)
|
||||||
{
|
{
|
||||||
@@ -79,6 +110,10 @@ METHOD(crypter_t, get_block_size, size_t,
|
|||||||
{
|
{
|
||||||
size_t len = 0;
|
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);
|
gcry_cipher_algo_info(this->alg, GCRYCTL_GET_BLKLEN, NULL, &len);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@@ -88,6 +123,10 @@ METHOD(crypter_t, get_iv_size, size_t,
|
|||||||
{
|
{
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (this->ctr_mode)
|
||||||
|
{
|
||||||
|
return sizeof(this->ctr.iv);
|
||||||
|
}
|
||||||
gcry_cipher_algo_info(this->alg, GCRYCTL_GET_BLKLEN, NULL, &len);
|
gcry_cipher_algo_info(this->alg, GCRYCTL_GET_BLKLEN, NULL, &len);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@@ -98,12 +137,23 @@ METHOD(crypter_t, get_key_size, size_t,
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
gcry_cipher_algo_info(this->alg, GCRYCTL_GET_KEYLEN, NULL, &len);
|
gcry_cipher_algo_info(this->alg, GCRYCTL_GET_KEYLEN, NULL, &len);
|
||||||
|
if (this->ctr_mode)
|
||||||
|
{
|
||||||
|
return len + sizeof(this->ctr.nonce);
|
||||||
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(crypter_t, set_key, void,
|
METHOD(crypter_t, set_key, void,
|
||||||
private_gcrypt_crypter_t *this, chunk_t key)
|
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);
|
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;
|
gcrypt_alg = GCRY_CIPHER_BLOWFISH;
|
||||||
break;
|
break;
|
||||||
/* case ENCR_AES_CTR:
|
case ENCR_AES_CTR:
|
||||||
mode = GCRY_CIPHER_MODE_CTR; */
|
mode = GCRY_CIPHER_MODE_CTR;
|
||||||
/* fall */
|
/* fall */
|
||||||
case ENCR_AES_CBC:
|
case ENCR_AES_CBC:
|
||||||
switch (key_size)
|
switch (key_size)
|
||||||
@@ -169,8 +219,8 @@ gcrypt_crypter_t *gcrypt_crypter_create(encryption_algorithm_t algo,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/* case ENCR_CAMELLIA_CTR:
|
case ENCR_CAMELLIA_CTR:
|
||||||
mode = GCRY_CIPHER_MODE_CTR; */
|
mode = GCRY_CIPHER_MODE_CTR;
|
||||||
/* fall */
|
/* fall */
|
||||||
case ENCR_CAMELLIA_CBC:
|
case ENCR_CAMELLIA_CBC:
|
||||||
switch (key_size)
|
switch (key_size)
|
||||||
@@ -234,6 +284,7 @@ gcrypt_crypter_t *gcrypt_crypter_create(encryption_algorithm_t algo,
|
|||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.alg = gcrypt_alg,
|
.alg = gcrypt_alg,
|
||||||
|
.ctr_mode = mode == GCRY_CIPHER_MODE_CTR,
|
||||||
);
|
);
|
||||||
|
|
||||||
err = gcry_cipher_open(&this->h, gcrypt_alg, mode, 0);
|
err = gcry_cipher_open(&this->h, gcrypt_alg, mode, 0);
|
||||||
|
|||||||
@@ -170,8 +170,14 @@ plugin_t *gcrypt_plugin_create()
|
|||||||
(crypter_constructor_t)gcrypt_crypter_create);
|
(crypter_constructor_t)gcrypt_crypter_create);
|
||||||
lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC,
|
lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC,
|
||||||
(crypter_constructor_t)gcrypt_crypter_create);
|
(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,
|
lib->crypto->add_crypter(lib->crypto, ENCR_CAMELLIA_CBC,
|
||||||
(crypter_constructor_t)gcrypt_crypter_create);
|
(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,
|
lib->crypto->add_crypter(lib->crypto, ENCR_SERPENT_CBC,
|
||||||
(crypter_constructor_t)gcrypt_crypter_create);
|
(crypter_constructor_t)gcrypt_crypter_create);
|
||||||
lib->crypto->add_crypter(lib->crypto, ENCR_TWOFISH_CBC,
|
lib->crypto->add_crypter(lib->crypto, ENCR_TWOFISH_CBC,
|
||||||
|
|||||||
Reference in New Issue
Block a user