blob: 797dfdc39c164009c75eef057442b8a3a3ea0a3b [file] [log] [blame]
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001import datetime
Paul Kehrer8d887e12015-10-24 09:09:55 -05002
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003from base64 import b16encode
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05004from functools import partial
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05005from operator import __eq__, __ne__, __lt__, __le__, __gt__, __ge__
Jean-Paul Calderone60432792015-04-13 12:26:07 -04006from warnings import warn as _warn
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05007
8from six import (
9 integer_types as _integer_types,
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -040010 text_type as _text_type,
11 PY3 as _PY3)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080012
Paul Kehrer72d968b2016-07-29 15:31:04 +080013from cryptography.hazmat.backends.openssl.backend import backend
14from cryptography.hazmat.primitives.asymmetric import dsa, rsa
15
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050016from OpenSSL._util import (
17 ffi as _ffi,
18 lib as _lib,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050019 exception_from_error_queue as _exception_from_error_queue,
20 byte_string as _byte_string,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040021 native as _native,
22 UNSPECIFIED as _UNSPECIFIED,
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -040023 text_to_bytes_and_warn as _text_to_bytes_and_warn,
Alex Gaynor67903a62016-06-02 10:37:13 -070024 make_assert as _make_assert,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040025)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080026
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050027FILETYPE_PEM = _lib.SSL_FILETYPE_PEM
28FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080029
30# TODO This was an API mistake. OpenSSL has no such constant.
31FILETYPE_TEXT = 2 ** 16 - 1
32
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050033TYPE_RSA = _lib.EVP_PKEY_RSA
34TYPE_DSA = _lib.EVP_PKEY_DSA
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -080035
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080036
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050037class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050038 """
39 An error occurred in an `OpenSSL.crypto` API.
40 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050041
42
43_raise_current_error = partial(_exception_from_error_queue, Error)
Alex Gaynor67903a62016-06-02 10:37:13 -070044_openssl_assert = _make_assert(Error)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050045
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070046
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050047def _untested_error(where):
48 """
49 An OpenSSL API failed somehow. Additionally, the failure which was
50 encountered isn't one that's exercised by the test suite so future behavior
51 of pyOpenSSL is now somewhat less predictable.
52 """
53 raise RuntimeError("Unknown %s failure" % (where,))
54
55
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050056def _new_mem_buf(buffer=None):
57 """
58 Allocate a new OpenSSL memory BIO.
59
60 Arrange for the garbage collector to clean it up automatically.
61
62 :param buffer: None or some bytes to use to put into the BIO so that they
63 can be read out.
64 """
65 if buffer is None:
66 bio = _lib.BIO_new(_lib.BIO_s_mem())
67 free = _lib.BIO_free
68 else:
69 data = _ffi.new("char[]", buffer)
70 bio = _lib.BIO_new_mem_buf(data, len(buffer))
Alex Gaynor5945ea82015-09-05 14:59:06 -040071
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050072 # Keep the memory alive as long as the bio is alive!
73 def free(bio, ref=data):
74 return _lib.BIO_free(bio)
75
Alex Gaynorfb8a2a12016-06-04 18:26:26 -070076 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050077
78 bio = _ffi.gc(bio, free)
79 return bio
80
81
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080082def _bio_to_string(bio):
83 """
84 Copy the contents of an OpenSSL BIO object into a Python byte string.
85 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050086 result_buffer = _ffi.new('char**')
87 buffer_length = _lib.BIO_get_mem_data(bio, result_buffer)
88 return _ffi.buffer(result_buffer[0], buffer_length)[:]
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080089
90
Jean-Paul Calderone57122982013-02-21 08:47:05 -080091def _set_asn1_time(boundary, when):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -050092 """
93 The the time value of an ASN1 time object.
94
95 @param boundary: An ASN1_GENERALIZEDTIME pointer (or an object safely
96 castable to that type) which will have its value set.
97 @param when: A string representation of the desired time value.
98
99 @raise TypeError: If C{when} is not a L{bytes} string.
100 @raise ValueError: If C{when} does not represent a time in the required
101 format.
102 @raise RuntimeError: If the time value cannot be set for some other
103 (unspecified) reason.
104 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800105 if not isinstance(when, bytes):
106 raise TypeError("when must be a byte string")
107
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500108 set_result = _lib.ASN1_GENERALIZEDTIME_set_string(
109 _ffi.cast('ASN1_GENERALIZEDTIME*', boundary), when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800110 if set_result == 0:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500111 dummy = _ffi.gc(_lib.ASN1_STRING_new(), _lib.ASN1_STRING_free)
112 _lib.ASN1_STRING_set(dummy, when, len(when))
113 check_result = _lib.ASN1_GENERALIZEDTIME_check(
114 _ffi.cast('ASN1_GENERALIZEDTIME*', dummy))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800115 if not check_result:
116 raise ValueError("Invalid string")
117 else:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500118 _untested_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800119
Alex Gaynor510293e2016-06-02 12:07:59 -0700120
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800121def _get_asn1_time(timestamp):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500122 """
123 Retrieve the time value of an ASN1 time object.
124
125 @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to
126 that type) from which the time value will be retrieved.
127
128 @return: The time value from C{timestamp} as a L{bytes} string in a certain
129 format. Or C{None} if the object contains no time value.
130 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500131 string_timestamp = _ffi.cast('ASN1_STRING*', timestamp)
132 if _lib.ASN1_STRING_length(string_timestamp) == 0:
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800133 return None
Alex Gaynor5945ea82015-09-05 14:59:06 -0400134 elif (
135 _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME
136 ):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500137 return _ffi.string(_lib.ASN1_STRING_data(string_timestamp))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800138 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500139 generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**")
140 _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp)
141 if generalized_timestamp[0] == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500142 # This may happen:
143 # - if timestamp was not an ASN1_TIME
144 # - if allocating memory for the ASN1_GENERALIZEDTIME failed
145 # - if a copy of the time data from timestamp cannot be made for
146 # the newly allocated ASN1_GENERALIZEDTIME
147 #
148 # These are difficult to test. cffi enforces the ASN1_TIME type.
149 # Memory allocation failures are a pain to trigger
150 # deterministically.
151 _untested_error("ASN1_TIME_to_generalizedtime")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800152 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500153 string_timestamp = _ffi.cast(
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800154 "ASN1_STRING*", generalized_timestamp[0])
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500155 string_data = _lib.ASN1_STRING_data(string_timestamp)
156 string_result = _ffi.string(string_data)
157 _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0])
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800158 return string_result
159
160
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800161class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200162 """
163 A class representing an DSA or RSA public key or key pair.
164 """
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800165 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800166 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800167
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800168 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500169 pkey = _lib.EVP_PKEY_new()
170 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800171 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800172
Paul Kehrer72d968b2016-07-29 15:31:04 +0800173 def to_cryptography_key(self):
174 """
175 Export as a ``cryptography`` key.
176
177 :rtype: One of ``cryptography``'s `key interfaces`_.
178
179 .. _key interfaces: https://cryptography.io/en/latest/hazmat/\
180 primitives/asymmetric/rsa/#key-interfaces
181
182 .. versionadded:: 16.1.0
183 """
184 if self._only_public:
185 return backend._evp_pkey_to_public_key(self._pkey)
186 else:
187 return backend._evp_pkey_to_private_key(self._pkey)
188
189 @classmethod
190 def from_cryptography_key(cls, crypto_key):
191 """
192 Construct based on a ``cryptography`` *crypto_key*.
193
194 :param crypto_key: A ``cryptography`` key.
195 :type crypto_key: One of ``cryptography``'s `key interfaces`_.
196
197 :rtype: PKey
198
199 .. versionadded:: 16.1.0
200 """
201 pkey = cls()
202 if not isinstance(crypto_key, (rsa.RSAPublicKey, rsa.RSAPrivateKey,
203 dsa.DSAPublicKey, dsa.DSAPrivateKey)):
204 raise TypeError("Unsupported key type")
205
206 pkey._pkey = crypto_key._evp_pkey
207 if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)):
208 pkey._only_public = True
209 pkey._initialized = True
210 return pkey
211
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800212 def generate_key(self, type, bits):
213 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700214 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800215
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200216 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800217
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200218 :param type: The key type.
219 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
220 :param bits: The number of bits.
221 :type bits: :py:data:`int` ``>= 0``
222 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
223 of the appropriate type.
224 :raises ValueError: If the number of bits isn't an integer of
225 the appropriate size.
Dan Sully44e767a2016-06-04 18:05:27 -0700226 :return: ``None``
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800227 """
228 if not isinstance(type, int):
229 raise TypeError("type must be an integer")
230
231 if not isinstance(bits, int):
232 raise TypeError("bits must be an integer")
233
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800234 # TODO Check error return
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500235 exponent = _lib.BN_new()
236 exponent = _ffi.gc(exponent, _lib.BN_free)
237 _lib.BN_set_word(exponent, _lib.RSA_F4)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800238
239 if type == TYPE_RSA:
240 if bits <= 0:
241 raise ValueError("Invalid number of bits")
242
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500243 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800244
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500245 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400246 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800247
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500248 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400249 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800250
251 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400252 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700253 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400254
255 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400256 res = _lib.DSA_generate_parameters_ex(
257 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
258 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700259 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400260
261 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
262 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800263 else:
264 raise Error("No such key type")
265
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800266 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800267
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800268 def check(self):
269 """
270 Check the consistency of an RSA private key.
271
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200272 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
273
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800274 :return: True if key is consistent.
275 :raise Error: if the key is inconsistent.
276 :raise TypeError: if the key is of a type which cannot be checked.
277 Only RSA keys can currently be checked.
278 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800279 if self._only_public:
280 raise TypeError("public key only")
281
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100282 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800283 raise TypeError("key type unsupported")
284
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500285 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
286 rsa = _ffi.gc(rsa, _lib.RSA_free)
287 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800288 if result:
289 return True
290 _raise_current_error()
291
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800292 def type(self):
293 """
294 Returns the type of the key
295
296 :return: The type of the key.
297 """
Alex Gaynorc84567b2016-03-16 07:45:09 -0400298 return _lib.Cryptography_EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800299
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800300 def bits(self):
301 """
302 Returns the number of bits of the key
303
304 :return: The number of bits of the key.
305 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500306 return _lib.EVP_PKEY_bits(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800307PKeyType = PKey
308
309
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400310class _EllipticCurve(object):
311 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400312 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400313
314 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
315 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
316 instances each of which represents one curve supported by the system.
317 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400318 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400319 _curves = None
320
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400321 if _PY3:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400322 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400323 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400324 """
325 Implement cooperation with the right-hand side argument of ``!=``.
326
327 Python 3 seems to have dropped this cooperation in this very narrow
328 circumstance.
329 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400330 if isinstance(other, _EllipticCurve):
331 return super(_EllipticCurve, self).__ne__(other)
332 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400333
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400334 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400335 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400336 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400337 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400338
339 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400340
341 :return: A :py:type:`set` of ``cls`` instances giving the names of the
342 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400343 """
344 if lib.Cryptography_HAS_EC:
345 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
346 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
Alex Gaynor5945ea82015-09-05 14:59:06 -0400347 # The return value on this call should be num_curves again. We
348 # could check it to make sure but if it *isn't* then.. what could
349 # we do? Abort the whole process, I suppose...? -exarkun
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400350 lib.EC_get_builtin_curves(builtin_curves, num_curves)
351 return set(
352 cls.from_nid(lib, c.nid)
353 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400354 return set()
355
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400356 @classmethod
357 def _get_elliptic_curves(cls, lib):
358 """
359 Get, cache, and return the curves supported by OpenSSL.
360
361 :param lib: The OpenSSL library binding object.
362
363 :return: A :py:type:`set` of ``cls`` instances giving the names of the
364 elliptic curves the underlying library supports.
365 """
366 if cls._curves is None:
367 cls._curves = cls._load_elliptic_curves(lib)
368 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400369
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400370 @classmethod
371 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400372 """
373 Instantiate a new :py:class:`_EllipticCurve` associated with the given
374 OpenSSL NID.
375
376 :param lib: The OpenSSL library binding object.
377
378 :param nid: The OpenSSL NID the resulting curve object will represent.
379 This must be a curve NID (and not, for example, a hash NID) or
380 subsequent operations will fail in unpredictable ways.
381 :type nid: :py:class:`int`
382
383 :return: The curve object.
384 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400385 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
386
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400387 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400388 """
389 :param _lib: The :py:mod:`cryptography` binding instance used to
390 interface with OpenSSL.
391
392 :param _nid: The OpenSSL NID identifying the curve this object
393 represents.
394 :type _nid: :py:class:`int`
395
396 :param name: The OpenSSL short name identifying the curve this object
397 represents.
398 :type name: :py:class:`unicode`
399 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400400 self._lib = lib
401 self._nid = nid
402 self.name = name
403
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400404 def __repr__(self):
405 return "<Curve %r>" % (self.name,)
406
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400407 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400408 """
409 Create a new OpenSSL EC_KEY structure initialized to use this curve.
410
411 The structure is automatically garbage collected when the Python object
412 is garbage collected.
413 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400414 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
415 return _ffi.gc(key, _lib.EC_KEY_free)
416
417
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400418def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400419 """
420 Return a set of objects representing the elliptic curves supported in the
421 OpenSSL build in use.
422
423 The curve objects have a :py:class:`unicode` ``name`` attribute by which
424 they identify themselves.
425
426 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400427 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
428 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400429 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400430 return _EllipticCurve._get_elliptic_curves(_lib)
431
432
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400433def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400434 """
435 Return a single curve object selected by name.
436
437 See :py:func:`get_elliptic_curves` for information about curve objects.
438
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400439 :param name: The OpenSSL short name identifying the curve object to
440 retrieve.
441 :type name: :py:class:`unicode`
442
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400443 If the named curve is not supported then :py:class:`ValueError` is raised.
444 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400445 for curve in get_elliptic_curves():
446 if curve.name == name:
447 return curve
448 raise ValueError("unknown curve name", name)
449
450
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800451class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200452 """
453 An X.509 Distinguished Name.
454
455 :ivar countryName: The country of the entity.
456 :ivar C: Alias for :py:attr:`countryName`.
457
458 :ivar stateOrProvinceName: The state or province of the entity.
459 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
460
461 :ivar localityName: The locality of the entity.
462 :ivar L: Alias for :py:attr:`localityName`.
463
464 :ivar organizationName: The organization name of the entity.
465 :ivar O: Alias for :py:attr:`organizationName`.
466
467 :ivar organizationalUnitName: The organizational unit of the entity.
468 :ivar OU: Alias for :py:attr:`organizationalUnitName`
469
470 :ivar commonName: The common name of the entity.
471 :ivar CN: Alias for :py:attr:`commonName`.
472
473 :ivar emailAddress: The e-mail address of the entity.
474 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400475
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800476 def __init__(self, name):
477 """
478 Create a new X509Name, copying the given X509Name instance.
479
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200480 :param name: The name to copy.
481 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800482 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500483 name = _lib.X509_NAME_dup(name._name)
484 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800485
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800486 def __setattr__(self, name, value):
487 if name.startswith('_'):
488 return super(X509Name, self).__setattr__(name, value)
489
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800490 # Note: we really do not want str subclasses here, so we do not use
491 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800492 if type(name) is not str:
493 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400494 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800495
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500496 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500497 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800498 try:
499 _raise_current_error()
500 except Error:
501 pass
502 raise AttributeError("No such attribute")
503
504 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500505 for i in range(_lib.X509_NAME_entry_count(self._name)):
506 ent = _lib.X509_NAME_get_entry(self._name, i)
507 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
508 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800509 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500510 ent = _lib.X509_NAME_delete_entry(self._name, i)
511 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800512 break
513
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500514 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800515 value = value.encode('utf-8')
516
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500517 add_result = _lib.X509_NAME_add_entry_by_NID(
518 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800519 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500520 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800521
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800522 def __getattr__(self, name):
523 """
524 Find attribute. An X509Name object has the following attributes:
525 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400526 organization (alias O), organizationalUnit (alias OU), commonName
527 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800528 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500529 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500530 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800531 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
532 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
533 # push something onto the error queue. If we don't clean that up
534 # now, someone else will bump into it later and be quite confused.
535 # See lp#314814.
536 try:
537 _raise_current_error()
538 except Error:
539 pass
540 return super(X509Name, self).__getattr__(name)
541
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500542 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800543 if entry_index == -1:
544 return None
545
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500546 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
547 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800548
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500549 result_buffer = _ffi.new("unsigned char**")
550 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400551 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800552
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700553 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400554 result = _ffi.buffer(
555 result_buffer[0], data_length
556 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700557 finally:
558 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500559 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800560 return result
561
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500562 def _cmp(op):
563 def f(self, other):
564 if not isinstance(other, X509Name):
565 return NotImplemented
566 result = _lib.X509_NAME_cmp(self._name, other._name)
567 return op(result, 0)
568 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800569
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500570 __eq__ = _cmp(__eq__)
571 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800572
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500573 __lt__ = _cmp(__lt__)
574 __le__ = _cmp(__le__)
575
576 __gt__ = _cmp(__gt__)
577 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800578
579 def __repr__(self):
580 """
581 String representation of an X509Name
582 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400583 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500584 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800585 self._name, result_buffer, len(result_buffer))
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700586 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800587
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500588 return "<X509Name object '%s'>" % (
589 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800590
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800591 def hash(self):
592 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200593 Return an integer representation of the first four bytes of the
594 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800595
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200596 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
597
598 :return: The (integer) hash of this name.
599 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800600 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500601 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800602
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800603 def der(self):
604 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200605 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800606
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200607 :return: The DER encoded form of this name.
608 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800609 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500610 result_buffer = _ffi.new('unsigned char**')
611 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400612 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800613
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500614 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
615 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800616 return string_result
617
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800618 def get_components(self):
619 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200620 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800621
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200622 :return: The components of this name.
623 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800624 """
625 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500626 for i in range(_lib.X509_NAME_entry_count(self._name)):
627 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800628
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500629 fname = _lib.X509_NAME_ENTRY_get_object(ent)
630 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800631
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500632 nid = _lib.OBJ_obj2nid(fname)
633 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800634
635 result.append((
Alex Gaynora738ed52015-09-05 11:17:10 -0400636 _ffi.string(name),
637 _ffi.string(
638 _lib.ASN1_STRING_data(fval),
639 _lib.ASN1_STRING_length(fval))))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800640
641 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200642
643
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800644X509NameType = X509Name
645
646
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800647class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200648 """
649 An X.509 v3 certificate extension.
650 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400651
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800652 def __init__(self, type_name, critical, value, subject=None, issuer=None):
653 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200654 Initializes an X509 extension.
655
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100656 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400657 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800658
Alex Gaynor5945ea82015-09-05 14:59:06 -0400659 :param bool critical: A flag indicating whether this is a critical
660 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800661
662 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200663 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800664
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200665 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800666 :type subject: :py:class:`X509`
667
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200668 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800669 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100670
671 .. _extension: https://openssl.org/docs/manmaster/apps/
672 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800673 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500674 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800675
Alex Gaynor5945ea82015-09-05 14:59:06 -0400676 # A context is necessary for any extension which uses the r2i
677 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
678 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500679 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800680
681 # We have no configuration database - but perhaps we should (some
682 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500683 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800684
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800685 # Initialize the subject and issuer, if appropriate. ctx is a local,
686 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400687 # any references, so no need to mess with reference counts or
688 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800689 if issuer is not None:
690 if not isinstance(issuer, X509):
691 raise TypeError("issuer must be an X509 instance")
692 ctx.issuer_cert = issuer._x509
693 if subject is not None:
694 if not isinstance(subject, X509):
695 raise TypeError("subject must be an X509 instance")
696 ctx.subject_cert = subject._x509
697
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800698 if critical:
699 # There are other OpenSSL APIs which would let us pass in critical
700 # separately, but they're harder to use, and since value is already
701 # a pile of crappy junk smuggling a ton of utterly important
702 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400703 # with strings? (However, X509V3_EXT_i2d in particular seems like
704 # it would be a better API to invoke. I do not know where to get
705 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500706 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800707
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500708 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
709 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800710 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500711 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800712
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400713 @property
714 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400715 return _lib.OBJ_obj2nid(
716 _lib.X509_EXTENSION_get_object(self._extension)
717 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400718
719 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500720 _lib.GEN_EMAIL: "email",
721 _lib.GEN_DNS: "DNS",
722 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400723 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400724
725 def _subjectAltNameString(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500726 method = _lib.X509V3_EXT_get(self._extension)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700727 _openssl_assert(method != _ffi.NULL)
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400728 ext_data = _lib.X509_EXTENSION_get_data(self._extension)
729 payload = ext_data.data
730 length = ext_data.length
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400731
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500732 payloadptr = _ffi.new("unsigned char**")
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400733 payloadptr[0] = payload
734
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500735 if method.it != _ffi.NULL:
736 ptr = _lib.ASN1_ITEM_ptr(method.it)
737 data = _lib.ASN1_item_d2i(_ffi.NULL, payloadptr, length, ptr)
738 names = _ffi.cast("GENERAL_NAMES*", data)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400739 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500740 names = _ffi.cast(
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400741 "GENERAL_NAMES*",
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500742 method.d2i(_ffi.NULL, payloadptr, length))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400743
Paul Kehrerb7d79502015-05-04 07:43:51 -0500744 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400745 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500746 for i in range(_lib.sk_GENERAL_NAME_num(names)):
747 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400748 try:
749 label = self._prefixes[name.type]
750 except KeyError:
751 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500752 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500753 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400754 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500755 value = _native(
756 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
757 parts.append(label + ":" + value)
758 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400759
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800760 def __str__(self):
761 """
762 :return: a nice text representation of the extension
763 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500764 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400765 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800766
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400767 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500768 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400769 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800770
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500771 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800772
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800773 def get_critical(self):
774 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200775 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800776
777 :return: The critical field.
778 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500779 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800780
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800781 def get_short_name(self):
782 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200783 Returns the short type name of this X.509 extension.
784
785 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800786
787 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200788 :rtype: :py:data:`bytes`
789
790 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800791 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500792 obj = _lib.X509_EXTENSION_get_object(self._extension)
793 nid = _lib.OBJ_obj2nid(obj)
794 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800795
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800796 def get_data(self):
797 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200798 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800799
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200800 :return: The ASN.1 encoded data of this X509 extension.
801 :rtype: :py:data:`bytes`
802
803 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800804 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500805 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
806 string_result = _ffi.cast('ASN1_STRING*', octet_result)
807 char_result = _lib.ASN1_STRING_data(string_result)
808 result_length = _lib.ASN1_STRING_length(string_result)
809 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800810
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200811
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800812X509ExtensionType = X509Extension
813
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800814
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800815class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200816 """
817 An X.509 certificate signing requests.
818 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400819
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800820 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500821 req = _lib.X509_REQ_new()
822 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Alex Gaynor5af32d02016-09-24 01:52:21 -0400823 # Default to version 0.
824 self.set_version(0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800825
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800826 def set_pubkey(self, pkey):
827 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200828 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800829
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200830 :param pkey: The public key to use.
831 :type pkey: :py:class:`PKey`
832
Dan Sully44e767a2016-06-04 18:05:27 -0700833 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800834 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500835 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400836 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800837
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800838 def get_pubkey(self):
839 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200840 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800841
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200842 :return: The public key.
843 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800844 """
845 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500846 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700847 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500848 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800849 pkey._only_public = True
850 return pkey
851
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800852 def set_version(self, version):
853 """
854 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
855 request.
856
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200857 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700858 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800859 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500860 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400861 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800862
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800863 def get_version(self):
864 """
865 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
866 request.
867
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200868 :return: The value of the version subfield.
869 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800870 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500871 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800872
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800873 def get_subject(self):
874 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200875 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800876
Cory Benfield881dc8d2015-12-09 08:25:14 +0000877 This creates a new :class:`X509Name` that wraps the underlying subject
878 name field on the certificate signing request. Modifying it will modify
879 the underlying signing request, and will have the effect of modifying
880 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200881
882 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000883 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800884 """
885 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500886 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700887 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800888
889 # The name is owned by the X509Req structure. As long as the X509Name
890 # Python object is alive, keep the X509Req Python object alive.
891 name._owner = self
892
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800893 return name
894
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800895 def add_extensions(self, extensions):
896 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200897 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800898
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200899 :param extensions: The X.509 extensions to add.
900 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700901 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800902 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500903 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700904 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800905
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500906 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800907
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800908 for ext in extensions:
909 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -0800910 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800911
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800912 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500913 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800914
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500915 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400916 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800917
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800918 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800919 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200920 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800921
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200922 :return: The X.509 extensions in this request.
923 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
924
925 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800926 """
927 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500928 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -0500929 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800930 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500931 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800932 exts.append(ext)
933 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800934
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800935 def sign(self, pkey, digest):
936 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -0700937 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800938
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200939 :param pkey: The key pair to sign with.
940 :type pkey: :py:class:`PKey`
941 :param digest: The name of the message digest to use for the signature,
Alex Gaynor239e2d32016-09-11 12:36:35 -0400942 e.g. :py:data:`b"sha256"`.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200943 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -0700944 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800945 """
946 if pkey._only_public:
947 raise ValueError("Key has only public part")
948
949 if not pkey._initialized:
950 raise ValueError("Key is uninitialized")
951
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500952 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500953 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800954 raise ValueError("No such digest method")
955
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500956 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400957 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800958
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800959 def verify(self, pkey):
960 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200961 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800962
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200963 :param key: A public key.
964 :type key: :py:class:`PKey`
965 :return: :py:data:`True` if the signature is correct.
966 :rtype: :py:class:`bool`
967 :raises Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800968 problem verifying the signature.
969 """
970 if not isinstance(pkey, PKey):
971 raise TypeError("pkey must be a PKey instance")
972
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500973 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800974 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500975 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800976
977 return result
978
979
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800980X509ReqType = X509Req
981
982
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800983class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200984 """
985 An X.509 certificate.
986 """
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800987 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500988 x509 = _lib.X509_new()
Hynek Schlawack8a2dd772016-07-31 13:46:20 +0200989 _openssl_assert(x509 != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500990 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800991
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800992 def set_version(self, version):
993 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200994 Set the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800995
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200996 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800997 :type version: :py:class:`int`
998
Dan Sully44e767a2016-06-04 18:05:27 -0700999 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001000 """
1001 if not isinstance(version, int):
1002 raise TypeError("version must be an integer")
1003
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001004 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001005
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001006 def get_version(self):
1007 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001008 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001009
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001010 :return: The version number of the certificate.
1011 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001012 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001013 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001014
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001015 def get_pubkey(self):
1016 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001017 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001018
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001019 :return: The public key.
1020 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001021 """
1022 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001023 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1024 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001025 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001026 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001027 pkey._only_public = True
1028 return pkey
1029
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001030 def set_pubkey(self, pkey):
1031 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001032 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001033
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001034 :param pkey: The public key.
1035 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001036
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001037 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001038 """
1039 if not isinstance(pkey, PKey):
1040 raise TypeError("pkey must be a PKey instance")
1041
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001042 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001043 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001044
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001045 def sign(self, pkey, digest):
1046 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001047 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001048
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001049 :param pkey: The key to sign with.
1050 :type pkey: :py:class:`PKey`
1051
1052 :param digest: The name of the message digest to use.
1053 :type digest: :py:class:`bytes`
1054
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001055 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001056 """
1057 if not isinstance(pkey, PKey):
1058 raise TypeError("pkey must be a PKey instance")
1059
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001060 if pkey._only_public:
1061 raise ValueError("Key only has public part")
1062
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001063 if not pkey._initialized:
1064 raise ValueError("Key is uninitialized")
1065
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001066 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001067 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001068 raise ValueError("No such digest method")
1069
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001070 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001071 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001072
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001073 def get_signature_algorithm(self):
1074 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001075 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001076
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001077 :return: The name of the algorithm.
1078 :rtype: :py:class:`bytes`
1079
1080 :raises ValueError: If the signature algorithm is undefined.
1081
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001082 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001083 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001084 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1085 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001086 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001087 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001088 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001089
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001090 def digest(self, digest_name):
1091 """
1092 Return the digest of the X509 object.
1093
1094 :param digest_name: The name of the digest algorithm to use.
1095 :type digest_name: :py:class:`bytes`
1096
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001097 :return: The digest of the object, formatted as
1098 :py:const:`b":"`-delimited hex pairs.
1099 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001100 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001101 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001102 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001103 raise ValueError("No such digest method")
1104
Paul Kehrer9f9113a2016-09-20 20:10:25 -05001105 result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001106 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001107 result_length[0] = len(result_buffer)
1108
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001109 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001110 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001111 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001112
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001113 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001114 b16encode(ch).upper() for ch
1115 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001116
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001117 def subject_name_hash(self):
1118 """
1119 Return the hash of the X509 subject.
1120
1121 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001122 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001123 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001124 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001125
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001126 def set_serial_number(self, serial):
1127 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001128 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001129
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001130 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001131 :type serial: :py:class:`int`
1132
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001133 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001134 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001135 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001136 raise TypeError("serial must be an integer")
1137
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001138 hex_serial = hex(serial)[2:]
1139 if not isinstance(hex_serial, bytes):
1140 hex_serial = hex_serial.encode('ascii')
1141
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001142 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001143
1144 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001145 # it. If bignum is still NULL after this call, then the return value
1146 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001147 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001148
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001149 if bignum_serial[0] == _ffi.NULL:
1150 set_result = _lib.ASN1_INTEGER_set(
1151 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001152 if set_result:
1153 # TODO Not tested
1154 _raise_current_error()
1155 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001156 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1157 _lib.BN_free(bignum_serial[0])
1158 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001159 # TODO Not tested
1160 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001161 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1162 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001163 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001164
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001165 def get_serial_number(self):
1166 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001167 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001168
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001169 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001170 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001171 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001172 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1173 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001174 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001175 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001176 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001177 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001178 serial = int(hexstring_serial, 16)
1179 return serial
1180 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001181 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001182 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001183 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001184
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001185 def gmtime_adj_notAfter(self, amount):
1186 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001187 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001188
Dan Sully44e767a2016-06-04 18:05:27 -07001189 :param int amount: The number of seconds by which to adjust the
1190 timestamp.
1191 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001192 """
1193 if not isinstance(amount, int):
1194 raise TypeError("amount must be an integer")
1195
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001196 notAfter = _lib.X509_get_notAfter(self._x509)
1197 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001198
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001199 def gmtime_adj_notBefore(self, amount):
1200 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001201 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001202
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001203 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001204 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001205 """
1206 if not isinstance(amount, int):
1207 raise TypeError("amount must be an integer")
1208
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001209 notBefore = _lib.X509_get_notBefore(self._x509)
1210 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001211
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001212 def has_expired(self):
1213 """
1214 Check whether the certificate has expired.
1215
Dan Sully44e767a2016-06-04 18:05:27 -07001216 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1217 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001218 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001219 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001220 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001221
Paul Kehrerfde45c92016-01-21 12:57:37 -06001222 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001223
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001224 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001225 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001226
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001227 def get_notBefore(self):
1228 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001229 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001230
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001231 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001232
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001233 YYYYMMDDhhmmssZ
1234 YYYYMMDDhhmmss+hhmm
1235 YYYYMMDDhhmmss-hhmm
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001236
Dan Sully44e767a2016-06-04 18:05:27 -07001237 :return: A timestamp string, or ``None`` if there is none.
1238 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001239 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001240 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001241
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001242 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001243 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001244
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001245 def set_notBefore(self, when):
1246 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001247 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001248
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001249 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001250
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001251 YYYYMMDDhhmmssZ
1252 YYYYMMDDhhmmss+hhmm
1253 YYYYMMDDhhmmss-hhmm
1254
Dan Sully44e767a2016-06-04 18:05:27 -07001255 :param bytes when: A timestamp string.
1256 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001257 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001258 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001259
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001260 def get_notAfter(self):
1261 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001262 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001263
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001264 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001265
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001266 YYYYMMDDhhmmssZ
1267 YYYYMMDDhhmmss+hhmm
1268 YYYYMMDDhhmmss-hhmm
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001269
Dan Sully44e767a2016-06-04 18:05:27 -07001270 :return: A timestamp string, or ``None`` if there is none.
1271 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001272 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001273 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001274
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001275 def set_notAfter(self, when):
1276 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001277 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001278
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001279 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001280
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001281 YYYYMMDDhhmmssZ
1282 YYYYMMDDhhmmss+hhmm
1283 YYYYMMDDhhmmss-hhmm
1284
Dan Sully44e767a2016-06-04 18:05:27 -07001285 :param bytes when: A timestamp string.
1286 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001287 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001288 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001289
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001290 def _get_name(self, which):
1291 name = X509Name.__new__(X509Name)
1292 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001293 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001294
1295 # The name is owned by the X509 structure. As long as the X509Name
1296 # Python object is alive, keep the X509 Python object alive.
1297 name._owner = self
1298
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001299 return name
1300
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001301 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001302 if not isinstance(name, X509Name):
1303 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001304 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001305 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001306
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001307 def get_issuer(self):
1308 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001309 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001310
Cory Benfielde6bcce82015-12-09 08:40:03 +00001311 This creates a new :class:`X509Name` that wraps the underlying issuer
1312 name field on the certificate. Modifying it will modify the underlying
1313 certificate, and will have the effect of modifying any other
1314 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001315
1316 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001317 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001318 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001319 return self._get_name(_lib.X509_get_issuer_name)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001320
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001321 def set_issuer(self, issuer):
1322 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001323 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001324
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001325 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001326 :type issuer: :py:class:`X509Name`
1327
Dan Sully44e767a2016-06-04 18:05:27 -07001328 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001329 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001330 return self._set_name(_lib.X509_set_issuer_name, issuer)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001331
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001332 def get_subject(self):
1333 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001334 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001335
Cory Benfielde6bcce82015-12-09 08:40:03 +00001336 This creates a new :class:`X509Name` that wraps the underlying subject
1337 name field on the certificate. Modifying it will modify the underlying
1338 certificate, and will have the effect of modifying any other
1339 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001340
1341 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001342 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001343 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001344 return self._get_name(_lib.X509_get_subject_name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001345
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001346 def set_subject(self, subject):
1347 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001348 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001349
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001350 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001351 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001352
Dan Sully44e767a2016-06-04 18:05:27 -07001353 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001354 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001355 return self._set_name(_lib.X509_set_subject_name, subject)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001356
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001357 def get_extension_count(self):
1358 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001359 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001360
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001361 :return: The number of extensions.
1362 :rtype: :py:class:`int`
1363
1364 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001365 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001366 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001367
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001368 def add_extensions(self, extensions):
1369 """
1370 Add extensions to the certificate.
1371
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001372 :param extensions: The extensions to add.
1373 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001374 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001375 """
1376 for ext in extensions:
1377 if not isinstance(ext, X509Extension):
1378 raise ValueError("One of the elements is not an X509Extension")
1379
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001380 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001381 if not add_result:
1382 _raise_current_error()
1383
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001384 def get_extension(self, index):
1385 """
1386 Get a specific extension of the certificate by index.
1387
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001388 Extensions on a certificate are kept in order. The index
1389 parameter selects which extension will be returned.
1390
1391 :param int index: The index of the extension to retrieve.
1392 :return: The extension at the specified index.
1393 :rtype: :py:class:`X509Extension`
1394 :raises IndexError: If the extension index was out of bounds.
1395
1396 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001397 """
1398 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001399 ext._extension = _lib.X509_get_ext(self._x509, index)
1400 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001401 raise IndexError("extension index out of bounds")
1402
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001403 extension = _lib.X509_EXTENSION_dup(ext._extension)
1404 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001405 return ext
1406
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001407
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001408X509Type = X509
1409
1410
Dan Sully44e767a2016-06-04 18:05:27 -07001411class X509StoreFlags(object):
1412 """
1413 Flags for X509 verification, used to change the behavior of
1414 :class:`X509Store`.
1415
1416 See `OpenSSL Verification Flags`_ for details.
1417
1418 .. _OpenSSL Verification Flags:
1419 https://www.openssl.org/docs/manmaster/crypto/X509_VERIFY_PARAM_set_flags.html
1420 """
1421 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1422 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1423 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1424 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1425 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1426 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1427 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1428 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1429 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1430 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1431 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1432
1433
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001434class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001435 """
Dan Sully44e767a2016-06-04 18:05:27 -07001436 An X.509 store.
1437
1438 An X.509 store is used to describe a context in which to verify a
1439 certificate. A description of a context may include a set of certificates
1440 to trust, a set of certificate revocation lists, verification flags and
1441 more.
1442
1443 An X.509 store, being only a description, cannot be used by itself to
1444 verify a certificate. To carry out the actual verification process, see
1445 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001446 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001447
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001448 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001449 store = _lib.X509_STORE_new()
1450 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001451
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001452 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001453 """
Dan Sully44e767a2016-06-04 18:05:27 -07001454 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001455
Dan Sully44e767a2016-06-04 18:05:27 -07001456 Adding a certificate with this method adds this certificate as a
1457 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001458
1459 :param X509 cert: The certificate to add to this store.
Dan Sully44e767a2016-06-04 18:05:27 -07001460 :raises TypeError: If the certificate is not an :class:`X509`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001461 :raises Error: If OpenSSL was unhappy with your certificate.
Dan Sully44e767a2016-06-04 18:05:27 -07001462 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001463 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001464 if not isinstance(cert, X509):
1465 raise TypeError()
1466
Dan Sully44e767a2016-06-04 18:05:27 -07001467 _openssl_assert(_lib.X509_STORE_add_cert(self._store, cert._x509) != 0)
1468
1469 def add_crl(self, crl):
1470 """
1471 Add a certificate revocation list to this store.
1472
1473 The certificate revocation lists added to a store will only be used if
1474 the associated flags are configured to check certificate revocation
1475 lists.
1476
1477 .. versionadded:: 16.1.0
1478
1479 :param CRL crl: The certificate revocation list to add to this store.
1480 :return: ``None`` if the certificate revocation list was added
1481 successfully.
1482 """
1483 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1484
1485 def set_flags(self, flags):
1486 """
1487 Set verification flags to this store.
1488
1489 Verification flags can be combined by oring them together.
1490
1491 .. note::
1492
1493 Setting a verification flag sometimes requires clients to add
1494 additional information to the store, otherwise a suitable error will
1495 be raised.
1496
1497 For example, in setting flags to enable CRL checking a
1498 suitable CRL must be added to the store otherwise an error will be
1499 raised.
1500
1501 .. versionadded:: 16.1.0
1502
1503 :param int flags: The verification flags to set on this store.
1504 See :class:`X509StoreFlags` for available constants.
1505 :return: ``None`` if the verification flags were successfully set.
1506 """
1507 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001508
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001509
1510X509StoreType = X509Store
1511
1512
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001513class X509StoreContextError(Exception):
1514 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001515 An exception raised when an error occurred while verifying a certificate
1516 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001517
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001518 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001519 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001520 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001521
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001522 def __init__(self, message, certificate):
1523 super(X509StoreContextError, self).__init__(message)
1524 self.certificate = certificate
1525
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001526
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001527class X509StoreContext(object):
1528 """
1529 An X.509 store context.
1530
Dan Sully44e767a2016-06-04 18:05:27 -07001531 An X.509 store context is used to carry out the actual verification process
1532 of a certificate in a described context. For describing such a context, see
1533 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001534
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001535 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1536 instance. It is dynamically allocated and automatically garbage
1537 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001538 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001539 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001540 :param X509Store store: The certificates which will be trusted for the
1541 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001542 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001543 """
1544
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001545 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001546 store_ctx = _lib.X509_STORE_CTX_new()
1547 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1548 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001549 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001550 # Make the store context available for use after instantiating this
1551 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001552 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001553 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001554
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001555 def _init(self):
1556 """
1557 Set up the store context for a subsequent verification operation.
1558 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001559 ret = _lib.X509_STORE_CTX_init(
1560 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1561 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001562 if ret <= 0:
1563 _raise_current_error()
1564
1565 def _cleanup(self):
1566 """
1567 Internally cleans up the store context.
1568
Dan Sully44e767a2016-06-04 18:05:27 -07001569 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001570 """
1571 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1572
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001573 def _exception_from_context(self):
1574 """
1575 Convert an OpenSSL native context error failure into a Python
1576 exception.
1577
Alex Gaynor5945ea82015-09-05 14:59:06 -04001578 When a call to native OpenSSL X509_verify_cert fails, additional
1579 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001580 """
1581 errors = [
1582 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1583 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1584 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001585 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001586 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001587 # A context error should always be associated with a certificate, so we
1588 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001589 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001590 _cert = _lib.X509_dup(_x509)
1591 pycert = X509.__new__(X509)
1592 pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001593 return X509StoreContextError(errors, pycert)
1594
Stephen Holsapple46a09252015-02-12 14:45:43 -08001595 def set_store(self, store):
1596 """
Dan Sully44e767a2016-06-04 18:05:27 -07001597 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001598
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001599 .. versionadded:: 0.15
1600
Dan Sully44e767a2016-06-04 18:05:27 -07001601 :param X509Store store: The store description which will be used for
1602 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001603 """
1604 self._store = store
1605
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001606 def verify_certificate(self):
1607 """
1608 Verify a certificate in a context.
1609
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001610 .. versionadded:: 0.15
1611
Alex Gaynorca87ff62015-09-04 23:31:03 -04001612 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001613 certificate in the context. Sets ``certificate`` attribute to
1614 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001615 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001616 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001617 # :meth:`verify_certificate` is called multiple times.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001618 self._init()
1619 ret = _lib.X509_verify_cert(self._store_ctx)
1620 self._cleanup()
1621 if ret <= 0:
1622 raise self._exception_from_context()
1623
1624
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001625def load_certificate(type, buffer):
1626 """
1627 Load a certificate from a buffer
1628
1629 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1630
Dan Sully44e767a2016-06-04 18:05:27 -07001631 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001632
1633 :return: The X509 object
1634 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001635 if isinstance(buffer, _text_type):
1636 buffer = buffer.encode("ascii")
1637
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001638 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001639
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001640 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001641 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001642 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001643 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001644 else:
1645 raise ValueError(
1646 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001647
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001648 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001649 _raise_current_error()
1650
1651 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001652 cert._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001653 return cert
1654
1655
1656def dump_certificate(type, cert):
1657 """
1658 Dump a certificate to a buffer
1659
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001660 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1661 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001662 :param cert: The certificate to dump
1663 :return: The buffer with the dumped certificate in
1664 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001665 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001666
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001667 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001668 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001669 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001670 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001671 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001672 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001673 else:
1674 raise ValueError(
1675 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1676 "FILETYPE_TEXT")
1677
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001678 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001679 return _bio_to_string(bio)
1680
1681
Cory Benfield6492f7c2015-10-27 16:57:58 +09001682def dump_publickey(type, pkey):
1683 """
Cory Benfield11c10192015-10-27 17:23:03 +09001684 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001685
Cory Benfield9c590b92015-10-28 14:55:05 +09001686 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001687 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001688 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001689 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001690 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001691 """
1692 bio = _new_mem_buf()
1693 if type == FILETYPE_PEM:
1694 write_bio = _lib.PEM_write_bio_PUBKEY
1695 elif type == FILETYPE_ASN1:
1696 write_bio = _lib.i2d_PUBKEY_bio
1697 else:
1698 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1699
1700 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001701 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001702 _raise_current_error()
1703
1704 return _bio_to_string(bio)
1705
1706
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001707def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1708 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001709 Dump the private key *pkey* into a buffer string encoded with the type
1710 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1711 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001712
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001713 :param type: The file type (one of :const:`FILETYPE_PEM`,
1714 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1715 :param PKey pkey: The PKey to dump
1716 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001717 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001718 the passphrase to use, or a callback for providing the passphrase.
1719
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001720 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001721 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001722 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001723 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001724
1725 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001726 if passphrase is None:
1727 raise TypeError(
1728 "if a value is given for cipher "
1729 "one must also be given for passphrase")
1730 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001731 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001732 raise ValueError("Invalid cipher name")
1733 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001734 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001735
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001736 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001737 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001738 result_code = _lib.PEM_write_bio_PrivateKey(
1739 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001740 helper.callback, helper.callback_args)
1741 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001742 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001743 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001744 elif type == FILETYPE_TEXT:
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001745 rsa = _ffi.gc(
1746 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1747 _lib.RSA_free
1748 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001749 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001750 else:
1751 raise ValueError(
1752 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1753 "FILETYPE_TEXT")
1754
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001755 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001756
1757 return _bio_to_string(bio)
1758
1759
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001760class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001761 """
1762 A certificate revocation.
1763 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001764 # http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_
1765 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1766 # OCSP_crl_reason_str. We use the latter, just like the command line
1767 # program.
1768 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001769 b"unspecified",
1770 b"keyCompromise",
1771 b"CACompromise",
1772 b"affiliationChanged",
1773 b"superseded",
1774 b"cessationOfOperation",
1775 b"certificateHold",
1776 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001777 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001778
1779 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001780 revoked = _lib.X509_REVOKED_new()
1781 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001782
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001783 def set_serial(self, hex_str):
1784 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001785 Set the serial number.
1786
1787 The serial number is formatted as a hexadecimal number encoded in
1788 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001789
Dan Sully44e767a2016-06-04 18:05:27 -07001790 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001791
Dan Sully44e767a2016-06-04 18:05:27 -07001792 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001793 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001794 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1795 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001796 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001797 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001798 if not bn_result:
1799 raise ValueError("bad hex string")
1800
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001801 asn1_serial = _ffi.gc(
1802 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1803 _lib.ASN1_INTEGER_free)
1804 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001805
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001806 def get_serial(self):
1807 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001808 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001809
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001810 The serial number is formatted as a hexadecimal number encoded in
1811 ASCII.
1812
1813 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001814 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001815 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001816 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001817
Alex Gaynor67903a62016-06-02 10:37:13 -07001818 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1819 _openssl_assert(asn1_int != _ffi.NULL)
1820 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1821 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001822 return _bio_to_string(bio)
1823
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001824 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001825 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1826 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001827 obj = _lib.X509_EXTENSION_get_object(ext)
1828 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001829 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001830 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001831 break
1832
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001833 def set_reason(self, reason):
1834 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001835 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001836
Dan Sully44e767a2016-06-04 18:05:27 -07001837 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001838
1839 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07001840 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001841
Dan Sully44e767a2016-06-04 18:05:27 -07001842 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001843
1844 .. seealso::
1845
Dan Sully44e767a2016-06-04 18:05:27 -07001846 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001847 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001848 """
1849 if reason is None:
1850 self._delete_reason()
1851 elif not isinstance(reason, bytes):
1852 raise TypeError("reason must be None or a byte string")
1853 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001854 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001855 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
1856
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001857 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07001858 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001859 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001860
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001861 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001862 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001863
1864 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001865 add_result = _lib.X509_REVOKED_add1_ext_i2d(
1866 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001867 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001868
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001869 def get_reason(self):
1870 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04001871 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001872
Dan Sully44e767a2016-06-04 18:05:27 -07001873 :return: The reason, or ``None`` if there is none.
1874 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001875
1876 .. seealso::
1877
Dan Sully44e767a2016-06-04 18:05:27 -07001878 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001879 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001880 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001881 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1882 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001883 obj = _lib.X509_EXTENSION_get_object(ext)
1884 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001885 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001886
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001887 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001888 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04001889 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001890 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04001891 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04001892 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001893
1894 return _bio_to_string(bio)
1895
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001896 def all_reasons(self):
1897 """
1898 Return a list of all the supported reason strings.
1899
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001900 This list is a copy; modifying it does not change the supported reason
1901 strings.
1902
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001903 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07001904 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001905 """
1906 return self._crl_reasons[:]
1907
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001908 def set_rev_date(self, when):
1909 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001910 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001911
Dan Sully44e767a2016-06-04 18:05:27 -07001912 :param bytes when: The timestamp of the revocation,
1913 as ASN.1 GENERALIZEDTIME.
1914 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001915 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001916 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1917 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001918
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001919 def get_rev_date(self):
1920 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001921 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001922
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001923 :return: The timestamp of the revocation, as ASN.1 GENERALIZEDTIME.
Dan Sully44e767a2016-06-04 18:05:27 -07001924 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001925 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001926 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1927 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001928
1929
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001930class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001931 """
1932 A certificate revocation list.
1933 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001934
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001935 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001936 crl = _lib.X509_CRL_new()
1937 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001938
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001939 def get_revoked(self):
1940 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001941 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001942
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001943 These revocations will be provided by value, not by reference.
1944 That means it's okay to mutate them: it won't affect this CRL.
1945
1946 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07001947 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001948 """
1949 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07001950 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001951 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
1952 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04001953 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001954 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001955 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001956 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08001957 if results:
1958 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001959
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001960 def add_revoked(self, revoked):
1961 """
1962 Add a revoked (by value not reference) to the CRL structure
1963
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001964 This revocation will be added by value, not by reference. That
1965 means it's okay to mutate it after adding: it won't affect
1966 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001967
Dan Sully44e767a2016-06-04 18:05:27 -07001968 :param Revoked revoked: The new revocation.
1969 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001970 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04001971 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001972 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001973
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001974 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001975 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001976
Dan Sully44e767a2016-06-04 18:05:27 -07001977 def get_issuer(self):
1978 """
1979 Get the CRL's issuer.
1980
1981 .. versionadded:: 16.1.0
1982
1983 :rtype: X509Name
1984 """
1985 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
1986 _openssl_assert(_issuer != _ffi.NULL)
1987 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
1988 issuer = X509Name.__new__(X509Name)
1989 issuer._name = _issuer
1990 return issuer
1991
1992 def set_version(self, version):
1993 """
1994 Set the CRL version.
1995
1996 .. versionadded:: 16.1.0
1997
1998 :param int version: The version of the CRL.
1999 :return: ``None``
2000 """
2001 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2002
2003 def _set_boundary_time(self, which, when):
2004 return _set_asn1_time(which(self._crl), when)
2005
2006 def set_lastUpdate(self, when):
2007 """
2008 Set when the CRL was last updated.
2009
2010 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
2011
2012 YYYYMMDDhhmmssZ
2013 YYYYMMDDhhmmss+hhmm
2014 YYYYMMDDhhmmss-hhmm
2015
2016 .. versionadded:: 16.1.0
2017
2018 :param bytes when: A timestamp string.
2019 :return: ``None``
2020 """
2021 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2022
2023 def set_nextUpdate(self, when):
2024 """
2025 Set when the CRL will next be udpated.
2026
2027 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
2028
2029 YYYYMMDDhhmmssZ
2030 YYYYMMDDhhmmss+hhmm
2031 YYYYMMDDhhmmss-hhmm
2032
2033 .. versionadded:: 16.1.0
2034
2035 :param bytes when: A timestamp string.
2036 :return: ``None``
2037 """
2038 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2039
2040 def sign(self, issuer_cert, issuer_key, digest):
2041 """
2042 Sign the CRL.
2043
2044 Signing a CRL enables clients to associate the CRL itself with an
2045 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2046 be signed by an issuer.
2047
2048 This method implicitly sets the issuer's name based on the issuer
2049 certificate and private key used to sign the CRL.
2050
2051 .. versionadded:: 16.1.0
2052
2053 :param X509 issuer_cert: The issuer's certificate.
2054 :param PKey issuer_key: The issuer's private key.
2055 :param bytes digest: The digest method to sign the CRL with.
2056 """
2057 digest_obj = _lib.EVP_get_digestbyname(digest)
2058 _openssl_assert(digest_obj != _ffi.NULL)
2059 _lib.X509_CRL_set_issuer_name(
2060 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2061 _lib.X509_CRL_sort(self._crl)
2062 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2063 _openssl_assert(result != 0)
2064
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002065 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002066 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002067 """
Dan Sully44e767a2016-06-04 18:05:27 -07002068 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002069
Dan Sully44e767a2016-06-04 18:05:27 -07002070 :param X509 cert: The certificate used to sign the CRL.
2071 :param PKey key: The key used to sign the CRL.
2072 :param int type: The export format, either :data:`FILETYPE_PEM`,
2073 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002074 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002075 :param bytes digest: The name of the message digest to use (eg
Alex Gaynor239e2d32016-09-11 12:36:35 -04002076 ``b"sha2566"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002077 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002078 """
Dan Sully44e767a2016-06-04 18:05:27 -07002079
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002080 if not isinstance(cert, X509):
2081 raise TypeError("cert must be an X509 instance")
2082 if not isinstance(key, PKey):
2083 raise TypeError("key must be a PKey instance")
2084 if not isinstance(type, int):
2085 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002086
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002087 if digest is _UNSPECIFIED:
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002088 _warn(
2089 "The default message digest (md5) is deprecated. "
2090 "Pass the name of a message digest explicitly.",
2091 category=DeprecationWarning,
2092 stacklevel=2,
2093 )
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002094 digest = b"md5"
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002095
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002096 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002097 if digest_obj == _ffi.NULL:
2098 raise ValueError("No such digest method")
2099
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002100 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002101 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002102
Alex Gaynora738ed52015-09-05 11:17:10 -04002103 # A scratch time object to give different values to different CRL
2104 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002105 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002106 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002107
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002108 _lib.X509_gmtime_adj(sometime, 0)
2109 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002110
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002111 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2112 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002113
Alex Gaynor5945ea82015-09-05 14:59:06 -04002114 _lib.X509_CRL_set_issuer_name(
2115 self._crl, _lib.X509_get_subject_name(cert._x509)
2116 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002117
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002118 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002119 if not sign_result:
2120 _raise_current_error()
2121
Dominic Chenf05b2122015-10-13 16:32:35 +00002122 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002123
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002124
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002125CRLType = CRL
2126
2127
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002128class PKCS7(object):
2129 def type_is_signed(self):
2130 """
2131 Check if this NID_pkcs7_signed object
2132
2133 :return: True if the PKCS7 is of type signed
2134 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002135 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002136
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002137 def type_is_enveloped(self):
2138 """
2139 Check if this NID_pkcs7_enveloped object
2140
2141 :returns: True if the PKCS7 is of type enveloped
2142 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002143 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002144
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002145 def type_is_signedAndEnveloped(self):
2146 """
2147 Check if this NID_pkcs7_signedAndEnveloped object
2148
2149 :returns: True if the PKCS7 is of type signedAndEnveloped
2150 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002151 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002152
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002153 def type_is_data(self):
2154 """
2155 Check if this NID_pkcs7_data object
2156
2157 :return: True if the PKCS7 is of type data
2158 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002159 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002160
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002161 def get_type_name(self):
2162 """
2163 Returns the type name of the PKCS7 structure
2164
2165 :return: A string with the typename
2166 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002167 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2168 string_type = _lib.OBJ_nid2sn(nid)
2169 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002170
2171PKCS7Type = PKCS7
2172
2173
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002174class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002175 """
2176 A PKCS #12 archive.
2177 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002178
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002179 def __init__(self):
2180 self._pkey = None
2181 self._cert = None
2182 self._cacerts = None
2183 self._friendlyname = None
2184
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002185 def get_certificate(self):
2186 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002187 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002188
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002189 :return: The certificate, or :py:const:`None` if there is none.
2190 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002191 """
2192 return self._cert
2193
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002194 def set_certificate(self, cert):
2195 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002196 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002197
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002198 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002199 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002200
Dan Sully44e767a2016-06-04 18:05:27 -07002201 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002202 """
2203 if not isinstance(cert, X509):
2204 raise TypeError("cert must be an X509 instance")
2205 self._cert = cert
2206
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002207 def get_privatekey(self):
2208 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002209 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002210
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002211 :return: The private key, or :py:const:`None` if there is none.
2212 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002213 """
2214 return self._pkey
2215
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002216 def set_privatekey(self, pkey):
2217 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002218 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002219
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002220 :param pkey: The new private key, or :py:const:`None` to unset it.
2221 :type pkey: :py:class:`PKey` or :py:const:`None`
2222
Dan Sully44e767a2016-06-04 18:05:27 -07002223 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002224 """
2225 if not isinstance(pkey, PKey):
2226 raise TypeError("pkey must be a PKey instance")
2227 self._pkey = pkey
2228
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002229 def get_ca_certificates(self):
2230 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002231 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002232
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002233 :return: A tuple with the CA certificates in the chain, or
2234 :py:const:`None` if there are none.
2235 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002236 """
2237 if self._cacerts is not None:
2238 return tuple(self._cacerts)
2239
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002240 def set_ca_certificates(self, cacerts):
2241 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002242 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002243
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002244 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2245 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002246 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002247
Dan Sully44e767a2016-06-04 18:05:27 -07002248 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002249 """
2250 if cacerts is None:
2251 self._cacerts = None
2252 else:
2253 cacerts = list(cacerts)
2254 for cert in cacerts:
2255 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002256 raise TypeError(
2257 "iterable must only contain X509 instances"
2258 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002259 self._cacerts = cacerts
2260
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002261 def set_friendlyname(self, name):
2262 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002263 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002264
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002265 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002266 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002267
Dan Sully44e767a2016-06-04 18:05:27 -07002268 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002269 """
2270 if name is None:
2271 self._friendlyname = None
2272 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002273 raise TypeError(
2274 "name must be a byte string or None (not %r)" % (name,)
2275 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002276 self._friendlyname = name
2277
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002278 def get_friendlyname(self):
2279 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002280 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002281
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002282 :returns: The friendly name, or :py:const:`None` if there is none.
2283 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002284 """
2285 return self._friendlyname
2286
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002287 def export(self, passphrase=None, iter=2048, maciter=1):
2288 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002289 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002290
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002291 For more information, see the :c:func:`PKCS12_create` man page.
2292
2293 :param passphrase: The passphrase used to encrypt the structure. Unlike
2294 some other passphrase arguments, this *must* be a string, not a
2295 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002296 :type passphrase: :py:data:`bytes`
2297
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002298 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002299 :type iter: :py:data:`int`
2300
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002301 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002302 :type maciter: :py:data:`int`
2303
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002304 :return: The string representation of the PKCS #12 structure.
2305 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002306 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002307 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002308
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002309 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002310 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002311 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002312 cacerts = _lib.sk_X509_new_null()
2313 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002314 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002315 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002316
2317 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002318 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002319
2320 friendlyname = self._friendlyname
2321 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002322 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002323
2324 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002325 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002326 else:
2327 pkey = self._pkey._pkey
2328
2329 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002330 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002331 else:
2332 cert = self._cert._x509
2333
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002334 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002335 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002336 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2337 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002338 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002339 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002340 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002341 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002342
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002343 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002344 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002345 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002346
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002347
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002348PKCS12Type = PKCS12
2349
2350
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002351class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002352 """
2353 A Netscape SPKI object.
2354 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002355
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002356 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002357 spki = _lib.NETSCAPE_SPKI_new()
2358 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002359
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002360 def sign(self, pkey, digest):
2361 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002362 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002363
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002364 :param pkey: The private key to sign with.
2365 :type pkey: :py:class:`PKey`
2366
2367 :param digest: The message digest to use.
2368 :type digest: :py:class:`bytes`
2369
Dan Sully44e767a2016-06-04 18:05:27 -07002370 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002371 """
2372 if pkey._only_public:
2373 raise ValueError("Key has only public part")
2374
2375 if not pkey._initialized:
2376 raise ValueError("Key is uninitialized")
2377
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002378 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002379 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002380 raise ValueError("No such digest method")
2381
Alex Gaynor5945ea82015-09-05 14:59:06 -04002382 sign_result = _lib.NETSCAPE_SPKI_sign(
2383 self._spki, pkey._pkey, digest_obj
2384 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002385 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002386
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002387 def verify(self, key):
2388 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002389 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002390
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002391 :param key: The public key that signature is supposedly from.
2392 :type pkey: :py:class:`PKey`
2393
2394 :return: :py:const:`True` if the signature is correct.
2395 :rtype: :py:class:`bool`
2396
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002397 :raises Error: If the signature is invalid, or there was a problem
2398 verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002399 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002400 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002401 if answer <= 0:
2402 _raise_current_error()
2403 return True
2404
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002405 def b64_encode(self):
2406 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002407 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002408
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002409 :return: The base64 encoded string.
2410 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002411 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002412 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2413 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002414 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002415 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002416
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002417 def get_pubkey(self):
2418 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002419 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002420
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002421 :return: The public key.
2422 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002423 """
2424 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002425 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002426 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002427 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002428 pkey._only_public = True
2429 return pkey
2430
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002431 def set_pubkey(self, pkey):
2432 """
2433 Set the public key of the certificate
2434
2435 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002436 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002437 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002438 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002439 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002440
2441
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002442NetscapeSPKIType = NetscapeSPKI
2443
2444
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002445class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002446 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002447 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002448 raise ValueError(
2449 "only FILETYPE_PEM key format supports encryption"
2450 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002451 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002452 self._more_args = more_args
2453 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002454 self._problems = []
2455
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002456 @property
2457 def callback(self):
2458 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002459 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002460 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002461 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002462 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002463 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002464 else:
2465 raise TypeError("Last argument must be string or callable")
2466
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002467 @property
2468 def callback_args(self):
2469 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002470 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002471 elif isinstance(self._passphrase, bytes):
2472 return self._passphrase
2473 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002474 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002475 else:
2476 raise TypeError("Last argument must be string or callable")
2477
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002478 def raise_if_problem(self, exceptionType=Error):
2479 try:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05002480 _exception_from_error_queue(exceptionType)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002481 except exceptionType as e:
Jean-Paul Calderone9b4115f2014-01-10 14:06:04 -05002482 from_queue = e
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002483 if self._problems:
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002484 raise self._problems[0]
Jean-Paul Calderone9b4115f2014-01-10 14:06:04 -05002485 return from_queue
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002486
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002487 def _read_passphrase(self, buf, size, rwflag, userdata):
2488 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002489 if self._more_args:
2490 result = self._passphrase(size, rwflag, userdata)
2491 else:
2492 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002493 if not isinstance(result, bytes):
2494 raise ValueError("String expected")
2495 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002496 if self._truncate:
2497 result = result[:size]
2498 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002499 raise ValueError(
2500 "passphrase returned by callback is too long"
2501 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002502 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002503 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002504 return len(result)
2505 except Exception as e:
2506 self._problems.append(e)
2507 return 0
2508
2509
Cory Benfield6492f7c2015-10-27 16:57:58 +09002510def load_publickey(type, buffer):
2511 """
Cory Benfield11c10192015-10-27 17:23:03 +09002512 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002513
Cory Benfield9c590b92015-10-28 14:55:05 +09002514 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002515 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002516 :param buffer: The buffer the key is stored in.
2517 :type buffer: A Python string object, either unicode or bytestring.
2518 :return: The PKey object.
2519 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002520 """
2521 if isinstance(buffer, _text_type):
2522 buffer = buffer.encode("ascii")
2523
2524 bio = _new_mem_buf(buffer)
2525
2526 if type == FILETYPE_PEM:
2527 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2528 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2529 elif type == FILETYPE_ASN1:
2530 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2531 else:
2532 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2533
2534 if evp_pkey == _ffi.NULL:
2535 _raise_current_error()
2536
2537 pkey = PKey.__new__(PKey)
2538 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002539 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002540 return pkey
2541
2542
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002543def load_privatekey(type, buffer, passphrase=None):
2544 """
2545 Load a private key from a buffer
2546
2547 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2548 :param buffer: The buffer the key is stored in
2549 :param passphrase: (optional) if encrypted PEM format, this can be
2550 either the passphrase to use, or a callback for
2551 providing the passphrase.
2552
2553 :return: The PKey object
2554 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002555 if isinstance(buffer, _text_type):
2556 buffer = buffer.encode("ascii")
2557
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002558 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002559
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002560 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002561 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002562 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2563 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002564 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002565 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002566 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002567 else:
2568 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2569
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002570 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002571 _raise_current_error()
2572
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002573 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002574 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002575 return pkey
2576
2577
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002578def dump_certificate_request(type, req):
2579 """
2580 Dump a certificate request to a buffer
2581
2582 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2583 :param req: The certificate request to dump
2584 :return: The buffer with the dumped certificate request in
2585 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002586 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002587
2588 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002589 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002590 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002591 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002592 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002593 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002594 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002595 raise ValueError(
2596 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2597 "FILETYPE_TEXT"
2598 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002599
Alex Gaynor09a386e2016-07-03 09:32:44 -04002600 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002601
2602 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002603
2604
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002605def load_certificate_request(type, buffer):
2606 """
2607 Load a certificate request from a buffer
2608
2609 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2610 :param buffer: The buffer the certificate request is stored in
2611 :return: The X509Req object
2612 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002613 if isinstance(buffer, _text_type):
2614 buffer = buffer.encode("ascii")
2615
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002616 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002617
2618 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002619 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002620 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002621 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002622 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002623 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002624
Alex Gaynoradd5b072016-06-04 21:04:00 -07002625 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002626
2627 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002628 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002629 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002630
2631
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002632def sign(pkey, data, digest):
2633 """
2634 Sign data with a digest
2635
2636 :param pkey: Pkey to sign with
2637 :param data: data to be signed
2638 :param digest: message digest to use
2639 :return: signature
2640 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002641 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002642
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002643 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002644 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002645 raise ValueError("No such digest method")
2646
Alex Gaynor67903a62016-06-02 10:37:13 -07002647 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002648 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002649
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002650 _lib.EVP_SignInit(md_ctx, digest_obj)
2651 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002652
Colleen Murphye09399b2016-03-01 17:40:49 -08002653 pkey_length = (PKey.bits(pkey) + 7) // 8
2654 signature_buffer = _ffi.new("unsigned char[]", pkey_length)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002655 signature_length = _ffi.new("unsigned int*")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002656 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002657 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002658 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002659
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002660 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002661
2662
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002663def verify(cert, signature, data, digest):
2664 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002665 Verify a signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002666
2667 :param cert: signing certificate (X509 object)
2668 :param signature: signature returned by sign function
2669 :param data: data to be verified
2670 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002671 :return: ``None`` if the signature is correct, raise exception otherwise.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002672 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002673 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002674
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002675 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002676 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002677 raise ValueError("No such digest method")
2678
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002679 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002680 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002681 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002682
Alex Gaynor67903a62016-06-02 10:37:13 -07002683 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002684 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002685
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002686 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2687 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002688 verify_result = _lib.EVP_VerifyFinal(
2689 md_ctx, signature, len(signature), pkey
2690 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002691
2692 if verify_result != 1:
2693 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002694
2695
Dominic Chenf05b2122015-10-13 16:32:35 +00002696def dump_crl(type, crl):
2697 """
2698 Dump a certificate revocation list to a buffer.
2699
2700 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2701 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002702 :param CRL crl: The CRL to dump.
2703
Dominic Chenf05b2122015-10-13 16:32:35 +00002704 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002705 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002706 """
2707 bio = _new_mem_buf()
2708
2709 if type == FILETYPE_PEM:
2710 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2711 elif type == FILETYPE_ASN1:
2712 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2713 elif type == FILETYPE_TEXT:
2714 ret = _lib.X509_CRL_print(bio, crl._crl)
2715 else:
2716 raise ValueError(
2717 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2718 "FILETYPE_TEXT")
2719
2720 assert ret == 1
2721 return _bio_to_string(bio)
2722
2723
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002724def load_crl(type, buffer):
2725 """
2726 Load a certificate revocation list from a buffer
2727
2728 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2729 :param buffer: The buffer the CRL is stored in
2730
2731 :return: The PKey object
2732 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002733 if isinstance(buffer, _text_type):
2734 buffer = buffer.encode("ascii")
2735
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002736 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002737
2738 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002739 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002740 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002741 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002742 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002743 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2744
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002745 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002746 _raise_current_error()
2747
2748 result = CRL.__new__(CRL)
2749 result._crl = crl
2750 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002751
2752
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002753def load_pkcs7_data(type, buffer):
2754 """
2755 Load pkcs7 data from a buffer
2756
2757 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2758 :param buffer: The buffer with the pkcs7 data.
2759 :return: The PKCS7 object
2760 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002761 if isinstance(buffer, _text_type):
2762 buffer = buffer.encode("ascii")
2763
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002764 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002765
2766 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002767 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002768 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002769 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002770 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002771 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2772
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002773 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002774 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002775
2776 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002777 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002778 return pypkcs7
2779
2780
Stephen Holsapple38482622014-04-05 20:29:34 -07002781def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002782 """
2783 Load a PKCS12 object from a buffer
2784
2785 :param buffer: The buffer the certificate is stored in
2786 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2787 :returns: The PKCS12 object
2788 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002789 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002790
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002791 if isinstance(buffer, _text_type):
2792 buffer = buffer.encode("ascii")
2793
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002794 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002795
Stephen Holsapple38482622014-04-05 20:29:34 -07002796 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2797 # password based encryption no password and a zero length password are two
2798 # different things, but OpenSSL implementation will try both to figure out
2799 # which one works.
2800 if not passphrase:
2801 passphrase = _ffi.NULL
2802
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002803 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2804 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002805 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002806 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002807
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002808 pkey = _ffi.new("EVP_PKEY**")
2809 cert = _ffi.new("X509**")
2810 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002811
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002812 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002813 if not parse_result:
2814 _raise_current_error()
2815
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002816 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002817
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002818 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
2819 # queue for no particular reason. This error isn't interesting to anyone
2820 # outside this function. It's not even interesting to us. Get rid of it.
2821 try:
2822 _raise_current_error()
2823 except Error:
2824 pass
2825
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002826 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002827 pykey = None
2828 else:
2829 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002830 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002831
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002832 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002833 pycert = None
2834 friendlyname = None
2835 else:
2836 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002837 pycert._x509 = _ffi.gc(cert[0], _lib.X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002838
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002839 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04002840 friendlyname_buffer = _lib.X509_alias_get0(
2841 cert[0], friendlyname_length
2842 )
2843 friendlyname = _ffi.buffer(
2844 friendlyname_buffer, friendlyname_length[0]
2845 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002846 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002847 friendlyname = None
2848
2849 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002850 for i in range(_lib.sk_X509_num(cacerts)):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002851 pycacert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002852 pycacert._x509 = _lib.sk_X509_value(cacerts, i)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002853 pycacerts.append(pycacert)
2854 if not pycacerts:
2855 pycacerts = None
2856
2857 pkcs12 = PKCS12.__new__(PKCS12)
2858 pkcs12._pkey = pykey
2859 pkcs12._cert = pycert
2860 pkcs12._cacerts = pycacerts
2861 pkcs12._friendlyname = friendlyname
2862 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05002863
2864
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05002865# There are no direct unit tests for this initialization. It is tested
2866# indirectly since it is necessary for functions like dump_privatekey when
2867# using encryption.
2868#
2869# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
2870# and some other similar tests may fail without this (though they may not if
2871# the Python runtime has already done some initialization of the underlying
2872# OpenSSL library (and is linked against the same one that cryptography is
2873# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05002874_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05002875
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05002876# This is similar but exercised mainly by exception_from_error_queue. It calls
2877# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
2878_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002879
2880
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002881# Set the default string mask to match OpenSSL upstream (since 2005) and
2882# RFC5280 recommendations.
2883_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')