1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
* Copyright (c) 2012 by naehrwert
* This file is released under the GPLv2.
*/

/*
* mode_auth_data (0x50 bytes) is stored in SC EEPROM @ 0x48D8E (should be all 0xFFs on any unit though).
* Full keyset not included for legal reasons. Even if it's blatantly insecure...
*/

#include <stdio.h>
#include <string.h>

#include "aes.h"
#include "sha1.h"

//Super secure AES keyset? Veeery nice.
u8 aes_key[0x20] = 
{
	0xFE, 0xDC, 0xBA, 0x98, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX,
	XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX
};

u8 aes_iv[0x10] = 
{
	0x01, 0x23, 0x45, 0x67, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX
};

//SHA-1 HMAC key.
u8 hmac_key[0x40] = 
{
	0x12, 0x3D, 0xA1, 0x4B, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX,
	XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX,
	XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX,
	XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX
};

//"Ryotaro is cute!" magic.
u8 ryotaro[0x10] = 
{
	0x52, 0x79, 0x6F, 0x74, 0x6, 0x72, 0x6F, 0x20, 0x69, 0x73, 0x20, 0x63, 0x75, 0x74, 0x65, 0x21
};

/*! Verify mode_auth_data (0x50 bytes). */
BOOL verify_mode_auth_data(u8 *data)
{
	u8 hmac[0x14];
	aes_context aes_ctxt;
	
	//Decrypt data.
	aes_setkey_enc(&aes_ctxt, aes_key, 0x100);
	aes_crypt_cbc(&aes_ctxt, AES_DECRYPT, 0x50, aes_iv, data, data);
	
	//Check SHA-1 HMAC.
	sha1_hmac(hmac_key, 0x40, data, 0x3C, hmac);
	if(memcmp(data + 0x3C, hmac, 0x14) != 0)
	{
		printf("Error: Failed to verify SHA-1 HMAC.\n");
		return FALSE;
	}
	
	//Check magic.
	if(memcmp(data + 0x04, ryotaro, 0x10) != 0)
	{
		printf("Error: Wrong magic bytes.\n");
		return FALSE;
	}
	
	return TRUE;
}