blob: dfbd7f072295a252307740d3ca75103e29d31248 [file] [log] [blame]
/** @file hmac_sha1.c
*
* @brief This file defines algorithm for hmac sha1
*
* Copyright (C) 2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
* (the "License"). You may use, redistribute and/or modify this File in
* accordance with the terms and conditions of the License, a copy of which
* is available by writing to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
* this warranty disclaimer.
*/
/******************************************************
Change log:
03/07/2014: Initial version
******************************************************/
#include "wltypes.h"
#include "wl_macros.h"
#include "sha1.h"
#include "hostsa_ext_def.h"
#include "authenticator.h"
void
Mrvl_hmac_sha1(void *priv, unsigned char **ppText,
int *pTextLen,
int textNum,
unsigned char *key,
int key_len, unsigned char *output, int outputLen)
{
/*
Note- Some of the variables are made static in this function
becuase currently this function executes in the idle task. The idle
task dosent have enough stack space to accomodate these varables.
In the future if this function in executed in a different task or
if we increase the stack size of the idle task then we can put
these variables on the stack */
// BufferDesc_t * pDesc = NULL;
phostsa_private psapriv = (phostsa_private)priv;
hostsa_util_fns *util_fns = &psapriv->util_fns;
UINT8 buf[400] = { 0 };
Mrvl_SHA1_CTX *context;
unsigned char *k_pad; /* padding - key XORd with i/opad */
unsigned char *digest;
int i;
k_pad = (unsigned char *)buf;
digest = k_pad + 64;
context = (Mrvl_SHA1_CTX *)(k_pad + 64 + 20);
/* if key is longer than 64 bytes reset it to key=SHA1(key) */
if (key_len > 64) {
Mrvl_SHA1Init(context);
Mrvl_SHA1Update(context, key, key_len);
Mrvl_SHA1Final((void *)priv, context, key);
key_len = 20;
}
/*
* the HMAC_SHA1 transform looks like:
*
* SHA1(K XOR opad, SHA1(K XOR ipad, text))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected
*/
/* perform inner SHA1 */
/* start out by storing key in pads */
memset(util_fns, k_pad, 0, 64);
memcpy(util_fns, k_pad, key, key_len);
/* XOR key with ipad and opad values */
for (i = 0; i < 8; i++) {
((UINT64 *)k_pad)[i] ^= 0x3636363636363636;
}
Mrvl_SHA1Init(context); /* init context for 1st pass */
Mrvl_SHA1Update(context, k_pad, 64); /* start with inner pad */
for (i = 0; i < textNum; i++) {
/* then text of datagram */
Mrvl_SHA1Update(context, ppText[i], pTextLen[i]);
}
Mrvl_SHA1Final((void *)priv, context, digest); /* finish up 1st pass */
/* perform outer SHA1 */
/* start out by storing key in pads */
memset(util_fns, k_pad, 0, 64);
memcpy(util_fns, k_pad, key, key_len);
/* XOR key with ipad and opad values */
for (i = 0; i < 8; i++) {
((UINT64 *)k_pad)[i] ^= 0x5c5c5c5c5c5c5c5c;
}
Mrvl_SHA1Init(context); /* init context for 2nd pass */
Mrvl_SHA1Update(context, k_pad, 64); /* start with outer pad */
Mrvl_SHA1Update(context, digest, 20); /* then results of 1st hash */
Mrvl_SHA1Final((void *)priv, context, digest); /* finish up 2nd pass */
memcpy(util_fns, output, digest, outputLen);
// bml_FreeBuffer((UINT32)pDesc);
}
/*
* PRF -- Length of output is in octets rather than bits
* since length is always a multiple of 8 output array is
* organized so first N octets starting from 0 contains PRF output
*
* supported inputs are 16, 32, 48, 64
* output array must be 80 octets to allow for sha1 overflow
*/
void
Mrvl_PRF(void *priv, unsigned char *key, int key_len,
unsigned char *prefix, int prefix_len,
unsigned char *data, int data_len, unsigned char *output, int len)
{
phostsa_private psapriv = (phostsa_private)priv;
hostsa_util_fns *util_fns = &psapriv->util_fns;
int i;
int currentindex = 0;
int total_len;
UINT8 prf_input[120]; /* concatenated input */
unsigned char *pText = prf_input;
SINT8 remain = len;
memset(util_fns, prf_input, 0x00, sizeof(prf_input));
if (prefix) {
memcpy(util_fns, prf_input, prefix, prefix_len);
prf_input[prefix_len] = 0; /* single octet 0 */
memcpy(util_fns, &prf_input[prefix_len + 1], data, data_len);
total_len = prefix_len + 1 + data_len;
} else {
memcpy(util_fns, prf_input, data, data_len);
total_len = data_len;
}
prf_input[total_len] = 0; /* single octet count, starts at 0 */
total_len++;
for (i = 0; i < (len + 19) / 20; i++) {
Mrvl_hmac_sha1(priv, (UINT8 **)&pText,
&total_len,
1,
key,
key_len, &output[currentindex], MIN(20, remain));
currentindex += MIN(20, remain); /* next concatenation
location */
remain -= 20;
prf_input[total_len - 1]++; /* increment octet count */
}
}