GetSignKeys- Genera claves de PS3

getsignkeys es una herramienta que permite generar automaticamente los archivos de firma ECDSA de PS3 e integrarlos en las ps3tools publicadas recientemente. La principal diferencia con la versión de AerialX, es que este genera la clave pública y el tipo de curva, validando la clave completa y almacenandola en su correspondiente archivo de claves en ~/.ps3/. Esas claves serán automáticamente accesibles desde las herramientas publicadas por fail0verflow, incluyendo la herramienta para firmar archivos self. Este programa es 100% libre de cualquier clave pública o privada de sony.

¿Que necesitas para hacerlo funcionar?
Ya que esta utilidad está proporcionada como un parche, clona el repositorio de ps3tools, aplica el parche y compilalo normalmente.

Código:
git clone git://git.fail0verflow.com/ps3tools.git
cp getsignkeys.patch ps3tools
cd ps3tools
patch -p1 < getsignkeys-1.0.patch
make


Este código debería crear una utilidad adicional llamada "getsignkeys". Ejemplo de uso:
Código:
getsignkeys app1_para_342.self app2_para_342.self 342


Si ha funcionado correctamente, creará los archivos "app-ctype-342", "app-pub-342" y "app-priv-342" en tu carpeta ~/.ps3/. El último parametro es el sufijo usado para la generación de las claves. Nota: Esta herramienta no está limitada solo a aplicaciones, funciona también con cualquier otro tipo (ldr, lv1, lv2, etc..), simplemente usando dos SELFs del mismo tipo y añadiendo la clave AES necesaria.

Ten en cuenta que necesitas la clave AES correspondiente en tu carpeta ~/.ps3/ para descifrar los archivos SELF. En el ejemplo anterior, debería haber algo parecido a "app-key-342" y "app-iv-342" en la carpeta. Estos archivos son fáciles de encontrar en la red. También necesitas el archivo "curves", que contiene el conjunto de posibles curvas elípticas a usar. Este archivo no contiene ningún tipo de clave pública o privada, por lo que no tiene por qué ser oculto.

Hemos detectado un problema en esta versión que esperamos que sea arreglado pronto en una nueva versión del programa. Hasta entonces, podrían haber situaciones en que la clave no se encuentre y la utilidad se queje por las curvas. Este problema no afecta a la calidad de las claves calculadas, todas ellas son verificadas antes de cualquier resultado.

Finalmente, esta aplicación ha sido diseñada para integrarse con las utilidades de fail0verflow

EDITO: He encontrado esto, creo que es el trabajo que hace
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);

salu2
Hola, gracias por la info, pero... donde esta el archivo getsignkeys.patch?
Dime donde conseguirlo y hacemos una prueba rapida de un helloworld.
Un saludo.
no lo he encontrado pero lo que he puesto abajo es lo que sale al hacer la prueba
2 respuestas