structure.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. # Copyright (c) 2003-2016 CORE Security Technologies
  2. #
  3. # This software is provided under under a slightly modified version
  4. # of the Apache Software License. See the accompanying LICENSE file
  5. # for more information.
  6. #
  7. from struct import pack, unpack, calcsize
  8. class Structure:
  9. """ sublcasses can define commonHdr and/or structure.
  10. each of them is an tuple of either two: (fieldName, format) or three: (fieldName, ':', class) fields.
  11. [it can't be a dictionary, because order is important]
  12. where format specifies how the data in the field will be converted to/from bytes (string)
  13. class is the class to use when unpacking ':' fields.
  14. each field can only contain one value (or an array of values for *)
  15. i.e. struct.pack('Hl',1,2) is valid, but format specifier 'Hl' is not (you must use 2 dfferent fields)
  16. format specifiers:
  17. specifiers from module pack can be used with the same format
  18. see struct.__doc__ (pack/unpack is finally called)
  19. x [padding byte]
  20. c [character]
  21. b [signed byte]
  22. B [unsigned byte]
  23. h [signed short]
  24. H [unsigned short]
  25. l [signed long]
  26. L [unsigned long]
  27. i [signed integer]
  28. I [unsigned integer]
  29. q [signed long long (quad)]
  30. Q [unsigned long long (quad)]
  31. s [string (array of chars), must be preceded with length in format specifier, padded with zeros]
  32. p [pascal string (includes byte count), must be preceded with length in format specifier, padded with zeros]
  33. f [float]
  34. d [double]
  35. = [native byte ordering, size and alignment]
  36. @ [native byte ordering, standard size and alignment]
  37. ! [network byte ordering]
  38. < [little endian]
  39. > [big endian]
  40. usual printf like specifiers can be used (if started with %)
  41. [not recommeneded, there is no why to unpack this]
  42. %08x will output an 8 bytes hex
  43. %s will output a string
  44. %s\\x00 will output a NUL terminated string
  45. %d%d will output 2 decimal digits (against the very same specification of Structure)
  46. ...
  47. some additional format specifiers:
  48. : just copy the bytes from the field into the output string (input may be string, other structure, or anything responding to __str__()) (for unpacking, all what's left is returned)
  49. z same as :, but adds a NUL byte at the end (asciiz) (for unpacking the first NUL byte is used as terminator) [asciiz string]
  50. u same as z, but adds two NUL bytes at the end (after padding to an even size with NULs). (same for unpacking) [unicode string]
  51. w DCE-RPC/NDR string (it's a macro for [ '<L=(len(field)+1)/2','"\\x00\\x00\\x00\\x00','<L=(len(field)+1)/2',':' ]
  52. ?-field length of field named 'field', formated as specified with ? ('?' may be '!H' for example). The input value overrides the real length
  53. ?1*?2 array of elements. Each formated as '?2', the number of elements in the array is stored as specified by '?1' (?1 is optional, or can also be a constant (number), for unpacking)
  54. 'xxxx literal xxxx (field's value doesn't change the output. quotes must not be closed or escaped)
  55. "xxxx literal xxxx (field's value doesn't change the output. quotes must not be closed or escaped)
  56. _ will not pack the field. Accepts a third argument, which is an unpack code. See _Test_UnpackCode for an example
  57. ?=packcode will evaluate packcode in the context of the structure, and pack the result as specified by ?. Unpacking is made plain
  58. ?&fieldname "Address of field fieldname".
  59. For packing it will simply pack the id() of fieldname. Or use 0 if fieldname doesn't exists.
  60. For unpacking, it's used to know weather fieldname has to be unpacked or not, i.e. by adding a & field you turn another field (fieldname) in an optional field.
  61. """
  62. commonHdr = ()
  63. structure = ()
  64. debug = 0
  65. def __init__(self, data = None, alignment = 0):
  66. if not hasattr(self, 'alignment'):
  67. self.alignment = alignment
  68. self.fields = {}
  69. self.rawData = data
  70. if data is not None:
  71. self.fromString(data)
  72. else:
  73. self.data = None
  74. @classmethod
  75. def fromFile(self, file):
  76. answer = self()
  77. answer.fromString(file.read(len(answer)))
  78. return answer
  79. def setAlignment(self, alignment):
  80. self.alignment = alignment
  81. def setData(self, data):
  82. self.data = data
  83. def packField(self, fieldName, format = None):
  84. if self.debug:
  85. print "packField( %s | %s )" % (fieldName, format)
  86. if format is None:
  87. format = self.formatForField(fieldName)
  88. if self.fields.has_key(fieldName):
  89. ans = self.pack(format, self.fields[fieldName], field = fieldName)
  90. else:
  91. ans = self.pack(format, None, field = fieldName)
  92. if self.debug:
  93. print "\tanswer %r" % ans
  94. return ans
  95. def getData(self):
  96. if self.data is not None:
  97. return self.data
  98. data = ''
  99. for field in self.commonHdr+self.structure:
  100. try:
  101. data += self.packField(field[0], field[1])
  102. except Exception, e:
  103. if self.fields.has_key(field[0]):
  104. e.args += ("When packing field '%s | %s | %r' in %s" % (field[0], field[1], self[field[0]], self.__class__),)
  105. else:
  106. e.args += ("When packing field '%s | %s' in %s" % (field[0], field[1], self.__class__),)
  107. raise
  108. if self.alignment:
  109. if len(data) % self.alignment:
  110. data += ('\x00'*self.alignment)[:-(len(data) % self.alignment)]
  111. #if len(data) % self.alignment: data += ('\x00'*self.alignment)[:-(len(data) % self.alignment)]
  112. return data
  113. def fromString(self, data):
  114. self.rawData = data
  115. for field in self.commonHdr+self.structure:
  116. if self.debug:
  117. print "fromString( %s | %s | %r )" % (field[0], field[1], data)
  118. size = self.calcUnpackSize(field[1], data, field[0])
  119. if self.debug:
  120. print " size = %d" % size
  121. dataClassOrCode = str
  122. if len(field) > 2:
  123. dataClassOrCode = field[2]
  124. try:
  125. self[field[0]] = self.unpack(field[1], data[:size], dataClassOrCode = dataClassOrCode, field = field[0])
  126. except Exception,e:
  127. e.args += ("When unpacking field '%s | %s | %r[:%d]'" % (field[0], field[1], data, size),)
  128. raise
  129. size = self.calcPackSize(field[1], self[field[0]], field[0])
  130. if self.alignment and size % self.alignment:
  131. size += self.alignment - (size % self.alignment)
  132. data = data[size:]
  133. return self
  134. def __setitem__(self, key, value):
  135. self.fields[key] = value
  136. self.data = None # force recompute
  137. def __getitem__(self, key):
  138. return self.fields[key]
  139. def __delitem__(self, key):
  140. del self.fields[key]
  141. def __str__(self):
  142. return self.getData()
  143. def __len__(self):
  144. # XXX: improve
  145. return len(self.getData())
  146. def pack(self, format, data, field = None):
  147. if self.debug:
  148. print " pack( %s | %r | %s)" % (format, data, field)
  149. if field:
  150. addressField = self.findAddressFieldFor(field)
  151. if (addressField is not None) and (data is None):
  152. return ''
  153. # void specifier
  154. if format[:1] == '_':
  155. return ''
  156. # quote specifier
  157. if format[:1] == "'" or format[:1] == '"':
  158. return format[1:]
  159. # code specifier
  160. two = format.split('=')
  161. if len(two) >= 2:
  162. try:
  163. return self.pack(two[0], data)
  164. except:
  165. fields = {'self':self}
  166. fields.update(self.fields)
  167. return self.pack(two[0], eval(two[1], {}, fields))
  168. # address specifier
  169. two = format.split('&')
  170. if len(two) == 2:
  171. try:
  172. return self.pack(two[0], data)
  173. except:
  174. if (self.fields.has_key(two[1])) and (self[two[1]] is not None):
  175. return self.pack(two[0], id(self[two[1]]) & ((1<<(calcsize(two[0])*8))-1) )
  176. else:
  177. return self.pack(two[0], 0)
  178. # length specifier
  179. two = format.split('-')
  180. if len(two) == 2:
  181. try:
  182. return self.pack(two[0],data)
  183. except:
  184. return self.pack(two[0], self.calcPackFieldSize(two[1]))
  185. # array specifier
  186. two = format.split('*')
  187. if len(two) == 2:
  188. answer = ''
  189. for each in data:
  190. answer += self.pack(two[1], each)
  191. if two[0]:
  192. if two[0].isdigit():
  193. if int(two[0]) != len(data):
  194. raise Exception, "Array field has a constant size, and it doesn't match the actual value"
  195. else:
  196. return self.pack(two[0], len(data))+answer
  197. return answer
  198. # "printf" string specifier
  199. if format[:1] == '%':
  200. # format string like specifier
  201. return format % data
  202. # asciiz specifier
  203. if format[:1] == 'z':
  204. return str(data)+'\0'
  205. # unicode specifier
  206. if format[:1] == 'u':
  207. return str(data)+'\0\0' + (len(data) & 1 and '\0' or '')
  208. # DCE-RPC/NDR string specifier
  209. if format[:1] == 'w':
  210. if len(data) == 0:
  211. data = '\0\0'
  212. elif len(data) % 2:
  213. data += '\0'
  214. l = pack('<L', len(data)/2)
  215. return '%s\0\0\0\0%s%s' % (l,l,data)
  216. if data is None:
  217. raise Exception, "Trying to pack None"
  218. # literal specifier
  219. if format[:1] == ':':
  220. return str(data)
  221. # struct like specifier
  222. return pack(format, data)
  223. def unpack(self, format, data, dataClassOrCode = str, field = None):
  224. if self.debug:
  225. print " unpack( %s | %r )" % (format, data)
  226. if field:
  227. addressField = self.findAddressFieldFor(field)
  228. if addressField is not None:
  229. if not self[addressField]:
  230. return
  231. # void specifier
  232. if format[:1] == '_':
  233. if dataClassOrCode != str:
  234. fields = {'self':self, 'inputDataLeft':data}
  235. fields.update(self.fields)
  236. return eval(dataClassOrCode, {}, fields)
  237. else:
  238. return None
  239. # quote specifier
  240. if format[:1] == "'" or format[:1] == '"':
  241. answer = format[1:]
  242. if answer != data:
  243. raise Exception, "Unpacked data doesn't match constant value '%r' should be '%r'" % (data, answer)
  244. return answer
  245. # address specifier
  246. two = format.split('&')
  247. if len(two) == 2:
  248. return self.unpack(two[0],data)
  249. # code specifier
  250. two = format.split('=')
  251. if len(two) >= 2:
  252. return self.unpack(two[0],data)
  253. # length specifier
  254. two = format.split('-')
  255. if len(two) == 2:
  256. return self.unpack(two[0],data)
  257. # array specifier
  258. two = format.split('*')
  259. if len(two) == 2:
  260. answer = []
  261. sofar = 0
  262. if two[0].isdigit():
  263. number = int(two[0])
  264. elif two[0]:
  265. sofar += self.calcUnpackSize(two[0], data)
  266. number = self.unpack(two[0], data[:sofar])
  267. else:
  268. number = -1
  269. while number and sofar < len(data):
  270. nsofar = sofar + self.calcUnpackSize(two[1],data[sofar:])
  271. answer.append(self.unpack(two[1], data[sofar:nsofar], dataClassOrCode))
  272. number -= 1
  273. sofar = nsofar
  274. return answer
  275. # "printf" string specifier
  276. if format[:1] == '%':
  277. # format string like specifier
  278. return format % data
  279. # asciiz specifier
  280. if format == 'z':
  281. if data[-1] != '\x00':
  282. raise Exception, ("%s 'z' field is not NUL terminated: %r" % (field, data))
  283. return data[:-1] # remove trailing NUL
  284. # unicode specifier
  285. if format == 'u':
  286. if data[-2:] != '\x00\x00':
  287. raise Exception, ("%s 'u' field is not NUL-NUL terminated: %r" % (field, data))
  288. return data[:-2] # remove trailing NUL
  289. # DCE-RPC/NDR string specifier
  290. if format == 'w':
  291. l = unpack('<L', data[:4])[0]
  292. return data[12:12+l*2]
  293. # literal specifier
  294. if format == ':':
  295. return dataClassOrCode(data)
  296. # struct like specifier
  297. return unpack(format, data)[0]
  298. def calcPackSize(self, format, data, field = None):
  299. # # print " calcPackSize %s:%r" % (format, data)
  300. if field:
  301. addressField = self.findAddressFieldFor(field)
  302. if addressField is not None:
  303. if not self[addressField]:
  304. return 0
  305. # void specifier
  306. if format[:1] == '_':
  307. return 0
  308. # quote specifier
  309. if format[:1] == "'" or format[:1] == '"':
  310. return len(format)-1
  311. # address specifier
  312. two = format.split('&')
  313. if len(two) == 2:
  314. return self.calcPackSize(two[0], data)
  315. # code specifier
  316. two = format.split('=')
  317. if len(two) >= 2:
  318. return self.calcPackSize(two[0], data)
  319. # length specifier
  320. two = format.split('-')
  321. if len(two) == 2:
  322. return self.calcPackSize(two[0], data)
  323. # array specifier
  324. two = format.split('*')
  325. if len(two) == 2:
  326. answer = 0
  327. if two[0].isdigit():
  328. if int(two[0]) != len(data):
  329. raise Exception, "Array field has a constant size, and it doesn't match the actual value"
  330. elif two[0]:
  331. answer += self.calcPackSize(two[0], len(data))
  332. for each in data:
  333. answer += self.calcPackSize(two[1], each)
  334. return answer
  335. # "printf" string specifier
  336. if format[:1] == '%':
  337. # format string like specifier
  338. return len(format % data)
  339. # asciiz specifier
  340. if format[:1] == 'z':
  341. return len(data)+1
  342. # asciiz specifier
  343. if format[:1] == 'u':
  344. l = len(data)
  345. return l + (l & 1 and 3 or 2)
  346. # DCE-RPC/NDR string specifier
  347. if format[:1] == 'w':
  348. l = len(data)
  349. return 12+l+l % 2
  350. # literal specifier
  351. if format[:1] == ':':
  352. return len(data)
  353. # struct like specifier
  354. return calcsize(format)
  355. def calcUnpackSize(self, format, data, field = None):
  356. if self.debug:
  357. print " calcUnpackSize( %s | %s | %r)" % (field, format, data)
  358. # void specifier
  359. if format[:1] == '_':
  360. return 0
  361. addressField = self.findAddressFieldFor(field)
  362. if addressField is not None:
  363. if not self[addressField]:
  364. return 0
  365. try:
  366. lengthField = self.findLengthFieldFor(field)
  367. return self[lengthField]
  368. except:
  369. pass
  370. # XXX: Try to match to actual values, raise if no match
  371. # quote specifier
  372. if format[:1] == "'" or format[:1] == '"':
  373. return len(format)-1
  374. # address specifier
  375. two = format.split('&')
  376. if len(two) == 2:
  377. return self.calcUnpackSize(two[0], data)
  378. # code specifier
  379. two = format.split('=')
  380. if len(two) >= 2:
  381. return self.calcUnpackSize(two[0], data)
  382. # length specifier
  383. two = format.split('-')
  384. if len(two) == 2:
  385. return self.calcUnpackSize(two[0], data)
  386. # array specifier
  387. two = format.split('*')
  388. if len(two) == 2:
  389. answer = 0
  390. if two[0]:
  391. if two[0].isdigit():
  392. number = int(two[0])
  393. else:
  394. answer += self.calcUnpackSize(two[0], data)
  395. number = self.unpack(two[0], data[:answer])
  396. while number:
  397. number -= 1
  398. answer += self.calcUnpackSize(two[1], data[answer:])
  399. else:
  400. while answer < len(data):
  401. answer += self.calcUnpackSize(two[1], data[answer:])
  402. return answer
  403. # "printf" string specifier
  404. if format[:1] == '%':
  405. raise Exception, "Can't guess the size of a printf like specifier for unpacking"
  406. # asciiz specifier
  407. if format[:1] == 'z':
  408. return data.index('\x00')+1
  409. # asciiz specifier
  410. if format[:1] == 'u':
  411. l = data.index('\x00\x00')
  412. return l + (l & 1 and 3 or 2)
  413. # DCE-RPC/NDR string specifier
  414. if format[:1] == 'w':
  415. l = unpack('<L', data[:4])[0]
  416. return 12+l*2
  417. # literal specifier
  418. if format[:1] == ':':
  419. return len(data)
  420. # struct like specifier
  421. return calcsize(format)
  422. def calcPackFieldSize(self, fieldName, format = None):
  423. if format is None:
  424. format = self.formatForField(fieldName)
  425. return self.calcPackSize(format, self[fieldName])
  426. def formatForField(self, fieldName):
  427. for field in self.commonHdr+self.structure:
  428. if field[0] == fieldName:
  429. return field[1]
  430. raise Exception, ("Field %s not found" % fieldName)
  431. def findAddressFieldFor(self, fieldName):
  432. descriptor = '&%s' % fieldName
  433. l = len(descriptor)
  434. for field in self.commonHdr+self.structure:
  435. if field[1][-l:] == descriptor:
  436. return field[0]
  437. return None
  438. def findLengthFieldFor(self, fieldName):
  439. descriptor = '-%s' % fieldName
  440. l = len(descriptor)
  441. for field in self.commonHdr+self.structure:
  442. if field[1][-l:] == descriptor:
  443. return field[0]
  444. return None
  445. def zeroValue(self, format):
  446. two = format.split('*')
  447. if len(two) == 2:
  448. if two[0].isdigit():
  449. return (self.zeroValue(two[1]),)*int(two[0])
  450. if not format.find('*') == -1: return ()
  451. if 's' in format: return ''
  452. if format in ['z',':','u']: return ''
  453. if format == 'w': return '\x00\x00'
  454. return 0
  455. def clear(self):
  456. for field in self.commonHdr + self.structure:
  457. self[field[0]] = self.zeroValue(field[1])
  458. def dump(self, msg = None, indent = 0):
  459. if msg is None: msg = self.__class__.__name__
  460. ind = ' '*indent
  461. print "\n%s" % msg
  462. fixedFields = []
  463. for field in self.commonHdr+self.structure:
  464. i = field[0]
  465. if i in self.fields:
  466. fixedFields.append(i)
  467. if isinstance(self[i], Structure):
  468. self[i].dump('%s%s:{' % (ind,i), indent = indent + 4)
  469. print "%s}" % ind
  470. else:
  471. print "%s%s: {%r}" % (ind,i,self[i])
  472. # Do we have remaining fields not defined in the structures? let's
  473. # print them
  474. remainingFields = list(set(self.fields) - set(fixedFields))
  475. for i in remainingFields:
  476. if isinstance(self[i], Structure):
  477. self[i].dump('%s%s:{' % (ind,i), indent = indent + 4)
  478. print "%s}" % ind
  479. else:
  480. print "%s%s: {%r}" % (ind,i,self[i])
  481. class _StructureTest:
  482. alignment = 0
  483. def create(self,data = None):
  484. if data is not None:
  485. return self.theClass(data, alignment = self.alignment)
  486. else:
  487. return self.theClass(alignment = self.alignment)
  488. def run(self):
  489. print
  490. print "-"*70
  491. testName = self.__class__.__name__
  492. print "starting test: %s....." % testName
  493. a = self.create()
  494. self.populate(a)
  495. a.dump("packing.....")
  496. a_str = str(a)
  497. print "packed: %r" % a_str
  498. print "unpacking....."
  499. b = self.create(a_str)
  500. b.dump("unpacked.....")
  501. print "repacking....."
  502. b_str = str(b)
  503. if b_str != a_str:
  504. print "ERROR: original packed and repacked don't match"
  505. print "packed: %r" % b_str
  506. class _Test_simple(_StructureTest):
  507. class theClass(Structure):
  508. commonHdr = ()
  509. structure = (
  510. ('int1', '!L'),
  511. ('len1','!L-z1'),
  512. ('arr1','B*<L'),
  513. ('z1', 'z'),
  514. ('u1','u'),
  515. ('', '"COCA'),
  516. ('len2','!H-:1'),
  517. ('', '"COCA'),
  518. (':1', ':'),
  519. ('int3','>L'),
  520. ('code1','>L=len(arr1)*2+0x1000'),
  521. )
  522. def populate(self, a):
  523. a['default'] = 'hola'
  524. a['int1'] = 0x3131
  525. a['int3'] = 0x45444342
  526. a['z1'] = 'hola'
  527. a['u1'] = 'hola'.encode('utf_16_le')
  528. a[':1'] = ':1234:'
  529. a['arr1'] = (0x12341234,0x88990077,0x41414141)
  530. # a['len1'] = 0x42424242
  531. class _Test_fixedLength(_Test_simple):
  532. def populate(self, a):
  533. _Test_simple.populate(self, a)
  534. a['len1'] = 0x42424242
  535. class _Test_simple_aligned4(_Test_simple):
  536. alignment = 4
  537. class _Test_nested(_StructureTest):
  538. class theClass(Structure):
  539. class _Inner(Structure):
  540. structure = (('data', 'z'),)
  541. structure = (
  542. ('nest1', ':', _Inner),
  543. ('nest2', ':', _Inner),
  544. ('int', '<L'),
  545. )
  546. def populate(self, a):
  547. a['nest1'] = _Test_nested.theClass._Inner()
  548. a['nest2'] = _Test_nested.theClass._Inner()
  549. a['nest1']['data'] = 'hola manola'
  550. a['nest2']['data'] = 'chau loco'
  551. a['int'] = 0x12345678
  552. class _Test_Optional(_StructureTest):
  553. class theClass(Structure):
  554. structure = (
  555. ('pName','<L&Name'),
  556. ('pList','<L&List'),
  557. ('Name','w'),
  558. ('List','<H*<L'),
  559. )
  560. def populate(self, a):
  561. a['Name'] = 'Optional test'
  562. a['List'] = (1,2,3,4)
  563. class _Test_Optional_sparse(_Test_Optional):
  564. def populate(self, a):
  565. _Test_Optional.populate(self, a)
  566. del a['Name']
  567. class _Test_AsciiZArray(_StructureTest):
  568. class theClass(Structure):
  569. structure = (
  570. ('head','<L'),
  571. ('array','B*z'),
  572. ('tail','<L'),
  573. )
  574. def populate(self, a):
  575. a['head'] = 0x1234
  576. a['tail'] = 0xabcd
  577. a['array'] = ('hola','manola','te traje')
  578. class _Test_UnpackCode(_StructureTest):
  579. class theClass(Structure):
  580. structure = (
  581. ('leni','<L=len(uno)*2'),
  582. ('cuchi','_-uno','leni/2'),
  583. ('uno',':'),
  584. ('dos',':'),
  585. )
  586. def populate(self, a):
  587. a['uno'] = 'soy un loco!'
  588. a['dos'] = 'que haces fiera'
  589. class _Test_AAA(_StructureTest):
  590. class theClass(Structure):
  591. commonHdr = ()
  592. structure = (
  593. ('iv', '!L=((init_vector & 0xFFFFFF) << 8) | ((pad & 0x3f) << 2) | (keyid & 3)'),
  594. ('init_vector', '_','(iv >> 8)'),
  595. ('pad', '_','((iv >>2) & 0x3F)'),
  596. ('keyid', '_','( iv & 0x03 )'),
  597. ('dataLen', '_-data', 'len(inputDataLeft)-4'),
  598. ('data',':'),
  599. ('icv','>L'),
  600. )
  601. def populate(self, a):
  602. a['init_vector']=0x01020304
  603. #a['pad']=int('01010101',2)
  604. a['pad']=int('010101',2)
  605. a['keyid']=0x07
  606. a['data']="\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9"
  607. a['icv'] = 0x05060708
  608. #a['iv'] = 0x01020304
  609. if __name__ == '__main__':
  610. _Test_simple().run()
  611. try:
  612. _Test_fixedLength().run()
  613. except:
  614. print "cannot repack because length is bogus"
  615. _Test_simple_aligned4().run()
  616. _Test_nested().run()
  617. _Test_Optional().run()
  618. _Test_Optional_sparse().run()
  619. _Test_AsciiZArray().run()
  620. _Test_UnpackCode().run()
  621. _Test_AAA().run()