Commit 5654cd6c authored by James Morris's avatar James Morris Committed by Linus Torvalds

[CRYPTO]: Add setkey operation for digests.

From Jouni Malinen <jkmaline@cc.hut.fi>

Added support for using keyed digest with an optional dit_setkey handler.
This does not change the behavior of the existing digest algorithms, but
allows new ones to add setkey handler that can be used to initialize the
algorithm with a key or seed. setkey is to be called after init, but before
any of the update call(s).
parent c81430b5
...@@ -42,6 +42,15 @@ static void final(struct crypto_tfm *tfm, u8 *out) ...@@ -42,6 +42,15 @@ static void final(struct crypto_tfm *tfm, u8 *out)
tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out); tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
} }
static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
{
u32 flags;
if (tfm->__crt_alg->cra_digest.dia_setkey == NULL)
return -ENOSYS;
return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm),
key, keylen, &flags);
}
static void digest(struct crypto_tfm *tfm, static void digest(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg, u8 *out) struct scatterlist *sg, unsigned int nsg, u8 *out)
{ {
...@@ -72,6 +81,7 @@ int crypto_init_digest_ops(struct crypto_tfm *tfm) ...@@ -72,6 +81,7 @@ int crypto_init_digest_ops(struct crypto_tfm *tfm)
ops->dit_update = update; ops->dit_update = update;
ops->dit_final = final; ops->dit_final = final;
ops->dit_digest = digest; ops->dit_digest = digest;
ops->dit_setkey = setkey;
return crypto_alloc_hmac_block(tfm); return crypto_alloc_hmac_block(tfm);
} }
......
...@@ -112,6 +112,10 @@ test_hash (char * algo, struct hash_testvec * template, unsigned int tcount) ...@@ -112,6 +112,10 @@ test_hash (char * algo, struct hash_testvec * template, unsigned int tcount)
sg[0].length = hash_tv[i].psize; sg[0].length = hash_tv[i].psize;
crypto_digest_init (tfm); crypto_digest_init (tfm);
if (tfm->crt_u.digest.dit_setkey) {
crypto_digest_setkey (tfm, hash_tv[i].key,
hash_tv[i].ksize);
}
crypto_digest_update (tfm, sg, 1); crypto_digest_update (tfm, sg, 1);
crypto_digest_final (tfm, result); crypto_digest_final (tfm, result);
......
...@@ -30,6 +30,8 @@ struct hash_testvec { ...@@ -30,6 +30,8 @@ struct hash_testvec {
char digest[MAX_DIGEST_SIZE]; char digest[MAX_DIGEST_SIZE];
unsigned char np; unsigned char np;
unsigned char tap[MAX_TAP]; unsigned char tap[MAX_TAP];
char key[128]; /* only used with keyed hash algorithms */
unsigned char ksize;
}; };
struct hmac_testvec { struct hmac_testvec {
......
...@@ -76,6 +76,8 @@ struct digest_alg { ...@@ -76,6 +76,8 @@ struct digest_alg {
void (*dia_init)(void *ctx); void (*dia_init)(void *ctx);
void (*dia_update)(void *ctx, const u8 *data, unsigned int len); void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
void (*dia_final)(void *ctx, u8 *out); void (*dia_final)(void *ctx, u8 *out);
int (*dia_setkey)(void *ctx, const u8 *key,
unsigned int keylen, u32 *flags);
}; };
struct compress_alg { struct compress_alg {
...@@ -157,6 +159,8 @@ struct digest_tfm { ...@@ -157,6 +159,8 @@ struct digest_tfm {
void (*dit_final)(struct crypto_tfm *tfm, u8 *out); void (*dit_final)(struct crypto_tfm *tfm, u8 *out);
void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg, void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
unsigned int nsg, u8 *out); unsigned int nsg, u8 *out);
int (*dit_setkey)(struct crypto_tfm *tfm,
const u8 *key, unsigned int keylen);
#ifdef CONFIG_CRYPTO_HMAC #ifdef CONFIG_CRYPTO_HMAC
void *dit_hmac_block; void *dit_hmac_block;
#endif #endif
...@@ -282,6 +286,15 @@ static inline void crypto_digest_digest(struct crypto_tfm *tfm, ...@@ -282,6 +286,15 @@ static inline void crypto_digest_digest(struct crypto_tfm *tfm,
tfm->crt_digest.dit_digest(tfm, sg, nsg, out); tfm->crt_digest.dit_digest(tfm, sg, nsg, out);
} }
static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
const u8 *key, unsigned int keylen)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
if (tfm->crt_digest.dit_setkey == NULL)
return -ENOSYS;
return tfm->crt_digest.dit_setkey(tfm, key, keylen);
}
static inline int crypto_cipher_setkey(struct crypto_tfm *tfm, static inline int crypto_cipher_setkey(struct crypto_tfm *tfm,
const u8 *key, unsigned int keylen) const u8 *key, unsigned int keylen)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment