blob: f5fe2f840ce57af5ffd3c5c2606f2277918fa3b4 [file] [log] [blame]
Jean-Paul Calderonec7b3c892011-03-02 19:40:02 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
3
Jean-Paul Calderone19555b92008-02-19 22:29:57 -05004import sys
5
Jean-Paul Calderone8e37f762011-09-14 10:00:50 -04006from OpenSSL.crypto import (
Jonathan Giannuzzi54c42002014-03-24 01:33:08 +01007 FILETYPE_PEM, TYPE_DSA, Error, PKey, X509, load_privatekey, CRL, Revoked,
8 _X509_REVOKED_dup)
9
10from OpenSSL._util import lib as _lib
Jean-Paul Calderone19555b92008-02-19 22:29:57 -050011
Jean-Paul Calderone8e37f762011-09-14 10:00:50 -040012
13
14class BaseChecker(object):
Jean-Paul Calderone19555b92008-02-19 22:29:57 -050015 def __init__(self, iterations):
16 self.iterations = iterations
17
18
Jean-Paul Calderone8e37f762011-09-14 10:00:50 -040019
20class Checker_X509_get_pubkey(BaseChecker):
21 """
22 Leak checks for L{X509.get_pubkey}.
23 """
Jean-Paul Calderone19555b92008-02-19 22:29:57 -050024 def check_exception(self):
25 """
26 Call the method repeatedly such that it will raise an exception.
27 """
28 for i in xrange(self.iterations):
29 cert = X509()
30 try:
31 cert.get_pubkey()
32 except Error:
33 pass
34
35
36 def check_success(self):
37 """
38 Call the method repeatedly such that it will return a PKey object.
39 """
40 small = xrange(3)
41 for i in xrange(self.iterations):
42 key = PKey()
43 key.generate_key(TYPE_DSA, 256)
44 for i in small:
45 cert = X509()
46 cert.set_pubkey(key)
47 for i in small:
48 cert.get_pubkey()
49
50
Jean-Paul Calderone8e37f762011-09-14 10:00:50 -040051
52class Checker_load_privatekey(BaseChecker):
53 """
54 Leak checks for :py:obj:`load_privatekey`.
55 """
56 ENCRYPTED_PEM = """\
57-----BEGIN RSA PRIVATE KEY-----
58Proc-Type: 4,ENCRYPTED
59DEK-Info: BF-CBC,3763C340F9B5A1D0
60
61a/DO10mLjHLCAOG8/Hc5Lbuh3pfjvcTZiCexShP+tupkp0VxW2YbZjML8uoXrpA6
62fSPUo7cEC+r96GjV03ZIVhjmsxxesdWMpfkzXRpG8rUbWEW2KcCJWdSX8bEkuNW3
63uvAXdXZwiOrm56ANDo/48gj27GcLwnlA8ld39+ylAzkUJ1tcMVzzTjfcyd6BMFpR
64Yjg23ikseug6iWEsZQormdl0ITdYzmFpM+YYsG7kmmmi4UjCEYfb9zFaqJn+WZT2
65qXxmo2ZPFzmEVkuB46mf5GCqMwLRN2QTbIZX2+Dljj1Hfo5erf5jROewE/yzcTwO
66FCB5K3c2kkTv2KjcCAimjxkE+SBKfHg35W0wB0AWkXpVFO5W/TbHg4tqtkpt/KMn
67/MPnSxvYr/vEqYMfW4Y83c45iqK0Cyr2pwY60lcn8Kk=
68-----END RSA PRIVATE KEY-----
69"""
70 def check_load_privatekey_callback(self):
71 """
72 Call the function with an encrypted PEM and a passphrase callback.
73 """
74 for i in xrange(self.iterations * 10):
75 load_privatekey(
76 FILETYPE_PEM, self.ENCRYPTED_PEM, lambda *args: "hello, secret")
77
78
79 def check_load_privatekey_callback_incorrect(self):
80 """
81 Call the function with an encrypted PEM and a passphrase callback which
82 returns the wrong passphrase.
83 """
84 for i in xrange(self.iterations * 10):
85 try:
86 load_privatekey(
87 FILETYPE_PEM, self.ENCRYPTED_PEM,
88 lambda *args: "hello, public")
89 except Error:
90 pass
91
92
93 def check_load_privatekey_callback_wrong_type(self):
94 """
95 Call the function with an encrypted PEM and a passphrase callback which
96 returns a non-string.
97 """
98 for i in xrange(self.iterations * 10):
99 try:
100 load_privatekey(
101 FILETYPE_PEM, self.ENCRYPTED_PEM,
102 lambda *args: {})
Jean-Paul Calderone2a864f12011-09-14 11:10:29 -0400103 except ValueError:
Jean-Paul Calderone8e37f762011-09-14 10:00:50 -0400104 pass
105
106
Jonathan Giannuzzi99eff822014-03-23 22:48:41 +0100107
Jonathan Giannuzzi8e6a64e2014-03-24 01:32:58 +0100108class Checker_CRL(BaseChecker):
Jonathan Giannuzzi99eff822014-03-23 22:48:41 +0100109 """
Jonathan Giannuzzi8e6a64e2014-03-24 01:32:58 +0100110 Leak checks for L{CRL.add_revoked} and L{CRL.get_revoked}.
Jonathan Giannuzzi99eff822014-03-23 22:48:41 +0100111 """
Jonathan Giannuzzi8e6a64e2014-03-24 01:32:58 +0100112 def check_add_revoked(self):
113 """
114 Call the add_revoked method repeatedly on an empty CRL.
115 """
116 for i in xrange(self.iterations * 200):
117 CRL().add_revoked(Revoked())
118
119
Jonathan Giannuzzi99eff822014-03-23 22:48:41 +0100120 def check_get_revoked(self):
121 """
Jonathan Giannuzzi3b97ec12014-03-24 00:47:06 +0100122 Create a CRL object with 100 Revoked objects, then call the
Jonathan Giannuzzi99eff822014-03-23 22:48:41 +0100123 get_revoked method repeatedly.
124 """
125 crl = CRL()
Jonathan Giannuzzi3b97ec12014-03-24 00:47:06 +0100126 for i in xrange(100):
127 crl.add_revoked(Revoked())
Jonathan Giannuzzi99eff822014-03-23 22:48:41 +0100128 for i in xrange(self.iterations):
129 crl.get_revoked()
130
131
132
Jonathan Giannuzzi54c42002014-03-24 01:33:08 +0100133class Checker_X509_REVOKED_dup(BaseChecker):
134 """
135 Leak checks for :py:obj:`_X509_REVOKED_dup`.
136 """
137 def check_X509_REVOKED_dup(self):
138 """
139 Copy an empty Revoked object repeatedly. The copy is not garbage
140 collected, therefore it needs to be manually freed.
141 """
142 for i in xrange(self.iterations * 100):
143 revoked_copy = _X509_REVOKED_dup(Revoked()._revoked)
144 _lib.X509_REVOKED_free(revoked_copy)
145
146
147
Jean-Paul Calderone19555b92008-02-19 22:29:57 -0500148def vmsize():
149 return [x for x in file('/proc/self/status').readlines() if 'VmSize' in x]
150
151
152def main(iterations='1000'):
153 iterations = int(iterations)
154 for klass in globals():
155 if klass.startswith('Checker_'):
156 klass = globals()[klass]
157 print klass
158 checker = klass(iterations)
159 for meth in dir(checker):
160 if meth.startswith('check_'):
161 print '\t', meth, vmsize(), '...',
162 getattr(checker, meth)()
163 print vmsize()
164
165
166if __name__ == '__main__':
167 main(*sys.argv[1:])