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.
19 #define DMA_ADDR 0x000cff00
20 #define UNCACHEDSEG(vaddr) (0x20000000 | vaddr)
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
42 u8 PrimaryDomainServerName
[32];
44 int SecurityMode
; // 0 = share level, 1 = user level
45 int PasswordType
; // 0 = PlainText passwords, 1 = use challenge/response
47 u8 Password
[48]; // either PlainText, either hashed
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"};
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
)
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];
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];
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
);
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)
158 else if (*PasswordLen
== 0)
160 memcpy(Buffer
, Password
, *PasswordLen
);
165 * _smbauth_thread: main SMB authentification thread
167 static int _smbauth_thread(void *args
)
169 SifDmaTransfer_t dmat
;
172 /* the thread sleep down until it's awaken up by our DMA interrupt handler */
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 */
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
;
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 */
207 * _SifDmaIntrHandler: our DMA interrupt handler
209 int _SifDmaIntrHandler()
213 flag
= *sifDmaDataPtr
;
218 /* Wake Up our SMB auth thread */
219 iWakeupThread(smbauth_thread_id
);
223 __asm__
__volatile__(
232 * start_smbauth_thread: used to start the EE SMB auth thread
234 void start_smbauth_thread(void)
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;
254 ret
= StartThread(smbauth_thread_id
, NULL
);
256 DPRINTF("EE Core: failed to start smbauth thread...\n");
257 GS_BGCOLOUR
= 0x008080;
261 /* install our DMA interrupt handler */
265 if (_lw(DMAC_COMM_STAT
) & STAT_SIF0
)
266 _sw(STAT_SIF0
, DMAC_COMM_STAT
);
268 if (!(_lw(DMAC_SIF0_CHCR
) & CHCR_STR
))
271 sif0_id
= AddDmacHandler(5, _SifDmaIntrHandler
, 0);