Module Name: src Committed By: christos Date: Fri Jul 1 22:41:40 UTC 2016
Modified Files: src/lib/libc: shlib_version src/lib/libc/hash: Makefile.inc Added Files: src/lib/libc/hash: hmac.3 hmac.c Log Message: new hmac function. To generate a diff of this commit: cvs rdiff -u -r1.264 -r1.265 src/lib/libc/shlib_version cvs rdiff -u -r1.12 -r1.13 src/lib/libc/hash/Makefile.inc cvs rdiff -u -r0 -r1.1 src/lib/libc/hash/hmac.3 cvs rdiff -u -r0 -r1.3 src/lib/libc/hash/hmac.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/shlib_version diff -u src/lib/libc/shlib_version:1.264 src/lib/libc/shlib_version:1.265 --- src/lib/libc/shlib_version:1.264 Sat Apr 23 19:11:31 2016 +++ src/lib/libc/shlib_version Fri Jul 1 18:41:39 2016 @@ -1,4 +1,4 @@ -# $NetBSD: shlib_version,v 1.264 2016/04/23 23:11:31 christos Exp $ +# $NetBSD: shlib_version,v 1.265 2016/07/01 22:41:39 christos Exp $ # Remember to update distrib/sets/lists/base/shl.* when changing # # things we wish to do on next major version bump: @@ -44,4 +44,4 @@ # - decide whether soft-float should support fenv.h, including thread-local contett # - stop all math functions from setting errno major=12 -minor=202 +minor=203 Index: src/lib/libc/hash/Makefile.inc diff -u src/lib/libc/hash/Makefile.inc:1.12 src/lib/libc/hash/Makefile.inc:1.13 --- src/lib/libc/hash/Makefile.inc:1.12 Sat Jul 7 21:21:12 2012 +++ src/lib/libc/hash/Makefile.inc Fri Jul 1 18:41:39 2016 @@ -1,9 +1,12 @@ -# $NetBSD: Makefile.inc,v 1.12 2012/07/08 01:21:12 rmind Exp $ +# $NetBSD: Makefile.inc,v 1.13 2016/07/01 22:41:39 christos Exp $ # $OpenBSD: Makefile.inc,v 1.5 1997/07/17 06:02:42 millert Exp $ # hash functions .PATH: ${ARCHDIR}/hash ${.CURDIR}/hash +SRCS+= hmac.c +MAN+= hmac.3 + .include "${.CURDIR}/hash/md2/Makefile.inc" .include "${.CURDIR}/hash/rmd160/Makefile.inc" .include "${.CURDIR}/hash/sha1/Makefile.inc" Added files: Index: src/lib/libc/hash/hmac.3 diff -u /dev/null src/lib/libc/hash/hmac.3:1.1 --- /dev/null Fri Jul 1 18:41:40 2016 +++ src/lib/libc/hash/hmac.3 Fri Jul 1 18:41:39 2016 @@ -0,0 +1,58 @@ +.\" $NetBSD: hmac.3,v 1.1 2016/07/01 22:41:39 christos Exp $ +.\" +.Dd July 1, 2016 +.Dt HMAC 3 +.Os +.Sh NAME +.Nm hmac , +.Nd Compute a key-Hash Message Authentication Code +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In stdlib.h +.Ft ssize_t +.Fn hmac "const char *hname" "const void *key" "size_t klen" "const void *text" "size_t tlen" "void *digest" "size_t dlen" +.Sh DESCRIPTION +The +.Fn hmac +function computes the key-Hash Message Authentication Code per +.%R RFC 2104 +and places the result in +.Fa digest +writing up to +.Fa dlen +bytes. +The actual number of bytes that would be written is returned. +.Pp +The hash functions supported are: md2, md4, md5, rmd160, sha1, sha224, +sha256, sha384, sha512. +.Sh RETURN VALUES +The +.Fn hmac +return +.Dv -1 +if the +.Fa hname +is not found +and the length of the digest string which is dependend on the hashing +function. +.Sh SEE ALSO +.Xr md2 3 , +.Xr md4 3 , +.Xr md5 3 , +.Xr rmd160 3 , +.Xr sha1 3 , +.Xr sha2 3 +.Sh STANDARDS +.%R RFC 2104 +.Sh NOTES +The maximum digest length has been extended from +.Dv 64 +to +.Dv 128 +bytes to handle SHA2. +.Sh HISTORY +The +.Fn hmac +function appeared in +.Nx 8 Index: src/lib/libc/hash/hmac.c diff -u /dev/null src/lib/libc/hash/hmac.c:1.3 --- /dev/null Fri Jul 1 18:41:40 2016 +++ src/lib/libc/hash/hmac.c Fri Jul 1 18:41:39 2016 @@ -0,0 +1,164 @@ +/* $NetBSD: hmac.c,v 1.3 2016/07/01 22:41:39 christos Exp $ */ + +/*- + * Copyright (c) 2016 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__RCSID("$NetBSD: hmac.c,v 1.3 2016/07/01 22:41:39 christos Exp $"); + +#include <string.h> +#include <stdlib.h> + +#include <md2.h> +#include <md4.h> +#include <md5.h> +#include <rmd160.h> +#include <sha1.h> +#include <sha2.h> + +#define HMAC_SIZE 128 +#define HMAC_IPAD 0x36 +#define HMAC_OPAD 0x5C + +static const struct hmac { + const char *name; + size_t ctxsize; + size_t digsize; + size_t blocksize; + void (*init)(void *); + void (*update)(void *, const uint8_t *, unsigned int); + void (*final)(uint8_t *, void *); +} hmacs[] = { + { + "md2", sizeof(MD2_CTX), MD2_DIGEST_LENGTH, MD2_BLOCK_LENGTH, + (void *)MD2Init, (void *)MD2Update, (void *)MD2Final, + }, + { + "md4", sizeof(MD4_CTX), MD4_DIGEST_LENGTH, MD4_BLOCK_LENGTH, + (void *)MD4Init, (void *)MD4Update, (void *)MD4Final, + }, + { + "md5", sizeof(MD5_CTX), MD5_DIGEST_LENGTH, MD5_BLOCK_LENGTH, + (void *)MD5Init, (void *)MD5Update, (void *)MD5Final, + }, + { + "rmd160", sizeof(RMD160_CTX), RMD160_DIGEST_LENGTH, + RMD160_BLOCK_LENGTH, + (void *)RMD160Init, (void *)RMD160Update, (void *)RMD160Final, + }, + { + "sha1", sizeof(SHA1_CTX), SHA1_DIGEST_LENGTH, SHA1_BLOCK_LENGTH, + (void *)SHA1Init, (void *)SHA1Update, (void *)SHA1Final, + }, + { + "sha224", sizeof(SHA224_CTX), SHA224_DIGEST_LENGTH, + SHA224_BLOCK_LENGTH, + (void *)SHA224_Init, (void *)SHA224_Update, + (void *)SHA224_Final, + }, + { + "sha256", sizeof(SHA256_CTX), SHA256_DIGEST_LENGTH, + SHA256_BLOCK_LENGTH, + (void *)SHA256_Init, (void *)SHA256_Update, + (void *)SHA256_Final, + }, + { + "sha384", sizeof(SHA384_CTX), SHA384_DIGEST_LENGTH, + SHA384_BLOCK_LENGTH, + (void *)SHA384_Init, (void *)SHA384_Update, + (void *)SHA384_Final, + }, + { + "sha512", sizeof(SHA512_CTX), SHA512_DIGEST_LENGTH, + SHA512_BLOCK_LENGTH, + (void *)SHA512_Init, (void *)SHA512_Update, + (void *)SHA512_Final, + }, +}; + +static const struct hmac * +hmac_find(const char *name) +{ + for (size_t i = 0; i < __arraycount(hmacs); i++) { + if (strcmp(hmacs[i].name, name) != 0) + continue; + return &hmacs[i]; + } + return NULL; +} + +ssize_t +hmac(const char *name, + const void *key, size_t klen, + const void *text, size_t tlen, + void *digest, size_t dlen) +{ + uint8_t ipad[HMAC_SIZE], opad[HMAC_SIZE], d[HMAC_SIZE]; + const uint8_t *k = key; + const struct hmac *h; + uint64_t c[32]; + void *p; + + if ((h = hmac_find(name)) == NULL) + return -1; + + + if (klen > h->blocksize) { + (*h->init)(c); + (*h->update)(c, k, (unsigned int)klen); + (*h->final)(d, c); + k = (void *)d; + klen = h->digsize; + } + + /* Form input and output pads for the digests */ + for (size_t i = 0; i < sizeof(ipad); i++) { + ipad[i] = (i < klen ? k[i] : 0) ^ HMAC_IPAD; + opad[i] = (i < klen ? k[i] : 0) ^ HMAC_OPAD; + } + + p = dlen >= h->digsize ? digest : d; + if (p != digest) { + memcpy(p, digest, dlen); + memset((char *)p + dlen, 0, h->digsize - dlen); + } + (*h->init)(c); + (*h->update)(c, ipad, h->blocksize); + (*h->update)(c, text, (unsigned int)tlen); + (*h->final)(p, c); + + (*h->init)(c); + (*h->update)(c, opad, h->blocksize); + (*h->update)(c, digest, (unsigned int)h->digsize); + (*h->final)(p, c); + + if (p != digest) + memcpy(digest, p, dlen); + + return h->digsize; +}