diff --git a/.gitignore b/.gitignore index 6454b95..3634d48 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.pyc .*.swp *.o +a.out diff --git a/board/bootstub.c b/board/bootstub.c index ba4eb29..12195bb 100644 --- a/board/bootstub.c +++ b/board/bootstub.c @@ -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])(); diff --git a/board/build.mk b/board/build.mk index 13b466d..c9c7a08 100644 --- a/board/build.mk +++ b/board/build.mk @@ -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 diff --git a/board/crypto/rsa.c b/board/crypto/rsa.c index e4d9436..f98ba64 100644 --- a/board/crypto/rsa.c +++ b/board/crypto/rsa.c @@ -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 +#include + +#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; +} + diff --git a/board/tools/getcertheader.py b/board/tools/getcertheader.py index 94bb0c7..15d63a8 100755 --- a/board/tools/getcertheader.py +++ b/board/tools/getcertheader.py @@ -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 '};'