1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - NWM - libraries
3   File:     nwm_passphrase.c
4 
5   Copyright 2007-2008 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2007-10-09#$
14   $Rev: 1469 $
15   $Author: okajima_manabu $
16  *---------------------------------------------------------------------------*/
17 
18 #include <twl.h>
19 
20 #define SHA1_MAC_LEN 20
21 
22 static void pbkdf2_sha1(const u8 *passphrase, const u8 *ssid, u8 ssid_len,
23 		 u32 iterations, u8 *buf, u32 buflen);
24 
25 static void pbkdf2_sha1_f(const u8 *passphrase, const u8 *ssid,
26 			  u32 ssid_len, u32 iterations, u32 count,
27 			  u8 *digest);
28 
29 #ifndef SDK_TWL
30 
31 static void hmac_sha1_vector(const u8 *key, u32 key_len, u32 num_elem,
32 		      const u8 *addr[], const u32 *len, u8 *mac);
33 
34 static void sha1_vector(u32 num_elem, const u8 *addr[], const u32 *len,
35 		 u8 *mac);
36 
37 #endif
38 
39 /*---------------------------------------------------------------------------*
40   Name:         NWM_Passphrase2PSK
41 
42   Description:
43 
44 
45   Arguments:
46 
47   Returns:      None
48 
49  *---------------------------------------------------------------------------*/
50 
NWM_Passphrase2PSK(const u8 passphrase[NWM_WPA_PASSPHRASE_LENGTH_MAX],const u8 * ssid,u8 ssidlen,u8 psk[NWM_WPA_PSK_LENGTH])51 void NWM_Passphrase2PSK(const u8 passphrase[NWM_WPA_PASSPHRASE_LENGTH_MAX], const u8 *ssid, u8 ssidlen, u8 psk[NWM_WPA_PSK_LENGTH])
52 {
53     pbkdf2_sha1(passphrase, (const u8 *)ssid, ssidlen, 4096, psk, NWM_WPA_PSK_LENGTH);
54 }
55 
pbkdf2_sha1(const u8 * passphrase,const u8 * ssid,u8 ssid_len,u32 iterations,u8 * buf,u32 buflen)56 void pbkdf2_sha1(const u8 *passphrase, const u8 *ssid, u8 ssid_len,
57 		 u32 iterations, u8 *buf, u32 buflen)
58 {
59 	u32 count = 0;
60 	u8 *pos = buf;
61 	u32 left = buflen, plen;
62 	u8 digest[SHA1_MAC_LEN];
63 
64 	while (left > 0) {
65 		count++;
66 		pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, count, digest);
67 		plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left;
68         MI_CpuCopy8(digest, pos, plen);
69 		pos += plen;
70 		left -= plen;
71 	}
72 }
73 
74 
pbkdf2_sha1_f(const u8 * passphrase,const u8 * ssid,u32 ssid_len,u32 iterations,u32 count,u8 * digest)75 static void pbkdf2_sha1_f(const u8 *passphrase, const u8 *ssid,
76 			  u32 ssid_len, u32 iterations, u32 count,
77 			  u8 *digest)
78 {
79 	int i, j;
80 	u8 tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN];
81 	u8 count_buf[4];
82 	const u8 *addr[2];
83 	u32 len[2];
84 	u32 passphrase_len = (u32)STD_StrLen((const char*)passphrase);
85 #ifdef SDK_TWL
86     SVCHMACSHA1Context ctx;
87 #endif
88 
89 	addr[0] = (const u8 *) ssid;
90 	len[0] = (u32)ssid_len;
91 	addr[1] = count_buf;
92 	len[1] = 4;
93 
94 	/* F(P, S, c, i) = U1 xor U2 xor ... Uc
95 	 * U1 = PRF(P, S || i)
96 	 * U2 = PRF(P, U1)
97 	 * Uc = PRF(P, Uc-1)
98 	 */
99 
100 	count_buf[0] = (u8)((count >> 24) & 0xff);
101 	count_buf[1] = (u8)((count >> 16) & 0xff);
102 	count_buf[2] = (u8)((count >> 8) & 0xff);
103 	count_buf[3] = (u8)(count & 0xff);
104 #ifdef SDK_TWL
105     MI_CpuClear8(&ctx, sizeof(ctx));
106     SVC_HMACSHA1Init( &ctx, (const void *)passphrase, (u32)passphrase_len );
107     for (i=0; i < 2; i++) {
108         SVC_HMACSHA1Update( &ctx, (const void *)addr[i], (u32)len[i] );
109     }
110     SVC_HMACSHA1GetHash( &ctx, (void*)tmp );
111 #else
112     hmac_sha1_vector((const u8 *) passphrase, passphrase_len, 2, addr, len, tmp);
113 #endif
114     MI_CpuCopy8(tmp, digest, SHA1_MAC_LEN);
115 
116 	for (i = 1; i < iterations; i++) {
117         addr[0] = (const u8 *)tmp;
118         len[0] = SHA1_MAC_LEN;
119 #ifdef SDK_TWL
120         MI_CpuClear8(&ctx, sizeof(ctx));
121         SVC_HMACSHA1Init( &ctx, (const void *)passphrase, (u32)passphrase_len );
122         SVC_HMACSHA1Update( &ctx, (const void *)addr[0], (u32)len[0] );
123         SVC_HMACSHA1GetHash( &ctx, (void*)tmp2 );
124 #else
125         hmac_sha1_vector((const u8 *) passphrase, passphrase_len, 1, addr, len, tmp2);
126 #endif
127         MI_CpuCopy8(tmp2, tmp, SHA1_MAC_LEN);
128 		for (j = 0; j < SHA1_MAC_LEN; j++)
129 			digest[j] ^= tmp2[j];
130 	}
131 
132 }
133 
134 #ifndef SDK_TWL
135 
hmac_sha1_vector(const u8 * key,u32 key_len,u32 num_elem,const u8 * addr[],const u32 * len,u8 * mac)136 void hmac_sha1_vector(const u8 *key, u32 key_len, u32 num_elem,
137 		      const u8 *addr[], const u32 *len, u8 *mac)
138 {
139     u8 k_pad[64]; /* padding - key XORd with ipad/opad */
140     u8 tk[20];
141     int i;
142     const u8 *_addr[6];
143     u32 _len[6];
144 
145     if (num_elem > 5) {
146         /*
147          * Fixed limit on the number of fragments to avoid having to
148          * allocate memory (which could fail).
149          */
150         return;
151     }
152 
153     /* if key is longer than 64 bytes reset it to key = SHA1(key) */
154     if (key_len > 64) {
155         sha1_vector(1, &key, &key_len, tk);
156         key = tk;
157         key_len = 20;
158     }
159 
160     /* the HMAC_SHA1 transform looks like:
161      *
162      * SHA1(K XOR opad, SHA1(K XOR ipad, text))
163      *
164      * where K is an n byte key
165      * ipad is the byte 0x36 repeated 64 times
166      * opad is the byte 0x5c repeated 64 times
167      * and text is the data being protected */
168 
169     /* start out by storing key in ipad */
170     MI_CpuClear8(k_pad, sizeof(k_pad));
171     MI_CpuCopy8(key, k_pad, key_len);
172     /* XOR key with ipad values */
173     for (i = 0; i < 64; i++)
174         k_pad[i] ^= 0x36;
175 
176     /* perform inner SHA1 */
177     _addr[0] = k_pad;
178     _len[0] = 64;
179     for (i = 0; i < num_elem; i++) {
180         _addr[i + 1] = addr[i];
181         _len[i + 1] = len[i];
182     }
183     sha1_vector(1 + num_elem, _addr, _len, mac);
184 
185     MI_CpuClear8(k_pad, sizeof(k_pad));
186     MI_CpuCopy8(key, k_pad, key_len);
187     /* XOR key with opad values */
188     for (i = 0; i < 64; i++)
189         k_pad[i] ^= 0x5c;
190 
191     /* perform outer SHA1 */
192     _addr[0] = k_pad;
193     _len[0] = 64;
194     _addr[1] = mac;
195     _len[1] = SHA1_MAC_LEN;
196     sha1_vector(2, _addr, _len, mac);
197 }
198 
199 
sha1_vector(u32 num_elem,const u8 * addr[],const u32 * len,u8 * mac)200 void sha1_vector(u32 num_elem, const u8 *addr[], const u32 *len,
201 		 u8 *mac)
202 {
203 	int i;
204 #ifdef SDK_TWL
205     SVCSHA1Context context;
206 #else
207     MATHSHA1Context context;
208 #endif
209 
210     MI_CpuClear8(&context, sizeof(context));
211 
212 #ifdef SDK_TWL
213 	SVC_SHA1Init( &context );
214 #else
215     MATH_SHA1Init( &context );
216 #endif
217 
218     for (i = 0; i < num_elem; i++) {
219 #ifdef SDK_TWL
220         SVC_SHA1Update( &context, addr[i], len[i] );
221 #else
222         MATH_SHA1Update( &context, (const void*)addr[i], len[i] );
223 #endif
224     }
225 #ifdef SDK_TWL
226 	SVC_SHA1GetHash( &context, mac );
227 #else
228     MATH_SHA1GetHash( &context, (void*)mac );
229 #endif
230 }
231 
232 #endif /* #ifndef SDK_TWL */