Initial commit

This commit is contained in:
Hector Martin
2016-11-23 14:35:12 +09:00
commit 5b1c4f85b6
296 changed files with 39925 additions and 0 deletions

335
pywii/Common/Struct.py Normal file
View File

@@ -0,0 +1,335 @@
import struct, sys
class StructType(tuple):
def __getitem__(self, value):
return [self] * value
def __call__(self, value, endian='<'):
if isinstance(value, str):
return struct.unpack(endian + tuple.__getitem__(self, 0), value[:tuple.__getitem__(self, 1)])[0]
else:
return struct.pack(endian + tuple.__getitem__(self, 0), value)
class StructException(Exception):
pass
class Struct(object):
__slots__ = ('__attrs__', '__baked__', '__defs__', '__endian__', '__next__', '__sizes__', '__values__')
int8 = StructType(('b', 1))
uint8 = StructType(('B', 1))
int16 = StructType(('h', 2))
uint16 = StructType(('H', 2))
int32 = StructType(('l', 4))
uint32 = StructType(('L', 4))
int64 = StructType(('q', 8))
uint64 = StructType(('Q', 8))
float = StructType(('f', 4))
@classmethod
def string(cls, len, offset=0, encoding=None, stripNulls=False, value=''):
return StructType(('string', (len, offset, encoding, stripNulls, value)))
LE = '<'
BE = '>'
__endian__ = '<'
def __init__(self, func=None, unpack=None, **kwargs):
self.__defs__ = []
self.__sizes__ = []
self.__attrs__ = []
self.__values__ = {}
self.__next__ = True
self.__baked__ = False
if func == None:
self.__format__()
else:
sys.settrace(self.__trace__)
func()
for name in func.func_code.co_varnames:
value = self.__frame__.f_locals[name]
self.__setattr__(name, value)
self.__baked__ = True
if unpack != None:
if isinstance(unpack, tuple):
self.unpack(*unpack)
else:
self.unpack(unpack)
if len(kwargs):
for name in kwargs:
self.__values__[name] = kwargs[name]
def __trace__(self, frame, event, arg):
self.__frame__ = frame
sys.settrace(None)
def __setattr__(self, name, value):
if name in self.__slots__:
return object.__setattr__(self, name, value)
if self.__baked__ == False:
if not isinstance(value, list):
value = [value]
attrname = name
else:
attrname = '*' + name
self.__values__[name] = None
for sub in value:
if isinstance(sub, Struct):
sub = sub.__class__
try:
if issubclass(sub, Struct):
sub = ('struct', sub)
except TypeError:
pass
type_, size = tuple(sub)
if type_ == 'string':
self.__defs__.append(Struct.string)
self.__sizes__.append(size)
self.__attrs__.append(attrname)
self.__next__ = True
if attrname[0] != '*':
self.__values__[name] = size[3]
elif self.__values__[name] == None:
self.__values__[name] = [size[3] for val in value]
elif type_ == 'struct':
self.__defs__.append(Struct)
self.__sizes__.append(size)
self.__attrs__.append(attrname)
self.__next__ = True
if attrname[0] != '*':
self.__values__[name] = size()
elif self.__values__[name] == None:
self.__values__[name] = [size() for val in value]
else:
if self.__next__:
self.__defs__.append('')
self.__sizes__.append(0)
self.__attrs__.append([])
self.__next__ = False
self.__defs__[-1] += type_
self.__sizes__[-1] += size
self.__attrs__[-1].append(attrname)
if attrname[0] != '*':
self.__values__[name] = 0
elif self.__values__[name] == None:
self.__values__[name] = [0 for val in value]
else:
try:
self.__values__[name] = value
except KeyError:
raise AttributeError(name)
def __getattr__(self, name):
if self.__baked__ == False:
return name
else:
try:
return self.__values__[name]
except KeyError:
raise AttributeError(name)
def __len__(self):
ret = 0
arraypos, arrayname = None, None
for i in range(len(self.__defs__)):
sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i]
if sdef == Struct.string:
size, offset, encoding, stripNulls, value = size
if isinstance(size, str):
size = self.__values__[size] + offset
elif sdef == Struct:
if attrs[0] == '*':
if arrayname != attrs:
arrayname = attrs
arraypos = 0
size = len(self.__values__[attrs[1:]][arraypos])
size = len(self.__values__[attrs])
ret += size
return ret
def unpack(self, data, pos=0):
for name in self.__values__:
if not isinstance(self.__values__[name], Struct):
self.__values__[name] = None
elif self.__values__[name].__class__ == list and len(self.__values__[name]) != 0:
if not isinstance(self.__values__[name][0], Struct):
self.__values__[name] = None
arraypos, arrayname = None, None
for i in range(len(self.__defs__)):
sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i]
if sdef == Struct.string:
size, offset, encoding, stripNulls, value = size
if isinstance(size, str):
size = self.__values__[size] + offset
temp = data[pos:pos+size]
if len(temp) != size:
raise StructException('Expected %i byte string, got %i' % (size, len(temp)))
if encoding != None:
temp = temp.decode(encoding)
if stripNulls:
temp = temp.rstrip('\0')
if attrs[0] == '*':
name = attrs[1:]
if self.__values__[name] == None:
self.__values__[name] = []
self.__values__[name].append(temp)
else:
self.__values__[attrs] = temp
pos += size
elif sdef == Struct:
if attrs[0] == '*':
if arrayname != attrs:
arrayname = attrs
arraypos = 0
name = attrs[1:]
self.__values__[attrs][arraypos].unpack(data, pos)
pos += len(self.__values__[attrs][arraypos])
arraypos += 1
else:
self.__values__[attrs].unpack(data, pos)
pos += len(self.__values__[attrs])
else:
values = struct.unpack(self.__endian__+sdef, data[pos:pos+size])
pos += size
j = 0
for name in attrs:
if name[0] == '*':
name = name[1:]
if self.__values__[name] == None:
self.__values__[name] = []
self.__values__[name].append(values[j])
else:
self.__values__[name] = values[j]
j += 1
return self
def pack(self):
arraypos, arrayname = None, None
ret = ''
for i in range(len(self.__defs__)):
sdef, size, attrs = self.__defs__[i], self.__sizes__[i], self.__attrs__[i]
if sdef == Struct.string:
size, offset, encoding, stripNulls, value = size
if isinstance(size, str):
size = self.__values__[size]+offset
if attrs[0] == '*':
if arrayname != attrs:
arraypos = 0
arrayname = attrs
temp = self.__values__[attrs[1:]][arraypos]
arraypos += 1
else:
temp = self.__values__[attrs]
if encoding != None:
temp = temp.encode(encoding)
temp = temp[:size]
ret += temp + ('\0' * (size - len(temp)))
elif sdef == Struct:
if attrs[0] == '*':
if arrayname != attrs:
arraypos = 0
arrayname = attrs
ret += self.__values__[attrs[1:]][arraypos].pack()
arraypos += 1
else:
ret += self.__values__[attrs].pack()
else:
values = []
for name in attrs:
if name[0] == '*':
if arrayname != name:
arraypos = 0
arrayname = name
values.append(self.__values__[name[1:]][arraypos])
arraypos += 1
else:
values.append(self.__values__[name])
ret += struct.pack(self.__endian__+sdef, *values)
return ret
def __getitem__(self, value):
return [('struct', self.__class__)] * value
if __name__=='__main__':
class TestStruct(Struct):
__endian__ = Struct.LE
def __format__(self):
self.foo, self.bar = Struct.uint32, Struct.float
self.baz = Struct.string(8)
self.omg = Struct.uint32
self.wtf = Struct.string(self.omg)
class HaxStruct(Struct):
__endian__ = Struct.LE
def __format__(self):
self.thing1 = Struct.uint32
self.thing2 = Struct.uint32
self.hax = HaxStruct
test = TestStruct()
test.unpack('\xEF\xBE\xAD\xDE\x00\x00\x80\x3Fdeadbeef\x04\x00\x00\x00test\xCA\xFE\xBA\xBE\xBE\xBA\xFE\xCA')
assert test.foo == 0xDEADBEEF
assert test.bar == 1.0
assert test.baz == 'deadbeef'
assert test.omg == 4
assert test.wtf == 'test'
assert test.hax.thing1 == 0xBEBAFECA
assert test.hax.thing2 == 0xCAFEBABE
print 'Tests successful'
"""
@Struct.LE
def TestStruct():
foo, bar = Struct.uint32, Struct.float
baz = Struct.string(8)
omg = Struct.uint32
wtf = Struct.string(omg)
@Struct.LE
def HaxStruct():
thing1 = Struct.uint32
thing2 = Struct.uint32
hax = HaxStruct()
test = TestStruct()
test.foo = 0xCAFEBABE
test.bar = 0.0
thing = test.hax.thing1
test.hax.thing1 = test.hax.thing2
test.hax.thing2 = thing
assert test.pack() == '\xBE\xBA\xFE\xCA\0\0\0\0deadbeef\x04\x00\x00\x00test\xBE\xBA\xFE\xCA\xCA\xFE\xBA\xBE'
"""

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env python
from wii import *

367
pywii/Common/pywii/ec.py Normal file
View File

@@ -0,0 +1,367 @@
#!/usr/bin/python
# Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org>
# Copyright 2008 Hector Martin <marcan@marcansoft.com>
# Licensed under the terms of the GNU GPL, version 2
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
from array import array
from struct import pack, unpack
from Crypto.Util.number import bytes_to_long, long_to_bytes
# y**2 + x*y = x**3 + x + b
ec_b = "\x00\x66\x64\x7e\xde\x6c\x33\x2c\x7f\x8c\x09\x23\xbb\x58\x21"+\
"\x3b\x33\x3b\x20\xe9\xce\x42\x81\xfe\x11\x5f\x7d\x8f\x90\xad"
def hexdump(s,sep=""):
return sep.join(map(lambda x: "%02x"%ord(x),s))
def bhex(s,sep=""):
return hexdump(long_to_bytes(s,30),sep)
fastelt = False
try:
import _ec
fastelt = True
except ImportError:
#print "C Elliptic Curve functions not available. EC certificate checking will be much slower."
pass
class ByteArray(array):
def __new__(cls, initializer=None):
return super(ByteArray, cls) .__new__(cls,'B',initializer)
def __init__(self,initializer=None):
array.__init__(self)
def __setitem__(self,item,value):
if isinstance(item, slice):
array.__setitem__(self, item, [x & 0xFF for x in value])
else:
array.__setitem__(self, item, value & 0xFF)
def __long__(self):
return bytes_to_long(self.tostring())
def __str__(self):
return ''.join(["%02x"%ord(x) for x in self.tostring()])
def __repr__(self):
return "ByteArray('%s')"%''.join(["\\x%02x"%ord(x) for x in self.tostring()])
class ELT_PY:
SIZEBITS=233
SIZE=(SIZEBITS+7)/8
square = ByteArray("\x00\x01\x04\x05\x10\x11\x14\x15\x40\x41\x44\x45\x50\x51\x54\x55")
def __init__(self, initializer=None):
if isinstance(initializer, long) or isinstance(initializer, int):
self.d = ByteArray(long_to_bytes(initializer,self.SIZE))
elif isinstance(initializer, str):
self.d = ByteArray(initializer)
elif isinstance(initializer, ByteArray):
self.d = ByteArray(initializer)
elif isinstance(initializer, array):
self.d = ByteArray(initializer)
elif isinstance(initializer, ELT):
self.d = ByteArray(initializer.d)
elif initializer is None:
self.d = ByteArray([0]*self.SIZE)
else:
raise TypeError("Invalid initializer type")
if len(self.d) != self.SIZE:
raise ValueError("ELT size must be 30")
def __cmp__(self, other):
if other == 0: #exception
if self:
return 1
else:
return 0
if not isinstance(other,ELT):
return NotImplemented
return cmp(self.d,other.d)
def __long__(self):
return long(self.d)
def __repr__(self):
return repr(self.d).replace("ByteArray","ELT")
def __str__(self):
return str(self.d)
def __nonzero__(self):
for x in self.d:
if x != 0:
return True
return False
def __len__(self):
return self.SIZE
def __add__(self,other):
if not isinstance(other,ELT):
return NotImplemented
new = ELT(self)
for x in range(self.SIZE):
new[x] ^= other[x]
return new
def _mul_x(self):
carry = self[0]&1
x = 0
d = ELT()
for i in range(self.SIZE-1):
y = self[i + 1]
d[i] = x ^ (y >> 7)
x = y << 1
d[29] = x ^ carry
d[20] ^= carry << 2
return d
def __mul__(self,other):
if not isinstance(other,ELT):
return NotImplemented
d = ELT()
i = 0
mask = 1
for n in range(self.SIZEBITS):
d = d._mul_x()
if (self[i] & mask) != 0:
d += other
mask >>= 1
if mask == 0:
mask = 0x80
i+=1
return d
def __pow__(self,other):
if other == -1:
return 1/self
if other < 1:
return NotImplemented
if other % 2 == 0:
return self._square()**(other/2)
x = self
for i in range(other-1):
x *= self
return x
def _square(self):
wide = ByteArray([0]*self.SIZE*2)
for i in range(self.SIZE):
wide[2*i] = self.square[self[i] >> 4]
wide[2*i + 1] = self.square[self[i] & 0xf]
for i in range(self.SIZE):
x = wide[i]
wide[i + 19] ^= x >> 7;
wide[i + 20] ^= x << 1;
wide[i + 29] ^= x >> 1;
wide[i + 30] ^= x << 7;
x = wide[30] & 0xFE;
wide[49] ^= x >> 7;
wide[50] ^= x << 1;
wide[59] ^= x >> 1;
wide[30] &= 1;
return ELT(wide[self.SIZE:])
def _itoh_tsujii(self,b,j):
t = ELT(self)
return t**(2**j) * b
def __rdiv__(self,other):
if isinstance(other,ELT):
return 1/self * other
elif other == 1:
t = self._itoh_tsujii(self, 1)
s = t._itoh_tsujii(self, 1)
t = s._itoh_tsujii(s, 3)
s = t._itoh_tsujii(self, 1)
t = s._itoh_tsujii(s, 7)
s = t._itoh_tsujii(t, 14)
t = s._itoh_tsujii(self, 1)
s = t._itoh_tsujii(t, 29)
t = s._itoh_tsujii(s, 58)
s = t._itoh_tsujii(t, 116)
return s**2
else:
return NotImplemented
def __getitem__(self,item):
return self.d[item]
def __setitem__(self,item,value):
self.d[item] = value
def tobignum(self):
return bytes_to_long(self.d.tostring())
def tobytes(self):
return self.d.tostring()
class ELT_C(ELT_PY):
def __mul__(self,other):
if not isinstance(other,ELT):
return NotImplemented
return ELT(_ec.elt_mul(self.d.tostring(),other.d.tostring()))
def __rdiv__(self,other):
if other != 1:
return ELT_PY.__rdiv__(self,other)
return ELT(_ec.elt_inv(self.d.tostring()))
def _square(self):
return ELT(_ec.elt_square(self.d.tostring()))
if fastelt:
ELT = ELT_C
else:
ELT = ELT_PY
class Point:
def __init__(self,x,y=None):
if isinstance(x,str) and (y is None) and (len(x) == 60):
self.x = ELT(x[:30])
self.y = ELT(x[30:])
elif isinstance(x,Point):
self.x = ELT(x.x)
self.y = ELT(x.y)
else:
self.x = ELT(x)
self.y = ELT(y)
def on_curve(self):
return (self.x**3 + self.x**2 + self.y**2 + self.x*self.y + ELT(ec_b)) == 0
def __cmp__(self, other):
if other == 0:
if self.x or self.y:
return 1
else:
return 0
elif isinstance(other, Point):
ca = cmp(self.x,other.x)
if ca != 0:
return ca
return cmp(self.y,other.y)
return NotImplemented
def _double(self):
if self.x == 0:
return Point(0,0)
s = self.y/self.x + self.x
rx = s**2 + s
rx[29] ^= 1;
ry = s * rx + rx + self.x**2
return Point(rx,ry)
def __add__(self, other):
if not isinstance(other,Point):
return NotImplemented
if self == 0:
return Point(other)
if other == 0:
return Point(self)
u = self.x + other.x
if u == 0:
u = self.y + other.y
if u == 0:
return self._double()
else:
return Point(0,0)
s = (self.y + other.y) / u
t = s**2 + s + other.x
t[29] ^= 1
rx = t+self.x
ry = s*t+self.y+rx
return Point(rx,ry)
def __mul__(self, other):
bts = long_to_bytes(other,30)
d = Point(0,0)
for i in range(30):
mask = 0x80
while mask != 0:
d = d._double()
if ((ord(bts[i]) & mask) != 0):
d += self
mask >>=1
return d
#def __mul__(self, other):
#if not (isinstance(other,long) or isinstance(other,int)):
#return NotImplemented
#d = Point(0,0)
#s = Point(self)
#while other != 0:
#if other & 1:
#d += s
#s = s._double()
#other >>= 1
#return d
def __rmul__(self, other):
return self * other
def __str__(self):
return "(%s,%s)"%(str(self.x),str(self.y))
def __repr__(self):
return "Point"+str(self)
def __nonzero__(self):
return self.x or self.y
def tobytes(self):
return self.x.tobytes() + self.y.tobytes()
#only for prime N
#segher, your math makes my head hurt. But it works.
def bn_inv(a,N):
return pow(a,N-2,N)
# order of the addition group of points
ec_N = bytes_to_long(
"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"+\
"\x13\xe9\x74\xe7\x2f\x8a\x69\x22\x03\x1d\x26\x03\xcf\xe0\xd7")
# base point
ec_G = Point(
"\x00\xfa\xc9\xdf\xcb\xac\x83\x13\xbb\x21\x39\xf1\xbb\x75\x5f"+
"\xef\x65\xbc\x39\x1f\x8b\x36\xf8\xf8\xeb\x73\x71\xfd\x55\x8b"+
"\x01\x00\x6a\x08\xa4\x19\x03\x35\x06\x78\xe5\x85\x28\xbe\xbf"+
"\x8a\x0b\xef\xf8\x67\xa7\xca\x36\x71\x6f\x7e\x01\xf8\x10\x52")
def generate_ecdsa(k, sha):
k = bytes_to_long(k)
if k >= ec_N:
raise Exception("Invalid private key")
e = bytes_to_long(sha)
m = open("/dev/random","rb").read(30)
if len(m) != 30:
raise Exception("Failed to get random data")
m = bytes_to_long(m) % ec_N
r = (m * ec_G).x.tobignum() % ec_N
kk = ((r*k)+e)%ec_N
s = (bn_inv(m,ec_N) * kk)%ec_N
r = long_to_bytes(r,30)
s = long_to_bytes(s,30)
return r,s
def check_ecdsa(q,r,s,sha):
q = Point(q)
r = bytes_to_long(r)
s = bytes_to_long(s)
e = bytes_to_long(sha)
s_inv = bn_inv(s,ec_N)
w1 = (e*s_inv)%ec_N
w2 = (r*s_inv)%ec_N
r1 = w1 * ec_G + w2 * q
rx = r1.x.tobignum()%ec_N
return rx == r
def priv_to_pub(k):
k = bytes_to_long(k)
q = k * ec_G
return q.tobytes()
def gen_priv_key():
k = open("/dev/random","rb").read(30)
if len(k) != 30:
raise Exception("Failed to get random data")
k = bytes_to_long(k)
k = k % ec_N
return long_to_bytes(k,30)

1757
pywii/Common/pywii/wii.py Normal file

File diff suppressed because it is too large Load Diff