signature checking works on ST

master
George Hotz 2017-04-26 10:41:57 -07:00
parent 0550e87492
commit bdc3a05a93
6 changed files with 118 additions and 12 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
*.pyc
.*.swp
*.o
a.out

View File

@ -27,16 +27,16 @@ int main() {
// validate length
int len = _app_start[0];
if (len < 4) fail();
if (len < 8) fail();
// compute SHA hash
char digest[SHA_DIGEST_SIZE];
SHA_hash(&_app_start[1], len, digest);
SHA_hash(&_app_start[1], len-4, digest);
// verify RSA signature
/*if (!RSA_verify(&rsa_key, ((void*)&_app_start[1]) + len, 0x80, digest, SHA_DIGEST_SIZE)) {
if (!RSA_verify(&rsa_key, ((void*)&_app_start[0]) + len, RSANUMBYTES, digest, SHA_DIGEST_SIZE)) {
fail();
}*/
}
// jump to flash
((void(*)()) _app_start[1])();

View File

@ -37,7 +37,7 @@ obj/gitversion.h:
echo "const uint8_t gitversion[] = \"RELEASE\";" > $@
endif
obj/cert.h:
obj/cert.h: tools/getcertheader.py
./tools/getcertheader.py $(CERT) > $@
obj/bootstub.$(PROJ_NAME).o: bootstub.c early.h obj/cert.h

View File

@ -184,13 +184,33 @@ static const uint8_t sha_padding[RSANUMBYTES] = {
};
*/
static const uint8_t sha_padding_1024[RSANUMBYTES] = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00,
// 20 bytes of hash go here.
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
// SHA-1 of PKCS1.5 signature sha_padding for 2048 bit, as above.
// At the location of the bytes of the hash all 00 are hashed.
static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = {
/*static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = {
0xdc, 0xbd, 0xbe, 0x42, 0xd5, 0xf5, 0xa7, 0x2e,
0x6e, 0xfc, 0xf5, 0x5d, 0xaf, 0x9d, 0xea, 0x68,
0x7c, 0xfb, 0xf1, 0x67
};
};*/
// Verify a 2048-bit RSA PKCS1.5 signature against an expected hash.
// Both e=3 and e=65537 are supported. hash_len may be
@ -230,13 +250,24 @@ int RSA_verify(const RSAPublicKey *key,
modpow(key, buf); // In-place exponentiation.
#ifdef TEST_RSA
printf("sig\n");
for (i=0;i<len;i++) { if(i!=0 && i%0x10 == 0) printf("\n"); printf("%02X ", signature[i]); } printf("\n");
printf("hash\n");
for (i=0;i<hash_len;i++) { if(i!=0 && i%0x10 == 0) printf("\n"); printf("%02X ", hash[i]); } printf("\n");
printf("out\n");
for (i=0;i<RSANUMBYTES;i++) { if(i!=0 && i%0x10 == 0) printf("\n"); printf("%02X ", buf[i]); } printf("\n");
printf("target\n");
for (i=0;i<RSANUMBYTES;i++) { if(i!=0 && i%0x10 == 0) printf("\n"); printf("%02X ", sha_padding_1024[i]); } printf("\n");
#endif
// Xor sha portion, so it all becomes 00 iff equal.
for (i = len - hash_len; i < len; ++i) {
buf[i] ^= *hash++;
}
// Hash resulting buf, in-place.
switch (hash_len) {
/*switch (hash_len) {
case SHA_DIGEST_SIZE:
padding_hash = kExpectedPadShaRsa2048;
SHA_hash(buf, len, buf);
@ -245,11 +276,18 @@ int RSA_verify(const RSAPublicKey *key,
return 0;
}
// Compare against expected hash value.
for (i = 0; i < hash_len; ++i) {
if (buf[i] != padding_hash[i]) {
return 0;
}
}*/
for (i = 0; i < RSANUMBYTES; ++i) {
if (buf[i] != sha_padding_1024[i]) {
return 0;
}
}
return 1; // All checked out OK.

View File

@ -0,0 +1,35 @@
/*
gcc -DTEST_RSA test_rsa.c ../crypto/rsa.c ../crypto/sha.c && ./a.out
*/
#include <stdio.h>
#include <stdlib.h>
#define MAX_LEN 0x40000
char buf[MAX_LEN];
#include "../crypto/sha.h"
#include "../crypto/rsa.h"
#include "../obj/cert.h"
int main() {
FILE *f = fopen("../obj/panda.bin", "rb");
int tlen = fread(buf, 1, MAX_LEN, f);
fclose(f);
printf("read %d\n", tlen);
uint32_t *_app_start = (uint32_t *)buf;
int len = _app_start[0];
char digest[SHA_DIGEST_SIZE];
SHA_hash(&_app_start[1], len-4, digest);
printf("SHA hash done\n");
if (!RSA_verify(&rsa_key, ((void*)&_app_start[0]) + len, RSANUMBYTES, digest, SHA_DIGEST_SIZE)) {
printf("RSA fail\n");
} else {
printf("RSA match!!!\n");
}
return 0;
}

View File

@ -1,11 +1,43 @@
#!/usr/bin/env python
import sys
import struct
from Crypto.PublicKey import RSA
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m
def to_c_string(x):
mod = (hex(x)[2:-1].rjust(0x100, '0'))
hh = ''.join('\\x'+mod[i:i+2] for i in range(0, 0x100, 2))
return hh
def to_c_uint32(x):
nums = []
for i in range(0x20):
nums.append(x%(2**32))
x /= (2**32)
return "{"+'U,'.join(map(str, nums))+"U}"
rsa = RSA.importKey(open(sys.argv[1]).read())
mod = (hex(rsa.n)[2:-1].rjust(0x100, '0'))
hh = ''.join('\\x'+mod[i:i+2] for i in range(0, 0x100, 2))
print 'char rsa_mod[] = "'+hh+'";'
print 'int rsa_e = %d;' % rsa.e
rr = pow(2**1024, 2, rsa.n)
n0inv = 2**32 - modinv(rsa.n, 2**32)
print 'RSAPublicKey rsa_key = {.len = 0x20,'
print ' .n0inv = %dU,' % n0inv
print ' .n = %s,' % to_c_uint32(rsa.n)
print ' .rr = %s,' % to_c_uint32(rr)
print ' .exponent = %d,' % rsa.e
print '};'