1 /** @file hmac_sha1.c
2 *
3 * @brief This file defines algorithm for hmac sha1
4 *
5 * Copyright (C) 2014-2017, Marvell International Ltd.
6 *
7 * This software file (the "File") is distributed by Marvell International
8 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
9 * (the "License"). You may use, redistribute and/or modify this File in
10 * accordance with the terms and conditions of the License, a copy of which
11 * is available by writing to the Free Software Foundation, Inc.,
12 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
13 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
14 *
15 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
17 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
18 * this warranty disclaimer.
19 */
20
21 /******************************************************
22 Change log:
23 03/07/2014: Initial version
24 ******************************************************/
25 #include "wltypes.h"
26 #include "wl_macros.h"
27 #include "sha1.h"
28 #include "hostsa_ext_def.h"
29 #include "authenticator.h"
30
31 void
Mrvl_hmac_sha1(void * priv,unsigned char ** ppText,int * pTextLen,int textNum,unsigned char * key,int key_len,unsigned char * output,int outputLen)32 Mrvl_hmac_sha1(void *priv, unsigned char **ppText,
33 int *pTextLen,
34 int textNum,
35 unsigned char *key,
36 int key_len, unsigned char *output, int outputLen)
37 {
38 /*
39 Note- Some of the variables are made static in this function
40 becuase currently this function executes in the idle task.
41 The idle task dosent have enough stack space to accomodate
42 these varables. In the future if this function in executed in
43 a different task or if we increase the stack size of the idle
44 task then we can put these variables on the stack
45 */
46 //BufferDesc_t * pDesc = NULL;
47 phostsa_private psapriv = (phostsa_private)priv;
48 hostsa_util_fns *util_fns = &psapriv->util_fns;
49 UINT8 buf[400] = { 0 };
50 Mrvl_SHA1_CTX *context;
51 unsigned char *k_pad; /* padding - key XORd with i/opad */
52 unsigned char *digest;
53 int i;
54
55 k_pad = (unsigned char *)buf;
56 digest = k_pad + 64;
57 context = (Mrvl_SHA1_CTX *)(k_pad + 64 + 20);
58
59 /* if key is longer than 64 bytes reset it to key=SHA1(key) */
60 if (key_len > 64) {
61 Mrvl_SHA1Init(context);
62 Mrvl_SHA1Update(context, key, key_len);
63 Mrvl_SHA1Final((void *)priv, context, key);
64
65 key_len = 20;
66 }
67
68 /*
69 * the HMAC_SHA1 transform looks like:
70 *
71 * SHA1(K XOR opad, SHA1(K XOR ipad, text))
72 *
73 * where K is an n byte key
74 * ipad is the byte 0x36 repeated 64 times
75 * opad is the byte 0x5c repeated 64 times
76 * and text is the data being protected
77 */
78
79 /* perform inner SHA1 */
80 /* start out by storing key in pads */
81 memset(util_fns, k_pad, 0, 64);
82 memcpy(util_fns, k_pad, key, key_len);
83
84 /* XOR key with ipad and opad values */
85 for (i = 0; i < 8; i++) {
86 ((UINT64 *)k_pad)[i] ^= 0x3636363636363636ULL;
87 }
88
89 Mrvl_SHA1Init(context); /* init context for 1st pass */
90 Mrvl_SHA1Update(context, k_pad, 64); /* start with inner pad */
91 for (i = 0; i < textNum; i++) {
92 /* then text of datagram */
93 Mrvl_SHA1Update(context, ppText[i], pTextLen[i]);
94 }
95
96 Mrvl_SHA1Final((void *)priv, context, digest); /* finish up 1st pass */
97
98 /* perform outer SHA1 */
99 /* start out by storing key in pads */
100 memset(util_fns, k_pad, 0, 64);
101 memcpy(util_fns, k_pad, key, key_len);
102
103 /* XOR key with ipad and opad values */
104 for (i = 0; i < 8; i++) {
105 ((UINT64 *)k_pad)[i] ^= 0x5c5c5c5c5c5c5c5cULL;
106 }
107
108 Mrvl_SHA1Init(context); /* init context for 2nd pass */
109 Mrvl_SHA1Update(context, k_pad, 64); /* start with outer pad */
110 Mrvl_SHA1Update(context, digest, 20); /* then results of 1st hash */
111 Mrvl_SHA1Final((void *)priv, context, digest); /* finish up 2nd pass */
112 memcpy(util_fns, output, digest, outputLen);
113
114 // bml_FreeBuffer((UINT32)pDesc);
115 }
116
117 /*
118 * PRF -- Length of output is in octets rather than bits
119 * since length is always a multiple of 8 output array is
120 * organized so first N octets starting from 0 contains PRF output
121 *
122 * supported inputs are 16, 32, 48, 64
123 * output array must be 80 octets to allow for sha1 overflow
124 */
125 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)126 Mrvl_PRF(void *priv, unsigned char *key, int key_len,
127 unsigned char *prefix, int prefix_len,
128 unsigned char *data, int data_len, unsigned char *output, int len)
129 {
130 phostsa_private psapriv = (phostsa_private)priv;
131 hostsa_util_fns *util_fns = &psapriv->util_fns;
132 int i;
133 int currentindex = 0;
134 int total_len;
135 UINT8 prf_input[120]; /* concatenated input */
136 unsigned char *pText = prf_input;
137 SINT8 remain = len;
138
139 memset(util_fns, prf_input, 0x00, sizeof(prf_input));
140
141 if (prefix) {
142 memcpy(util_fns, prf_input, prefix, prefix_len);
143 prf_input[prefix_len] = 0; /* single octet 0 */
144 memcpy(util_fns, &prf_input[prefix_len + 1], data, data_len);
145 total_len = prefix_len + 1 + data_len;
146 } else {
147 memcpy(util_fns, prf_input, data, data_len);
148 total_len = data_len;
149 }
150
151 prf_input[total_len] = 0; /* single octet count, starts at 0 */
152 total_len++;
153 for (i = 0; i < (len + 19) / 20; i++) {
154 Mrvl_hmac_sha1(priv, (UINT8 **)&pText,
155 &total_len,
156 1,
157 key,
158 key_len, &output[currentindex], MIN(20, remain));
159 currentindex += MIN(20, remain); /* next concatenation location */
160 remain -= 20;
161 prf_input[total_len - 1]++; /* increment octet count */
162 }
163 }
164