Skip to content

Commit

Permalink
signature checking works on ST
Browse files Browse the repository at this point in the history
  • Loading branch information
geohot committed Apr 26, 2017
1 parent 0550e87 commit bdc3a05
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*.pyc
.*.swp
*.o
a.out

8 changes: 4 additions & 4 deletions board/bootstub.c
Original file line number Diff line number Diff line change
Expand Up @@ -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])();
Expand Down
2 changes: 1 addition & 1 deletion board/build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 41 additions & 3 deletions board/crypto/rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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.
Expand Down
35 changes: 35 additions & 0 deletions board/tests/test_rsa.c
Original file line number Diff line number Diff line change
@@ -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;
}

40 changes: 36 additions & 4 deletions board/tools/getcertheader.py
Original file line number Diff line number Diff line change
@@ -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 '};'


0 comments on commit bdc3a05

Please sign in to comment.