xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/mvl88w8977/mlan/esa/common/hmac_sha1.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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