diff --git a/WiiQt/bn.cpp b/WiiQt/bn.cpp new file mode 100755 index 0000000..6056e62 --- /dev/null +++ b/WiiQt/bn.cpp @@ -0,0 +1,123 @@ +// Copyright 2007,2008 Segher Boessenkool +// Licensed under the terms of the GNU GPL, version 2 +// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt + +//#include +//#include + +#include "bn.h" +/* +static void bn_print(char *name, quint8 *a, quint32 n) +{ + quint32 i; + + printf("%s = ", name); + + for (i = 0; i < n; i++) + printf("%02x", a[i]); + + printf("\n"); +} +*/ +static void bn_zero(quint8 *d, quint32 n) +{ + memset(d, 0, n); +} + +static void bn_copy(quint8 *d, quint8 *a, quint32 n) +{ + memcpy(d, a, n); +} + +int bn_compare(quint8 *a, quint8 *b, quint32 n) +{ + quint32 i; + + for (i = 0; i < n; i++) { + if (a[i] < b[i]) + return -1; + if (a[i] > b[i]) + return 1; + } + + return 0; +} + +void bn_sub_modulus(quint8 *a, quint8 *N, quint32 n) +{ + quint32 i; + quint32 dig; + quint8 c; + + c = 0; + for (i = n - 1; i < n; i--) { + dig = N[i] + c; + c = (a[i] < dig); + a[i] -= dig; + } +} + +void bn_add(quint8 *d, quint8 *a, quint8 *b, quint8 *N, quint32 n) +{ + quint32 i; + quint32 dig; + quint8 c; + + c = 0; + for (i = n - 1; i < n; i--) { + dig = a[i] + b[i] + c; + c = (dig >= 0x100); + d[i] = dig; + } + + if (c) + bn_sub_modulus(d, N, n); + + if (bn_compare(d, N, n) >= 0) + bn_sub_modulus(d, N, n); +} + +void bn_mul(quint8 *d, quint8 *a, quint8 *b, quint8 *N, quint32 n) +{ + quint32 i; + quint8 mask; + + bn_zero(d, n); + + for (i = 0; i < n; i++) + for (mask = 0x80; mask != 0; mask >>= 1) { + bn_add(d, d, d, N, n); + if ((a[i] & mask) != 0) + bn_add(d, d, b, N, n); + } +} + +void bn_exp(quint8 *d, quint8 *a, quint8 *N, quint32 n, quint8 *e, quint32 en) +{ + quint8 t[512]; + quint32 i; + quint8 mask; + + bn_zero(d, n); + d[n-1] = 1; + for (i = 0; i < en; i++) + for (mask = 0x80; mask != 0; mask >>= 1) { + bn_mul(t, d, d, N, n); + if ((e[i] & mask) != 0) + bn_mul(d, t, a, N, n); + else + bn_copy(d, t, n); + } +} + +// only for prime N -- stupid but lazy, see if I care +void bn_inv(quint8 *d, quint8 *a, quint8 *N, quint32 n) +{ + quint8 t[512], s[512]; + + bn_copy(t, N, n); + bn_zero(s, n); + s[n-1] = 2; + bn_sub_modulus(t, s, n); + bn_exp(d, a, N, n, t, n); +} diff --git a/WiiQt/bn.h b/WiiQt/bn.h new file mode 100644 index 0000000..677e9da --- /dev/null +++ b/WiiQt/bn.h @@ -0,0 +1,11 @@ +#ifndef BN_H +#define BN_H +#include "includes.h" + +int bn_compare(quint8 *a, quint8 *b, quint32 n); +void bn_sub_modulus(quint8 *a, quint8 *N, quint32 n); +void bn_add(quint8 *d, quint8 *a, quint8 *b, quint8 *N, quint32 n); +void bn_mul(quint8 *d, quint8 *a, quint8 *b, quint8 *N, quint32 n); +void bn_exp(quint8 *d, quint8 *a, quint8 *N, quint32 n, quint8 *e, quint32 en); +void bn_inv(quint8 *d, quint8 *a, quint8 *N, quint32 n); +#endif // BN_H diff --git a/WiiQt/ec.cpp b/WiiQt/ec.cpp new file mode 100755 index 0000000..62c720f --- /dev/null +++ b/WiiQt/ec.cpp @@ -0,0 +1,451 @@ +// Copyright 2007,2008 Segher Boessenkool +// Licensed under the terms of the GNU GPL, version 2 +// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt + +//#include +//#include + +#include "tools.h" +#include "bn.h" +#include "sha1.h" + +// y**2 + x*y = x**3 + x + b +/*static quint8 ec_b[30] = { 0x00, 0x66, 0x64, 0x7e, 0xde, 0x6c, 0x33, 0x2c, 0x7f, 0x8c, 0x09, 0x23, 0xbb, 0x58, 0x21, + 0x3b, 0x33, 0x3b, 0x20, 0xe9, 0xce, 0x42, 0x81, 0xfe, 0x11, 0x5f, 0x7d, 0x8f, 0x90, 0xad }; +*/ +// order of the addition group of points +static quint8 ec_N[30] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0xe9, 0x74, 0xe7, 0x2f, 0x8a, 0x69, 0x22, 0x03, 0x1d, 0x26, 0x03, 0xcf, 0xe0, 0xd7 }; + +// base point +static quint8 ec_G[60] = { 0x00, 0xfa, 0xc9, 0xdf, 0xcb, 0xac, 0x83, 0x13, 0xbb, 0x21, 0x39, 0xf1, 0xbb, 0x75, 0x5f, + 0xef, 0x65, 0xbc, 0x39, 0x1f, 0x8b, 0x36, 0xf8, 0xf8, 0xeb, 0x73, 0x71, 0xfd, 0x55, 0x8b, + 0x01, 0x00, 0x6a, 0x08, 0xa4, 0x19, 0x03, 0x35, 0x06, 0x78, 0xe5, 0x85, 0x28, 0xbe, 0xbf, + 0x8a, 0x0b, 0xef, 0xf8, 0x67, 0xa7, 0xca, 0x36, 0x71, 0x6f, 0x7e, 0x01, 0xf8, 0x10, 0x52 }; +/* +static void elt_print(char *name, quint8 *a) +{ + quint32 i; + + printf("%s = ", name); + + for (i = 0; i < 30; i++) + printf("%02x", a[i]); + + printf("\n"); +} +*/ +static void elt_copy(quint8 *d, quint8 *a) +{ + memcpy(d, a, 30); +} + +static void elt_zero(quint8 *d) +{ + memset(d, 0, 30); +} + +static int elt_is_zero(quint8 *d) +{ + quint32 i; + + for (i = 0; i < 30; i++) + if (d[i] != 0) + return 0; + + return 1; +} + +static void elt_add(quint8 *d, quint8 *a, quint8 *b) +{ + quint32 i; + + for (i = 0; i < 30; i++) + d[i] = a[i] ^ b[i]; +} + +static void elt_mul_x(quint8 *d, quint8 *a) +{ + quint8 carry, x, y; + quint32 i; + + carry = a[0] & 1; + + x = 0; + for (i = 0; i < 29; i++) { + y = a[i + 1]; + d[i] = x ^ (y >> 7); + x = y << 1; + } + d[29] = x ^ carry; + + d[20] ^= carry << 2; +} + +static void elt_mul(quint8 *d, quint8 *a, quint8 *b) +{ + quint32 i, n; + quint8 mask; + + elt_zero(d); + + i = 0; + mask = 1; + for (n = 0; n < 233; n++) { + elt_mul_x(d, d); + + if ((a[i] & mask) != 0) + elt_add(d, d, b); + + mask >>= 1; + if (mask == 0) { + mask = 0x80; + i++; + } + } +} + +static const quint8 square[16] = { 0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15, 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 }; + +static void elt_square_to_wide(quint8 *d, quint8 *a) +{ + quint32 i; + + for (i = 0; i < 30; i++) { + d[2*i] = square[a[i] >> 4]; + d[2*i + 1] = square[a[i] & 15]; + } +} + +static void wide_reduce(quint8 *d) +{ + quint32 i; + quint8 x; + + for (i = 0; i < 30; i++) { + x = d[i]; + + d[i + 19] ^= x >> 7; + d[i + 20] ^= x << 1; + + d[i + 29] ^= x >> 1; + d[i + 30] ^= x << 7; + } + + x = d[30] & ~1; + + d[49] ^= x >> 7; + d[50] ^= x << 1; + + d[59] ^= x >> 1; + + d[30] &= 1; +} + +static void elt_square(quint8 *d, quint8 *a) +{ + quint8 wide[60]; + + elt_square_to_wide(wide, a); + wide_reduce(wide); + + elt_copy(d, wide + 30); +} + +static void itoh_tsujii(quint8 *d, quint8 *a, quint8 *b, quint32 j) +{ + quint8 t[30]; + + elt_copy(t, a); + while (j--) { + elt_square(d, t); + elt_copy(t, d); + } + + elt_mul(d, t, b); +} + +static void elt_inv(quint8 *d, quint8 *a) +{ + quint8 t[30]; + quint8 s[30]; + + itoh_tsujii(t, a, a, 1); + itoh_tsujii(s, t, a, 1); + itoh_tsujii(t, s, s, 3); + itoh_tsujii(s, t, a, 1); + itoh_tsujii(t, s, s, 7); + itoh_tsujii(s, t, t, 14); + itoh_tsujii(t, s, a, 1); + itoh_tsujii(s, t, t, 29); + itoh_tsujii(t, s, s, 58); + itoh_tsujii(s, t, t, 116); + elt_square(d, s); +} +/* +static int point_is_on_curve(quint8 *p) +{ + quint8 s[30], t[30]; + quint8 *x, *y; + + x = p; + y = p + 30; + + elt_square(t, x); + elt_mul(s, t, x); + + elt_add(s, s, t); + + elt_square(t, y); + elt_add(s, s, t); + + elt_mul(t, x, y); + elt_add(s, s, t); + + elt_add(s, s, ec_b); + + return elt_is_zero(s); +} +*/ +static int point_is_zero(quint8 *p) +{ + return elt_is_zero(p) && elt_is_zero(p + 30); +} + +static void point_double(quint8 *r, quint8 *p) +{ + quint8 s[30], t[30]; + quint8 *px, *py, *rx, *ry; + + px = p; + py = p + 30; + rx = r; + ry = r + 30; + + if (elt_is_zero(px)) { + elt_zero(rx); + elt_zero(ry); + + return; + } + + elt_inv(t, px); + elt_mul(s, py, t); + elt_add(s, s, px); + + elt_square(t, px); + + elt_square(rx, s); + elt_add(rx, rx, s); + rx[29] ^= 1; + + elt_mul(ry, s, rx); + elt_add(ry, ry, rx); + elt_add(ry, ry, t); +} + +static void point_add(quint8 *r, quint8 *p, quint8 *q) +{ + quint8 s[30], t[30], u[30]; + quint8 *px, *py, *qx, *qy, *rx, *ry; + + px = p; + py = p + 30; + qx = q; + qy = q + 30; + rx = r; + ry = r + 30; + + if (point_is_zero(p)) { + elt_copy(rx, qx); + elt_copy(ry, qy); + return; + } + + if (point_is_zero(q)) { + elt_copy(rx, px); + elt_copy(ry, py); + return; + } + + elt_add(u, px, qx); + + if (elt_is_zero(u)) { + elt_add(u, py, qy); + if (elt_is_zero(u)) + point_double(r, p); + else { + elt_zero(rx); + elt_zero(ry); + } + + return; + } + + elt_inv(t, u); + elt_add(u, py, qy); + elt_mul(s, t, u); + + elt_square(t, s); + elt_add(t, t, s); + elt_add(t, t, qx); + t[29] ^= 1; + + elt_mul(u, s, t); + elt_add(s, u, py); + elt_add(rx, t, px); + elt_add(ry, s, rx); +} + +static void point_mul(quint8 *d, quint8 *a, quint8 *b) // a is bignum +{ + quint32 i; + quint8 mask; + + elt_zero(d); + elt_zero(d + 30); + + for (i = 0; i < 30; i++) + for (mask = 0x80; mask != 0; mask >>= 1) { + point_double(d, d); + if ((a[i] & mask) != 0) + point_add(d, d, b); + } +} + +void generate_ecdsa(quint8 *R, quint8 *S, quint8 *k, quint8 *hash) +{ + quint8 e[30]; + quint8 kk[30]; + quint8 m[30]; + quint8 minv[30]; + quint8 mG[60]; + //FILE *fp; + + elt_zero(e); + memcpy(e + 10, hash, 20); + memset( &m, 0, sizeof( m ) ); + + QTime midnight( 0, 0, 0 ); + qsrand( midnight.secsTo( QTime::currentTime() ) ); + for( quint16 i = 0; i < 15; i++ ) + { + quint16 rn = qrand() % 0xffff; + memcpy( (char*)&m + ( i * 2 ), &rn, 2 ); + //qDebug() << "m:" << i; + //hexdump( (void*)&m, 30 ); + } + + + //fp = fopen("/dev/random", "rb"); + //if (fread(m, sizeof m, 1, fp) != 1) + //fatal("reading random"); + //fclose(fp); + m[0] = 0; + + // R = (mG).x + + point_mul(mG, m, ec_G); + elt_copy(R, mG); + if (bn_compare(R, ec_N, 30) >= 0) + bn_sub_modulus(R, ec_N, 30); + + // S = m**-1*(e + Rk) (mod N) + + elt_copy(kk, k); + if (bn_compare(kk, ec_N, 30) >= 0) + bn_sub_modulus(kk, ec_N, 30); + bn_mul(S, R, kk, ec_N, 30); + bn_add(kk, S, e, ec_N, 30); + bn_inv(minv, m, ec_N, 30); + bn_mul(S, minv, kk, ec_N, 30); +} + +int check_ecdsa(quint8 *Q, quint8 *R, quint8 *S, quint8 *hash) +{ + quint8 Sinv[30]; + quint8 e[30]; + quint8 w1[30], w2[30]; + quint8 r1[60], r2[60]; + + bn_inv(Sinv, S, ec_N, 30); + + elt_zero(e); + memcpy(e + 10, hash, 20); + + bn_mul(w1, e, Sinv, ec_N, 30); + bn_mul(w2, R, Sinv, ec_N, 30); + + point_mul(r1, w1, ec_G); + point_mul(r2, w2, Q); + + point_add(r1, r1, r2); + + if (bn_compare(r1, ec_N, 30) >= 0) + bn_sub_modulus(r1, ec_N, 30); + + return (bn_compare(r1, R, 30) == 0); +} + +void ec_priv_to_pub(quint8 *k, quint8 *Q) +{ + point_mul(Q, k, ec_G); +} + +int check_ec(quint8 *ng, quint8 *ap, quint8 *sig, quint8 *sig_hash) +{ + //qDebug() << QByteArray( (const char*)ng, 0x10 ).toHex(); + //qDebug() << QByteArray( (const char*)ap, 0x10 ).toHex(); + //qDebug() << QByteArray( (const char*)sig, 0x10 ).toHex(); + //qDebug() << QByteArray( (const char*)sig_hash, 0x10 ).toHex(); + quint8 ap_hash[20]; + quint8 *ng_Q, *ap_R, *ap_S; + quint8 *ap_Q, *sig_R, *sig_S; + + ng_Q = ng + 0x0108; + ap_R = ap + 0x04; + ap_S = ap + 0x22; + + + SHA1Context sha; + SHA1Reset( &sha ); + SHA1Input( &sha, (const unsigned char*)ap + 0x80, 0x100 ); + SHA1Result( &sha ); + + for( int i = 0; i < 5 ; i++ ) + { + quint32 part = qFromBigEndian( sha.Message_Digest[ i ] ); + memcpy( (char*)&ap_hash + ( i * 4 ), &part, 4 ); + } + ap_Q = ap + 0x0108; + sig_R = sig; + sig_S = sig + 30; + + return check_ecdsa(ng_Q, ap_R, ap_S, ap_hash) + && check_ecdsa(ap_Q, sig_R, sig_S, sig_hash); +} + +void make_ec_cert( quint8 *cert, quint8 *sig, char *signer, char *name, quint8 *priv, quint32 key_id ) +{ + //qDebug() << "make_ec_cert"; + memset( cert, 0, 0x180 ); + //qDebug() << "1"; + quint32 tmp = qFromBigEndian( (quint32)0x10002 ); + memcpy( (char*)cert, (const void*)&tmp, 4 ); + //qDebug() << "2"; + memcpy( cert + 4, sig, 60 ); + //qDebug() << "3"; + strcpy( (char*)cert + 0x80, signer ); + //qDebug() << "4"; + tmp = qFromBigEndian( (quint32)2 ); + memcpy( (char*)cert + 0xc0, (const void*)&tmp, 4 ); + //qDebug() << "5"; + //wbe32( cert + 0xc0, 2 ); + strcpy( (char*)cert + 0xc4, name ); + //qDebug() << "6"; + tmp = qFromBigEndian( key_id ); + memcpy( (char*)cert + 0x104, (const void*)&tmp, 4 ); + //qDebug() << "7"; + //wbe32( cert + 0x104, key_id ); + ec_priv_to_pub( priv, cert + 0x108 ); +} diff --git a/WiiQt/ec.h b/WiiQt/ec.h new file mode 100644 index 0000000..367346d --- /dev/null +++ b/WiiQt/ec.h @@ -0,0 +1,9 @@ +#ifndef EC_H +#define EC_H +#include "includes.h" + +int check_ec( quint8 *ng, quint8 *ap, quint8 *sig, quint8 *sig_hash ); +void make_ec_cert( quint8 *cert, quint8 *sig, char *signer, char *name, quint8 *priv, quint32 key_id ); +void generate_ecdsa( quint8 *R, quint8 *S, quint8 *k, quint8 *hash ); + +#endif // EC_H