184 lines
5.2 KiB
Python
184 lines
5.2 KiB
Python
# Copyright (C) Jean-Paul Calderone
|
|
# See LICENSE for details.
|
|
|
|
import sys
|
|
|
|
from OpenSSL.crypto import (
|
|
FILETYPE_PEM, TYPE_DSA, Error, PKey, X509, load_privatekey, CRL, Revoked,
|
|
get_elliptic_curves, _X509_REVOKED_dup)
|
|
|
|
from OpenSSL._util import lib as _lib
|
|
|
|
|
|
|
|
class BaseChecker(object):
|
|
def __init__(self, iterations):
|
|
self.iterations = iterations
|
|
|
|
|
|
|
|
class Checker_X509_get_pubkey(BaseChecker):
|
|
"""
|
|
Leak checks for L{X509.get_pubkey}.
|
|
"""
|
|
def check_exception(self):
|
|
"""
|
|
Call the method repeatedly such that it will raise an exception.
|
|
"""
|
|
for i in xrange(self.iterations):
|
|
cert = X509()
|
|
try:
|
|
cert.get_pubkey()
|
|
except Error:
|
|
pass
|
|
|
|
|
|
def check_success(self):
|
|
"""
|
|
Call the method repeatedly such that it will return a PKey object.
|
|
"""
|
|
small = xrange(3)
|
|
for i in xrange(self.iterations):
|
|
key = PKey()
|
|
key.generate_key(TYPE_DSA, 256)
|
|
for i in small:
|
|
cert = X509()
|
|
cert.set_pubkey(key)
|
|
for i in small:
|
|
cert.get_pubkey()
|
|
|
|
|
|
|
|
class Checker_load_privatekey(BaseChecker):
|
|
"""
|
|
Leak checks for :py:obj:`load_privatekey`.
|
|
"""
|
|
ENCRYPTED_PEM = """\
|
|
-----BEGIN RSA PRIVATE KEY-----
|
|
Proc-Type: 4,ENCRYPTED
|
|
DEK-Info: BF-CBC,3763C340F9B5A1D0
|
|
|
|
a/DO10mLjHLCAOG8/Hc5Lbuh3pfjvcTZiCexShP+tupkp0VxW2YbZjML8uoXrpA6
|
|
fSPUo7cEC+r96GjV03ZIVhjmsxxesdWMpfkzXRpG8rUbWEW2KcCJWdSX8bEkuNW3
|
|
uvAXdXZwiOrm56ANDo/48gj27GcLwnlA8ld39+ylAzkUJ1tcMVzzTjfcyd6BMFpR
|
|
Yjg23ikseug6iWEsZQormdl0ITdYzmFpM+YYsG7kmmmi4UjCEYfb9zFaqJn+WZT2
|
|
qXxmo2ZPFzmEVkuB46mf5GCqMwLRN2QTbIZX2+Dljj1Hfo5erf5jROewE/yzcTwO
|
|
FCB5K3c2kkTv2KjcCAimjxkE+SBKfHg35W0wB0AWkXpVFO5W/TbHg4tqtkpt/KMn
|
|
/MPnSxvYr/vEqYMfW4Y83c45iqK0Cyr2pwY60lcn8Kk=
|
|
-----END RSA PRIVATE KEY-----
|
|
"""
|
|
def check_load_privatekey_callback(self):
|
|
"""
|
|
Call the function with an encrypted PEM and a passphrase callback.
|
|
"""
|
|
for i in xrange(self.iterations * 10):
|
|
load_privatekey(
|
|
FILETYPE_PEM, self.ENCRYPTED_PEM, lambda *args: "hello, secret")
|
|
|
|
|
|
def check_load_privatekey_callback_incorrect(self):
|
|
"""
|
|
Call the function with an encrypted PEM and a passphrase callback which
|
|
returns the wrong passphrase.
|
|
"""
|
|
for i in xrange(self.iterations * 10):
|
|
try:
|
|
load_privatekey(
|
|
FILETYPE_PEM, self.ENCRYPTED_PEM,
|
|
lambda *args: "hello, public")
|
|
except Error:
|
|
pass
|
|
|
|
|
|
def check_load_privatekey_callback_wrong_type(self):
|
|
"""
|
|
Call the function with an encrypted PEM and a passphrase callback which
|
|
returns a non-string.
|
|
"""
|
|
for i in xrange(self.iterations * 10):
|
|
try:
|
|
load_privatekey(
|
|
FILETYPE_PEM, self.ENCRYPTED_PEM,
|
|
lambda *args: {})
|
|
except ValueError:
|
|
pass
|
|
|
|
|
|
|
|
class Checker_CRL(BaseChecker):
|
|
"""
|
|
Leak checks for L{CRL.add_revoked} and L{CRL.get_revoked}.
|
|
"""
|
|
def check_add_revoked(self):
|
|
"""
|
|
Call the add_revoked method repeatedly on an empty CRL.
|
|
"""
|
|
for i in xrange(self.iterations * 200):
|
|
CRL().add_revoked(Revoked())
|
|
|
|
|
|
def check_get_revoked(self):
|
|
"""
|
|
Create a CRL object with 100 Revoked objects, then call the
|
|
get_revoked method repeatedly.
|
|
"""
|
|
crl = CRL()
|
|
for i in xrange(100):
|
|
crl.add_revoked(Revoked())
|
|
for i in xrange(self.iterations):
|
|
crl.get_revoked()
|
|
|
|
|
|
|
|
class Checker_X509_REVOKED_dup(BaseChecker):
|
|
"""
|
|
Leak checks for :py:obj:`_X509_REVOKED_dup`.
|
|
"""
|
|
def check_X509_REVOKED_dup(self):
|
|
"""
|
|
Copy an empty Revoked object repeatedly. The copy is not garbage
|
|
collected, therefore it needs to be manually freed.
|
|
"""
|
|
for i in xrange(self.iterations * 100):
|
|
revoked_copy = _X509_REVOKED_dup(Revoked()._revoked)
|
|
_lib.X509_REVOKED_free(revoked_copy)
|
|
|
|
|
|
|
|
class Checker_EllipticCurve(BaseChecker):
|
|
"""
|
|
Leak checks for :py:obj:`_EllipticCurve`.
|
|
"""
|
|
def check_to_EC_KEY(self):
|
|
"""
|
|
Repeatedly create an EC_KEY* from an :py:obj:`_EllipticCurve`. The
|
|
structure should be automatically garbage collected.
|
|
"""
|
|
curves = get_elliptic_curves()
|
|
if curves:
|
|
curve = next(iter(curves))
|
|
for i in xrange(self.iterations * 1000):
|
|
curve._to_EC_KEY()
|
|
|
|
|
|
def vmsize():
|
|
return [x for x in file('/proc/self/status').readlines() if 'VmSize' in x]
|
|
|
|
|
|
def main(iterations='1000'):
|
|
iterations = int(iterations)
|
|
for klass in globals():
|
|
if klass.startswith('Checker_'):
|
|
klass = globals()[klass]
|
|
print klass
|
|
checker = klass(iterations)
|
|
for meth in dir(checker):
|
|
if meth.startswith('check_'):
|
|
print '\t', meth, vmsize(), '...',
|
|
getattr(checker, meth)()
|
|
print vmsize()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main(*sys.argv[1:])
|