diff options
Diffstat (limited to 'pow/POW-0.7/lib')
-rw-r--r-- | pow/POW-0.7/lib/__init__.py | 16 | ||||
-rw-r--r-- | pow/POW-0.7/lib/_der.py | 2294 | ||||
-rwxr-xr-x | pow/POW-0.7/lib/_simpledb.py | 55 | ||||
-rwxr-xr-x | pow/POW-0.7/lib/pkix.py | 2087 |
4 files changed, 0 insertions, 4452 deletions
diff --git a/pow/POW-0.7/lib/__init__.py b/pow/POW-0.7/lib/__init__.py deleted file mode 100644 index b150bbf1..00000000 --- a/pow/POW-0.7/lib/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -from _POW import * -from _POW import _docset - -## @mainpage -## -## Python OpenSSL Wrappers (POW) is an old (but well-written) -## interface between Python and OpenSSL (ok, you could have guessed -## that from the name). Sadly, it appears to have fallen by the -## wayside, and M2Crypto is getting a lot more attention these days. -## -## POW ships with a submodule, POW.pkix, which includes a wonderful -## set of pure-Python routines for dealing with ASN.1 encodings of -## X.509v3 certificates, extensions, and related data. I haven't -## found anything as good anywhere else. This code deserves to be -## salvaged and put to work. - diff --git a/pow/POW-0.7/lib/_der.py b/pow/POW-0.7/lib/_der.py deleted file mode 100644 index c7f58411..00000000 --- a/pow/POW-0.7/lib/_der.py +++ /dev/null @@ -1,2294 +0,0 @@ -#*****************************************************************************# -#* *# -#* Copyright (c) 2002, Peter Shannon *# -#* All rights reserved. *# -#* *# -#* Redistribution and use in source and binary forms, with or without *# -#* modification, are permitted provided that the following conditions *# -#* are met: *# -#* *# -#* * Redistributions of source code must retain the above *# -#* copyright notice, this list of conditions and the following *# -#* disclaimer. *# -#* *# -#* * Redistributions in binary form must reproduce the above *# -#* copyright notice, this list of conditions and the following *# -#* disclaimer in the documentation and/or other materials *# -#* provided with the distribution. *# -#* *# -#* * The name of the contributors may be used to endorse or promote *# -#* products derived from this software without specific prior *# -#* written permission. *# -#* *# -#* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *# -#* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *# -#* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *# -#* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS *# -#* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *# -#* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *# -#* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *# -#* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *# -#* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *# -#* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *# -#* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *# -#* *# -#*****************************************************************************# - -import exceptions, types, copy, string, time, base64, traceback, cStringIO - -DEBUG = 0 - -# CLASS -CLASS_UNIVERSAL = 0x00 -CLASS_APPLICATION = 0x40 -CLASS_CONTEXT = 0x80 -CLASS_PRIVATE = 0xC0 - -# FORM -FORM_PRIMITIVE = 0x00 -FORM_CONSTRUCTED = 0x20 - -# TAG -TAG_BOOLEAN = 0x01 -TAG_INTEGER = 0x02 -TAG_BITSTRING = 0x03 -TAG_OCTETSTRING = 0x04 -TAG_NULL = 0x05 -TAG_OID = 0x06 -TAG_OBJDESCRIPTOR = 0x07 -TAG_EXTERNAL = 0x08 -TAG_REAL = 0x09 -TAG_ENUMERATED = 0x0A -TAG_EMBEDDED_PDV = 0x0B -TAG_UTF8STRING = 0x0C -TAG_SEQUENCE = 0x10 -TAG_SET = 0x11 -TAG_NUMERICSTRING = 0x12 -TAG_PRINTABLESTRING = 0x13 -TAG_T61STRING = 0x14 -TAG_VIDEOTEXSTRING = 0x15 -TAG_IA5STRING = 0x16 -TAG_UTCTIME = 0x17 -TAG_GENERALIZEDTIME = 0x18 -TAG_GRAPHICSTRING = 0x19 -TAG_VISIBLESTRING = 0x1A -TAG_GENERALSTRING = 0x1B -TAG_UNIVERSALSTRING = 0x1C -TAG_BMPSTRING = 0x1E - -_fragments = [] - -def _docset(): - return _fragments - -def _addFragment(frag): - global _fragments - _fragments.append(frag) - - -_addFragment(''' -<moduleDescription> - <header> - <name>POW.pkix</name> - <author>Peter Shannon</author> - </header> - <body> - <para> - This module is a solution to reading and writing X509v3 written - purely in Python. It does use limited facilities from POW for - signing and verifying but these could be replaced easily. It is - an abstract module and to use it successfully RFC3280 should be - referred to as well as the sourcecode where necessary. The correct - use of many extensions often not clear from the definitions alone. - Do refer to the RFC for details. - </para> - <para> - Each constructed objects defined in the RFC is built from primitives - defined by the ASN1 recommedations. Not all ASN1 primitive are available but all those - required for X509v3 should be. The implementation is more or less - complete for DER encoding the only caveat, aside from a few - missing objects, is the behaviour of <classname>SET</classname> objects - and <classname>SET OF</classname> objects. The order the objects are - written in should be determined at runtime by sorting their tags but this - library does not do this. For X509 it isn't really necessary - since all the <classname>Set</classname> objects are simple and the - order they are written in is defined by the object's constructor. - </para> - <para> - Every documented object in this module supports the functions documented for - <classname>_GeneralObject</classname>. In general the function - will only be documented in descendant classes if the class changes - the behaviour significantly from its ancestor. This would - normally be <classname>_GeneralObject</classname> or - <classname>Sequence</classname>. - </para> - </body> -</moduleDescription> -''') - -class DerError(Exception): - def __init__(self, msg): - if not isinstance(msg, types.StringType): - raise Exception, 'argunment should be a string' - self.msg = msg - - def __repr__(self): - return self.msg - - __str__ = __repr__ - -class _Tag(object): - def __init__(self): - self.tagclass = 0 - self.tagform = 0 - self.tagnumber = 0 - - def __repr__(self): - return '(%s, %s, %s)' % (self.tagclass, self.tagform, self.tagnumber) - - def write(self, file): - if self.tagnumber < 31: - file.write( chr(self.tagclass | self.tagform | self.tagnumber) ) - else: - val = copy.deepcopy(self.tagnumber) - bytes = [] - while val: - byte = val & 0x7F - bytes.append(byte | 0x80) - val = val >> 7 - bytes[0] = bytes[0] ^ 0x80 - bytes.append( self.tagclass | self.tagform | 0x1F ) - bytes.reverse() - file.write( string.join(map(chr, bytes), '') ) - - def read(self, file): - octet1 = ord( file.read(1) ) - self.tagclass = octet1 & 0xC0 - self.tagform = octet1 & 0x20 - value = octet1 & 0x1F - if value < 31: - self.tagnumber = value - else: - total = 0 - byte = 0x80 - while byte & 0x80: - byte = ord( file.read(1) ) - if byte & 0x80: - total = (total << 7) | byte ^ 0x80 - else: - total = (total << 7) | byte - self.tagnumber = total - -class _Length(object): - def __init__(self): - self.length = 0 - - def __repr__(self): - return '(%s)' % self.length - - def write(self, file): - if self.length < 128: - file.write( chr(self.length) ) - else: - val = copy.deepcopy(self.length) - bytes = [] - while val: - byte = val & 0xFF - bytes.append(byte) - val = val >> 8 - lengthOfLength = len(bytes) - if lengthOfLength > 126: - raise DerError, 'object is too long!' - bytes.append(lengthOfLength) - bytes.reverse() - bytes[0] = bytes[0] ^ 0x80 - file.write( string.join(map(chr, bytes), '') ) - - def read(self, file): - octet1 = ord( file.read(1) ) - if octet1 < 128: - self.length = octet1 - else: - total = 0 - byte = 0 - for i in range(octet1 ^ 0x80): - byte = ord( file.read(1) ) - total = (total << 8) | byte - self.length = total - -class _TlvIo(_Tag, _Length): - def __init__(self, file): - self.file = file - self.offset = None - self.valueOffset = None - - def __repr__(self): - return '<TAG:%s Length:%s>' % (_Tag.__repr__(self), _Length.__repr__(self)) - - def __nonzero__(self): - pos = self.file.tell() - self.file.seek(0,2) - if self.file.tell(): - self.file.seek(pos) - return 1 - else: - return 0 - - def read(self): - self.offset = self.file.tell() - _Tag.read( self, self.file ) - _Length.read( self, self.file ) - self.valueOffset = self.file.tell() - self.file.seek( self.length, 1 ) - - def readValue(self): - self.file.seek( self.valueOffset ) - return self.file.read( self.length ) - - def write(self, val): - _Tag.write( self, self.file ) - self.length = len(val) - _Length.write( self, self.file ) - self.file.write(val) - -def _decodeBoolean(val): - 'der encoded value not including tag or length' - if not isinstance(val, types.StringType): - raise DerError, 'argument should be a string' - if ord(val) == 0xFF: - return 1 - elif ord(val) == 0x00: - return 0 - else: - raise DerError, 'boolean should be encode as all 1s or all 0s' - -def _encodeBoolean(val): - 'anything we can test for truth' - if val: - return chr(0xFF) - else: - return chr(0x00) - -def _decodeInteger(val): - 'der encoded value not including tag or length' - if not isinstance(val, types.StringType): - raise DerError, 'argument should be a string' - total = 0L - if ord(val[0]) & 0x80: - val = map( lambda x : ord(x) ^ 0xFF, val ) - for byte in val: - total = (total << 8) | byte - total = -(total+1) - else: - for byte in val: - total = (total << 8) | ord(byte) - return total - -def _encodeInteger(val): - 'python integer' - if not isinstance(val, types.IntType) and not isinstance(val, types.LongType): - raise DerError, 'argument should be an integer' - if val == 0: - return chr(0x00) - else: - val2 = copy.deepcopy(val) - if val2 < 0: - val2 = -(val2+1) - bytes = [] - byte = 0 - while val2: - byte = val2 & 0xFF - bytes.append(byte) - val2 = val2 >> 8 - # if we have no used up the last byte to represent the value we need - # to add one more on to show if this is negative of positive. Also, - # due to adding 1 and inverting -1 would be 0 or if 0 is the encoding - # value, so bytes would empty and this would lead to and empty value - # and this would not be working properly. Adding this null byte - # fixes this, since it is inverted to -1 and preserved for 0. - if byte & 0x80 or not bytes: - bytes.append(0x00) - if val < 0: - bytes = map( lambda x : x ^ 0xFF, bytes ) - bytes.reverse() - - return string.join(map(chr, bytes), '') - -def _decodeBitString(val): - 'der encoded value not including tag or length' - if not isinstance(val, types.StringType): - raise DerError, 'argument should be a string' - bitmasks = [0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01] - unused = ord( val[0] ) - bits = [] - for byte in val[1:]: - for j in range(8): - if ord(byte) & bitmasks[j]: - bits.append(1) - else: - bits.append(0) - if unused == 0: - return tuple(bits) - else: - return tuple(bits[:-unused]) - -def _encodeBitString(val): - 'list of true/false objects ie [0,1,1,0,1,1]' - if not (isinstance(val, types.ListType) or isinstance(val, types.TupleType)): - raise DerError, 'argument should be a list or tuple' - bitmasks = [0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01] - bytes = [] - fits, leftover = divmod(len(val), 8) - nobytes = fits - if leftover > 0: - nobytes = nobytes + 1 - if leftover: - unused = 8 - leftover - else: - unused = 0 - bytes.append(unused) - for i in range(nobytes): - byte = 0 - for j in range(8): - offset = j + i*8 - if offset < len(val): - if val[offset]: - byte = byte | bitmasks[j] - bytes.append(byte) - - return string.join(map(chr, bytes), '') - -def _decodeOid(val): - 'der encoded value not including tag or length' - if not isinstance(val, types.StringType): - raise DerError, 'argument should be a string' - arc12 = ord( val[0] ) - arc1, arc2 = divmod(arc12, 40) - oids = [arc1,arc2] - - total = 0 - for byte in val[1:]: - val = ord(byte) - if val & 0x80: - total = (total << 7) | (val ^ 0x80) - else: - total = (total << 7) | val - oids.append(total) - total = 0 - - return tuple(oids) - -def _encodeOid(val): - 'list of intgers' - if not (isinstance(val, types.ListType) or isinstance(val, types.TupleType)): - raise DerError, 'argument should be a list or tuple' - oids = [] - oids.append( chr(40 * val[0] + val[1]) ) - for val in val[2:]: - if val == 0: - oids.append( chr(0) ) - else: - bytes = [] - while val: - val, rem = divmod(val, 128) - bytes.append(rem | 0x80) - bytes[0] = bytes[0] ^ 0x80 - bytes.reverse() - oids.append( string.join(map(chr, bytes), '') ) - - return string.join(oids, '') - -def _decodeSequence(val): - 'der encoded value not including tag or length' - if not isinstance(val, types.StringType): - raise DerError, 'argument should be a string' - buf = cStringIO.StringIO(val) - buflen = len(val) - tvls = [] - while buf.tell() < buflen: - t = _TlvIo(buf) - t.read() - tvls.append(t) - return tuple(tvls) - -def _encodeSequence(val): - 'list of GenerlObjects' - if not (isinstance(val, types.ListType) or isinstance(val, types.TupleType)): - raise DerError, 'argument should be a list or tuple' - buf = cStringIO.StringIO() - for obj in val: - if obj or isinstance(obj, _GeneralObject): - obj.write(buf) - elif not obj.optional: - raise DerError, 'object not set which should be: %s' % obj - - return buf.getvalue() - -_addFragment(''' -<class> - <header> - <name>_GeneralObject</name> - </header> - <body> - <para> - <classname>_GeneralObject</classname> is the basis for all DER objects, - primitive or constructed. It defines the basic behaviour of an - object which is serialised using the tag, length and value - approach of DER. It is unlikely you would ever want to - instantiate one of these directly but I include a description - since many primatives don't override much of - <classname>_GeneralObject</classname>'s functions. - </para> - </body> -</class> -''') - -class _GeneralObject(object): - - _addFragment(''' - <constructor> - <header> - <memberof>_GeneralObject</memberof> - <parameter>normclass</parameter> - <parameter>normform</parameter> - <parameter>normnumber</parameter> - <parameter>encRoutine</parameter> - <parameter>decRoutine</parameter> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - <body> - <para> - <parameter>normclass</parameter> is the class of the object, - ei: universal, application, context or private. - <parameter>normform</parameter> is the form of the object, ei - primitive or constructed. <parameter>normnumber</parameter> is - the tag number of the object. - <parameter>encRoutine</parameter> is a function which takes a - value and encodes it according the appropriate DER rules. - <parameter>decRoutine</parameter> is a function which reads a - string value and returns a value which is more useful in - Python. <parameter>optional</parameter> is a boolean - indicating if this object is optional. The final parameter, - <parameter>default</parameter> is the base 64 encoded DER - value, which should be used as the default in leu of a value to - read or incase it is unset. - </para> - </body> - </constructor> - ''') - - def __init__(self, normclass, normform, normnumber, encRoutine, decRoutine, optional=0, default=''): - if not isinstance(normclass, types.IntType): - raise DerError, 'nomrclass argument should be an integer : %s' % normclass - if not isinstance(normform, types.IntType): - raise DerError, 'normform argument should be an integer : %s' % normform - if not isinstance(normnumber, types.IntType): - raise DerError, 'normnumber argument should be an integer : %s' % normnumber - if not isinstance(encRoutine, types.FunctionType): - raise DerError, 'encRoutine argument should be an function : %s' % encRoutine - if not isinstance(decRoutine, types.FunctionType): - raise DerError, 'decRoutine argument should be an function : %s' % decRoutine - if not isinstance(optional, types.IntType): - raise DerError, 'optional argument should be an integer : %s' % optional - if not isinstance(default, types.StringType): - raise DerError, 'default argument should be an String : %s' % default - self.normclass = normclass - self.normform = normform - self.normnumber = normnumber - self.encRoutine = encRoutine - self.decRoutine = decRoutine - self.value = None - self.optional = optional - self.default = default - self.reset() - - def _ioSafe(self): - 'is it safe to write this object' - if self.optional or self._isSet(): - return 1 - else: - return 0 - - def _isSet(self): - 'are the values of this object set or not' - if self.value is not None: - return 1 - else: - return 0 - - _addFragment(''' - <method> - <header> - <memberof>_GeneralObject</memberof> - <name>reset</name> - </header> - <body> - <para> - This function re-initialises the object, clearing the value or - setting it to any default. - </para> - </body> - </method> - ''') - def reset(self): - self.value = None - if self.default: - buf = cStringIO.StringIO( base64.decodestring( self.default ) ) - io = _TlvIo(buf) - io.read() - self.read(io) - - _addFragment(''' - <method> - <header> - <memberof>_GeneralObject</memberof> - <name>set</name> - <parameter>value</parameter> - </header> - <body> - <para> - This dosn't do much except store <parameter>value</parameter>, - presumably prior to writing the object. The correct values to - use would be determined by the encoder or decoder this class is - instantiated with. Be careful, there is some flexibility in - setting objects so you might find that once the object has been - written and read back in the value isn't identical. A good - example would be anything which contains a sequence(list or - tuple), all sequence objects are returned as tuples. - </para> - </body> - </method> - ''') - def set(self, value): - if value is not None: - self.value = value - - _addFragment(''' - <method> - <header> - <memberof>_GeneralObject</memberof> - <name>get</name> - </header> - <body> - <para> - Gets the value stored presumably after reading the object. - </para> - </body> - </method> - ''') - def get(self): - return self.value - - _addFragment(''' - <method> - <header> - <memberof>_GeneralObject</memberof> - <name>implied</name> - <parameter>impclass</parameter> - <parameter>impform</parameter> - <parameter>impnumber</parameter> - </header> - <body> - <para> - This function is used to change how the tag is written or read - for a particular object and should be called in the constructor - for derived objects. If you have an example of the structure you need to - process, Pete Gutmann's excellent - <application>dumpasn1</application> can be invaluable for - debugging objects. - </para> - </body> - </method> - ''') - def implied(self, impclass, impform, impnumber): - if not isinstance(impclass, types.IntType): - raise DerError, 'impclass argument should be an integer' - if not isinstance(impform, types.IntType): - raise DerError, 'impform argument should be an integer' - if not isinstance(impnumber, types.IntType): - raise DerError, 'impnumber argument should be an integer' - self.normclass = impclass - self.normform = impform - self.normnumber = impnumber - - _addFragment(''' - <method> - <header> - <memberof>_GeneralObject</memberof> - <name>read</name> - <parameter>io</parameter> - </header> - <body> - <para> - <parameter>io</parameter> should be a file like object. If the - object being read matches the expected class, form and tag the - value is read and decoded using - <function>decRoutine</function>. Else, if it has a default - that is read and stored. - </para> - <para> - The return value of this function does not indicate success but - whether this TLV was processed successfully. This bahaviour is - vital for processing constructed types since the object may be - optional or have a default. Failure to decode would be indicated - by an exception. - </para> - </body> - </method> - ''') - - def read(self, io=None): - - processDefOpt = 0 - if io is None: - processDefOpt = 1 - elif isinstance(io, _TlvIo): - if not io: - processDefOpt = 1 - else: - pos = io.tell() - io.seek(0,2) - if io.tell(): - io.seek(pos) - else: - processDefOpt = 1 - - if processDefOpt: - if self.optional or self.default: - self.reset() - return 0 - else: - raise DerError, 'no TLV is available to read in non-optional/non-default object: %s' % repr(self) - - if not isinstance(io, _TlvIo): - tmp = _TlvIo(io) - tmp.read() - io = tmp - - if io.tagclass != self.normclass or io.tagform != self.normform or io.tagnumber != self.normnumber: - if self.default or self.optional: - self.reset() - return 0 - else: - raise DerError, 'error in encoding, missing object:%s' % repr(self) - else: - derval = io.readValue() - self.value = self.decRoutine( derval ) - return 1 - - _addFragment(''' - <method> - <header> - <memberof>_GeneralObject</memberof> - <name>write</name> - <parameter>io</parameter> - </header> - <body> - <para> - If this object has not been set and is not optional and dosn't - have a default, a <classname>DerError</classname> exception will be raised - </para> - <para> - If no value has been set and this object is optional, nothing - is written. If this object's value is equal to the default, - nothing is written as stipulated by DER. Otherwise the value - is encoded and written. - </para> - </body> - </method> - ''') - - def write(self, file): - if not self._ioSafe(): - raise DerError, 'object not set which must be: %s' % repr(self) - elif self.optional and self.value is None: - pass - else: - buf = cStringIO.StringIO() - io = _TlvIo(buf) - io.tagclass = self.normclass - io.tagform = self.normform - io.tagnumber = self.normnumber - derval = self.encRoutine( self.value ) - io.length = len(derval) - io.write(derval) - if self.default: - if buf.getvalue() != base64.decodestring(self.default): - file.write( buf.getvalue() ) - else: - file.write( buf.getvalue() ) - - _addFragment(''' - <method> - <header> - <memberof>_GeneralObject</memberof> - <name>toString</name> - </header> - <body> - <para> - Encodes the value in DER and returns it as a string. - </para> - </body> - </method> - ''') - - def toString(self): - buf = cStringIO.StringIO() - self.write(buf) - return buf.getvalue() - - _addFragment(''' - <method> - <header> - <memberof>_GeneralObject</memberof> - <name>fromString</name> - </header> - <body> - <para> - Decodes the string and sets the value of this object. - </para> - </body> - </method> - ''') - - def fromString(self, value): - buf = cStringIO.StringIO(value) - self.read(buf) - -class Any(_GeneralObject): - - def __init__(self): - self.value = None - self.normclass = None - self.normform = None - self.normnumber = None - - def _ioSafe(self): - if self.optional or (self._isSet() and self.normclass is not None and self.normform is not None and self.normnumber is not None): - return 1 - else: - return 0 - - def setTag(self, klass, form, number): - self.normclass = klass - self.normform = form - self.normnumber = number - - def reset(self): - self.value = None - - def get(self): - return self.value - - def set(self, value): - self.value = value - - def write(self,file): - if not self._ioSafe(): - raise DerError, 'object not set which must be: %s' % repr(self) - elif self.optional and self.value is None: - pass - else: - buf = cStringIO.StringIO() - io = _TlvIo(buf) - io.tagclass = self.normclass - io.tagform = self.normform - io.tagnumber = self.normnumber - io.length = len(self.value) - io.write(self.value) - file.write(buf.getvalue()) - - def read(self, io=None): - - processDefOpt = 0 - if io is None: - processDefOpt = 1 - elif isinstance(io, _TlvIo): - if not io: - processDefOpt = 1 - else: - pos = io.tell() - io.seek(0,2) - if io.tell(): - io.seek(pos) - else: - processDefOpt = 1 - if processDefOpt: - if self.optional or self.default: - self.reset() - return 0 - else: - raise DerError, 'no TLV is available to read in non-optional/non-default object: %s' % repr(self) - - if not isinstance(io, _TlvIo): - tmp = _TlvIo(io) - tmp.read() - io = tmp - - self.value = io.readValue() - self.normclass = io.tagclass - self.normform = io.tagform - self.normnumber = io.tagnumber - -_addFragment(''' -<class> - <header> - <name>Boolean</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 BOOLEAN type. It can be set - with any object which can be tested for truth. - </para> - </body> -</class> -''') - -class Boolean(_GeneralObject): # 0x01 - - _addFragment(''' - <constructor> - <header> - <memberof>Boolean</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_BOOLEAN, _encodeBoolean, _decodeBoolean, optional, default) - -_addFragment(''' -<class> - <header> - <name>Integer</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 INTEGER type. It should be set - with a Python integer. - </para> - </body> -</class> -''') - -class Integer(_GeneralObject): # 0x02 - - _addFragment(''' - <constructor> - <header> - <memberof>Integer</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_INTEGER, _encodeInteger, _decodeInteger, optional, default) - -_addFragment(''' -<class> - <header> - <name>BitString</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 BIT STRING type. It should be set - with a sequence of integers. A non-zero number will set the bit, - zero will leave the bit unset. - </para> - </body> -</class> -''') - -class BitString(_GeneralObject): # 0x03 - - _addFragment(''' - <constructor> - <header> - <memberof>BitString</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_BITSTRING, _encodeBitString, _decodeBitString, optional, default) - -_addFragment(''' -<class> - <header> - <name>AltBitString</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 BIT STRING type. It differs from - the first <classname>BitString</classname> in that it's coding - routines treat values as binary data and do not interpret the data - in any way. Some application treat the - <classname>BIT STRING</classname> in the same way as - <classname>OCTET STRING</classname> type, hence this extra object. - </para> - </body> -</class> -''') - -class AltBitString(_GeneralObject): # 0x03 - - _addFragment(''' - <constructor> - <header> - <memberof>AltBitString</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_BITSTRING, lambda x : chr(0)+x, lambda x : x[1:], optional, default) - -_addFragment(''' -<class> - <header> - <name>OctetString</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 OCTET STRING type. This object - can be set with any binary data. - </para> - </body> -</class> -''') -class OctetString(_GeneralObject): # 0x04 - - _addFragment(''' - <constructor> - <header> - <memberof>OctetString</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_OCTETSTRING, lambda x : x, lambda x : x, optional, default) - -_addFragment(''' -<class> - <header> - <name>Null</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 NULL type. There is no point in - setting this object, the value will always be ignored when it is - written out. - </para> - </body> -</class> -''') -class Null(_GeneralObject): # 0x05 - - _addFragment(''' - <constructor> - <header> - <memberof>Null</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_NULL, lambda x : '', lambda x : '', optional, default) - self.value = '' - - def _ioSafe(self): - return 1 - - def reset(self): - self.value = '' - -_addFragment(''' -<class> - <header> - <name>Oid</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 OID type. This object should be - set with a list or tuple of integers defining an objects oid. - Please note that the first three arcs have a restricted set of - values, so encoding (5, 3, 7, 1) will produce bad results. - </para> - </body> -</class> -''') -class Oid(_GeneralObject): # 0x06 - - _addFragment(''' - <constructor> - <header> - <memberof>Oid</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_OID, _encodeOid, _decodeOid, optional, default) - -_addFragment(''' -<class> - <header> - <name>Enum</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 ENUM type. This should be set - using a Python integer, the meaning should be described in the - ASN1 document for the object you are encoding. - </para> - </body> -</class> -''') -class Enum(_GeneralObject): # 0x0A - - _addFragment(''' - <constructor> - <header> - <memberof>Enum</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_ENUMERATED, _encodeInteger, _decodeInteger, optional, default) - -_addFragment(''' -<class> - <header> - <name>Utf8String</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 UTF8String type. This object - should be set with a string. It is up to the application to ensure - it only contains valid characters for this type. - </para> - </body> -</class> -''') -class Utf8String(_GeneralObject): # 0x0C - - _addFragment(''' - <constructor> - <header> - <memberof>Utf8String</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_UTF8STRING, lambda x : x, lambda x : x, optional, default) - -_addFragment(''' -<class> - <header> - <name>NumericString</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 NumericString type. This should - object should be set with a string. It is up to the application to ensure - it only contains valid characters for this type. - </para> - </body> -</class> -''') -class NumericString(_GeneralObject): # 0x12 - - _addFragment(''' - <constructor> - <header> - <memberof>NumericString</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_NUMERICSTRING, lambda x : x, lambda x : x, optional, default) -_addFragment(''' -<class> - <header> - <name>PrintableString</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 PrintableString type. This should - object should be set with a string. It is up to the application to ensure - it only contains valid characters for this type. - </para> - </body> -</class> -''') -class PrintableString(_GeneralObject): # 0x13 - - _addFragment(''' - <constructor> - <header> - <memberof>PrintableString</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_PRINTABLESTRING, lambda x : x, lambda x : x, optional, default) - -_addFragment(''' -<class> - <header> - <name>T61String</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 T61String type. This object - should be set with a string. It is up to the application to ensure - it only contains valid characters for this type. - </para> - </body> -</class> -''') -class T61String(_GeneralObject): # 0x14 - - _addFragment(''' - <constructor> - <header> - <memberof>T61String</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_T61STRING, lambda x : x, lambda x : x, optional, default) - -_addFragment(''' -<class> - <header> - <name>VideotexString</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 VideotexString type. This should - object should be set with a string. It is up to the application to ensure - it only contains valid characters for this type. - </para> - </body> -</class> -''') -class VideotexString(_GeneralObject): # 0x15 - - _addFragment(''' - <constructor> - <header> - <memberof>VideotexString</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_VIDEOTEXSTRING, lambda x : x, lambda x : x, optional, default) - -_addFragment(''' -<class> - <header> - <name>IA5String</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 IA5String type. This object - should be set with a string. It is up to the application to ensure - it only contains valid characters for this type. - </para> - </body> -</class> -''') -class IA5String(_GeneralObject): # 0x16 - - _addFragment(''' - <constructor> - <header> - <memberof>IA5String</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_IA5STRING, lambda x : x, lambda x : x, optional, default) - -_addFragment(''' -<class> - <header> - <name>UtcTime</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 UTCTime type. This object should - be set with a string of the general format YYMMDDhhmmssZ. The - helper functions <function>time2utc</function> and - <function>utc2time</function> can be used to handle the conversion - from an integer to a string and back. - </para> - </body> -</class> -''') -class UtcTime(_GeneralObject): # 0x17 - - _addFragment(''' - <constructor> - <header> - <memberof>UtcTime</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_UTCTIME, lambda x : x, lambda x : x, optional, default) - -_addFragment(''' -<class> - <header> - <name>GeneralizedTime</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 GeneralizedTime type. This object should - be set with a string of the general format YYYYMMDDhhmmssZ. The - helper functions <function>time2utc</function> and - <function>utc2time</function> can be used to handle the conversion - from an integer to a string and back. - </para> - </body> -</class> -''') -class GeneralizedTime(_GeneralObject): # 0x18 - - _addFragment(''' - <constructor> - <header> - <memberof>GeneralizedTime</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_GENERALIZEDTIME, lambda x : x, lambda x : x, optional, default) - -_addFragment(''' -<class> - <header> - <name>GraphicString</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 GraphicString type. This should - object should be set with a string. It is up to the application to - ensure it only contains valid characters for this type. - </para> - </body> -</class> -''') -class GraphicString(_GeneralObject): # 0x19 - - _addFragment(''' - <constructor> - <header> - <memberof>GraphicString</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_GRAPHICSTRING, lambda x : x, lambda x : x, optional, default) - -_addFragment(''' -<class> - <header> - <name>VisibleString</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 VisibleString type. This should - object should be set with a string. It is up to the application to - ensure it only contains valid characters for this type. - </para> - </body> -</class> -''') -class VisibleString(_GeneralObject): # 0xC0 - - _addFragment(''' - <constructor> - <header> - <memberof>VisibleString</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_VISIBLESTRING, lambda x : x, lambda x : x, optional, default) - -_addFragment(''' -<class> - <header> - <name>GeneralString</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 GeneralString type. This should - object should be set with a string. It is up to the application to - ensure it only contains valid characters for this type. - </para> - </body> -</class> -''') -class GeneralString(_GeneralObject): # 0xC0 - - _addFragment(''' - <constructor> - <header> - <memberof>GeneralString</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_GENERALSTRING, lambda x : x, lambda x : x, optional, default) - -_addFragment(''' -<class> - <header> - <name>UniversalString</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 UniversalString type. This should - object should be set with a string. It is up to the application to - ensure it only contains valid characters for this type. - </para> - </body> -</class> -''') -class UniversalString(_GeneralObject): # 0xC0 - - _addFragment(''' - <constructor> - <header> - <memberof>UniversalString</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_UNIVERSALSTRING, lambda x : x, lambda x : x, optional, default) - -_addFragment(''' -<class> - <header> - <name>BmpString</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 BMPString type. This object - should be set with a string. It is up to the application to ensure - it only contains valid characters for this type. - </para> - </body> -</class> -''') -class BmpString(_GeneralObject): # 0xC0 - - _addFragment(''' - <constructor> - <header> - <memberof>BmpString</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - - def __init__(self, optional=0, default=''): - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_PRIMITIVE, TAG_BMPSTRING, lambda x : x, lambda x : x, optional, default) - -_addFragment(''' -<class> - <header> - <name>Sequence</name> - <super>_GeneralObject</super> - </header> - <body> - <para> - This object represents the ASN1 SEQUENCE type. - </para> - </body> -</class> -''') -class Sequence(_GeneralObject): # 0x10 - - _addFragment(''' - <constructor> - <header> - <memberof>Sequence</memberof> - <super>_GeneralObject</super> - <parameter>contents</parameter> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - <body> - <para> - The <parameter>contents</parameter> should be a list or tuple containing - the contents of the sequence. - Two important members are initialised this this constructor. - First <constant>self.next</constant> this is used to keep track - of which TLVs in this sequence has been read succesfully. The second, - <constant>self.contents</constant> should be set to the list of - objects stored in this sequence. Note that the order they are - specified in is the order in which they are written or read. - </para> - </body> - </constructor> - ''') - - def __init__(self, contents, optional=0, default=''): - self.contents = contents - self.next = 0 - _GeneralObject.__init__(self, CLASS_UNIVERSAL, FORM_CONSTRUCTED, TAG_SEQUENCE, _encodeSequence, _decodeSequence, optional, default) - - def _childRead(self, obj): - if self.next < len(self.value): - if obj.read( self.value[self.next] ): - self.next += 1 - else: - obj.read() - - _addFragment(''' - <method> - <header> - <memberof>Sequence</memberof> - <name>readContents</name> - <parameter>io</parameter> - <parameter>contents</parameter> - </header> - <body> - <para> - This function implements basic SEQUENCE like reading behaviour. - It will attempt to read each of the objects in - <parameter>contents</parameter> in turn from - <parameter>io</parameter>. It exists as a function, separate - from <function>read</function> for the benefit of the SEQUENCE - OF implementation. - </para> - <para> - The TLV of this SEQUENCE is read and parsed into a list of - TLVs, which are store in <constant>self.value</constant>, by - <classname>_GeneralObject</classname>.<function>read</function>. - Then <function>read</function> is called on each member to - process each TLV in turn. The next TLV is moved onto only when - a member returns TRUE from the read call. - </para> - </body> - </method> - ''') - - def readContents(self, io, contents): - if _GeneralObject.read( self, io ): - for item in contents: - Sequence._childRead( self, item ) - return 1 - else: - return 0 - - _addFragment(''' - <method> - <header> - <memberof>Sequence</memberof> - <name>read</name> - <parameter>io</parameter> - </header> - <body> - <para> - Most of the logic for reading is implemented in <function>readContents</function> - so it can be reused for <classname>SequenceOf</classname>'s - <function>read</function> function. - </para> - </body> - </method> - ''') - - def read(self, io=None): - self.next = 0 - return self.readContents(io, self.contents) - - _addFragment(''' - <method> - <header> - <memberof>Sequence</memberof> - <name>write</name> - <parameter>file</parameter> - </header> - <body> - <para> - <constant>self.value</constant> is set to the contents of this - SEQUENCE and then written by calling - <classname>_GeneralObject</classname>.<function>write</function> - whos encoder will call <function>write</function> of - each element in the list of contents in turn. - </para> - </body> - </method> - ''') - - def write(self, file): - if self._ioSafe(): - if self._isSet(): - _GeneralObject.set( self, self.contents ) - _GeneralObject.write( self, file ) - elif self.optional: - pass - else: - prob = self.findUnset() - raise DerError, '%s is not in a state which can be written, %s is unset' % (repr(self), repr(prob) ) - - _addFragment(''' - <method> - <header> - <memberof>Sequence</memberof> - <name>set</name> - <parameter>values</parameter> - </header> - <body> - <para> - Accessing and setting values for ASN1 objects is a bit of a - thorny issue. The problem stems from the arbitrary complexity - of the data and the possible levels of nesting, which in - practice are used and are quite massive. Designing a good general - approach is a bit tricky, perhaps nearly - impossible. I choose to use a most compact - form which is excellent for simple objects and is very concise. - </para> - <para> - <parameter>value</parameter> should be a list or tuple of - values. Each element of the list (or tuple) will be used in - turn to set a member. Defaults can be specified by using the - default value itself or <constant>None</constant>. Hence, for - SEQUENCES of SEQUENCES, SEQUENCES OF, SET and so on - <parameter>values</parameter> should consist of nested lists or - tuples. Look at the ASN1 specs for that object to figure out - exactly what these should look like. - </para> - </body> - </method> - ''') - - def set(self, values): - if self.contents is None: - raise DerError, 'the contents attribute should be set before using this object' - if not( isinstance(values, types.ListType) or isinstance(values, types.TupleType) ): - raise DerError, 'a sequence should be set with a list or tuple of values' - if len(values) != len(self.contents): - raise DerError, 'wrong number of values have been supplied to set %s. Expecting %i, got %i' % \ - (self.__class__.__name__, len(self.contents), len(values) ) - - i = 0 - for val in values: - self.contents[i].set(val) - i = i + 1 - - _addFragment(''' - <method> - <header> - <memberof>Sequence</memberof> - <name>get</name> - </header> - <body> - <para> - A tuple of the values of the contents of this sequence will be - returned. Hence, for SEQUENCES of SEQUENCES, SEQUENCES OF, SET - and so on nested tuples will be returned. - <function>get</function> always returns tuples even if a list - was used to set and object. - </para> - </body> - </method> - ''') - - def get(self): - if self.contents is None: - return _GeneralObject.get(self) - else: - results = [] - for obj in self.contents: - results.append( obj.get() ) - return tuple(results) - - def reset(self): - if self.contents is None: - raise DerError, 'this object has no members to set' - self.next = 0 - for obj in self.contents: - obj.reset() # clear all child objects prior to possible setting - # via default - _GeneralObject.reset(self) - - def _isSet(self): - if self.contents is None: - raise DerError, 'this object has no members to set' - for obj in self.contents: - if not obj._ioSafe(): - return 0 - return 1 - - def findUnset(self): - if self.contents is None: - raise DerError, 'this object has no members to check' - for obj in self.contents: - if not obj._ioSafe(): - return obj - - def _ioSafe(self): - if self.optional or self._isSet(): - return 1 - else: - for obj in self.contents: - if not obj._ioSafe(): - return 0 - return 1 - -_addFragment(''' -<class> - <header> - <name>SequenceOf</name> - <super>Sequence</super> - </header> - <body> - <para> - This object represents the ASN1 SEQUENCE OF construct. - </para> - </body> -</class> -''') -class SequenceOf(Sequence): - - _addFragment(''' - <constructor> - <header> - <memberof>SequenceOf</memberof> - <super>Sequence</super> - <parameter>contains</parameter> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - <body> - <para> - The <parameter>contains</parameter> should be the constructor - for the objects which this SEQUENCE OF contains. - </para> - </body> - </constructor> - ''') - - def __init__(self, contains, optional=0, default=''): - self.contains = contains - self.sequenceOf = [] - Sequence.__init__(self, [], optional, default) - - def _ioSafe(self): - return 1 - - def reset(self): - if self.contents is None: - raise DerError, 'this object has no members to set' - self.next = 0 - self.sequenceOf = [] - _GeneralObject.reset(self) - - def _isSet(self): - if self.sequenceOf: - for obj in self.contents: - if not obj._ioSafe(): - return 0 - return 1 - else: - return 0 - - def set(self, values): - if isinstance(values, types.NoneType): - return - objects = [] - for val in values: - obj = self.contains() - obj.set(val) - objects.append(obj) - self.sequenceOf = objects - - def get(self): - results = [] - for obj in self.sequenceOf: - results.append( obj.get() ) - return tuple(results) - - def read(self, io=None): - self.sequenceOf = [] - self.next = 0 - if _GeneralObject.read( self, io ): - for tagio in _GeneralObject.get(self): - value = self.contains() - value.read(tagio) - self.sequenceOf.append(value) - return 1 - else: - return 0 - - def write(self, file): - if not self._isSet() and self.optional: - pass - else: - _GeneralObject.set( self, self.sequenceOf ) - _GeneralObject.write( self, file ) - - def __len__(self): - return len(self.sequenceOf) - - def __getitem__(self, key): - return self.sequenceOf[key] - - def __iter__(self): - for i in self.sequenceOf: - yield(i) - - def __contains__(self, item): - return item in self.sequenceOf - -_addFragment(''' -<class> - <header> - <name>Set</name> - <super>Sequence</super> - </header> - <body> - <para> - This object represents the ASN1 Set type. - </para> - </body> -</class> -''') -class Set(Sequence): # 0x11 - - _addFragment(''' - <constructor> - <header> - <memberof>Set</memberof> - <super>Sequence</super> - <parameter>contents</parameter> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - <body> - <para> - The <parameter>contents</parameter> should be a list containing - the contents of the sequence. - </para> - </body> - </constructor> - ''') - - def __init__(self, contents, optional=0, default=''): - Sequence.__init__(self, contents, optional, default) - self.normnumber = TAG_SET - -_addFragment(''' -<class> - <header> - <name>SetOf</name> - <super>SequenceOf</super> - </header> - <body> - <para> - This object represents the ASN1 SET OF construct. - </para> - </body> -</class> -''') -class SetOf(SequenceOf): - - _addFragment(''' - <constructor> - <header> - <memberof>SetOf</memberof> - <super>SequenceOf</super> - <parameter>contains</parameter> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - <body> - <para> - The <parameter>contains</parameter> should be the constructor - for the objects which this SET OF contains. - </para> - </body> - </constructor> - ''') - - def __init__(self, contains, optional=0, default=''): - SequenceOf.__init__(self, contains, optional, default) - self.normnumber = TAG_SET - -_addFragment(''' -<class> - <header> - <name>Explicit</name> - <super>Sequence</super> - </header> - <body> - <para> - Explicit objects support the DER concept of explicit tagging. In - general they behave just like a SEQUENCE which must have only one - element. See below for other differences. - </para> - </body> -</class> -''') -class Explicit(Sequence): - - _addFragment(''' - <constructor> - <header> - <memberof>Explicit</memberof> - <super>Sequence</super> - <parameter>expclass</parameter> - <parameter>expform</parameter> - <parameter>expnumber</parameter> - <parameter>contents</parameter> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - <body> - <para> - <parameter>expclass</parameter>, - <parameter>expform</parameter>, - <parameter>expnumber</parameter> should be as - specified in the ASN1 documentation for this object. - <parameter>contents</parameter> should be an object instance - such as <classname>Integer</classname>, - <classname>Oid</classname> or a derived object which supports - the <classname>_GeneralObjec</classname> interface. - </para> - </body> - </constructor> - ''') - - def __init__(self, expclass, expform, expnumber, contents, optional=0, default=''): - self.contents = [contents] - self.next = 0 - _GeneralObject.__init__(self, expclass, expform, expnumber, _encodeSequence, _decodeSequence, optional, default) - - _addFragment(''' - <method> - <header> - <memberof>Explicit</memberof> - <name>set</name> - <parameter>value</parameter> - </header> - <body> - <para> - <parameter>value</parameter> is passed direct to - <function>set</function> of the explicit object, so it should - not be placed in a list or tuple(unless you are setting a constructed - object). - </para> - </body> - </method> - ''') - def set(self, value): - return Sequence.set(self, [value]) - - _addFragment(''' - <method> - <header> - <memberof>Explicit</memberof> - <name>get</name> - </header> - <body> - <para> - The value of explicit object is returned and not - put in a tuple. - </para> - </body> - </method> - ''') - def get(self): - return Sequence.get(self)[0] - -_addFragment(''' -<class> - <header> - <name>Choice</name> - </header> - <body> - <para> - This object represents the ASN1 Choice type. - </para> - </body> -</class> -''') -class Choice(object): - - _addFragment(''' - <constructor> - <header> - <memberof>Choice</memberof> - <parameter>choices</parameter> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - <body> - <para> - <parameter>choices</parameter> should be a dictionary of - objects which support the <classname>_GeneralObject</classname> - interface. The key being the name of the choice specified in the - ASN1 documentation. <parameter>optional</parameter> is a boolean - indicating if this object is optional. The final parameter, - <parameter>default</parameter> is the base 64 encoded DER - value, which should be used as the default in leu of a value to - read or incase it is unset. If neither - <parameter>optional</parameter> or - <parameter>default</parameter> is not set then the first choice - which is optional or has a default will be honored. - </para> - </body> - </constructor> - ''') - - def __init__(self, choices, optional=0, default=''): - self.value = None - self.choices = choices - self.optional = optional - self.default = default - self.choice = None - self.reset() - - def _ioSafe(self): - if self.optional or self._isSet(): - return 1 - elif self.choice and self.choices[ self.choice ]._ioSafe(): - return 1 - else: - return 0 - - def _isSet(self): - if self.choice and self.choices[self.choice]._isSet(): - return 1 - else: - return 0 - - _addFragment(''' - <method> - <header> - <memberof>Choice</memberof> - <name>reset</name> - </header> - <body> - <para> - This function re-initialises the object, clearing the value or - setting it to any default. - </para> - </body> - </method> - ''') - def reset(self): - self.value = None - self.choice = None - if self.default: - buf = cStringIO.StringIO( base64.decodestring( self.default ) ) - io = _TlvIo(buf) - io.read() - self.read(io) - else: - for key in self.choices.keys(): - self.choices[key].reset() - if self.choices[key]._ioSafe(): - self.choice = key - break; - - - _addFragment(''' - <method> - <header> - <memberof>Choice</memberof> - <name>set</name> - <parameter>value</parameter> - </header> - <body> - <para> - <parameter>value</parameter> should be a list or tuple with two - elements. The first value should be the name of the choice to - be set and the second the value to set it with. - </para> - </body> - </method> - ''') - def set(self, val): - if val is None: - return - if not (isinstance(val, types.ListType) or isinstance(val, types.TupleType)): - raise DerError, 'argument should be a list or tuple' - if not self.choices.has_key( val[0] ): - raise DerError, 'unknown choice: %s' % val[0] - self.choices[ val[0] ].set(val[1]) - self.choice = val[0] - - _addFragment(''' - <method> - <header> - <memberof>Choice</memberof> - <name>get</name> - </header> - <body> - <para> - This function will return tuple with two elements. The first - value will be the name of the choice which was set and the second - the value it was set to. - </para> - </body> - </method> - ''') - - def get(self): - if self._isSet(): - return (self.choice, self.choices[ self.choice ].get()) - else: - return None - - _addFragment(''' - <method> - <header> - <memberof>Choice</memberof> - <name>toString</name> - </header> - <body> - <para> - Encodes the value in DER and returns it as a string. - </para> - </body> - </method> - ''') - - def toString(self): - buf = cStringIO.StringIO() - self.write(buf) - return buf.getvalue() - - _addFragment(''' - <method> - <header> - <memberof>Choice</memberof> - <name>fromString</name> - </header> - <body> - <para> - Decodes the string and sets the value of this object. - </para> - </body> - </method> - ''') - - def fromString(self, value): - buf = cStringIO.StringIO(value) - self.read(buf) - - _addFragment(''' - <method> - <header> - <memberof>Choice</memberof> - <name>read</name> - <parameter>io</parameter> - </header> - <body> - <para> - <parameter>io</parameter> should be a file like object. If the - object being read matches the expected class, form and tag the - value is read and decoded using - <function>decRoutine</function>. Else, if it has a default - that is read and stored. - </para> - <para> - The return value of this function does not indicate success but - whether this TLV was processed successfully. This bahaviour is - vital for processing constructed types since the object may be - optional or have a default. Failure to decode would be indicated - by an exception. - </para> - </body> - </method> - ''') - - def _readChoices(self, io): - for key in self.choices.keys(): - try: - readindicator = self.choices[key].read(io) - self.choice = key - break; - except DerError: - if DEBUG: - traceback.print_exc() - return readindicator - - def read(self, io=None): - - self.choice = None - processDefOpt = 0 - readindicator = 0 - - if io is None: - processDefOpt = 1 - elif isinstance(io, _TlvIo): - if not io: - processDefOpt = 1 - else: - pos = io.tell() - io.seek(0,2) - if io.tell(): - io.seek(pos) - else: - processDefOpt = 1 - - if processDefOpt: - if self.optional or self.default: - self.reset() - return 0 - else: - readindicator = self._readChoices(io) - for key in self.choices.keys(): - try: - readindicator = self.choices[key].read(io) - self.choice = key - break; - except DerError: - if DEBUG: - traceback.print_exc() - if not self._isSet(): - raise DerError, 'no TLV is available to read in non-optional/non-default object: %s' % repr(self) - else: - return readindicator - - if not isinstance(io, _TlvIo): - tmp = _TlvIo(io) - tmp.read() - io = tmp - - for key in self.choices.keys(): - try: - if self.choices[key].read(io): - self.choice = key - readindicator = 1 - break; - except DerError: - if DEBUG: - traceback.print_exc() - - if not self._isSet(): - self.reset() - else: - return readindicator - - _addFragment(''' - <method> - <header> - <memberof>Choice</memberof> - <name>write</name> - <parameter>file</parameter> - </header> - <body> - <para> - If this object has not been set and is not optional and dosn't - have a default, a <classname>DerError</classname> exception will be raised - </para> - <para> - If no value has been set and this object is optional, nothing - is written. If this object's value is equal to the default, - nothing is written as stipulated by DER. Otherwise the value - is encoded and written. - </para> - </body> - </method> - ''') - def write(self,file): - if self.optional and not self.choice: - pass - elif not self.choice: - raise DerError, 'choice not set' - elif self.choice: - if self.default: - defval = base64.decodestring( self.default ) - if defval != self.choices[ self.choice ].toString(): - self.choices[ self.choice ].write(file) - else: - self.choices[ self.choice ].write(file) - else: - raise DerError, 'an internal error has occured: %s' % repr(self) - - diff --git a/pow/POW-0.7/lib/_simpledb.py b/pow/POW-0.7/lib/_simpledb.py deleted file mode 100755 index 190e96be..00000000 --- a/pow/POW-0.7/lib/_simpledb.py +++ /dev/null @@ -1,55 +0,0 @@ -#*****************************************************************************# -#* *# -#* Copyright (c) 2002, Peter Shannon *# -#* All rights reserved. *# -#* *# -#* Redistribution and use in source and binary forms, with or without *# -#* modification, are permitted provided that the following conditions *# -#* are met: *# -#* *# -#* * Redistributions of source code must retain the above *# -#* copyright notice, this list of conditions and the following *# -#* disclaimer. *# -#* *# -#* * Redistributions in binary form must reproduce the above *# -#* copyright notice, this list of conditions and the following *# -#* disclaimer in the documentation and/or other materials *# -#* provided with the distribution. *# -#* *# -#* * The name of the contributors may be used to endorse or promote *# -#* products derived from this software without specific prior *# -#* written permission. *# -#* *# -#* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *# -#* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *# -#* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *# -#* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS *# -#* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *# -#* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *# -#* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *# -#* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *# -#* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *# -#* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *# -#* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *# -#* *# -#*****************************************************************************# - -import _oids, _objects, types - -class OidData(object): - def __init__(self): - self.oids = _oids.data - self.objs = _objects.data - - def obj2oid(self, obj): - if not self.objs.has_key(obj): - raise Exception, 'unknown object: %s' % obj - return tuple(self.objs[obj]['oid']) - - def oid2obj(self, oid): - if isinstance( oid, types.ListType ): - oid = tuple(oid) - if not self.oids.has_key(oid): - raise Exception, 'unknown oid %s' % `oid` - return self.oids[oid]['name'] - diff --git a/pow/POW-0.7/lib/pkix.py b/pow/POW-0.7/lib/pkix.py deleted file mode 100755 index e7d9dde1..00000000 --- a/pow/POW-0.7/lib/pkix.py +++ /dev/null @@ -1,2087 +0,0 @@ -#*****************************************************************************# -#* *# -#* Copyright (c) 2002, Peter Shannon *# -#* All rights reserved. *# -#* *# -#* Redistribution and use in source and binary forms, with or without *# -#* modification, are permitted provided that the following conditions *# -#* are met: *# -#* *# -#* * Redistributions of source code must retain the above *# -#* copyright notice, this list of conditions and the following *# -#* disclaimer. *# -#* *# -#* * Redistributions in binary form must reproduce the above *# -#* copyright notice, this list of conditions and the following *# -#* disclaimer in the documentation and/or other materials *# -#* provided with the distribution. *# -#* *# -#* * The name of the contributors may be used to endorse or promote *# -#* products derived from this software without specific prior *# -#* written permission. *# -#* *# -#* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *# -#* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *# -#* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *# -#* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS *# -#* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *# -#* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *# -#* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *# -#* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *# -#* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *# -#* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *# -#* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *# -#* *# -#*****************************************************************************# - -import types, time, pprint, cStringIO, _der -from _simpledb import OidData as _OidData -from _der import * - -DEBUG = 0 - -_oidData = _OidData() -obj2oid = _oidData.obj2oid -oid2obj = _oidData.oid2obj - -_fragments = [] - -def _docset(): - return _der._docset() + _fragments - -#---------- crypto driver ----------# - -class CryptoDriver(object): - """Dispatcher for crypto calls. - - This module has very minimal dependencies on crypto code, as it's - almost entirely about ASN.1 encoding and decoding. Rather than - wiring in the handful of crypto calls, we dispatch them through - this driver. The default driver uses POW, but you can replace it - with any crypto package you like. - - This is a virtual class. You will have to subtype it. - """ - - def getOID(self, digestType): - """Convert a digest identifier into an OID. - - If the identifier we get is a tuple, we assume it's already an - OID and just return it. If the identifier is in the driver - identifier mapping table, we use that to return an OID. - Otherwise, we try mapping it via the name-to-OID database. - """ - if isinstance(digestType, tuple): - return digestType - if digestType in self.driver2OID: - return self.driver2OID[digestType] - return obj2oid(digestType) - - def sign(self, key, oid, plaintext): - """Sign something with an RSA key and a given digest algorithm.""" - raise NotImplementedError - - def verify(self, key, oid, plaintext, signature): - """Verify a signature.""" - raise NotImplementedError - - def toPublicDER(self, key): - """Get the DER representation of an RSA key.""" - raise NotImplementedError - - def fromPublicDER(self, der): - """Set the driver representation of an RSA key from DER.""" - raise NotImplementedError - -class POWCryptoDriver(CryptoDriver): - """Dispatcher for crypto calls using POW package.""" - - def __init__(self): - global POW - try: - import rpki.POW - POW = rpki.POW - except ImportError: - import POW - self.driver2OID = {} - for k, v in (("MD2_DIGEST", (1, 2, 840, 113549, 1, 1, 2)), # md2WithRSAEncryption - ("MD5_DIGEST", (1, 2, 840, 113549, 1, 1, 4)), # md5WithRSAEncryption - ("SHA_DIGEST", (1, 3, 14, 3, 2, 15)), # shaWithRSAEncryption - ("SHA1_DIGEST", (1, 2, 840, 113549, 1, 1, 5)), # sha1withRSAEncryption - ("RIPEMD160_DIGEST", (1, 2, 840, 113549, 1, 1, 6)), # ripemd160WithRSAEncryption - ("SHA256_DIGEST", (1, 2, 840, 113549, 1, 1, 11)), # sha256WithRSAEncryption - ("SHA384_DIGEST", (1, 2, 840, 113549, 1, 1, 12)), # sha384WithRSAEncryption - ("SHA512_DIGEST", (1, 2, 840, 113549, 1, 1, 13)), # sha512WithRSAEncryption - ): - try: - self.driver2OID[getattr(POW, k)] = v - except AttributeError: - pass - self.OID2driver = dict((v,k) for k,v in self.driver2OID.items()) - - def _digest(self, oid, plaintext): - digest = POW.Digest(self.OID2driver[oid]) - digest.update(plaintext) - return digest.digest() - - def sign(self, key, oid, plaintext): - return key.sign(self._digest(oid, plaintext), self.OID2driver[oid]) - - def verify(self, key, oid, plaintext, signature): - return key.verify(signature, self._digest(oid, plaintext), self.OID2driver[oid]) - - def toPublicDER(self, key): - return key.derWrite(POW.RSA_PUBLIC_KEY) - - def fromPublicDER(self, der): - return POW.derRead(POW.RSA_PUBLIC_KEY, der) - -_cryptoDriver = None # Don't touch this directly - -def setCryptoDriver(driver): - """Set crypto driver. - - The driver should be an instance of CryptoDriver. - """ - assert isinstance(driver, CryptoDriver) - global _cryptoDriver - _cryptoDriver = driver - -def getCryptoDriver(): - """Return the currently selected CryptoDriver instance. - - If no driver has been selected, instantiate the default POW driver. - """ - global _cryptoDriver - if _cryptoDriver is None: - setCryptoDriver(POWCryptoDriver()) - return _cryptoDriver - -#---------- crypto driver ----------# - -def _addFragment(frag): - global _fragments - _fragments.append(frag) - -_addFragment(''' -<modulefunction> - <header> - <name>utc2time</name> - <parameter>time</parameter> - </header> - <body> - <para> - This is a helper function for turning a UTCTime string into an - integer. It isn't built into the encoder since the various - functions which are used to manipulate the tm structure are - notoriously unreliable. - </para> - </body> -</modulefunction> -''') -def utc2time(val): - 'der encoded value not including tag or length' - if not isinstance(val, types.StringType): - raise DerError, 'argument should be a string' - t = time.strptime(val, '%y%m%d%H%M%SZ') - return int(time.mktime(t)) - -_addFragment(''' -<modulefunction> - <header> - <name>time2utc</name> - <parameter>time</parameter> - </header> - <body> - <para> - This is a helper function for turning an integer into a - UTCTime string. It isn't built into the encoder since the - various functions which are used to manipulate the tm structure - are notoriously unreliable. - </para> - </body> -</modulefunction> -''') -def time2utc(val): - 'numerical time value like time_t' - val = int(val) - t = time.gmtime(val) - return time.strftime('%y%m%d%H%M%SZ', t) - -_addFragment(''' -<modulefunction> - <header> - <name>gen2time</name> - <parameter>time</parameter> - </header> - <body> - <para> - This is a helper function for turning a GeneralizedTime string into an - integer. It isn't built into the encoder since the various - functions which are used to manipulate the tm structure are - notoriously unreliable. - </para> - </body> -</modulefunction> -''') -def gen2Time(val): - 'der encoded value not including tag or length' - if not isinstance(val, types.StringType): - raise DerError, 'argument should be a string' - t = time.strptime(val, '%Y%m%d%H%M%SZ') - return int(time.mktime(t)) - -_addFragment(''' -<modulefunction> - <header> - <name>time2gen</name> - <parameter>time</parameter> - </header> - <body> - <para> - This is a helper function for turning an integer into a - GeneralizedTime string. It isn't built into the encoder since the - various functions which are used to manipulate the tm structure - are notoriously unreliable. - </para> - </body> -</modulefunction> -''') -def time2gen(val): - 'numerical time value like time_t' - val = int(val) - t = time.gmtime(val) - return time.strftime('%Y%m%d%H%M%SZ', t) - -_addFragment(''' -<method> - <header> - <name>ip42oct</name> - <parameter>ip</parameter> - </header> - <body> - <para> - <parameter>ip</parameter> should be a list or tuple of integers, - from 0 to 256. - </para> - <example> - <title>Setting <classname>IpAddress</classname></title> - <programlisting> - ip = IpAddress() - ip.set( ip42oct(192, 168, 0, 231) ) - </programlisting> - </example> - </body> -</method> -''') -def ip42oct(val0, val1, val2, val3): - return chr(val0) + chr(val1) + chr(val2) + chr(val3) - -_addFragment(''' -<method> - <header> - <name>oct2ip4</name> - <parameter>val</parameter> - </header> - <body> - <para> - Returns a tuple of 4 integers, from 0 to 256. - </para> - </body> -</method> -''') -def oct2ip4(val): - if not isinstance(val, types.StringType) or len(val) != 4: - raise DerError, 'parameter should be string of 4 characters' - return ( ord(val[0]), ord(val[1]), ord(val[2]), ord(val[3]) ) - -#---------- certificate support ----------# -class TbsCertificate(Sequence): - def __init__(self, optional=0, default=''): - - self.version = Integer() - self.explicitVersion = Explicit( CLASS_CONTEXT, FORM_CONSTRUCTED, 0, self.version, 0, 'oAMCAQA=\n' ) - - self.serial = Integer() - self.signature = AlgorithmIdentifier() - self.issuer = Name() - self.subject = Name() - self.subjectPublicKeyInfo = SubjectPublicKeyInfo() - - self.validity = Validity() - - self.issuerUniqueID = BitString(1) - self.issuerUniqueID.implied( CLASS_CONTEXT, FORM_PRIMITIVE, 1 ) - self.subjectUniqueID = BitString(1) - self.subjectUniqueID.implied( CLASS_CONTEXT, FORM_PRIMITIVE, 2 ) - - self.extensions = Extensions() - self.explicitExtensions = Explicit( CLASS_CONTEXT, FORM_CONSTRUCTED, 3, self.extensions, 1 ) - - contents = [ - self.explicitVersion, - self.serial, - self.signature, - self.issuer, - self.validity, - self.subject, - self.subjectPublicKeyInfo, - self.issuerUniqueID, - self.subjectUniqueID, - self.explicitExtensions - ] - - Sequence.__init__(self, contents, optional, default) - -class Validity(Sequence): - def __init__(self, optional=0, default=''): - Time = lambda : Choice({ 'generalTime' : GeneralizedTime(), 'utcTime' : UtcTime() }) - self.notBefore = Time() - self.notAfter = Time() - contents = [self.notBefore, self.notAfter] - Sequence.__init__(self, contents, optional, default) - -# IA5String should not be allowed in DirectoryString, but old -# implementations (deprecated but not quite outlawed by RFC 3280) -# sometimes use it for EmailAddress attributes in subject names, which -# triggers decode failures here unless we violate RFC 3280 by allowing -# IA5String. Do not use, do not use, do not use. - -class DirectoryString(Choice): - def __init__(self, optional=0, default=''): - choices = { 'teletexString' : T61String(), - 'printableString' : PrintableString(), - 'universalString' : UniversalString(), - 'bmpString' : BmpString(), - 'utf8String' : Utf8String(), - 'ia5String' : IA5String() } - - Choice.__init__(self, choices, optional, default) - -class AttributeTypeAndValue(Sequence): - def __init__(self, optional=0, default=''): - self.type = Oid() - self.dirstr = DirectoryString() - contents = [ self.type, self.dirstr ] - Sequence.__init__(self, contents, optional, default) - -class RelativeDistinguishedName(SetOf): - def __init__(self, optional=0, default=''): - SetOf.__init__(self, AttributeTypeAndValue, optional, default) - -class Name(SequenceOf): - def __init__(self, optional=0, default=''): - SequenceOf.__init__(self, RelativeDistinguishedName, optional, default) - -class AlgorithmIdentifier(Sequence): - def __init__(self, optional=0, default=''): - self.algorithm = Oid() - self.parameters = Null() - contents = [self.algorithm, self.parameters] - Sequence.__init__(self, contents, optional, default) - -class SubjectPublicKeyInfo(Sequence): - def __init__(self, optional=0, default=''): - self.algorithmId = AlgorithmIdentifier() - self.subjectPublicKey = AltBitString() - contents = [ self.algorithmId, self.subjectPublicKey ] - Sequence.__init__(self, contents, optional, default) - -class Extensions(SequenceOf): - def __init__(self, optional=0, default=''): - SequenceOf.__init__(self, Extension, optional, default) - -_addFragment(''' -<class> - <header> - <name>Certificate</name> - <super>Sequence</super> - </header> - <body> - <example> - <title>Setting <classname>Certificate</classname></title> - <programlisting> - rsa = POW.Asymmetric() - cert = POW.pkix.Certificate() - cert.setVersion(1) - cert.setSerial(5) - - name = ( (( o2i('countryName'), ('printableString', 'GB') ),), - (( o2i('stateOrProvinceName'), ('printableString', 'Hertfordshire') ),), - (( o2i('organizationName'), ('printableString', 'The House') ),), - (( o2i('commonName'), ('printableString', 'Client') ),) ) - - cert.setIssuer(name) - cert.setSubject(name) - - now = POW.pkix.time2gen( time.time() ) - then = POW.pkix.time2gen(time.time() + 60*60*24*365*12) - cert.setNotBefore( ('generalTime', now) ) - cert.setNotAfter( ( 'generalTime', then) ) - cert.setIssuerUniqueID((1,0,1,0)) - cert.setSubjectUniqueID((1,0,0,1)) - cert.sign(rsa, POW.MD5_DIGEST) - </programlisting> - </example> - </body> -</class> -''') - -class Certificate(Sequence): - - _addFragment(''' - <constructor> - <header> - <memberof>Certificate</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - def __init__(self, optional=0, default=''): - self.tbs = TbsCertificate() - self.signatureAlgorithm = AlgorithmIdentifier() - self.signatureValue = AltBitString() - contents = [ self.tbs, self.signatureAlgorithm, self.signatureValue ] - Sequence.__init__(self, contents, optional, default) - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>setVersion</name> - <parameter>version</parameter> - </header> - <body> - <para> - This function sets an <classname>Integer</classname> object. 0 - indicates a version 1 certificate, 1 a version 2 certificate and 2 a - version 3 certificate. - </para> - </body> - </method> - ''') - def setVersion(self, version): - self.tbs.version.set(version) - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>getVersion</name> - </header> - <body> - <para> - This function returns whatever the version object is set to, - this should be 0, 1 or 2. - </para> - </body> - </method> - ''') - def getVersion(self): - return self.tbs.version.get() - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>setSerial</name> - <parameter>serial</parameter> - </header> - <body> - <para> - This function sets an <classname>Integer</classname> object. - No two certificates issued should ever have the same serial - number. - </para> - </body> - </method> - ''') - def setSerial(self, serial): - self.tbs.serial.set(serial) - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>getVersion</name> - </header> - <body> - <para> - This function returns whatever the serial object is set to. - </para> - </body> - </method> - ''') - def getSerial(self): - return self.tbs.serial.get() - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>setIssuer</name> - <parameter>names</parameter> - </header> - <body> - <para> - This function sets an <classname>Name</classname> object. - See <classname>Certificate</classname> class for an example. - </para> - </body> - </method> - ''') - def setIssuer(self, issuer): - self.tbs.issuer.set(issuer) - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>getIssuer</name> - </header> - <body> - <para> - This function returns a complex tuple containing other tuples. - </para> - </body> - </method> - ''') - def getIssuer(self): - return self.tbs.issuer.get() - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>setSubject</name> - <parameter>names</parameter> - </header> - <body> - <para> - This function sets an <classname>Name</classname> object. - See <classname>Certificate</classname> class for an example. - </para> - </body> - </method> - ''') - def setSubject(self, subject): - self.tbs.subject.set(subject) - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>getSubject</name> - </header> - <body> - <para> - This function returns a complex tuple containing other tuples. - </para> - </body> - </method> - ''') - def getSubject(self): - return self.tbs.subject.get() - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>setNotBefore</name> - <parameter>time</parameter> - </header> - <body> - <para> - This function sets a <classname>Choice</classname> object. - It can be either a <classname>GeneralTime</classname> or - <classname>UTCTime</classname> object. The functions - <function>gen2time</function>, <function>utc2time</function>, - <function>time2gen</function> and <function>time2utc</function> - can be used to convert to and from integer times and their - string representation. - </para> - <example> - <title><function>setNotBefore</function> method usage</title> - <programlisting> - cert = POW.pkix.Certificate() - now = POW.pkix.time2gen( time.time() ) - cert.setNotBefore( ('generalTime', now) ) - </programlisting> - </example> - </body> - </method> - ''') - def setNotBefore(self, nb): - self.tbs.validity.notBefore.set(nb) - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>getNotBefore</name> - </header> - <body> - <para> - This function returns a tuple indicating which type of time was - stored and its value. See <function>setNotBefore</function> for details. - </para> - </body> - </method> - ''') - def getNotBefore(self): - return self.tbs.validity.notBefore.get() - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>setNotAfter</name> - <parameter>time</parameter> - </header> - <body> - <para> - This function sets a <classname>Choice</classname> object. - See <function>setNotBefore</function> for details. - </para> - </body> - </method> - ''') - def setNotAfter(self, na): - self.tbs.validity.notAfter.set(na) - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>getNotAfter</name> - </header> - <body> - <para> - This function returns a tuple indicating which type of time was - stored and its value. See <function>setNotBefore</function> for details. - </para> - </body> - </method> - ''') - def getNotAfter(self): - return self.tbs.validity.notAfter.get() - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>setIssuerUniqueID</name> - <parameter>id</parameter> - </header> - <body> - <para> - This function sets a <classname>BitString</classname> object. - This is part of the X509v2 standard and is quite poorly - regarded in general, its use is not recommended. It is set - using the normal <classname>BitString</classname> method, that - is with a sequence of true/false objects. - </para> - </body> - </method> - ''') - def setIssuerUniqueID(self, id): - self.tbs.issuerUniqueID.set(id) - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>getIssuerUniqueID</name> - </header> - <body> - <para> - This function returns a tuple of integers, 1 or 0. - </para> - </body> - </method> - ''') - def getIssuerUniqueID(self): - return self.tbs.issuerUniqueID.get() - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>setSubjectUniqueID</name> - <parameter>id</parameter> - </header> - <body> - <para> - This function sets a <classname>BitString</classname> object. - This is part of the X509v2 standard and is quite poorly - regarded in general, its use is not recommended. It is set - using the normal <classname>BitString</classname> method, that - is with a sequence of true/false objects. - </para> - </body> - </method> - ''') - def setSubjectUniqueID(self, id): - self.tbs.subjectUniqueID.set(id) - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>getSubjectUniqueID</name> - </header> - <body> - <para> - This function returns a tuple of integers, 1 or 0. - </para> - </body> - </method> - ''') - def getSubjectUniqueID(self): - return self.tbs.subjectUniqueID.get() - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>setExtensions</name> - <parameter>extns</parameter> - </header> - <body> - <para> - This method sets an <classname>Extensions</classname> object, - defined as SEQUENCE OF Extension. The parameter - <parameter>extns</parameter> should consist of a list or tuple - of values suitable to set an extension. See the extension - class for details. - </para> - </body> - </method> - ''') - def setExtensions(self, extns): - self.tbs.extensions.set(extns) - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>getExtensions</name> - </header> - <body> - <para> - This function returns a tuple of - <classname>Extension</classname> values. See - <classname>Extension</classname> for details. - </para> - </body> - </method> - ''') - def getExtensions(self): - return self.tbs.extensions.get() - - def getExtension(self, oid): - for x in self.getExtensions(): - if x[0] == oid: - return x - return None - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>sign</name> - <parameter>rsa</parameter> - <parameter>digestType</parameter> - </header> - <body> - <para> - This function updates structured of the - <classname>Certificate</classname> and - <constant>tbs</constant> as appropriate and performs the - specified digest on the <constant>tbs</constant> and set - <constant>signedText</constant> to signed the digest. - </para> - </body> - </method> - ''') - def sign(self, rsa, digestType): - driver = getCryptoDriver() - oid = driver.getOID(digestType) - self.tbs.signature.set([oid, None]) - signedText = driver.sign(rsa, oid, self.tbs.toString()) - self.signatureAlgorithm.set([oid, None]) - self.signatureValue.set(signedText) - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>verify</name> - <parameter>rsa</parameter> - </header> - <body> - <para> - This function works out what kind of digest was used to - during signing, calculates the digest of - <constant>tbs</constant> and verifies the envelope using the - key. - </para> - </body> - </method> - ''') - def verify(self, rsa): - driver = getCryptoDriver() - oid = self.signatureAlgorithm.get()[0] - return driver.verify(rsa, oid, self.tbs.toString(), self.signatureValue.get()) - -#---------- certificate support ----------# -#---------- CRL ----------# - -class RevokedCertificate(Sequence): - def __init__(self, optional=0, default=''): - self.userCertificate = Integer() - self.revocationDate = Choice( { 'generalTime' : GeneralizedTime(), 'utcTime' : UtcTime() } ) - self.crlEntryExtensions = Extensions(1) - contents = [ self.userCertificate, self.revocationDate, self.crlEntryExtensions ] - Sequence.__init__(self, contents, optional, default) - -class RevokedCertificates(SequenceOf): - def __init__(self, optional=0, default=''): - SequenceOf.__init__(self, RevokedCertificate, optional, default) - -class TbsCertList(Sequence): - def __init__(self, optional=0, default=''): - self.version = Integer(1) - self.signature = AlgorithmIdentifier() - self.issuer = Name() - self.thisUpdate = Choice( { 'generalTime' : GeneralizedTime(), 'utcTime' : UtcTime() } ) - self.nextUpdate = Choice( { 'generalTime' : GeneralizedTime(), 'utcTime' : UtcTime() }, 1 ) - self.revokedCertificates = RevokedCertificates(1) - self.crlExtensions = Extensions() - self.explicitCrlExtensions = Explicit( CLASS_CONTEXT, FORM_CONSTRUCTED, 0, self.crlExtensions, 1 ) - contents = [ self.version, - self.signature, - self.issuer, - self.thisUpdate, - self.nextUpdate, - self.revokedCertificates, - self.explicitCrlExtensions ] - Sequence.__init__(self, contents, optional, default) - -_addFragment(''' -<class> - <header> - <name>CertificateList</name> - <super>Sequence</super> - </header> - <body> - <example> - <title>Setting <classname>CertificateList</classname></title> - <programlisting> - now = POW.pkix.time2gen( time.time() ) - then = POW.pkix.time2gen(time.time() + 60*60*24*365*12) - rsa = POW.Asymmetric() - - crl = POW.pkix.CertificateList() - crl.setThisUpdate( ('generalTime', now ) ) - - name = ( (( o2i('countryName'), ('printableString', 'GB') ),), - (( o2i('stateOrProvinceName'), ('printableString', 'Hertfordshire') ),), - (( o2i('organizationName'), ('printableString', 'The House') ),), - (( o2i('commonName'), ('printableString', 'Client') ),) ) - - myRevocations = ( - (1, ('generalTime', now), ()), - (2, ('generalTime', now), ()), - (3, ('generalTime', now), (( o2i('cRLReason'), 0, 1),)) - ) - - crl.setIssuer(name) - crl.setRevokedCertificates( myRevocations ) - - crl.sign(rsa, POW.MD5_DIGEST) - </programlisting> - </example> - </body> -</class> -''') -class CertificateList(Sequence): - _addFragment(''' - <constructor> - <header> - <memberof>CertificateList</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - def __init__(self, optional=0, default=''): - self.tbs = TbsCertList() - self.signatureAlgorithm = AlgorithmIdentifier() - self.signature = AltBitString() - contents = [self.tbs, self.signatureAlgorithm, self.signature] - Sequence.__init__(self, contents, optional, default) - - _addFragment(''' - <method> - <header> - <memberof>CertificateList</memberof> - <name>setVersion</name> - <parameter>version</parameter> - </header> - <body> - <para> - This function sets an <classname>Integer</classname> object. 0 - indicates a version 1 CRL, and 1 a version 2 CRL. - </para> - </body> - </method> - ''') - def setVersion(self, version): - self.tbs.version.set(version) - - _addFragment(''' - <method> - <header> - <memberof>CertificateList</memberof> - <name>getVersion</name> - </header> - <body> - <para> - This function returns whatever the version object is set to, - this should be 0, 1 or 2. - </para> - </body> - </method> - ''') - def getVersion(self): - return self.tbs.version.get() - - _addFragment(''' - <method> - <header> - <memberof>CertificateList</memberof> - <name>setIssuer</name> - <parameter>names</parameter> - </header> - <body> - <para> - This function sets an <classname>Name</classname> object. - </para> - </body> - </method> - ''') - def setIssuer(self, issuer): - self.tbs.issuer.set(issuer) - - _addFragment(''' - <method> - <header> - <memberof>CertificateList</memberof> - <name>getIssuer</name> - </header> - <body> - <para> - This function returns a complex tuple containing other tuples. - </para> - </body> - </method> - ''') - def getIssuer(self): - return self.tbs.issuer.get() - - _addFragment(''' - <method> - <header> - <memberof>setThisUpdate</memberof> - <name>setNotBefore</name> - <parameter>time</parameter> - </header> - <body> - <para> - This function sets a <classname>Choice</classname> object. - It can be either a <classname>GeneralTime</classname> or - <classname>UTCTime</classname> object. The functions - <function>gen2time</function>, <function>utc2time</function>, - <function>time2gen</function> and <function>time2utc</function> - can be used to convert to and from integer times and their - string representation. - </para> - <example> - <title><function>setNotBefore</function> method usage</title> - <programlisting> - crl = POW.pkix.CertificateList() - now = POW.pkix.time2gen( time.time() ) - crl.setNotBefore( ('generalTime', now) ) - </programlisting> - </example> - </body> - </method> - ''') - def setThisUpdate(self, nu): - self.tbs.thisUpdate.set(nu) - - _addFragment(''' - <method> - <header> - <memberof>CertificateList</memberof> - <name>getThisUpdate</name> - </header> - <body> - <para> - This function returns a tuple containing two strings. The first - is either 'utcTime' or 'generalTime' and the second is the time - value as a string. - </para> - </body> - </method> - ''') - def getThisUpdate(self): - return self.tbs.thisUpdate.get() - - _addFragment(''' - <method> - <header> - <memberof>CertificateList</memberof> - <name>setNextUpdate</name> - </header> - <body> - <para> - See set <function>setThisUpdate</function>. - </para> - </body> - </method> - ''') - def setNextUpdate(self, nu): - self.tbs.nextUpdate.set(nu) - - _addFragment(''' - <method> - <header> - <memberof>CertificateList</memberof> - <name>getNextUpdate</name> - </header> - <body> - <para> - See set <function>getThisUpdate</function>. - </para> - </body> - </method> - ''') - def getNextUpdate(self): - return self.tbs.nextUpdate.get() - - _addFragment(''' - <method> - <header> - <memberof>CertificateList</memberof> - <name>setExtensions</name> - <parameter>extns</parameter> - </header> - <body> - <para> - This method sets an <classname>Extensions</classname> object, - defined as SEQUENCE OF Extension. The parameter - <parameter>extns</parameter> should consist of a list or tuple - of values suitable to set an extension. See the extension - class for details. - </para> - </body> - </method> - ''') - def setExtensions(self, extns): - self.tbs.crlExtensions.set(extns) - - _addFragment(''' - <method> - <header> - <memberof>CertificateList</memberof> - <name>getExtensions</name> - </header> - <body> - <para> - This function returns a tuple of - <classname>Extension</classname> values. See - <classname>Extension</classname> for details. - </para> - </body> - </method> - ''') - def getExtensions(self): - return self.tbs.crlExtensions.get() - - def getExtension(self, oid): - for x in self.getExtensions(): - if x[0] == oid: - return x - return None - - _addFragment(''' - <method> - <header> - <memberof>CertificateList</memberof> - <name>setRevokedCertificates</name> - </header> - <body> - <para> - This function sets a sequence of - <classname>revokedCertificate</classname> objects. - This object is optional. See - <classname>CertificateList</classname> for an example of its - use. - </para> - </body> - </method> - ''') - def setRevokedCertificates(self, rc): - self.tbs.revokedCertificates.set(rc) - - _addFragment(''' - <method> - <header> - <memberof>CertificateList</memberof> - <name>getRevokedCertificates</name> - </header> - <body> - <para> - This function return a sequence of - <classname>revokedCertificate</classname> objects or None. - </para> - </body> - </method> - ''') - def getRevokedCertificates(self): - return self.tbs.revokedCertificates.get() - - _addFragment(''' - <method> - <header> - <memberof>Certificate</memberof> - <name>sign</name> - </header> - <body> - <para> - This function updates structured of the - <classname>certificateList</classname> and - <classname>tBSCertList</classname> as appropriate, performs the - specified digest on the <classname>tBSCertList</classname> and sets - <constant>signedValue</constant> to signed the digest. - </para> - </body> - </method> - ''') - def sign(self, rsa, digestType): - driver = getCryptoDriver() - oid = driver.getOID(digestType) - self.tbs.signature.set([oid, None]) - signedText = driver.sign(rsa, oid, self.tbs.toString()) - self.signatureAlgorithm.set([oid, None]) - self.signature.set(signedText) - - _addFragment(''' - <method> - <header> - <memberof>CertificateList</memberof> - <name>verify</name> - </header> - <body> - <para> - This function works out what kind of digest was used to during - signing, calculates the digest of - <classname>tBSCertList</classname> and verifies the - <constant>signedText</constant> using the key. - </para> - </body> - </method> - ''') - def verify(self, rsa): - driver = getCryptoDriver() - oid = self.signatureAlgorithm.get()[0] - return driver.verify(rsa, oid, self.tbs.toString(), self.signature.get()) - -#---------- CRL ----------# -#---------- PKCS10 ----------# - -# My ASN.1-foo (and perhaps this ASN.1 implementation) isn't quite up -# to X.501 or PKCS #10, so this is partly based on a dump of what -# OpenSSL generates, and doesn't handle attributes other than X.509v3 -# extensions. - -class PKCS10AttributeSet(SetOf): - def __init__(self, optional=0, default=''): - SetOf.__init__(self, Extensions, optional, default) - -class PKCS10AttributeChoice(Choice): - def __init__(self, optional=0, default=''): - choices = { 'single' : Extensions(), - 'set' : PKCS10AttributeSet() } - Choice.__init__(self, choices, optional, default) - -class PKCS10Attributes(Sequence): - def __init__(self, optional=1, default=''): - self.oid = Oid() - self.val = PKCS10AttributeChoice() - contents = [ self.oid, self.val ] - Sequence.__init__(self, contents, optional, default) - -class CertificationRequestInfo(Sequence): - def __init__(self, optional=0, default=''): - self.version = Integer() - self.subject = Name() - self.subjectPublicKeyInfo = SubjectPublicKeyInfo() - self.attributes = PKCS10Attributes() - self.explicitAttributes = Explicit(CLASS_CONTEXT, FORM_CONSTRUCTED, 0, self.attributes) - contents = [ self.version, self.subject, self.subjectPublicKeyInfo, self.explicitAttributes ] - Sequence.__init__(self, contents, optional, default) - -class CertificationRequest(Sequence): - def __init__(self, optional=0, default=''): - self.certificationRequestInfo = CertificationRequestInfo() - self.signatureAlgorithm = AlgorithmIdentifier() - self.signatureValue = AltBitString() - contents = [ self.certificationRequestInfo, self.signatureAlgorithm, self.signatureValue ] - Sequence.__init__(self, contents, optional, default) - - def sign(self, rsa, digestType): - driver = getCryptoDriver() - oid = driver.getOID(digestType) - self.certificationRequestInfo.subjectPublicKeyInfo.fromString(driver.toPublicDER(rsa)) - signedText = driver.sign(rsa, oid, self.certificationRequestInfo.toString()) - self.signatureAlgorithm.set([oid, None]) - self.signatureValue.set(signedText) - - def verify(self): - driver = getCryptoDriver() - oid = self.signatureAlgorithm.get()[0] - rsa = driver.fromPublicDER(self.certificationRequestInfo.subjectPublicKeyInfo.toString()) - return driver.verify(rsa, oid, self.certificationRequestInfo.toString(), self.signatureValue.get()) - - def getExtensions(self): - oid = self.certificationRequestInfo.attributes.oid.get() - if oid is None: - return () - if oid != (1, 2, 840, 113549, 1, 9, 14) or \ - self.certificationRequestInfo.attributes.val.choice != "set" or \ - len(self.certificationRequestInfo.attributes.val.choices["set"]) > 1: - raise DerError, "failed to understand X.501 Attribute encoding, sorry: %s" % self.get() - return self.certificationRequestInfo.attributes.val.choices["set"][0].get() - - def getExtension(self, oid): - for x in self.getExtensions(): - if x[0] == oid: - return x - return None - - def setExtensions(self, exts): - self.certificationRequestInfo.attributes.oid.set((1, 2, 840, 113549, 1, 9, 14)) - self.certificationRequestInfo.attributes.val.set(("set", [exts])) - -#---------- PKCS10 ----------# -#---------- GeneralNames object support ----------# -class OtherName(Sequence): - def __init__(self, optional=0, default=''): - self.typeId = Oid() - self.any = Any() - contents = [self.typeId, self.any] - Sequence.__init__(self, contents, optional, default) - -class EdiPartyName(Sequence): - def __init__(self, optional=0, default=''): - self.nameAssigner = DirectoryString() - self.partyName = DirectoryString() - self.explicitNameAssigner = Explicit( CLASS_CONTEXT, FORM_CONSTRUCTED, 0, self.nameAssigner, 1 ) - self.explicitPartyName = Explicit( CLASS_CONTEXT, FORM_CONSTRUCTED, 1, self.partyName ) - contents = [ self.explicitNameAssigner, self.explicitPartyName ] - Sequence.__init__(self, contents, optional, default) - -class IpAddress(OctetString): - pass - -class GeneralName(Choice): - def __init__(self, optional=0, default=''): - - otherName = OtherName() - otherName.implied( CLASS_CONTEXT, FORM_CONSTRUCTED, 0 ) - rfc822Name = IA5String() - rfc822Name.implied( CLASS_CONTEXT, FORM_PRIMITIVE, 1 ) - dnsName = IA5String() - dnsName.implied( CLASS_CONTEXT, FORM_PRIMITIVE, 2 ) - directoryName = Name() - explicitDirectoryName = Explicit( CLASS_CONTEXT, FORM_CONSTRUCTED, 4, directoryName) - ediPartyName = EdiPartyName() - ediPartyName.implied( CLASS_CONTEXT, FORM_CONSTRUCTED, 5 ) - uri = IA5String() - uri.implied( CLASS_CONTEXT, FORM_PRIMITIVE, 6 ) - ipAddress = IpAddress() - ipAddress.implied( CLASS_CONTEXT, FORM_PRIMITIVE, 7 ) - registeredId = Oid() - registeredId.implied( CLASS_CONTEXT, FORM_PRIMITIVE, 8 ) - - choices = { 'otherName' : otherName , - 'rfc822Name' : rfc822Name , - 'dNSName' : dnsName , - 'directoryName' : explicitDirectoryName , - 'ediPartyName' : ediPartyName , - 'uri' : uri , - 'iPAddress' : ipAddress , - 'registeredId' : registeredId } - - Choice.__init__(self, choices, optional, default) - -class GeneralNames(SequenceOf): - def __init__(self, optional=0, default=''): - SequenceOf.__init__(self, GeneralName, optional, default) - -#---------- GeneralNames object support ----------# -#---------- X509v3 extensions ----------# - -_addFragment(''' -<class> - <header> - <name>BasicConstraints</name> - <super>Sequence</super> - </header> - <body> - <para> - This little extension has recently caused plenty of problems for - several large organisations. It consist of a - <classname>Boolean</classname> and an - <classname>Integer</classname>. The first indicates if the owner - is a CA, the second indicates how long a chain of CAs you should - trust which the subject of this certificate trusts. - </para> - <example> - <title>Setting <classname>BasicConstraints</classname></title> - <programlisting> - bc = BasicConstraints() - bc.set( (1, 1) ) - </programlisting> - </example> - </body> -</class> -''') -class BasicConstraints(Sequence): - _addFragment(''' - <constructor> - <header> - <memberof>BasicConstraints</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - def __init__(self, optional=0, default=''): - self.ca = Boolean(0, 'AQEA\n') - self.pathLenConstraint = Integer(1) - contents = [self.ca, self.pathLenConstraint] - Sequence.__init__(self, contents, optional, default) - -_addFragment(''' -<class> - <header> - <name>KeyUsage</name> - <super>BitString</super> - </header> -</class> -''') -class KeyUsage(BitString): - pass - -_addFragment(''' -<class> - <header> - <name>SubjectAltName</name> - <super>GeneralNames</super> - </header> -</class> -''') -class SubjectAltName(GeneralNames): - pass - -_addFragment(''' -<class> - <header> - <name>IssuerAltName</name> - <super>GeneralNames</super> - </header> -</class> -''') -class IssuerAltName(GeneralNames): - pass - -_addFragment(''' -<class> - <header> - <name>SubjectKeyIdentifier</name> - <super>OctetString</super> - </header> -</class> -''') -class SubjectKeyIdentifier(OctetString): - pass - -_addFragment(''' -<class> - <header> - <name>AuthorityKeyIdentifier</name> - <super>Sequence</super> - </header> - <body> - <para> - </para> - <example> - <title>Setting <classname>AuthorityKeyIdentifier</classname></title> - <programlisting> - id = AuthorityKeyIdentifier() - authdigest = POW.Digest( POW.SHA1_DIGEST ) - authdigest.update(rsa.derWrite(POW.RSA_PUBLIC_KEY)) - keyHash = authdigest.digest() - id.set( (keyHash, None, None) ) - </programlisting> - </example> - </body> - -</class> -''') -class AuthorityKeyIdentifier(Sequence): - _addFragment(''' - <constructor> - <header> - <memberof>AuthorityKeyIdentifier</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - def __init__(self, optional=0, default=''): - self.keyIdentifier = OctetString(1) - self.keyIdentifier.implied( CLASS_CONTEXT, FORM_PRIMITIVE, 0 ) - self.authorityCertIssuer = GeneralNames(1) - self.authorityCertIssuer.implied( CLASS_CONTEXT, FORM_CONSTRUCTED, 1 ) - self.authorityCertSerialNumber = Integer(1) - self.authorityCertSerialNumber.implied( CLASS_CONTEXT, FORM_PRIMITIVE, 2 ) - contents = [self.keyIdentifier, self.authorityCertIssuer, self.authorityCertSerialNumber] - Sequence.__init__(self, contents, optional, default) - -_addFragment(''' -<class> - <header> - <name>PrivateKeyUsagePeriod</name> - <super>Sequence</super> - </header> - <body> - <example> - <title>Setting <classname>PrivateKeyUsagePeriod</classname></title> - <programlisting> - period = PrivateKeyUsagePeriod() - period.set( ( time2gen( time.time() ), None) ) - </programlisting> - </example> - </body> -</class> -''') -class PrivateKeyUsagePeriod(Sequence): - _addFragment(''' - <constructor> - <header> - <memberof>PrivateKeyUsagePeriod</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - def __init__(self, optional=0, default=''): - self.notBefore = GeneralizedTime() - self.notBefore.implied( CLASS_CONTEXT, FORM_PRIMITIVE, 0 ) - self.notAfter = GeneralizedTime() - self.notAfter.implied( CLASS_CONTEXT, FORM_PRIMITIVE, 1 ) - contents = [self.notBefore, self.notAfter] - Sequence.__init__(self, contents, optional, default) - -class DisplayText(Choice): - def __init__(self, optional=0, default=''): - choices = { 'visibleString' : VisibleString(), - 'bmpString' : BmpString(), - 'utf8String' : Utf8String() } - - Choice.__init__(self, choices, optional, default) - -class NoticeNumbers(SequenceOf): - def __init__(self, optional=0, default=''): - SequenceOf.__init__(self, Integer, optional, default) - -class NoticeReference(Sequence): - def __init__(self, optional=0, default=''): - self.organization = DisplayText() - self.noticeNumbers = NoticeNumbers() - contents = [self.organization, self.noticeNumbers] - Sequence.__init__(self, contents, optional, default) - -class UserNotice(Sequence): - def __init__(self, optional=0, default=''): - self.noticeRef = NoticeReference(1) - self.explicitText = DisplayText(1) - contents = [self.noticeRef, self.explicitText] - Sequence.__init__(self, contents, optional, default) - -class Qualifier(Choice): - def __init__(self, optional=0, default=''): - choices = { 'cPSuri' : IA5String(), - 'userNotice' : UserNotice() } - - Choice.__init__(self, choices, optional, default) - -class PolicyQualifierInfo(Sequence): - def __init__(self, optional=0, default=''): - self.policyQualifierId = Oid() - self.qualifier = Qualifier() - contents = [self.policyQualifierId, self.qualifier] - Sequence.__init__(self, contents, optional, default) - -class PolicyQualifiers(SequenceOf): - def __init__(self, optional=0, default=''): - SequenceOf.__init__(self, PolicyQualifierInfo, optional, default) - -class PolicyInformation(Sequence): - def __init__(self, optional=0, default=''): - self.policyIdentifier = Oid() - self.policyQualifiers = PolicyQualifiers(1) - contents = [self.policyIdentifier, self.policyQualifiers] - Sequence.__init__(self, contents, optional, default) - -_addFragment(''' -<class> - <header> - <name>CertificatePolicies</name> - <super>SequenceOf</super> - </header> - <body> - <example> - <title>Setting <classname>CertificatePolicies</classname></title> - <programlisting> - data = ( - ( o2i('id-cti-ets-proofOfReceipt'), ( - (o2i('cps'), ('cPSuri', 'http://www.p-s.org.uk/policies/policy1')), - (o2i('unotice'), ( 'userNotice', - ((('visibleString', 'The House'),(1,2,3)), - ('visibleString', 'We guarentee nothing')))), - )), - ( o2i('id-cti-ets-proofOfOrigin'), ( - (o2i('cps'), ('cPSuri', 'http://www.p-s.org.uk/policies/policy2')), - )) - ) - policies = CertificatePolicies() - policies.set( data ) - </programlisting> - </example> - </body> -</class> -''') -class CertificatePolicies(SequenceOf): - _addFragment(''' - <constructor> - <header> - <memberof>CertificatePolicies</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - def __init__(self, optional=0, default=''): - SequenceOf.__init__(self, PolicyInformation, optional, default) - -class DistributionPointName(Choice): - def __init__(self, optional=0, default=''): - fullName = GeneralNames() - fullName.implied( CLASS_CONTEXT, FORM_CONSTRUCTED, 0 ) - nameRelativeToCRLIssuer = RelativeDistinguishedName() - nameRelativeToCRLIssuer.implied( CLASS_CONTEXT, FORM_CONSTRUCTED, 1 ) - - choices = { 'fullName' : fullName, - 'nameRelativeToCRLIssuer ' : nameRelativeToCRLIssuer } - - Choice.__init__(self, choices, optional, default) - -class DistributionPoint(Sequence): - def __init__(self, optional=0, default=''): - self.distributionPoint = DistributionPointName(1) - self.explicitDistributionPoint = Explicit(CLASS_CONTEXT, FORM_CONSTRUCTED, 0, self.distributionPoint) - self.reasons = BitString(1) - self.reasons.implied( CLASS_CONTEXT, FORM_PRIMITIVE, 1 ) - self.cRLIssuer = GeneralNames(1) - self.cRLIssuer.implied( CLASS_CONTEXT, FORM_CONSTRUCTED, 2 ) - contents = [self.explicitDistributionPoint, self.reasons, self.cRLIssuer] - Sequence.__init__(self, contents, optional, default) - -_addFragment(''' -<class> - <header> - <name>CRLDistrobutionPoints</name> - <super>SequenceOf</super> - </header> - <body> - <example> - <title>Setting <classname>CRLDistrobutionPoints</classname></title> - <programlisting> - n1 = ('directoryName', - ( (( o2i('countryName'), ('printableString', 'UK') ),), - (( o2i('stateOrProvinceName'), ('printableString', 'Herts') ),), - (( o2i('organizationName'), ('printableString', 'The House') ),), - (( o2i('commonName'), ('printableString', 'Shannon Works') ),) ) ) - - n2 = ('iPAddress', POW.pkix.ip42oct(192,168,100,51)) - - data = ( ( ('fullName',(n1, n2)), (1,1,1,1,1), (n1,) ), ) - points = CRLDistrobutionPoints() - points.set( data ) - </programlisting> - </example> - </body> -</class> -''') -class CRLDistributionPoints(SequenceOf): - _addFragment(''' - <constructor> - <header> - <memberof>CRLDistrobutionPoints</memberof> - <parameter>optional=0</parameter> - <parameter>default=''</parameter> - </header> - </constructor> - ''') - def __init__(self, optional=0, default=''): - SequenceOf.__init__(self, DistributionPoint, optional, default) - -_addFragment(''' -<class> - <header> - <name>CrlNumber</name> - <super>Integer</super> - </header> -</class> -''') -class CrlNumber(Integer): - pass - -_addFragment(''' -<class> - <header> - <name>DeltaCrlIndicator</name> - <super>Integer</super> - </header> -</class> -''') -class DeltaCrlIndicator(Integer): - pass - -_addFragment(''' -<class> - <header> - <name>InvalidityDate</name> - <super>GeneralizedTime</super> - </header> -</class> -''') -class InvalidityDate(GeneralizedTime): - pass - -_addFragment(''' -<class> - <header> - <name>CrlReason</name> - <super>Enum</super> - </header> -</class> -''') -class CrlReason(Enum): - pass - -_addFragment(''' -<class> - <header> - <name>IPAddressRange</name> - <super>Sequence</super> - </header> -</class> -''') -class IPAddressRange(Sequence): - def __init__(self, optional=0, default=''): - self.min = BitString() - self.max = BitString() - contents = [ self.min, self.max ] - Sequence.__init__(self, contents, optional, default) - -_addFragment(''' -<class> - <header> - <name>IPAddressOrRange</name> - <super>Choice</super> - </header> -</class> -''') -class IPAddressOrRange(Choice): - def __init__(self, optional=0, default=''): - choices = { 'addressPrefix' : BitString(), - 'addressRange' : IPAddressRange() } - Choice.__init__(self, choices, optional, default) - -_addFragment(''' -<class> - <header> - <name>IPAddressesOrRanges</name> - <super>SequenceOf</super> - </header> -</class> -''') -class IPAddressesOrRanges(SequenceOf): - def __init__(self, optional=0, default=''): - SequenceOf.__init__(self, IPAddressOrRange, optional, default) - -_addFragment(''' -<class> - <header> - <name>IPAddressChoice</name> - <super>Choice</super> - </header> -</class> -''') -class IPAddressChoice(Choice): - def __init__(self, optional=0, default=''): - choices = { 'inherit' : Null(), - 'addressesOrRanges' : IPAddressesOrRanges() } - Choice.__init__(self, choices, optional, default) - -_addFragment(''' -<class> - <header> - <name>IPAddressFamily</name> - <super>Sequence</super> - </header> -</class> -''') -class IPAddressFamily(Sequence): - def __init__(self, optional=0, default=''): - self.addressFamily = OctetString() - self.ipAddressChoice = IPAddressChoice() - contents = [ self.addressFamily, self.ipAddressChoice ] - Sequence.__init__(self, contents, optional, default) - -_addFragment(''' -<class> - <header> - <name>IPAddrBlocks</name> - <super>SequenceOf</super> - </header> - <body> - <para> - Implementation of RFC 3779 section 2.2.3. - </para> - </body> -</class> -''') -class IPAddrBlocks(SequenceOf): - def __init__(self, optional=0, default=''): - SequenceOf.__init__(self, IPAddressFamily, optional, default) - -_addFragment(''' -<class> - <header> - <name>ASRange</name> - <super>Sequence</super> - </header> -</class> -''') -class ASRange(Sequence): - def __init__(self, optional=0, default=''): - self.min = Integer() - self.max = Integer() - contents = [ self.min, self.max ] - Sequence.__init__(self, contents, optional, default) - -_addFragment(''' -<class> - <header> - <name>ASIdOrRange</name> - <super>Choice</super> - </header> -</class> -''') -class ASIdOrRange(Choice): - def __init__(self, optional=0, default=''): - choices = { 'id' : Integer(), - 'range' : ASRange() } - Choice.__init__(self, choices, optional, default) - -_addFragment(''' -<class> - <header> - <name>ASIdsOrRanges</name> - <super>SequenceOf</super> - </header> -</class> -''') -class ASIdsOrRanges(SequenceOf): - def __init__(self, optional=0, default=''): - SequenceOf.__init__(self, ASIdOrRange, optional, default) - -_addFragment(''' -<class> - <header> - <name>ASIdentifierChoice</name> - <super>Choice</super> - </header> -</class> -''') -class ASIdentifierChoice(Choice): - def __init__(self, optional=0, default=''): - choices = { 'inherit' : Null(), - 'asIdsOrRanges' : ASIdsOrRanges() } - Choice.__init__(self, choices, optional, default) - -_addFragment(''' -<class> - <header> - <name>ASIdentifiers</name> - <super>Sequence</super> - </header> - <body> - <para> - Implementation of RFC 3779 section 3.2.3. - </para> - </body> -</class> -''') -class ASIdentifiers(Sequence): - def __init__(self, optional=0, default=''): - # - # This is what we -should- be doing - #self.asnum = ASIdentifierChoice() - #self.rdi = ASIdentifierChoice() - #self.explicitAsnum = Explicit(CLASS_CONTEXT, FORM_CONSTRUCTED, 0, self.asnum, 1) - #self.explictRdi = Explicit(CLASS_CONTEXT, FORM_CONSTRUCTED, 1, self.rdi, 1) - #contents = [ self.explicitAsnum, self.explictRdi ] - # - # ...but it generates a spurious empty RDI clause, so try this instead - # since we know that we never use RDI anyway. - self.asnum = ASIdentifierChoice() - self.explicitAsnum = Explicit(CLASS_CONTEXT, FORM_CONSTRUCTED, 0, self.asnum, 1) - contents = [ self.explicitAsnum ] - # - Sequence.__init__(self, contents, optional, default) - - def set(self, values): - assert len(values) == 1 or (len(values) == 2 and values[1] is None) - Sequence.set(self, (values[0],)) - -_addFragment(''' -<class> - <header> - <name>AccessDescription</name> - <super>Sequence</super> - </header> -</class> -''') -class AccessDescription(Sequence): - def __init__(self, optional=0, default=''): - self.accessMethod = Oid() - self.accessLocation = GeneralName() - contents = [ self.accessMethod, self.accessLocation ] - Sequence.__init__(self, contents, optional, default) - -_addFragment(''' -<class> - <header> - <name>AuthorityInfoAccess</name> - <super>SequenceOf</super> - </header> - <body> - <para> - Implementation of RFC 3280 section 4.2.2.1. - </para> - </body> -</class> -''') -class AuthorityInfoAccess(SequenceOf): - def __init__(self, optional=0, default=''): - SequenceOf.__init__(self, AccessDescription, optional, default) - -_addFragment(''' -<class> - <header> - <name>SubjectInfoAccess</name> - <super>SequenceOf</super> - </header> - <body> - <para> - Implementation of RFC 3280 section 4.2.2.2. - </para> - </body> -</class> -''') -class SubjectInfoAccess(SequenceOf): - def __init__(self, optional=0, default=''): - SequenceOf.__init__(self, AccessDescription, optional, default) - -#---------- X509v3 extensions ----------# - -_addFragment(''' -<class> - <header> - <name>Extension</name> - <super>Sequence</super> - </header> - <body> - <para> - This class is a useful little object. It is set by passing three - values: an oid, an integer(a boolean really) and a value. The - boolean indicates if this extension is critical. The value is - used to set the extension once it has been created. The oid - is used to create the correct object which, to be fully supported it must - be one of these: - <simplelist> - <member><classname>basicConstraints</classname></member> - <member><classname>subjectAltName</classname></member> - <member><classname>issuerAltName</classname></member> - <member><classname>authorityKeyIdentifier</classname></member> - <member><classname>privateKeyUsagePeriod</classname></member> - <member><classname>certificatePolicies</classname></member> - <member><classname>cRLDistributionPoints</classname></member> - <member><classname>subjectKeyIdentifier</classname></member> - <member><classname>keyUsage</classname></member> - <member><classname>crlNumber</classname></member> - <member><classname>deltaCrlIndicator</classname></member> - <member><classname>invalidityDate</classname></member> - <member><classname>crlReason</classname></member> - </simplelist> - </para> - <example> - <title>Setting <classname>Extension</classname></title> - <programlisting> - extn = Extension() - email = ('rfc822Name', 'peter_shannon@yahoo.com') - extn.set( (obj2oid('subjectAltName'),1, (email,)) ) - </programlisting> - </example> - </body> -</class> -''') -class Extension(Sequence): - - classMap = { - (2, 5, 29, 19) : BasicConstraints, - (2, 5, 29, 17) : SubjectAltName, - (2, 5, 29, 18) : IssuerAltName, - (2, 5, 29, 35) : AuthorityKeyIdentifier, - (2, 5, 29, 16) : PrivateKeyUsagePeriod, - (2, 5, 29, 32) : CertificatePolicies, - (2, 5, 29, 31) : CRLDistributionPoints, - (2, 5, 29, 14) : SubjectKeyIdentifier, - (2, 5, 29, 15) : KeyUsage, - (2, 5, 29, 20) : CrlNumber, - (2, 5, 29, 27) : DeltaCrlIndicator, - (2, 5, 29, 24) : InvalidityDate, - (2, 5, 29, 21) : CrlReason, - (1, 3, 6, 1, 5, 5, 7, 1, 1) : AuthorityInfoAccess, - (1, 3, 6, 1, 5, 5, 7, 1, 7) : IPAddrBlocks, - (1, 3, 6, 1, 5, 5, 7, 1, 8) : ASIdentifiers, - (1, 3, 6, 1, 5, 5, 7, 1, 11) : SubjectInfoAccess, - } -# Missing -- fix later -# extendedKeyUsage -# privateKeyUsagePeriod -# policyMappings -# nameConstraints -# policyConstraints -# subjectDirectoryAttributes -# instructionCode -# issuingDistrobutionPoint - - def __init__(self, optional=0, default=''): - self.extnID = Oid() - self.critical = Boolean(0, 'AQEA') - self.extnValue = OctetString() - contents = [self.extnID, self.critical, self.extnValue] - Sequence.__init__(self, contents, optional, default) - - _addFragment(''' - <method> - <header> - <memberof>Extension</memberof> - <name>set</name> - <parameter>values</parameter> - </header> - <body> - <para> - <parameter>values</parameter> should be a sequence of three - values, the oid, critical marker and a value to set the - extension. If an unknown oid is passed to this function it - will raise an exception. <parameter>critical</parameter> is a - boolean. <parameter>value</parameter> will be used to set the - extension after it has been created. - </para> - </body> - </method> - ''') - def set(self, (oid, critical, val) ): - self.extnID.set( oid ) - self.critical.set( critical ) - - extnObj = None - if self.classMap.has_key(oid): - extnObj = self.classMap[oid]() - else: - if not (isinstance(oid, types.TupleType) or isinstance(oid, types.ListType)): - raise DerError, 'the oid should be specified as a sequence of integers' - else: - raise DerError, 'unknown object extension %s' % oid - - try: - extnObj.set( val ) - self.extnValue.set( extnObj.toString() ) - except DerError, e: - raise DerError, 'failed to set %s, with:\n\t%s\nresulting in:\n\t%s' % (oid, val, `e`) - - _addFragment(''' - <method> - <header> - <memberof>Extension</memberof> - <name>get</name> - </header> - <body> - <para> - There are several ways this function might fail to decode an - extension. Firstly if the extension was marked critical but if - the oid cannot be mapped to a class or If a failure occurs decoding the - <constant>extnValue</constant>, an exception will be raised. - If a failure occurred and the extension was not marked critical it - will return a tuple like this: <constant>(oid, critical, - ())</constant>. If no failures occur a tuple will be returned, - containg the oid, critical and extension values. - </para> - </body> - </method> - ''') - def get(self): - oid = self.extnID.get() - critical = self.critical.get() - - if self.classMap.has_key(oid): - extnObj = self.classMap[oid]() - else: - if critical: - raise DerError, 'failed to read critical extension %s' % str(oid) - else: - return (oid, critical, ()) - - try: - extnObj = self.classMap[oid]() - extnObj.fromString(self.extnValue.get()) - value = extnObj.get() - except: - if critical: - raise DerError, 'failed to read critical extension %s' % str(oid) - else: - return (oid, critical, ()) - - return (oid, critical, value) |