4 #include <sys/socket.h>
6 #include <linux/wireless.h>
11 /*------------------------------------------------------------------*/
14 * Depending on the protocol present, open the right socket. The socket
15 * will allow us to talk to the driver.
19 static const int families
[] = {
20 AF_INET
, AF_IPX
, AF_AX25
, AF_APPLETALK
26 * Now pick any (exisiting) useful socket family for generic queries
27 * Note : don't open all the socket, only returns when one matches,
28 * all protocols might not be valid.
29 * Workaround by Jim Kaba <jkaba@sarnoff.com>
30 * Note : in 99% of the case, we will just open the inet_sock.
31 * The remaining 1% case are not fully correct...
34 /* Try all families we support */
35 for(i
= 0; i
< sizeof(families
)/sizeof(int); ++i
)
37 /* Try to open the socket, if success returns it */
38 sock
= socket(families
[i
], SOCK_DGRAM
, 0);
46 int OidQueryInformation(USHORT OidQueryCode
, int socket_id
, char *DeviceName
, void *ptr
, ULONG PtrLength
)
50 strcpy(wrq
.ifr_name
, DeviceName
);
51 wrq
.u
.data
.length
= PtrLength
;
52 wrq
.u
.data
.pointer
= (caddr_t
) ptr
;
53 wrq
.u
.data
.flags
= OidQueryCode
;
55 return (ioctl(socket_id
, RT_PRIV_IOCTL
, &wrq
));
58 int OidSetInformation(USHORT OidQueryCode
, int socket_id
, char *DeviceName
, void *ptr
, ULONG PtrLength
)
62 strcpy(wrq
.ifr_name
, DeviceName
);
63 wrq
.u
.data
.length
= PtrLength
;
64 wrq
.u
.data
.pointer
= (caddr_t
) ptr
;
65 wrq
.u
.data
.flags
= OidQueryCode
| OID_GET_SET_TOGGLE
;
67 return (ioctl(socket_id
, RT_PRIV_IOCTL
, &wrq
));
70 UINT
ConvertRssiToSignalQuality(NDIS_802_11_RSSI RSSI
)
75 else if (RSSI
>= -80) // between -50 ~ -80dbm
76 signal_quality
= (UINT
)(24 + (RSSI
+ 80) * 2.6);
77 else if (RSSI
>= -90) // between -80 ~ -90dbm
78 signal_quality
= (UINT
)((RSSI
+ 90) * 2.6);
82 return signal_quality
;
86 // FUNCTION: BtoH(char *, char *, int)
88 // PURPOSE: Converts ascii byte to numeric
91 // ch - ascii byte to convert
94 // associated numeric value
98 // Will convert any hex ascii digit to its numeric counterpart.
99 // Puts in 0xff if not a valid hex digit.
102 unsigned char BtoH(char ch
)
104 if (ch
>= '0' && ch
<= '9') return (ch
- '0'); // Handle numerals
105 if (ch
>= 'A' && ch
<= 'F') return (ch
- 'A' + 0xA); // Handle capitol hex digits
106 if (ch
>= 'a' && ch
<= 'f') return (ch
- 'a' + 0xA); // Handle small hex digits
111 // FUNCTION: AtoH(char *, UCHAR *, int)
113 // PURPOSE: Converts ascii string to network order hex
116 // src - pointer to input ascii string
117 // dest - pointer to output hex
118 // destlen - size of dest
122 // 2 ascii bytes make a hex byte so must put 1st ascii byte of pair
123 // into upper nibble and 2nd ascii byte of pair into lower nibble.
126 void AtoH(char * src
, UCHAR
* dest
, int destlen
)
131 PUCHAR destTemp
= dest
;
135 *destTemp
= BtoH(*srcptr
++) << 4; // Put 1st ascii byte in upper nibble.
136 *destTemp
+= BtoH(*srcptr
++); // Add 2nd ascii byte to above.
141 static void hmac_sha1(unsigned char *text
, int text_len
, unsigned char *key
, int key_len
, unsigned char *digest
)
144 unsigned char k_ipad
[65]; /* inner padding - key XORd with ipad */
145 unsigned char k_opad
[65]; /* outer padding - key XORd with opad */
148 /* if key is longer than 64 bytes reset it to key=SHA1(key) */
154 A_SHAUpdate(&tctx
, key
, key_len
);
155 A_SHAFinal(&tctx
, key
);
161 * the HMAC_SHA1 transform looks like:
163 * SHA1(K XOR opad, SHA1(K XOR ipad, text))
165 * where K is an n byte key
166 * ipad is the byte 0x36 repeated 64 times
167 * opad is the byte 0x5c repeated 64 times
168 * and text is the data being protected
171 /* start out by storing key in pads */
172 memset(k_ipad
, 0, sizeof k_ipad
);
173 memset(k_opad
, 0, sizeof k_opad
);
174 memcpy(k_ipad
, key
, key_len
);
175 memcpy(k_opad
, key
, key_len
);
177 /* XOR key with ipad and opad values */
178 for (i
= 0; i
< 64; i
++)
184 /* perform inner SHA1*/
185 A_SHAInit(&context
); /* init context for 1st pass */
186 A_SHAUpdate(&context
, k_ipad
, 64); /* start with inner pad */
187 A_SHAUpdate(&context
, text
, text_len
); /* then text of datagram */
188 A_SHAFinal(&context
, digest
); /* finish up 1st pass */
190 /* perform outer SHA1 */
191 A_SHAInit(&context
); /* init context for 2nd pass */
192 A_SHAUpdate(&context
, k_opad
, 64); /* start with outer pad */
193 A_SHAUpdate(&context
, digest
, 20); /* then results of 1st hash */
194 A_SHAFinal(&context
, digest
); /* finish up 2nd pass */
198 * F(P, S, c, i) = U1 xor U2 xor ... Uc
199 * U1 = PRF(P, S || Int(i))
204 static void F(char *password
, unsigned char *ssid
, int ssidlength
, int iterations
, int count
, unsigned char *output
)
206 unsigned char digest
[36], digest1
[A_SHA_DIGEST_LEN
];
209 /* U1 = PRF(P, S || int(i)) */
210 memcpy(digest
, ssid
, ssidlength
);
211 digest
[ssidlength
] = (unsigned char)((count
>>24) & 0xff);
212 digest
[ssidlength
+1] = (unsigned char)((count
>>16) & 0xff);
213 digest
[ssidlength
+2] = (unsigned char)((count
>>8) & 0xff);
214 digest
[ssidlength
+3] = (unsigned char)(count
& 0xff);
215 hmac_sha1(digest
, ssidlength
+4, (unsigned char*) password
, (int) strlen(password
), digest1
); // for WPA update
218 memcpy(output
, digest1
, A_SHA_DIGEST_LEN
);
220 for (i
= 1; i
< iterations
; i
++)
222 /* Un = PRF(P, Un-1) */
223 hmac_sha1(digest1
, A_SHA_DIGEST_LEN
, (unsigned char*) password
, (int) strlen(password
), digest
); // for WPA update
224 memcpy(digest1
, digest
, A_SHA_DIGEST_LEN
);
226 /* output = output xor Un */
227 for (j
= 0; j
< A_SHA_DIGEST_LEN
; j
++)
229 output
[j
] ^= digest
[j
];
234 * password - ascii string up to 63 characters in length
235 * ssid - octet string up to 32 octets
236 * ssidlength - length of ssid in octets
237 * output must be 40 octets in length and outputs 256 bits of key
239 int PasswordHash(char *password
, unsigned char *ssid
, int ssidlength
, unsigned char *output
)
241 if ((strlen(password
) > 63) || (ssidlength
> 32))
244 F(password
, ssid
, ssidlength
, 4096, 1, output
);
245 F(password
, ssid
, ssidlength
, 4096, 2, &output
[A_SHA_DIGEST_LEN
]);