summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Morris <jmorris@redhat.com>2004-03-21 06:36:22 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-03-21 06:36:22 -0800
commit5654cd6cccf5d2a1eec0f8d60b5196fd454f523a (patch)
tree24e4d4124df920be8916acb43a988468c15b2c5e
parentc81430b50f55670cd5bef96242021943832e4470 (diff)
[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).
-rw-r--r--crypto/digest.c10
-rw-r--r--crypto/tcrypt.c4
-rw-r--r--crypto/tcrypt.h2
-rw-r--r--include/linux/crypto.h13
4 files changed, 29 insertions, 0 deletions
diff --git a/crypto/digest.c b/crypto/digest.c
index a62327d3c37b..30dabe203d30 100644
--- a/crypto/digest.c
+++ b/crypto/digest.c
@@ -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);
}
+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,
struct scatterlist *sg, unsigned int nsg, u8 *out)
{
@@ -72,6 +81,7 @@ int crypto_init_digest_ops(struct crypto_tfm *tfm)
ops->dit_update = update;
ops->dit_final = final;
ops->dit_digest = digest;
+ ops->dit_setkey = setkey;
return crypto_alloc_hmac_block(tfm);
}
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 0208e531315f..0caf31954330 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -112,6 +112,10 @@ test_hash (char * algo, struct hash_testvec * template, unsigned int tcount)
sg[0].length = hash_tv[i].psize;
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_final (tfm, result);
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index 0880165b1400..f4a6f3dd5ec1 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -30,6 +30,8 @@ struct hash_testvec {
char digest[MAX_DIGEST_SIZE];
unsigned char np;
unsigned char tap[MAX_TAP];
+ char key[128]; /* only used with keyed hash algorithms */
+ unsigned char ksize;
};
struct hmac_testvec {
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 2331966abe8f..0f0d8a9f5b53 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -76,6 +76,8 @@ struct digest_alg {
void (*dia_init)(void *ctx);
void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
void (*dia_final)(void *ctx, u8 *out);
+ int (*dia_setkey)(void *ctx, const u8 *key,
+ unsigned int keylen, u32 *flags);
};
struct compress_alg {
@@ -157,6 +159,8 @@ struct digest_tfm {
void (*dit_final)(struct crypto_tfm *tfm, u8 *out);
void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
unsigned int nsg, u8 *out);
+ int (*dit_setkey)(struct crypto_tfm *tfm,
+ const u8 *key, unsigned int keylen);
#ifdef CONFIG_CRYPTO_HMAC
void *dit_hmac_block;
#endif
@@ -282,6 +286,15 @@ static inline void crypto_digest_digest(struct crypto_tfm *tfm,
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,
const u8 *key, unsigned int keylen)
{