Merge remote branch 'jevinskie/master'
[ps3tools.git] / sceverify.c
blobc88daeaa315984011e4a350cca9412126db728a3
1 // Copyright 2010 Sven Peter <svenpeter@gmail.com>
2 // Licensed under the terms of the GNU GPL, version 2
3 // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
5 #include "tools.h"
6 #include "types.h"
8 #include <stdio.h>
9 #include <string.h>
10 #include <assert.h>
11 #include <stdlib.h>
13 static u8 *ptr = NULL;
15 static u16 type;
16 static u16 flags;
17 static u32 meta_offset;
18 static u64 info_offset;
19 static u32 app_type;
20 static u64 filesize;
21 static u64 header_len;
22 static int did_fail = 0;
24 static struct keylist *klist = NULL;
26 static struct keylist *self_load_keys(void)
28 enum sce_key id;
30 switch (app_type) {
31 case 1:
32 id = KEY_LV0;
33 break;
34 case 2:
35 id = KEY_LV1;
36 break;
37 case 3:
38 id = KEY_LV2;
39 break;
40 case 4:
41 id = KEY_APP;
42 break;
43 case 5:
44 id = KEY_ISO;
45 break;
46 case 6:
47 id = KEY_LDR;
48 break;
49 default:
50 fail("invalid type: %08x", app_type);
53 return keys_get(id);
56 static void read_self_header(void)
58 flags = be16(ptr + 0x08);
59 meta_offset = be32(ptr + 0x0c);
60 header_len = be64(ptr + 0x10);
61 filesize = be64(ptr + 0x18);
62 info_offset = be64(ptr + 0x28);
64 app_type = be32(ptr + info_offset + 0x0c);
66 klist = self_load_keys();
69 static void read_pkg_header(void)
71 flags = be16(ptr + 0x08);
72 meta_offset = be32(ptr + 0x0c);
73 header_len = be64(ptr + 0x10);
74 filesize = be64(ptr + 0x18);
76 klist = keys_get(KEY_PKG);
79 static void read_spp_header(void)
81 flags = be16(ptr + 0x08);
82 meta_offset = be32(ptr + 0x0c);
83 header_len = be64(ptr + 0x10);
84 filesize = be64(ptr + 0x18);
86 klist = keys_get(KEY_SPP);
89 static void decrypt(void)
91 int keyid;
93 keyid = sce_decrypt_header(ptr, klist);
95 if (keyid < 0)
96 fail("sce_decrypt_header failed");
98 if (sce_decrypt_data(ptr) < 0)
99 fail("sce_decrypt_data failed");
101 if (klist->keys[keyid].pub_avail < 0)
102 fail("no public key available");
104 if (ecdsa_set_curve(klist->keys[keyid].ctype) < 0)
105 fail("ecdsa_set_curve failed");
107 ecdsa_set_pub(klist->keys[keyid].pub);
110 static void verify_signature(void)
112 u8 *r, *s;
113 u8 hash[20];
114 u64 sig_len;
116 sig_len = be64(ptr + meta_offset + 0x60);
117 r = ptr + sig_len;
118 s = r + 21;
120 sha1(ptr, sig_len, hash);
122 printf("Signature\n");
123 if (ecdsa_verify(hash, r, s))
124 printf(" Status: OK\n");
125 else
126 printf(" Status: FAIL\n");
128 printf("\n");
131 static int verify_hash(u8 *p, u8 *hashes)
133 u64 offset;
134 u64 size;
135 u64 id;
136 u8 *hash, *key;
137 u8 result[20];
139 offset = be64(p + 0x00);
140 size = be64(p + 0x08);
141 id = be32(p + 0x1c);
143 if (id == 0xffffffff)
144 return 0;
146 hash = hashes + id * 0x10;
147 key = hash + 0x20;
149 // XXX: possible integer overflow here
150 if (offset > (filesize + header_len))
151 return 1;
153 // XXX: possible integer overflow here
154 if ((offset + size) > (filesize + header_len))
155 return 1;
157 sha1_hmac(key, ptr + offset, size, result);
159 if (memcmp(result, hash, 20) == 0)
160 return 0;
161 else
162 return -1;
165 static void verify_hashes(void)
167 u32 meta_n_hdr;
168 u32 i;
169 u8 *hashes;
170 int res;
172 meta_n_hdr = be32(ptr + meta_offset + 0x60 + 0xc);
173 hashes = ptr + meta_offset + 0x80 + 0x30 * meta_n_hdr;
175 printf("Hashes\n");
177 for (i = 0; i < meta_n_hdr; i++) {
178 printf(" Section #%02d: ", i);
179 res = verify_hash(ptr + meta_offset + 0x80 + 0x30 * i, hashes);
180 if (res < 0) {
181 did_fail = 1;
182 printf("FAIL*\n");
183 } else if (res > 0) {
184 printf("???\n");
185 } else {
186 printf("OK\n");
190 printf("\n");
193 int main(int argc, char *argv[])
195 if (argc != 2)
196 fail("usage: sceverify filename");
198 ptr = mmap_file(argv[1]);
200 type = be16(ptr + 0x0a);
202 if (type == 1)
203 read_self_header();
204 else if(type == 3)
205 read_pkg_header();
206 else if(type == 4)
207 read_spp_header();
208 else
209 fail("Unknown type: %d", type);
211 if (flags & 0x8000)
212 fail("devkit file; nothing to verify");
214 if (klist == NULL)
215 fail("no key found");
217 decrypt();
218 verify_signature();
219 verify_hashes();
221 if (did_fail)
222 printf(" * please not that the hash will always fail for "
223 "unaligned non-LOAD phdrs\n");
224 return 0;