| 468 | |
| 469 | |
| 470 | class RelativeOIDPayloadDecoder(AbstractSimplePayloadDecoder): |
| 471 | protoComponent = univ.RelativeOID(()) |
| 472 | |
| 473 | def valueDecoder(self, substrate, asn1Spec, |
| 474 | tagSet=None, length=None, state=None, |
| 475 | decodeFun=None, substrateFun=None, |
| 476 | **options): |
| 477 | if tagSet[0].tagFormat != tag.tagFormatSimple: |
| 478 | raise error.PyAsn1Error('Simple tag format expected') |
| 479 | |
| 480 | for chunk in readFromStream(substrate, length, options): |
| 481 | if isinstance(chunk, SubstrateUnderrunError): |
| 482 | yield chunk |
| 483 | |
| 484 | if not chunk: |
| 485 | raise error.PyAsn1Error('Empty substrate') |
| 486 | |
| 487 | reloid = () |
| 488 | index = 0 |
| 489 | substrateLen = len(chunk) |
| 490 | while index < substrateLen: |
| 491 | subId = chunk[index] |
| 492 | index += 1 |
| 493 | if subId < 128: |
| 494 | reloid += (subId,) |
| 495 | elif subId > 128: |
| 496 | # Construct subid from a number of octets |
| 497 | nextSubId = subId |
| 498 | subId = 0 |
| 499 | continuationOctetCount = 0 |
| 500 | while nextSubId >= 128: |
| 501 | continuationOctetCount += 1 |
| 502 | if continuationOctetCount > MAX_OID_ARC_CONTINUATION_OCTETS: |
| 503 | raise error.PyAsn1Error( |
| 504 | 'RELATIVE-OID arc exceeds maximum continuation octets limit (%d) ' |
| 505 | 'at position %d' % (MAX_OID_ARC_CONTINUATION_OCTETS, index) |
| 506 | ) |
| 507 | subId = (subId << 7) + (nextSubId & 0x7F) |
| 508 | if index >= substrateLen: |
| 509 | raise error.SubstrateUnderrunError( |
| 510 | 'Short substrate for sub-OID past %s' % (reloid,) |
| 511 | ) |
| 512 | nextSubId = chunk[index] |
| 513 | index += 1 |
| 514 | reloid += ((subId << 7) + nextSubId,) |
| 515 | elif subId == 128: |
| 516 | # ASN.1 spec forbids leading zeros (0x80) in OID |
| 517 | # encoding, tolerating it opens a vulnerability. See |
| 518 | # https://www.esat.kuleuven.be/cosic/publications/article-1432.pdf |
| 519 | # page 7 |
| 520 | raise error.PyAsn1Error('Invalid octet 0x80 in RELATIVE-OID encoding') |
| 521 | |
| 522 | yield self._createComponent(asn1Spec, tagSet, reloid, **options) |
| 523 | |
| 524 | |
| 525 | class RealPayloadDecoder(AbstractSimplePayloadDecoder): |