diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/auth/hmac_sha256.c | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/auth/hmac_sha256.c')
-rw-r--r-- | Src/auth/hmac_sha256.c | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/Src/auth/hmac_sha256.c b/Src/auth/hmac_sha256.c new file mode 100644 index 00000000..7cfba799 --- /dev/null +++ b/Src/auth/hmac_sha256.c @@ -0,0 +1,195 @@ +/* + * hmac_sha1.c + * + * Version 1.0.0 + * + * Written by Aaron D. Gifford <me@aarongifford.com> + * + * Copyright 1998, 2000 Aaron D. Gifford. All rights reserved. + * + * 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. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) 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 AUTHOR(S) 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. + */ + +/* + * The HMAC-SHA256 has is defined as: + * + * HMAC = SHA256(K XOR opad, SHA256(K XOR ipad, message)) + * + * "opad" is 64 bytes filled with 0x5c + * "ipad" is 64 bytes filled with 0x36 + * "K" is the key material + * + * If the key material "K" is longer than 64 bytes, then the key material + * will first be digested (K = SHA1(K)) resulting in a 20-byte hash. + * If the key material is shorter than 64 bytes, it is padded with zero + * bytes. + * + * This code precomputes "K XOR ipad" and "K XOR opad" since that just makes + * sense. + * + * This code was heavily influenced by Eric A. Young's in how the interface + * was designed and how this file is formatted. + */ + +#ifndef __HMAC_SHA256_H__ +#define __HMAC_SHA256_H__ + +#include "hmac_sha256.h" +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Filler bytes: */ +#define IPAD_BYTE 0x36 +#define OPAD_BYTE 0x5c +#define ZERO_BYTE 0x00 + +void HMAC_SHA256_Init(HMAC_SHA256_CTX *ctx) { + memset(&(ctx->key[0]), ZERO_BYTE, HMAC_SHA256_BLOCK_LENGTH); + memset(&(ctx->ipad[0]), IPAD_BYTE, HMAC_SHA256_BLOCK_LENGTH); + memset(&(ctx->opad[0]), OPAD_BYTE, HMAC_SHA256_BLOCK_LENGTH); + ctx->keylen = 0; + ctx->hashkey = 0; +} + +void HMAC_SHA256_UpdateKey(HMAC_SHA256_CTX *ctx, unsigned char *key, unsigned int keylen) { + + /* Do we have anything to work with? If not, return right away. */ + if (keylen < 1) + return; + + /* + * Is the total key length (current data and any previous data) + * longer than the hash block length? + */ + if (ctx->hashkey !=0 || (keylen + ctx->keylen) > HMAC_SHA256_BLOCK_LENGTH) { + /* + * Looks like the key data exceeds the hash block length, + * so that means we use a hash of the key as the key data + * instead. + */ + if (ctx->hashkey == 0) { + /* + * Ah, we haven't started hashing the key + * data yet, so we must init. the hash + * monster to begin feeding it. + */ + + /* Set the hash key flag to true (non-zero) */ + ctx->hashkey = 1; + + /* Init. the hash beastie... */ + SHA256_Init(&ctx->shactx); + + /* If there's any previous key data, use it */ + if (ctx->keylen > 0) { + SHA256_Update(&ctx->shactx, &(ctx->key[0]), ctx->keylen); + } + + /* + * Reset the key length to the future true + * key length, HMAC_SHA256_DIGEST_LENGTH + */ + ctx->keylen = HMAC_SHA256_DIGEST_LENGTH; + } + /* Now feed the latest key data to the has monster */ + SHA256_Update(&ctx->shactx, key, keylen); + } else { + /* + * Key data length hasn't yet exceeded the hash + * block length (HMAC_SHA1_BLOCK_LENGTH), so theres + * no need to hash the key data (yet). Copy it + * into the key buffer. + */ + memcpy(&(ctx->key[ctx->keylen]), key, keylen); + ctx->keylen += keylen; + } +} + +void HMAC_SHA256_EndKey(HMAC_SHA256_CTX *ctx) { + unsigned char *ipad, *opad, *key; + int i; + unsigned int j; + + /* Did we end up hashing the key? */ + if (ctx->hashkey) { + memset(&(ctx->key[0]), ZERO_BYTE, HMAC_SHA256_BLOCK_LENGTH); + /* Yes, so finish up and copy the key data */ + SHA256_Final(&(ctx->key[0]), &ctx->shactx); + /* ctx->keylen was already set correctly */ + } + /* Pad the key if necessary with zero bytes */ + if ((i = HMAC_SHA256_BLOCK_LENGTH - ctx->keylen) > 0) { + memset(&(ctx->key[ctx->keylen]), ZERO_BYTE, i); + } + + ipad = &(ctx->ipad[0]); + opad = &(ctx->opad[0]); + + /* Precompute the respective pads XORed with the key */ + key = &(ctx->key[0]); + for (j = 0; j < ctx->keylen; j++, key++) { + /* XOR the key byte with the appropriate pad filler byte */ + *ipad++ ^= *key; + *opad++ ^= *key; + } +} + +void HMAC_SHA256_StartMessage(HMAC_SHA256_CTX *ctx) { + SHA256_Init(&ctx->shactx); + SHA256_Update(&ctx->shactx, &(ctx->ipad[0]), HMAC_SHA256_BLOCK_LENGTH); +} + +void HMAC_SHA256_UpdateMessage(HMAC_SHA256_CTX *ctx, unsigned char *data, unsigned int datalen) { + SHA256_Update(&ctx->shactx, data, datalen); +} + +void HMAC_SHA256_EndMessage(unsigned char *out, HMAC_SHA256_CTX *ctx) { + unsigned char buf[HMAC_SHA256_DIGEST_LENGTH]; + SHA256_CTX *c = &ctx->shactx; + + SHA256_Final(&(buf[0]), c); + SHA256_Init(c); + SHA256_Update(c, &(ctx->opad[0]), HMAC_SHA256_BLOCK_LENGTH); + SHA256_Update(c, buf, HMAC_SHA256_DIGEST_LENGTH); + SHA256_Final(out, c); +} + +void HMAC_SHA256_Done(HMAC_SHA256_CTX *ctx) { + /* Just to be safe, toast all context data */ + memset(&(ctx->ipad[0]), ZERO_BYTE, HMAC_SHA256_BLOCK_LENGTH); + memset(&(ctx->ipad[0]), ZERO_BYTE, HMAC_SHA256_BLOCK_LENGTH); + memset(&(ctx->key[0]), ZERO_BYTE, HMAC_SHA256_BLOCK_LENGTH); + ctx->keylen = 0; + ctx->hashkey = 0; +} + +#ifdef __cplusplus +} +#endif + +#endif |