mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-09-07 22:15:19 +00:00
Add generic message authentication interface
Add generic interface for generating and verifying MACs (message authentication codes). Replace multiple HMAC implementation with a generic one.
This commit is contained in:
parent
7eec398875
commit
de2a27e255
1
lib/Doc
1
lib/Doc
@ -2,6 +2,7 @@ H Library functions
|
||||
S ip.c
|
||||
S lists.c
|
||||
S checksum.c bitops.c patmatch.c printf.c xmalloc.c tbf.c
|
||||
S mac.c
|
||||
D resource.sgml
|
||||
S resource.c
|
||||
S mempool.c
|
||||
|
@ -11,6 +11,8 @@ ip.h
|
||||
ip.c
|
||||
lists.c
|
||||
lists.h
|
||||
mac.c
|
||||
mac.h
|
||||
md5.c
|
||||
md5.h
|
||||
mempool.c
|
||||
|
289
lib/mac.c
Normal file
289
lib/mac.c
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* BIRD Library -- Message Authentication Codes
|
||||
*
|
||||
* (c) 2016 Ondrej Zajicek <santiago@crfreenet.org>
|
||||
* (c) 2016 CZ.NIC z.s.p.o.
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: Message authentication codes
|
||||
*
|
||||
* MAC algorithms are simple cryptographic tools for message authentication.
|
||||
* They use shared a secret key a and message text to generate authentication
|
||||
* code, which is then passed with the message to the other side, where the code
|
||||
* is verified. There are multiple families of MAC algorithms based on different
|
||||
* cryptographic primitives, BIRD implements two MAC families which use hash
|
||||
* functions.
|
||||
*
|
||||
* The first family is simply a cryptographic hash camouflaged as MAC algorithm.
|
||||
* Originally supposed to be (m|k)-hash (message is concatenated with key, and
|
||||
* that is hashed), but later it turned out that a raw hash is more practical.
|
||||
* This is used for cryptographic authentication in OSPFv2, RIP and BFD.
|
||||
*
|
||||
* The second family is the standard HMAC (RFC 2104), using inner and outer hash
|
||||
* to process key and message. HMAC (with SHA) is used in advanced OSPF and RIP
|
||||
* authentication (RFC 5709, RFC 4822).
|
||||
*/
|
||||
|
||||
#include "lib/mac.h"
|
||||
#include "lib/md5.h"
|
||||
#include "lib/sha1.h"
|
||||
#include "lib/sha256.h"
|
||||
#include "lib/sha512.h"
|
||||
|
||||
|
||||
/*
|
||||
* Internal hash calls
|
||||
*/
|
||||
|
||||
static inline void
|
||||
hash_init(struct mac_context *mctx, struct hash_context *hctx)
|
||||
{ mctx->type->hash_init(hctx); }
|
||||
|
||||
static inline void
|
||||
hash_update(struct mac_context *mctx, struct hash_context *hctx, const byte *buf, uint len)
|
||||
{ mctx->type->hash_update(hctx, buf, len); }
|
||||
|
||||
static inline byte *
|
||||
hash_final(struct mac_context *mctx, struct hash_context *hctx)
|
||||
{ return mctx->type->hash_final(hctx); }
|
||||
|
||||
static inline void
|
||||
hash_buffer(struct mac_context *mctx, byte *outbuf, const byte *buffer, uint length)
|
||||
{
|
||||
struct hash_context hctx;
|
||||
|
||||
hash_init(mctx, &hctx);
|
||||
hash_update(mctx, &hctx, buffer, length);
|
||||
memcpy(outbuf, hash_final(mctx, &hctx), mctx->type->hash_size);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (not-really-MAC) Hash
|
||||
*/
|
||||
|
||||
static void
|
||||
nrmh_init(struct mac_context *ctx, const byte *key UNUSED, uint keylen UNUSED)
|
||||
{
|
||||
struct nrmh_context *ct = (void *) ctx;
|
||||
hash_init(ctx, &ct->ictx);
|
||||
}
|
||||
|
||||
static void
|
||||
nrmh_update(struct mac_context *ctx, const byte *data, uint datalen)
|
||||
{
|
||||
struct nrmh_context *ct = (void *) ctx;
|
||||
hash_update(ctx, &ct->ictx, data, datalen);
|
||||
}
|
||||
|
||||
static byte *
|
||||
nrmh_final(struct mac_context *ctx)
|
||||
{
|
||||
struct nrmh_context *ct = (void *) ctx;
|
||||
return hash_final(ctx, &ct->ictx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* HMAC
|
||||
*/
|
||||
|
||||
static void
|
||||
hmac_init(struct mac_context *ctx, const byte *key, uint keylen)
|
||||
{
|
||||
struct hmac_context *ct = (void *) ctx;
|
||||
uint block_size = ctx->type->block_size;
|
||||
uint hash_size = ctx->type->hash_size;
|
||||
|
||||
byte *keybuf = alloca(block_size);
|
||||
byte *buf = alloca(block_size);
|
||||
uint i;
|
||||
|
||||
/* Hash the key if necessary */
|
||||
if (keylen <= block_size)
|
||||
{
|
||||
memcpy(keybuf, key, keylen);
|
||||
memset(keybuf + keylen, 0, block_size - keylen);
|
||||
}
|
||||
else
|
||||
{
|
||||
hash_buffer(ctx, keybuf, key, keylen);
|
||||
memset(keybuf + hash_size, 0, block_size - hash_size);
|
||||
}
|
||||
|
||||
/* Initialize the inner digest */
|
||||
hash_init(ctx, &ct->ictx);
|
||||
for (i = 0; i < block_size; i++)
|
||||
buf[i] = keybuf[i] ^ 0x36;
|
||||
hash_update(ctx, &ct->ictx, buf, block_size);
|
||||
|
||||
/* Initialize the outer digest */
|
||||
hash_init(ctx, &ct->octx);
|
||||
for (i = 0; i < block_size; i++)
|
||||
buf[i] = keybuf[i] ^ 0x5c;
|
||||
hash_update(ctx, &ct->octx, buf, block_size);
|
||||
}
|
||||
|
||||
static void
|
||||
hmac_update(struct mac_context *ctx, const byte *data, uint datalen)
|
||||
{
|
||||
struct hmac_context *ct = (void *) ctx;
|
||||
|
||||
/* Just update the inner digest */
|
||||
hash_update(ctx, &ct->ictx, data, datalen);
|
||||
}
|
||||
|
||||
static byte *
|
||||
hmac_final(struct mac_context *ctx)
|
||||
{
|
||||
struct hmac_context *ct = (void *) ctx;
|
||||
|
||||
/* Finish the inner digest */
|
||||
byte *isha = hash_final(ctx, &ct->ictx);
|
||||
|
||||
/* Finish the outer digest */
|
||||
hash_update(ctx, &ct->octx, isha, ctx->type->hash_size);
|
||||
return hash_final(ctx, &ct->octx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Common code
|
||||
*/
|
||||
|
||||
#define HASH_DESC(name, px, PX) \
|
||||
{ name, PX##_SIZE, sizeof(struct nrmh_context), nrmh_init, nrmh_update, nrmh_final, \
|
||||
PX##_SIZE, PX##_BLOCK_SIZE, px##_init, px##_update, px##_final }
|
||||
|
||||
#define HMAC_DESC(name, px, PX) \
|
||||
{ name, PX##_SIZE, sizeof(struct hmac_context), hmac_init, hmac_update, hmac_final, \
|
||||
PX##_SIZE, PX##_BLOCK_SIZE, px##_init, px##_update, px##_final }
|
||||
|
||||
const struct mac_desc mac_table[ALG_MAX] = {
|
||||
[ALG_MD5] = HASH_DESC("Keyed MD5", md5, MD5),
|
||||
[ALG_SHA1] = HASH_DESC("Keyed SHA-1", sha1, SHA1),
|
||||
[ALG_SHA224] = HASH_DESC("Keyed SHA-224", sha224, SHA224),
|
||||
[ALG_SHA256] = HASH_DESC("Keyed SHA-256", sha256, SHA256),
|
||||
[ALG_SHA384] = HASH_DESC("Keyed SHA-384", sha384, SHA384),
|
||||
[ALG_SHA512] = HASH_DESC("Keyed SHA-512", sha512, SHA512),
|
||||
[ALG_HMAC_MD5] = HMAC_DESC("HMAC-MD5", md5, MD5),
|
||||
[ALG_HMAC_SHA1] = HMAC_DESC("HMAC-SHA-1", sha1, SHA1),
|
||||
[ALG_HMAC_SHA224] = HMAC_DESC("HMAC-SHA-224", sha224, SHA224),
|
||||
[ALG_HMAC_SHA256] = HMAC_DESC("HMAC-SHA-256", sha256, SHA256),
|
||||
[ALG_HMAC_SHA384] = HMAC_DESC("HMAC-SHA-384", sha384, SHA384),
|
||||
[ALG_HMAC_SHA512] = HMAC_DESC("HMAC-SHA-512", sha512, SHA512),
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* mac_init - initialize MAC algorithm
|
||||
* @ctx: context to initialize
|
||||
* @id: MAC algorithm ID
|
||||
* @key: MAC key
|
||||
* @keylen: MAC key length
|
||||
*
|
||||
* Initialize MAC context @ctx for algorithm @id (e.g., %ALG_HMAC_SHA1), with
|
||||
* key @key of length @keylen. After that, message data could be added using
|
||||
* mac_update() function.
|
||||
*/
|
||||
void
|
||||
mac_init(struct mac_context *ctx, uint id, const byte *key, uint keylen)
|
||||
{
|
||||
ctx->type = &mac_table[id];
|
||||
ctx->type->init(ctx, key, keylen);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* mac_update - add more data to MAC algorithm
|
||||
* @ctx: MAC context
|
||||
* @data: data to add
|
||||
* @datalen: length of data
|
||||
*
|
||||
* Push another @datalen bytes of data pointed to by @data into the MAC
|
||||
* algorithm currently in @ctx. Can be called multiple times for the same MAC
|
||||
* context. It has the same effect as concatenating all the data together and
|
||||
* passing them at once.
|
||||
*/
|
||||
void mac_update(struct mac_context *ctx, const byte *data, uint datalen)
|
||||
{ DUMMY; }
|
||||
|
||||
/**
|
||||
* mac_final - finalize MAC algorithm
|
||||
* @ctx: MAC context
|
||||
*
|
||||
* Finish MAC computation and return a pointer to the result. No more
|
||||
* @mac_update() calls could be done, but the context may be reinitialized
|
||||
* later.
|
||||
*
|
||||
* Note that the returned pointer points into data in the @ctx context. If it
|
||||
* ceases to exist, the pointer becomes invalid.
|
||||
*/
|
||||
byte *mac_final(struct mac_context *ctx)
|
||||
{ DUMMY; }
|
||||
|
||||
/**
|
||||
* mac_cleanup - cleanup MAC context
|
||||
* @ctx: MAC context
|
||||
*
|
||||
* Cleanup MAC context after computation (by filling with zeros). Not strictly
|
||||
* necessary, just to erase sensitive data from stack. This also invalidates the
|
||||
* pointer returned by @mac_final().
|
||||
*/
|
||||
void mac_cleanup(struct mac_context *ctx)
|
||||
{ DUMMY; }
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* mac_fill - compute and fill MAC
|
||||
* @id: MAC algorithm ID
|
||||
* @key: secret key
|
||||
* @keylen: key length
|
||||
* @data: message data
|
||||
* @datalen: message length
|
||||
* @mac: place to fill MAC
|
||||
*
|
||||
* Compute MAC for specified key @key and message @data using algorithm @id and
|
||||
* copy it to buffer @mac. mac_fill() is a shortcut function doing all usual
|
||||
* steps for transmitted messages.
|
||||
*/
|
||||
void
|
||||
mac_fill(uint id, const byte *key, uint keylen, const byte *data, uint datalen, byte *mac)
|
||||
{
|
||||
struct mac_context ctx;
|
||||
|
||||
mac_init(&ctx, id, key, keylen);
|
||||
mac_update(&ctx, data, datalen);
|
||||
memcpy(mac, mac_final(&ctx), mac_get_length(&ctx));
|
||||
mac_cleanup(&ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* mac_verify - compute and verify MAC
|
||||
* @id: MAC algorithm ID
|
||||
* @key: secret key
|
||||
* @keylen: key length
|
||||
* @data: message data
|
||||
* @datalen: message length
|
||||
* @mac: received MAC
|
||||
*
|
||||
* Compute MAC for specified key @key and message @data using algorithm @id and
|
||||
* compare it with received @mac, return whether they are the same. mac_verify()
|
||||
* is a shortcut function doing all usual steps for received messages.
|
||||
*/
|
||||
int
|
||||
mac_verify(uint id, const byte *key, uint keylen, const byte *data, uint datalen, const byte *mac)
|
||||
{
|
||||
struct mac_context ctx;
|
||||
|
||||
mac_init(&ctx, id, key, keylen);
|
||||
mac_update(&ctx, data, datalen);
|
||||
int res = !memcmp(mac, mac_final(&ctx), mac_get_length(&ctx));
|
||||
mac_cleanup(&ctx);
|
||||
|
||||
return res;
|
||||
}
|
117
lib/mac.h
Normal file
117
lib/mac.h
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* BIRD Library -- Message Authentication Codes
|
||||
*
|
||||
* (c) 2016 Ondrej Zajicek <santiago@crfreenet.org>
|
||||
* (c) 2016 CZ.NIC z.s.p.o.
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
#ifndef _BIRD_MAC_H_
|
||||
#define _BIRD_MAC_H_
|
||||
|
||||
#include "nest/bird.h"
|
||||
#include "lib/sha512.h"
|
||||
|
||||
|
||||
#define ALG_UNDEFINED 0
|
||||
#define ALG_MD5 0x01
|
||||
#define ALG_SHA1 0x02
|
||||
#define ALG_SHA224 0x03
|
||||
#define ALG_SHA256 0x04
|
||||
#define ALG_SHA384 0x05
|
||||
#define ALG_SHA512 0x06
|
||||
#define ALG_HMAC_MD5 0x11
|
||||
#define ALG_HMAC_SHA1 0x12
|
||||
#define ALG_HMAC_SHA224 0x13
|
||||
#define ALG_HMAC_SHA256 0x14
|
||||
#define ALG_HMAC_SHA384 0x15
|
||||
#define ALG_HMAC_SHA512 0x16
|
||||
#define ALG_MAX 0x17
|
||||
|
||||
/* These are maximums for HASH/MAC lengths and required context space */
|
||||
#define MAX_HASH_SIZE SHA512_SIZE
|
||||
#define HASH_STORAGE sizeof(struct sha512_context)
|
||||
#define MAC_STORAGE sizeof(struct hmac_context)
|
||||
|
||||
/* Generic context used by hash functions */
|
||||
struct hash_context
|
||||
{
|
||||
u8 data[HASH_STORAGE];
|
||||
u64 align[0];
|
||||
};
|
||||
|
||||
/* Context for embedded hash (not-really-MAC hash) */
|
||||
struct nrmh_context {
|
||||
const struct mac_desc *type;
|
||||
struct hash_context ictx;
|
||||
};
|
||||
|
||||
/* Context for hash based HMAC */
|
||||
struct hmac_context {
|
||||
const struct mac_desc *type;
|
||||
struct hash_context ictx;
|
||||
struct hash_context octx;
|
||||
};
|
||||
|
||||
/* Generic context used by MAC functions */
|
||||
struct mac_context
|
||||
{
|
||||
const struct mac_desc *type;
|
||||
u8 data[MAC_STORAGE - sizeof(void *)];
|
||||
u64 align[0];
|
||||
};
|
||||
|
||||
/* Union to satisfy C aliasing rules */
|
||||
union mac_context_union {
|
||||
struct mac_context mac;
|
||||
struct nrmh_context nrmh;
|
||||
struct hmac_context hmac;
|
||||
};
|
||||
|
||||
|
||||
struct mac_desc {
|
||||
const char *name; /* Name of MAC algorithm */
|
||||
uint mac_length; /* Length of authentication code */
|
||||
uint ctx_length; /* Length of algorithm context */
|
||||
void (*init)(struct mac_context *ctx, const byte *key, uint keylen);
|
||||
void (*update)(struct mac_context *ctx, const byte *data, uint datalen);
|
||||
byte *(*final)(struct mac_context *ctx);
|
||||
|
||||
uint hash_size; /* Hash length, for hash-based MACs */
|
||||
uint block_size; /* Hash block size, for hash-based MACs */
|
||||
void (*hash_init)(struct hash_context *ctx);
|
||||
void (*hash_update)(struct hash_context *ctx, const byte *data, uint datalen);
|
||||
byte *(*hash_final)(struct hash_context *ctx);
|
||||
};
|
||||
|
||||
const struct mac_desc mac_table[ALG_MAX];
|
||||
|
||||
static inline const char *mac_type_name(uint id)
|
||||
{ return mac_table[id].name; }
|
||||
|
||||
static inline uint mac_type_length(uint id)
|
||||
{ return mac_table[id].mac_length; }
|
||||
|
||||
static inline const char *mac_get_name(struct mac_context *ctx)
|
||||
{ return ctx->type->name; }
|
||||
|
||||
static inline uint mac_get_length(struct mac_context *ctx)
|
||||
{ return ctx->type->mac_length; }
|
||||
|
||||
void mac_init(struct mac_context *ctx, uint id, const byte *key, uint keylen);
|
||||
|
||||
static inline void mac_update(struct mac_context *ctx, const byte *data, uint datalen)
|
||||
{ ctx->type->update(ctx, data, datalen); }
|
||||
|
||||
static inline byte *mac_final(struct mac_context *ctx)
|
||||
{ return ctx->type->final(ctx); }
|
||||
|
||||
static inline void mac_cleanup(struct mac_context *ctx)
|
||||
{ memset(ctx, 0, ctx->type->ctx_length); }
|
||||
|
||||
void mac_fill(uint id, const byte *key, uint keylen, const byte *data, uint datalen, byte *mac);
|
||||
int mac_verify(uint id, const byte *key, uint keylen, const byte *data, uint datalen, const byte *mac);
|
||||
|
||||
|
||||
#endif /* _BIRD_MAC_H_ */
|
81
lib/md5.c
81
lib/md5.c
@ -39,8 +39,10 @@ static void md5_transform(u32 buf[4], u32 const in[16]);
|
||||
* initialization constants.
|
||||
*/
|
||||
void
|
||||
md5_init(struct md5_context *ctx)
|
||||
md5_init(struct hash_context *CTX)
|
||||
{
|
||||
struct md5_context *ctx = (void *) CTX;
|
||||
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
@ -55,8 +57,9 @@ md5_init(struct md5_context *ctx)
|
||||
* of bytes.
|
||||
*/
|
||||
void
|
||||
md5_update(struct md5_context *ctx, const byte *buf, uint len)
|
||||
md5_update(struct hash_context *CTX, const byte *buf, uint len)
|
||||
{
|
||||
struct md5_context *ctx = (void *) CTX;
|
||||
u32 t;
|
||||
|
||||
/* Update bitcount */
|
||||
@ -105,8 +108,9 @@ md5_update(struct md5_context *ctx, const byte *buf, uint len)
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
byte *
|
||||
md5_final(struct md5_context *ctx)
|
||||
md5_final(struct hash_context *CTX)
|
||||
{
|
||||
struct md5_context *ctx = (void *) CTX;
|
||||
uint count;
|
||||
byte *p;
|
||||
|
||||
@ -149,13 +153,6 @@ md5_final(struct md5_context *ctx)
|
||||
return (byte*) ctx->buf;
|
||||
}
|
||||
|
||||
/* I am a hard paranoid */
|
||||
void
|
||||
md5_erase_ctx(struct md5_context *ctx)
|
||||
{
|
||||
memset((char *) ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
@ -256,67 +253,3 @@ md5_transform(u32 buf[4], u32 const in[16])
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MD5-HMAC
|
||||
*/
|
||||
|
||||
static void
|
||||
md5_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
|
||||
{
|
||||
struct md5_context hd_tmp;
|
||||
|
||||
md5_init(&hd_tmp);
|
||||
md5_update(&hd_tmp, buffer, length);
|
||||
memcpy(outbuf, md5_final(&hd_tmp), MD5_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
md5_hmac_init(struct md5_hmac_context *ctx, const byte *key, size_t keylen)
|
||||
{
|
||||
byte keybuf[MD5_BLOCK_SIZE], buf[MD5_BLOCK_SIZE];
|
||||
|
||||
/* Hash the key if necessary */
|
||||
if (keylen <= MD5_BLOCK_SIZE)
|
||||
{
|
||||
memcpy(keybuf, key, keylen);
|
||||
bzero(keybuf + keylen, MD5_BLOCK_SIZE - keylen);
|
||||
}
|
||||
else
|
||||
{
|
||||
md5_hash_buffer(keybuf, key, keylen);
|
||||
bzero(keybuf + MD5_SIZE, MD5_BLOCK_SIZE - MD5_SIZE);
|
||||
}
|
||||
|
||||
/* Initialize the inner digest */
|
||||
md5_init(&ctx->ictx);
|
||||
int i;
|
||||
for (i = 0; i < MD5_BLOCK_SIZE; i++)
|
||||
buf[i] = keybuf[i] ^ 0x36;
|
||||
md5_update(&ctx->ictx, buf, MD5_BLOCK_SIZE);
|
||||
|
||||
/* Initialize the outer digest */
|
||||
md5_init(&ctx->octx);
|
||||
for (i = 0; i < MD5_BLOCK_SIZE; i++)
|
||||
buf[i] = keybuf[i] ^ 0x5c;
|
||||
md5_update(&ctx->octx, buf, MD5_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
md5_hmac_update(struct md5_hmac_context *ctx, const byte *buf, size_t buflen)
|
||||
{
|
||||
/* Just update the inner digest */
|
||||
md5_update(&ctx->ictx, buf, buflen);
|
||||
}
|
||||
|
||||
byte *
|
||||
md5_hmac_final(struct md5_hmac_context *ctx)
|
||||
{
|
||||
/* Finish the inner digest */
|
||||
byte *isha = md5_final(&ctx->ictx);
|
||||
|
||||
/* Finish the outer digest */
|
||||
md5_update(&ctx->octx, isha, MD5_SIZE);
|
||||
return md5_final(&ctx->octx);
|
||||
}
|
||||
|
21
lib/md5.h
21
lib/md5.h
@ -19,29 +19,18 @@
|
||||
#define MD5_BLOCK_SIZE 64
|
||||
|
||||
|
||||
struct hash_context;
|
||||
|
||||
struct md5_context {
|
||||
u32 buf[4];
|
||||
u32 bits[2];
|
||||
byte in[64];
|
||||
};
|
||||
|
||||
void md5_init(struct md5_context *ctx);
|
||||
void md5_update(struct md5_context *ctx, const byte *buf, uint len);
|
||||
byte *md5_final(struct md5_context *ctx);
|
||||
|
||||
|
||||
/*
|
||||
* HMAC-MD5
|
||||
*/
|
||||
|
||||
struct md5_hmac_context {
|
||||
struct md5_context ictx;
|
||||
struct md5_context octx;
|
||||
};
|
||||
|
||||
void md5_hmac_init(struct md5_hmac_context *ctx, const byte *key, size_t keylen);
|
||||
void md5_hmac_update(struct md5_hmac_context *ctx, const byte *buf, size_t buflen);
|
||||
byte *md5_hmac_final(struct md5_hmac_context *ctx);
|
||||
void md5_init(struct hash_context *ctx);
|
||||
void md5_update(struct hash_context *ctx, const byte *buf, uint len);
|
||||
byte *md5_final(struct hash_context *ctx);
|
||||
|
||||
|
||||
#endif /* _BIRD_MD5_H_ */
|
||||
|
95
lib/sha1.c
95
lib/sha1.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174) and HMAC-SHA-1
|
||||
* BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174)
|
||||
*
|
||||
* (c) 2015 CZ.NIC z.s.p.o.
|
||||
*
|
||||
@ -17,8 +17,10 @@
|
||||
|
||||
|
||||
void
|
||||
sha1_init(struct sha1_context *ctx)
|
||||
sha1_init(struct hash_context *CTX)
|
||||
{
|
||||
struct sha1_context *ctx = (void *) CTX;
|
||||
|
||||
ctx->h0 = 0x67452301;
|
||||
ctx->h1 = 0xefcdab89;
|
||||
ctx->h2 = 0x98badcfe;
|
||||
@ -167,8 +169,10 @@ sha1_transform(struct sha1_context *ctx, const byte *data)
|
||||
* Update the message digest with the contents of BUF with length LEN.
|
||||
*/
|
||||
void
|
||||
sha1_update(struct sha1_context *ctx, const byte *buf, uint len)
|
||||
sha1_update(struct hash_context *CTX, const byte *buf, uint len)
|
||||
{
|
||||
struct sha1_context *ctx = (void *) CTX;
|
||||
|
||||
if (ctx->count)
|
||||
{
|
||||
/* Fill rest of internal buffer */
|
||||
@ -209,11 +213,12 @@ sha1_update(struct sha1_context *ctx, const byte *buf, uint len)
|
||||
* Returns: 20 bytes representing the digest.
|
||||
*/
|
||||
byte *
|
||||
sha1_final(struct sha1_context *ctx)
|
||||
sha1_final(struct hash_context *CTX)
|
||||
{
|
||||
struct sha1_context *ctx = (void *) CTX;
|
||||
u32 t, msb, lsb;
|
||||
|
||||
sha1_update(ctx, NULL, 0); /* flush */
|
||||
sha1_update(CTX, NULL, 0); /* flush */
|
||||
|
||||
t = ctx->nblocks;
|
||||
/* multiply by 64 to make a byte count */
|
||||
@ -242,7 +247,7 @@ sha1_final(struct sha1_context *ctx)
|
||||
ctx->buf[ctx->count++] = 0x80; /* pad character */
|
||||
while (ctx->count < 64)
|
||||
ctx->buf[ctx->count++] = 0;
|
||||
sha1_update(ctx, NULL, 0); /* flush */
|
||||
sha1_update(CTX, NULL, 0); /* flush */
|
||||
memset(ctx->buf, 0, 56); /* fill next block with zeroes */
|
||||
}
|
||||
|
||||
@ -268,81 +273,3 @@ sha1_final(struct sha1_context *ctx)
|
||||
|
||||
return ctx->buf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SHA1-HMAC
|
||||
*/
|
||||
|
||||
/*
|
||||
* Shortcut function which puts the hash value of the supplied buffer
|
||||
* into outbuf which must have a size of 20 bytes.
|
||||
*/
|
||||
void
|
||||
sha1_hash_buffer(byte *outbuf, const byte *buffer, uint length)
|
||||
{
|
||||
struct sha1_context ctx;
|
||||
|
||||
sha1_init(&ctx);
|
||||
sha1_update(&ctx, buffer, length);
|
||||
memcpy(outbuf, sha1_final(&ctx), SHA1_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
sha1_hmac_init(struct sha1_hmac_context *ctx, const byte *key, uint keylen)
|
||||
{
|
||||
byte keybuf[SHA1_BLOCK_SIZE], buf[SHA1_BLOCK_SIZE];
|
||||
|
||||
/* Hash the key if necessary */
|
||||
if (keylen <= SHA1_BLOCK_SIZE)
|
||||
{
|
||||
memcpy(keybuf, key, keylen);
|
||||
memset(keybuf + keylen, 0, SHA1_BLOCK_SIZE - keylen);
|
||||
}
|
||||
else
|
||||
{
|
||||
sha1_hash_buffer(keybuf, key, keylen);
|
||||
memset(keybuf + SHA1_SIZE, 0, SHA1_BLOCK_SIZE - SHA1_SIZE);
|
||||
}
|
||||
|
||||
/* Initialize the inner digest */
|
||||
sha1_init(&ctx->ictx);
|
||||
int i;
|
||||
for (i = 0; i < SHA1_BLOCK_SIZE; i++)
|
||||
buf[i] = keybuf[i] ^ 0x36;
|
||||
sha1_update(&ctx->ictx, buf, SHA1_BLOCK_SIZE);
|
||||
|
||||
/* Initialize the outer digest */
|
||||
sha1_init(&ctx->octx);
|
||||
for (i = 0; i < SHA1_BLOCK_SIZE; i++)
|
||||
buf[i] = keybuf[i] ^ 0x5c;
|
||||
sha1_update(&ctx->octx, buf, SHA1_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
sha1_hmac_update(struct sha1_hmac_context *ctx, const byte *data, uint datalen)
|
||||
{
|
||||
/* Just update the inner digest */
|
||||
sha1_update(&ctx->ictx, data, datalen);
|
||||
}
|
||||
|
||||
byte *
|
||||
sha1_hmac_final(struct sha1_hmac_context *ctx)
|
||||
{
|
||||
/* Finish the inner digest */
|
||||
byte *isha = sha1_final(&ctx->ictx);
|
||||
|
||||
/* Finish the outer digest */
|
||||
sha1_update(&ctx->octx, isha, SHA1_SIZE);
|
||||
return sha1_final(&ctx->octx);
|
||||
}
|
||||
|
||||
void
|
||||
sha1_hmac(byte *outbuf, const byte *key, uint keylen, const byte *data, uint datalen)
|
||||
{
|
||||
struct sha1_hmac_context ctx;
|
||||
|
||||
sha1_hmac_init(&ctx, key, keylen);
|
||||
sha1_hmac_update(&ctx, data, datalen);
|
||||
memcpy(outbuf, sha1_hmac_final(&ctx), SHA1_SIZE);
|
||||
}
|
||||
|
30
lib/sha1.h
30
lib/sha1.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174) and HMAC-SHA-1
|
||||
* BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174)
|
||||
*
|
||||
* (c) 2015 CZ.NIC z.s.p.o.
|
||||
*
|
||||
@ -27,6 +27,8 @@
|
||||
* Internal SHA1 state.
|
||||
* You should use it just as an opaque handle only.
|
||||
*/
|
||||
struct hash_context;
|
||||
|
||||
struct sha1_context {
|
||||
u32 h0, h1, h2, h3, h4;
|
||||
byte buf[SHA1_BLOCK_SIZE];
|
||||
@ -34,15 +36,14 @@ struct sha1_context {
|
||||
uint count;
|
||||
};
|
||||
|
||||
|
||||
void sha1_init(struct sha1_context *ctx); /* Initialize new algorithm run in the @ctx context. **/
|
||||
void sha1_init(struct hash_context *ctx); /* Initialize new algorithm run in the @ctx context. **/
|
||||
/*
|
||||
* Push another @len bytes of data pointed to by @buf onto the SHA1 hash
|
||||
* currently in @ctx. You can call this any times you want on the same hash (and
|
||||
* you do not need to reinitialize it by @sha1_init()). It has the same effect
|
||||
* as concatenating all the data together and passing them at once.
|
||||
*/
|
||||
void sha1_update(struct sha1_context *ctx, const byte *buf, uint len);
|
||||
void sha1_update(struct hash_context *ctx, const byte *buf, uint len);
|
||||
/*
|
||||
* No more @sha1_update() calls will be done. This terminates the hash and
|
||||
* returns a pointer to it.
|
||||
@ -50,7 +51,7 @@ void sha1_update(struct sha1_context *ctx, const byte *buf, uint len);
|
||||
* Note that the pointer points into data in the @ctx context. If it ceases to
|
||||
* exist, the pointer becomes invalid.
|
||||
*/
|
||||
byte *sha1_final(struct sha1_context *ctx);
|
||||
byte *sha1_final(struct hash_context *ctx);
|
||||
|
||||
/*
|
||||
* A convenience one-shot function for SHA1 hash. It is equivalent to this
|
||||
@ -63,24 +64,5 @@ byte *sha1_final(struct sha1_context *ctx);
|
||||
*/
|
||||
void sha1_hash_buffer(byte *outbuf, const byte *buffer, uint length);
|
||||
|
||||
/*
|
||||
* SHA1 HMAC message authentication. If you provide @key and @data, the result
|
||||
* will be stored in @outbuf.
|
||||
*/
|
||||
void sha1_hmac(byte *outbuf, const byte *key, uint keylen, const byte *data, uint datalen);
|
||||
|
||||
/*
|
||||
* The HMAC also exists in a stream version in a way analogous to the plain
|
||||
* SHA1. Pass this as a context.
|
||||
*/
|
||||
struct sha1_hmac_context {
|
||||
struct sha1_context ictx;
|
||||
struct sha1_context octx;
|
||||
};
|
||||
|
||||
void sha1_hmac_init(struct sha1_hmac_context *ctx, const byte *key, uint keylen); /* Initialize HMAC with context @ctx and the given key. See sha1_init(). */
|
||||
void sha1_hmac_update(struct sha1_hmac_context *ctx, const byte *data, uint datalen); /* Hash another @datalen bytes of data. See sha1_update(). */
|
||||
byte *sha1_hmac_final(struct sha1_hmac_context *ctx); /* Terminate the HMAC and return a pointer to the allocated hash. See sha1_final(). */
|
||||
|
||||
|
||||
#endif /* _BIRD_SHA1_H_ */
|
||||
|
150
lib/sha256.c
150
lib/sha256.c
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* BIRD Library -- SHA-256 and SHA-224 Hash Functions,
|
||||
* HMAC-SHA-256 and HMAC-SHA-224 Functions
|
||||
* BIRD Library -- SHA-256 and SHA-224 Hash Functions
|
||||
*
|
||||
* (c) 2015 CZ.NIC z.s.p.o.
|
||||
*
|
||||
@ -17,8 +16,10 @@
|
||||
// #define SHA256_UNROLLED
|
||||
|
||||
void
|
||||
sha256_init(struct sha256_context *ctx)
|
||||
sha256_init(struct hash_context *CTX)
|
||||
{
|
||||
struct sha256_context *ctx = (void *) CTX;
|
||||
|
||||
ctx->h0 = 0x6a09e667;
|
||||
ctx->h1 = 0xbb67ae85;
|
||||
ctx->h2 = 0x3c6ef372;
|
||||
@ -33,8 +34,10 @@ sha256_init(struct sha256_context *ctx)
|
||||
}
|
||||
|
||||
void
|
||||
sha224_init(struct sha224_context *ctx)
|
||||
sha224_init(struct hash_context *CTX)
|
||||
{
|
||||
struct sha224_context *ctx = (void *) CTX;
|
||||
|
||||
ctx->h0 = 0xc1059ed8;
|
||||
ctx->h1 = 0x367cd507;
|
||||
ctx->h2 = 0x3070dd17;
|
||||
@ -219,8 +222,10 @@ sha256_transform(struct sha256_context *ctx, const byte *data)
|
||||
not have any meaning but writing after finalize is sometimes
|
||||
helpful to mitigate timing attacks. */
|
||||
void
|
||||
sha256_update(struct sha256_context *ctx, const byte *buf, size_t len)
|
||||
sha256_update(struct hash_context *CTX, const byte *buf, uint len)
|
||||
{
|
||||
struct sha256_context *ctx = (void *) CTX;
|
||||
|
||||
if (ctx->count)
|
||||
{
|
||||
/* Fill rest of internal buffer */
|
||||
@ -261,11 +266,12 @@ sha256_update(struct sha256_context *ctx, const byte *buf, size_t len)
|
||||
* Returns: 32 bytes with the message the digest. 28 bytes for SHA-224.
|
||||
*/
|
||||
byte *
|
||||
sha256_final(struct sha256_context *ctx)
|
||||
sha256_final(struct hash_context *CTX)
|
||||
{
|
||||
struct sha256_context *ctx = (void *) CTX;
|
||||
u32 t, th, msb, lsb;
|
||||
|
||||
sha256_update(ctx, NULL, 0); /* flush */
|
||||
sha256_update(CTX, NULL, 0); /* flush */
|
||||
|
||||
t = ctx->nblocks;
|
||||
th = 0;
|
||||
@ -296,7 +302,7 @@ sha256_final(struct sha256_context *ctx)
|
||||
ctx->buf[ctx->count++] = 0x80; /* pad character */
|
||||
while (ctx->count < 64)
|
||||
ctx->buf[ctx->count++] = 0;
|
||||
sha256_update(ctx, NULL, 0); /* flush */;
|
||||
sha256_update(CTX, NULL, 0); /* flush */;
|
||||
memset(ctx->buf, 0, 56 ); /* fill next block with zeroes */
|
||||
}
|
||||
|
||||
@ -319,131 +325,3 @@ sha256_final(struct sha256_context *ctx)
|
||||
|
||||
return ctx->buf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SHA256-HMAC
|
||||
*/
|
||||
|
||||
static void
|
||||
sha256_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
|
||||
{
|
||||
struct sha256_context ctx;
|
||||
|
||||
sha256_init(&ctx);
|
||||
sha256_update(&ctx, buffer, length);
|
||||
memcpy(outbuf, sha256_final(&ctx), SHA256_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
sha256_hmac_init(struct sha256_hmac_context *ctx, const byte *key, size_t keylen)
|
||||
{
|
||||
byte keybuf[SHA256_BLOCK_SIZE], buf[SHA256_BLOCK_SIZE];
|
||||
|
||||
/* Hash the key if necessary */
|
||||
if (keylen <= SHA256_BLOCK_SIZE)
|
||||
{
|
||||
memcpy(keybuf, key, keylen);
|
||||
memset(keybuf + keylen, 0, SHA256_BLOCK_SIZE - keylen);
|
||||
}
|
||||
else
|
||||
{
|
||||
sha256_hash_buffer(keybuf, key, keylen);
|
||||
memset(keybuf + SHA256_SIZE, 0, SHA256_BLOCK_SIZE - SHA256_SIZE);
|
||||
}
|
||||
|
||||
/* Initialize the inner digest */
|
||||
sha256_init(&ctx->ictx);
|
||||
int i;
|
||||
for (i = 0; i < SHA256_BLOCK_SIZE; i++)
|
||||
buf[i] = keybuf[i] ^ 0x36;
|
||||
sha256_update(&ctx->ictx, buf, SHA256_BLOCK_SIZE);
|
||||
|
||||
/* Initialize the outer digest */
|
||||
sha256_init(&ctx->octx);
|
||||
for (i = 0; i < SHA256_BLOCK_SIZE; i++)
|
||||
buf[i] = keybuf[i] ^ 0x5c;
|
||||
sha256_update(&ctx->octx, buf, SHA256_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
sha256_hmac_update(struct sha256_hmac_context *ctx, const byte *buf, size_t buflen)
|
||||
{
|
||||
/* Just update the inner digest */
|
||||
sha256_update(&ctx->ictx, buf, buflen);
|
||||
}
|
||||
|
||||
byte *
|
||||
sha256_hmac_final(struct sha256_hmac_context *ctx)
|
||||
{
|
||||
/* Finish the inner digest */
|
||||
byte *isha = sha256_final(&ctx->ictx);
|
||||
|
||||
/* Finish the outer digest */
|
||||
sha256_update(&ctx->octx, isha, SHA256_SIZE);
|
||||
return sha256_final(&ctx->octx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SHA224-HMAC
|
||||
*/
|
||||
|
||||
static void
|
||||
sha224_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
|
||||
{
|
||||
struct sha224_context ctx;
|
||||
|
||||
sha224_init(&ctx);
|
||||
sha224_update(&ctx, buffer, length);
|
||||
memcpy(outbuf, sha224_final(&ctx), SHA224_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
sha224_hmac_init(struct sha224_hmac_context *ctx, const byte *key, size_t keylen)
|
||||
{
|
||||
byte keybuf[SHA224_BLOCK_SIZE], buf[SHA224_BLOCK_SIZE];
|
||||
|
||||
/* Hash the key if necessary */
|
||||
if (keylen <= SHA224_BLOCK_SIZE)
|
||||
{
|
||||
memcpy(keybuf, key, keylen);
|
||||
memset(keybuf + keylen, 0, SHA224_BLOCK_SIZE - keylen);
|
||||
}
|
||||
else
|
||||
{
|
||||
sha224_hash_buffer(keybuf, key, keylen);
|
||||
memset(keybuf + SHA224_SIZE, 0, SHA224_BLOCK_SIZE - SHA224_SIZE);
|
||||
}
|
||||
|
||||
/* Initialize the inner digest */
|
||||
sha224_init(&ctx->ictx);
|
||||
int i;
|
||||
for (i = 0; i < SHA224_BLOCK_SIZE; i++)
|
||||
buf[i] = keybuf[i] ^ 0x36;
|
||||
sha224_update(&ctx->ictx, buf, SHA224_BLOCK_SIZE);
|
||||
|
||||
/* Initialize the outer digest */
|
||||
sha224_init(&ctx->octx);
|
||||
for (i = 0; i < SHA224_BLOCK_SIZE; i++)
|
||||
buf[i] = keybuf[i] ^ 0x5c;
|
||||
sha224_update(&ctx->octx, buf, SHA224_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
sha224_hmac_update(struct sha224_hmac_context *ctx, const byte *buf, size_t buflen)
|
||||
{
|
||||
/* Just update the inner digest */
|
||||
sha256_update(&ctx->ictx, buf, buflen);
|
||||
}
|
||||
|
||||
byte *
|
||||
sha224_hmac_final(struct sha224_hmac_context *ctx)
|
||||
{
|
||||
/* Finish the inner digest */
|
||||
byte *isha = sha224_final(&ctx->ictx);
|
||||
|
||||
/* Finish the outer digest */
|
||||
sha224_update(&ctx->octx, isha, SHA224_SIZE);
|
||||
return sha224_final(&ctx->octx);
|
||||
}
|
||||
|
42
lib/sha256.h
42
lib/sha256.h
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* BIRD Library -- SHA-256 and SHA-224 Hash Functions,
|
||||
* HMAC-SHA-256 and HMAC-SHA-224 Functions
|
||||
* BIRD Library -- SHA-256 and SHA-224 Hash Functions
|
||||
*
|
||||
* (c) 2015 CZ.NIC z.s.p.o.
|
||||
*
|
||||
@ -25,6 +24,8 @@
|
||||
#define SHA256_BLOCK_SIZE 64
|
||||
|
||||
|
||||
struct hash_context;
|
||||
|
||||
struct sha256_context {
|
||||
u32 h0, h1, h2, h3, h4, h5, h6, h7;
|
||||
byte buf[SHA256_BLOCK_SIZE];
|
||||
@ -35,39 +36,14 @@ struct sha256_context {
|
||||
#define sha224_context sha256_context
|
||||
|
||||
|
||||
void sha256_init(struct sha256_context *ctx);
|
||||
void sha224_init(struct sha224_context *ctx);
|
||||
void sha256_init(struct hash_context *ctx);
|
||||
void sha224_init(struct hash_context *ctx);
|
||||
|
||||
void sha256_update(struct sha256_context *ctx, const byte *buf, size_t len);
|
||||
static inline void sha224_update(struct sha224_context *ctx, const byte *buf, size_t len)
|
||||
{ sha256_update(ctx, buf, len); }
|
||||
void sha256_update(struct hash_context *ctx, const byte *buf, uint len);
|
||||
#define sha224_update sha256_update
|
||||
|
||||
byte *sha256_final(struct sha256_context *ctx);
|
||||
static inline byte *sha224_final(struct sha224_context *ctx)
|
||||
{ return sha256_final(ctx); }
|
||||
|
||||
|
||||
/*
|
||||
* HMAC-SHA256, HMAC-SHA224
|
||||
*/
|
||||
|
||||
struct sha256_hmac_context
|
||||
{
|
||||
struct sha256_context ictx;
|
||||
struct sha256_context octx;
|
||||
};
|
||||
|
||||
#define sha224_hmac_context sha256_hmac_context
|
||||
|
||||
|
||||
void sha256_hmac_init(struct sha256_hmac_context *ctx, const byte *key, size_t keylen);
|
||||
void sha224_hmac_init(struct sha224_hmac_context *ctx, const byte *key, size_t keylen);
|
||||
|
||||
void sha256_hmac_update(struct sha256_hmac_context *ctx, const byte *buf, size_t buflen);
|
||||
void sha224_hmac_update(struct sha224_hmac_context *ctx, const byte *buf, size_t buflen);
|
||||
|
||||
byte *sha256_hmac_final(struct sha256_hmac_context *ctx);
|
||||
byte *sha224_hmac_final(struct sha224_hmac_context *ctx);
|
||||
byte *sha256_final(struct hash_context *ctx);
|
||||
#define sha224_final sha256_final
|
||||
|
||||
|
||||
#endif /* _BIRD_SHA256_H_ */
|
||||
|
150
lib/sha512.c
150
lib/sha512.c
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* BIRD Library -- SHA-512 and SHA-384 Hash Functions,
|
||||
* HMAC-SHA-512 and HMAC-SHA-384 Functions
|
||||
* BIRD Library -- SHA-512 and SHA-384 Hash Functions
|
||||
*
|
||||
* (c) 2015 CZ.NIC z.s.p.o.
|
||||
*
|
||||
@ -17,8 +16,10 @@
|
||||
// #define SHA512_UNROLLED
|
||||
|
||||
void
|
||||
sha512_init(struct sha512_context *ctx)
|
||||
sha512_init(struct hash_context *CTX)
|
||||
{
|
||||
struct sha512_context *ctx = (void *) CTX;
|
||||
|
||||
ctx->h0 = U64(0x6a09e667f3bcc908);
|
||||
ctx->h1 = U64(0xbb67ae8584caa73b);
|
||||
ctx->h2 = U64(0x3c6ef372fe94f82b);
|
||||
@ -33,8 +34,10 @@ sha512_init(struct sha512_context *ctx)
|
||||
}
|
||||
|
||||
void
|
||||
sha384_init(struct sha384_context *ctx)
|
||||
sha384_init(struct hash_context *CTX)
|
||||
{
|
||||
struct sha384_context *ctx = (void *) CTX;
|
||||
|
||||
ctx->h0 = U64(0xcbbb9d5dc1059ed8);
|
||||
ctx->h1 = U64(0x629a292a367cd507);
|
||||
ctx->h2 = U64(0x9159015a3070dd17);
|
||||
@ -389,8 +392,10 @@ sha512_transform(struct sha512_context *ctx, const byte *data)
|
||||
}
|
||||
|
||||
void
|
||||
sha512_update(struct sha512_context *ctx, const byte *buf, size_t len)
|
||||
sha512_update(struct hash_context *CTX, const byte *buf, uint len)
|
||||
{
|
||||
struct sha512_context *ctx = (void *) CTX;
|
||||
|
||||
if (ctx->count)
|
||||
{
|
||||
/* Fill rest of internal buffer */
|
||||
@ -432,11 +437,12 @@ sha512_update(struct sha512_context *ctx, const byte *buf, size_t len)
|
||||
* first 48 of those bytes.
|
||||
*/
|
||||
byte *
|
||||
sha512_final(struct sha512_context *ctx)
|
||||
sha512_final(struct hash_context *CTX)
|
||||
{
|
||||
struct sha512_context *ctx = (void *) CTX;
|
||||
u64 t, th, msb, lsb;
|
||||
|
||||
sha512_update(ctx, NULL, 0); /* flush */
|
||||
sha512_update(CTX, NULL, 0); /* flush */
|
||||
|
||||
t = ctx->nblocks;
|
||||
th = 0;
|
||||
@ -467,7 +473,7 @@ sha512_final(struct sha512_context *ctx)
|
||||
ctx->buf[ctx->count++] = 0x80; /* pad character */
|
||||
while(ctx->count < 128)
|
||||
ctx->buf[ctx->count++] = 0;
|
||||
sha512_update(ctx, NULL, 0); /* flush */
|
||||
sha512_update(CTX, NULL, 0); /* flush */
|
||||
memset(ctx->buf, 0, 112); /* fill next block with zeroes */
|
||||
}
|
||||
|
||||
@ -490,131 +496,3 @@ sha512_final(struct sha512_context *ctx)
|
||||
|
||||
return ctx->buf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SHA512-HMAC
|
||||
*/
|
||||
|
||||
static void
|
||||
sha512_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
|
||||
{
|
||||
struct sha512_context ctx;
|
||||
|
||||
sha512_init(&ctx);
|
||||
sha512_update(&ctx, buffer, length);
|
||||
memcpy(outbuf, sha512_final(&ctx), SHA512_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
sha512_hmac_init(struct sha512_hmac_context *ctx, const byte *key, size_t keylen)
|
||||
{
|
||||
byte keybuf[SHA512_BLOCK_SIZE], buf[SHA512_BLOCK_SIZE];
|
||||
|
||||
/* Hash the key if necessary */
|
||||
if (keylen <= SHA512_BLOCK_SIZE)
|
||||
{
|
||||
memcpy(keybuf, key, keylen);
|
||||
memset(keybuf + keylen, 0, SHA512_BLOCK_SIZE - keylen);
|
||||
}
|
||||
else
|
||||
{
|
||||
sha512_hash_buffer(keybuf, key, keylen);
|
||||
memset(keybuf + SHA512_SIZE, 0, SHA512_BLOCK_SIZE - SHA512_SIZE);
|
||||
}
|
||||
|
||||
/* Initialize the inner digest */
|
||||
sha512_init(&ctx->ictx);
|
||||
int i;
|
||||
for (i = 0; i < SHA512_BLOCK_SIZE; i++)
|
||||
buf[i] = keybuf[i] ^ 0x36;
|
||||
sha512_update(&ctx->ictx, buf, SHA512_BLOCK_SIZE);
|
||||
|
||||
/* Initialize the outer digest */
|
||||
sha512_init(&ctx->octx);
|
||||
for (i = 0; i < SHA512_BLOCK_SIZE; i++)
|
||||
buf[i] = keybuf[i] ^ 0x5c;
|
||||
sha512_update(&ctx->octx, buf, SHA512_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
sha512_hmac_update(struct sha512_hmac_context *ctx, const byte *buf, size_t buflen)
|
||||
{
|
||||
/* Just update the inner digest */
|
||||
sha512_update(&ctx->ictx, buf, buflen);
|
||||
}
|
||||
|
||||
byte *
|
||||
sha512_hmac_final(struct sha512_hmac_context *ctx)
|
||||
{
|
||||
/* Finish the inner digest */
|
||||
byte *isha = sha512_final(&ctx->ictx);
|
||||
|
||||
/* Finish the outer digest */
|
||||
sha512_update(&ctx->octx, isha, SHA512_SIZE);
|
||||
return sha512_final(&ctx->octx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SHA384-HMAC
|
||||
*/
|
||||
|
||||
static void
|
||||
sha384_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
|
||||
{
|
||||
struct sha384_context ctx;
|
||||
|
||||
sha384_init(&ctx);
|
||||
sha384_update(&ctx, buffer, length);
|
||||
memcpy(outbuf, sha384_final(&ctx), SHA384_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
sha384_hmac_init(struct sha384_hmac_context *ctx, const byte *key, size_t keylen)
|
||||
{
|
||||
byte keybuf[SHA384_BLOCK_SIZE], buf[SHA384_BLOCK_SIZE];
|
||||
|
||||
/* Hash the key if necessary */
|
||||
if (keylen <= SHA384_BLOCK_SIZE)
|
||||
{
|
||||
memcpy(keybuf, key, keylen);
|
||||
memset(keybuf + keylen, 0, SHA384_BLOCK_SIZE - keylen);
|
||||
}
|
||||
else
|
||||
{
|
||||
sha384_hash_buffer(keybuf, key, keylen);
|
||||
memset(keybuf + SHA384_SIZE, 0, SHA384_BLOCK_SIZE - SHA384_SIZE);
|
||||
}
|
||||
|
||||
/* Initialize the inner digest */
|
||||
sha384_init(&ctx->ictx);
|
||||
int i;
|
||||
for (i = 0; i < SHA384_BLOCK_SIZE; i++)
|
||||
buf[i] = keybuf[i] ^ 0x36;
|
||||
sha384_update(&ctx->ictx, buf, SHA384_BLOCK_SIZE);
|
||||
|
||||
/* Initialize the outer digest */
|
||||
sha384_init(&ctx->octx);
|
||||
for (i = 0; i < SHA384_BLOCK_SIZE; i++)
|
||||
buf[i] = keybuf[i] ^ 0x5c;
|
||||
sha384_update(&ctx->octx, buf, SHA384_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
sha384_hmac_update(struct sha384_hmac_context *ctx, const byte *buf, size_t buflen)
|
||||
{
|
||||
/* Just update the inner digest */
|
||||
sha384_update(&ctx->ictx, buf, buflen);
|
||||
}
|
||||
|
||||
byte *
|
||||
sha384_hmac_final(struct sha384_hmac_context *ctx)
|
||||
{
|
||||
/* Finish the inner digest */
|
||||
byte *isha = sha384_final(&ctx->ictx);
|
||||
|
||||
/* Finish the outer digest */
|
||||
sha384_update(&ctx->octx, isha, SHA384_SIZE);
|
||||
return sha384_final(&ctx->octx);
|
||||
}
|
||||
|
44
lib/sha512.h
44
lib/sha512.h
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* BIRD Library -- SHA-512 and SHA-384 Hash Functions,
|
||||
* HMAC-SHA-512 and HMAC-SHA-384 Functions
|
||||
* BIRD Library -- SHA-512 and SHA-384 Hash Functions
|
||||
*
|
||||
* (c) 2015 CZ.NIC z.s.p.o.
|
||||
*
|
||||
@ -25,8 +24,10 @@
|
||||
#define SHA512_BLOCK_SIZE 128
|
||||
|
||||
|
||||
struct hash_context;
|
||||
|
||||
struct sha512_context {
|
||||
u64 h0, h1, h2, h3, h4, h5, h6, h7;
|
||||
u64 h0, h1, h2, h3, h4, h5, h6, h7;
|
||||
byte buf[SHA512_BLOCK_SIZE];
|
||||
uint nblocks;
|
||||
uint count;
|
||||
@ -35,39 +36,14 @@ struct sha512_context {
|
||||
#define sha384_context sha512_context
|
||||
|
||||
|
||||
void sha512_init(struct sha512_context *ctx);
|
||||
void sha384_init(struct sha384_context *ctx);
|
||||
void sha512_init(struct hash_context *ctx);
|
||||
void sha384_init(struct hash_context *ctx);
|
||||
|
||||
void sha512_update(struct sha512_context *ctx, const byte *buf, size_t len);
|
||||
static inline void sha384_update(struct sha384_context *ctx, const byte *buf, size_t len)
|
||||
{ sha512_update(ctx, buf, len); }
|
||||
void sha512_update(struct hash_context *ctx, const byte *buf, uint len);
|
||||
#define sha384_update sha512_update
|
||||
|
||||
byte *sha512_final(struct sha512_context *ctx);
|
||||
static inline byte *sha384_final(struct sha384_context *ctx)
|
||||
{ return sha512_final(ctx); }
|
||||
|
||||
|
||||
/*
|
||||
* HMAC-SHA512, HMAC-SHA384
|
||||
*/
|
||||
|
||||
struct sha512_hmac_context
|
||||
{
|
||||
struct sha512_context ictx;
|
||||
struct sha512_context octx;
|
||||
};
|
||||
|
||||
#define sha384_hmac_context sha512_hmac_context
|
||||
|
||||
|
||||
void sha512_hmac_init(struct sha512_hmac_context *ctx, const byte *key, size_t keylen);
|
||||
void sha384_hmac_init(struct sha384_hmac_context *ctx, const byte *key, size_t keylen);
|
||||
|
||||
void sha512_hmac_update(struct sha512_hmac_context *ctx, const byte *buf, size_t buflen);
|
||||
void sha384_hmac_update(struct sha384_hmac_context *ctx, const byte *buf, size_t buflen);
|
||||
|
||||
byte *sha512_hmac_final(struct sha512_hmac_context *ctx);
|
||||
byte *sha384_hmac_final(struct sha384_hmac_context *ctx);
|
||||
byte *sha512_final(struct hash_context *ctx);
|
||||
#define sha384_final sha512_final
|
||||
|
||||
|
||||
#endif /* _BIRD_SHA512_H_ */
|
||||
|
@ -37,7 +37,7 @@ password_find(list *l, int first_fit)
|
||||
}
|
||||
|
||||
struct password_item *
|
||||
password_find_by_id(list *l, int id)
|
||||
password_find_by_id(list *l, uint id)
|
||||
{
|
||||
struct password_item *pi;
|
||||
|
||||
|
@ -21,7 +21,7 @@ struct password_item {
|
||||
extern struct password_item *last_password_item;
|
||||
|
||||
struct password_item *password_find(list *l, int first_fit);
|
||||
struct password_item *password_find_by_id(list *l, int id);
|
||||
struct password_item *password_find_by_id(list *l, uint id);
|
||||
struct password_item *password_find_by_value(list *l, char *pass, uint size);
|
||||
|
||||
static inline int password_verify(struct password_item *p1, char *p2, uint size)
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "ospf.h"
|
||||
#include "nest/password.h"
|
||||
#include "lib/md5.h"
|
||||
#include "lib/mac.h"
|
||||
#include "lib/socket.h"
|
||||
|
||||
void
|
||||
@ -109,7 +110,7 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
|
||||
char password[OSPF_AUTH_CRYPT_SIZE];
|
||||
strncpy(password, passwd->password, sizeof(password));
|
||||
|
||||
struct md5_context ctx;
|
||||
struct hash_context ctx;
|
||||
md5_init(&ctx);
|
||||
md5_update(&ctx, (char *) pkt, plen);
|
||||
md5_update(&ctx, password, OSPF_AUTH_CRYPT_SIZE);
|
||||
@ -180,7 +181,7 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
|
||||
memcpy(received, tail, OSPF_AUTH_CRYPT_SIZE);
|
||||
strncpy(tail, pass->password, OSPF_AUTH_CRYPT_SIZE);
|
||||
|
||||
struct md5_context ctx;
|
||||
struct hash_context ctx;
|
||||
md5_init(&ctx);
|
||||
md5_update(&ctx, (byte *) pkt, plen + OSPF_AUTH_CRYPT_SIZE);
|
||||
char *computed = md5_final(&ctx);
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "rip.h"
|
||||
#include "lib/md5.h"
|
||||
#include "lib/mac.h"
|
||||
|
||||
|
||||
#define RIP_CMD_REQUEST 1 /* want info */
|
||||
@ -241,7 +242,7 @@ rip_fill_authentication(struct rip_proto *p, struct rip_iface *ifa, struct rip_p
|
||||
|
||||
*plen += sizeof(struct rip_auth_tail) + RIP_MD5_LENGTH;
|
||||
|
||||
struct md5_context ctx;
|
||||
struct hash_context ctx;
|
||||
md5_init(&ctx);
|
||||
md5_update(&ctx, (byte *) pkt, *plen);
|
||||
memcpy(tail->auth_data, md5_final(&ctx), RIP_MD5_LENGTH);
|
||||
@ -315,7 +316,7 @@ rip_check_authentication(struct rip_proto *p, struct rip_iface *ifa, struct rip_
|
||||
memcpy(received, tail->auth_data, RIP_MD5_LENGTH);
|
||||
strncpy(tail->auth_data, pass->password, RIP_MD5_LENGTH);
|
||||
|
||||
struct md5_context ctx;
|
||||
struct hash_context ctx;
|
||||
md5_init(&ctx);
|
||||
md5_update(&ctx, (byte *) pkt, *plen);
|
||||
char *computed = md5_final(&ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user