Home | History | Annotate | Download | only in testserver
      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 
      7 import types
      8 
      9 
     10 def 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 
     39 def 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 
     44 def 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 
     61 class 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 
     70 class 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 
     84 class 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 
     92 class 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 
    101 class 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 
    110 class 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 
    118 class 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 
    144 class 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 
    152 class 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 
    160 class 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