blob: 4a379e84e730415b98b76faf062c05415337e2b2 [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
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050013from OpenSSL._util import (
14 ffi as _ffi,
15 lib as _lib,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050016 exception_from_error_queue as _exception_from_error_queue,
17 byte_string as _byte_string,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040018 native as _native,
19 UNSPECIFIED as _UNSPECIFIED,
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -040020 text_to_bytes_and_warn as _text_to_bytes_and_warn,
Alex Gaynor67903a62016-06-02 10:37:13 -070021 make_assert as _make_assert,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040022)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080023
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050024FILETYPE_PEM = _lib.SSL_FILETYPE_PEM
25FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080026
27# TODO This was an API mistake. OpenSSL has no such constant.
28FILETYPE_TEXT = 2 ** 16 - 1
29
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050030TYPE_RSA = _lib.EVP_PKEY_RSA
31TYPE_DSA = _lib.EVP_PKEY_DSA
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -080032
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080033
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050034class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050035 """
36 An error occurred in an `OpenSSL.crypto` API.
37 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050038
39
40_raise_current_error = partial(_exception_from_error_queue, Error)
Alex Gaynor67903a62016-06-02 10:37:13 -070041_openssl_assert = _make_assert(Error)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050042
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070043
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050044def _untested_error(where):
45 """
46 An OpenSSL API failed somehow. Additionally, the failure which was
47 encountered isn't one that's exercised by the test suite so future behavior
48 of pyOpenSSL is now somewhat less predictable.
49 """
50 raise RuntimeError("Unknown %s failure" % (where,))
51
52
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050053def _new_mem_buf(buffer=None):
54 """
55 Allocate a new OpenSSL memory BIO.
56
57 Arrange for the garbage collector to clean it up automatically.
58
59 :param buffer: None or some bytes to use to put into the BIO so that they
60 can be read out.
61 """
62 if buffer is None:
63 bio = _lib.BIO_new(_lib.BIO_s_mem())
64 free = _lib.BIO_free
65 else:
66 data = _ffi.new("char[]", buffer)
67 bio = _lib.BIO_new_mem_buf(data, len(buffer))
Alex Gaynor5945ea82015-09-05 14:59:06 -040068
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050069 # Keep the memory alive as long as the bio is alive!
70 def free(bio, ref=data):
71 return _lib.BIO_free(bio)
72
Alex Gaynorfb8a2a12016-06-04 18:26:26 -070073 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050074
75 bio = _ffi.gc(bio, free)
76 return bio
77
78
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080079def _bio_to_string(bio):
80 """
81 Copy the contents of an OpenSSL BIO object into a Python byte string.
82 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050083 result_buffer = _ffi.new('char**')
84 buffer_length = _lib.BIO_get_mem_data(bio, result_buffer)
85 return _ffi.buffer(result_buffer[0], buffer_length)[:]
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080086
87
Jean-Paul Calderone57122982013-02-21 08:47:05 -080088def _set_asn1_time(boundary, when):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -050089 """
90 The the time value of an ASN1 time object.
91
92 @param boundary: An ASN1_GENERALIZEDTIME pointer (or an object safely
93 castable to that type) which will have its value set.
94 @param when: A string representation of the desired time value.
95
96 @raise TypeError: If C{when} is not a L{bytes} string.
97 @raise ValueError: If C{when} does not represent a time in the required
98 format.
99 @raise RuntimeError: If the time value cannot be set for some other
100 (unspecified) reason.
101 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800102 if not isinstance(when, bytes):
103 raise TypeError("when must be a byte string")
104
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500105 set_result = _lib.ASN1_GENERALIZEDTIME_set_string(
106 _ffi.cast('ASN1_GENERALIZEDTIME*', boundary), when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800107 if set_result == 0:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500108 dummy = _ffi.gc(_lib.ASN1_STRING_new(), _lib.ASN1_STRING_free)
109 _lib.ASN1_STRING_set(dummy, when, len(when))
110 check_result = _lib.ASN1_GENERALIZEDTIME_check(
111 _ffi.cast('ASN1_GENERALIZEDTIME*', dummy))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800112 if not check_result:
113 raise ValueError("Invalid string")
114 else:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500115 _untested_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800116
Alex Gaynor510293e2016-06-02 12:07:59 -0700117
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800118def _get_asn1_time(timestamp):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500119 """
120 Retrieve the time value of an ASN1 time object.
121
122 @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to
123 that type) from which the time value will be retrieved.
124
125 @return: The time value from C{timestamp} as a L{bytes} string in a certain
126 format. Or C{None} if the object contains no time value.
127 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500128 string_timestamp = _ffi.cast('ASN1_STRING*', timestamp)
129 if _lib.ASN1_STRING_length(string_timestamp) == 0:
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800130 return None
Alex Gaynor5945ea82015-09-05 14:59:06 -0400131 elif (
132 _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME
133 ):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500134 return _ffi.string(_lib.ASN1_STRING_data(string_timestamp))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800135 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500136 generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**")
137 _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp)
138 if generalized_timestamp[0] == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500139 # This may happen:
140 # - if timestamp was not an ASN1_TIME
141 # - if allocating memory for the ASN1_GENERALIZEDTIME failed
142 # - if a copy of the time data from timestamp cannot be made for
143 # the newly allocated ASN1_GENERALIZEDTIME
144 #
145 # These are difficult to test. cffi enforces the ASN1_TIME type.
146 # Memory allocation failures are a pain to trigger
147 # deterministically.
148 _untested_error("ASN1_TIME_to_generalizedtime")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800149 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500150 string_timestamp = _ffi.cast(
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800151 "ASN1_STRING*", generalized_timestamp[0])
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500152 string_data = _lib.ASN1_STRING_data(string_timestamp)
153 string_result = _ffi.string(string_data)
154 _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0])
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800155 return string_result
156
157
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800158class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200159 """
160 A class representing an DSA or RSA public key or key pair.
161 """
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800162 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800163 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800164
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800165 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500166 pkey = _lib.EVP_PKEY_new()
167 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800168 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800169
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800170 def generate_key(self, type, bits):
171 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700172 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800173
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200174 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800175
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200176 :param type: The key type.
177 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
178 :param bits: The number of bits.
179 :type bits: :py:data:`int` ``>= 0``
180 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
181 of the appropriate type.
182 :raises ValueError: If the number of bits isn't an integer of
183 the appropriate size.
Dan Sully44e767a2016-06-04 18:05:27 -0700184 :return: ``None``
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800185 """
186 if not isinstance(type, int):
187 raise TypeError("type must be an integer")
188
189 if not isinstance(bits, int):
190 raise TypeError("bits must be an integer")
191
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800192 # TODO Check error return
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500193 exponent = _lib.BN_new()
194 exponent = _ffi.gc(exponent, _lib.BN_free)
195 _lib.BN_set_word(exponent, _lib.RSA_F4)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800196
197 if type == TYPE_RSA:
198 if bits <= 0:
199 raise ValueError("Invalid number of bits")
200
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500201 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800202
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500203 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400204 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800205
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500206 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400207 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800208
209 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400210 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700211 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400212
213 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400214 res = _lib.DSA_generate_parameters_ex(
215 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
216 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700217 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400218
219 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
220 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800221 else:
222 raise Error("No such key type")
223
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800224 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800225
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800226 def check(self):
227 """
228 Check the consistency of an RSA private key.
229
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200230 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
231
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800232 :return: True if key is consistent.
233 :raise Error: if the key is inconsistent.
234 :raise TypeError: if the key is of a type which cannot be checked.
235 Only RSA keys can currently be checked.
236 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800237 if self._only_public:
238 raise TypeError("public key only")
239
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100240 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800241 raise TypeError("key type unsupported")
242
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500243 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
244 rsa = _ffi.gc(rsa, _lib.RSA_free)
245 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800246 if result:
247 return True
248 _raise_current_error()
249
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800250 def type(self):
251 """
252 Returns the type of the key
253
254 :return: The type of the key.
255 """
Alex Gaynorc84567b2016-03-16 07:45:09 -0400256 return _lib.Cryptography_EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800257
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800258 def bits(self):
259 """
260 Returns the number of bits of the key
261
262 :return: The number of bits of the key.
263 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500264 return _lib.EVP_PKEY_bits(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800265PKeyType = PKey
266
267
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400268class _EllipticCurve(object):
269 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400270 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400271
272 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
273 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
274 instances each of which represents one curve supported by the system.
275 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400276 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400277 _curves = None
278
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400279 if _PY3:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400280 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400281 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400282 """
283 Implement cooperation with the right-hand side argument of ``!=``.
284
285 Python 3 seems to have dropped this cooperation in this very narrow
286 circumstance.
287 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400288 if isinstance(other, _EllipticCurve):
289 return super(_EllipticCurve, self).__ne__(other)
290 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400291
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400292 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400293 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400294 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400295 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400296
297 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400298
299 :return: A :py:type:`set` of ``cls`` instances giving the names of the
300 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400301 """
302 if lib.Cryptography_HAS_EC:
303 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
304 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
Alex Gaynor5945ea82015-09-05 14:59:06 -0400305 # The return value on this call should be num_curves again. We
306 # could check it to make sure but if it *isn't* then.. what could
307 # we do? Abort the whole process, I suppose...? -exarkun
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400308 lib.EC_get_builtin_curves(builtin_curves, num_curves)
309 return set(
310 cls.from_nid(lib, c.nid)
311 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400312 return set()
313
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400314 @classmethod
315 def _get_elliptic_curves(cls, lib):
316 """
317 Get, cache, and return the curves supported by OpenSSL.
318
319 :param lib: The OpenSSL library binding object.
320
321 :return: A :py:type:`set` of ``cls`` instances giving the names of the
322 elliptic curves the underlying library supports.
323 """
324 if cls._curves is None:
325 cls._curves = cls._load_elliptic_curves(lib)
326 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400327
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400328 @classmethod
329 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400330 """
331 Instantiate a new :py:class:`_EllipticCurve` associated with the given
332 OpenSSL NID.
333
334 :param lib: The OpenSSL library binding object.
335
336 :param nid: The OpenSSL NID the resulting curve object will represent.
337 This must be a curve NID (and not, for example, a hash NID) or
338 subsequent operations will fail in unpredictable ways.
339 :type nid: :py:class:`int`
340
341 :return: The curve object.
342 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400343 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
344
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400345 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400346 """
347 :param _lib: The :py:mod:`cryptography` binding instance used to
348 interface with OpenSSL.
349
350 :param _nid: The OpenSSL NID identifying the curve this object
351 represents.
352 :type _nid: :py:class:`int`
353
354 :param name: The OpenSSL short name identifying the curve this object
355 represents.
356 :type name: :py:class:`unicode`
357 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400358 self._lib = lib
359 self._nid = nid
360 self.name = name
361
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400362 def __repr__(self):
363 return "<Curve %r>" % (self.name,)
364
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400365 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400366 """
367 Create a new OpenSSL EC_KEY structure initialized to use this curve.
368
369 The structure is automatically garbage collected when the Python object
370 is garbage collected.
371 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400372 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
373 return _ffi.gc(key, _lib.EC_KEY_free)
374
375
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400376def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400377 """
378 Return a set of objects representing the elliptic curves supported in the
379 OpenSSL build in use.
380
381 The curve objects have a :py:class:`unicode` ``name`` attribute by which
382 they identify themselves.
383
384 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400385 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
386 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400387 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400388 return _EllipticCurve._get_elliptic_curves(_lib)
389
390
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400391def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400392 """
393 Return a single curve object selected by name.
394
395 See :py:func:`get_elliptic_curves` for information about curve objects.
396
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400397 :param name: The OpenSSL short name identifying the curve object to
398 retrieve.
399 :type name: :py:class:`unicode`
400
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400401 If the named curve is not supported then :py:class:`ValueError` is raised.
402 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400403 for curve in get_elliptic_curves():
404 if curve.name == name:
405 return curve
406 raise ValueError("unknown curve name", name)
407
408
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800409class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200410 """
411 An X.509 Distinguished Name.
412
413 :ivar countryName: The country of the entity.
414 :ivar C: Alias for :py:attr:`countryName`.
415
416 :ivar stateOrProvinceName: The state or province of the entity.
417 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
418
419 :ivar localityName: The locality of the entity.
420 :ivar L: Alias for :py:attr:`localityName`.
421
422 :ivar organizationName: The organization name of the entity.
423 :ivar O: Alias for :py:attr:`organizationName`.
424
425 :ivar organizationalUnitName: The organizational unit of the entity.
426 :ivar OU: Alias for :py:attr:`organizationalUnitName`
427
428 :ivar commonName: The common name of the entity.
429 :ivar CN: Alias for :py:attr:`commonName`.
430
431 :ivar emailAddress: The e-mail address of the entity.
432 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400433
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800434 def __init__(self, name):
435 """
436 Create a new X509Name, copying the given X509Name instance.
437
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200438 :param name: The name to copy.
439 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800440 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500441 name = _lib.X509_NAME_dup(name._name)
442 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800443
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800444 def __setattr__(self, name, value):
445 if name.startswith('_'):
446 return super(X509Name, self).__setattr__(name, value)
447
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800448 # Note: we really do not want str subclasses here, so we do not use
449 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800450 if type(name) is not str:
451 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400452 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800453
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500454 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500455 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800456 try:
457 _raise_current_error()
458 except Error:
459 pass
460 raise AttributeError("No such attribute")
461
462 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500463 for i in range(_lib.X509_NAME_entry_count(self._name)):
464 ent = _lib.X509_NAME_get_entry(self._name, i)
465 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
466 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800467 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500468 ent = _lib.X509_NAME_delete_entry(self._name, i)
469 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800470 break
471
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500472 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800473 value = value.encode('utf-8')
474
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500475 add_result = _lib.X509_NAME_add_entry_by_NID(
476 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800477 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500478 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800479
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800480 def __getattr__(self, name):
481 """
482 Find attribute. An X509Name object has the following attributes:
483 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400484 organization (alias O), organizationalUnit (alias OU), commonName
485 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800486 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500487 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500488 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800489 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
490 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
491 # push something onto the error queue. If we don't clean that up
492 # now, someone else will bump into it later and be quite confused.
493 # See lp#314814.
494 try:
495 _raise_current_error()
496 except Error:
497 pass
498 return super(X509Name, self).__getattr__(name)
499
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500500 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800501 if entry_index == -1:
502 return None
503
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500504 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
505 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800506
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500507 result_buffer = _ffi.new("unsigned char**")
508 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400509 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800510
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700511 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400512 result = _ffi.buffer(
513 result_buffer[0], data_length
514 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700515 finally:
516 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500517 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800518 return result
519
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500520 def _cmp(op):
521 def f(self, other):
522 if not isinstance(other, X509Name):
523 return NotImplemented
524 result = _lib.X509_NAME_cmp(self._name, other._name)
525 return op(result, 0)
526 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800527
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500528 __eq__ = _cmp(__eq__)
529 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800530
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500531 __lt__ = _cmp(__lt__)
532 __le__ = _cmp(__le__)
533
534 __gt__ = _cmp(__gt__)
535 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800536
537 def __repr__(self):
538 """
539 String representation of an X509Name
540 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400541 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500542 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800543 self._name, result_buffer, len(result_buffer))
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700544 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800545
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500546 return "<X509Name object '%s'>" % (
547 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800548
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800549 def hash(self):
550 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200551 Return an integer representation of the first four bytes of the
552 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800553
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200554 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
555
556 :return: The (integer) hash of this name.
557 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800558 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500559 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800560
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800561 def der(self):
562 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200563 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800564
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200565 :return: The DER encoded form of this name.
566 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800567 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500568 result_buffer = _ffi.new('unsigned char**')
569 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400570 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800571
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500572 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
573 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800574 return string_result
575
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800576 def get_components(self):
577 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200578 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800579
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200580 :return: The components of this name.
581 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800582 """
583 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500584 for i in range(_lib.X509_NAME_entry_count(self._name)):
585 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800586
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500587 fname = _lib.X509_NAME_ENTRY_get_object(ent)
588 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800589
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500590 nid = _lib.OBJ_obj2nid(fname)
591 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800592
593 result.append((
Alex Gaynora738ed52015-09-05 11:17:10 -0400594 _ffi.string(name),
595 _ffi.string(
596 _lib.ASN1_STRING_data(fval),
597 _lib.ASN1_STRING_length(fval))))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800598
599 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200600
601
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800602X509NameType = X509Name
603
604
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800605class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200606 """
607 An X.509 v3 certificate extension.
608 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400609
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800610 def __init__(self, type_name, critical, value, subject=None, issuer=None):
611 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200612 Initializes an X509 extension.
613
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100614 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400615 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800616
Alex Gaynor5945ea82015-09-05 14:59:06 -0400617 :param bool critical: A flag indicating whether this is a critical
618 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800619
620 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200621 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800622
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200623 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800624 :type subject: :py:class:`X509`
625
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200626 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800627 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100628
629 .. _extension: https://openssl.org/docs/manmaster/apps/
630 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800631 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500632 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800633
Alex Gaynor5945ea82015-09-05 14:59:06 -0400634 # A context is necessary for any extension which uses the r2i
635 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
636 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500637 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800638
639 # We have no configuration database - but perhaps we should (some
640 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500641 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800642
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800643 # Initialize the subject and issuer, if appropriate. ctx is a local,
644 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400645 # any references, so no need to mess with reference counts or
646 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800647 if issuer is not None:
648 if not isinstance(issuer, X509):
649 raise TypeError("issuer must be an X509 instance")
650 ctx.issuer_cert = issuer._x509
651 if subject is not None:
652 if not isinstance(subject, X509):
653 raise TypeError("subject must be an X509 instance")
654 ctx.subject_cert = subject._x509
655
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800656 if critical:
657 # There are other OpenSSL APIs which would let us pass in critical
658 # separately, but they're harder to use, and since value is already
659 # a pile of crappy junk smuggling a ton of utterly important
660 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400661 # with strings? (However, X509V3_EXT_i2d in particular seems like
662 # it would be a better API to invoke. I do not know where to get
663 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500664 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800665
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500666 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
667 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800668 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500669 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800670
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400671 @property
672 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400673 return _lib.OBJ_obj2nid(
674 _lib.X509_EXTENSION_get_object(self._extension)
675 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400676
677 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500678 _lib.GEN_EMAIL: "email",
679 _lib.GEN_DNS: "DNS",
680 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400681 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400682
683 def _subjectAltNameString(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500684 method = _lib.X509V3_EXT_get(self._extension)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700685 _openssl_assert(method != _ffi.NULL)
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400686 ext_data = _lib.X509_EXTENSION_get_data(self._extension)
687 payload = ext_data.data
688 length = ext_data.length
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400689
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500690 payloadptr = _ffi.new("unsigned char**")
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400691 payloadptr[0] = payload
692
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500693 if method.it != _ffi.NULL:
694 ptr = _lib.ASN1_ITEM_ptr(method.it)
695 data = _lib.ASN1_item_d2i(_ffi.NULL, payloadptr, length, ptr)
696 names = _ffi.cast("GENERAL_NAMES*", data)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400697 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500698 names = _ffi.cast(
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400699 "GENERAL_NAMES*",
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500700 method.d2i(_ffi.NULL, payloadptr, length))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400701
Paul Kehrerb7d79502015-05-04 07:43:51 -0500702 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400703 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500704 for i in range(_lib.sk_GENERAL_NAME_num(names)):
705 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400706 try:
707 label = self._prefixes[name.type]
708 except KeyError:
709 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500710 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500711 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400712 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500713 value = _native(
714 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
715 parts.append(label + ":" + value)
716 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400717
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800718 def __str__(self):
719 """
720 :return: a nice text representation of the extension
721 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500722 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400723 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800724
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400725 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500726 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400727 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800728
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500729 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800730
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800731 def get_critical(self):
732 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200733 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800734
735 :return: The critical field.
736 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500737 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800738
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800739 def get_short_name(self):
740 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200741 Returns the short type name of this X.509 extension.
742
743 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800744
745 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200746 :rtype: :py:data:`bytes`
747
748 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800749 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500750 obj = _lib.X509_EXTENSION_get_object(self._extension)
751 nid = _lib.OBJ_obj2nid(obj)
752 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800753
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800754 def get_data(self):
755 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200756 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800757
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200758 :return: The ASN.1 encoded data of this X509 extension.
759 :rtype: :py:data:`bytes`
760
761 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800762 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500763 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
764 string_result = _ffi.cast('ASN1_STRING*', octet_result)
765 char_result = _lib.ASN1_STRING_data(string_result)
766 result_length = _lib.ASN1_STRING_length(string_result)
767 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800768
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200769
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800770X509ExtensionType = X509Extension
771
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800772
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800773class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200774 """
775 An X.509 certificate signing requests.
776 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400777
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800778 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500779 req = _lib.X509_REQ_new()
780 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800781
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800782 def set_pubkey(self, pkey):
783 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200784 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800785
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200786 :param pkey: The public key to use.
787 :type pkey: :py:class:`PKey`
788
Dan Sully44e767a2016-06-04 18:05:27 -0700789 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800790 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500791 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400792 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800793
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800794 def get_pubkey(self):
795 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200796 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800797
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200798 :return: The public key.
799 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800800 """
801 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500802 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700803 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500804 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800805 pkey._only_public = True
806 return pkey
807
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800808 def set_version(self, version):
809 """
810 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
811 request.
812
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200813 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700814 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800815 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500816 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400817 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800818
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800819 def get_version(self):
820 """
821 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
822 request.
823
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200824 :return: The value of the version subfield.
825 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800826 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500827 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800828
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800829 def get_subject(self):
830 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200831 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800832
Cory Benfield881dc8d2015-12-09 08:25:14 +0000833 This creates a new :class:`X509Name` that wraps the underlying subject
834 name field on the certificate signing request. Modifying it will modify
835 the underlying signing request, and will have the effect of modifying
836 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200837
838 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000839 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800840 """
841 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500842 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700843 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800844
845 # The name is owned by the X509Req structure. As long as the X509Name
846 # Python object is alive, keep the X509Req Python object alive.
847 name._owner = self
848
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800849 return name
850
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800851 def add_extensions(self, extensions):
852 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200853 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800854
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200855 :param extensions: The X.509 extensions to add.
856 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700857 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800858 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500859 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700860 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800861
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500862 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800863
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800864 for ext in extensions:
865 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -0800866 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800867
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800868 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500869 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800870
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500871 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400872 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800873
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800874 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800875 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200876 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800877
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200878 :return: The X.509 extensions in this request.
879 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
880
881 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800882 """
883 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500884 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -0500885 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800886 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500887 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800888 exts.append(ext)
889 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800890
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800891 def sign(self, pkey, digest):
892 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -0700893 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800894
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200895 :param pkey: The key pair to sign with.
896 :type pkey: :py:class:`PKey`
897 :param digest: The name of the message digest to use for the signature,
898 e.g. :py:data:`b"sha1"`.
899 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -0700900 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800901 """
902 if pkey._only_public:
903 raise ValueError("Key has only public part")
904
905 if not pkey._initialized:
906 raise ValueError("Key is uninitialized")
907
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500908 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500909 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800910 raise ValueError("No such digest method")
911
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500912 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400913 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800914
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800915 def verify(self, pkey):
916 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200917 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800918
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200919 :param key: A public key.
920 :type key: :py:class:`PKey`
921 :return: :py:data:`True` if the signature is correct.
922 :rtype: :py:class:`bool`
923 :raises Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800924 problem verifying the signature.
925 """
926 if not isinstance(pkey, PKey):
927 raise TypeError("pkey must be a PKey instance")
928
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500929 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800930 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500931 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800932
933 return result
934
935
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800936X509ReqType = X509Req
937
938
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800939class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200940 """
941 An X.509 certificate.
942 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400943
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800944 def __init__(self):
945 # TODO Allocation failure? And why not __new__ instead of __init__?
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500946 x509 = _lib.X509_new()
947 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800948
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800949 def set_version(self, version):
950 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200951 Set the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800952
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200953 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800954 :type version: :py:class:`int`
955
Dan Sully44e767a2016-06-04 18:05:27 -0700956 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800957 """
958 if not isinstance(version, int):
959 raise TypeError("version must be an integer")
960
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500961 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800962
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800963 def get_version(self):
964 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200965 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800966
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200967 :return: The version number of the certificate.
968 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800969 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500970 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800971
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800972 def get_pubkey(self):
973 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200974 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800975
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200976 :return: The public key.
977 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800978 """
979 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500980 pkey._pkey = _lib.X509_get_pubkey(self._x509)
981 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800982 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500983 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800984 pkey._only_public = True
985 return pkey
986
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800987 def set_pubkey(self, pkey):
988 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200989 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800990
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200991 :param pkey: The public key.
992 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800993
Laurens Van Houtven33fcf122015-04-23 10:50:08 -0700994 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800995 """
996 if not isinstance(pkey, PKey):
997 raise TypeError("pkey must be a PKey instance")
998
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500999 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001000 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001001
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001002 def sign(self, pkey, digest):
1003 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001004 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001005
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001006 :param pkey: The key to sign with.
1007 :type pkey: :py:class:`PKey`
1008
1009 :param digest: The name of the message digest to use.
1010 :type digest: :py:class:`bytes`
1011
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001012 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001013 """
1014 if not isinstance(pkey, PKey):
1015 raise TypeError("pkey must be a PKey instance")
1016
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001017 if pkey._only_public:
1018 raise ValueError("Key only has public part")
1019
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001020 if not pkey._initialized:
1021 raise ValueError("Key is uninitialized")
1022
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001023 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001024 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001025 raise ValueError("No such digest method")
1026
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001027 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001028 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001029
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001030 def get_signature_algorithm(self):
1031 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001032 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001033
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001034 :return: The name of the algorithm.
1035 :rtype: :py:class:`bytes`
1036
1037 :raises ValueError: If the signature algorithm is undefined.
1038
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001039 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001040 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001041 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1042 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001043 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001044 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001045 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001046
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001047 def digest(self, digest_name):
1048 """
1049 Return the digest of the X509 object.
1050
1051 :param digest_name: The name of the digest algorithm to use.
1052 :type digest_name: :py:class:`bytes`
1053
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001054 :return: The digest of the object, formatted as
1055 :py:const:`b":"`-delimited hex pairs.
1056 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001057 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001058 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001059 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001060 raise ValueError("No such digest method")
1061
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001062 result_buffer = _ffi.new("char[]", _lib.EVP_MAX_MD_SIZE)
1063 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001064 result_length[0] = len(result_buffer)
1065
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001066 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001067 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001068 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001069
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001070 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001071 b16encode(ch).upper() for ch
1072 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001073
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001074 def subject_name_hash(self):
1075 """
1076 Return the hash of the X509 subject.
1077
1078 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001079 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001080 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001081 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001082
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001083 def set_serial_number(self, serial):
1084 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001085 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001086
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001087 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001088 :type serial: :py:class:`int`
1089
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001090 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001091 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001092 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001093 raise TypeError("serial must be an integer")
1094
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001095 hex_serial = hex(serial)[2:]
1096 if not isinstance(hex_serial, bytes):
1097 hex_serial = hex_serial.encode('ascii')
1098
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001099 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001100
1101 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001102 # it. If bignum is still NULL after this call, then the return value
1103 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001104 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001105
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001106 if bignum_serial[0] == _ffi.NULL:
1107 set_result = _lib.ASN1_INTEGER_set(
1108 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001109 if set_result:
1110 # TODO Not tested
1111 _raise_current_error()
1112 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001113 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1114 _lib.BN_free(bignum_serial[0])
1115 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001116 # TODO Not tested
1117 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001118 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1119 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001120 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001121
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001122 def get_serial_number(self):
1123 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001124 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001125
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001126 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001127 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001128 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001129 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1130 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001131 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001132 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001133 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001134 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001135 serial = int(hexstring_serial, 16)
1136 return serial
1137 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001138 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001139 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001140 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001141
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001142 def gmtime_adj_notAfter(self, amount):
1143 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001144 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001145
Dan Sully44e767a2016-06-04 18:05:27 -07001146 :param int amount: The number of seconds by which to adjust the
1147 timestamp.
1148 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001149 """
1150 if not isinstance(amount, int):
1151 raise TypeError("amount must be an integer")
1152
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001153 notAfter = _lib.X509_get_notAfter(self._x509)
1154 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001155
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001156 def gmtime_adj_notBefore(self, amount):
1157 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001158 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001159
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001160 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001161 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001162 """
1163 if not isinstance(amount, int):
1164 raise TypeError("amount must be an integer")
1165
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001166 notBefore = _lib.X509_get_notBefore(self._x509)
1167 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001168
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001169 def has_expired(self):
1170 """
1171 Check whether the certificate has expired.
1172
Dan Sully44e767a2016-06-04 18:05:27 -07001173 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1174 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001175 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001176 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001177 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001178
Paul Kehrerfde45c92016-01-21 12:57:37 -06001179 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001180
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001181 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001182 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001183
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001184 def get_notBefore(self):
1185 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001186 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001187
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001188 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001189
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001190 YYYYMMDDhhmmssZ
1191 YYYYMMDDhhmmss+hhmm
1192 YYYYMMDDhhmmss-hhmm
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001193
Dan Sully44e767a2016-06-04 18:05:27 -07001194 :return: A timestamp string, or ``None`` if there is none.
1195 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001196 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001197 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001198
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001199 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001200 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001201
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001202 def set_notBefore(self, when):
1203 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001204 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001205
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001206 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001207
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001208 YYYYMMDDhhmmssZ
1209 YYYYMMDDhhmmss+hhmm
1210 YYYYMMDDhhmmss-hhmm
1211
Dan Sully44e767a2016-06-04 18:05:27 -07001212 :param bytes when: A timestamp string.
1213 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001214 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001215 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001216
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001217 def get_notAfter(self):
1218 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001219 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001220
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001221 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001222
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001223 YYYYMMDDhhmmssZ
1224 YYYYMMDDhhmmss+hhmm
1225 YYYYMMDDhhmmss-hhmm
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001226
Dan Sully44e767a2016-06-04 18:05:27 -07001227 :return: A timestamp string, or ``None`` if there is none.
1228 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001229 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001230 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001231
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001232 def set_notAfter(self, when):
1233 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001234 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001235
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001236 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001237
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001238 YYYYMMDDhhmmssZ
1239 YYYYMMDDhhmmss+hhmm
1240 YYYYMMDDhhmmss-hhmm
1241
Dan Sully44e767a2016-06-04 18:05:27 -07001242 :param bytes when: A timestamp string.
1243 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001244 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001245 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001246
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001247 def _get_name(self, which):
1248 name = X509Name.__new__(X509Name)
1249 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001250 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001251
1252 # The name is owned by the X509 structure. As long as the X509Name
1253 # Python object is alive, keep the X509 Python object alive.
1254 name._owner = self
1255
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001256 return name
1257
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001258 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001259 if not isinstance(name, X509Name):
1260 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001261 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001262 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001263
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001264 def get_issuer(self):
1265 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001266 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001267
Cory Benfielde6bcce82015-12-09 08:40:03 +00001268 This creates a new :class:`X509Name` that wraps the underlying issuer
1269 name field on the certificate. Modifying it will modify the underlying
1270 certificate, and will have the effect of modifying any other
1271 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001272
1273 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001274 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001275 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001276 return self._get_name(_lib.X509_get_issuer_name)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001277
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001278 def set_issuer(self, issuer):
1279 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001280 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001281
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001282 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001283 :type issuer: :py:class:`X509Name`
1284
Dan Sully44e767a2016-06-04 18:05:27 -07001285 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001286 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001287 return self._set_name(_lib.X509_set_issuer_name, issuer)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001288
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001289 def get_subject(self):
1290 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001291 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001292
Cory Benfielde6bcce82015-12-09 08:40:03 +00001293 This creates a new :class:`X509Name` that wraps the underlying subject
1294 name field on the certificate. Modifying it will modify the underlying
1295 certificate, and will have the effect of modifying any other
1296 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001297
1298 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001299 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001300 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001301 return self._get_name(_lib.X509_get_subject_name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001302
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001303 def set_subject(self, subject):
1304 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001305 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001306
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001307 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001308 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001309
Dan Sully44e767a2016-06-04 18:05:27 -07001310 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001311 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001312 return self._set_name(_lib.X509_set_subject_name, subject)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001313
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001314 def get_extension_count(self):
1315 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001316 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001317
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001318 :return: The number of extensions.
1319 :rtype: :py:class:`int`
1320
1321 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001322 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001323 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001324
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001325 def add_extensions(self, extensions):
1326 """
1327 Add extensions to the certificate.
1328
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001329 :param extensions: The extensions to add.
1330 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001331 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001332 """
1333 for ext in extensions:
1334 if not isinstance(ext, X509Extension):
1335 raise ValueError("One of the elements is not an X509Extension")
1336
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001337 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001338 if not add_result:
1339 _raise_current_error()
1340
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001341 def get_extension(self, index):
1342 """
1343 Get a specific extension of the certificate by index.
1344
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001345 Extensions on a certificate are kept in order. The index
1346 parameter selects which extension will be returned.
1347
1348 :param int index: The index of the extension to retrieve.
1349 :return: The extension at the specified index.
1350 :rtype: :py:class:`X509Extension`
1351 :raises IndexError: If the extension index was out of bounds.
1352
1353 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001354 """
1355 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001356 ext._extension = _lib.X509_get_ext(self._x509, index)
1357 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001358 raise IndexError("extension index out of bounds")
1359
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001360 extension = _lib.X509_EXTENSION_dup(ext._extension)
1361 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001362 return ext
1363
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001364
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001365X509Type = X509
1366
1367
Dan Sully44e767a2016-06-04 18:05:27 -07001368class X509StoreFlags(object):
1369 """
1370 Flags for X509 verification, used to change the behavior of
1371 :class:`X509Store`.
1372
1373 See `OpenSSL Verification Flags`_ for details.
1374
1375 .. _OpenSSL Verification Flags:
1376 https://www.openssl.org/docs/manmaster/crypto/X509_VERIFY_PARAM_set_flags.html
1377 """
1378 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1379 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1380 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1381 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1382 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1383 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1384 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1385 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1386 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1387 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1388 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1389
1390
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001391class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001392 """
Dan Sully44e767a2016-06-04 18:05:27 -07001393 An X.509 store.
1394
1395 An X.509 store is used to describe a context in which to verify a
1396 certificate. A description of a context may include a set of certificates
1397 to trust, a set of certificate revocation lists, verification flags and
1398 more.
1399
1400 An X.509 store, being only a description, cannot be used by itself to
1401 verify a certificate. To carry out the actual verification process, see
1402 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001403 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001404
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001405 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001406 store = _lib.X509_STORE_new()
1407 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001408
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001409 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001410 """
Dan Sully44e767a2016-06-04 18:05:27 -07001411 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001412
Dan Sully44e767a2016-06-04 18:05:27 -07001413 Adding a certificate with this method adds this certificate as a
1414 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001415
1416 :param X509 cert: The certificate to add to this store.
Dan Sully44e767a2016-06-04 18:05:27 -07001417 :raises TypeError: If the certificate is not an :class:`X509`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001418 :raises Error: If OpenSSL was unhappy with your certificate.
Dan Sully44e767a2016-06-04 18:05:27 -07001419 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001420 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001421 if not isinstance(cert, X509):
1422 raise TypeError()
1423
Dan Sully44e767a2016-06-04 18:05:27 -07001424 _openssl_assert(_lib.X509_STORE_add_cert(self._store, cert._x509) != 0)
1425
1426 def add_crl(self, crl):
1427 """
1428 Add a certificate revocation list to this store.
1429
1430 The certificate revocation lists added to a store will only be used if
1431 the associated flags are configured to check certificate revocation
1432 lists.
1433
1434 .. versionadded:: 16.1.0
1435
1436 :param CRL crl: The certificate revocation list to add to this store.
1437 :return: ``None`` if the certificate revocation list was added
1438 successfully.
1439 """
1440 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1441
1442 def set_flags(self, flags):
1443 """
1444 Set verification flags to this store.
1445
1446 Verification flags can be combined by oring them together.
1447
1448 .. note::
1449
1450 Setting a verification flag sometimes requires clients to add
1451 additional information to the store, otherwise a suitable error will
1452 be raised.
1453
1454 For example, in setting flags to enable CRL checking a
1455 suitable CRL must be added to the store otherwise an error will be
1456 raised.
1457
1458 .. versionadded:: 16.1.0
1459
1460 :param int flags: The verification flags to set on this store.
1461 See :class:`X509StoreFlags` for available constants.
1462 :return: ``None`` if the verification flags were successfully set.
1463 """
1464 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001465
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001466
1467X509StoreType = X509Store
1468
1469
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001470class X509StoreContextError(Exception):
1471 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001472 An exception raised when an error occurred while verifying a certificate
1473 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001474
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001475 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001476 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001477 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001478
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001479 def __init__(self, message, certificate):
1480 super(X509StoreContextError, self).__init__(message)
1481 self.certificate = certificate
1482
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001483
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001484class X509StoreContext(object):
1485 """
1486 An X.509 store context.
1487
Dan Sully44e767a2016-06-04 18:05:27 -07001488 An X.509 store context is used to carry out the actual verification process
1489 of a certificate in a described context. For describing such a context, see
1490 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001491
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001492 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1493 instance. It is dynamically allocated and automatically garbage
1494 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001495 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001496 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001497 :param X509Store store: The certificates which will be trusted for the
1498 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001499 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001500 """
1501
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001502 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001503 store_ctx = _lib.X509_STORE_CTX_new()
1504 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1505 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001506 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001507 # Make the store context available for use after instantiating this
1508 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001509 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001510 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001511
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001512 def _init(self):
1513 """
1514 Set up the store context for a subsequent verification operation.
1515 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001516 ret = _lib.X509_STORE_CTX_init(
1517 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1518 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001519 if ret <= 0:
1520 _raise_current_error()
1521
1522 def _cleanup(self):
1523 """
1524 Internally cleans up the store context.
1525
Dan Sully44e767a2016-06-04 18:05:27 -07001526 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001527 """
1528 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1529
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001530 def _exception_from_context(self):
1531 """
1532 Convert an OpenSSL native context error failure into a Python
1533 exception.
1534
Alex Gaynor5945ea82015-09-05 14:59:06 -04001535 When a call to native OpenSSL X509_verify_cert fails, additional
1536 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001537 """
1538 errors = [
1539 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1540 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1541 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001542 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001543 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001544 # A context error should always be associated with a certificate, so we
1545 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001546 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001547 _cert = _lib.X509_dup(_x509)
1548 pycert = X509.__new__(X509)
1549 pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001550 return X509StoreContextError(errors, pycert)
1551
Stephen Holsapple46a09252015-02-12 14:45:43 -08001552 def set_store(self, store):
1553 """
Dan Sully44e767a2016-06-04 18:05:27 -07001554 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001555
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001556 .. versionadded:: 0.15
1557
Dan Sully44e767a2016-06-04 18:05:27 -07001558 :param X509Store store: The store description which will be used for
1559 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001560 """
1561 self._store = store
1562
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001563 def verify_certificate(self):
1564 """
1565 Verify a certificate in a context.
1566
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001567 .. versionadded:: 0.15
1568
Alex Gaynorca87ff62015-09-04 23:31:03 -04001569 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001570 certificate in the context. Sets ``certificate`` attribute to
1571 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001572 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001573 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001574 # :meth:`verify_certificate` is called multiple times.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001575 self._init()
1576 ret = _lib.X509_verify_cert(self._store_ctx)
1577 self._cleanup()
1578 if ret <= 0:
1579 raise self._exception_from_context()
1580
1581
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001582def load_certificate(type, buffer):
1583 """
1584 Load a certificate from a buffer
1585
1586 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1587
Dan Sully44e767a2016-06-04 18:05:27 -07001588 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001589
1590 :return: The X509 object
1591 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001592 if isinstance(buffer, _text_type):
1593 buffer = buffer.encode("ascii")
1594
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001595 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001596
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001597 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001598 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001599 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001600 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001601 else:
1602 raise ValueError(
1603 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001604
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001605 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001606 _raise_current_error()
1607
1608 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001609 cert._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001610 return cert
1611
1612
1613def dump_certificate(type, cert):
1614 """
1615 Dump a certificate to a buffer
1616
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001617 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1618 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001619 :param cert: The certificate to dump
1620 :return: The buffer with the dumped certificate in
1621 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001622 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001623
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001624 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001625 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001626 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001627 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001628 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001629 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001630 else:
1631 raise ValueError(
1632 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1633 "FILETYPE_TEXT")
1634
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001635 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001636 return _bio_to_string(bio)
1637
1638
Cory Benfield6492f7c2015-10-27 16:57:58 +09001639def dump_publickey(type, pkey):
1640 """
Cory Benfield11c10192015-10-27 17:23:03 +09001641 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001642
Cory Benfield9c590b92015-10-28 14:55:05 +09001643 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001644 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001645 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001646 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001647 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001648 """
1649 bio = _new_mem_buf()
1650 if type == FILETYPE_PEM:
1651 write_bio = _lib.PEM_write_bio_PUBKEY
1652 elif type == FILETYPE_ASN1:
1653 write_bio = _lib.i2d_PUBKEY_bio
1654 else:
1655 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1656
1657 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001658 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001659 _raise_current_error()
1660
1661 return _bio_to_string(bio)
1662
1663
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001664def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1665 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001666 Dump the private key *pkey* into a buffer string encoded with the type
1667 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1668 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001669
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001670 :param type: The file type (one of :const:`FILETYPE_PEM`,
1671 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1672 :param PKey pkey: The PKey to dump
1673 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001674 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001675 the passphrase to use, or a callback for providing the passphrase.
1676
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001677 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001678 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001679 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001680 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001681
1682 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001683 if passphrase is None:
1684 raise TypeError(
1685 "if a value is given for cipher "
1686 "one must also be given for passphrase")
1687 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001688 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001689 raise ValueError("Invalid cipher name")
1690 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001691 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001692
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001693 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001694 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001695 result_code = _lib.PEM_write_bio_PrivateKey(
1696 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001697 helper.callback, helper.callback_args)
1698 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001699 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001700 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001701 elif type == FILETYPE_TEXT:
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001702 rsa = _ffi.gc(
1703 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1704 _lib.RSA_free
1705 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001706 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001707 else:
1708 raise ValueError(
1709 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1710 "FILETYPE_TEXT")
1711
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001712 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001713
1714 return _bio_to_string(bio)
1715
1716
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001717class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001718 """
1719 A certificate revocation.
1720 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001721 # http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_
1722 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1723 # OCSP_crl_reason_str. We use the latter, just like the command line
1724 # program.
1725 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001726 b"unspecified",
1727 b"keyCompromise",
1728 b"CACompromise",
1729 b"affiliationChanged",
1730 b"superseded",
1731 b"cessationOfOperation",
1732 b"certificateHold",
1733 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001734 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001735
1736 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001737 revoked = _lib.X509_REVOKED_new()
1738 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001739
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001740 def set_serial(self, hex_str):
1741 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001742 Set the serial number.
1743
1744 The serial number is formatted as a hexadecimal number encoded in
1745 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001746
Dan Sully44e767a2016-06-04 18:05:27 -07001747 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001748
Dan Sully44e767a2016-06-04 18:05:27 -07001749 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001750 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001751 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1752 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001753 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001754 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001755 if not bn_result:
1756 raise ValueError("bad hex string")
1757
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001758 asn1_serial = _ffi.gc(
1759 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1760 _lib.ASN1_INTEGER_free)
1761 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001762
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001763 def get_serial(self):
1764 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001765 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001766
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001767 The serial number is formatted as a hexadecimal number encoded in
1768 ASCII.
1769
1770 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001771 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001772 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001773 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001774
Alex Gaynor67903a62016-06-02 10:37:13 -07001775 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1776 _openssl_assert(asn1_int != _ffi.NULL)
1777 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1778 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001779 return _bio_to_string(bio)
1780
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001781 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001782 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1783 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001784 obj = _lib.X509_EXTENSION_get_object(ext)
1785 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001786 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001787 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001788 break
1789
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001790 def set_reason(self, reason):
1791 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001792 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001793
Dan Sully44e767a2016-06-04 18:05:27 -07001794 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001795
1796 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07001797 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001798
Dan Sully44e767a2016-06-04 18:05:27 -07001799 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001800
1801 .. seealso::
1802
Dan Sully44e767a2016-06-04 18:05:27 -07001803 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001804 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001805 """
1806 if reason is None:
1807 self._delete_reason()
1808 elif not isinstance(reason, bytes):
1809 raise TypeError("reason must be None or a byte string")
1810 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001811 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001812 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
1813
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001814 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07001815 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001816 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001817
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001818 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001819 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001820
1821 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001822 add_result = _lib.X509_REVOKED_add1_ext_i2d(
1823 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001824 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001825
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001826 def get_reason(self):
1827 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04001828 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001829
Dan Sully44e767a2016-06-04 18:05:27 -07001830 :return: The reason, or ``None`` if there is none.
1831 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001832
1833 .. seealso::
1834
Dan Sully44e767a2016-06-04 18:05:27 -07001835 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001836 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001837 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001838 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1839 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001840 obj = _lib.X509_EXTENSION_get_object(ext)
1841 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001842 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001843
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001844 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001845 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04001846 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001847 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04001848 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04001849 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001850
1851 return _bio_to_string(bio)
1852
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001853 def all_reasons(self):
1854 """
1855 Return a list of all the supported reason strings.
1856
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001857 This list is a copy; modifying it does not change the supported reason
1858 strings.
1859
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001860 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07001861 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001862 """
1863 return self._crl_reasons[:]
1864
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001865 def set_rev_date(self, when):
1866 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001867 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001868
Dan Sully44e767a2016-06-04 18:05:27 -07001869 :param bytes when: The timestamp of the revocation,
1870 as ASN.1 GENERALIZEDTIME.
1871 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001872 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001873 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1874 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001875
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001876 def get_rev_date(self):
1877 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001878 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001879
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001880 :return: The timestamp of the revocation, as ASN.1 GENERALIZEDTIME.
Dan Sully44e767a2016-06-04 18:05:27 -07001881 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001882 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001883 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1884 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001885
1886
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001887class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001888 """
1889 A certificate revocation list.
1890 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001891
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001892 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001893 crl = _lib.X509_CRL_new()
1894 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001895
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001896 def get_revoked(self):
1897 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001898 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001899
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001900 These revocations will be provided by value, not by reference.
1901 That means it's okay to mutate them: it won't affect this CRL.
1902
1903 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07001904 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001905 """
1906 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07001907 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001908 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
1909 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04001910 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001911 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001912 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001913 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08001914 if results:
1915 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001916
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001917 def add_revoked(self, revoked):
1918 """
1919 Add a revoked (by value not reference) to the CRL structure
1920
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001921 This revocation will be added by value, not by reference. That
1922 means it's okay to mutate it after adding: it won't affect
1923 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001924
Dan Sully44e767a2016-06-04 18:05:27 -07001925 :param Revoked revoked: The new revocation.
1926 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001927 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04001928 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001929 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001930
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001931 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001932 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001933
Dan Sully44e767a2016-06-04 18:05:27 -07001934 def get_issuer(self):
1935 """
1936 Get the CRL's issuer.
1937
1938 .. versionadded:: 16.1.0
1939
1940 :rtype: X509Name
1941 """
1942 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
1943 _openssl_assert(_issuer != _ffi.NULL)
1944 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
1945 issuer = X509Name.__new__(X509Name)
1946 issuer._name = _issuer
1947 return issuer
1948
1949 def set_version(self, version):
1950 """
1951 Set the CRL version.
1952
1953 .. versionadded:: 16.1.0
1954
1955 :param int version: The version of the CRL.
1956 :return: ``None``
1957 """
1958 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
1959
1960 def _set_boundary_time(self, which, when):
1961 return _set_asn1_time(which(self._crl), when)
1962
1963 def set_lastUpdate(self, when):
1964 """
1965 Set when the CRL was last updated.
1966
1967 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
1968
1969 YYYYMMDDhhmmssZ
1970 YYYYMMDDhhmmss+hhmm
1971 YYYYMMDDhhmmss-hhmm
1972
1973 .. versionadded:: 16.1.0
1974
1975 :param bytes when: A timestamp string.
1976 :return: ``None``
1977 """
1978 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
1979
1980 def set_nextUpdate(self, when):
1981 """
1982 Set when the CRL will next be udpated.
1983
1984 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
1985
1986 YYYYMMDDhhmmssZ
1987 YYYYMMDDhhmmss+hhmm
1988 YYYYMMDDhhmmss-hhmm
1989
1990 .. versionadded:: 16.1.0
1991
1992 :param bytes when: A timestamp string.
1993 :return: ``None``
1994 """
1995 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
1996
1997 def sign(self, issuer_cert, issuer_key, digest):
1998 """
1999 Sign the CRL.
2000
2001 Signing a CRL enables clients to associate the CRL itself with an
2002 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2003 be signed by an issuer.
2004
2005 This method implicitly sets the issuer's name based on the issuer
2006 certificate and private key used to sign the CRL.
2007
2008 .. versionadded:: 16.1.0
2009
2010 :param X509 issuer_cert: The issuer's certificate.
2011 :param PKey issuer_key: The issuer's private key.
2012 :param bytes digest: The digest method to sign the CRL with.
2013 """
2014 digest_obj = _lib.EVP_get_digestbyname(digest)
2015 _openssl_assert(digest_obj != _ffi.NULL)
2016 _lib.X509_CRL_set_issuer_name(
2017 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2018 _lib.X509_CRL_sort(self._crl)
2019 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2020 _openssl_assert(result != 0)
2021
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002022 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002023 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002024 """
Dan Sully44e767a2016-06-04 18:05:27 -07002025 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002026
Dan Sully44e767a2016-06-04 18:05:27 -07002027 :param X509 cert: The certificate used to sign the CRL.
2028 :param PKey key: The key used to sign the CRL.
2029 :param int type: The export format, either :data:`FILETYPE_PEM`,
2030 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002031 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002032 :param bytes digest: The name of the message digest to use (eg
2033 ``b"sha1"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002034 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002035 """
Dan Sully44e767a2016-06-04 18:05:27 -07002036
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002037 if not isinstance(cert, X509):
2038 raise TypeError("cert must be an X509 instance")
2039 if not isinstance(key, PKey):
2040 raise TypeError("key must be a PKey instance")
2041 if not isinstance(type, int):
2042 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002043
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002044 if digest is _UNSPECIFIED:
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002045 _warn(
2046 "The default message digest (md5) is deprecated. "
2047 "Pass the name of a message digest explicitly.",
2048 category=DeprecationWarning,
2049 stacklevel=2,
2050 )
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002051 digest = b"md5"
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002052
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002053 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002054 if digest_obj == _ffi.NULL:
2055 raise ValueError("No such digest method")
2056
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002057 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002058 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002059
Alex Gaynora738ed52015-09-05 11:17:10 -04002060 # A scratch time object to give different values to different CRL
2061 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002062 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002063 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002064
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002065 _lib.X509_gmtime_adj(sometime, 0)
2066 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002067
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002068 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2069 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002070
Alex Gaynor5945ea82015-09-05 14:59:06 -04002071 _lib.X509_CRL_set_issuer_name(
2072 self._crl, _lib.X509_get_subject_name(cert._x509)
2073 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002074
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002075 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002076 if not sign_result:
2077 _raise_current_error()
2078
Dominic Chenf05b2122015-10-13 16:32:35 +00002079 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002080
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002081
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002082CRLType = CRL
2083
2084
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002085class PKCS7(object):
2086 def type_is_signed(self):
2087 """
2088 Check if this NID_pkcs7_signed object
2089
2090 :return: True if the PKCS7 is of type signed
2091 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002092 if _lib.PKCS7_type_is_signed(self._pkcs7):
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002093 return True
2094 return False
2095
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002096 def type_is_enveloped(self):
2097 """
2098 Check if this NID_pkcs7_enveloped object
2099
2100 :returns: True if the PKCS7 is of type enveloped
2101 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002102 if _lib.PKCS7_type_is_enveloped(self._pkcs7):
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002103 return True
2104 return False
2105
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002106 def type_is_signedAndEnveloped(self):
2107 """
2108 Check if this NID_pkcs7_signedAndEnveloped object
2109
2110 :returns: True if the PKCS7 is of type signedAndEnveloped
2111 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002112 if _lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7):
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002113 return True
2114 return False
2115
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002116 def type_is_data(self):
2117 """
2118 Check if this NID_pkcs7_data object
2119
2120 :return: True if the PKCS7 is of type data
2121 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002122 if _lib.PKCS7_type_is_data(self._pkcs7):
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002123 return True
2124 return False
2125
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002126 def get_type_name(self):
2127 """
2128 Returns the type name of the PKCS7 structure
2129
2130 :return: A string with the typename
2131 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002132 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2133 string_type = _lib.OBJ_nid2sn(nid)
2134 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002135
2136PKCS7Type = PKCS7
2137
2138
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002139class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002140 """
2141 A PKCS #12 archive.
2142 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002143
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002144 def __init__(self):
2145 self._pkey = None
2146 self._cert = None
2147 self._cacerts = None
2148 self._friendlyname = None
2149
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002150 def get_certificate(self):
2151 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002152 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002153
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002154 :return: The certificate, or :py:const:`None` if there is none.
2155 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002156 """
2157 return self._cert
2158
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002159 def set_certificate(self, cert):
2160 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002161 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002162
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002163 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002164 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002165
Dan Sully44e767a2016-06-04 18:05:27 -07002166 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002167 """
2168 if not isinstance(cert, X509):
2169 raise TypeError("cert must be an X509 instance")
2170 self._cert = cert
2171
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002172 def get_privatekey(self):
2173 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002174 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002175
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002176 :return: The private key, or :py:const:`None` if there is none.
2177 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002178 """
2179 return self._pkey
2180
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002181 def set_privatekey(self, pkey):
2182 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002183 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002184
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002185 :param pkey: The new private key, or :py:const:`None` to unset it.
2186 :type pkey: :py:class:`PKey` or :py:const:`None`
2187
Dan Sully44e767a2016-06-04 18:05:27 -07002188 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002189 """
2190 if not isinstance(pkey, PKey):
2191 raise TypeError("pkey must be a PKey instance")
2192 self._pkey = pkey
2193
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002194 def get_ca_certificates(self):
2195 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002196 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002197
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002198 :return: A tuple with the CA certificates in the chain, or
2199 :py:const:`None` if there are none.
2200 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002201 """
2202 if self._cacerts is not None:
2203 return tuple(self._cacerts)
2204
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002205 def set_ca_certificates(self, cacerts):
2206 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002207 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002208
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002209 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2210 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002211 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002212
Dan Sully44e767a2016-06-04 18:05:27 -07002213 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002214 """
2215 if cacerts is None:
2216 self._cacerts = None
2217 else:
2218 cacerts = list(cacerts)
2219 for cert in cacerts:
2220 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002221 raise TypeError(
2222 "iterable must only contain X509 instances"
2223 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002224 self._cacerts = cacerts
2225
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002226 def set_friendlyname(self, name):
2227 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002228 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002229
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002230 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002231 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002232
Dan Sully44e767a2016-06-04 18:05:27 -07002233 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002234 """
2235 if name is None:
2236 self._friendlyname = None
2237 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002238 raise TypeError(
2239 "name must be a byte string or None (not %r)" % (name,)
2240 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002241 self._friendlyname = name
2242
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002243 def get_friendlyname(self):
2244 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002245 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002246
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002247 :returns: The friendly name, or :py:const:`None` if there is none.
2248 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002249 """
2250 return self._friendlyname
2251
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002252 def export(self, passphrase=None, iter=2048, maciter=1):
2253 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002254 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002255
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002256 For more information, see the :c:func:`PKCS12_create` man page.
2257
2258 :param passphrase: The passphrase used to encrypt the structure. Unlike
2259 some other passphrase arguments, this *must* be a string, not a
2260 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002261 :type passphrase: :py:data:`bytes`
2262
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002263 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002264 :type iter: :py:data:`int`
2265
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002266 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002267 :type maciter: :py:data:`int`
2268
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002269 :return: The string representation of the PKCS #12 structure.
2270 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002271 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002272 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002273
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002274 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002275 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002276 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002277 cacerts = _lib.sk_X509_new_null()
2278 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002279 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002280 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002281
2282 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002283 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002284
2285 friendlyname = self._friendlyname
2286 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002287 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002288
2289 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002290 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002291 else:
2292 pkey = self._pkey._pkey
2293
2294 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002295 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002296 else:
2297 cert = self._cert._x509
2298
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002299 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002300 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002301 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2302 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002303 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002304 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002305 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002306 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002307
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002308 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002309 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002310 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002311
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002312
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002313PKCS12Type = PKCS12
2314
2315
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002316class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002317 """
2318 A Netscape SPKI object.
2319 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002320
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002321 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002322 spki = _lib.NETSCAPE_SPKI_new()
2323 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002324
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002325 def sign(self, pkey, digest):
2326 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002327 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002328
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002329 :param pkey: The private key to sign with.
2330 :type pkey: :py:class:`PKey`
2331
2332 :param digest: The message digest to use.
2333 :type digest: :py:class:`bytes`
2334
Dan Sully44e767a2016-06-04 18:05:27 -07002335 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002336 """
2337 if pkey._only_public:
2338 raise ValueError("Key has only public part")
2339
2340 if not pkey._initialized:
2341 raise ValueError("Key is uninitialized")
2342
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002343 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002344 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002345 raise ValueError("No such digest method")
2346
Alex Gaynor5945ea82015-09-05 14:59:06 -04002347 sign_result = _lib.NETSCAPE_SPKI_sign(
2348 self._spki, pkey._pkey, digest_obj
2349 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002350 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002351
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002352 def verify(self, key):
2353 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002354 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002355
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002356 :param key: The public key that signature is supposedly from.
2357 :type pkey: :py:class:`PKey`
2358
2359 :return: :py:const:`True` if the signature is correct.
2360 :rtype: :py:class:`bool`
2361
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002362 :raises Error: If the signature is invalid, or there was a problem
2363 verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002364 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002365 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002366 if answer <= 0:
2367 _raise_current_error()
2368 return True
2369
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002370 def b64_encode(self):
2371 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002372 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002373
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002374 :return: The base64 encoded string.
2375 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002376 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002377 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2378 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002379 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002380 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002381
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002382 def get_pubkey(self):
2383 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002384 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002385
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002386 :return: The public key.
2387 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002388 """
2389 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002390 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002391 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002392 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002393 pkey._only_public = True
2394 return pkey
2395
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002396 def set_pubkey(self, pkey):
2397 """
2398 Set the public key of the certificate
2399
2400 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002401 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002402 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002403 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002404 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002405
2406
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002407NetscapeSPKIType = NetscapeSPKI
2408
2409
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002410class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002411 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002412 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002413 raise ValueError(
2414 "only FILETYPE_PEM key format supports encryption"
2415 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002416 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002417 self._more_args = more_args
2418 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002419 self._problems = []
2420
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002421 @property
2422 def callback(self):
2423 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002424 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002425 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002426 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002427 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002428 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002429 else:
2430 raise TypeError("Last argument must be string or callable")
2431
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002432 @property
2433 def callback_args(self):
2434 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002435 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002436 elif isinstance(self._passphrase, bytes):
2437 return self._passphrase
2438 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002439 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002440 else:
2441 raise TypeError("Last argument must be string or callable")
2442
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002443 def raise_if_problem(self, exceptionType=Error):
2444 try:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05002445 _exception_from_error_queue(exceptionType)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002446 except exceptionType as e:
Jean-Paul Calderone9b4115f2014-01-10 14:06:04 -05002447 from_queue = e
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002448 if self._problems:
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002449 raise self._problems[0]
Jean-Paul Calderone9b4115f2014-01-10 14:06:04 -05002450 return from_queue
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002451
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002452 def _read_passphrase(self, buf, size, rwflag, userdata):
2453 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002454 if self._more_args:
2455 result = self._passphrase(size, rwflag, userdata)
2456 else:
2457 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002458 if not isinstance(result, bytes):
2459 raise ValueError("String expected")
2460 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002461 if self._truncate:
2462 result = result[:size]
2463 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002464 raise ValueError(
2465 "passphrase returned by callback is too long"
2466 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002467 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002468 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002469 return len(result)
2470 except Exception as e:
2471 self._problems.append(e)
2472 return 0
2473
2474
Cory Benfield6492f7c2015-10-27 16:57:58 +09002475def load_publickey(type, buffer):
2476 """
Cory Benfield11c10192015-10-27 17:23:03 +09002477 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002478
Cory Benfield9c590b92015-10-28 14:55:05 +09002479 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002480 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002481 :param buffer: The buffer the key is stored in.
2482 :type buffer: A Python string object, either unicode or bytestring.
2483 :return: The PKey object.
2484 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002485 """
2486 if isinstance(buffer, _text_type):
2487 buffer = buffer.encode("ascii")
2488
2489 bio = _new_mem_buf(buffer)
2490
2491 if type == FILETYPE_PEM:
2492 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2493 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2494 elif type == FILETYPE_ASN1:
2495 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2496 else:
2497 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2498
2499 if evp_pkey == _ffi.NULL:
2500 _raise_current_error()
2501
2502 pkey = PKey.__new__(PKey)
2503 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002504 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002505 return pkey
2506
2507
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002508def load_privatekey(type, buffer, passphrase=None):
2509 """
2510 Load a private key from a buffer
2511
2512 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2513 :param buffer: The buffer the key is stored in
2514 :param passphrase: (optional) if encrypted PEM format, this can be
2515 either the passphrase to use, or a callback for
2516 providing the passphrase.
2517
2518 :return: The PKey object
2519 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002520 if isinstance(buffer, _text_type):
2521 buffer = buffer.encode("ascii")
2522
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002523 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002524
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002525 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002526 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002527 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2528 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002529 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002530 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002531 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002532 else:
2533 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2534
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002535 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002536 _raise_current_error()
2537
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002538 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002539 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002540 return pkey
2541
2542
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002543def dump_certificate_request(type, req):
2544 """
2545 Dump a certificate request to a buffer
2546
2547 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2548 :param req: The certificate request to dump
2549 :return: The buffer with the dumped certificate request in
2550 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002551 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002552
2553 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002554 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002555 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002556 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002557 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002558 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002559 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002560 raise ValueError(
2561 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2562 "FILETYPE_TEXT"
2563 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002564
Alex Gaynor09a386e2016-07-03 09:32:44 -04002565 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002566
2567 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002568
2569
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002570def load_certificate_request(type, buffer):
2571 """
2572 Load a certificate request from a buffer
2573
2574 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2575 :param buffer: The buffer the certificate request is stored in
2576 :return: The X509Req object
2577 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002578 if isinstance(buffer, _text_type):
2579 buffer = buffer.encode("ascii")
2580
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002581 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002582
2583 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002584 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002585 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002586 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002587 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002588 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002589
Alex Gaynoradd5b072016-06-04 21:04:00 -07002590 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002591
2592 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002593 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002594 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002595
2596
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002597def sign(pkey, data, digest):
2598 """
2599 Sign data with a digest
2600
2601 :param pkey: Pkey to sign with
2602 :param data: data to be signed
2603 :param digest: message digest to use
2604 :return: signature
2605 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002606 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002607
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002608 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002609 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002610 raise ValueError("No such digest method")
2611
Alex Gaynor67903a62016-06-02 10:37:13 -07002612 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002613 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002614
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002615 _lib.EVP_SignInit(md_ctx, digest_obj)
2616 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002617
Colleen Murphye09399b2016-03-01 17:40:49 -08002618 pkey_length = (PKey.bits(pkey) + 7) // 8
2619 signature_buffer = _ffi.new("unsigned char[]", pkey_length)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002620 signature_length = _ffi.new("unsigned int*")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002621 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002622 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002623 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002624
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002625 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002626
2627
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002628def verify(cert, signature, data, digest):
2629 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002630 Verify a signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002631
2632 :param cert: signing certificate (X509 object)
2633 :param signature: signature returned by sign function
2634 :param data: data to be verified
2635 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002636 :return: ``None`` if the signature is correct, raise exception otherwise.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002637 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002638 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002639
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002640 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002641 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002642 raise ValueError("No such digest method")
2643
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002644 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002645 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002646 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002647
Alex Gaynor67903a62016-06-02 10:37:13 -07002648 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002649 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002650
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002651 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2652 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002653 verify_result = _lib.EVP_VerifyFinal(
2654 md_ctx, signature, len(signature), pkey
2655 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002656
2657 if verify_result != 1:
2658 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002659
2660
Dominic Chenf05b2122015-10-13 16:32:35 +00002661def dump_crl(type, crl):
2662 """
2663 Dump a certificate revocation list to a buffer.
2664
2665 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2666 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002667 :param CRL crl: The CRL to dump.
2668
Dominic Chenf05b2122015-10-13 16:32:35 +00002669 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002670 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002671 """
2672 bio = _new_mem_buf()
2673
2674 if type == FILETYPE_PEM:
2675 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2676 elif type == FILETYPE_ASN1:
2677 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2678 elif type == FILETYPE_TEXT:
2679 ret = _lib.X509_CRL_print(bio, crl._crl)
2680 else:
2681 raise ValueError(
2682 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2683 "FILETYPE_TEXT")
2684
2685 assert ret == 1
2686 return _bio_to_string(bio)
2687
2688
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002689def load_crl(type, buffer):
2690 """
2691 Load a certificate revocation list from a buffer
2692
2693 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2694 :param buffer: The buffer the CRL is stored in
2695
2696 :return: The PKey object
2697 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002698 if isinstance(buffer, _text_type):
2699 buffer = buffer.encode("ascii")
2700
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002701 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002702
2703 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002704 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002705 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002706 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002707 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002708 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2709
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002710 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002711 _raise_current_error()
2712
2713 result = CRL.__new__(CRL)
2714 result._crl = crl
2715 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002716
2717
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002718def load_pkcs7_data(type, buffer):
2719 """
2720 Load pkcs7 data from a buffer
2721
2722 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2723 :param buffer: The buffer with the pkcs7 data.
2724 :return: The PKCS7 object
2725 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002726 if isinstance(buffer, _text_type):
2727 buffer = buffer.encode("ascii")
2728
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002729 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002730
2731 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002732 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002733 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002734 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002735 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002736 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2737
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002738 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002739 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002740
2741 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002742 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002743 return pypkcs7
2744
2745
Stephen Holsapple38482622014-04-05 20:29:34 -07002746def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002747 """
2748 Load a PKCS12 object from a buffer
2749
2750 :param buffer: The buffer the certificate is stored in
2751 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2752 :returns: The PKCS12 object
2753 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002754 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002755
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002756 if isinstance(buffer, _text_type):
2757 buffer = buffer.encode("ascii")
2758
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002759 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002760
Stephen Holsapple38482622014-04-05 20:29:34 -07002761 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2762 # password based encryption no password and a zero length password are two
2763 # different things, but OpenSSL implementation will try both to figure out
2764 # which one works.
2765 if not passphrase:
2766 passphrase = _ffi.NULL
2767
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002768 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2769 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002770 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002771 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002772
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002773 pkey = _ffi.new("EVP_PKEY**")
2774 cert = _ffi.new("X509**")
2775 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002776
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002777 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002778 if not parse_result:
2779 _raise_current_error()
2780
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002781 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002782
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002783 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
2784 # queue for no particular reason. This error isn't interesting to anyone
2785 # outside this function. It's not even interesting to us. Get rid of it.
2786 try:
2787 _raise_current_error()
2788 except Error:
2789 pass
2790
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002791 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002792 pykey = None
2793 else:
2794 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002795 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002796
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002797 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002798 pycert = None
2799 friendlyname = None
2800 else:
2801 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002802 pycert._x509 = _ffi.gc(cert[0], _lib.X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002803
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002804 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04002805 friendlyname_buffer = _lib.X509_alias_get0(
2806 cert[0], friendlyname_length
2807 )
2808 friendlyname = _ffi.buffer(
2809 friendlyname_buffer, friendlyname_length[0]
2810 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002811 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002812 friendlyname = None
2813
2814 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002815 for i in range(_lib.sk_X509_num(cacerts)):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002816 pycacert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002817 pycacert._x509 = _lib.sk_X509_value(cacerts, i)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002818 pycacerts.append(pycacert)
2819 if not pycacerts:
2820 pycacerts = None
2821
2822 pkcs12 = PKCS12.__new__(PKCS12)
2823 pkcs12._pkey = pykey
2824 pkcs12._cert = pycert
2825 pkcs12._cacerts = pycacerts
2826 pkcs12._friendlyname = friendlyname
2827 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05002828
2829
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05002830# There are no direct unit tests for this initialization. It is tested
2831# indirectly since it is necessary for functions like dump_privatekey when
2832# using encryption.
2833#
2834# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
2835# and some other similar tests may fail without this (though they may not if
2836# the Python runtime has already done some initialization of the underlying
2837# OpenSSL library (and is linked against the same one that cryptography is
2838# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05002839_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05002840
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05002841# This is similar but exercised mainly by exception_from_error_queue. It calls
2842# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
2843_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002844
2845
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002846# Set the default string mask to match OpenSSL upstream (since 2005) and
2847# RFC5280 recommendations.
2848_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')