blob: 70ae3d20b11b3dda5c903cf94cd0362b20c04f28 [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)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500204 if result == 0:
205 # TODO: The test for this case is commented out. Different
206 # builds of OpenSSL appear to have different failure modes that
207 # make it hard to test. Visual inspection of the OpenSSL
208 # source reveals that a return value of 0 signals an error.
209 # Manual testing on a particular build of OpenSSL suggests that
210 # this is probably the appropriate way to handle those errors.
211 _raise_current_error()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800212
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500213 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800214 if not result:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500215 # TODO: It appears as though this can fail if an engine is in
216 # use which does not support RSA.
217 _raise_current_error()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800218
219 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400220 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700221 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400222
223 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400224 res = _lib.DSA_generate_parameters_ex(
225 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
226 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700227 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400228
229 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
230 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800231 else:
232 raise Error("No such key type")
233
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800234 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800235
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800236 def check(self):
237 """
238 Check the consistency of an RSA private key.
239
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200240 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
241
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800242 :return: True if key is consistent.
243 :raise Error: if the key is inconsistent.
244 :raise TypeError: if the key is of a type which cannot be checked.
245 Only RSA keys can currently be checked.
246 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800247 if self._only_public:
248 raise TypeError("public key only")
249
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100250 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800251 raise TypeError("key type unsupported")
252
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500253 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
254 rsa = _ffi.gc(rsa, _lib.RSA_free)
255 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800256 if result:
257 return True
258 _raise_current_error()
259
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800260 def type(self):
261 """
262 Returns the type of the key
263
264 :return: The type of the key.
265 """
Alex Gaynorc84567b2016-03-16 07:45:09 -0400266 return _lib.Cryptography_EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800267
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800268 def bits(self):
269 """
270 Returns the number of bits of the key
271
272 :return: The number of bits of the key.
273 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500274 return _lib.EVP_PKEY_bits(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800275PKeyType = PKey
276
277
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400278class _EllipticCurve(object):
279 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400280 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400281
282 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
283 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
284 instances each of which represents one curve supported by the system.
285 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400286 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400287 _curves = None
288
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400289 if _PY3:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400290 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400291 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400292 """
293 Implement cooperation with the right-hand side argument of ``!=``.
294
295 Python 3 seems to have dropped this cooperation in this very narrow
296 circumstance.
297 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400298 if isinstance(other, _EllipticCurve):
299 return super(_EllipticCurve, self).__ne__(other)
300 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400301
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400302 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400303 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400304 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400305 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400306
307 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400308
309 :return: A :py:type:`set` of ``cls`` instances giving the names of the
310 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400311 """
312 if lib.Cryptography_HAS_EC:
313 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
314 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
Alex Gaynor5945ea82015-09-05 14:59:06 -0400315 # The return value on this call should be num_curves again. We
316 # could check it to make sure but if it *isn't* then.. what could
317 # we do? Abort the whole process, I suppose...? -exarkun
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400318 lib.EC_get_builtin_curves(builtin_curves, num_curves)
319 return set(
320 cls.from_nid(lib, c.nid)
321 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400322 return set()
323
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400324 @classmethod
325 def _get_elliptic_curves(cls, lib):
326 """
327 Get, cache, and return the curves supported by OpenSSL.
328
329 :param lib: The OpenSSL library binding object.
330
331 :return: A :py:type:`set` of ``cls`` instances giving the names of the
332 elliptic curves the underlying library supports.
333 """
334 if cls._curves is None:
335 cls._curves = cls._load_elliptic_curves(lib)
336 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400337
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400338 @classmethod
339 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400340 """
341 Instantiate a new :py:class:`_EllipticCurve` associated with the given
342 OpenSSL NID.
343
344 :param lib: The OpenSSL library binding object.
345
346 :param nid: The OpenSSL NID the resulting curve object will represent.
347 This must be a curve NID (and not, for example, a hash NID) or
348 subsequent operations will fail in unpredictable ways.
349 :type nid: :py:class:`int`
350
351 :return: The curve object.
352 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400353 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
354
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400355 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400356 """
357 :param _lib: The :py:mod:`cryptography` binding instance used to
358 interface with OpenSSL.
359
360 :param _nid: The OpenSSL NID identifying the curve this object
361 represents.
362 :type _nid: :py:class:`int`
363
364 :param name: The OpenSSL short name identifying the curve this object
365 represents.
366 :type name: :py:class:`unicode`
367 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400368 self._lib = lib
369 self._nid = nid
370 self.name = name
371
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400372 def __repr__(self):
373 return "<Curve %r>" % (self.name,)
374
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400375 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400376 """
377 Create a new OpenSSL EC_KEY structure initialized to use this curve.
378
379 The structure is automatically garbage collected when the Python object
380 is garbage collected.
381 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400382 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
383 return _ffi.gc(key, _lib.EC_KEY_free)
384
385
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400386def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400387 """
388 Return a set of objects representing the elliptic curves supported in the
389 OpenSSL build in use.
390
391 The curve objects have a :py:class:`unicode` ``name`` attribute by which
392 they identify themselves.
393
394 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400395 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
396 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400397 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400398 return _EllipticCurve._get_elliptic_curves(_lib)
399
400
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400401def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400402 """
403 Return a single curve object selected by name.
404
405 See :py:func:`get_elliptic_curves` for information about curve objects.
406
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400407 :param name: The OpenSSL short name identifying the curve object to
408 retrieve.
409 :type name: :py:class:`unicode`
410
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400411 If the named curve is not supported then :py:class:`ValueError` is raised.
412 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400413 for curve in get_elliptic_curves():
414 if curve.name == name:
415 return curve
416 raise ValueError("unknown curve name", name)
417
418
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800419class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200420 """
421 An X.509 Distinguished Name.
422
423 :ivar countryName: The country of the entity.
424 :ivar C: Alias for :py:attr:`countryName`.
425
426 :ivar stateOrProvinceName: The state or province of the entity.
427 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
428
429 :ivar localityName: The locality of the entity.
430 :ivar L: Alias for :py:attr:`localityName`.
431
432 :ivar organizationName: The organization name of the entity.
433 :ivar O: Alias for :py:attr:`organizationName`.
434
435 :ivar organizationalUnitName: The organizational unit of the entity.
436 :ivar OU: Alias for :py:attr:`organizationalUnitName`
437
438 :ivar commonName: The common name of the entity.
439 :ivar CN: Alias for :py:attr:`commonName`.
440
441 :ivar emailAddress: The e-mail address of the entity.
442 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400443
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800444 def __init__(self, name):
445 """
446 Create a new X509Name, copying the given X509Name instance.
447
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200448 :param name: The name to copy.
449 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800450 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500451 name = _lib.X509_NAME_dup(name._name)
452 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800453
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800454 def __setattr__(self, name, value):
455 if name.startswith('_'):
456 return super(X509Name, self).__setattr__(name, value)
457
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800458 # Note: we really do not want str subclasses here, so we do not use
459 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800460 if type(name) is not str:
461 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400462 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800463
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500464 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500465 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800466 try:
467 _raise_current_error()
468 except Error:
469 pass
470 raise AttributeError("No such attribute")
471
472 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500473 for i in range(_lib.X509_NAME_entry_count(self._name)):
474 ent = _lib.X509_NAME_get_entry(self._name, i)
475 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
476 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800477 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500478 ent = _lib.X509_NAME_delete_entry(self._name, i)
479 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800480 break
481
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500482 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800483 value = value.encode('utf-8')
484
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500485 add_result = _lib.X509_NAME_add_entry_by_NID(
486 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800487 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500488 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800489
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800490 def __getattr__(self, name):
491 """
492 Find attribute. An X509Name object has the following attributes:
493 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400494 organization (alias O), organizationalUnit (alias OU), commonName
495 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800496 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500497 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500498 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800499 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
500 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
501 # push something onto the error queue. If we don't clean that up
502 # now, someone else will bump into it later and be quite confused.
503 # See lp#314814.
504 try:
505 _raise_current_error()
506 except Error:
507 pass
508 return super(X509Name, self).__getattr__(name)
509
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500510 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800511 if entry_index == -1:
512 return None
513
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500514 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
515 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800516
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500517 result_buffer = _ffi.new("unsigned char**")
518 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400519 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800520
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700521 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400522 result = _ffi.buffer(
523 result_buffer[0], data_length
524 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700525 finally:
526 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500527 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800528 return result
529
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500530 def _cmp(op):
531 def f(self, other):
532 if not isinstance(other, X509Name):
533 return NotImplemented
534 result = _lib.X509_NAME_cmp(self._name, other._name)
535 return op(result, 0)
536 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800537
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500538 __eq__ = _cmp(__eq__)
539 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800540
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500541 __lt__ = _cmp(__lt__)
542 __le__ = _cmp(__le__)
543
544 __gt__ = _cmp(__gt__)
545 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800546
547 def __repr__(self):
548 """
549 String representation of an X509Name
550 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400551 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500552 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800553 self._name, result_buffer, len(result_buffer))
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700554 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800555
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500556 return "<X509Name object '%s'>" % (
557 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800558
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800559 def hash(self):
560 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200561 Return an integer representation of the first four bytes of the
562 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800563
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200564 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
565
566 :return: The (integer) hash of this name.
567 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800568 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500569 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800570
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800571 def der(self):
572 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200573 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800574
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200575 :return: The DER encoded form of this name.
576 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800577 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500578 result_buffer = _ffi.new('unsigned char**')
579 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400580 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800581
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500582 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
583 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800584 return string_result
585
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800586 def get_components(self):
587 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200588 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800589
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200590 :return: The components of this name.
591 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800592 """
593 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500594 for i in range(_lib.X509_NAME_entry_count(self._name)):
595 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800596
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500597 fname = _lib.X509_NAME_ENTRY_get_object(ent)
598 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800599
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500600 nid = _lib.OBJ_obj2nid(fname)
601 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800602
603 result.append((
Alex Gaynora738ed52015-09-05 11:17:10 -0400604 _ffi.string(name),
605 _ffi.string(
606 _lib.ASN1_STRING_data(fval),
607 _lib.ASN1_STRING_length(fval))))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800608
609 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200610
611
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800612X509NameType = X509Name
613
614
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800615class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200616 """
617 An X.509 v3 certificate extension.
618 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400619
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800620 def __init__(self, type_name, critical, value, subject=None, issuer=None):
621 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200622 Initializes an X509 extension.
623
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100624 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400625 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800626
Alex Gaynor5945ea82015-09-05 14:59:06 -0400627 :param bool critical: A flag indicating whether this is a critical
628 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800629
630 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200631 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800632
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200633 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800634 :type subject: :py:class:`X509`
635
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200636 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800637 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100638
639 .. _extension: https://openssl.org/docs/manmaster/apps/
640 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800641 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500642 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800643
Alex Gaynor5945ea82015-09-05 14:59:06 -0400644 # A context is necessary for any extension which uses the r2i
645 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
646 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500647 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800648
649 # We have no configuration database - but perhaps we should (some
650 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500651 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800652
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800653 # Initialize the subject and issuer, if appropriate. ctx is a local,
654 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400655 # any references, so no need to mess with reference counts or
656 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800657 if issuer is not None:
658 if not isinstance(issuer, X509):
659 raise TypeError("issuer must be an X509 instance")
660 ctx.issuer_cert = issuer._x509
661 if subject is not None:
662 if not isinstance(subject, X509):
663 raise TypeError("subject must be an X509 instance")
664 ctx.subject_cert = subject._x509
665
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800666 if critical:
667 # There are other OpenSSL APIs which would let us pass in critical
668 # separately, but they're harder to use, and since value is already
669 # a pile of crappy junk smuggling a ton of utterly important
670 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400671 # with strings? (However, X509V3_EXT_i2d in particular seems like
672 # it would be a better API to invoke. I do not know where to get
673 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500674 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800675
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500676 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
677 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800678 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500679 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800680
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400681 @property
682 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400683 return _lib.OBJ_obj2nid(
684 _lib.X509_EXTENSION_get_object(self._extension)
685 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400686
687 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500688 _lib.GEN_EMAIL: "email",
689 _lib.GEN_DNS: "DNS",
690 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400691 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400692
693 def _subjectAltNameString(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500694 method = _lib.X509V3_EXT_get(self._extension)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700695 _openssl_assert(method != _ffi.NULL)
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400696 ext_data = _lib.X509_EXTENSION_get_data(self._extension)
697 payload = ext_data.data
698 length = ext_data.length
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400699
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500700 payloadptr = _ffi.new("unsigned char**")
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400701 payloadptr[0] = payload
702
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500703 if method.it != _ffi.NULL:
704 ptr = _lib.ASN1_ITEM_ptr(method.it)
705 data = _lib.ASN1_item_d2i(_ffi.NULL, payloadptr, length, ptr)
706 names = _ffi.cast("GENERAL_NAMES*", data)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400707 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500708 names = _ffi.cast(
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400709 "GENERAL_NAMES*",
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500710 method.d2i(_ffi.NULL, payloadptr, length))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400711
Paul Kehrerb7d79502015-05-04 07:43:51 -0500712 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400713 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500714 for i in range(_lib.sk_GENERAL_NAME_num(names)):
715 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400716 try:
717 label = self._prefixes[name.type]
718 except KeyError:
719 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500720 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500721 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400722 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500723 value = _native(
724 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
725 parts.append(label + ":" + value)
726 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400727
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800728 def __str__(self):
729 """
730 :return: a nice text representation of the extension
731 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500732 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400733 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800734
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400735 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500736 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400737 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800738
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500739 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800740
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800741 def get_critical(self):
742 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200743 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800744
745 :return: The critical field.
746 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500747 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800748
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800749 def get_short_name(self):
750 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200751 Returns the short type name of this X.509 extension.
752
753 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800754
755 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200756 :rtype: :py:data:`bytes`
757
758 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800759 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500760 obj = _lib.X509_EXTENSION_get_object(self._extension)
761 nid = _lib.OBJ_obj2nid(obj)
762 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800763
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800764 def get_data(self):
765 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200766 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800767
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200768 :return: The ASN.1 encoded data of this X509 extension.
769 :rtype: :py:data:`bytes`
770
771 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800772 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500773 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
774 string_result = _ffi.cast('ASN1_STRING*', octet_result)
775 char_result = _lib.ASN1_STRING_data(string_result)
776 result_length = _lib.ASN1_STRING_length(string_result)
777 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800778
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200779
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800780X509ExtensionType = X509Extension
781
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800782
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800783class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200784 """
785 An X.509 certificate signing requests.
786 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400787
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800788 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500789 req = _lib.X509_REQ_new()
790 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800791
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800792 def set_pubkey(self, pkey):
793 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200794 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800795
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200796 :param pkey: The public key to use.
797 :type pkey: :py:class:`PKey`
798
Dan Sully44e767a2016-06-04 18:05:27 -0700799 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800800 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500801 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400802 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800803
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800804 def get_pubkey(self):
805 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200806 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800807
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200808 :return: The public key.
809 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800810 """
811 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500812 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700813 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500814 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800815 pkey._only_public = True
816 return pkey
817
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800818 def set_version(self, version):
819 """
820 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
821 request.
822
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200823 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700824 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800825 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500826 set_result = _lib.X509_REQ_set_version(self._req, version)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800827 if not set_result:
828 _raise_current_error()
829
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800830 def get_version(self):
831 """
832 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
833 request.
834
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200835 :return: The value of the version subfield.
836 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800837 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500838 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800839
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800840 def get_subject(self):
841 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200842 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800843
Cory Benfield881dc8d2015-12-09 08:25:14 +0000844 This creates a new :class:`X509Name` that wraps the underlying subject
845 name field on the certificate signing request. Modifying it will modify
846 the underlying signing request, and will have the effect of modifying
847 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200848
849 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000850 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800851 """
852 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500853 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700854 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800855
856 # The name is owned by the X509Req structure. As long as the X509Name
857 # Python object is alive, keep the X509Req Python object alive.
858 name._owner = self
859
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800860 return name
861
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800862 def add_extensions(self, extensions):
863 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200864 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800865
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200866 :param extensions: The X.509 extensions to add.
867 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700868 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800869 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500870 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700871 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800872
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500873 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800874
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800875 for ext in extensions:
876 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -0800877 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800878
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800879 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500880 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800881
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500882 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400883 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800884
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800885 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800886 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200887 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800888
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200889 :return: The X.509 extensions in this request.
890 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
891
892 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800893 """
894 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500895 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -0500896 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800897 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500898 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800899 exts.append(ext)
900 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800901
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800902 def sign(self, pkey, digest):
903 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -0700904 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800905
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200906 :param pkey: The key pair to sign with.
907 :type pkey: :py:class:`PKey`
908 :param digest: The name of the message digest to use for the signature,
909 e.g. :py:data:`b"sha1"`.
910 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -0700911 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800912 """
913 if pkey._only_public:
914 raise ValueError("Key has only public part")
915
916 if not pkey._initialized:
917 raise ValueError("Key is uninitialized")
918
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500919 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500920 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800921 raise ValueError("No such digest method")
922
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500923 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400924 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800925
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800926 def verify(self, pkey):
927 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200928 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800929
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200930 :param key: A public key.
931 :type key: :py:class:`PKey`
932 :return: :py:data:`True` if the signature is correct.
933 :rtype: :py:class:`bool`
934 :raises Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800935 problem verifying the signature.
936 """
937 if not isinstance(pkey, PKey):
938 raise TypeError("pkey must be a PKey instance")
939
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500940 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800941 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500942 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800943
944 return result
945
946
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800947X509ReqType = X509Req
948
949
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800950class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200951 """
952 An X.509 certificate.
953 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400954
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800955 def __init__(self):
956 # TODO Allocation failure? And why not __new__ instead of __init__?
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500957 x509 = _lib.X509_new()
958 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800959
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800960 def set_version(self, version):
961 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200962 Set the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800963
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200964 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800965 :type version: :py:class:`int`
966
Dan Sully44e767a2016-06-04 18:05:27 -0700967 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800968 """
969 if not isinstance(version, int):
970 raise TypeError("version must be an integer")
971
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500972 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800973
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800974 def get_version(self):
975 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200976 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800977
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200978 :return: The version number of the certificate.
979 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800980 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500981 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800982
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800983 def get_pubkey(self):
984 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200985 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800986
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200987 :return: The public key.
988 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800989 """
990 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500991 pkey._pkey = _lib.X509_get_pubkey(self._x509)
992 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800993 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500994 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800995 pkey._only_public = True
996 return pkey
997
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800998 def set_pubkey(self, pkey):
999 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001000 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001001
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001002 :param pkey: The public key.
1003 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001004
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001005 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001006 """
1007 if not isinstance(pkey, PKey):
1008 raise TypeError("pkey must be a PKey instance")
1009
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001010 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001011 if not set_result:
1012 _raise_current_error()
1013
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001014 def sign(self, pkey, digest):
1015 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001016 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001017
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001018 :param pkey: The key to sign with.
1019 :type pkey: :py:class:`PKey`
1020
1021 :param digest: The name of the message digest to use.
1022 :type digest: :py:class:`bytes`
1023
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001024 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001025 """
1026 if not isinstance(pkey, PKey):
1027 raise TypeError("pkey must be a PKey instance")
1028
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001029 if pkey._only_public:
1030 raise ValueError("Key only has public part")
1031
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001032 if not pkey._initialized:
1033 raise ValueError("Key is uninitialized")
1034
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001035 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001036 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001037 raise ValueError("No such digest method")
1038
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001039 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001040 if not sign_result:
1041 _raise_current_error()
1042
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001043 def get_signature_algorithm(self):
1044 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001045 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001046
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001047 :return: The name of the algorithm.
1048 :rtype: :py:class:`bytes`
1049
1050 :raises ValueError: If the signature algorithm is undefined.
1051
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001052 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001053 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001054 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1055 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001056 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001057 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001058 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001059
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001060 def digest(self, digest_name):
1061 """
1062 Return the digest of the X509 object.
1063
1064 :param digest_name: The name of the digest algorithm to use.
1065 :type digest_name: :py:class:`bytes`
1066
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001067 :return: The digest of the object, formatted as
1068 :py:const:`b":"`-delimited hex pairs.
1069 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001070 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001071 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001072 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001073 raise ValueError("No such digest method")
1074
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001075 result_buffer = _ffi.new("char[]", _lib.EVP_MAX_MD_SIZE)
1076 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001077 result_length[0] = len(result_buffer)
1078
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001079 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001080 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001081 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001082
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001083 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001084 b16encode(ch).upper() for ch
1085 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001086
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001087 def subject_name_hash(self):
1088 """
1089 Return the hash of the X509 subject.
1090
1091 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001092 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001093 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001094 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001095
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001096 def set_serial_number(self, serial):
1097 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001098 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001099
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001100 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001101 :type serial: :py:class:`int`
1102
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001103 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001104 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001105 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001106 raise TypeError("serial must be an integer")
1107
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001108 hex_serial = hex(serial)[2:]
1109 if not isinstance(hex_serial, bytes):
1110 hex_serial = hex_serial.encode('ascii')
1111
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001112 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001113
1114 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001115 # it. If bignum is still NULL after this call, then the return value
1116 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001117 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001118
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001119 if bignum_serial[0] == _ffi.NULL:
1120 set_result = _lib.ASN1_INTEGER_set(
1121 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001122 if set_result:
1123 # TODO Not tested
1124 _raise_current_error()
1125 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001126 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1127 _lib.BN_free(bignum_serial[0])
1128 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001129 # TODO Not tested
1130 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001131 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1132 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001133 if not set_result:
1134 # TODO Not tested
1135 _raise_current_error()
1136
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001137 def get_serial_number(self):
1138 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001139 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001140
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001141 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001142 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001143 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001144 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1145 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001146 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001147 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001148 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001149 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001150 serial = int(hexstring_serial, 16)
1151 return serial
1152 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001153 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001154 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001155 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001156
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001157 def gmtime_adj_notAfter(self, amount):
1158 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001159 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001160
Dan Sully44e767a2016-06-04 18:05:27 -07001161 :param int amount: The number of seconds by which to adjust the
1162 timestamp.
1163 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001164 """
1165 if not isinstance(amount, int):
1166 raise TypeError("amount must be an integer")
1167
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001168 notAfter = _lib.X509_get_notAfter(self._x509)
1169 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001170
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001171 def gmtime_adj_notBefore(self, amount):
1172 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001173 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001174
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001175 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001176 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001177 """
1178 if not isinstance(amount, int):
1179 raise TypeError("amount must be an integer")
1180
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001181 notBefore = _lib.X509_get_notBefore(self._x509)
1182 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001183
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001184 def has_expired(self):
1185 """
1186 Check whether the certificate has expired.
1187
Dan Sully44e767a2016-06-04 18:05:27 -07001188 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1189 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001190 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001191 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001192 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001193
Paul Kehrerfde45c92016-01-21 12:57:37 -06001194 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001195
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001196 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001197 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001198
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001199 def get_notBefore(self):
1200 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001201 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001202
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001203 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001204
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001205 YYYYMMDDhhmmssZ
1206 YYYYMMDDhhmmss+hhmm
1207 YYYYMMDDhhmmss-hhmm
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001208
Dan Sully44e767a2016-06-04 18:05:27 -07001209 :return: A timestamp string, or ``None`` if there is none.
1210 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001211 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001212 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001213
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001214 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001215 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001216
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001217 def set_notBefore(self, when):
1218 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001219 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001220
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001221 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001222
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001223 YYYYMMDDhhmmssZ
1224 YYYYMMDDhhmmss+hhmm
1225 YYYYMMDDhhmmss-hhmm
1226
Dan Sully44e767a2016-06-04 18:05:27 -07001227 :param bytes when: A timestamp string.
1228 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001229 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001230 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001231
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001232 def get_notAfter(self):
1233 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001234 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001235
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001236 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001237
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001238 YYYYMMDDhhmmssZ
1239 YYYYMMDDhhmmss+hhmm
1240 YYYYMMDDhhmmss-hhmm
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001241
Dan Sully44e767a2016-06-04 18:05:27 -07001242 :return: A timestamp string, or ``None`` if there is none.
1243 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001244 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001245 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001246
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001247 def set_notAfter(self, when):
1248 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001249 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001250
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001251 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001252
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001253 YYYYMMDDhhmmssZ
1254 YYYYMMDDhhmmss+hhmm
1255 YYYYMMDDhhmmss-hhmm
1256
Dan Sully44e767a2016-06-04 18:05:27 -07001257 :param bytes when: A timestamp string.
1258 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001259 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001260 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001261
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001262 def _get_name(self, which):
1263 name = X509Name.__new__(X509Name)
1264 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001265 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001266
1267 # The name is owned by the X509 structure. As long as the X509Name
1268 # Python object is alive, keep the X509 Python object alive.
1269 name._owner = self
1270
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001271 return name
1272
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001273 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001274 if not isinstance(name, X509Name):
1275 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001276 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001277 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001278
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001279 def get_issuer(self):
1280 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001281 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001282
Cory Benfielde6bcce82015-12-09 08:40:03 +00001283 This creates a new :class:`X509Name` that wraps the underlying issuer
1284 name field on the certificate. Modifying it will modify the underlying
1285 certificate, and will have the effect of modifying any other
1286 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001287
1288 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001289 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001290 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001291 return self._get_name(_lib.X509_get_issuer_name)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001292
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001293 def set_issuer(self, issuer):
1294 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001295 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001296
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001297 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001298 :type issuer: :py:class:`X509Name`
1299
Dan Sully44e767a2016-06-04 18:05:27 -07001300 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001301 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001302 return self._set_name(_lib.X509_set_issuer_name, issuer)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001303
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001304 def get_subject(self):
1305 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001306 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001307
Cory Benfielde6bcce82015-12-09 08:40:03 +00001308 This creates a new :class:`X509Name` that wraps the underlying subject
1309 name field on the certificate. Modifying it will modify the underlying
1310 certificate, and will have the effect of modifying any other
1311 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001312
1313 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001314 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001315 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001316 return self._get_name(_lib.X509_get_subject_name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001317
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001318 def set_subject(self, subject):
1319 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001320 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001321
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001322 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001323 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001324
Dan Sully44e767a2016-06-04 18:05:27 -07001325 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001326 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001327 return self._set_name(_lib.X509_set_subject_name, subject)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001328
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001329 def get_extension_count(self):
1330 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001331 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001332
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001333 :return: The number of extensions.
1334 :rtype: :py:class:`int`
1335
1336 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001337 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001338 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001339
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001340 def add_extensions(self, extensions):
1341 """
1342 Add extensions to the certificate.
1343
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001344 :param extensions: The extensions to add.
1345 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001346 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001347 """
1348 for ext in extensions:
1349 if not isinstance(ext, X509Extension):
1350 raise ValueError("One of the elements is not an X509Extension")
1351
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001352 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001353 if not add_result:
1354 _raise_current_error()
1355
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001356 def get_extension(self, index):
1357 """
1358 Get a specific extension of the certificate by index.
1359
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001360 Extensions on a certificate are kept in order. The index
1361 parameter selects which extension will be returned.
1362
1363 :param int index: The index of the extension to retrieve.
1364 :return: The extension at the specified index.
1365 :rtype: :py:class:`X509Extension`
1366 :raises IndexError: If the extension index was out of bounds.
1367
1368 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001369 """
1370 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001371 ext._extension = _lib.X509_get_ext(self._x509, index)
1372 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001373 raise IndexError("extension index out of bounds")
1374
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001375 extension = _lib.X509_EXTENSION_dup(ext._extension)
1376 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001377 return ext
1378
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001379
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001380X509Type = X509
1381
1382
Dan Sully44e767a2016-06-04 18:05:27 -07001383class X509StoreFlags(object):
1384 """
1385 Flags for X509 verification, used to change the behavior of
1386 :class:`X509Store`.
1387
1388 See `OpenSSL Verification Flags`_ for details.
1389
1390 .. _OpenSSL Verification Flags:
1391 https://www.openssl.org/docs/manmaster/crypto/X509_VERIFY_PARAM_set_flags.html
1392 """
1393 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1394 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1395 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1396 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1397 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1398 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1399 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1400 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1401 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1402 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1403 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1404
1405
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001406class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001407 """
Dan Sully44e767a2016-06-04 18:05:27 -07001408 An X.509 store.
1409
1410 An X.509 store is used to describe a context in which to verify a
1411 certificate. A description of a context may include a set of certificates
1412 to trust, a set of certificate revocation lists, verification flags and
1413 more.
1414
1415 An X.509 store, being only a description, cannot be used by itself to
1416 verify a certificate. To carry out the actual verification process, see
1417 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001418 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001419
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001420 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001421 store = _lib.X509_STORE_new()
1422 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001423
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001424 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001425 """
Dan Sully44e767a2016-06-04 18:05:27 -07001426 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001427
Dan Sully44e767a2016-06-04 18:05:27 -07001428 Adding a certificate with this method adds this certificate as a
1429 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001430
1431 :param X509 cert: The certificate to add to this store.
Dan Sully44e767a2016-06-04 18:05:27 -07001432 :raises TypeError: If the certificate is not an :class:`X509`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001433 :raises Error: If OpenSSL was unhappy with your certificate.
Dan Sully44e767a2016-06-04 18:05:27 -07001434 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001435 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001436 if not isinstance(cert, X509):
1437 raise TypeError()
1438
Dan Sully44e767a2016-06-04 18:05:27 -07001439 _openssl_assert(_lib.X509_STORE_add_cert(self._store, cert._x509) != 0)
1440
1441 def add_crl(self, crl):
1442 """
1443 Add a certificate revocation list to this store.
1444
1445 The certificate revocation lists added to a store will only be used if
1446 the associated flags are configured to check certificate revocation
1447 lists.
1448
1449 .. versionadded:: 16.1.0
1450
1451 :param CRL crl: The certificate revocation list to add to this store.
1452 :return: ``None`` if the certificate revocation list was added
1453 successfully.
1454 """
1455 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1456
1457 def set_flags(self, flags):
1458 """
1459 Set verification flags to this store.
1460
1461 Verification flags can be combined by oring them together.
1462
1463 .. note::
1464
1465 Setting a verification flag sometimes requires clients to add
1466 additional information to the store, otherwise a suitable error will
1467 be raised.
1468
1469 For example, in setting flags to enable CRL checking a
1470 suitable CRL must be added to the store otherwise an error will be
1471 raised.
1472
1473 .. versionadded:: 16.1.0
1474
1475 :param int flags: The verification flags to set on this store.
1476 See :class:`X509StoreFlags` for available constants.
1477 :return: ``None`` if the verification flags were successfully set.
1478 """
1479 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001480
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001481
1482X509StoreType = X509Store
1483
1484
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001485class X509StoreContextError(Exception):
1486 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001487 An exception raised when an error occurred while verifying a certificate
1488 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001489
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001490 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001491 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001492 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001493
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001494 def __init__(self, message, certificate):
1495 super(X509StoreContextError, self).__init__(message)
1496 self.certificate = certificate
1497
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001498
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001499class X509StoreContext(object):
1500 """
1501 An X.509 store context.
1502
Dan Sully44e767a2016-06-04 18:05:27 -07001503 An X.509 store context is used to carry out the actual verification process
1504 of a certificate in a described context. For describing such a context, see
1505 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001506
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001507 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1508 instance. It is dynamically allocated and automatically garbage
1509 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001510 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001511 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001512 :param X509Store store: The certificates which will be trusted for the
1513 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001514 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001515 """
1516
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001517 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001518 store_ctx = _lib.X509_STORE_CTX_new()
1519 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1520 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001521 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001522 # Make the store context available for use after instantiating this
1523 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001524 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001525 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001526
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001527 def _init(self):
1528 """
1529 Set up the store context for a subsequent verification operation.
1530 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001531 ret = _lib.X509_STORE_CTX_init(
1532 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1533 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001534 if ret <= 0:
1535 _raise_current_error()
1536
1537 def _cleanup(self):
1538 """
1539 Internally cleans up the store context.
1540
Dan Sully44e767a2016-06-04 18:05:27 -07001541 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001542 """
1543 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1544
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001545 def _exception_from_context(self):
1546 """
1547 Convert an OpenSSL native context error failure into a Python
1548 exception.
1549
Alex Gaynor5945ea82015-09-05 14:59:06 -04001550 When a call to native OpenSSL X509_verify_cert fails, additional
1551 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001552 """
1553 errors = [
1554 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1555 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1556 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001557 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001558 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001559 # A context error should always be associated with a certificate, so we
1560 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001561 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001562 _cert = _lib.X509_dup(_x509)
1563 pycert = X509.__new__(X509)
1564 pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001565 return X509StoreContextError(errors, pycert)
1566
Stephen Holsapple46a09252015-02-12 14:45:43 -08001567 def set_store(self, store):
1568 """
Dan Sully44e767a2016-06-04 18:05:27 -07001569 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001570
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001571 .. versionadded:: 0.15
1572
Dan Sully44e767a2016-06-04 18:05:27 -07001573 :param X509Store store: The store description which will be used for
1574 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001575 """
1576 self._store = store
1577
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001578 def verify_certificate(self):
1579 """
1580 Verify a certificate in a context.
1581
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001582 .. versionadded:: 0.15
1583
Alex Gaynorca87ff62015-09-04 23:31:03 -04001584 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001585 certificate in the context. Sets ``certificate`` attribute to
1586 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001587 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001588 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001589 # :meth:`verify_certificate` is called multiple times.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001590 self._init()
1591 ret = _lib.X509_verify_cert(self._store_ctx)
1592 self._cleanup()
1593 if ret <= 0:
1594 raise self._exception_from_context()
1595
1596
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001597def load_certificate(type, buffer):
1598 """
1599 Load a certificate from a buffer
1600
1601 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1602
Dan Sully44e767a2016-06-04 18:05:27 -07001603 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001604
1605 :return: The X509 object
1606 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001607 if isinstance(buffer, _text_type):
1608 buffer = buffer.encode("ascii")
1609
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001610 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001611
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001612 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001613 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001614 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001615 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001616 else:
1617 raise ValueError(
1618 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001619
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001620 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001621 _raise_current_error()
1622
1623 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001624 cert._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001625 return cert
1626
1627
1628def dump_certificate(type, cert):
1629 """
1630 Dump a certificate to a buffer
1631
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001632 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1633 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001634 :param cert: The certificate to dump
1635 :return: The buffer with the dumped certificate in
1636 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001637 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001638
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001639 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001640 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001641 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001642 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001643 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001644 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001645 else:
1646 raise ValueError(
1647 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1648 "FILETYPE_TEXT")
1649
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001650 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001651 return _bio_to_string(bio)
1652
1653
Cory Benfield6492f7c2015-10-27 16:57:58 +09001654def dump_publickey(type, pkey):
1655 """
Cory Benfield11c10192015-10-27 17:23:03 +09001656 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001657
Cory Benfield9c590b92015-10-28 14:55:05 +09001658 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001659 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001660 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001661 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001662 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001663 """
1664 bio = _new_mem_buf()
1665 if type == FILETYPE_PEM:
1666 write_bio = _lib.PEM_write_bio_PUBKEY
1667 elif type == FILETYPE_ASN1:
1668 write_bio = _lib.i2d_PUBKEY_bio
1669 else:
1670 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1671
1672 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001673 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001674 _raise_current_error()
1675
1676 return _bio_to_string(bio)
1677
1678
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001679def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1680 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001681 Dump the private key *pkey* into a buffer string encoded with the type
1682 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1683 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001684
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001685 :param type: The file type (one of :const:`FILETYPE_PEM`,
1686 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1687 :param PKey pkey: The PKey to dump
1688 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001689 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001690 the passphrase to use, or a callback for providing the passphrase.
1691
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001692 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001693 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001694 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001695 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001696
1697 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001698 if passphrase is None:
1699 raise TypeError(
1700 "if a value is given for cipher "
1701 "one must also be given for passphrase")
1702 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001703 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001704 raise ValueError("Invalid cipher name")
1705 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001706 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001707
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001708 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001709 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001710 result_code = _lib.PEM_write_bio_PrivateKey(
1711 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001712 helper.callback, helper.callback_args)
1713 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001714 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001715 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001716 elif type == FILETYPE_TEXT:
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001717 rsa = _ffi.gc(
1718 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1719 _lib.RSA_free
1720 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001721 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001722 else:
1723 raise ValueError(
1724 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1725 "FILETYPE_TEXT")
1726
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001727 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001728
1729 return _bio_to_string(bio)
1730
1731
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001732class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001733 """
1734 A certificate revocation.
1735 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001736 # http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_
1737 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1738 # OCSP_crl_reason_str. We use the latter, just like the command line
1739 # program.
1740 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001741 b"unspecified",
1742 b"keyCompromise",
1743 b"CACompromise",
1744 b"affiliationChanged",
1745 b"superseded",
1746 b"cessationOfOperation",
1747 b"certificateHold",
1748 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001749 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001750
1751 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001752 revoked = _lib.X509_REVOKED_new()
1753 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001754
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001755 def set_serial(self, hex_str):
1756 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001757 Set the serial number.
1758
1759 The serial number is formatted as a hexadecimal number encoded in
1760 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001761
Dan Sully44e767a2016-06-04 18:05:27 -07001762 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001763
Dan Sully44e767a2016-06-04 18:05:27 -07001764 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001765 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001766 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1767 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001768 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001769 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001770 if not bn_result:
1771 raise ValueError("bad hex string")
1772
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001773 asn1_serial = _ffi.gc(
1774 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1775 _lib.ASN1_INTEGER_free)
1776 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001777
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001778 def get_serial(self):
1779 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001780 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001781
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001782 The serial number is formatted as a hexadecimal number encoded in
1783 ASCII.
1784
1785 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001786 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001787 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001788 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001789
Alex Gaynor67903a62016-06-02 10:37:13 -07001790 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1791 _openssl_assert(asn1_int != _ffi.NULL)
1792 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1793 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001794 return _bio_to_string(bio)
1795
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001796 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001797 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1798 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001799 obj = _lib.X509_EXTENSION_get_object(ext)
1800 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001801 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001802 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001803 break
1804
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001805 def set_reason(self, reason):
1806 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001807 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001808
Dan Sully44e767a2016-06-04 18:05:27 -07001809 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001810
1811 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07001812 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001813
Dan Sully44e767a2016-06-04 18:05:27 -07001814 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001815
1816 .. seealso::
1817
Dan Sully44e767a2016-06-04 18:05:27 -07001818 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001819 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001820 """
1821 if reason is None:
1822 self._delete_reason()
1823 elif not isinstance(reason, bytes):
1824 raise TypeError("reason must be None or a byte string")
1825 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001826 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001827 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
1828
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001829 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07001830 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001831 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001832
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001833 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001834 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001835
1836 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001837 add_result = _lib.X509_REVOKED_add1_ext_i2d(
1838 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001839 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001840
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001841 def get_reason(self):
1842 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04001843 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001844
Dan Sully44e767a2016-06-04 18:05:27 -07001845 :return: The reason, or ``None`` if there is none.
1846 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001847
1848 .. seealso::
1849
Dan Sully44e767a2016-06-04 18:05:27 -07001850 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001851 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001852 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001853 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1854 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001855 obj = _lib.X509_EXTENSION_get_object(ext)
1856 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001857 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001858
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001859 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001860 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04001861 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001862 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04001863 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04001864 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001865
1866 return _bio_to_string(bio)
1867
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001868 def all_reasons(self):
1869 """
1870 Return a list of all the supported reason strings.
1871
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001872 This list is a copy; modifying it does not change the supported reason
1873 strings.
1874
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001875 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07001876 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001877 """
1878 return self._crl_reasons[:]
1879
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001880 def set_rev_date(self, when):
1881 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001882 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001883
Dan Sully44e767a2016-06-04 18:05:27 -07001884 :param bytes when: The timestamp of the revocation,
1885 as ASN.1 GENERALIZEDTIME.
1886 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001887 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001888 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1889 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001890
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001891 def get_rev_date(self):
1892 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001893 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001894
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001895 :return: The timestamp of the revocation, as ASN.1 GENERALIZEDTIME.
Dan Sully44e767a2016-06-04 18:05:27 -07001896 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001897 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001898 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1899 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001900
1901
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001902class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001903 """
1904 A certificate revocation list.
1905 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001906
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001907 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001908 crl = _lib.X509_CRL_new()
1909 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001910
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001911 def get_revoked(self):
1912 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001913 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001914
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001915 These revocations will be provided by value, not by reference.
1916 That means it's okay to mutate them: it won't affect this CRL.
1917
1918 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07001919 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001920 """
1921 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07001922 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001923 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
1924 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04001925 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001926 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001927 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001928 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08001929 if results:
1930 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001931
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001932 def add_revoked(self, revoked):
1933 """
1934 Add a revoked (by value not reference) to the CRL structure
1935
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001936 This revocation will be added by value, not by reference. That
1937 means it's okay to mutate it after adding: it won't affect
1938 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001939
Dan Sully44e767a2016-06-04 18:05:27 -07001940 :param Revoked revoked: The new revocation.
1941 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001942 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04001943 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001944 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001945
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001946 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001947 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001948
Dan Sully44e767a2016-06-04 18:05:27 -07001949 def get_issuer(self):
1950 """
1951 Get the CRL's issuer.
1952
1953 .. versionadded:: 16.1.0
1954
1955 :rtype: X509Name
1956 """
1957 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
1958 _openssl_assert(_issuer != _ffi.NULL)
1959 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
1960 issuer = X509Name.__new__(X509Name)
1961 issuer._name = _issuer
1962 return issuer
1963
1964 def set_version(self, version):
1965 """
1966 Set the CRL version.
1967
1968 .. versionadded:: 16.1.0
1969
1970 :param int version: The version of the CRL.
1971 :return: ``None``
1972 """
1973 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
1974
1975 def _set_boundary_time(self, which, when):
1976 return _set_asn1_time(which(self._crl), when)
1977
1978 def set_lastUpdate(self, when):
1979 """
1980 Set when the CRL was last updated.
1981
1982 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
1983
1984 YYYYMMDDhhmmssZ
1985 YYYYMMDDhhmmss+hhmm
1986 YYYYMMDDhhmmss-hhmm
1987
1988 .. versionadded:: 16.1.0
1989
1990 :param bytes when: A timestamp string.
1991 :return: ``None``
1992 """
1993 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
1994
1995 def set_nextUpdate(self, when):
1996 """
1997 Set when the CRL will next be udpated.
1998
1999 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
2000
2001 YYYYMMDDhhmmssZ
2002 YYYYMMDDhhmmss+hhmm
2003 YYYYMMDDhhmmss-hhmm
2004
2005 .. versionadded:: 16.1.0
2006
2007 :param bytes when: A timestamp string.
2008 :return: ``None``
2009 """
2010 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2011
2012 def sign(self, issuer_cert, issuer_key, digest):
2013 """
2014 Sign the CRL.
2015
2016 Signing a CRL enables clients to associate the CRL itself with an
2017 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2018 be signed by an issuer.
2019
2020 This method implicitly sets the issuer's name based on the issuer
2021 certificate and private key used to sign the CRL.
2022
2023 .. versionadded:: 16.1.0
2024
2025 :param X509 issuer_cert: The issuer's certificate.
2026 :param PKey issuer_key: The issuer's private key.
2027 :param bytes digest: The digest method to sign the CRL with.
2028 """
2029 digest_obj = _lib.EVP_get_digestbyname(digest)
2030 _openssl_assert(digest_obj != _ffi.NULL)
2031 _lib.X509_CRL_set_issuer_name(
2032 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2033 _lib.X509_CRL_sort(self._crl)
2034 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2035 _openssl_assert(result != 0)
2036
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002037 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002038 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002039 """
Dan Sully44e767a2016-06-04 18:05:27 -07002040 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002041
Dan Sully44e767a2016-06-04 18:05:27 -07002042 :param X509 cert: The certificate used to sign the CRL.
2043 :param PKey key: The key used to sign the CRL.
2044 :param int type: The export format, either :data:`FILETYPE_PEM`,
2045 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002046 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002047 :param bytes digest: The name of the message digest to use (eg
2048 ``b"sha1"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002049 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002050 """
Dan Sully44e767a2016-06-04 18:05:27 -07002051
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002052 if not isinstance(cert, X509):
2053 raise TypeError("cert must be an X509 instance")
2054 if not isinstance(key, PKey):
2055 raise TypeError("key must be a PKey instance")
2056 if not isinstance(type, int):
2057 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002058
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002059 if digest is _UNSPECIFIED:
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002060 _warn(
2061 "The default message digest (md5) is deprecated. "
2062 "Pass the name of a message digest explicitly.",
2063 category=DeprecationWarning,
2064 stacklevel=2,
2065 )
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002066 digest = b"md5"
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002067
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002068 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002069 if digest_obj == _ffi.NULL:
2070 raise ValueError("No such digest method")
2071
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002072 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002073 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002074
Alex Gaynora738ed52015-09-05 11:17:10 -04002075 # A scratch time object to give different values to different CRL
2076 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002077 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002078 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002079
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002080 _lib.X509_gmtime_adj(sometime, 0)
2081 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002082
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002083 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2084 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002085
Alex Gaynor5945ea82015-09-05 14:59:06 -04002086 _lib.X509_CRL_set_issuer_name(
2087 self._crl, _lib.X509_get_subject_name(cert._x509)
2088 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002089
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002090 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002091 if not sign_result:
2092 _raise_current_error()
2093
Dominic Chenf05b2122015-10-13 16:32:35 +00002094 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002095
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002096
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002097CRLType = CRL
2098
2099
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002100class PKCS7(object):
2101 def type_is_signed(self):
2102 """
2103 Check if this NID_pkcs7_signed object
2104
2105 :return: True if the PKCS7 is of type signed
2106 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002107 if _lib.PKCS7_type_is_signed(self._pkcs7):
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002108 return True
2109 return False
2110
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002111 def type_is_enveloped(self):
2112 """
2113 Check if this NID_pkcs7_enveloped object
2114
2115 :returns: True if the PKCS7 is of type enveloped
2116 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002117 if _lib.PKCS7_type_is_enveloped(self._pkcs7):
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002118 return True
2119 return False
2120
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002121 def type_is_signedAndEnveloped(self):
2122 """
2123 Check if this NID_pkcs7_signedAndEnveloped object
2124
2125 :returns: True if the PKCS7 is of type signedAndEnveloped
2126 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002127 if _lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7):
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002128 return True
2129 return False
2130
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002131 def type_is_data(self):
2132 """
2133 Check if this NID_pkcs7_data object
2134
2135 :return: True if the PKCS7 is of type data
2136 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002137 if _lib.PKCS7_type_is_data(self._pkcs7):
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002138 return True
2139 return False
2140
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002141 def get_type_name(self):
2142 """
2143 Returns the type name of the PKCS7 structure
2144
2145 :return: A string with the typename
2146 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002147 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2148 string_type = _lib.OBJ_nid2sn(nid)
2149 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002150
2151PKCS7Type = PKCS7
2152
2153
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002154class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002155 """
2156 A PKCS #12 archive.
2157 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002158
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002159 def __init__(self):
2160 self._pkey = None
2161 self._cert = None
2162 self._cacerts = None
2163 self._friendlyname = None
2164
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002165 def get_certificate(self):
2166 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002167 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002168
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002169 :return: The certificate, or :py:const:`None` if there is none.
2170 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002171 """
2172 return self._cert
2173
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002174 def set_certificate(self, cert):
2175 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002176 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002177
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002178 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002179 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002180
Dan Sully44e767a2016-06-04 18:05:27 -07002181 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002182 """
2183 if not isinstance(cert, X509):
2184 raise TypeError("cert must be an X509 instance")
2185 self._cert = cert
2186
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002187 def get_privatekey(self):
2188 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002189 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002190
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002191 :return: The private key, or :py:const:`None` if there is none.
2192 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002193 """
2194 return self._pkey
2195
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002196 def set_privatekey(self, pkey):
2197 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002198 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002199
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002200 :param pkey: The new private key, or :py:const:`None` to unset it.
2201 :type pkey: :py:class:`PKey` or :py:const:`None`
2202
Dan Sully44e767a2016-06-04 18:05:27 -07002203 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002204 """
2205 if not isinstance(pkey, PKey):
2206 raise TypeError("pkey must be a PKey instance")
2207 self._pkey = pkey
2208
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002209 def get_ca_certificates(self):
2210 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002211 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002212
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002213 :return: A tuple with the CA certificates in the chain, or
2214 :py:const:`None` if there are none.
2215 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002216 """
2217 if self._cacerts is not None:
2218 return tuple(self._cacerts)
2219
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002220 def set_ca_certificates(self, cacerts):
2221 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002222 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002223
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002224 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2225 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002226 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002227
Dan Sully44e767a2016-06-04 18:05:27 -07002228 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002229 """
2230 if cacerts is None:
2231 self._cacerts = None
2232 else:
2233 cacerts = list(cacerts)
2234 for cert in cacerts:
2235 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002236 raise TypeError(
2237 "iterable must only contain X509 instances"
2238 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002239 self._cacerts = cacerts
2240
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002241 def set_friendlyname(self, name):
2242 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002243 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002244
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002245 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002246 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002247
Dan Sully44e767a2016-06-04 18:05:27 -07002248 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002249 """
2250 if name is None:
2251 self._friendlyname = None
2252 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002253 raise TypeError(
2254 "name must be a byte string or None (not %r)" % (name,)
2255 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002256 self._friendlyname = name
2257
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002258 def get_friendlyname(self):
2259 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002260 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002261
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002262 :returns: The friendly name, or :py:const:`None` if there is none.
2263 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002264 """
2265 return self._friendlyname
2266
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002267 def export(self, passphrase=None, iter=2048, maciter=1):
2268 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002269 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002270
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002271 For more information, see the :c:func:`PKCS12_create` man page.
2272
2273 :param passphrase: The passphrase used to encrypt the structure. Unlike
2274 some other passphrase arguments, this *must* be a string, not a
2275 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002276 :type passphrase: :py:data:`bytes`
2277
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002278 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002279 :type iter: :py:data:`int`
2280
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002281 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002282 :type maciter: :py:data:`int`
2283
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002284 :return: The string representation of the PKCS #12 structure.
2285 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002286 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002287 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002288
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002289 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002290 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002291 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002292 cacerts = _lib.sk_X509_new_null()
2293 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002294 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002295 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002296
2297 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002298 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002299
2300 friendlyname = self._friendlyname
2301 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002302 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002303
2304 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002305 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002306 else:
2307 pkey = self._pkey._pkey
2308
2309 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002310 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002311 else:
2312 cert = self._cert._x509
2313
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002314 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002315 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002316 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2317 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002318 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002319 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002320 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002321 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002322
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002323 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002324 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002325 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002326
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002327
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002328PKCS12Type = PKCS12
2329
2330
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002331class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002332 """
2333 A Netscape SPKI object.
2334 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002335
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002336 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002337 spki = _lib.NETSCAPE_SPKI_new()
2338 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002339
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002340 def sign(self, pkey, digest):
2341 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002342 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002343
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002344 :param pkey: The private key to sign with.
2345 :type pkey: :py:class:`PKey`
2346
2347 :param digest: The message digest to use.
2348 :type digest: :py:class:`bytes`
2349
Dan Sully44e767a2016-06-04 18:05:27 -07002350 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002351 """
2352 if pkey._only_public:
2353 raise ValueError("Key has only public part")
2354
2355 if not pkey._initialized:
2356 raise ValueError("Key is uninitialized")
2357
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002358 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002359 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002360 raise ValueError("No such digest method")
2361
Alex Gaynor5945ea82015-09-05 14:59:06 -04002362 sign_result = _lib.NETSCAPE_SPKI_sign(
2363 self._spki, pkey._pkey, digest_obj
2364 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002365 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002366
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002367 def verify(self, key):
2368 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002369 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002370
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002371 :param key: The public key that signature is supposedly from.
2372 :type pkey: :py:class:`PKey`
2373
2374 :return: :py:const:`True` if the signature is correct.
2375 :rtype: :py:class:`bool`
2376
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002377 :raises Error: If the signature is invalid, or there was a problem
2378 verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002379 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002380 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002381 if answer <= 0:
2382 _raise_current_error()
2383 return True
2384
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002385 def b64_encode(self):
2386 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002387 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002388
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002389 :return: The base64 encoded string.
2390 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002391 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002392 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2393 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002394 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002395 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002396
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002397 def get_pubkey(self):
2398 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002399 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002400
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002401 :return: The public key.
2402 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002403 """
2404 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002405 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002406 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002407 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002408 pkey._only_public = True
2409 return pkey
2410
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002411 def set_pubkey(self, pkey):
2412 """
2413 Set the public key of the certificate
2414
2415 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002416 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002417 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002418 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002419 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002420
2421
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002422NetscapeSPKIType = NetscapeSPKI
2423
2424
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002425class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002426 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002427 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002428 raise ValueError(
2429 "only FILETYPE_PEM key format supports encryption"
2430 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002431 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002432 self._more_args = more_args
2433 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002434 self._problems = []
2435
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002436 @property
2437 def callback(self):
2438 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002439 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002440 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002441 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002442 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002443 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002444 else:
2445 raise TypeError("Last argument must be string or callable")
2446
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002447 @property
2448 def callback_args(self):
2449 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002450 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002451 elif isinstance(self._passphrase, bytes):
2452 return self._passphrase
2453 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002454 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002455 else:
2456 raise TypeError("Last argument must be string or callable")
2457
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002458 def raise_if_problem(self, exceptionType=Error):
2459 try:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05002460 _exception_from_error_queue(exceptionType)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002461 except exceptionType as e:
Jean-Paul Calderone9b4115f2014-01-10 14:06:04 -05002462 from_queue = e
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002463 if self._problems:
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002464 raise self._problems[0]
Jean-Paul Calderone9b4115f2014-01-10 14:06:04 -05002465 return from_queue
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002466
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002467 def _read_passphrase(self, buf, size, rwflag, userdata):
2468 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002469 if self._more_args:
2470 result = self._passphrase(size, rwflag, userdata)
2471 else:
2472 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002473 if not isinstance(result, bytes):
2474 raise ValueError("String expected")
2475 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002476 if self._truncate:
2477 result = result[:size]
2478 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002479 raise ValueError(
2480 "passphrase returned by callback is too long"
2481 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002482 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002483 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002484 return len(result)
2485 except Exception as e:
2486 self._problems.append(e)
2487 return 0
2488
2489
Cory Benfield6492f7c2015-10-27 16:57:58 +09002490def load_publickey(type, buffer):
2491 """
Cory Benfield11c10192015-10-27 17:23:03 +09002492 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002493
Cory Benfield9c590b92015-10-28 14:55:05 +09002494 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002495 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002496 :param buffer: The buffer the key is stored in.
2497 :type buffer: A Python string object, either unicode or bytestring.
2498 :return: The PKey object.
2499 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002500 """
2501 if isinstance(buffer, _text_type):
2502 buffer = buffer.encode("ascii")
2503
2504 bio = _new_mem_buf(buffer)
2505
2506 if type == FILETYPE_PEM:
2507 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2508 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2509 elif type == FILETYPE_ASN1:
2510 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2511 else:
2512 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2513
2514 if evp_pkey == _ffi.NULL:
2515 _raise_current_error()
2516
2517 pkey = PKey.__new__(PKey)
2518 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002519 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002520 return pkey
2521
2522
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002523def load_privatekey(type, buffer, passphrase=None):
2524 """
2525 Load a private key from a buffer
2526
2527 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2528 :param buffer: The buffer the key is stored in
2529 :param passphrase: (optional) if encrypted PEM format, this can be
2530 either the passphrase to use, or a callback for
2531 providing the passphrase.
2532
2533 :return: The PKey object
2534 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002535 if isinstance(buffer, _text_type):
2536 buffer = buffer.encode("ascii")
2537
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002538 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002539
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002540 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002541 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002542 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2543 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002544 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002545 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002546 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002547 else:
2548 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2549
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002550 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002551 _raise_current_error()
2552
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002553 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002554 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002555 return pkey
2556
2557
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002558def dump_certificate_request(type, req):
2559 """
2560 Dump a certificate request to a buffer
2561
2562 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2563 :param req: The certificate request to dump
2564 :return: The buffer with the dumped certificate request in
2565 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002566 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002567
2568 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002569 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002570 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002571 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002572 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002573 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002574 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002575 raise ValueError(
2576 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2577 "FILETYPE_TEXT"
2578 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002579
Alex Gaynor09a386e2016-07-03 09:32:44 -04002580 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002581
2582 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002583
2584
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002585def load_certificate_request(type, buffer):
2586 """
2587 Load a certificate request from a buffer
2588
2589 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2590 :param buffer: The buffer the certificate request is stored in
2591 :return: The X509Req object
2592 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002593 if isinstance(buffer, _text_type):
2594 buffer = buffer.encode("ascii")
2595
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002596 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002597
2598 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002599 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002600 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002601 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002602 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002603 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002604
Alex Gaynoradd5b072016-06-04 21:04:00 -07002605 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002606
2607 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002608 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002609 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002610
2611
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002612def sign(pkey, data, digest):
2613 """
2614 Sign data with a digest
2615
2616 :param pkey: Pkey to sign with
2617 :param data: data to be signed
2618 :param digest: message digest to use
2619 :return: signature
2620 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002621 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002622
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002623 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002624 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002625 raise ValueError("No such digest method")
2626
Alex Gaynor67903a62016-06-02 10:37:13 -07002627 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002628 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002629
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002630 _lib.EVP_SignInit(md_ctx, digest_obj)
2631 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002632
Colleen Murphye09399b2016-03-01 17:40:49 -08002633 pkey_length = (PKey.bits(pkey) + 7) // 8
2634 signature_buffer = _ffi.new("unsigned char[]", pkey_length)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002635 signature_length = _ffi.new("unsigned int*")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002636 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002637 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002638 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002639
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002640 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002641
2642
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002643def verify(cert, signature, data, digest):
2644 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002645 Verify a signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002646
2647 :param cert: signing certificate (X509 object)
2648 :param signature: signature returned by sign function
2649 :param data: data to be verified
2650 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002651 :return: ``None`` if the signature is correct, raise exception otherwise.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002652 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002653 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002654
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002655 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002656 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002657 raise ValueError("No such digest method")
2658
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002659 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002660 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002661 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002662
Alex Gaynor67903a62016-06-02 10:37:13 -07002663 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002664 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002665
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002666 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2667 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002668 verify_result = _lib.EVP_VerifyFinal(
2669 md_ctx, signature, len(signature), pkey
2670 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002671
2672 if verify_result != 1:
2673 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002674
2675
Dominic Chenf05b2122015-10-13 16:32:35 +00002676def dump_crl(type, crl):
2677 """
2678 Dump a certificate revocation list to a buffer.
2679
2680 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2681 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002682 :param CRL crl: The CRL to dump.
2683
Dominic Chenf05b2122015-10-13 16:32:35 +00002684 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002685 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002686 """
2687 bio = _new_mem_buf()
2688
2689 if type == FILETYPE_PEM:
2690 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2691 elif type == FILETYPE_ASN1:
2692 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2693 elif type == FILETYPE_TEXT:
2694 ret = _lib.X509_CRL_print(bio, crl._crl)
2695 else:
2696 raise ValueError(
2697 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2698 "FILETYPE_TEXT")
2699
2700 assert ret == 1
2701 return _bio_to_string(bio)
2702
2703
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002704def load_crl(type, buffer):
2705 """
2706 Load a certificate revocation list from a buffer
2707
2708 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2709 :param buffer: The buffer the CRL is stored in
2710
2711 :return: The PKey object
2712 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002713 if isinstance(buffer, _text_type):
2714 buffer = buffer.encode("ascii")
2715
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002716 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002717
2718 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002719 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002720 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002721 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002722 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002723 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2724
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002725 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002726 _raise_current_error()
2727
2728 result = CRL.__new__(CRL)
2729 result._crl = crl
2730 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002731
2732
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002733def load_pkcs7_data(type, buffer):
2734 """
2735 Load pkcs7 data from a buffer
2736
2737 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2738 :param buffer: The buffer with the pkcs7 data.
2739 :return: The PKCS7 object
2740 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002741 if isinstance(buffer, _text_type):
2742 buffer = buffer.encode("ascii")
2743
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002744 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002745
2746 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002747 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002748 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002749 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002750 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002751 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2752
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002753 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002754 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002755
2756 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002757 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002758 return pypkcs7
2759
2760
Stephen Holsapple38482622014-04-05 20:29:34 -07002761def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002762 """
2763 Load a PKCS12 object from a buffer
2764
2765 :param buffer: The buffer the certificate is stored in
2766 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2767 :returns: The PKCS12 object
2768 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002769 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002770
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002771 if isinstance(buffer, _text_type):
2772 buffer = buffer.encode("ascii")
2773
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002774 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002775
Stephen Holsapple38482622014-04-05 20:29:34 -07002776 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2777 # password based encryption no password and a zero length password are two
2778 # different things, but OpenSSL implementation will try both to figure out
2779 # which one works.
2780 if not passphrase:
2781 passphrase = _ffi.NULL
2782
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002783 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2784 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002785 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002786 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002787
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002788 pkey = _ffi.new("EVP_PKEY**")
2789 cert = _ffi.new("X509**")
2790 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002791
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002792 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002793 if not parse_result:
2794 _raise_current_error()
2795
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002796 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002797
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002798 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
2799 # queue for no particular reason. This error isn't interesting to anyone
2800 # outside this function. It's not even interesting to us. Get rid of it.
2801 try:
2802 _raise_current_error()
2803 except Error:
2804 pass
2805
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002806 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002807 pykey = None
2808 else:
2809 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002810 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002811
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002812 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002813 pycert = None
2814 friendlyname = None
2815 else:
2816 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002817 pycert._x509 = _ffi.gc(cert[0], _lib.X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002818
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002819 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04002820 friendlyname_buffer = _lib.X509_alias_get0(
2821 cert[0], friendlyname_length
2822 )
2823 friendlyname = _ffi.buffer(
2824 friendlyname_buffer, friendlyname_length[0]
2825 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002826 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002827 friendlyname = None
2828
2829 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002830 for i in range(_lib.sk_X509_num(cacerts)):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002831 pycacert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002832 pycacert._x509 = _lib.sk_X509_value(cacerts, i)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002833 pycacerts.append(pycacert)
2834 if not pycacerts:
2835 pycacerts = None
2836
2837 pkcs12 = PKCS12.__new__(PKCS12)
2838 pkcs12._pkey = pykey
2839 pkcs12._cert = pycert
2840 pkcs12._cacerts = pycacerts
2841 pkcs12._friendlyname = friendlyname
2842 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05002843
2844
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05002845# There are no direct unit tests for this initialization. It is tested
2846# indirectly since it is necessary for functions like dump_privatekey when
2847# using encryption.
2848#
2849# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
2850# and some other similar tests may fail without this (though they may not if
2851# the Python runtime has already done some initialization of the underlying
2852# OpenSSL library (and is linked against the same one that cryptography is
2853# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05002854_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05002855
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05002856# This is similar but exercised mainly by exception_from_error_queue. It calls
2857# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
2858_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002859
2860
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002861# Set the default string mask to match OpenSSL upstream (since 2005) and
2862# RFC5280 recommendations.
2863_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')