d4b23966cb64984ef893cd96d7d6f3cc7c6fffb1
[firefly-linux-kernel-4.4.55.git] / drivers / staging / rt2860 / common / crypt_sha2.c
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************/
26
27 #include "../crypt_sha2.h"
28
29 /* Basic operations */
30 #define SHR(x,n) (x >> n) /* SHR(x)^n, right shift n bits , x is w-bit word, 0 <= n <= w */
31 #define ROTR(x,n,w) ((x >> n) | (x << (w - n))) /* ROTR(x)^n, circular right shift n bits , x is w-bit word, 0 <= n <= w */
32 #define ROTL(x,n,w) ((x << n) | (x >> (w - n))) /* ROTL(x)^n, circular left shift n bits , x is w-bit word, 0 <= n <= w */
33 #define ROTR32(x,n) ROTR(x,n,32) /* 32 bits word */
34 #define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */
35
36 /* Basic functions */
37 #define Ch(x,y,z) ((x & y) ^ ((~x) & z))
38 #define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
39 #define Parity(x,y,z) (x ^ y ^ z)
40
41 #ifdef SHA1_SUPPORT
42 /* SHA1 constants */
43 #define SHA1_MASK 0x0000000f
44 static const UINT32 SHA1_K[4] = {
45     0x5a827999UL, 0x6ed9eba1UL, 0x8f1bbcdcUL, 0xca62c1d6UL
46 };
47 static const UINT32 SHA1_DefaultHashValue[5] = {
48     0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL, 0xc3d2e1f0UL
49 };
50
51 /*
52 ========================================================================
53 Routine Description:
54     Initial SHA1_CTX_STRUC
55
56 Arguments:
57     pSHA_CTX        Pointer to SHA1_CTX_STRUC
58
59 Return Value:
60     None
61
62 Note:
63     None
64 ========================================================================
65 */
66 VOID RT_SHA1_Init (
67     IN  SHA1_CTX_STRUC *pSHA_CTX)
68 {
69     NdisMoveMemory(pSHA_CTX->HashValue, SHA1_DefaultHashValue,
70         sizeof(SHA1_DefaultHashValue));
71     NdisZeroMemory(pSHA_CTX->Block, SHA1_BLOCK_SIZE);
72     pSHA_CTX->MessageLen = 0;
73     pSHA_CTX->BlockLen   = 0;
74 } /* End of RT_SHA1_Init */
75
76
77 /*
78 ========================================================================
79 Routine Description:
80     SHA1 computation for one block (512 bits)
81
82 Arguments:
83     pSHA_CTX        Pointer to SHA1_CTX_STRUC
84
85 Return Value:
86     None
87
88 Note:
89     None
90 ========================================================================
91 */
92 VOID SHA1_Hash (
93     IN  SHA1_CTX_STRUC *pSHA_CTX)
94 {
95     UINT32 W_i,t,s;
96     UINT32 W[16];
97     UINT32 a,b,c,d,e,T,f_t = 0;
98
99     /* Prepare the message schedule, {W_i}, 0 < t < 15 */
100     NdisMoveMemory(W, pSHA_CTX->Block, SHA1_BLOCK_SIZE);
101     for (W_i = 0; W_i < 16; W_i++)
102         W[W_i] = cpu2be32(W[W_i]); /* Endian Swap */
103         /* End of for */
104
105     /* SHA256 hash computation */
106     /* Initialize the working variables */
107     a = pSHA_CTX->HashValue[0];
108     b = pSHA_CTX->HashValue[1];
109     c = pSHA_CTX->HashValue[2];
110     d = pSHA_CTX->HashValue[3];
111     e = pSHA_CTX->HashValue[4];
112
113     /* 80 rounds */
114     for (t = 0;t < 80;t++) {
115         s = t & SHA1_MASK;
116         if (t > 15) { /* Prepare the message schedule, {W_i}, 16 < t < 79 */
117             W[s] = (W[(s+13) & SHA1_MASK]) ^ (W[(s+8) & SHA1_MASK]) ^ (W[(s+2) & SHA1_MASK]) ^ W[s];
118             W[s] = ROTL32(W[s],1);
119         } /* End of if */
120         switch (t / 20) {
121             case 0:
122                  f_t = Ch(b,c,d);
123                  break;
124             case 1:
125                  f_t = Parity(b,c,d);
126                  break;
127             case 2:
128                  f_t = Maj(b,c,d);
129                  break;
130             case 3:
131                  f_t = Parity(b,c,d);
132                  break;
133         } /* End of switch */
134         T = ROTL32(a,5) + f_t + e + SHA1_K[t / 20] + W[s];
135         e = d;
136         d = c;
137         c = ROTL32(b,30);
138         b = a;
139         a = T;
140      } /* End of for */
141
142      /* Compute the i^th intermediate hash value H^(i) */
143      pSHA_CTX->HashValue[0] += a;
144      pSHA_CTX->HashValue[1] += b;
145      pSHA_CTX->HashValue[2] += c;
146      pSHA_CTX->HashValue[3] += d;
147      pSHA_CTX->HashValue[4] += e;
148
149     NdisZeroMemory(pSHA_CTX->Block, SHA1_BLOCK_SIZE);
150     pSHA_CTX->BlockLen = 0;
151 } /* End of SHA1_Hash */
152
153
154 /*
155 ========================================================================
156 Routine Description:
157     The message is appended to block. If block size > 64 bytes, the SHA1_Hash
158 will be called.
159
160 Arguments:
161     pSHA_CTX        Pointer to SHA1_CTX_STRUC
162     message         Message context
163     messageLen      The length of message in bytes
164
165 Return Value:
166     None
167
168 Note:
169     None
170 ========================================================================
171 */
172 VOID SHA1_Append (
173     IN  SHA1_CTX_STRUC *pSHA_CTX,
174     IN  const UINT8 Message[],
175     IN  UINT MessageLen)
176 {
177     UINT appendLen = 0;
178     UINT diffLen   = 0;
179
180     while (appendLen != MessageLen) {
181         diffLen = MessageLen - appendLen;
182         if ((pSHA_CTX->BlockLen + diffLen) <  SHA1_BLOCK_SIZE) {
183             NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen,
184                 Message + appendLen, diffLen);
185             pSHA_CTX->BlockLen += diffLen;
186             appendLen += diffLen;
187         }
188         else
189         {
190             NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen,
191                 Message + appendLen, SHA1_BLOCK_SIZE - pSHA_CTX->BlockLen);
192             appendLen += (SHA1_BLOCK_SIZE - pSHA_CTX->BlockLen);
193             pSHA_CTX->BlockLen = SHA1_BLOCK_SIZE;
194             SHA1_Hash(pSHA_CTX);
195         } /* End of if */
196     } /* End of while */
197     pSHA_CTX->MessageLen += MessageLen;
198 } /* End of SHA1_Append */
199
200
201 /*
202 ========================================================================
203 Routine Description:
204     1. Append bit 1 to end of the message
205     2. Append the length of message in rightmost 64 bits
206     3. Transform the Hash Value to digest message
207
208 Arguments:
209     pSHA_CTX        Pointer to SHA1_CTX_STRUC
210
211 Return Value:
212     digestMessage   Digest message
213
214 Note:
215     None
216 ========================================================================
217 */
218 VOID SHA1_End (
219     IN  SHA1_CTX_STRUC *pSHA_CTX,
220     OUT UINT8 DigestMessage[])
221 {
222     UINT index;
223     UINT64 message_length_bits;
224
225     /* Append bit 1 to end of the message */
226     NdisFillMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, 1, 0x80);
227
228     /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */
229     if (pSHA_CTX->BlockLen > 55)
230         SHA1_Hash(pSHA_CTX);
231         /* End of if */
232
233     /* Append the length of message in rightmost 64 bits */
234     message_length_bits = pSHA_CTX->MessageLen*8;
235     message_length_bits = cpu2be64(message_length_bits);
236     NdisMoveMemory(&pSHA_CTX->Block[56], &message_length_bits, 8);
237     SHA1_Hash(pSHA_CTX);
238
239     /* Return message digest, transform the UINT32 hash value to bytes */
240     for (index = 0; index < 5;index++)
241         pSHA_CTX->HashValue[index] = cpu2be32(pSHA_CTX->HashValue[index]);
242         /* End of for */
243     NdisMoveMemory(DigestMessage, pSHA_CTX->HashValue, SHA1_DIGEST_SIZE);
244 } /* End of SHA1_End */
245
246
247 /*
248 ========================================================================
249 Routine Description:
250     SHA1 algorithm
251
252 Arguments:
253     message         Message context
254     messageLen      The length of message in bytes
255
256 Return Value:
257     digestMessage   Digest message
258
259 Note:
260     None
261 ========================================================================
262 */
263 VOID RT_SHA1 (
264     IN  const UINT8 Message[],
265     IN  UINT MessageLen,
266     OUT UINT8 DigestMessage[])
267 {
268
269     SHA1_CTX_STRUC sha_ctx;
270
271     NdisZeroMemory(&sha_ctx, sizeof(SHA1_CTX_STRUC));
272     RT_SHA1_Init(&sha_ctx);
273     SHA1_Append(&sha_ctx, Message, MessageLen);
274     SHA1_End(&sha_ctx, DigestMessage);
275 } /* End of RT_SHA1 */
276 #endif /* SHA1_SUPPORT */
277
278 /* End of crypt_sha2.c */