| Index: net/tools/testserver/asn1.py | 
| diff --git a/net/tools/testserver/asn1.py b/net/tools/testserver/asn1.py | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..6bff256f159d1be5112bdc35cfaf0fa83f82621d | 
| --- /dev/null | 
| +++ b/net/tools/testserver/asn1.py | 
| @@ -0,0 +1,164 @@ | 
| +# 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 | 
|  |