decoder.py 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207
  1. #
  2. # This file is part of pyasn1 software.
  3. #
  4. # Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
  5. # License: https://pyasn1.readthedocs.io/en/latest/license.html
  6. #
  7. import io
  8. import os
  9. import sys
  10. import warnings
  11. from pyasn1 import debug
  12. from pyasn1 import error
  13. from pyasn1.codec.ber import eoo
  14. from pyasn1.codec.streaming import asSeekableStream
  15. from pyasn1.codec.streaming import isEndOfStream
  16. from pyasn1.codec.streaming import peekIntoStream
  17. from pyasn1.codec.streaming import readFromStream
  18. from pyasn1.compat import _MISSING
  19. from pyasn1.error import PyAsn1Error
  20. from pyasn1.type import base
  21. from pyasn1.type import char
  22. from pyasn1.type import tag
  23. from pyasn1.type import tagmap
  24. from pyasn1.type import univ
  25. from pyasn1.type import useful
  26. __all__ = ['StreamingDecoder', 'Decoder', 'decode']
  27. LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_DECODER)
  28. noValue = base.noValue
  29. SubstrateUnderrunError = error.SubstrateUnderrunError
  30. # Maximum number of continuation octets (high-bit set) allowed per OID arc.
  31. # 20 octets allows up to 140-bit integers, supporting UUID-based OIDs
  32. MAX_OID_ARC_CONTINUATION_OCTETS = 20
  33. class AbstractPayloadDecoder(object):
  34. protoComponent = None
  35. def valueDecoder(self, substrate, asn1Spec,
  36. tagSet=None, length=None, state=None,
  37. decodeFun=None, substrateFun=None,
  38. **options):
  39. """Decode value with fixed byte length.
  40. The decoder is allowed to consume as many bytes as necessary.
  41. """
  42. raise error.PyAsn1Error('SingleItemDecoder not implemented for %s' % (tagSet,)) # TODO: Seems more like an NotImplementedError?
  43. def indefLenValueDecoder(self, substrate, asn1Spec,
  44. tagSet=None, length=None, state=None,
  45. decodeFun=None, substrateFun=None,
  46. **options):
  47. """Decode value with undefined length.
  48. The decoder is allowed to consume as many bytes as necessary.
  49. """
  50. raise error.PyAsn1Error('Indefinite length mode decoder not implemented for %s' % (tagSet,)) # TODO: Seems more like an NotImplementedError?
  51. @staticmethod
  52. def _passAsn1Object(asn1Object, options):
  53. if 'asn1Object' not in options:
  54. options['asn1Object'] = asn1Object
  55. return options
  56. class AbstractSimplePayloadDecoder(AbstractPayloadDecoder):
  57. @staticmethod
  58. def substrateCollector(asn1Object, substrate, length, options):
  59. for chunk in readFromStream(substrate, length, options):
  60. yield chunk
  61. def _createComponent(self, asn1Spec, tagSet, value, **options):
  62. if options.get('native'):
  63. return value
  64. elif asn1Spec is None:
  65. return self.protoComponent.clone(value, tagSet=tagSet)
  66. elif value is noValue:
  67. return asn1Spec
  68. else:
  69. return asn1Spec.clone(value)
  70. class RawPayloadDecoder(AbstractSimplePayloadDecoder):
  71. protoComponent = univ.Any('')
  72. def valueDecoder(self, substrate, asn1Spec,
  73. tagSet=None, length=None, state=None,
  74. decodeFun=None, substrateFun=None,
  75. **options):
  76. if substrateFun:
  77. asn1Object = self._createComponent(asn1Spec, tagSet, '', **options)
  78. for chunk in substrateFun(asn1Object, substrate, length, options):
  79. yield chunk
  80. return
  81. for value in decodeFun(substrate, asn1Spec, tagSet, length, **options):
  82. yield value
  83. def indefLenValueDecoder(self, substrate, asn1Spec,
  84. tagSet=None, length=None, state=None,
  85. decodeFun=None, substrateFun=None,
  86. **options):
  87. if substrateFun:
  88. asn1Object = self._createComponent(asn1Spec, tagSet, '', **options)
  89. for chunk in substrateFun(asn1Object, substrate, length, options):
  90. yield chunk
  91. return
  92. while True:
  93. for value in decodeFun(
  94. substrate, asn1Spec, tagSet, length,
  95. allowEoo=True, **options):
  96. if value is eoo.endOfOctets:
  97. return
  98. yield value
  99. rawPayloadDecoder = RawPayloadDecoder()
  100. class IntegerPayloadDecoder(AbstractSimplePayloadDecoder):
  101. protoComponent = univ.Integer(0)
  102. def valueDecoder(self, substrate, asn1Spec,
  103. tagSet=None, length=None, state=None,
  104. decodeFun=None, substrateFun=None,
  105. **options):
  106. if tagSet[0].tagFormat != tag.tagFormatSimple:
  107. raise error.PyAsn1Error('Simple tag format expected')
  108. for chunk in readFromStream(substrate, length, options):
  109. if isinstance(chunk, SubstrateUnderrunError):
  110. yield chunk
  111. if chunk:
  112. value = int.from_bytes(bytes(chunk), 'big', signed=True)
  113. else:
  114. value = 0
  115. yield self._createComponent(asn1Spec, tagSet, value, **options)
  116. class BooleanPayloadDecoder(IntegerPayloadDecoder):
  117. protoComponent = univ.Boolean(0)
  118. def _createComponent(self, asn1Spec, tagSet, value, **options):
  119. return IntegerPayloadDecoder._createComponent(
  120. self, asn1Spec, tagSet, value and 1 or 0, **options)
  121. class BitStringPayloadDecoder(AbstractSimplePayloadDecoder):
  122. protoComponent = univ.BitString(())
  123. supportConstructedForm = True
  124. def valueDecoder(self, substrate, asn1Spec,
  125. tagSet=None, length=None, state=None,
  126. decodeFun=None, substrateFun=None,
  127. **options):
  128. if substrateFun:
  129. asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options)
  130. for chunk in substrateFun(asn1Object, substrate, length, options):
  131. yield chunk
  132. return
  133. if not length:
  134. raise error.PyAsn1Error('Empty BIT STRING substrate')
  135. for chunk in isEndOfStream(substrate):
  136. if isinstance(chunk, SubstrateUnderrunError):
  137. yield chunk
  138. if chunk:
  139. raise error.PyAsn1Error('Empty BIT STRING substrate')
  140. if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check?
  141. for trailingBits in readFromStream(substrate, 1, options):
  142. if isinstance(trailingBits, SubstrateUnderrunError):
  143. yield trailingBits
  144. trailingBits = ord(trailingBits)
  145. if trailingBits > 7:
  146. raise error.PyAsn1Error(
  147. 'Trailing bits overflow %s' % trailingBits
  148. )
  149. for chunk in readFromStream(substrate, length - 1, options):
  150. if isinstance(chunk, SubstrateUnderrunError):
  151. yield chunk
  152. value = self.protoComponent.fromOctetString(
  153. chunk, internalFormat=True, padding=trailingBits)
  154. yield self._createComponent(asn1Spec, tagSet, value, **options)
  155. return
  156. if not self.supportConstructedForm:
  157. raise error.PyAsn1Error('Constructed encoding form prohibited '
  158. 'at %s' % self.__class__.__name__)
  159. if LOG:
  160. LOG('assembling constructed serialization')
  161. # All inner fragments are of the same type, treat them as octet string
  162. substrateFun = self.substrateCollector
  163. bitString = self.protoComponent.fromOctetString(b'', internalFormat=True)
  164. current_position = substrate.tell()
  165. while substrate.tell() - current_position < length:
  166. for component in decodeFun(
  167. substrate, self.protoComponent, substrateFun=substrateFun,
  168. **options):
  169. if isinstance(component, SubstrateUnderrunError):
  170. yield component
  171. trailingBits = component[0]
  172. if trailingBits > 7:
  173. raise error.PyAsn1Error(
  174. 'Trailing bits overflow %s' % trailingBits
  175. )
  176. bitString = self.protoComponent.fromOctetString(
  177. component[1:], internalFormat=True,
  178. prepend=bitString, padding=trailingBits
  179. )
  180. yield self._createComponent(asn1Spec, tagSet, bitString, **options)
  181. def indefLenValueDecoder(self, substrate, asn1Spec,
  182. tagSet=None, length=None, state=None,
  183. decodeFun=None, substrateFun=None,
  184. **options):
  185. if substrateFun:
  186. asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options)
  187. for chunk in substrateFun(asn1Object, substrate, length, options):
  188. yield chunk
  189. return
  190. # All inner fragments are of the same type, treat them as octet string
  191. substrateFun = self.substrateCollector
  192. bitString = self.protoComponent.fromOctetString(b'', internalFormat=True)
  193. while True: # loop over fragments
  194. for component in decodeFun(
  195. substrate, self.protoComponent, substrateFun=substrateFun,
  196. allowEoo=True, **options):
  197. if component is eoo.endOfOctets:
  198. break
  199. if isinstance(component, SubstrateUnderrunError):
  200. yield component
  201. if component is eoo.endOfOctets:
  202. break
  203. trailingBits = component[0]
  204. if trailingBits > 7:
  205. raise error.PyAsn1Error(
  206. 'Trailing bits overflow %s' % trailingBits
  207. )
  208. bitString = self.protoComponent.fromOctetString(
  209. component[1:], internalFormat=True,
  210. prepend=bitString, padding=trailingBits
  211. )
  212. yield self._createComponent(asn1Spec, tagSet, bitString, **options)
  213. class OctetStringPayloadDecoder(AbstractSimplePayloadDecoder):
  214. protoComponent = univ.OctetString('')
  215. supportConstructedForm = True
  216. def valueDecoder(self, substrate, asn1Spec,
  217. tagSet=None, length=None, state=None,
  218. decodeFun=None, substrateFun=None,
  219. **options):
  220. if substrateFun:
  221. asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options)
  222. for chunk in substrateFun(asn1Object, substrate, length, options):
  223. yield chunk
  224. return
  225. if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check?
  226. for chunk in readFromStream(substrate, length, options):
  227. if isinstance(chunk, SubstrateUnderrunError):
  228. yield chunk
  229. yield self._createComponent(asn1Spec, tagSet, chunk, **options)
  230. return
  231. if not self.supportConstructedForm:
  232. raise error.PyAsn1Error('Constructed encoding form prohibited at %s' % self.__class__.__name__)
  233. if LOG:
  234. LOG('assembling constructed serialization')
  235. # All inner fragments are of the same type, treat them as octet string
  236. substrateFun = self.substrateCollector
  237. header = b''
  238. original_position = substrate.tell()
  239. # head = popSubstream(substrate, length)
  240. while substrate.tell() - original_position < length:
  241. for component in decodeFun(
  242. substrate, self.protoComponent, substrateFun=substrateFun,
  243. **options):
  244. if isinstance(component, SubstrateUnderrunError):
  245. yield component
  246. header += component
  247. yield self._createComponent(asn1Spec, tagSet, header, **options)
  248. def indefLenValueDecoder(self, substrate, asn1Spec,
  249. tagSet=None, length=None, state=None,
  250. decodeFun=None, substrateFun=None,
  251. **options):
  252. if substrateFun and substrateFun is not self.substrateCollector:
  253. asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options)
  254. for chunk in substrateFun(asn1Object, substrate, length, options):
  255. yield chunk
  256. return
  257. # All inner fragments are of the same type, treat them as octet string
  258. substrateFun = self.substrateCollector
  259. header = b''
  260. while True: # loop over fragments
  261. for component in decodeFun(
  262. substrate, self.protoComponent, substrateFun=substrateFun,
  263. allowEoo=True, **options):
  264. if isinstance(component, SubstrateUnderrunError):
  265. yield component
  266. if component is eoo.endOfOctets:
  267. break
  268. if component is eoo.endOfOctets:
  269. break
  270. header += component
  271. yield self._createComponent(asn1Spec, tagSet, header, **options)
  272. class NullPayloadDecoder(AbstractSimplePayloadDecoder):
  273. protoComponent = univ.Null('')
  274. def valueDecoder(self, substrate, asn1Spec,
  275. tagSet=None, length=None, state=None,
  276. decodeFun=None, substrateFun=None,
  277. **options):
  278. if tagSet[0].tagFormat != tag.tagFormatSimple:
  279. raise error.PyAsn1Error('Simple tag format expected')
  280. for chunk in readFromStream(substrate, length, options):
  281. if isinstance(chunk, SubstrateUnderrunError):
  282. yield chunk
  283. component = self._createComponent(asn1Spec, tagSet, '', **options)
  284. if chunk:
  285. raise error.PyAsn1Error('Unexpected %d-octet substrate for Null' % length)
  286. yield component
  287. class ObjectIdentifierPayloadDecoder(AbstractSimplePayloadDecoder):
  288. protoComponent = univ.ObjectIdentifier(())
  289. def valueDecoder(self, substrate, asn1Spec,
  290. tagSet=None, length=None, state=None,
  291. decodeFun=None, substrateFun=None,
  292. **options):
  293. if tagSet[0].tagFormat != tag.tagFormatSimple:
  294. raise error.PyAsn1Error('Simple tag format expected')
  295. for chunk in readFromStream(substrate, length, options):
  296. if isinstance(chunk, SubstrateUnderrunError):
  297. yield chunk
  298. if not chunk:
  299. raise error.PyAsn1Error('Empty substrate')
  300. oid = ()
  301. index = 0
  302. substrateLen = len(chunk)
  303. while index < substrateLen:
  304. subId = chunk[index]
  305. index += 1
  306. if subId < 128:
  307. oid += (subId,)
  308. elif subId > 128:
  309. # Construct subid from a number of octets
  310. nextSubId = subId
  311. subId = 0
  312. continuationOctetCount = 0
  313. while nextSubId >= 128:
  314. continuationOctetCount += 1
  315. if continuationOctetCount > MAX_OID_ARC_CONTINUATION_OCTETS:
  316. raise error.PyAsn1Error(
  317. 'OID arc exceeds maximum continuation octets limit (%d) '
  318. 'at position %d' % (MAX_OID_ARC_CONTINUATION_OCTETS, index)
  319. )
  320. subId = (subId << 7) + (nextSubId & 0x7F)
  321. if index >= substrateLen:
  322. raise error.SubstrateUnderrunError(
  323. 'Short substrate for sub-OID past %s' % (oid,)
  324. )
  325. nextSubId = chunk[index]
  326. index += 1
  327. oid += ((subId << 7) + nextSubId,)
  328. elif subId == 128:
  329. # ASN.1 spec forbids leading zeros (0x80) in OID
  330. # encoding, tolerating it opens a vulnerability. See
  331. # https://www.esat.kuleuven.be/cosic/publications/article-1432.pdf
  332. # page 7
  333. raise error.PyAsn1Error('Invalid octet 0x80 in OID encoding')
  334. # Decode two leading arcs
  335. if 0 <= oid[0] <= 39:
  336. oid = (0,) + oid
  337. elif 40 <= oid[0] <= 79:
  338. oid = (1, oid[0] - 40) + oid[1:]
  339. elif oid[0] >= 80:
  340. oid = (2, oid[0] - 80) + oid[1:]
  341. else:
  342. raise error.PyAsn1Error('Malformed first OID octet: %s' % chunk[0])
  343. yield self._createComponent(asn1Spec, tagSet, oid, **options)
  344. class RelativeOIDPayloadDecoder(AbstractSimplePayloadDecoder):
  345. protoComponent = univ.RelativeOID(())
  346. def valueDecoder(self, substrate, asn1Spec,
  347. tagSet=None, length=None, state=None,
  348. decodeFun=None, substrateFun=None,
  349. **options):
  350. if tagSet[0].tagFormat != tag.tagFormatSimple:
  351. raise error.PyAsn1Error('Simple tag format expected')
  352. for chunk in readFromStream(substrate, length, options):
  353. if isinstance(chunk, SubstrateUnderrunError):
  354. yield chunk
  355. if not chunk:
  356. raise error.PyAsn1Error('Empty substrate')
  357. reloid = ()
  358. index = 0
  359. substrateLen = len(chunk)
  360. while index < substrateLen:
  361. subId = chunk[index]
  362. index += 1
  363. if subId < 128:
  364. reloid += (subId,)
  365. elif subId > 128:
  366. # Construct subid from a number of octets
  367. nextSubId = subId
  368. subId = 0
  369. continuationOctetCount = 0
  370. while nextSubId >= 128:
  371. continuationOctetCount += 1
  372. if continuationOctetCount > MAX_OID_ARC_CONTINUATION_OCTETS:
  373. raise error.PyAsn1Error(
  374. 'RELATIVE-OID arc exceeds maximum continuation octets limit (%d) '
  375. 'at position %d' % (MAX_OID_ARC_CONTINUATION_OCTETS, index)
  376. )
  377. subId = (subId << 7) + (nextSubId & 0x7F)
  378. if index >= substrateLen:
  379. raise error.SubstrateUnderrunError(
  380. 'Short substrate for sub-OID past %s' % (reloid,)
  381. )
  382. nextSubId = chunk[index]
  383. index += 1
  384. reloid += ((subId << 7) + nextSubId,)
  385. elif subId == 128:
  386. # ASN.1 spec forbids leading zeros (0x80) in OID
  387. # encoding, tolerating it opens a vulnerability. See
  388. # https://www.esat.kuleuven.be/cosic/publications/article-1432.pdf
  389. # page 7
  390. raise error.PyAsn1Error('Invalid octet 0x80 in RELATIVE-OID encoding')
  391. yield self._createComponent(asn1Spec, tagSet, reloid, **options)
  392. class RealPayloadDecoder(AbstractSimplePayloadDecoder):
  393. protoComponent = univ.Real()
  394. def valueDecoder(self, substrate, asn1Spec,
  395. tagSet=None, length=None, state=None,
  396. decodeFun=None, substrateFun=None,
  397. **options):
  398. if tagSet[0].tagFormat != tag.tagFormatSimple:
  399. raise error.PyAsn1Error('Simple tag format expected')
  400. for chunk in readFromStream(substrate, length, options):
  401. if isinstance(chunk, SubstrateUnderrunError):
  402. yield chunk
  403. if not chunk:
  404. yield self._createComponent(asn1Spec, tagSet, 0.0, **options)
  405. return
  406. fo = chunk[0]
  407. chunk = chunk[1:]
  408. if fo & 0x80: # binary encoding
  409. if not chunk:
  410. raise error.PyAsn1Error("Incomplete floating-point value")
  411. if LOG:
  412. LOG('decoding binary encoded REAL')
  413. n = (fo & 0x03) + 1
  414. if n == 4:
  415. n = chunk[0]
  416. chunk = chunk[1:]
  417. eo, chunk = chunk[:n], chunk[n:]
  418. if not eo or not chunk:
  419. raise error.PyAsn1Error('Real exponent screwed')
  420. e = eo[0] & 0x80 and -1 or 0
  421. while eo: # exponent
  422. e <<= 8
  423. e |= eo[0]
  424. eo = eo[1:]
  425. b = fo >> 4 & 0x03 # base bits
  426. if b > 2:
  427. raise error.PyAsn1Error('Illegal Real base')
  428. if b == 1: # encbase = 8
  429. e *= 3
  430. elif b == 2: # encbase = 16
  431. e *= 4
  432. p = 0
  433. while chunk: # value
  434. p <<= 8
  435. p |= chunk[0]
  436. chunk = chunk[1:]
  437. if fo & 0x40: # sign bit
  438. p = -p
  439. sf = fo >> 2 & 0x03 # scale bits
  440. p *= 2 ** sf
  441. value = (p, 2, e)
  442. elif fo & 0x40: # infinite value
  443. if LOG:
  444. LOG('decoding infinite REAL')
  445. value = fo & 0x01 and '-inf' or 'inf'
  446. elif fo & 0xc0 == 0: # character encoding
  447. if not chunk:
  448. raise error.PyAsn1Error("Incomplete floating-point value")
  449. if LOG:
  450. LOG('decoding character encoded REAL')
  451. try:
  452. if fo & 0x3 == 0x1: # NR1
  453. value = (int(chunk), 10, 0)
  454. elif fo & 0x3 == 0x2: # NR2
  455. value = float(chunk)
  456. elif fo & 0x3 == 0x3: # NR3
  457. value = float(chunk)
  458. else:
  459. raise error.SubstrateUnderrunError(
  460. 'Unknown NR (tag %s)' % fo
  461. )
  462. except ValueError:
  463. raise error.SubstrateUnderrunError(
  464. 'Bad character Real syntax'
  465. )
  466. else:
  467. raise error.SubstrateUnderrunError(
  468. 'Unknown encoding (tag %s)' % fo
  469. )
  470. yield self._createComponent(asn1Spec, tagSet, value, **options)
  471. class AbstractConstructedPayloadDecoder(AbstractPayloadDecoder):
  472. protoComponent = None
  473. class ConstructedPayloadDecoderBase(AbstractConstructedPayloadDecoder):
  474. protoRecordComponent = None
  475. protoSequenceComponent = None
  476. def _getComponentTagMap(self, asn1Object, idx):
  477. raise NotImplementedError
  478. def _getComponentPositionByType(self, asn1Object, tagSet, idx):
  479. raise NotImplementedError
  480. def _decodeComponentsSchemaless(
  481. self, substrate, tagSet=None, decodeFun=None,
  482. length=None, **options):
  483. asn1Object = None
  484. components = []
  485. componentTypes = set()
  486. original_position = substrate.tell()
  487. while length == -1 or substrate.tell() < original_position + length:
  488. for component in decodeFun(substrate, **options):
  489. if isinstance(component, SubstrateUnderrunError):
  490. yield component
  491. if length == -1 and component is eoo.endOfOctets:
  492. break
  493. components.append(component)
  494. componentTypes.add(component.tagSet)
  495. # Now we have to guess is it SEQUENCE/SET or SEQUENCE OF/SET OF
  496. # The heuristics is:
  497. # * 1+ components of different types -> likely SEQUENCE/SET
  498. # * otherwise -> likely SEQUENCE OF/SET OF
  499. if len(componentTypes) > 1:
  500. protoComponent = self.protoRecordComponent
  501. else:
  502. protoComponent = self.protoSequenceComponent
  503. asn1Object = protoComponent.clone(
  504. # construct tagSet from base tag from prototype ASN.1 object
  505. # and additional tags recovered from the substrate
  506. tagSet=tag.TagSet(protoComponent.tagSet.baseTag, *tagSet.superTags)
  507. )
  508. if LOG:
  509. LOG('guessed %r container type (pass `asn1Spec` to guide the '
  510. 'decoder)' % asn1Object)
  511. for idx, component in enumerate(components):
  512. asn1Object.setComponentByPosition(
  513. idx, component,
  514. verifyConstraints=False,
  515. matchTags=False, matchConstraints=False
  516. )
  517. yield asn1Object
  518. def valueDecoder(self, substrate, asn1Spec,
  519. tagSet=None, length=None, state=None,
  520. decodeFun=None, substrateFun=None,
  521. **options):
  522. if tagSet[0].tagFormat != tag.tagFormatConstructed:
  523. raise error.PyAsn1Error('Constructed tag format expected')
  524. original_position = substrate.tell()
  525. if substrateFun:
  526. if asn1Spec is not None:
  527. asn1Object = asn1Spec.clone()
  528. elif self.protoComponent is not None:
  529. asn1Object = self.protoComponent.clone(tagSet=tagSet)
  530. else:
  531. asn1Object = self.protoRecordComponent, self.protoSequenceComponent
  532. for chunk in substrateFun(asn1Object, substrate, length, options):
  533. yield chunk
  534. return
  535. if asn1Spec is None:
  536. for asn1Object in self._decodeComponentsSchemaless(
  537. substrate, tagSet=tagSet, decodeFun=decodeFun,
  538. length=length, **options):
  539. if isinstance(asn1Object, SubstrateUnderrunError):
  540. yield asn1Object
  541. if substrate.tell() < original_position + length:
  542. if LOG:
  543. for trailing in readFromStream(substrate, context=options):
  544. if isinstance(trailing, SubstrateUnderrunError):
  545. yield trailing
  546. LOG('Unused trailing %d octets encountered: %s' % (
  547. len(trailing), debug.hexdump(trailing)))
  548. yield asn1Object
  549. return
  550. asn1Object = asn1Spec.clone()
  551. asn1Object.clear()
  552. options = self._passAsn1Object(asn1Object, options)
  553. if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId):
  554. namedTypes = asn1Spec.componentType
  555. isSetType = asn1Spec.typeId == univ.Set.typeId
  556. isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault
  557. if LOG:
  558. LOG('decoding %sdeterministic %s type %r chosen by type ID' % (
  559. not isDeterministic and 'non-' or '', isSetType and 'SET' or '',
  560. asn1Spec))
  561. seenIndices = set()
  562. idx = 0
  563. while substrate.tell() - original_position < length:
  564. if not namedTypes:
  565. componentType = None
  566. elif isSetType:
  567. componentType = namedTypes.tagMapUnique
  568. else:
  569. try:
  570. if isDeterministic:
  571. componentType = namedTypes[idx].asn1Object
  572. elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:
  573. componentType = namedTypes.getTagMapNearPosition(idx)
  574. else:
  575. componentType = namedTypes[idx].asn1Object
  576. except IndexError:
  577. raise error.PyAsn1Error(
  578. 'Excessive components decoded at %r' % (asn1Spec,)
  579. )
  580. for component in decodeFun(substrate, componentType, **options):
  581. if isinstance(component, SubstrateUnderrunError):
  582. yield component
  583. if not isDeterministic and namedTypes:
  584. if isSetType:
  585. idx = namedTypes.getPositionByType(component.effectiveTagSet)
  586. elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:
  587. idx = namedTypes.getPositionNearType(component.effectiveTagSet, idx)
  588. asn1Object.setComponentByPosition(
  589. idx, component,
  590. verifyConstraints=False,
  591. matchTags=False, matchConstraints=False
  592. )
  593. seenIndices.add(idx)
  594. idx += 1
  595. if LOG:
  596. LOG('seen component indices %s' % seenIndices)
  597. if namedTypes:
  598. if not namedTypes.requiredComponents.issubset(seenIndices):
  599. raise error.PyAsn1Error(
  600. 'ASN.1 object %s has uninitialized '
  601. 'components' % asn1Object.__class__.__name__)
  602. if namedTypes.hasOpenTypes:
  603. openTypes = options.get('openTypes', {})
  604. if LOG:
  605. LOG('user-specified open types map:')
  606. for k, v in openTypes.items():
  607. LOG('%s -> %r' % (k, v))
  608. if openTypes or options.get('decodeOpenTypes', False):
  609. for idx, namedType in enumerate(namedTypes.namedTypes):
  610. if not namedType.openType:
  611. continue
  612. if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue:
  613. continue
  614. governingValue = asn1Object.getComponentByName(
  615. namedType.openType.name
  616. )
  617. try:
  618. openType = openTypes[governingValue]
  619. except KeyError:
  620. if LOG:
  621. LOG('default open types map of component '
  622. '"%s.%s" governed by component "%s.%s"'
  623. ':' % (asn1Object.__class__.__name__,
  624. namedType.name,
  625. asn1Object.__class__.__name__,
  626. namedType.openType.name))
  627. for k, v in namedType.openType.items():
  628. LOG('%s -> %r' % (k, v))
  629. try:
  630. openType = namedType.openType[governingValue]
  631. except KeyError:
  632. if LOG:
  633. LOG('failed to resolve open type by governing '
  634. 'value %r' % (governingValue,))
  635. continue
  636. if LOG:
  637. LOG('resolved open type %r by governing '
  638. 'value %r' % (openType, governingValue))
  639. containerValue = asn1Object.getComponentByPosition(idx)
  640. if containerValue.typeId in (
  641. univ.SetOf.typeId, univ.SequenceOf.typeId):
  642. for pos, containerElement in enumerate(
  643. containerValue):
  644. stream = asSeekableStream(containerValue[pos].asOctets())
  645. for component in decodeFun(stream, asn1Spec=openType, **options):
  646. if isinstance(component, SubstrateUnderrunError):
  647. yield component
  648. containerValue[pos] = component
  649. else:
  650. stream = asSeekableStream(asn1Object.getComponentByPosition(idx).asOctets())
  651. for component in decodeFun(stream, asn1Spec=openType, **options):
  652. if isinstance(component, SubstrateUnderrunError):
  653. yield component
  654. asn1Object.setComponentByPosition(idx, component)
  655. else:
  656. inconsistency = asn1Object.isInconsistent
  657. if inconsistency:
  658. raise error.PyAsn1Error(
  659. f"ASN.1 object {asn1Object.__class__.__name__} is inconsistent")
  660. else:
  661. componentType = asn1Spec.componentType
  662. if LOG:
  663. LOG('decoding type %r chosen by given `asn1Spec`' % componentType)
  664. idx = 0
  665. while substrate.tell() - original_position < length:
  666. for component in decodeFun(substrate, componentType, **options):
  667. if isinstance(component, SubstrateUnderrunError):
  668. yield component
  669. asn1Object.setComponentByPosition(
  670. idx, component,
  671. verifyConstraints=False,
  672. matchTags=False, matchConstraints=False
  673. )
  674. idx += 1
  675. yield asn1Object
  676. def indefLenValueDecoder(self, substrate, asn1Spec,
  677. tagSet=None, length=None, state=None,
  678. decodeFun=None, substrateFun=None,
  679. **options):
  680. if tagSet[0].tagFormat != tag.tagFormatConstructed:
  681. raise error.PyAsn1Error('Constructed tag format expected')
  682. if substrateFun is not None:
  683. if asn1Spec is not None:
  684. asn1Object = asn1Spec.clone()
  685. elif self.protoComponent is not None:
  686. asn1Object = self.protoComponent.clone(tagSet=tagSet)
  687. else:
  688. asn1Object = self.protoRecordComponent, self.protoSequenceComponent
  689. for chunk in substrateFun(asn1Object, substrate, length, options):
  690. yield chunk
  691. return
  692. if asn1Spec is None:
  693. for asn1Object in self._decodeComponentsSchemaless(
  694. substrate, tagSet=tagSet, decodeFun=decodeFun,
  695. length=length, **dict(options, allowEoo=True)):
  696. if isinstance(asn1Object, SubstrateUnderrunError):
  697. yield asn1Object
  698. yield asn1Object
  699. return
  700. asn1Object = asn1Spec.clone()
  701. asn1Object.clear()
  702. options = self._passAsn1Object(asn1Object, options)
  703. if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId):
  704. namedTypes = asn1Object.componentType
  705. isSetType = asn1Object.typeId == univ.Set.typeId
  706. isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault
  707. if LOG:
  708. LOG('decoding %sdeterministic %s type %r chosen by type ID' % (
  709. not isDeterministic and 'non-' or '', isSetType and 'SET' or '',
  710. asn1Spec))
  711. seenIndices = set()
  712. idx = 0
  713. while True: # loop over components
  714. if len(namedTypes) <= idx:
  715. asn1Spec = None
  716. elif isSetType:
  717. asn1Spec = namedTypes.tagMapUnique
  718. else:
  719. try:
  720. if isDeterministic:
  721. asn1Spec = namedTypes[idx].asn1Object
  722. elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:
  723. asn1Spec = namedTypes.getTagMapNearPosition(idx)
  724. else:
  725. asn1Spec = namedTypes[idx].asn1Object
  726. except IndexError:
  727. raise error.PyAsn1Error(
  728. 'Excessive components decoded at %r' % (asn1Object,)
  729. )
  730. for component in decodeFun(substrate, asn1Spec, allowEoo=True, **options):
  731. if isinstance(component, SubstrateUnderrunError):
  732. yield component
  733. if component is eoo.endOfOctets:
  734. break
  735. if component is eoo.endOfOctets:
  736. break
  737. if not isDeterministic and namedTypes:
  738. if isSetType:
  739. idx = namedTypes.getPositionByType(component.effectiveTagSet)
  740. elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:
  741. idx = namedTypes.getPositionNearType(component.effectiveTagSet, idx)
  742. asn1Object.setComponentByPosition(
  743. idx, component,
  744. verifyConstraints=False,
  745. matchTags=False, matchConstraints=False
  746. )
  747. seenIndices.add(idx)
  748. idx += 1
  749. if LOG:
  750. LOG('seen component indices %s' % seenIndices)
  751. if namedTypes:
  752. if not namedTypes.requiredComponents.issubset(seenIndices):
  753. raise error.PyAsn1Error(
  754. 'ASN.1 object %s has uninitialized '
  755. 'components' % asn1Object.__class__.__name__)
  756. if namedTypes.hasOpenTypes:
  757. openTypes = options.get('openTypes', {})
  758. if LOG:
  759. LOG('user-specified open types map:')
  760. for k, v in openTypes.items():
  761. LOG('%s -> %r' % (k, v))
  762. if openTypes or options.get('decodeOpenTypes', False):
  763. for idx, namedType in enumerate(namedTypes.namedTypes):
  764. if not namedType.openType:
  765. continue
  766. if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue:
  767. continue
  768. governingValue = asn1Object.getComponentByName(
  769. namedType.openType.name
  770. )
  771. try:
  772. openType = openTypes[governingValue]
  773. except KeyError:
  774. if LOG:
  775. LOG('default open types map of component '
  776. '"%s.%s" governed by component "%s.%s"'
  777. ':' % (asn1Object.__class__.__name__,
  778. namedType.name,
  779. asn1Object.__class__.__name__,
  780. namedType.openType.name))
  781. for k, v in namedType.openType.items():
  782. LOG('%s -> %r' % (k, v))
  783. try:
  784. openType = namedType.openType[governingValue]
  785. except KeyError:
  786. if LOG:
  787. LOG('failed to resolve open type by governing '
  788. 'value %r' % (governingValue,))
  789. continue
  790. if LOG:
  791. LOG('resolved open type %r by governing '
  792. 'value %r' % (openType, governingValue))
  793. containerValue = asn1Object.getComponentByPosition(idx)
  794. if containerValue.typeId in (
  795. univ.SetOf.typeId, univ.SequenceOf.typeId):
  796. for pos, containerElement in enumerate(
  797. containerValue):
  798. stream = asSeekableStream(containerValue[pos].asOctets())
  799. for component in decodeFun(stream, asn1Spec=openType,
  800. **dict(options, allowEoo=True)):
  801. if isinstance(component, SubstrateUnderrunError):
  802. yield component
  803. if component is eoo.endOfOctets:
  804. break
  805. containerValue[pos] = component
  806. else:
  807. stream = asSeekableStream(asn1Object.getComponentByPosition(idx).asOctets())
  808. for component in decodeFun(stream, asn1Spec=openType,
  809. **dict(options, allowEoo=True)):
  810. if isinstance(component, SubstrateUnderrunError):
  811. yield component
  812. if component is eoo.endOfOctets:
  813. break
  814. asn1Object.setComponentByPosition(idx, component)
  815. else:
  816. inconsistency = asn1Object.isInconsistent
  817. if inconsistency:
  818. raise error.PyAsn1Error(
  819. f"ASN.1 object {asn1Object.__class__.__name__} is inconsistent")
  820. else:
  821. componentType = asn1Spec.componentType
  822. if LOG:
  823. LOG('decoding type %r chosen by given `asn1Spec`' % componentType)
  824. idx = 0
  825. while True:
  826. for component in decodeFun(
  827. substrate, componentType, allowEoo=True, **options):
  828. if isinstance(component, SubstrateUnderrunError):
  829. yield component
  830. if component is eoo.endOfOctets:
  831. break
  832. if component is eoo.endOfOctets:
  833. break
  834. asn1Object.setComponentByPosition(
  835. idx, component,
  836. verifyConstraints=False,
  837. matchTags=False, matchConstraints=False
  838. )
  839. idx += 1
  840. yield asn1Object
  841. class SequenceOrSequenceOfPayloadDecoder(ConstructedPayloadDecoderBase):
  842. protoRecordComponent = univ.Sequence()
  843. protoSequenceComponent = univ.SequenceOf()
  844. class SequencePayloadDecoder(SequenceOrSequenceOfPayloadDecoder):
  845. protoComponent = univ.Sequence()
  846. class SequenceOfPayloadDecoder(SequenceOrSequenceOfPayloadDecoder):
  847. protoComponent = univ.SequenceOf()
  848. class SetOrSetOfPayloadDecoder(ConstructedPayloadDecoderBase):
  849. protoRecordComponent = univ.Set()
  850. protoSequenceComponent = univ.SetOf()
  851. class SetPayloadDecoder(SetOrSetOfPayloadDecoder):
  852. protoComponent = univ.Set()
  853. class SetOfPayloadDecoder(SetOrSetOfPayloadDecoder):
  854. protoComponent = univ.SetOf()
  855. class ChoicePayloadDecoder(ConstructedPayloadDecoderBase):
  856. protoComponent = univ.Choice()
  857. def valueDecoder(self, substrate, asn1Spec,
  858. tagSet=None, length=None, state=None,
  859. decodeFun=None, substrateFun=None,
  860. **options):
  861. if asn1Spec is None:
  862. asn1Object = self.protoComponent.clone(tagSet=tagSet)
  863. else:
  864. asn1Object = asn1Spec.clone()
  865. if substrateFun:
  866. for chunk in substrateFun(asn1Object, substrate, length, options):
  867. yield chunk
  868. return
  869. options = self._passAsn1Object(asn1Object, options)
  870. if asn1Object.tagSet == tagSet:
  871. if LOG:
  872. LOG('decoding %s as explicitly tagged CHOICE' % (tagSet,))
  873. for component in decodeFun(
  874. substrate, asn1Object.componentTagMap, **options):
  875. if isinstance(component, SubstrateUnderrunError):
  876. yield component
  877. else:
  878. if LOG:
  879. LOG('decoding %s as untagged CHOICE' % (tagSet,))
  880. for component in decodeFun(
  881. substrate, asn1Object.componentTagMap, tagSet, length,
  882. state, **options):
  883. if isinstance(component, SubstrateUnderrunError):
  884. yield component
  885. effectiveTagSet = component.effectiveTagSet
  886. if LOG:
  887. LOG('decoded component %s, effective tag set %s' % (component, effectiveTagSet))
  888. asn1Object.setComponentByType(
  889. effectiveTagSet, component,
  890. verifyConstraints=False,
  891. matchTags=False, matchConstraints=False,
  892. innerFlag=False
  893. )
  894. yield asn1Object
  895. def indefLenValueDecoder(self, substrate, asn1Spec,
  896. tagSet=None, length=None, state=None,
  897. decodeFun=None, substrateFun=None,
  898. **options):
  899. if asn1Spec is None:
  900. asn1Object = self.protoComponent.clone(tagSet=tagSet)
  901. else:
  902. asn1Object = asn1Spec.clone()
  903. if substrateFun:
  904. for chunk in substrateFun(asn1Object, substrate, length, options):
  905. yield chunk
  906. return
  907. options = self._passAsn1Object(asn1Object, options)
  908. isTagged = asn1Object.tagSet == tagSet
  909. if LOG:
  910. LOG('decoding %s as %stagged CHOICE' % (
  911. tagSet, isTagged and 'explicitly ' or 'un'))
  912. while True:
  913. if isTagged:
  914. iterator = decodeFun(
  915. substrate, asn1Object.componentType.tagMapUnique,
  916. **dict(options, allowEoo=True))
  917. else:
  918. iterator = decodeFun(
  919. substrate, asn1Object.componentType.tagMapUnique,
  920. tagSet, length, state, **dict(options, allowEoo=True))
  921. for component in iterator:
  922. if isinstance(component, SubstrateUnderrunError):
  923. yield component
  924. if component is eoo.endOfOctets:
  925. break
  926. effectiveTagSet = component.effectiveTagSet
  927. if LOG:
  928. LOG('decoded component %s, effective tag set '
  929. '%s' % (component, effectiveTagSet))
  930. asn1Object.setComponentByType(
  931. effectiveTagSet, component,
  932. verifyConstraints=False,
  933. matchTags=False, matchConstraints=False,
  934. innerFlag=False
  935. )
  936. if not isTagged:
  937. break
  938. if not isTagged or component is eoo.endOfOctets:
  939. break
  940. yield asn1Object
  941. class AnyPayloadDecoder(AbstractSimplePayloadDecoder):
  942. protoComponent = univ.Any()
  943. def valueDecoder(self, substrate, asn1Spec,
  944. tagSet=None, length=None, state=None,
  945. decodeFun=None, substrateFun=None,
  946. **options):
  947. if asn1Spec is None:
  948. isUntagged = True
  949. elif asn1Spec.__class__ is tagmap.TagMap:
  950. isUntagged = tagSet not in asn1Spec.tagMap
  951. else:
  952. isUntagged = tagSet != asn1Spec.tagSet
  953. if isUntagged:
  954. fullPosition = substrate.markedPosition
  955. currentPosition = substrate.tell()
  956. substrate.seek(fullPosition, os.SEEK_SET)
  957. length += currentPosition - fullPosition
  958. if LOG:
  959. for chunk in peekIntoStream(substrate, length):
  960. if isinstance(chunk, SubstrateUnderrunError):
  961. yield chunk
  962. LOG('decoding as untagged ANY, substrate '
  963. '%s' % debug.hexdump(chunk))
  964. if substrateFun:
  965. for chunk in substrateFun(
  966. self._createComponent(asn1Spec, tagSet, noValue, **options),
  967. substrate, length, options):
  968. yield chunk
  969. return
  970. for chunk in readFromStream(substrate, length, options):
  971. if isinstance(chunk, SubstrateUnderrunError):
  972. yield chunk
  973. yield self._createComponent(asn1Spec, tagSet, chunk, **options)
  974. def indefLenValueDecoder(self, substrate, asn1Spec,
  975. tagSet=None, length=None, state=None,
  976. decodeFun=None, substrateFun=None,
  977. **options):
  978. if asn1Spec is None:
  979. isTagged = False
  980. elif asn1Spec.__class__ is tagmap.TagMap:
  981. isTagged = tagSet in asn1Spec.tagMap
  982. else:
  983. isTagged = tagSet == asn1Spec.tagSet
  984. if isTagged:
  985. # tagged Any type -- consume header substrate
  986. chunk = b''
  987. if LOG:
  988. LOG('decoding as tagged ANY')
  989. else:
  990. # TODO: Seems not to be tested
  991. fullPosition = substrate.markedPosition
  992. currentPosition = substrate.tell()
  993. substrate.seek(fullPosition, os.SEEK_SET)
  994. for chunk in readFromStream(substrate, currentPosition - fullPosition, options):
  995. if isinstance(chunk, SubstrateUnderrunError):
  996. yield chunk
  997. if LOG:
  998. LOG('decoding as untagged ANY, header substrate %s' % debug.hexdump(chunk))
  999. # Any components do not inherit initial tag
  1000. asn1Spec = self.protoComponent
  1001. if substrateFun and substrateFun is not self.substrateCollector:
  1002. asn1Object = self._createComponent(
  1003. asn1Spec, tagSet, noValue, **options)
  1004. for chunk in substrateFun(
  1005. asn1Object, chunk + substrate, length + len(chunk), options):
  1006. yield chunk
  1007. return
  1008. if LOG:
  1009. LOG('assembling constructed serialization')
  1010. # All inner fragments are of the same type, treat them as octet string
  1011. substrateFun = self.substrateCollector
  1012. while True: # loop over fragments
  1013. for component in decodeFun(
  1014. substrate, asn1Spec, substrateFun=substrateFun,
  1015. allowEoo=True, **options):
  1016. if isinstance(component, SubstrateUnderrunError):
  1017. yield component
  1018. if component is eoo.endOfOctets:
  1019. break
  1020. if component is eoo.endOfOctets:
  1021. break
  1022. chunk += component
  1023. if substrateFun:
  1024. yield chunk # TODO: Weird
  1025. else:
  1026. yield self._createComponent(asn1Spec, tagSet, chunk, **options)
  1027. # character string types
  1028. class UTF8StringPayloadDecoder(OctetStringPayloadDecoder):
  1029. protoComponent = char.UTF8String()
  1030. class NumericStringPayloadDecoder(OctetStringPayloadDecoder):
  1031. protoComponent = char.NumericString()
  1032. class PrintableStringPayloadDecoder(OctetStringPayloadDecoder):
  1033. protoComponent = char.PrintableString()
  1034. class TeletexStringPayloadDecoder(OctetStringPayloadDecoder):
  1035. protoComponent = char.TeletexString()
  1036. class VideotexStringPayloadDecoder(OctetStringPayloadDecoder):
  1037. protoComponent = char.VideotexString()
  1038. class IA5StringPayloadDecoder(OctetStringPayloadDecoder):
  1039. protoComponent = char.IA5String()
  1040. class GraphicStringPayloadDecoder(OctetStringPayloadDecoder):
  1041. protoComponent = char.GraphicString()
  1042. class VisibleStringPayloadDecoder(OctetStringPayloadDecoder):
  1043. protoComponent = char.VisibleString()
  1044. class GeneralStringPayloadDecoder(OctetStringPayloadDecoder):
  1045. protoComponent = char.GeneralString()
  1046. class UniversalStringPayloadDecoder(OctetStringPayloadDecoder):
  1047. protoComponent = char.UniversalString()
  1048. class BMPStringPayloadDecoder(OctetStringPayloadDecoder):
  1049. protoComponent = char.BMPString()
  1050. # "useful" types
  1051. class ObjectDescriptorPayloadDecoder(OctetStringPayloadDecoder):
  1052. protoComponent = useful.ObjectDescriptor()
  1053. class GeneralizedTimePayloadDecoder(OctetStringPayloadDecoder):
  1054. protoComponent = useful.GeneralizedTime()
  1055. class UTCTimePayloadDecoder(OctetStringPayloadDecoder):
  1056. protoComponent = useful.UTCTime()
  1057. TAG_MAP = {
  1058. univ.Integer.tagSet: IntegerPayloadDecoder(),
  1059. univ.Boolean.tagSet: BooleanPayloadDecoder(),
  1060. univ.BitString.tagSet: BitStringPayloadDecoder(),
  1061. univ.OctetString.tagSet: OctetStringPayloadDecoder(),
  1062. univ.Null.tagSet: NullPayloadDecoder(),
  1063. univ.ObjectIdentifier.tagSet: ObjectIdentifierPayloadDecoder(),
  1064. univ.RelativeOID.tagSet: RelativeOIDPayloadDecoder(),
  1065. univ.Enumerated.tagSet: IntegerPayloadDecoder(),
  1066. univ.Real.tagSet: RealPayloadDecoder(),
  1067. univ.Sequence.tagSet: SequenceOrSequenceOfPayloadDecoder(), # conflicts with SequenceOf
  1068. univ.Set.tagSet: SetOrSetOfPayloadDecoder(), # conflicts with SetOf
  1069. univ.Choice.tagSet: ChoicePayloadDecoder(), # conflicts with Any
  1070. # character string types
  1071. char.UTF8String.tagSet: UTF8StringPayloadDecoder(),
  1072. char.NumericString.tagSet: NumericStringPayloadDecoder(),
  1073. char.PrintableString.tagSet: PrintableStringPayloadDecoder(),
  1074. char.TeletexString.tagSet: TeletexStringPayloadDecoder(),
  1075. char.VideotexString.tagSet: VideotexStringPayloadDecoder(),
  1076. char.IA5String.tagSet: IA5StringPayloadDecoder(),
  1077. char.GraphicString.tagSet: GraphicStringPayloadDecoder(),
  1078. char.VisibleString.tagSet: VisibleStringPayloadDecoder(),
  1079. char.GeneralString.tagSet: GeneralStringPayloadDecoder(),
  1080. char.UniversalString.tagSet: UniversalStringPayloadDecoder(),
  1081. char.BMPString.tagSet: BMPStringPayloadDecoder(),
  1082. # useful types
  1083. useful.ObjectDescriptor.tagSet: ObjectDescriptorPayloadDecoder(),
  1084. useful.GeneralizedTime.tagSet: GeneralizedTimePayloadDecoder(),
  1085. useful.UTCTime.tagSet: UTCTimePayloadDecoder()
  1086. }
  1087. # Type-to-codec map for ambiguous ASN.1 types
  1088. TYPE_MAP = {
  1089. univ.Set.typeId: SetPayloadDecoder(),
  1090. univ.SetOf.typeId: SetOfPayloadDecoder(),
  1091. univ.Sequence.typeId: SequencePayloadDecoder(),
  1092. univ.SequenceOf.typeId: SequenceOfPayloadDecoder(),
  1093. univ.Choice.typeId: ChoicePayloadDecoder(),
  1094. univ.Any.typeId: AnyPayloadDecoder()
  1095. }
  1096. # Put in non-ambiguous types for faster codec lookup
  1097. for typeDecoder in TAG_MAP.values():
  1098. if typeDecoder.protoComponent is not None:
  1099. typeId = typeDecoder.protoComponent.__class__.typeId
  1100. if typeId is not None and typeId not in TYPE_MAP:
  1101. TYPE_MAP[typeId] = typeDecoder
  1102. (stDecodeTag,
  1103. stDecodeLength,
  1104. stGetValueDecoder,
  1105. stGetValueDecoderByAsn1Spec,
  1106. stGetValueDecoderByTag,
  1107. stTryAsExplicitTag,
  1108. stDecodeValue,
  1109. stDumpRawValue,
  1110. stErrorCondition,
  1111. stStop) = [x for x in range(10)]
  1112. EOO_SENTINEL = bytes((0, 0))
  1113. class SingleItemDecoder(object):
  1114. defaultErrorState = stErrorCondition
  1115. #defaultErrorState = stDumpRawValue
  1116. defaultRawDecoder = AnyPayloadDecoder()
  1117. supportIndefLength = True
  1118. TAG_MAP = TAG_MAP
  1119. TYPE_MAP = TYPE_MAP
  1120. def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **ignored):
  1121. self._tagMap = tagMap if tagMap is not _MISSING else self.TAG_MAP
  1122. self._typeMap = typeMap if typeMap is not _MISSING else self.TYPE_MAP
  1123. # Tag & TagSet objects caches
  1124. self._tagCache = {}
  1125. self._tagSetCache = {}
  1126. def __call__(self, substrate, asn1Spec=None,
  1127. tagSet=None, length=None, state=stDecodeTag,
  1128. decodeFun=None, substrateFun=None,
  1129. **options):
  1130. allowEoo = options.pop('allowEoo', False)
  1131. if LOG:
  1132. LOG('decoder called at scope %s with state %d, working with up '
  1133. 'to %s octets of substrate: '
  1134. '%s' % (debug.scope, state, length, substrate))
  1135. # Look for end-of-octets sentinel
  1136. if allowEoo and self.supportIndefLength:
  1137. for eoo_candidate in readFromStream(substrate, 2, options):
  1138. if isinstance(eoo_candidate, SubstrateUnderrunError):
  1139. yield eoo_candidate
  1140. if eoo_candidate == EOO_SENTINEL:
  1141. if LOG:
  1142. LOG('end-of-octets sentinel found')
  1143. yield eoo.endOfOctets
  1144. return
  1145. else:
  1146. substrate.seek(-2, os.SEEK_CUR)
  1147. tagMap = self._tagMap
  1148. typeMap = self._typeMap
  1149. tagCache = self._tagCache
  1150. tagSetCache = self._tagSetCache
  1151. value = noValue
  1152. substrate.markedPosition = substrate.tell()
  1153. while state is not stStop:
  1154. if state is stDecodeTag:
  1155. # Decode tag
  1156. isShortTag = True
  1157. for firstByte in readFromStream(substrate, 1, options):
  1158. if isinstance(firstByte, SubstrateUnderrunError):
  1159. yield firstByte
  1160. firstOctet = ord(firstByte)
  1161. try:
  1162. lastTag = tagCache[firstOctet]
  1163. except KeyError:
  1164. integerTag = firstOctet
  1165. tagClass = integerTag & 0xC0
  1166. tagFormat = integerTag & 0x20
  1167. tagId = integerTag & 0x1F
  1168. if tagId == 0x1F:
  1169. isShortTag = False
  1170. lengthOctetIdx = 0
  1171. tagId = 0
  1172. while True:
  1173. for integerByte in readFromStream(substrate, 1, options):
  1174. if isinstance(integerByte, SubstrateUnderrunError):
  1175. yield integerByte
  1176. if not integerByte:
  1177. raise error.SubstrateUnderrunError(
  1178. 'Short octet stream on long tag decoding'
  1179. )
  1180. integerTag = ord(integerByte)
  1181. lengthOctetIdx += 1
  1182. tagId <<= 7
  1183. tagId |= (integerTag & 0x7F)
  1184. if not integerTag & 0x80:
  1185. break
  1186. lastTag = tag.Tag(
  1187. tagClass=tagClass, tagFormat=tagFormat, tagId=tagId
  1188. )
  1189. if isShortTag:
  1190. # cache short tags
  1191. tagCache[firstOctet] = lastTag
  1192. if tagSet is None:
  1193. if isShortTag:
  1194. try:
  1195. tagSet = tagSetCache[firstOctet]
  1196. except KeyError:
  1197. # base tag not recovered
  1198. tagSet = tag.TagSet((), lastTag)
  1199. tagSetCache[firstOctet] = tagSet
  1200. else:
  1201. tagSet = tag.TagSet((), lastTag)
  1202. else:
  1203. tagSet = lastTag + tagSet
  1204. state = stDecodeLength
  1205. if LOG:
  1206. LOG('tag decoded into %s, decoding length' % tagSet)
  1207. if state is stDecodeLength:
  1208. # Decode length
  1209. for firstOctet in readFromStream(substrate, 1, options):
  1210. if isinstance(firstOctet, SubstrateUnderrunError):
  1211. yield firstOctet
  1212. firstOctet = ord(firstOctet)
  1213. if firstOctet < 128:
  1214. length = firstOctet
  1215. elif firstOctet > 128:
  1216. size = firstOctet & 0x7F
  1217. # encoded in size bytes
  1218. for encodedLength in readFromStream(substrate, size, options):
  1219. if isinstance(encodedLength, SubstrateUnderrunError):
  1220. yield encodedLength
  1221. encodedLength = list(encodedLength)
  1222. # missing check on maximum size, which shouldn't be a
  1223. # problem, we can handle more than is possible
  1224. if len(encodedLength) != size:
  1225. raise error.SubstrateUnderrunError(
  1226. '%s<%s at %s' % (size, len(encodedLength), tagSet)
  1227. )
  1228. length = 0
  1229. for lengthOctet in encodedLength:
  1230. length <<= 8
  1231. length |= lengthOctet
  1232. size += 1
  1233. else: # 128 means indefinite
  1234. length = -1
  1235. if length == -1 and not self.supportIndefLength:
  1236. raise error.PyAsn1Error('Indefinite length encoding not supported by this codec')
  1237. state = stGetValueDecoder
  1238. if LOG:
  1239. LOG('value length decoded into %d' % length)
  1240. if state is stGetValueDecoder:
  1241. if asn1Spec is None:
  1242. state = stGetValueDecoderByTag
  1243. else:
  1244. state = stGetValueDecoderByAsn1Spec
  1245. #
  1246. # There're two ways of creating subtypes in ASN.1 what influences
  1247. # decoder operation. These methods are:
  1248. # 1) Either base types used in or no IMPLICIT tagging has been
  1249. # applied on subtyping.
  1250. # 2) Subtype syntax drops base type information (by means of
  1251. # IMPLICIT tagging.
  1252. # The first case allows for complete tag recovery from substrate
  1253. # while the second one requires original ASN.1 type spec for
  1254. # decoding.
  1255. #
  1256. # In either case a set of tags (tagSet) is coming from substrate
  1257. # in an incremental, tag-by-tag fashion (this is the case of
  1258. # EXPLICIT tag which is most basic). Outermost tag comes first
  1259. # from the wire.
  1260. #
  1261. if state is stGetValueDecoderByTag:
  1262. try:
  1263. concreteDecoder = tagMap[tagSet]
  1264. except KeyError:
  1265. concreteDecoder = None
  1266. if concreteDecoder:
  1267. state = stDecodeValue
  1268. else:
  1269. try:
  1270. concreteDecoder = tagMap[tagSet[:1]]
  1271. except KeyError:
  1272. concreteDecoder = None
  1273. if concreteDecoder:
  1274. state = stDecodeValue
  1275. else:
  1276. state = stTryAsExplicitTag
  1277. if LOG:
  1278. LOG('codec %s chosen by a built-in type, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state is stDecodeValue and 'value' or 'as explicit tag'))
  1279. debug.scope.push(concreteDecoder is None and '?' or concreteDecoder.protoComponent.__class__.__name__)
  1280. if state is stGetValueDecoderByAsn1Spec:
  1281. if asn1Spec.__class__ is tagmap.TagMap:
  1282. try:
  1283. chosenSpec = asn1Spec[tagSet]
  1284. except KeyError:
  1285. chosenSpec = None
  1286. if LOG:
  1287. LOG('candidate ASN.1 spec is a map of:')
  1288. for firstOctet, v in asn1Spec.presentTypes.items():
  1289. LOG(' %s -> %s' % (firstOctet, v.__class__.__name__))
  1290. if asn1Spec.skipTypes:
  1291. LOG('but neither of: ')
  1292. for firstOctet, v in asn1Spec.skipTypes.items():
  1293. LOG(' %s -> %s' % (firstOctet, v.__class__.__name__))
  1294. LOG('new candidate ASN.1 spec is %s, chosen by %s' % (chosenSpec is None and '<none>' or chosenSpec.prettyPrintType(), tagSet))
  1295. elif tagSet == asn1Spec.tagSet or tagSet in asn1Spec.tagMap:
  1296. chosenSpec = asn1Spec
  1297. if LOG:
  1298. LOG('candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__)
  1299. else:
  1300. chosenSpec = None
  1301. if chosenSpec is not None:
  1302. try:
  1303. # ambiguous type or just faster codec lookup
  1304. concreteDecoder = typeMap[chosenSpec.typeId]
  1305. if LOG:
  1306. LOG('value decoder chosen for an ambiguous type by type ID %s' % (chosenSpec.typeId,))
  1307. except KeyError:
  1308. # use base type for codec lookup to recover untagged types
  1309. baseTagSet = tag.TagSet(chosenSpec.tagSet.baseTag, chosenSpec.tagSet.baseTag)
  1310. try:
  1311. # base type or tagged subtype
  1312. concreteDecoder = tagMap[baseTagSet]
  1313. if LOG:
  1314. LOG('value decoder chosen by base %s' % (baseTagSet,))
  1315. except KeyError:
  1316. concreteDecoder = None
  1317. if concreteDecoder:
  1318. asn1Spec = chosenSpec
  1319. state = stDecodeValue
  1320. else:
  1321. state = stTryAsExplicitTag
  1322. else:
  1323. concreteDecoder = None
  1324. state = stTryAsExplicitTag
  1325. if LOG:
  1326. LOG('codec %s chosen by ASN.1 spec, decoding %s' % (state is stDecodeValue and concreteDecoder.__class__.__name__ or "<none>", state is stDecodeValue and 'value' or 'as explicit tag'))
  1327. debug.scope.push(chosenSpec is None and '?' or chosenSpec.__class__.__name__)
  1328. if state is stDecodeValue:
  1329. if not options.get('recursiveFlag', True) and not substrateFun: # deprecate this
  1330. def substrateFun(asn1Object, _substrate, _length, _options):
  1331. """Legacy hack to keep the recursiveFlag=False option supported.
  1332. The decode(..., substrateFun=userCallback) option was introduced in 0.1.4 as a generalization
  1333. of the old recursiveFlag=False option. Users should pass their callback instead of using
  1334. recursiveFlag.
  1335. """
  1336. yield asn1Object
  1337. original_position = substrate.tell()
  1338. if length == -1: # indef length
  1339. for value in concreteDecoder.indefLenValueDecoder(
  1340. substrate, asn1Spec,
  1341. tagSet, length, stGetValueDecoder,
  1342. self, substrateFun, **options):
  1343. if isinstance(value, SubstrateUnderrunError):
  1344. yield value
  1345. else:
  1346. for value in concreteDecoder.valueDecoder(
  1347. substrate, asn1Spec,
  1348. tagSet, length, stGetValueDecoder,
  1349. self, substrateFun, **options):
  1350. if isinstance(value, SubstrateUnderrunError):
  1351. yield value
  1352. bytesRead = substrate.tell() - original_position
  1353. if not substrateFun and bytesRead != length:
  1354. raise PyAsn1Error(
  1355. "Read %s bytes instead of expected %s." % (bytesRead, length))
  1356. elif substrateFun and bytesRead > length:
  1357. # custom substrateFun may be used for partial decoding, reading less is expected there
  1358. raise PyAsn1Error(
  1359. "Read %s bytes are more than expected %s." % (bytesRead, length))
  1360. if LOG:
  1361. LOG('codec %s yields type %s, value:\n%s\n...' % (
  1362. concreteDecoder.__class__.__name__, value.__class__.__name__,
  1363. isinstance(value, base.Asn1Item) and value.prettyPrint() or value))
  1364. state = stStop
  1365. break
  1366. if state is stTryAsExplicitTag:
  1367. if (tagSet and
  1368. tagSet[0].tagFormat == tag.tagFormatConstructed and
  1369. tagSet[0].tagClass != tag.tagClassUniversal):
  1370. # Assume explicit tagging
  1371. concreteDecoder = rawPayloadDecoder
  1372. state = stDecodeValue
  1373. else:
  1374. concreteDecoder = None
  1375. state = self.defaultErrorState
  1376. if LOG:
  1377. LOG('codec %s chosen, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state is stDecodeValue and 'value' or 'as failure'))
  1378. if state is stDumpRawValue:
  1379. concreteDecoder = self.defaultRawDecoder
  1380. if LOG:
  1381. LOG('codec %s chosen, decoding value' % concreteDecoder.__class__.__name__)
  1382. state = stDecodeValue
  1383. if state is stErrorCondition:
  1384. raise error.PyAsn1Error(
  1385. '%s not in asn1Spec: %r' % (tagSet, asn1Spec)
  1386. )
  1387. if LOG:
  1388. debug.scope.pop()
  1389. LOG('decoder left scope %s, call completed' % debug.scope)
  1390. yield value
  1391. class StreamingDecoder(object):
  1392. """Create an iterator that turns BER/CER/DER byte stream into ASN.1 objects.
  1393. On each iteration, consume whatever BER/CER/DER serialization is
  1394. available in the `substrate` stream-like object and turns it into
  1395. one or more, possibly nested, ASN.1 objects.
  1396. Parameters
  1397. ----------
  1398. substrate: :py:class:`file`, :py:class:`io.BytesIO`
  1399. BER/CER/DER serialization in form of a byte stream
  1400. Keyword Args
  1401. ------------
  1402. asn1Spec: :py:class:`~pyasn1.type.base.PyAsn1Item`
  1403. A pyasn1 type object to act as a template guiding the decoder.
  1404. Depending on the ASN.1 structure being decoded, `asn1Spec` may
  1405. or may not be required. One of the reasons why `asn1Spec` may
  1406. me required is that ASN.1 structure is encoded in the *IMPLICIT*
  1407. tagging mode.
  1408. Yields
  1409. ------
  1410. : :py:class:`~pyasn1.type.base.PyAsn1Item`, :py:class:`~pyasn1.error.SubstrateUnderrunError`
  1411. Decoded ASN.1 object (possibly, nested) or
  1412. :py:class:`~pyasn1.error.SubstrateUnderrunError` object indicating
  1413. insufficient BER/CER/DER serialization on input to fully recover ASN.1
  1414. objects from it.
  1415. In the latter case the caller is advised to ensure some more data in
  1416. the input stream, then call the iterator again. The decoder will resume
  1417. the decoding process using the newly arrived data.
  1418. The `context` property of :py:class:`~pyasn1.error.SubstrateUnderrunError`
  1419. object might hold a reference to the partially populated ASN.1 object
  1420. being reconstructed.
  1421. Raises
  1422. ------
  1423. ~pyasn1.error.PyAsn1Error, ~pyasn1.error.EndOfStreamError
  1424. `PyAsn1Error` on deserialization error, `EndOfStreamError` on
  1425. premature stream closure.
  1426. Examples
  1427. --------
  1428. Decode BER serialisation without ASN.1 schema
  1429. .. code-block:: pycon
  1430. >>> stream = io.BytesIO(
  1431. ... b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03')
  1432. >>>
  1433. >>> for asn1Object in StreamingDecoder(stream):
  1434. ... print(asn1Object)
  1435. >>>
  1436. SequenceOf:
  1437. 1 2 3
  1438. Decode BER serialisation with ASN.1 schema
  1439. .. code-block:: pycon
  1440. >>> stream = io.BytesIO(
  1441. ... b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03')
  1442. >>>
  1443. >>> schema = SequenceOf(componentType=Integer())
  1444. >>>
  1445. >>> decoder = StreamingDecoder(stream, asn1Spec=schema)
  1446. >>> for asn1Object in decoder:
  1447. ... print(asn1Object)
  1448. >>>
  1449. SequenceOf:
  1450. 1 2 3
  1451. """
  1452. SINGLE_ITEM_DECODER = SingleItemDecoder
  1453. def __init__(self, substrate, asn1Spec=None, **options):
  1454. self._singleItemDecoder = self.SINGLE_ITEM_DECODER(**options)
  1455. self._substrate = asSeekableStream(substrate)
  1456. self._asn1Spec = asn1Spec
  1457. self._options = options
  1458. def __iter__(self):
  1459. while True:
  1460. for asn1Object in self._singleItemDecoder(
  1461. self._substrate, self._asn1Spec, **self._options):
  1462. yield asn1Object
  1463. for chunk in isEndOfStream(self._substrate):
  1464. if isinstance(chunk, SubstrateUnderrunError):
  1465. yield
  1466. break
  1467. if chunk:
  1468. break
  1469. class Decoder(object):
  1470. """Create a BER decoder object.
  1471. Parse BER/CER/DER octet-stream into one, possibly nested, ASN.1 object.
  1472. """
  1473. STREAMING_DECODER = StreamingDecoder
  1474. @classmethod
  1475. def __call__(cls, substrate, asn1Spec=None, **options):
  1476. """Turns BER/CER/DER octet stream into an ASN.1 object.
  1477. Takes BER/CER/DER octet-stream in form of :py:class:`bytes`
  1478. and decode it into an ASN.1 object
  1479. (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
  1480. may be a scalar or an arbitrary nested structure.
  1481. Parameters
  1482. ----------
  1483. substrate: :py:class:`bytes`
  1484. BER/CER/DER octet-stream to parse
  1485. Keyword Args
  1486. ------------
  1487. asn1Spec: :py:class:`~pyasn1.type.base.PyAsn1Item`
  1488. A pyasn1 type object (:py:class:`~pyasn1.type.base.PyAsn1Item`
  1489. derivative) to act as a template guiding the decoder.
  1490. Depending on the ASN.1 structure being decoded, `asn1Spec` may or
  1491. may not be required. Most common reason for it to require is that
  1492. ASN.1 structure is encoded in *IMPLICIT* tagging mode.
  1493. substrateFun: :py:class:`Union[
  1494. Callable[[pyasn1.type.base.PyAsn1Item, bytes, int],
  1495. Tuple[pyasn1.type.base.PyAsn1Item, bytes]],
  1496. Callable[[pyasn1.type.base.PyAsn1Item, io.BytesIO, int, dict],
  1497. Generator[Union[pyasn1.type.base.PyAsn1Item,
  1498. pyasn1.error.SubstrateUnderrunError],
  1499. None, None]]
  1500. ]`
  1501. User callback meant to generalize special use cases like non-recursive or
  1502. partial decoding. A 3-arg non-streaming variant is supported for backwards
  1503. compatiblilty in addition to the newer 4-arg streaming variant.
  1504. The callback will receive the uninitialized object recovered from substrate
  1505. as 1st argument, the uninterpreted payload as 2nd argument, and the length
  1506. of the uninterpreted payload as 3rd argument. The streaming variant will
  1507. additionally receive the decode(..., **options) kwargs as 4th argument.
  1508. The non-streaming variant shall return an object that will be propagated
  1509. as decode() return value as 1st item, and the remainig payload for further
  1510. decode passes as 2nd item.
  1511. The streaming variant shall yield an object that will be propagated as
  1512. decode() return value, and leave the remaining payload in the stream.
  1513. Returns
  1514. -------
  1515. : :py:class:`tuple`
  1516. A tuple of :py:class:`~pyasn1.type.base.PyAsn1Item` object
  1517. recovered from BER/CER/DER substrate and the unprocessed trailing
  1518. portion of the `substrate` (may be empty)
  1519. Raises
  1520. ------
  1521. : :py:class:`~pyasn1.error.PyAsn1Error`
  1522. :py:class:`~pyasn1.error.SubstrateUnderrunError` on insufficient
  1523. input or :py:class:`~pyasn1.error.PyAsn1Error` on decoding error.
  1524. Examples
  1525. --------
  1526. Decode BER/CER/DER serialisation without ASN.1 schema
  1527. .. code-block:: pycon
  1528. >>> s, unprocessed = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03')
  1529. >>> str(s)
  1530. SequenceOf:
  1531. 1 2 3
  1532. Decode BER/CER/DER serialisation with ASN.1 schema
  1533. .. code-block:: pycon
  1534. >>> seq = SequenceOf(componentType=Integer())
  1535. >>> s, unprocessed = decode(
  1536. b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03', asn1Spec=seq)
  1537. >>> str(s)
  1538. SequenceOf:
  1539. 1 2 3
  1540. """
  1541. substrate = asSeekableStream(substrate)
  1542. if "substrateFun" in options:
  1543. origSubstrateFun = options["substrateFun"]
  1544. def substrateFunWrapper(asn1Object, substrate, length, options=None):
  1545. """Support both 0.4 and 0.5 style APIs.
  1546. substrateFun API has changed in 0.5 for use with streaming decoders. To stay backwards compatible,
  1547. we first try if we received a streaming user callback. If that fails,we assume we've received a
  1548. non-streaming v0.4 user callback and convert it for streaming on the fly
  1549. """
  1550. try:
  1551. substrate_gen = origSubstrateFun(asn1Object, substrate, length, options)
  1552. except TypeError as _value:
  1553. if _value.__traceback__.tb_next:
  1554. # Traceback depth > 1 means TypeError from inside user provided function
  1555. raise
  1556. # invariant maintained at Decoder.__call__ entry
  1557. assert isinstance(substrate, io.BytesIO) # nosec assert_used
  1558. substrate_gen = Decoder._callSubstrateFunV4asV5(origSubstrateFun, asn1Object, substrate, length)
  1559. for value in substrate_gen:
  1560. yield value
  1561. options["substrateFun"] = substrateFunWrapper
  1562. streamingDecoder = cls.STREAMING_DECODER(
  1563. substrate, asn1Spec, **options)
  1564. for asn1Object in streamingDecoder:
  1565. if isinstance(asn1Object, SubstrateUnderrunError):
  1566. raise error.SubstrateUnderrunError('Short substrate on input')
  1567. try:
  1568. tail = next(readFromStream(substrate))
  1569. except error.EndOfStreamError:
  1570. tail = b''
  1571. return asn1Object, tail
  1572. @staticmethod
  1573. def _callSubstrateFunV4asV5(substrateFunV4, asn1Object, substrate, length):
  1574. substrate_bytes = substrate.read()
  1575. if length == -1:
  1576. length = len(substrate_bytes)
  1577. value, nextSubstrate = substrateFunV4(asn1Object, substrate_bytes, length)
  1578. nbytes = substrate.write(nextSubstrate)
  1579. substrate.truncate()
  1580. substrate.seek(-nbytes, os.SEEK_CUR)
  1581. yield value
  1582. #: Turns BER octet stream into an ASN.1 object.
  1583. #:
  1584. #: Takes BER octet-stream and decode it into an ASN.1 object
  1585. #: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
  1586. #: may be a scalar or an arbitrary nested structure.
  1587. #:
  1588. #: Parameters
  1589. #: ----------
  1590. #: substrate: :py:class:`bytes`
  1591. #: BER octet-stream
  1592. #:
  1593. #: Keyword Args
  1594. #: ------------
  1595. #: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
  1596. #: A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure
  1597. #: being decoded, *asn1Spec* may or may not be required. Most common reason for
  1598. #: it to require is that ASN.1 structure is encoded in *IMPLICIT* tagging mode.
  1599. #:
  1600. #: Returns
  1601. #: -------
  1602. #: : :py:class:`tuple`
  1603. #: A tuple of pyasn1 object recovered from BER substrate (:py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
  1604. #: and the unprocessed trailing portion of the *substrate* (may be empty)
  1605. #:
  1606. #: Raises
  1607. #: ------
  1608. #: ~pyasn1.error.PyAsn1Error, ~pyasn1.error.SubstrateUnderrunError
  1609. #: On decoding errors
  1610. #:
  1611. #: Notes
  1612. #: -----
  1613. #: This function is deprecated. Please use :py:class:`Decoder` or
  1614. #: :py:class:`StreamingDecoder` class instance.
  1615. #:
  1616. #: Examples
  1617. #: --------
  1618. #: Decode BER serialisation without ASN.1 schema
  1619. #:
  1620. #: .. code-block:: pycon
  1621. #:
  1622. #: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03')
  1623. #: >>> str(s)
  1624. #: SequenceOf:
  1625. #: 1 2 3
  1626. #:
  1627. #: Decode BER serialisation with ASN.1 schema
  1628. #:
  1629. #: .. code-block:: pycon
  1630. #:
  1631. #: >>> seq = SequenceOf(componentType=Integer())
  1632. #: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03', asn1Spec=seq)
  1633. #: >>> str(s)
  1634. #: SequenceOf:
  1635. #: 1 2 3
  1636. #:
  1637. decode = Decoder()
  1638. def __getattr__(attr: str):
  1639. if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr):
  1640. warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning)
  1641. return globals()[newAttr]
  1642. raise AttributeError(attr)