mgh: fix for default HDD DMA mode, that wasn't correctly set
[open-ps2-loader.git] / ee_core / src / smbauth.c
blob6a2b3c9f24d4add37a2c42455ae277ff09aeb927
1 /*
2 Copyright 2010, jimmikaelkael <jimmikaelkael@wanadoo.fr>
3 Licenced under Academic Free License version 3.0
4 Review Open PS2 Loader README & LICENSE files for further details.
5 */
7 #include "ee_core.h"
8 #include "des.h"
9 #include "md4.h"
10 #include "util.h"
12 #include <tamtypes.h>
13 #include <kernel.h>
14 #include <stdio.h>
15 #include <sifcmd.h>
16 #include <sifdma.h>
17 #include <string.h>
19 #define DMA_ADDR 0x000cff00
20 #define UNCACHEDSEG(vaddr) (0x20000000 | vaddr)
22 extern int _gp;
24 /* EE DMAC registers. */
25 #define DMAC_COMM_STAT 0x1000e010
26 #define DMAC_SIF0_CHCR 0x1000c000
27 #define CHCR_STR 0x100
28 #define STAT_SIF0 0x20
30 static u8 thread_stack[0x800] __attribute__((aligned(16)));
31 static unsigned int *sifDmaDataPtr = (unsigned int *)UNCACHEDSEG(DMA_ADDR);
32 static int smbauth_thread_id;
33 static int sif0_id = -1;
35 static u8 passwd_buf[512] __attribute__((aligned(64)));
37 typedef struct { // size = 156
38 u32 MaxBufferSize;
39 u32 MaxMpxCount;
40 u32 SessionKey;
41 u32 StringsCF;
42 u8 PrimaryDomainServerName[32];
43 u8 EncryptionKey[8];
44 int SecurityMode; // 0 = share level, 1 = user level
45 int PasswordType; // 0 = PlainText passwords, 1 = use challenge/response
46 char Username[36];
47 u8 Password[48]; // either PlainText, either hashed
48 int PasswordLen;
49 int HashedFlag;
50 void *IOPaddr;
51 } server_specs_t;
53 static server_specs_t *server_specs = (void *)UNCACHEDSEG((DMA_ADDR + 0x40));
55 #define SERVER_USE_PLAINTEXT_PASSWORD 0
56 #define SERVER_USE_ENCRYPTED_PASSWORD 1
60 * LM_Password_Hash: this function create a LM password hash from a given password
62 static unsigned char *LM_Password_Hash(const unsigned char *password, unsigned char *cipher)
64 unsigned char tmp_pass[14] = {"\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
65 unsigned char K1[7];
66 unsigned char K2[7];
67 int i;
69 /* keep only 14 bytes of the password (padded with nul bytes) */
70 strncpy(tmp_pass, password, 14);
72 /* turn the password to uppercase */
73 for (i=0; i<14; i++) {
74 tmp_pass[i] = _toupper(tmp_pass[i]);
77 /* get 2 7bytes keys from password */
78 memcpy(K1, &tmp_pass[0], 7);
79 memcpy(K2, &tmp_pass[7], 7);
81 /* encrypt the magic string with the keys */
82 DES(K1, "KGS!@#$%", &cipher[0]);
83 DES(K2, "KGS!@#$%", &cipher[8]);
85 return (unsigned char *)cipher;
89 * NTLM_Password_Hash: this function create a NTLM password hash from a given password
91 static unsigned char *NTLM_Password_Hash(const unsigned char *password, unsigned char *cipher)
93 int i, j;
95 memset(passwd_buf, 0, sizeof(passwd_buf));
97 /* turn the password to unicode */
98 for (i=0, j=0; i<strlen(password); i++, j+=2)
99 passwd_buf[j] = password[i];
101 /* get the message digest */
102 MD4(passwd_buf, j, cipher);
104 return (unsigned char *)cipher;
108 * LM_Response: this function create a LM response from a given LM hash & challenge
110 static unsigned char *LM_Response(const unsigned char *LMpasswordhash, unsigned char *chal, unsigned char *cipher)
112 unsigned char P21[21];
113 unsigned char K[7];
114 int i;
116 /* padd the LM password hash with 5 nul bytes */
117 memcpy(&P21[0], LMpasswordhash, 16);
118 memset(&P21[16], 0, 5);
120 /* encrypt the challenge 3 times, using 7 bytes splitted keys */
121 for (i=0; i<3; i++) {
123 /* get the 7bytes key */
124 memcpy(K, &P21[i*7], 7);
126 /* encrypt each the challenge with the keys */
127 DES(K, chal, &cipher[i*8]);
130 return (unsigned char *)cipher;
134 * GenerateLMHashes: function used to generate LM/NTLM hashes
136 static void GenerateLMHashes(char *Password, int PasswordType, u8 *EncryptionKey, int *PasswordLen, u8 *Buffer)
138 u8 LMpasswordhash[16];
139 u8 NTLMpasswordhash[16];
140 u8 LMresponse[24];
141 u8 NTLMresponse[24];
143 if (PasswordType == SERVER_USE_ENCRYPTED_PASSWORD) {
144 /* Generate both LM & NTLM hashes */
145 LM_Password_Hash(Password, LMpasswordhash);
146 NTLM_Password_Hash(Password, NTLMpasswordhash);
147 *PasswordLen = 24;
148 LM_Response(LMpasswordhash, EncryptionKey, LMresponse);
149 LM_Response(NTLMpasswordhash, EncryptionKey, NTLMresponse);
150 memcpy(&Buffer[0], LMresponse, *PasswordLen);
151 memcpy(&Buffer[24], NTLMresponse, *PasswordLen);
153 else if (PasswordType == SERVER_USE_PLAINTEXT_PASSWORD) {
154 /* It seems that PlainText passwords and Unicode isn't meant to be... */
155 *PasswordLen = strlen(Password);
156 if (*PasswordLen > 14)
157 *PasswordLen = 14;
158 else if (*PasswordLen == 0)
159 *PasswordLen = 1;
160 memcpy(Buffer, Password, *PasswordLen);
165 * _smbauth_thread: main SMB authentification thread
167 static int _smbauth_thread(void *args)
169 SifDmaTransfer_t dmat;
170 int id;
172 /* the thread sleep down until it's awaken up by our DMA interrupt handler */
173 SleepThread();
175 DPRINTF("smbauth thread woken up !!!\n");
177 server_specs_t *ss = (server_specs_t *)server_specs;
178 if (ss->HashedFlag == 0) {
179 /* generate the LM and NTLM hash then fill Password buffer with both hashes */
180 if (strlen(ss->Password) > 0)
181 GenerateLMHashes(ss->Password, ss->PasswordType, ss->EncryptionKey, &ss->PasswordLen, ss->Password);
184 /* used to notify cdvdman that password are now hashed */
185 ss->HashedFlag = 1;
187 /* we send back server_specs_t to IOP */
188 dmat.dest = (void *)ss->IOPaddr;
189 dmat.size = sizeof(server_specs_t);
190 dmat.src = (void *)server_specs;
191 dmat.attr = SIF_DMA_INT_O;
193 id = 0;
194 while (!id)
195 id = SifSetDma(&dmat, 1);
196 while (SifDmaStat(id) >= 0);
198 /* remove our DMA interupt handler */
199 RemoveDmacHandler(5, sif0_id);
201 /* terminate SMB auth thread */
202 ExitDeleteThread();
203 return 0;
207 * _SifDmaIntrHandler: our DMA interrupt handler
209 int _SifDmaIntrHandler()
211 int flag;
213 flag = *sifDmaDataPtr;
214 iSifSetDChain();
216 if (flag) {
217 *sifDmaDataPtr = 0;
218 /* Wake Up our SMB auth thread */
219 iWakeupThread(smbauth_thread_id);
222 /* exit handler */
223 __asm__ __volatile__(
224 " sync;"
225 " ei;"
228 return 0;
232 * start_smbauth_thread: used to start the EE SMB auth thread
234 void start_smbauth_thread(void)
236 int ret;
237 ee_thread_t thread;
239 thread.func = _smbauth_thread;
240 thread.stack = thread_stack;
241 thread.stack_size = sizeof(thread_stack);
242 thread.gp_reg = &_gp;
243 thread.initial_priority = 1;
245 /* let's create the thread */
246 smbauth_thread_id = CreateThread(&thread);
247 if (smbauth_thread_id < 0) {
248 DPRINTF("EE Core: failed to create smbauth thread...\n");
249 GS_BGCOLOUR = 0x008080;
250 SleepThread();
253 /* start it */
254 ret = StartThread(smbauth_thread_id, NULL);
255 if (ret < 0) {
256 DPRINTF("EE Core: failed to start smbauth thread...\n");
257 GS_BGCOLOUR = 0x008080;
258 SleepThread();
261 /* install our DMA interrupt handler */
262 FlushCache(0);
263 *sifDmaDataPtr = 0;
265 if (_lw(DMAC_COMM_STAT) & STAT_SIF0)
266 _sw(STAT_SIF0, DMAC_COMM_STAT);
268 if (!(_lw(DMAC_SIF0_CHCR) & CHCR_STR))
269 SifSetDChain();
271 sif0_id = AddDmacHandler(5, _SifDmaIntrHandler, 0);
272 EnableDmac(5);