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