src/tools/py2sis/ensymble/cryptutil.py
author Vijayan <ts.vijayan@nokia.com>
Tue, 16 Feb 2010 10:07:05 +0530
changeset 0 ca70ae20a155
permissions -rw-r--r--
Base Python2.0 code
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
     1
#!/usr/bin/env python
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
     2
# -*- coding: utf-8 -*-
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
     3
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
     4
##############################################################################
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
     5
# cryptutil.py - OpenSSL command line utility wrappers for Ensymble
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
     6
# Copyright 2006, 2007, 2008 Jussi Ylänen
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
     7
#
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
     8
# This file is part of Ensymble developer utilities for Symbian OS(TM).
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
     9
#
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    10
# Ensymble is free software; you can redistribute it and/or modify
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    11
# it under the terms of the GNU General Public License as published by
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    12
# the Free Software Foundation; either version 2 of the License, or
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    13
# (at your option) any later version.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    14
#
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    15
# Ensymble is distributed in the hope that it will be useful,
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    16
# but WITHOUT ANY WARRANTY; without even the implied warranty of
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    18
# GNU General Public License for more details.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    19
#
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    20
# You should have received a copy of the GNU General Public License
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    21
# along with Ensymble; if not, write to the Free Software
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    22
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    23
##############################################################################
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    24
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    25
import sys
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    26
import os
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    27
import errno
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    28
import tempfile
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    29
import random
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    30
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    31
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    32
opensslcommand = None   # Path to OpenSSL command line tool
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    33
openssldebug   = False  # True for extra debug output
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    34
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    35
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    36
##############################################################################
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    37
# Public module-level functions
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    38
##############################################################################
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    39
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    40
def setdebug(active):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    41
    '''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    42
    Activate or deactivate debug output.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    43
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    44
    setdebug(...) -> None
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    45
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    46
    active      Debug output enabled / disabled, a boolean value
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    47
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    48
    Debug output consists of OpenSSL binary command line and
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    49
    any output produced to the standard error stream by OpenSSL.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    50
    '''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    51
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    52
    global openssldebug
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    53
    openssldebug =  not not active  # Convert to boolean.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    54
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    55
def signstring(privkey, passphrase, string):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    56
    '''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    57
    Sign a binary string using a given private key and its pass phrase.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    58
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    59
    signstring(...) -> (signature, keytype)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    60
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    61
    privkey     RSA or DSA private key, a string in PEM (base-64) format
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    62
    passphrase  pass phrase for the private key, a non-Unicode string or None
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    63
    string      a binary string to sign
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    64
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    65
    signature   signature, an ASN.1 encoded binary string
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    66
    keytype     detected key type, string, "RSA" or "DSA"
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    67
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    68
    NOTE: On platforms with poor file system security, decrypted version
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    69
    of the private key may be grabbed from the temporary directory!
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    70
    '''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    71
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    72
    if passphrase == None or len(passphrase) == 0:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    73
        # OpenSSL does not like empty stdin while reading a passphrase from it.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    74
        passphrase = "\n"
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    75
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    76
    # Create a temporary directory for OpenSSL to work in.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    77
    tempdir = mkdtemp("ensymble-XXXXXX")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    78
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    79
    keyfilename     = os.path.join(tempdir, "privkey.pem")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    80
    sigfilename     = os.path.join(tempdir, "signature.dat")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    81
    stringfilename  = os.path.join(tempdir, "string.dat")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    82
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    83
    try:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    84
        # If the private key is in PKCS#8 format, it needs to be converted.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    85
        privkey = convertpkcs8key(tempdir, privkey, passphrase)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    86
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    87
        # Decrypt the private key. Older versions of OpenSSL do not
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    88
        # accept the "-passin" parameter for the "dgst" command.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    89
        privkey, keytype = decryptkey(tempdir, privkey, passphrase)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    90
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    91
        if keytype == "DSA":
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    92
            signcmd = "-dss1"
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    93
        elif keytype == "RSA":
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    94
            signcmd = "-sha1"
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    95
        else:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    96
            raise ValueError("unknown private key type %s" % keytype)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    97
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    98
        # Write decrypted PEM format private key to file.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
    99
        keyfile = file(keyfilename, "wb")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   100
        keyfile.write(privkey)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   101
        keyfile.close()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   102
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   103
        # Write binary string to a file. On some systems, stdin is
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   104
        # always in text mode and thus unsuitable for binary data.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   105
        stringfile = file(stringfilename, "wb")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   106
        stringfile.write(string)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   107
        stringfile.close()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   108
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   109
        # Sign binary string using the decrypted private key.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   110
        command = ("dgst %s -binary -sign %s "
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   111
                   "-out %s %s") % (signcmd, quote(keyfilename),
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   112
                                    quote(sigfilename), quote(stringfilename))
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   113
        runopenssl(command)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   114
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   115
        signature = ""
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   116
        if os.path.isfile(sigfilename):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   117
            # Read signature from file.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   118
            sigfile = file(sigfilename, "rb")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   119
            signature = sigfile.read()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   120
            sigfile.close()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   121
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   122
        if signature.strip() == "":
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   123
            # OpenSSL did not create output, something went wrong.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   124
            raise ValueError("unspecified error during signing")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   125
    finally:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   126
        # Delete temporary files.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   127
        for fname in (keyfilename, sigfilename, stringfilename):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   128
            try:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   129
                os.remove(fname)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   130
            except OSError:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   131
               pass
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   132
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   133
        # Remove temporary directory.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   134
        os.rmdir(tempdir)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   135
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   136
    return (signature, keytype)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   137
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   138
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   139
def certtobinary(pemcert):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   140
    '''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   141
    Convert X.509 certificates from PEM (base-64) format to DER (binary).
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   142
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   143
    certtobinary(...) -> dercert
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   144
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   145
    pemcert     One or more X.509 certificates in PEM (base-64) format, a string
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   146
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   147
    dercert     X.509 certificate(s), an ASN.1 encoded binary string
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   148
    '''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   149
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   150
    # Find base-64 encoded data between header and footer.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   151
    header = "-----BEGIN CERTIFICATE-----"
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   152
    footer = "-----END CERTIFICATE-----"
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   153
    endoffset = 0
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   154
    certs = []
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   155
    while True:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   156
        # First find a header.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   157
        startoffset = pemcert.find(header, endoffset)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   158
        if startoffset < 0:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   159
            # No header found, stop search.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   160
            break
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   161
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   162
        startoffset += len(header)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   163
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   164
        # Next find a footer.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   165
        endoffset = pemcert.find(footer, startoffset)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   166
        if endoffset < 0:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   167
            # No footer found.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   168
            raise ValueError("missing PEM certificate footer")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   169
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   170
        # Extract the base-64 encoded certificate and decode it.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   171
        try:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   172
            cert = pemcert[startoffset:endoffset].decode("base-64")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   173
        except:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   174
            # Base-64 decoding error.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   175
            raise ValueError("invalid PEM format certificate")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   176
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   177
        certs.append(cert)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   178
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   179
        endoffset += len(footer)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   180
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   181
    if len(certs) == 0:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   182
        raise ValueError("not a PEM format certificate")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   183
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   184
    # DER certificates are simply raw binary versions
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   185
    # of the base-64 encoded PEM certificates.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   186
    return "".join(certs)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   187
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   188
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   189
##############################################################################
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   190
# Module-level functions which are normally only used by this module
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   191
##############################################################################
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   192
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   193
def convertpkcs8key(tempdir, privkey, passphrase):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   194
    '''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   195
    Convert a PKCS#8-format RSA or DSA private key to an older
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   196
    SSLeay-compatible format.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   197
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   198
    convertpkcs8key(...) -> privkeyout
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   199
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   200
    tempdir     Path to pre-existing temporary directory with read/write access
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   201
    privkey     RSA or DSA private key, a string in PEM (base-64) format
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   202
    passphrase  pass phrase for the private key, a non-Unicode string or None
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   203
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   204
    privkeyout  decrypted private key in PEM (base-64) format
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   205
    '''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   206
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   207
    # Determine PKCS#8 private key type.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   208
    if privkey.find("-----BEGIN PRIVATE KEY-----") >= 0:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   209
        # Unencrypted PKCS#8 private key
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   210
        encryptcmd = "-nocrypt"
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   211
    elif privkey.find("-----BEGIN ENCRYPTED PRIVATE KEY-----") >= 0:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   212
        # Encrypted PKCS#8 private key
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   213
        encryptcmd = ""
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   214
    else:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   215
        # Not a PKCS#8 private key, nothing to do.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   216
        return privkey
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   217
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   218
    keyinfilename = os.path.join(tempdir, "keyin.pem")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   219
    keyoutfilename = os.path.join(tempdir, "keyout.pem")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   220
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   221
    try:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   222
        # Write PEM format private key to file.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   223
        keyinfile = file(keyinfilename, "wb")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   224
        keyinfile.write(privkey)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   225
        keyinfile.close()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   226
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   227
        # Convert a PKCS#8 private key to older SSLeay-compatible format.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   228
        # Keep pass phrase as-is.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   229
        runopenssl("pkcs8 -in %s -out %s -passin stdin -passout stdin %s" %
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   230
                   (quote(keyinfilename), quote(keyoutfilename), encryptcmd),
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   231
                   "%s\n%s\n" % (passphrase, passphrase))
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   232
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   233
        privkey = ""
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   234
        if os.path.isfile(keyoutfilename):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   235
            # Read converted private key back.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   236
            keyoutfile = file(keyoutfilename, "rb")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   237
            privkey = keyoutfile.read()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   238
            keyoutfile.close()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   239
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   240
        if privkey.strip() == "":
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   241
            # OpenSSL did not create output. Probably a wrong pass phrase.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   242
            raise ValueError("wrong pass phrase or invalid PKCS#8 private key")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   243
    finally:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   244
        # Delete temporary files.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   245
        for fname in (keyinfilename, keyoutfilename):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   246
            try:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   247
                os.remove(fname)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   248
            except OSError:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   249
               pass
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   250
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   251
    return privkey
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   252
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   253
def decryptkey(tempdir, privkey, passphrase):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   254
    '''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   255
    decryptkey(...) -> (privkeyout, keytype)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   256
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   257
    tempdir     Path to pre-existing temporary directory with read/write access
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   258
    privkey     RSA or DSA private key, a string in PEM (base-64) format
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   259
    passphrase  pass phrase for the private key, a non-Unicode string or None
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   260
    string      a binary string to sign
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   261
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   262
    keytype     detected key type, string, "RSA" or "DSA"
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   263
    privkeyout  decrypted private key in PEM (base-64) format
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   264
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   265
    NOTE: On platforms with poor file system security, decrypted version
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   266
    of the private key may be grabbed from the temporary directory!
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   267
    '''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   268
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   269
    # Determine private key type.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   270
    if privkey.find("-----BEGIN DSA PRIVATE KEY-----") >= 0:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   271
        keytype = "DSA"
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   272
        convcmd = "dsa"
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   273
    elif privkey.find("-----BEGIN RSA PRIVATE KEY-----") >= 0:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   274
        keytype = "RSA"
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   275
        convcmd = "rsa"
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   276
    else:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   277
        raise ValueError("not an RSA or DSA private key in PEM format")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   278
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   279
    keyinfilename = os.path.join(tempdir, "keyin.pem")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   280
    keyoutfilename = os.path.join(tempdir, "keyout.pem")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   281
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   282
    try:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   283
        # Write PEM format private key to file.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   284
        keyinfile = file(keyinfilename, "wb")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   285
        keyinfile.write(privkey)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   286
        keyinfile.close()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   287
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   288
        # Decrypt the private key. Older versions of OpenSSL do not
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   289
        # accept the "-passin" parameter for the "dgst" command.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   290
        runopenssl("%s -in %s -out %s -passin stdin" %
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   291
                   (convcmd, quote(keyinfilename),
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   292
                    quote(keyoutfilename)), passphrase)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   293
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   294
        privkey = ""
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   295
        if os.path.isfile(keyoutfilename):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   296
            # Read decrypted private key back.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   297
            keyoutfile = file(keyoutfilename, "rb")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   298
            privkey = keyoutfile.read()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   299
            keyoutfile.close()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   300
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   301
        if privkey.strip() == "":
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   302
            # OpenSSL did not create output. Probably a wrong pass phrase.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   303
            raise ValueError("wrong pass phrase or invalid private key")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   304
    finally:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   305
        # Delete temporary files.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   306
        for fname in (keyinfilename, keyoutfilename):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   307
            try:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   308
                os.remove(fname)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   309
            except OSError:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   310
               pass
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   311
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   312
    return (privkey, keytype)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   313
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   314
def mkdtemp(template):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   315
    '''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   316
    Create a unique temporary directory.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   317
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   318
    tempfile.mkdtemp() was introduced in Python v2.3. This is for
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   319
    backward compatibility.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   320
    '''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   321
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   322
    # Cross-platform way to determine a suitable location for temporary files.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   323
    systemp = tempfile.gettempdir()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   324
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   325
    if not template.endswith("XXXXXX"):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   326
        raise ValueError("invalid template for mkdtemp(): %s" % template)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   327
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   328
    for n in xrange(10000):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   329
        randchars = []
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   330
        for m in xrange(6):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   331
            randchars.append(random.choice("abcdefghijklmnopqrstuvwxyz"))
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   332
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   333
        tempdir = os.path.join(systemp, template[: -6]) + "".join(randchars)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   334
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   335
        try:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   336
            os.mkdir(tempdir, 0700)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   337
            return tempdir
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   338
        except OSError:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   339
            pass
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   340
    else:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   341
        # All unique names in use, raise an error.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   342
        raise OSError(errno.EEXIST, os.strerror(errno.EEXIST),
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   343
                      os.path.join(systemp, template))
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   344
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   345
def quote(filename):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   346
    '''Quote a filename if it has spaces in it.'''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   347
    if " " in filename:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   348
        filename = '"%s"' % filename
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   349
    return filename
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   350
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   351
def runopenssl(command, datain = ""):
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   352
    '''Run the OpenSSL command line tool with the given parameters and data.'''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   353
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   354
    global opensslcommand
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   355
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   356
    if opensslcommand == None:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   357
        # Find path to the OpenSSL command.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   358
        findopenssl()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   359
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   360
    # Construct a command line for os.popen3().
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   361
    cmdline = '%s %s' % (opensslcommand, command)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   362
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   363
    if openssldebug:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   364
        # Print command line.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   365
        print "DEBUG: os.popen3(%s)" % repr(cmdline)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   366
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   367
    # Run command. Use os.popen3() to capture stdout and stderr.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   368
    pipein, pipeout, pipeerr = os.popen3(cmdline)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   369
    pipein.write(datain)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   370
    pipein.close()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   371
    dataout = pipeout.read()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   372
    pipeout.close()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   373
    errout = pipeerr.read()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   374
    pipeerr.close()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   375
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   376
    if openssldebug:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   377
        # Print standard error output.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   378
        print "DEBUG: pipeerr.read() = %s" % repr(errout)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   379
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   380
    return (dataout, errout)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   381
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   382
def findopenssl():
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   383
    '''Find the OpenSSL command line tool.'''
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   384
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   385
    global opensslcommand
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   386
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   387
    # Get PATH and split it to a list of paths.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   388
    paths = os.environ["PATH"].split(os.pathsep)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   389
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   390
    # Insert script path in front of others.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   391
    # On Windows, this is where openssl.exe resides by default.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   392
    if sys.path[0] != "":
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   393
        paths.insert(0, sys.path[0])
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   394
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   395
    for path in paths:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   396
        cmd = os.path.join(path, "openssl")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   397
        try:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   398
            # Try to query OpenSSL version.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   399
            pin, pout = os.popen4('"%s" version' % cmd)
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   400
            pin.close()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   401
            verstr = pout.read()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   402
            pout.close()
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   403
        except OSError:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   404
            # Could not run command, skip to the next path candidate.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   405
            continue
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   406
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   407
        if verstr.split()[0] == "OpenSSL":
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   408
            # Command found, stop searching.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   409
            break
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   410
    else:
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   411
        raise IOError("no valid OpenSSL command line tool found in PATH")
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   412
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   413
    # Add quotes around command in case of embedded whitespace on path.
ca70ae20a155 Base Python2.0 code
Vijayan <ts.vijayan@nokia.com>
parents:
diff changeset
   414
    opensslcommand = quote(cmd)