decoder.py 79 KB

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