1# Copyright (c) 2012 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5# This file implements very minimal ASN.1, DER serialization. 6 7import types 8 9 10def ToDER(obj): 11 '''ToDER converts the given object into DER encoding''' 12 if type(obj) == types.NoneType: 13 # None turns into NULL 14 return TagAndLength(5, 0) 15 if type(obj) == types.StringType: 16 # Strings are PRINTABLESTRING 17 return TagAndLength(19, len(obj)) + obj 18 if type(obj) == types.BooleanType: 19 val = "\x00" 20 if obj: 21 val = "\xff" 22 return TagAndLength(1, 1) + val 23 if type(obj) == types.IntType or type(obj) == types.LongType: 24 big_endian = [] 25 val = obj 26 while val != 0: 27 big_endian.append(val & 0xff) 28 val >>= 8 29 30 if len(big_endian) == 0 or big_endian[-1] >= 128: 31 big_endian.append(0) 32 33 big_endian.reverse() 34 return TagAndLength(2, len(big_endian)) + ToBytes(big_endian) 35 36 return obj.ToDER() 37 38 39def ToBytes(array_of_bytes): 40 '''ToBytes converts the array of byte values into a binary string''' 41 return ''.join([chr(x) for x in array_of_bytes]) 42 43 44def TagAndLength(tag, length): 45 der = [tag] 46 if length < 128: 47 der.append(length) 48 elif length < 256: 49 der.append(0x81) 50 der.append(length) 51 elif length < 65535: 52 der.append(0x82) 53 der.append(length >> 8) 54 der.append(length & 0xff) 55 else: 56 assert False 57 58 return ToBytes(der) 59 60 61class Raw(object): 62 '''Raw contains raw DER encoded bytes that are used verbatim''' 63 def __init__(self, der): 64 self.der = der 65 66 def ToDER(self): 67 return self.der 68 69 70class Explicit(object): 71 '''Explicit prepends an explicit tag''' 72 def __init__(self, tag, child): 73 self.tag = tag 74 self.child = child 75 76 def ToDER(self): 77 der = ToDER(self.child) 78 tag = self.tag 79 tag |= 0x80 # content specific 80 tag |= 0x20 # complex 81 return TagAndLength(tag, len(der)) + der 82 83 84class ENUMERATED(object): 85 def __init__(self, value): 86 self.value = value 87 88 def ToDER(self): 89 return TagAndLength(10, 1) + chr(self.value) 90 91 92class SEQUENCE(object): 93 def __init__(self, children): 94 self.children = children 95 96 def ToDER(self): 97 der = ''.join([ToDER(x) for x in self.children]) 98 return TagAndLength(0x30, len(der)) + der 99 100 101class SET(object): 102 def __init__(self, children): 103 self.children = children 104 105 def ToDER(self): 106 der = ''.join([ToDER(x) for x in self.children]) 107 return TagAndLength(0x31, len(der)) + der 108 109 110class OCTETSTRING(object): 111 def __init__(self, val): 112 self.val = val 113 114 def ToDER(self): 115 return TagAndLength(4, len(self.val)) + self.val 116 117 118class OID(object): 119 def __init__(self, parts): 120 self.parts = parts 121 122 def ToDER(self): 123 if len(self.parts) < 2 or self.parts[0] > 6 or self.parts[1] >= 40: 124 assert False 125 126 der = [self.parts[0]*40 + self.parts[1]] 127 for x in self.parts[2:]: 128 if x == 0: 129 der.append(0) 130 else: 131 octets = [] 132 while x != 0: 133 v = x & 0x7f 134 if len(octets) > 0: 135 v |= 0x80 136 octets.append(v) 137 x >>= 7 138 octets.reverse() 139 der = der + octets 140 141 return TagAndLength(6, len(der)) + ToBytes(der) 142 143 144class UTCTime(object): 145 def __init__(self, time_str): 146 self.time_str = time_str 147 148 def ToDER(self): 149 return TagAndLength(23, len(self.time_str)) + self.time_str 150 151 152class GeneralizedTime(object): 153 def __init__(self, time_str): 154 self.time_str = time_str 155 156 def ToDER(self): 157 return TagAndLength(24, len(self.time_str)) + self.time_str 158 159 160class BitString(object): 161 def __init__(self, bits): 162 self.bits = bits 163 164 def ToDER(self): 165 return TagAndLength(3, 1 + len(self.bits)) + "\x00" + self.bits 166