- add sources.
[platform/framework/web/crosswalk.git] / src / net / tools / testserver / asn1.py
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