diff options
Diffstat (limited to 'net/tools/testserver/asn1.py')
-rw-r--r-- | net/tools/testserver/asn1.py | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/net/tools/testserver/asn1.py b/net/tools/testserver/asn1.py new file mode 100644 index 0000000..c0e0398 --- /dev/null +++ b/net/tools/testserver/asn1.py @@ -0,0 +1,165 @@ +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file implements very minimal ASN.1, DER serialization. + +import types + + +def ToDER(obj): + '''ToDER converts the given object into DER encoding''' + if type(obj) == types.NoneType: + # None turns into NULL + return TagAndLength(5, 0) + if type(obj) == types.StringType: + # Strings are PRINTABLESTRING + return TagAndLength(19, len(obj)) + obj + if type(obj) == types.BooleanType: + val = "\x00" + if obj: + val = "\xff" + return TagAndLength(1, 1) + val + if type(obj) == types.IntType or type(obj) == types.LongType: + big_endian = [] + val = obj + while val != 0: + big_endian.append(val & 0xff) + val >>= 8 + + if len(big_endian) == 0 or big_endian[-1] >= 128: + big_endian.append(0) + + big_endian.reverse() + return TagAndLength(2, len(big_endian)) + ToBytes(big_endian) + + return obj.ToDER() + + +def ToBytes(array_of_bytes): + '''ToBytes converts the array of byte values into a binary string''' + return ''.join([chr(x) for x in array_of_bytes]) + + +def TagAndLength(tag, length): + der = [tag] + if length < 128: + der.append(length) + elif length < 256: + der.append(0x81) + der.append(length) + elif length < 65535: + der.append(0x82) + der.append(length >> 8) + der.append(length & 0xff) + else: + assert False + + return ToBytes(der) + + +class Raw(object): + '''Raw contains raw DER encoded bytes that are used verbatim''' + def __init__(self, der): + self.der = der + + def ToDER(self): + return self.der + + +class Explicit(object): + '''Explicit prepends an explicit tag''' + def __init__(self, tag, child): + self.tag = tag + self.child = child + + def ToDER(self): + der = ToDER(self.child) + tag = self.tag + tag |= 0x80 # content specific + tag |= 0x20 # complex + return TagAndLength(tag, len(der)) + der + + +class ENUMERATED(object): + def __init__(self, value): + self.value = value + + def ToDER(self): + return TagAndLength(10, 1) + chr(self.value) + + +class SEQUENCE(object): + def __init__(self, children): + self.children = children + + def ToDER(self): + der = ''.join([ToDER(x) for x in self.children]) + return TagAndLength(0x30, len(der)) + der + + +class SET(object): + def __init__(self, children): + self.children = children + + def ToDER(self): + der = ''.join([ToDER(x) for x in self.children]) + return TagAndLength(0x31, len(der)) + der + + +class OCTETSTRING(object): + def __init__(self, val): + self.val = val + + def ToDER(self): + return TagAndLength(4, len(self.val)) + self.val + + +class OID(object): + def __init__(self, parts): + self.parts = parts + + def ToDER(self): + if len(self.parts) < 2 or self.parts[0] > 6 or self.parts[1] >= 40: + assert False + + der = [self.parts[0]*40 + self.parts[1]] + for x in self.parts[2:]: + if x == 0: + der.append(0) + else: + octets = [] + while x != 0: + v = x & 0x7f + if len(octets) > 0: + v |= 0x80 + octets.append(v) + x >>= 7 + octets.reverse() + der = der + octets + + return TagAndLength(6, len(der)) + ToBytes(der) + + +class UTCTime(object): + def __init__(self, time_str): + self.time_str = time_str + + def ToDER(self): + return TagAndLength(23, len(self.time_str)) + self.time_str + + +class GeneralizedTime(object): + def __init__(self, time_str): + self.time_str = time_str + + def ToDER(self): + return TagAndLength(24, len(self.time_str)) + self.time_str + + +class BitString(object): + def __init__(self, bits): + self.bits = bits + + def ToDER(self): + return TagAndLength(3, 1 + len(self.bits)) + "\x00" + self.bits |