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
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
24 static int keyid
= -1;
26 static u8
*ptr1
= NULL
;
27 static u8
*ptr2
= NULL
;
39 static fileinfo info1
;
40 static fileinfo info2
;
42 static struct keylist
*klist
= NULL
;
44 static struct keylist
*self_load_keys(fileinfo
* info
)
48 switch (info
->app_type
) {
68 fail("invalid type: %08x", info
->app_type
);
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
)
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");
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
)
123 sig_len
= be64(ptr
+ info
->meta_offset
+ 0x60);
127 sha1(ptr
, sig_len
, hash
);
129 printf("Signature\n");
130 if (ecdsa_verify(hash
, *r
, *s
))
131 printf(" Status: OK\n");
133 printf(" Status: FAIL\n");
136 static void load_num(mpz_t n
, u8
* un
)
141 for (i
= 0; i
< 21; i
++) {
142 sprintf(ptr
, "%02x", un
[i
]);
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
);
156 mpz_invert(s2
, s2
, 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
[])
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");
183 read_self_header(ptr1
, &info1
);
184 } else if(type
== 3) {
185 read_pkg_header(ptr1
, &info1
);
187 fail("Unknown type: %d", type
);
189 if ((info1
.flags
) & 0x8000)
190 fail("devkit file; nothing to verify");
193 fail("no key found");
198 read_self_header(ptr2
, &info2
);
199 } else if(type
== 3) {
200 read_pkg_header(ptr2
, &info2
);
202 fail("Unknown type: %d", type
);
204 if ((info2
.flags
) & 0x8000)
205 fail("devkit file; nothing to verify");
208 fail("no key found");
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
);
237 printf("Private Key: ");
238 for (i
= len
/ 2; i
< 21; i
++)