Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pyasn1/codec/cer/decoder.py: 68%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

50 statements  

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# 

7import warnings 

8 

9from pyasn1 import error 

10from pyasn1.codec.streaming import readFromStream 

11from pyasn1.codec.ber import decoder 

12from pyasn1.type import univ 

13 

14__all__ = ['decode', 'StreamingDecoder'] 

15 

16SubstrateUnderrunError = error.SubstrateUnderrunError 

17 

18 

19class BooleanPayloadDecoder(decoder.AbstractSimplePayloadDecoder): 

20 protoComponent = univ.Boolean(0) 

21 

22 def valueDecoder(self, substrate, asn1Spec, 

23 tagSet=None, length=None, state=None, 

24 decodeFun=None, substrateFun=None, 

25 **options): 

26 

27 if length != 1: 

28 raise error.PyAsn1Error('Not single-octet Boolean payload') 

29 

30 for chunk in readFromStream(substrate, length, options): 

31 if isinstance(chunk, SubstrateUnderrunError): 

32 yield chunk 

33 

34 byte = chunk[0] 

35 

36 # CER/DER specifies encoding of TRUE as 0xFF and FALSE as 0x0, while 

37 # BER allows any non-zero value as TRUE; cf. sections 8.2.2. and 11.1  

38 # in https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf 

39 if byte == 0xff: 

40 value = 1 

41 

42 elif byte == 0x00: 

43 value = 0 

44 

45 else: 

46 raise error.PyAsn1Error('Unexpected Boolean payload: %s' % byte) 

47 

48 yield self._createComponent(asn1Spec, tagSet, value, **options) 

49 

50 

51# TODO: prohibit non-canonical encoding 

52BitStringPayloadDecoder = decoder.BitStringPayloadDecoder 

53OctetStringPayloadDecoder = decoder.OctetStringPayloadDecoder 

54RealPayloadDecoder = decoder.RealPayloadDecoder 

55 

56TAG_MAP = decoder.TAG_MAP.copy() 

57TAG_MAP.update( 

58 {univ.Boolean.tagSet: BooleanPayloadDecoder(), 

59 univ.BitString.tagSet: BitStringPayloadDecoder(), 

60 univ.OctetString.tagSet: OctetStringPayloadDecoder(), 

61 univ.Real.tagSet: RealPayloadDecoder()} 

62) 

63 

64TYPE_MAP = decoder.TYPE_MAP.copy() 

65 

66# Put in non-ambiguous types for faster codec lookup 

67for typeDecoder in TAG_MAP.values(): 

68 if typeDecoder.protoComponent is not None: 

69 typeId = typeDecoder.protoComponent.__class__.typeId 

70 if typeId is not None and typeId not in TYPE_MAP: 

71 TYPE_MAP[typeId] = typeDecoder 

72 

73 

74class SingleItemDecoder(decoder.SingleItemDecoder): 

75 __doc__ = decoder.SingleItemDecoder.__doc__ 

76 

77 TAG_MAP = TAG_MAP 

78 TYPE_MAP = TYPE_MAP 

79 

80 

81class StreamingDecoder(decoder.StreamingDecoder): 

82 __doc__ = decoder.StreamingDecoder.__doc__ 

83 

84 SINGLE_ITEM_DECODER = SingleItemDecoder 

85 

86 

87class Decoder(decoder.Decoder): 

88 __doc__ = decoder.Decoder.__doc__ 

89 

90 STREAMING_DECODER = StreamingDecoder 

91 

92 

93#: Turns CER octet stream into an ASN.1 object. 

94#: 

95#: Takes CER octet-stream and decode it into an ASN.1 object 

96#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which 

97#: may be a scalar or an arbitrary nested structure. 

98#: 

99#: Parameters 

100#: ---------- 

101#: substrate: :py:class:`bytes` 

102#: CER octet-stream 

103#: 

104#: Keyword Args 

105#: ------------ 

106#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative 

107#: A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure 

108#: being decoded, *asn1Spec* may or may not be required. Most common reason for 

109#: it to require is that ASN.1 structure is encoded in *IMPLICIT* tagging mode. 

110#: 

111#: Returns 

112#: ------- 

113#: : :py:class:`tuple` 

114#: A tuple of pyasn1 object recovered from CER substrate (:py:class:`~pyasn1.type.base.PyAsn1Item` derivative) 

115#: and the unprocessed trailing portion of the *substrate* (may be empty) 

116#: 

117#: Raises 

118#: ------ 

119#: ~pyasn1.error.PyAsn1Error, ~pyasn1.error.SubstrateUnderrunError 

120#: On decoding errors 

121#: 

122#: Examples 

123#: -------- 

124#: Decode CER serialisation without ASN.1 schema 

125#: 

126#: .. code-block:: pycon 

127#: 

128#: >>> s, _ = decode(b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00') 

129#: >>> str(s) 

130#: SequenceOf: 

131#: 1 2 3 

132#: 

133#: Decode CER serialisation with ASN.1 schema 

134#: 

135#: .. code-block:: pycon 

136#: 

137#: >>> seq = SequenceOf(componentType=Integer()) 

138#: >>> s, _ = decode(b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00', asn1Spec=seq) 

139#: >>> str(s) 

140#: SequenceOf: 

141#: 1 2 3 

142#: 

143decode = Decoder() 

144 

145def __getattr__(attr: str): 

146 if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr): 

147 warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning) 

148 return globals()[newAttr] 

149 raise AttributeError(attr)