› Foros › PlayStation 3 › Scene
git clone git://git.fail0verflow.com/ps3tools.git
cp getsignkeys.patch ps3tools
cd ps3tools
patch -p1 < getsignkeys-1.0.patch
make
getsignkeys app1_para_342.self app2_para_342.self 342
diff --git a/Makefile b/Makefile
index 7f93061..c57e504 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-TOOLS = readself pupunpack unself unpkg sceverify
+TOOLS = readself pupunpack unself unpkg sceverify getsignkeys
TOOLS += makeself makepkg norunpack puppack
COMMON = tools.o aes.o sha1.o ec.o bn.o
DEPS = Makefile tools.h types.h
diff --git a/ec.c b/ec.c
index 2d35f6b..dfe70bd 100644
--- a/ec.c
+++ b/ec.c
@@ -1,4 +1,5 @@
// Copyright 2007,2008,2010 Segher Boessenkool <segher@kernel.crashing.org>
+// Shirokuroneko <shirokuroneko@gmail.com>
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
@@ -108,6 +109,7 @@ static int point_zero(struct point *p)
{
elt_zero(p->x);
elt_zero(p->y);
+ return 0;
}
static int point_is_zero(struct point *p)
@@ -347,3 +349,66 @@ void ecdsa_sign(u8 *hash, u8 *R, u8 *S)
{
generate_ecdsa(R, S, ec_k, hash);
}
+
+void ecdsa_generate_keys(const u8 *hash1, const u8 *sign1, const u8 *hash2, const u8 *sign2, const u8 *R, u8 *d, u8 *Q)
+{
+ u8 h1[21], h2[21];
+ u8 s1[21], s2[21];
+ u8 hDiff[21];
+ u8 sDiff[21];
+ u8 sDiffInv[21];
+ u8 k[21];
+ u8 ks[21];
+ u8 r[21];
+ u8 rInv[21];
+ struct point Qmon;
+
+ h1[0] = 0;
+ memcpy(h1 + 1, hash1, 20);
+ bn_reduce(h1, ec_N, 21);
+
+ h2[0] = 0;
+ memcpy(h2 + 1, hash2, 20);
+ bn_reduce(h2, ec_N, 21);
+
+ memcpy(s1, sign1, 21);
+ bn_reduce(s1, ec_N, 21);
+
+ memcpy(s2, sign2, 21);
+ bn_reduce(s2, ec_N, 21);
+
+ memcpy(r, R, 21);
+ bn_reduce(r, ec_N, 21);
+
+ // Calculate k = (h1 - h2) (s1 - s2)^-1 (mod n)
+ bn_sub(hDiff, h1, h2, ec_N, 21);
+ bn_sub(sDiff, s1, s2, ec_N, 21);
+
+ bn_to_mon(hDiff, ec_N, 21);
+ bn_to_mon(sDiff, ec_N, 21);
+ bn_mon_inv(sDiffInv, sDiff, ec_N, 21);
+
+ bn_mon_mul(k, hDiff, sDiffInv, ec_N, 21);
+ bn_from_mon(k, ec_N, 21);
+ bn_reduce(k, ec_N, 21);
+
+ // Calculate d = (k s1 - h1) r^-1 (mod n)
+ bn_to_mon(s1, ec_N, 21);
+ bn_to_mon(k, ec_N, 21);
+ bn_mon_mul(ks, k, s1, ec_N, 21);
+ bn_from_mon(ks, ec_N, 21);
+ bn_sub(ks, ks, h1, ec_N, 21);
+
+ bn_to_mon(ks, ec_N, 21);
+ bn_to_mon(r, ec_N, 21);
+ bn_mon_inv(rInv, r, ec_N, 21);
+
+ bn_mon_mul(d, ks, rInv, ec_N, 21);
+ bn_from_mon(d, ec_N, 21);
+ bn_reduce(d, ec_N, 21);
+
+ // Calculate Q = d G in the elliptic curve
+ point_mul(&Qmon, d, &ec_G);
+ point_from_mon(&Qmon);
+ memcpy(Q, &Qmon, 40);
+}
diff --git a/getsignkeys.c b/getsignkeys.c
new file mode 100644
index 0000000..6253b6a
--- /dev/null
+++ b/getsignkeys.c
@@ -0,0 +1,171 @@
+// Copyright 2010 Sven Peter <svenpeter@gmail.com>
+// Shirokuroneko <shirokuroneko@gmail.com>
+// Licensed under the terms of the GNU GPL, version 2
+// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+
+#include "tools.h"
+#include "types.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+static struct keylist *self_load_keys(u32 app_type, enum sce_key *id)
+{
+ switch (app_type) {
+ case 1:
+ *id = KEY_LV0;
+ break;
+ case 2:
+ *id = KEY_LV1;
+ break;
+ case 3:
+ *id = KEY_LV2;
+ break;
+ case 4:
+ *id = KEY_APP;
+ break;
+ case 5:
+ *id = KEY_ISO;
+ break;
+ case 6:
+ *id = KEY_LDR;
+ break;
+ default:
+ fail("invalid type: %08x", app_type);
+ }
+
+ return keys_get(*id);
+}
+
+static void decrypt(u8 *ptr, struct keylist *klist)
+{
+ int keyid = sce_decrypt_header(ptr, klist);
+
+ if (keyid < 0)
+ fail("sce_decrypt_header failed");
+
+ if (sce_decrypt_data(ptr) < 0)
+ fail("sce_decrypt_data failed");
+}
+
+static void get_signature_params(u8 *ptr, u8 *hash, u8 **r, u8 **s)
+{
+ u32 meta_offset = be32(ptr + 0x0c);
+ u64 sig_len = be64(ptr + meta_offset + 0x60);
+ *r = ptr + sig_len;
+ *s = *r + 21;
+
+ sha1(ptr, sig_len, hash);
+}
+
+static u32 get_app_type(u8 *ptr)
+{
+ u16 type = be16(ptr + 0x0a);
+ u32 app_type;
+
+ if (type == 1) {
+ u64 info_offset = be64(ptr + 0x28);
+ app_type = be32(ptr + info_offset + 0x0c);
+ }
+ else if(type == 3)
+ app_type = KEY_PKG;
+ else
+ fail("Unknown type: %d", type);
+
+ u16 flags = be16(ptr + 0x08);
+ if (flags & 0x8000)
+ fail("devkit file; invalid");
+
+ return app_type;
+}
+
+static void print_key(const u8 *key, u32 size)
+{
+ u32 i;
+ for (i=0; i<size; ++i)
+ printf("%02X", key[i]);
+}
+
+static int generate_keys(u8 *h1, u8 *s1, u8 *h2, u8 *s2, u8 *r, u8 *d, u8 *Q, u32 *ctype)
+{
+ // Try all 64 elliptic curves
+ int type;
+ u8 s_backup[21];
+ memcpy(s_backup, s1, 21);
+
+ for (type=0; type < 64; ++type) {
+ if (ecdsa_set_curve(type) < 0)
+ fail("ecdsa_set_curve failed");
+
+ ecdsa_generate_keys(h1, s1, h2, s2, r, d, Q);
+
+ ecdsa_set_pub(Q);
+
+ if (ecdsa_verify(h1, r, s1)) { // Modifies s1
+ printf("Keys found!\n");
+ printf("ctype: 0x%02X\n", type);
+ printf("d: "); print_key(d, 21); printf("\n");
+ printf("Q: "); print_key(Q, 20); printf(", "); print_key(Q + 20, 20); printf("\n");
+ *ctype = type;
+ return 0;
+ }
+
+ memcpy(s1, s_backup, 21);
+ }
+
+ return -1;
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc != 4)
+ fail("usage: getkeys file1.self file2.self key_suffix");
+
+ // Read app types of both files
+ u8 *file1 = mmap_file(argv[1]);
+ u8 *file2 = mmap_file(argv[2]);
+
+ u32 app_type_1 = get_app_type(file1);
+ u32 app_type_2 = get_app_type(file2);
+ if (app_type_1 != app_type_2)
+ fail("self files have different application type");
+
+ enum sce_key id;
+ struct keylist *klist = self_load_keys(app_type_1, &id);
+ if (klist == NULL)
+ fail("no key found");
+
+ // Calculate signature parameters for each file
+ u8 hash1[20], hash2[20];
+ u8 *r1, *s1, *r2, *s2;
+
+ decrypt(file1, klist);
+ get_signature_params(file1, hash1, &r1, &s1);
+
+ if (klist->n > 0) free(klist->keys);
+ free(klist);
+ klist = self_load_keys(app_type_1, &id);
+ if (klist == NULL)
+ fail("no key found");
+
+ decrypt(file2, klist);
+ get_signature_params(file2, hash2, &r2, &s2);
+
+ if (bn_compare(r1, r2, 21) != 0)
+ fail("signature r values are different");
+
+ // Generate keys mathematically
+ u8 d[21], Q[40];
+ u32 ctype;
+ if (generate_keys(hash1, s1, hash2, s2, r1, d, Q, &ctype) < 0)
+ fail("couldn't generate the key with the provided curves (check your self files)");
+
+ // Store generated keys in the key folder (~/.ps3/)
+ if (save_sign_keys(d, Q, ctype, id, argv[3]) < 0)
+ fail("error saving signing keys");
+
+ return 0;
+}
+
diff --git a/tools.c b/tools.c
index 8af22dc..931f180 100644
--- a/tools.c
+++ b/tools.c
@@ -1,5 +1,6 @@
// Copyright 2010 Sven Peter <svenpeter@gmail.com>
// Copyright 2007,2008,2010 Segher Boessenkool <segher@kernel.crashing.org>
+// Shirokuroneko <shirokuroneko@gmail.com>
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
@@ -726,3 +727,64 @@ int sce_encrypt_data(u8 *ptr)
{
return sce_decrypt_data(ptr);
}
+
+int key_write(const char *path, u32 len, const u8 *dst)
+{
+ FILE *fp = NULL;
+ int ret = -1;
+
+ fp = fopen(path, "wb");
+ if (fp == NULL)
+ goto fail;
+
+ if (fwrite(dst, len, 1, fp) != 1)
+ goto fail;
+
+ ret = 0;
+
+fail:
+ if (fp != NULL)
+ fclose(fp);
+
+ return ret;
+}
+
+int save_sign_keys(const u8 *d, const u8 *Q, u32 ctype, enum sce_key type, const char *suffix)
+{
+ char base[256];
+ char path[256];
+ DIR *dp;
+
+ const char *name = id2name(type, t_key2file, NULL);
+ if (name == NULL)
+ return -1;
+
+ if (key_build_path(base) < 0)
+ return -1;
+
+ dp = opendir(base);
+ if (dp == NULL)
+ return -1;
+
+ u32 ctype_be = be32((u8 *)&ctype);
+ snprintf(path, sizeof path, "%s/%s-ctype-%s", base, name, suffix);
+ if (key_write(path, 4, (u8 *) &ctype_be) == 0)
+ printf("Created %s\n", path);
+ else
+ printf("Error creating %s\n", path);
+
+ snprintf(path, sizeof path, "%s/%s-pub-%s", base, name, suffix);
+ if (key_write(path, 40, Q) == 0)
+ printf("Created %s\n", path);
+ else
+ printf("Error creating %s\n", path);
+
+ snprintf(path, sizeof path, "%s/%s-priv-%s", base, name, suffix);
+ if (key_write(path, 21, d) == 0)
+ printf("Created %s\n", path);
+ else
+ printf("Error creating %s\n", path);
+
+ return 0;
+}
+
diff --git a/tools.h b/tools.h
index b0ecb60..fb1c5b6 100644
--- a/tools.h
+++ b/tools.h
@@ -42,6 +42,8 @@ void sha1_hmac(u8 *key, u8 *data, u32 len, u8 *digest);
int key_get(enum sce_key type, const char *suffix, struct key *k);
int key_get_simple(const char *name, u8 *bfr, u32 len);
struct keylist *keys_get(enum sce_key type);
+int key_write(const char *path, u32 len, const u8 *dst);
+int save_sign_keys(const u8 *d, const u8 *Q, u32 ctype, enum sce_key type, const char *suffix);
int sce_decrypt_header(u8 *ptr, struct keylist *klist);
int sce_encrypt_header(u8 *ptr, struct key *k);
@@ -54,6 +56,7 @@ void ecdsa_set_pub(u8 *Q);
void ecdsa_set_priv(u8 *k);
int ecdsa_verify(u8 *hash, u8 *R, u8 *S);
void ecdsa_sign(u8 *hash, u8 *R, u8 *S);
+void ecdsa_generate_keys(const u8 *hash1, const u8 *sign1, const u8 *hash2, const u8 *sign2, const u8 *R, u8 *d, u8 *Q);
void bn_copy(u8 *d, u8 *a, u32 n);
int bn_compare(u8 *a, u8 *b, u32 n);