crypto: drbg - use single block cipher API

The CTR DRBG only encrypts one single block at a time. Thus, use the
single block crypto API to avoid additional overhead from the block
chaining modes.

With the patch, the speed of the DRBG increases between 30% and 40%.

The DRBG still passes the CTR DRBG CAVS test.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Stephan Mueller 2015-03-01 20:39:17 +01:00 committed by Herbert Xu
parent e8e5995372
commit 04bcbfcf7e

View file

@ -119,19 +119,19 @@ static const struct drbg_core drbg_cores[] = {
.statelen = 32, /* 256 bits as defined in 10.2.1 */ .statelen = 32, /* 256 bits as defined in 10.2.1 */
.blocklen_bytes = 16, .blocklen_bytes = 16,
.cra_name = "ctr_aes128", .cra_name = "ctr_aes128",
.backend_cra_name = "ecb(aes)", .backend_cra_name = "aes",
}, { }, {
.flags = DRBG_CTR | DRBG_STRENGTH192, .flags = DRBG_CTR | DRBG_STRENGTH192,
.statelen = 40, /* 320 bits as defined in 10.2.1 */ .statelen = 40, /* 320 bits as defined in 10.2.1 */
.blocklen_bytes = 16, .blocklen_bytes = 16,
.cra_name = "ctr_aes192", .cra_name = "ctr_aes192",
.backend_cra_name = "ecb(aes)", .backend_cra_name = "aes",
}, { }, {
.flags = DRBG_CTR | DRBG_STRENGTH256, .flags = DRBG_CTR | DRBG_STRENGTH256,
.statelen = 48, /* 384 bits as defined in 10.2.1 */ .statelen = 48, /* 384 bits as defined in 10.2.1 */
.blocklen_bytes = 16, .blocklen_bytes = 16,
.cra_name = "ctr_aes256", .cra_name = "ctr_aes256",
.backend_cra_name = "ecb(aes)", .backend_cra_name = "aes",
}, },
#endif /* CONFIG_CRYPTO_DRBG_CTR */ #endif /* CONFIG_CRYPTO_DRBG_CTR */
#ifdef CONFIG_CRYPTO_DRBG_HASH #ifdef CONFIG_CRYPTO_DRBG_HASH
@ -1644,24 +1644,24 @@ static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
static int drbg_init_sym_kernel(struct drbg_state *drbg) static int drbg_init_sym_kernel(struct drbg_state *drbg)
{ {
int ret = 0; int ret = 0;
struct crypto_blkcipher *tfm; struct crypto_cipher *tfm;
tfm = crypto_alloc_blkcipher(drbg->core->backend_cra_name, 0, 0); tfm = crypto_alloc_cipher(drbg->core->backend_cra_name, 0, 0);
if (IS_ERR(tfm)) { if (IS_ERR(tfm)) {
pr_info("DRBG: could not allocate cipher TFM handle\n"); pr_info("DRBG: could not allocate cipher TFM handle\n");
return PTR_ERR(tfm); return PTR_ERR(tfm);
} }
BUG_ON(drbg_blocklen(drbg) != crypto_blkcipher_blocksize(tfm)); BUG_ON(drbg_blocklen(drbg) != crypto_cipher_blocksize(tfm));
drbg->priv_data = tfm; drbg->priv_data = tfm;
return ret; return ret;
} }
static int drbg_fini_sym_kernel(struct drbg_state *drbg) static int drbg_fini_sym_kernel(struct drbg_state *drbg)
{ {
struct crypto_blkcipher *tfm = struct crypto_cipher *tfm =
(struct crypto_blkcipher *)drbg->priv_data; (struct crypto_cipher *)drbg->priv_data;
if (tfm) if (tfm)
crypto_free_blkcipher(tfm); crypto_free_cipher(tfm);
drbg->priv_data = NULL; drbg->priv_data = NULL;
return 0; return 0;
} }
@ -1669,21 +1669,14 @@ static int drbg_fini_sym_kernel(struct drbg_state *drbg)
static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key, static int drbg_kcapi_sym(struct drbg_state *drbg, const unsigned char *key,
unsigned char *outval, const struct drbg_string *in) unsigned char *outval, const struct drbg_string *in)
{ {
int ret = 0; struct crypto_cipher *tfm =
struct scatterlist sg_in, sg_out; (struct crypto_cipher *)drbg->priv_data;
struct blkcipher_desc desc;
struct crypto_blkcipher *tfm =
(struct crypto_blkcipher *)drbg->priv_data;
desc.tfm = tfm; crypto_cipher_setkey(tfm, key, (drbg_keylen(drbg)));
desc.flags = 0;
crypto_blkcipher_setkey(tfm, key, (drbg_keylen(drbg)));
/* there is only component in *in */ /* there is only component in *in */
sg_init_one(&sg_in, in->buf, in->len); BUG_ON(in->len < drbg_blocklen(drbg));
sg_init_one(&sg_out, outval, drbg_blocklen(drbg)); crypto_cipher_encrypt_one(tfm, outval, in->buf);
ret = crypto_blkcipher_encrypt(&desc, &sg_out, &sg_in, in->len); return 0;
return ret;
} }
#endif /* CONFIG_CRYPTO_DRBG_CTR */ #endif /* CONFIG_CRYPTO_DRBG_CTR */