Commit 464ff460 authored by James Morris's avatar James Morris Committed by David S. Miller

[CRYPTO]: Rework HMAC interface.

parent 03d4a1cd
...@@ -9,24 +9,30 @@ config CRYPTO ...@@ -9,24 +9,30 @@ config CRYPTO
help help
This option provides the core Cryptographic API. This option provides the core Cryptographic API.
config CRYPTO_HMAC
bool "HMAC support"
depends on CRYPTO
help
HMAC: Keyed-Hashing for Message Authentication (RFC2104).
This is required for IPSec.
config CRYPTO_MD4 config CRYPTO_MD4
tristate "MD4 digest algorithm" tristate "MD4 digest algorithm"
depends on CRYPTO depends on CRYPTO
help help
MD4 message digest algorithm (RFC1320), including HMAC (RFC2104). MD4 message digest algorithm (RFC1320).
config CRYPTO_MD5 config CRYPTO_MD5
tristate "MD5 digest algorithm" tristate "MD5 digest algorithm"
depends on CRYPTO depends on CRYPTO
help help
MD5 message digest algorithm (RFC1321), including HMAC (RFC2104, RFC2403). MD5 message digest algorithm (RFC1321).
config CRYPTO_SHA1 config CRYPTO_SHA1
tristate "SHA-1 digest algorithm" tristate "SHA-1 digest algorithm"
depends on CRYPTO depends on CRYPTO
help help
SHA-1 secure hash standard (FIPS 180-1), including HMAC (RFC2104, RFC2404). SHA-1 secure hash standard (FIPS 180-1).
config CRYPTO_DES config CRYPTO_DES
tristate "DES and Triple DES EDE cipher algorithms" tristate "DES and Triple DES EDE cipher algorithms"
......
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
# Cryptographic API # Cryptographic API
# #
export-objs := api.o export-objs := api.o hmac.o
obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o
obj-$(CONFIG_KMOD) += autoload.o obj-$(CONFIG_KMOD) += autoload.o
obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
obj-$(CONFIG_CRYPTO_MD4) += md4.o obj-$(CONFIG_CRYPTO_MD4) += md4.o
obj-$(CONFIG_CRYPTO_MD5) += md5.o obj-$(CONFIG_CRYPTO_MD5) += md5.o
obj-$(CONFIG_CRYPTO_SHA1) += sha1.o obj-$(CONFIG_CRYPTO_SHA1) += sha1.o
......
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
* *
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au> * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* *
* The HMAC implementation is derived from USAGI.
* Copyright (c) 2002 Kazunori Miyazawa <miyazawa@linux-ipv6.org> / USAGI
*
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free * under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option) * Software Foundation; either version 2 of the License, or (at your option)
...@@ -61,56 +58,6 @@ static void digest(struct crypto_tfm *tfm, ...@@ -61,56 +58,6 @@ static void digest(struct crypto_tfm *tfm,
crypto_digest_final(tfm, out); crypto_digest_final(tfm, out);
} }
static void hmac(struct crypto_tfm *tfm, u8 *key, unsigned int keylen,
struct scatterlist *sg, unsigned int nsg, u8 *out)
{
unsigned int i;
struct scatterlist tmp;
char ipad[crypto_tfm_alg_blocksize(tfm) + 1];
char opad[crypto_tfm_alg_blocksize(tfm) + 1];
if (keylen > crypto_tfm_alg_blocksize(tfm)) {
tmp.page = virt_to_page(key);
tmp.offset = ((long)key & ~PAGE_MASK);
tmp.length = keylen;
crypto_digest_digest(tfm, &tmp, 1, key);
keylen = crypto_tfm_alg_digestsize(tfm);
}
memset(ipad, 0, sizeof(ipad));
memset(opad, 0, sizeof(opad));
memcpy(ipad, key, keylen);
memcpy(opad, key, keylen);
for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) {
ipad[i] ^= 0x36;
opad[i] ^= 0x5c;
}
tmp.page = virt_to_page(ipad);
tmp.offset = ((long)ipad & ~PAGE_MASK);
tmp.length = crypto_tfm_alg_blocksize(tfm);
crypto_digest_init(tfm);
crypto_digest_update(tfm, &tmp, 1);
crypto_digest_update(tfm, sg, nsg);
crypto_digest_final(tfm, out);
tmp.page = virt_to_page(opad);
tmp.offset = ((long)opad & ~PAGE_MASK);
tmp.length = crypto_tfm_alg_blocksize(tfm);
crypto_digest_init(tfm);
crypto_digest_update(tfm, &tmp, 1);
tmp.page = virt_to_page(out);
tmp.offset = ((long)out & ~PAGE_MASK);
tmp.length = crypto_tfm_alg_digestsize(tfm);
crypto_digest_update(tfm, &tmp, 1);
crypto_digest_final(tfm, out);
}
int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
{ {
return crypto_cipher_flags(flags) ? -EINVAL : 0; return crypto_cipher_flags(flags) ? -EINVAL : 0;
...@@ -124,5 +71,4 @@ void crypto_init_digest_ops(struct crypto_tfm *tfm) ...@@ -124,5 +71,4 @@ void 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_hmac = hmac;
} }
/*
* Cryptographic API.
*
* HMAC: Keyed-Hashing for Message Authentication (RFC2104).
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
*
* The HMAC implementation is derived from USAGI.
* Copyright (c) 2002 Kazunori Miyazawa <miyazawa@linux-ipv6.org> / USAGI
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
*/
#include <linux/crypto.h>
#include <linux/mm.h>
#include <linux/highmem.h>
#include <asm/scatterlist.h>
#include "internal.h"
static void hash_key(struct crypto_tfm *tfm, u8 *key, unsigned int keylen)
{
struct scatterlist tmp;
tmp.page = virt_to_page(key);
tmp.offset = ((long)key & ~PAGE_MASK);
tmp.length = keylen;
crypto_digest_digest(tfm, &tmp, 1, key);
}
void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen)
{
unsigned int i;
struct scatterlist tmp;
char ipad[crypto_tfm_alg_blocksize(tfm) + 1];
if (*keylen > crypto_tfm_alg_blocksize(tfm)) {
hash_key(tfm, key, *keylen);
*keylen = crypto_tfm_alg_digestsize(tfm);
}
memset(ipad, 0, sizeof(ipad));
memcpy(ipad, key, *keylen);
for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++)
ipad[i] ^= 0x36;
tmp.page = virt_to_page(ipad);
tmp.offset = ((long)ipad & ~PAGE_MASK);
tmp.length = crypto_tfm_alg_blocksize(tfm);
crypto_digest_init(tfm);
crypto_digest_update(tfm, &tmp, 1);
}
void crypto_hmac_update(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg)
{
crypto_digest_update(tfm, sg, nsg);
}
void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key,
unsigned int *keylen, u8 *out)
{
unsigned int i;
struct scatterlist tmp;
char opad[crypto_tfm_alg_blocksize(tfm) + 1];
if (*keylen > crypto_tfm_alg_blocksize(tfm)) {
hash_key(tfm, key, *keylen);
*keylen = crypto_tfm_alg_digestsize(tfm);
}
crypto_digest_final(tfm, out);
memset(opad, 0, sizeof(opad));
memcpy(opad, key, *keylen);
for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++)
opad[i] ^= 0x5c;
tmp.page = virt_to_page(opad);
tmp.offset = ((long)opad & ~PAGE_MASK);
tmp.length = crypto_tfm_alg_blocksize(tfm);
crypto_digest_init(tfm);
crypto_digest_update(tfm, &tmp, 1);
tmp.page = virt_to_page(out);
tmp.offset = ((long)out & ~PAGE_MASK);
tmp.length = crypto_tfm_alg_digestsize(tfm);
crypto_digest_update(tfm, &tmp, 1);
crypto_digest_final(tfm, out);
}
void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen,
struct scatterlist *sg, unsigned int nsg, u8 *out)
{
crypto_hmac_init(tfm, key, keylen);
crypto_hmac_update(tfm, sg, nsg);
crypto_hmac_final(tfm, key, keylen, out);
}
EXPORT_SYMBOL_GPL(crypto_hmac_init);
EXPORT_SYMBOL_GPL(crypto_hmac_update);
EXPORT_SYMBOL_GPL(crypto_hmac_final);
EXPORT_SYMBOL_GPL(crypto_hmac);
...@@ -66,7 +66,6 @@ test_md5(void) ...@@ -66,7 +66,6 @@ test_md5(void)
char result[128]; char result[128];
struct crypto_tfm *tfm; struct crypto_tfm *tfm;
struct md5_testvec *md5_tv; struct md5_testvec *md5_tv;
struct hmac_md5_testvec *hmac_md5_tv;
unsigned int tsize; unsigned int tsize;
printk("\ntesting md5\n"); printk("\ntesting md5\n");
...@@ -131,6 +130,26 @@ test_md5(void) ...@@ -131,6 +130,26 @@ test_md5(void)
printk("%s\n", printk("%s\n",
memcmp(result, md5_tv[4].digest, memcmp(result, md5_tv[4].digest,
crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
crypto_free_tfm(tfm);
}
#ifdef CONFIG_CRYPTO_HMAC
static void
test_hmac_md5(void)
{
char *p;
unsigned int i, klen;
struct scatterlist sg[2];
char result[128];
struct crypto_tfm *tfm;
struct hmac_md5_testvec *hmac_md5_tv;
unsigned int tsize;
tfm = crypto_alloc_tfm("md5", 0);
if (tfm == NULL) {
printk("failed to load transform for md5\n");
return;
}
printk("\ntesting hmac_md5\n"); printk("\ntesting hmac_md5\n");
...@@ -138,7 +157,7 @@ test_md5(void) ...@@ -138,7 +157,7 @@ test_md5(void)
if (tsize > TVMEMSIZE) { if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize, printk("template (%u) too big for tvmem (%u)\n", tsize,
TVMEMSIZE); TVMEMSIZE);
return; goto out;
} }
memcpy(tvmem, hmac_md5_tv_template, tsize); memcpy(tvmem, hmac_md5_tv_template, tsize);
...@@ -153,8 +172,8 @@ test_md5(void) ...@@ -153,8 +172,8 @@ test_md5(void)
sg[0].offset = ((long) p & ~PAGE_MASK); sg[0].offset = ((long) p & ~PAGE_MASK);
sg[0].length = strlen(hmac_md5_tv[i].plaintext); sg[0].length = strlen(hmac_md5_tv[i].plaintext);
crypto_digest_hmac(tfm, hmac_md5_tv[i].key, klen = strlen(hmac_md5_tv[i].key);
strlen(hmac_md5_tv[i].key), sg, 1, result); crypto_hmac(tfm, hmac_md5_tv[i].key, &klen, sg, 1, result);
hexdump(result, crypto_tfm_alg_digestsize(tfm)); hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n", printk("%s\n",
...@@ -181,16 +200,96 @@ test_md5(void) ...@@ -181,16 +200,96 @@ test_md5(void)
sg[1].length = 12; sg[1].length = 12;
memset(result, 0, sizeof (result)); memset(result, 0, sizeof (result));
crypto_digest_hmac(tfm, hmac_md5_tv[1].key, strlen(hmac_md5_tv[1].key), klen = strlen(hmac_md5_tv[7].key);
sg, 2, result); crypto_hmac(tfm, hmac_md5_tv[7].key, &klen, sg, 2, result);
hexdump(result, crypto_tfm_alg_digestsize(tfm)); hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n", printk("%s\n",
memcmp(result, hmac_md5_tv[1].digest, memcmp(result, hmac_md5_tv[7].digest,
crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
out:
crypto_free_tfm(tfm);
}
static void
test_hmac_sha1(void)
{
char *p;
unsigned int i, klen;
struct crypto_tfm *tfm;
struct hmac_sha1_testvec *hmac_sha1_tv;
struct scatterlist sg[2];
unsigned int tsize;
char result[SHA1_DIGEST_SIZE];
tfm = crypto_alloc_tfm("sha1", 0);
if (tfm == NULL) {
printk("failed to load transform for sha1\n");
return;
}
printk("\ntesting hmac_sha1\n");
tsize = sizeof (hmac_sha1_tv_template);
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize,
TVMEMSIZE);
goto out;
}
memcpy(tvmem, hmac_sha1_tv_template, tsize);
hmac_sha1_tv = (void *) tvmem;
for (i = 0; i < HMAC_SHA1_TEST_VECTORS; i++) {
printk("test %u:\n", i + 1);
memset(result, 0, sizeof (result));
p = hmac_sha1_tv[i].plaintext;
sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK);
sg[0].length = strlen(hmac_sha1_tv[i].plaintext);
klen = strlen(hmac_sha1_tv[i].key);
crypto_hmac(tfm, hmac_sha1_tv[i].key, &klen, sg, 1, result);
hexdump(result, sizeof (result));
printk("%s\n",
memcmp(result, hmac_sha1_tv[i].digest,
crypto_tfm_alg_digestsize(tfm)) ? "fail" :
"pass");
}
printk("\ntesting hmac_sha1 across pages\n");
/* setup the dummy buffer first */
memset(xbuf, 0, sizeof (xbuf));
memcpy(&xbuf[IDX1], "what do ya want ", 16);
memcpy(&xbuf[IDX2], "for nothing?", 12);
p = &xbuf[IDX1];
sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK);
sg[0].length = 16;
p = &xbuf[IDX2];
sg[1].page = virt_to_page(p);
sg[1].offset = ((long) p & ~PAGE_MASK);
sg[1].length = 12;
memset(result, 0, sizeof (result));
klen = strlen(hmac_sha1_tv[7].key);
crypto_hmac(tfm, hmac_sha1_tv[7].key, &klen, sg, 2, result);
hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n",
memcmp(result, hmac_sha1_tv[7].digest,
crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
out:
crypto_free_tfm(tfm); crypto_free_tfm(tfm);
} }
#endif /* CONFIG_CRYPTO_HMAC */
static void static void
test_md4(void) test_md4(void)
...@@ -249,7 +348,6 @@ test_sha1(void) ...@@ -249,7 +348,6 @@ test_sha1(void)
unsigned int i; unsigned int i;
struct crypto_tfm *tfm; struct crypto_tfm *tfm;
struct sha1_testvec *sha1_tv; struct sha1_testvec *sha1_tv;
struct hmac_sha1_testvec *hmac_sha1_tv;
struct scatterlist sg[2]; struct scatterlist sg[2];
unsigned int tsize; unsigned int tsize;
char result[SHA1_DIGEST_SIZE]; char result[SHA1_DIGEST_SIZE];
...@@ -315,64 +413,6 @@ test_sha1(void) ...@@ -315,64 +413,6 @@ test_sha1(void)
printk("%s\n", printk("%s\n",
memcmp(result, sha1_tv[1].digest, memcmp(result, sha1_tv[1].digest,
crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
printk("\ntesting hmac_sha1\n");
tsize = sizeof (hmac_sha1_tv_template);
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize,
TVMEMSIZE);
return;
}
memcpy(tvmem, hmac_sha1_tv_template, tsize);
hmac_sha1_tv = (void *) tvmem;
for (i = 0; i < HMAC_SHA1_TEST_VECTORS; i++) {
printk("test %u:\n", i + 1);
memset(result, 0, sizeof (result));
p = hmac_sha1_tv[i].plaintext;
sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK);
sg[0].length = strlen(hmac_sha1_tv[i].plaintext);
crypto_digest_hmac(tfm, hmac_sha1_tv[i].key,
strlen(hmac_sha1_tv[i].key), sg, 1, result);
hexdump(result, sizeof (result));
printk("%s\n",
memcmp(result, hmac_sha1_tv[i].digest,
crypto_tfm_alg_digestsize(tfm)) ? "fail" :
"pass");
}
printk("\ntesting hmac_sha1 across pages\n");
/* setup the dummy buffer first */
memset(xbuf, 0, sizeof (xbuf));
memcpy(&xbuf[IDX1], "what do ya want ", 16);
memcpy(&xbuf[IDX2], "for nothing?", 12);
p = &xbuf[IDX1];
sg[0].page = virt_to_page(p);
sg[0].offset = ((long) p & ~PAGE_MASK);
sg[0].length = 16;
p = &xbuf[IDX2];
sg[1].page = virt_to_page(p);
sg[1].offset = ((long) p & ~PAGE_MASK);
sg[1].length = 12;
memset(result, 0, sizeof (result));
crypto_digest_hmac(tfm, hmac_sha1_tv[1].key,
strlen(hmac_sha1_tv[1].key), sg, 2, result);
hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n",
memcmp(result, hmac_sha1_tv[1].digest,
crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
crypto_free_tfm(tfm); crypto_free_tfm(tfm);
} }
...@@ -1325,6 +1365,10 @@ do_test(void) ...@@ -1325,6 +1365,10 @@ do_test(void)
test_des(); test_des();
test_des3_ede(); test_des3_ede();
test_md4(); test_md4();
#ifdef CONFIG_CRYPTO_HMAC
test_hmac_md5();
test_hmac_sha1();
#endif
break; break;
case 1: case 1:
...@@ -1347,7 +1391,18 @@ do_test(void) ...@@ -1347,7 +1391,18 @@ do_test(void)
test_md4(); test_md4();
break; break;
#ifdef CONFIG_CRYPTO_HMAC
case 100: case 100:
test_hmac_md5();
break;
case 101:
test_hmac_sha1();
break;
#endif
case 1000:
test_available(); test_available();
break; break;
......
...@@ -105,6 +105,7 @@ struct md5_testvec { ...@@ -105,6 +105,7 @@ struct md5_testvec {
0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } } 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }
}; };
#ifdef CONFIG_CRYPTO_HMAC
/* /*
* HMAC-MD5 test vectors from RFC2202 * HMAC-MD5 test vectors from RFC2202
* (These need to be fixed to not use strlen). * (These need to be fixed to not use strlen).
...@@ -214,7 +215,19 @@ struct hmac_md5_testvec hmac_md5_tv_template[] = ...@@ -214,7 +215,19 @@ struct hmac_md5_testvec hmac_md5_tv_template[] =
{ 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, { 0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee,
0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e } 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e }
} },
/* cross page test, need to retain key */
{
{ 'J', 'e', 'f', 'e', 0 },
"what do ya want for nothing?",
{ 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 }
},
}; };
...@@ -334,9 +347,22 @@ struct hmac_sha1_testvec { ...@@ -334,9 +347,22 @@ struct hmac_sha1_testvec {
{ 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b,
0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 } 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 }
} },
/* cross page test */
{
{ 'J', 'e', 'f', 'e', 0 },
"what do ya want for nothing?",
{ 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74,
0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 }
},
}; };
#endif /* CONFIG_CRYPTO_HMAC */
/* /*
* SHA1 test vectors from from FIPS PUB 180-1 * SHA1 test vectors from from FIPS PUB 180-1
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/page.h>
/* /*
* Algorithm masks and types. * Algorithm masks and types.
...@@ -141,9 +142,6 @@ struct digest_tfm { ...@@ -141,9 +142,6 @@ 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);
void (*dit_hmac)(struct crypto_tfm *tfm, u8 *key,
unsigned int keylen, struct scatterlist *sg,
unsigned int nsg, u8 *out);
}; };
struct compress_tfm { struct compress_tfm {
...@@ -259,16 +257,6 @@ static inline void crypto_digest_digest(struct crypto_tfm *tfm, ...@@ -259,16 +257,6 @@ 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 void crypto_digest_hmac(struct crypto_tfm *tfm,
u8 *key, unsigned int keylen,
struct scatterlist *sg,
unsigned int nsg, u8 *out)
{
BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
tfm->crt_digest.dit_hmac(tfm, key, keylen, sg, nsg, out);
}
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)
{ {
...@@ -318,4 +306,18 @@ static inline void crypto_comp_decompress(struct crypto_tfm *tfm) ...@@ -318,4 +306,18 @@ static inline void crypto_comp_decompress(struct crypto_tfm *tfm)
tfm->crt_compress.cot_decompress(tfm); tfm->crt_compress.cot_decompress(tfm);
} }
/*
* HMAC support.
*/
#ifdef CONFIG_CRYPTO_HMAC
void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen);
void crypto_hmac_update(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg);
void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key,
unsigned int *keylen, u8 *out);
void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen,
struct scatterlist *sg, unsigned int nsg, u8 *out);
#endif /* CONFIG_CRYPTO_HMAC */
#endif /* _LINUX_CRYPTO_H */ #endif /* _LINUX_CRYPTO_H */
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