digest: add HMAC support for md5, sha1, sha224, sha256, sha384, sha512
the hmac algo will be registered as hmac(%s) such as hmac(sha256) Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
3a43692412
commit
2f3c3f512b
|
@ -30,4 +30,7 @@ config SHA384
|
|||
config SHA512
|
||||
bool "SHA512"
|
||||
|
||||
config DIGEST_HMAC
|
||||
bool "HMAC"
|
||||
|
||||
endif
|
||||
|
|
|
@ -2,6 +2,7 @@ obj-$(CONFIG_CRC32) += crc32.o
|
|||
obj-$(CONFIG_CRC16) += crc16.o
|
||||
obj-$(CONFIG_CRC7) += crc7.o
|
||||
obj-$(CONFIG_DIGEST) += digest.o
|
||||
obj-$(CONFIG_DIGEST_HMAC) += hmac.o
|
||||
obj-$(CONFIG_MD5) += md5.o
|
||||
obj-$(CONFIG_SHA1) += sha1.o
|
||||
obj-$(CONFIG_SHA224) += sha2.o
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
|
||||
*
|
||||
* GPL v2 only
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <digest.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
struct digest_hmac {
|
||||
char *name;
|
||||
unsigned int pad_length;
|
||||
struct digest_algo algo;
|
||||
};
|
||||
|
||||
struct digest_hmac_ctx {
|
||||
struct digest *d;
|
||||
|
||||
unsigned char *ipad;
|
||||
unsigned char *opad;
|
||||
|
||||
unsigned char *key;
|
||||
unsigned int keylen;
|
||||
};
|
||||
|
||||
static inline struct digest_hmac * to_digest_hmac(struct digest_algo *algo)
|
||||
{
|
||||
return container_of(algo, struct digest_hmac, algo);
|
||||
}
|
||||
|
||||
static int digest_hmac_alloc(struct digest *d)
|
||||
{
|
||||
struct digest_hmac_ctx *dh = d->ctx;
|
||||
struct digest_hmac *hmac = to_digest_hmac(d->algo);
|
||||
|
||||
dh->d = digest_alloc(hmac->name);
|
||||
if (!dh->d)
|
||||
return -EINVAL;
|
||||
|
||||
dh->ipad = xmalloc(hmac->pad_length);
|
||||
dh->opad = xmalloc(hmac->pad_length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void digest_hmac_free(struct digest *d)
|
||||
{
|
||||
struct digest_hmac_ctx *dh = d->ctx;
|
||||
|
||||
free(dh->ipad);
|
||||
free(dh->opad);
|
||||
free(dh->key);
|
||||
|
||||
digest_free(dh->d);
|
||||
}
|
||||
|
||||
static int digest_hmac_set_key(struct digest *d, const unsigned char *key,
|
||||
unsigned int len)
|
||||
{
|
||||
struct digest_hmac_ctx *dh = d->ctx;
|
||||
struct digest_hmac *hmac = to_digest_hmac(d->algo);
|
||||
|
||||
free(dh->key);
|
||||
if (len > hmac->pad_length) {
|
||||
unsigned char *sum;
|
||||
|
||||
sum = xmalloc(digest_length(dh->d));
|
||||
digest_init(dh->d);
|
||||
digest_update(dh->d, dh->key, dh->keylen);
|
||||
digest_final(dh->d, sum);
|
||||
dh->keylen = digest_length(dh->d);
|
||||
dh->key = sum;
|
||||
} else {
|
||||
dh->key = xmalloc(len);
|
||||
memcpy(dh->key, key, len);
|
||||
dh->keylen = len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int digest_hmac_init(struct digest *d)
|
||||
{
|
||||
struct digest_hmac_ctx *dh = d->ctx;
|
||||
struct digest_hmac *hmac = to_digest_hmac(d->algo);
|
||||
int i;
|
||||
unsigned char *key = dh->key;
|
||||
unsigned int keylen = dh->keylen;
|
||||
|
||||
memset(dh->ipad, 0x36, hmac->pad_length);
|
||||
memset(dh->opad, 0x5C, hmac->pad_length);
|
||||
|
||||
for (i = 0; i < keylen; i++) {
|
||||
dh->ipad[i] = (unsigned char)(dh->ipad[i] ^ key[i]);
|
||||
dh->opad[i] = (unsigned char)(dh->opad[i] ^ key[i]);
|
||||
}
|
||||
|
||||
digest_init(dh->d);
|
||||
digest_update(dh->d, dh->ipad, hmac->pad_length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int digest_hmac_update(struct digest *d, const void *data,
|
||||
unsigned long len)
|
||||
{
|
||||
struct digest_hmac_ctx *dh = d->ctx;
|
||||
|
||||
return digest_update(dh->d, data, len);
|
||||
}
|
||||
|
||||
static int digest_hmac_final(struct digest *d, unsigned char *md)
|
||||
{
|
||||
struct digest_hmac_ctx *dh = d->ctx;
|
||||
struct digest_hmac *hmac = to_digest_hmac(d->algo);
|
||||
unsigned char *tmp = NULL;
|
||||
|
||||
tmp = xmalloc(digest_length(d));
|
||||
|
||||
digest_final(dh->d, tmp);
|
||||
digest_init(dh->d);
|
||||
digest_update(dh->d, dh->opad, hmac->pad_length);
|
||||
digest_update(dh->d, tmp, digest_length(d));
|
||||
digest_final(dh->d, md);
|
||||
|
||||
free(tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct digest_algo hmac_algo = {
|
||||
.alloc = digest_hmac_alloc,
|
||||
.init = digest_hmac_init,
|
||||
.update = digest_hmac_update,
|
||||
.final = digest_hmac_final,
|
||||
.set_key = digest_hmac_set_key,
|
||||
.free = digest_hmac_free,
|
||||
.ctx_length = sizeof(struct digest_hmac),
|
||||
};
|
||||
|
||||
int digest_hmac_register(struct digest_algo *algo, unsigned int pad_length)
|
||||
{
|
||||
struct digest_hmac *dh;
|
||||
|
||||
if (!algo || !pad_length)
|
||||
return -EINVAL;
|
||||
|
||||
dh = xzalloc(sizeof(*dh));
|
||||
dh->name = xstrdup(algo->name);
|
||||
dh->pad_length = pad_length;
|
||||
dh->algo = hmac_algo;
|
||||
dh->algo.length = algo->length;
|
||||
dh->algo.name = asprintf("hmac(%s)", algo->name);
|
||||
|
||||
return digest_algo_register(&dh->algo);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* (C) Copyright 2015 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
|
||||
*
|
||||
* GPL v2 only
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_DIGEST_HMAC
|
||||
int digest_hmac_register(struct digest_algo *algo, unsigned int pad_length);
|
||||
#else
|
||||
static inline int digest_hmac_register(struct digest_algo *algo,
|
||||
unsigned int pad_length)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
10
crypto/md5.c
10
crypto/md5.c
|
@ -29,6 +29,8 @@
|
|||
#include <digest.h>
|
||||
#include <init.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
struct MD5Context {
|
||||
__u32 buf[4];
|
||||
__u32 bits[2];
|
||||
|
@ -298,8 +300,12 @@ static struct digest_algo md5 = {
|
|||
|
||||
static int md5_digest_register(void)
|
||||
{
|
||||
digest_algo_register(&md5);
|
||||
int ret;
|
||||
|
||||
return 0;
|
||||
ret = digest_algo_register(&md5);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return digest_hmac_register(&md5, 64);
|
||||
}
|
||||
device_initcall(md5_digest_register);
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <linux/string.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define SHA1_SUM_POS -0x20
|
||||
#define SHA1_SUM_LEN 20
|
||||
|
||||
|
@ -319,8 +321,12 @@ static struct digest_algo m = {
|
|||
|
||||
static int sha1_digest_register(void)
|
||||
{
|
||||
digest_algo_register(&m);
|
||||
int ret;
|
||||
|
||||
return 0;
|
||||
ret = digest_algo_register(&m);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return digest_hmac_register(&m, 64);
|
||||
}
|
||||
device_initcall(sha1_digest_register);
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <linux/string.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define SHA224_SUM_LEN 28
|
||||
#define SHA256_SUM_LEN 32
|
||||
|
||||
|
@ -290,7 +292,6 @@ static int digest_sha2_final(struct digest *d, unsigned char *md)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SHA224
|
||||
static int digest_sha224_init(struct digest *d)
|
||||
{
|
||||
sha2_starts(d->ctx, 1);
|
||||
|
@ -306,9 +307,22 @@ static struct digest_algo m224 = {
|
|||
.length = SHA224_SUM_LEN,
|
||||
.ctx_length = sizeof(sha2_context),
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SHA256
|
||||
static int sha224_digest_register(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SHA224))
|
||||
return 0;
|
||||
|
||||
ret = digest_algo_register(&m224);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return digest_hmac_register(&m224, 64);
|
||||
}
|
||||
device_initcall(sha224_digest_register);
|
||||
|
||||
static int digest_sha256_init(struct digest *d)
|
||||
{
|
||||
sha2_starts(d->ctx, 0);
|
||||
|
@ -324,17 +338,18 @@ static struct digest_algo m256 = {
|
|||
.length = SHA256_SUM_LEN,
|
||||
.ctx_length = sizeof(sha2_context),
|
||||
};
|
||||
#endif
|
||||
|
||||
static int sha2_digest_register(void)
|
||||
static int sha256_digest_register(void)
|
||||
{
|
||||
#ifdef CONFIG_SHA224
|
||||
digest_algo_register(&m224);
|
||||
#endif
|
||||
#ifdef CONFIG_SHA256
|
||||
digest_algo_register(&m256);
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
return 0;
|
||||
if (!IS_ENABLED(CONFIG_SHA256))
|
||||
return 0;
|
||||
|
||||
ret = digest_algo_register(&m256);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return digest_hmac_register(&m256, 64);
|
||||
}
|
||||
device_initcall(sha2_digest_register);
|
||||
device_initcall(sha256_digest_register);
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include <linux/string.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define SHA384_SUM_LEN 48
|
||||
#define SHA512_SUM_LEN 64
|
||||
|
||||
|
@ -311,6 +313,22 @@ static struct digest_algo m384 = {
|
|||
.ctx_length = sizeof(sha4_context),
|
||||
};
|
||||
|
||||
|
||||
static int sha384_digest_register(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SHA384))
|
||||
return 0;
|
||||
|
||||
ret = digest_algo_register(&m384);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return digest_hmac_register(&m384, 128);
|
||||
}
|
||||
device_initcall(sha384_digest_register);
|
||||
|
||||
static int digest_sha512_init(struct digest *d)
|
||||
{
|
||||
sha4_starts(d->ctx, 0);
|
||||
|
@ -327,14 +345,17 @@ static struct digest_algo m512 = {
|
|||
.ctx_length = sizeof(sha4_context),
|
||||
};
|
||||
|
||||
static int sha4_digest_register(void)
|
||||
static int sha512_digest_register(void)
|
||||
{
|
||||
if IS_ENABLED(CONFIG_SHA384)
|
||||
digest_algo_register(&m384);
|
||||
int ret;
|
||||
|
||||
if IS_ENABLED(CONFIG_SHA512)
|
||||
digest_algo_register(&m512);
|
||||
if (!IS_ENABLED(CONFIG_SHA512))
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
ret = digest_algo_register(&m512);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return digest_hmac_register(&m512, 128);
|
||||
}
|
||||
device_initcall(sha4_digest_register);
|
||||
device_initcall(sha512_digest_register);
|
||||
|
|
|
@ -31,6 +31,7 @@ struct digest_algo {
|
|||
int (*init)(struct digest *d);
|
||||
int (*update)(struct digest *d, const void *data, unsigned long len);
|
||||
int (*final)(struct digest *d, unsigned char *md);
|
||||
int (*set_key)(struct digest *d, unsigned char *key, unsigned int len);
|
||||
|
||||
unsigned int length;
|
||||
unsigned int ctx_length;
|
||||
|
@ -81,4 +82,11 @@ static inline int digest_length(struct digest *d)
|
|||
return d->algo->length;
|
||||
}
|
||||
|
||||
static inline int digest_set_key(struct digest *d, unsigned char *key, unsigned int len)
|
||||
{
|
||||
if (!d->algo->set_key)
|
||||
return -ENOTSUPP;
|
||||
return d->algo->set_key(d, key, len);
|
||||
}
|
||||
|
||||
#endif /* __SH_ST_DEVICES_H__ */
|
||||
|
|
Loading…
Reference in New Issue