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 */