xref: /aosp_15_r20/external/cronet/net/data/ssl/scripts/asn1.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker# Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker# This file implements very minimal ASN.1, DER serialization.
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker
8*6777b538SAndroid Build Coastguard Workerdef ToDER(obj):
9*6777b538SAndroid Build Coastguard Worker  '''ToDER converts the given object into DER encoding'''
10*6777b538SAndroid Build Coastguard Worker  if obj is None:
11*6777b538SAndroid Build Coastguard Worker    # None turns into NULL
12*6777b538SAndroid Build Coastguard Worker    return TagAndLength(5, 0)
13*6777b538SAndroid Build Coastguard Worker  if isinstance(obj, (str, bytes)):
14*6777b538SAndroid Build Coastguard Worker    # There are many ASN.1 string types, so rather than pick one implicitly,
15*6777b538SAndroid Build Coastguard Worker    # require the caller explicitly specify the encoding with asn1.UTF8String,
16*6777b538SAndroid Build Coastguard Worker    # etc., below.
17*6777b538SAndroid Build Coastguard Worker    raise TypeError("String types must be specified explicitly")
18*6777b538SAndroid Build Coastguard Worker  if isinstance(obj, bool):
19*6777b538SAndroid Build Coastguard Worker    val = b"\x00"
20*6777b538SAndroid Build Coastguard Worker    if obj:
21*6777b538SAndroid Build Coastguard Worker      val = b"\xff"
22*6777b538SAndroid Build Coastguard Worker    return TagAndData(1, val)
23*6777b538SAndroid Build Coastguard Worker  if isinstance(obj, int):
24*6777b538SAndroid Build Coastguard Worker    big_endian = bytearray()
25*6777b538SAndroid Build Coastguard Worker    val = obj
26*6777b538SAndroid Build Coastguard Worker    while val != 0:
27*6777b538SAndroid Build Coastguard Worker      big_endian.append(val & 0xff)
28*6777b538SAndroid Build Coastguard Worker      val >>= 8
29*6777b538SAndroid Build Coastguard Worker
30*6777b538SAndroid Build Coastguard Worker    if len(big_endian) == 0 or big_endian[-1] >= 128:
31*6777b538SAndroid Build Coastguard Worker      big_endian.append(0)
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker    big_endian.reverse()
34*6777b538SAndroid Build Coastguard Worker    return TagAndData(2, bytes(big_endian))
35*6777b538SAndroid Build Coastguard Worker
36*6777b538SAndroid Build Coastguard Worker  return obj.ToDER()
37*6777b538SAndroid Build Coastguard Worker
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard Workerdef TagAndLength(tag, length):
40*6777b538SAndroid Build Coastguard Worker  der = bytearray([tag])
41*6777b538SAndroid Build Coastguard Worker  if length < 128:
42*6777b538SAndroid Build Coastguard Worker    der.append(length)
43*6777b538SAndroid Build Coastguard Worker  elif length < 256:
44*6777b538SAndroid Build Coastguard Worker    der.append(0x81)
45*6777b538SAndroid Build Coastguard Worker    der.append(length)
46*6777b538SAndroid Build Coastguard Worker  elif length < 65535:
47*6777b538SAndroid Build Coastguard Worker    der.append(0x82)
48*6777b538SAndroid Build Coastguard Worker    der.append(length >> 8)
49*6777b538SAndroid Build Coastguard Worker    der.append(length & 0xff)
50*6777b538SAndroid Build Coastguard Worker  else:
51*6777b538SAndroid Build Coastguard Worker    assert False
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker  return bytes(der)
54*6777b538SAndroid Build Coastguard Worker
55*6777b538SAndroid Build Coastguard Worker
56*6777b538SAndroid Build Coastguard Workerdef TagAndData(tag, data):
57*6777b538SAndroid Build Coastguard Worker  return TagAndLength(tag, len(data)) + data
58*6777b538SAndroid Build Coastguard Worker
59*6777b538SAndroid Build Coastguard Worker
60*6777b538SAndroid Build Coastguard Workerclass Raw(object):
61*6777b538SAndroid Build Coastguard Worker  '''Raw contains raw DER encoded bytes that are used verbatim'''
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Worker  def __init__(self, der):
64*6777b538SAndroid Build Coastguard Worker    self.der = der
65*6777b538SAndroid Build Coastguard Worker
66*6777b538SAndroid Build Coastguard Worker  def ToDER(self):
67*6777b538SAndroid Build Coastguard Worker    return self.der
68*6777b538SAndroid Build Coastguard Worker
69*6777b538SAndroid Build Coastguard Worker
70*6777b538SAndroid Build Coastguard Workerclass Explicit(object):
71*6777b538SAndroid Build Coastguard Worker  '''Explicit prepends an explicit tag'''
72*6777b538SAndroid Build Coastguard Worker
73*6777b538SAndroid Build Coastguard Worker  def __init__(self, tag, child):
74*6777b538SAndroid Build Coastguard Worker    self.tag = tag
75*6777b538SAndroid Build Coastguard Worker    self.child = child
76*6777b538SAndroid Build Coastguard Worker
77*6777b538SAndroid Build Coastguard Worker  def ToDER(self):
78*6777b538SAndroid Build Coastguard Worker    der = ToDER(self.child)
79*6777b538SAndroid Build Coastguard Worker    tag = self.tag
80*6777b538SAndroid Build Coastguard Worker    tag |= 0x80  # content specific
81*6777b538SAndroid Build Coastguard Worker    tag |= 0x20  # complex
82*6777b538SAndroid Build Coastguard Worker    return TagAndData(tag, der)
83*6777b538SAndroid Build Coastguard Worker
84*6777b538SAndroid Build Coastguard Worker
85*6777b538SAndroid Build Coastguard Workerclass ENUMERATED(object):
86*6777b538SAndroid Build Coastguard Worker  def __init__(self, value):
87*6777b538SAndroid Build Coastguard Worker    self.value = value
88*6777b538SAndroid Build Coastguard Worker
89*6777b538SAndroid Build Coastguard Worker  def ToDER(self):
90*6777b538SAndroid Build Coastguard Worker    return TagAndData(10, bytes([self.value]))
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker
93*6777b538SAndroid Build Coastguard Workerclass SEQUENCE(object):
94*6777b538SAndroid Build Coastguard Worker  def __init__(self, children):
95*6777b538SAndroid Build Coastguard Worker    self.children = children
96*6777b538SAndroid Build Coastguard Worker
97*6777b538SAndroid Build Coastguard Worker  def ToDER(self):
98*6777b538SAndroid Build Coastguard Worker    der = b''.join([ToDER(x) for x in self.children])
99*6777b538SAndroid Build Coastguard Worker    return TagAndData(0x30, der)
100*6777b538SAndroid Build Coastguard Worker
101*6777b538SAndroid Build Coastguard Worker
102*6777b538SAndroid Build Coastguard Workerclass SET(object):
103*6777b538SAndroid Build Coastguard Worker  def __init__(self, children):
104*6777b538SAndroid Build Coastguard Worker    self.children = children
105*6777b538SAndroid Build Coastguard Worker
106*6777b538SAndroid Build Coastguard Worker  def ToDER(self):
107*6777b538SAndroid Build Coastguard Worker    der = b''.join([ToDER(x) for x in self.children])
108*6777b538SAndroid Build Coastguard Worker    return TagAndData(0x31, der)
109*6777b538SAndroid Build Coastguard Worker
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Workerclass OCTETSTRING(object):
112*6777b538SAndroid Build Coastguard Worker  def __init__(self, val):
113*6777b538SAndroid Build Coastguard Worker    self.val = val
114*6777b538SAndroid Build Coastguard Worker
115*6777b538SAndroid Build Coastguard Worker  def ToDER(self):
116*6777b538SAndroid Build Coastguard Worker    return TagAndData(4, self.val)
117*6777b538SAndroid Build Coastguard Worker
118*6777b538SAndroid Build Coastguard Worker
119*6777b538SAndroid Build Coastguard Workerclass PrintableString(object):
120*6777b538SAndroid Build Coastguard Worker  def __init__(self, val):
121*6777b538SAndroid Build Coastguard Worker    self.val = val
122*6777b538SAndroid Build Coastguard Worker
123*6777b538SAndroid Build Coastguard Worker  def ToDER(self):
124*6777b538SAndroid Build Coastguard Worker    return TagAndData(19, self.val)
125*6777b538SAndroid Build Coastguard Worker
126*6777b538SAndroid Build Coastguard Worker
127*6777b538SAndroid Build Coastguard Workerclass UTF8String(object):
128*6777b538SAndroid Build Coastguard Worker  def __init__(self, val):
129*6777b538SAndroid Build Coastguard Worker    self.val = val
130*6777b538SAndroid Build Coastguard Worker
131*6777b538SAndroid Build Coastguard Worker  def ToDER(self):
132*6777b538SAndroid Build Coastguard Worker    return TagAndData(12, self.val)
133*6777b538SAndroid Build Coastguard Worker
134*6777b538SAndroid Build Coastguard Worker
135*6777b538SAndroid Build Coastguard Workerclass OID(object):
136*6777b538SAndroid Build Coastguard Worker  def __init__(self, parts):
137*6777b538SAndroid Build Coastguard Worker    self.parts = parts
138*6777b538SAndroid Build Coastguard Worker
139*6777b538SAndroid Build Coastguard Worker  def ToDER(self):
140*6777b538SAndroid Build Coastguard Worker    if len(self.parts) < 2 or self.parts[0] > 6 or self.parts[1] >= 40:
141*6777b538SAndroid Build Coastguard Worker      assert False
142*6777b538SAndroid Build Coastguard Worker
143*6777b538SAndroid Build Coastguard Worker    der = bytearray([self.parts[0] * 40 + self.parts[1]])
144*6777b538SAndroid Build Coastguard Worker    for x in self.parts[2:]:
145*6777b538SAndroid Build Coastguard Worker      if x == 0:
146*6777b538SAndroid Build Coastguard Worker        der.append(0)
147*6777b538SAndroid Build Coastguard Worker      else:
148*6777b538SAndroid Build Coastguard Worker        octets = bytearray()
149*6777b538SAndroid Build Coastguard Worker        while x != 0:
150*6777b538SAndroid Build Coastguard Worker          v = x & 0x7f
151*6777b538SAndroid Build Coastguard Worker          if len(octets) > 0:
152*6777b538SAndroid Build Coastguard Worker            v |= 0x80
153*6777b538SAndroid Build Coastguard Worker          octets.append(v)
154*6777b538SAndroid Build Coastguard Worker          x >>= 7
155*6777b538SAndroid Build Coastguard Worker        octets.reverse()
156*6777b538SAndroid Build Coastguard Worker        der = der + octets
157*6777b538SAndroid Build Coastguard Worker
158*6777b538SAndroid Build Coastguard Worker    return TagAndData(6, bytes(der))
159*6777b538SAndroid Build Coastguard Worker
160*6777b538SAndroid Build Coastguard Worker
161*6777b538SAndroid Build Coastguard Workerclass UTCTime(object):
162*6777b538SAndroid Build Coastguard Worker  def __init__(self, time_str):
163*6777b538SAndroid Build Coastguard Worker    self.time_str = time_str
164*6777b538SAndroid Build Coastguard Worker
165*6777b538SAndroid Build Coastguard Worker  def ToDER(self):
166*6777b538SAndroid Build Coastguard Worker    return TagAndData(23, self.time_str.encode('ascii'))
167*6777b538SAndroid Build Coastguard Worker
168*6777b538SAndroid Build Coastguard Worker
169*6777b538SAndroid Build Coastguard Workerclass GeneralizedTime(object):
170*6777b538SAndroid Build Coastguard Worker  def __init__(self, time_str):
171*6777b538SAndroid Build Coastguard Worker    self.time_str = time_str
172*6777b538SAndroid Build Coastguard Worker
173*6777b538SAndroid Build Coastguard Worker  def ToDER(self):
174*6777b538SAndroid Build Coastguard Worker    return TagAndData(24, self.time_str.encode('ascii'))
175*6777b538SAndroid Build Coastguard Worker
176*6777b538SAndroid Build Coastguard Worker
177*6777b538SAndroid Build Coastguard Workerclass BitString(object):
178*6777b538SAndroid Build Coastguard Worker  def __init__(self, bits):
179*6777b538SAndroid Build Coastguard Worker    self.bits = bits
180*6777b538SAndroid Build Coastguard Worker
181*6777b538SAndroid Build Coastguard Worker  def ToDER(self):
182*6777b538SAndroid Build Coastguard Worker    return TagAndData(3, b"\x00" + self.bits)
183