Add COPYING file
[ps3tools.git] / scekrit.c
blobec46c2ef297955bba1666b4613d391063075c239
1 // SCEkrit.c (v1.01): Compute Sony's Private Keys
2 // Based on Sven's sceverify.c
3 // -------------------------------------------------------------
4 // Compile by copying to fail0verflow's ps3tools and add
5 // SCEkrit.c to TOOLS in the Makefile.
6 // Run with two files (selfs, pkgs) signed by the same key.
7 // Depends on libgmp; add -lgmp to LDFLAGS
8 // - Aaron Lindsay / @AerialX
9 // And thanks gbcft!
11 // Copyright 2010 Sven Peter <svenpeter@gmail.com>
12 // Licensed under the terms of the GNU GPL, version 2
13 // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
15 #include "tools.h"
16 #include "types.h"
18 #include <stdio.h>
19 #include <string.h>
20 #include <assert.h>
21 #include <stdlib.h>
22 #include <gmp.h>
24 static int keyid = -1;
26 static u8 *ptr1 = NULL;
27 static u8 *ptr2 = NULL;
29 static u16 type;
30 typedef struct {
31 u16 flags;
32 u32 meta_offset;
33 u64 info_offset;
34 u32 app_type;
35 u64 filesize;
36 u64 header_len;
37 } fileinfo;
39 static fileinfo info1;
40 static fileinfo info2;
42 static struct keylist *klist = NULL;
44 static struct keylist *self_load_keys(fileinfo* info)
46 enum sce_key id;
48 switch (info->app_type) {
49 case 1:
50 id = KEY_LV0;
51 break;
52 case 2:
53 id = KEY_LV1;
54 break;
55 case 3:
56 id = KEY_LV2;
57 break;
58 case 4:
59 id = KEY_APP;
60 break;
61 case 5:
62 id = KEY_ISO;
63 break;
64 case 6:
65 id = KEY_LDR;
66 break;
67 default:
68 fail("invalid type: %08x", info->app_type);
71 return keys_get(id);
74 static void read_self_header(u8* ptr, fileinfo* info)
76 info->flags = be16(ptr + 0x08);
77 info->meta_offset = be32(ptr + 0x0c);
78 info->header_len = be64(ptr + 0x10);
79 info->filesize = be64(ptr + 0x18);
80 info->info_offset = be64(ptr + 0x28);
82 info->app_type = be32(ptr + info->info_offset + 0x0c);
84 klist = self_load_keys(info);
87 static void read_pkg_header(u8* ptr, fileinfo* info)
89 info->flags = be16(ptr + 0x08);
90 info->meta_offset = be32(ptr + 0x0c);
91 info->header_len = be64(ptr + 0x10);
92 info->filesize = be64(ptr + 0x18);
94 klist = keys_get(KEY_PKG);
97 static void decrypt(u8* ptr)
99 if (keyid < 0)
100 keyid = sce_decrypt_header(ptr, klist);
101 else if (keyid != sce_decrypt_header(ptr, klist))
102 fail("Both files must have the same key id");
104 if (keyid < 0)
105 fail("sce_decrypt_header failed");
107 if (sce_decrypt_data(ptr) < 0)
108 fail("sce_decrypt_data failed");
110 if (klist->keys[keyid].pub_avail < 0)
111 fail("no public key available");
113 if (ecdsa_set_curve(klist->keys[keyid].ctype) < 0)
114 fail("ecdsa_set_curve failed");
116 ecdsa_set_pub(klist->keys[keyid].pub);
119 static void verify_signature(u8* ptr, fileinfo* info, u8* hash, u8** s, u8** r)
121 u64 sig_len;
123 sig_len = be64(ptr + info->meta_offset + 0x60);
124 *r = ptr + sig_len;
125 *s = *r + 21;
127 sha1(ptr, sig_len, hash);
129 printf("Signature\n");
130 if (ecdsa_verify(hash, *r, *s))
131 printf(" Status: OK\n");
132 else
133 printf(" Status: FAIL\n");
136 static void load_num(mpz_t n, u8* un)
138 char buffer[0x100];
139 char* ptr = buffer;
140 int i;
141 for (i = 0; i < 21; i++) {
142 sprintf(ptr, "%02x", un[i]);
143 ptr += 2;
145 mpz_set_str(n, buffer, 16);
148 static char* calculate_private_key(u8* us1, u8* us2, u8* uz1, u8* uz2, u8* un, u8* ur)
150 mpz_t s1, s2, z1, z2, n, r, k, dA;
151 mpz_init(s1); mpz_init(s2); mpz_init(z1); mpz_init(z2); mpz_init(n); mpz_init(r); mpz_init(k); mpz_init(dA);
152 load_num(s1, us1); load_num(s2, us2); load_num(z1, uz1); load_num(z2, uz2); load_num(n, un); load_num(r, ur);
154 mpz_sub(z2, z1, z2);
155 mpz_sub(s2, s1, s2);
156 mpz_invert(s2, s2, n);
157 mpz_mul(k, z2, s2);
158 mpz_mod(k, k, n);
160 mpz_mul(s2, s1, k);
161 mpz_sub(s2, s2, z1);
162 mpz_invert(r, r, n);
163 mpz_mul(dA, s2, r);
164 mpz_mod(dA, dA, n);
166 // printf("k: %s\n", mpz_get_str(NULL, 16, k));
167 return mpz_get_str(NULL, 16, dA);
170 int main(int argc, char *argv[])
172 if (argc != 3)
173 fail("usage: scesekrit signedfile1 signedfile2");
175 ptr1 = mmap_file(argv[1]);
176 ptr2 = mmap_file(argv[2]);
178 type = be16(ptr1 + 0x0a);
179 if (type != be16(ptr2 + 0x0a))
180 fail("Files must be the same type");
182 if (type == 1) {
183 read_self_header(ptr1, &info1);
184 } else if(type == 3) {
185 read_pkg_header(ptr1, &info1);
186 } else
187 fail("Unknown type: %d", type);
189 if ((info1.flags) & 0x8000)
190 fail("devkit file; nothing to verify");
192 if (klist == NULL)
193 fail("no key found");
195 decrypt(ptr1);
197 if (type == 1) {
198 read_self_header(ptr2, &info2);
199 } else if(type == 3) {
200 read_pkg_header(ptr2, &info2);
201 } else
202 fail("Unknown type: %d", type);
204 if ((info2.flags) & 0x8000)
205 fail("devkit file; nothing to verify");
207 if (klist == NULL)
208 fail("no key found");
210 decrypt(ptr2);
212 u8* s1;
213 u8* s2;
214 u8 z1[21];
215 u8 z2[21];
216 u8* r1;
217 u8* r2;
218 u8 ec[21];
219 u8 n[21];
220 z1[0] = 0;
221 z2[0] = 0;
223 ecdsa_get_params(klist->keys[keyid].ctype, ec, ec, ec, n, ec, ec);
225 printf("%s ", argv[1]);
226 verify_signature(ptr1, &info1, z1 + 1, &s1, &r1);
227 printf("%s ", argv[2]);
228 verify_signature(ptr2, &info2, z2 + 1, &s2, &r2);
230 if (memcmp(r1, r2, 21))
231 fail("Both files must share the same r signature value.");
233 const char* dA = calculate_private_key(s1, s2, z1, z2, n, r1);
235 int len = strlen(dA);
236 int i;
237 printf("Private Key: ");
238 for (i = len / 2; i < 21; i++)
239 printf("00");
240 printf("%s\n", dA);
242 return 0;