blob: 4f7e4d88f6aace1830ddb81d86051039273a4aa1 [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__
6
7from six import (
8 integer_types as _integer_types,
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -04009 text_type as _text_type,
10 PY3 as _PY3)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080011
Alex Gaynor9939ba12017-06-25 16:28:24 -040012from cryptography import x509
Paul Kehrer72d968b2016-07-29 15:31:04 +080013from cryptography.hazmat.primitives.asymmetric import dsa, rsa
Alex Gaynor10d30832017-06-29 15:31:39 -070014from cryptography.utils import deprecated
Paul Kehrer72d968b2016-07-29 15:31:04 +080015
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050016from OpenSSL._util import (
17 ffi as _ffi,
18 lib as _lib,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050019 exception_from_error_queue as _exception_from_error_queue,
20 byte_string as _byte_string,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040021 native as _native,
22 UNSPECIFIED as _UNSPECIFIED,
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -040023 text_to_bytes_and_warn as _text_to_bytes_and_warn,
Alex Gaynor67903a62016-06-02 10:37:13 -070024 make_assert as _make_assert,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040025)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080026
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050027FILETYPE_PEM = _lib.SSL_FILETYPE_PEM
28FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080029
30# TODO This was an API mistake. OpenSSL has no such constant.
31FILETYPE_TEXT = 2 ** 16 - 1
32
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050033TYPE_RSA = _lib.EVP_PKEY_RSA
34TYPE_DSA = _lib.EVP_PKEY_DSA
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -080035
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080036
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050037class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050038 """
39 An error occurred in an `OpenSSL.crypto` API.
40 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050041
42
43_raise_current_error = partial(_exception_from_error_queue, Error)
Alex Gaynor67903a62016-06-02 10:37:13 -070044_openssl_assert = _make_assert(Error)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050045
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070046
Paul Kehrereb633842016-10-06 11:22:01 +020047def _get_backend():
48 """
49 Importing the backend from cryptography has the side effect of activating
50 the osrandom engine. This mutates the global state of OpenSSL in the
51 process and causes issues for various programs that use subinterpreters or
52 embed Python. By putting the import in this function we can avoid
53 triggering this side effect unless _get_backend is called.
54 """
55 from cryptography.hazmat.backends.openssl.backend import backend
56 return backend
57
58
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050059def _untested_error(where):
60 """
61 An OpenSSL API failed somehow. Additionally, the failure which was
62 encountered isn't one that's exercised by the test suite so future behavior
63 of pyOpenSSL is now somewhat less predictable.
64 """
65 raise RuntimeError("Unknown %s failure" % (where,))
66
67
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050068def _new_mem_buf(buffer=None):
69 """
70 Allocate a new OpenSSL memory BIO.
71
72 Arrange for the garbage collector to clean it up automatically.
73
74 :param buffer: None or some bytes to use to put into the BIO so that they
75 can be read out.
76 """
77 if buffer is None:
78 bio = _lib.BIO_new(_lib.BIO_s_mem())
79 free = _lib.BIO_free
80 else:
81 data = _ffi.new("char[]", buffer)
82 bio = _lib.BIO_new_mem_buf(data, len(buffer))
Alex Gaynor5945ea82015-09-05 14:59:06 -040083
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050084 # Keep the memory alive as long as the bio is alive!
85 def free(bio, ref=data):
86 return _lib.BIO_free(bio)
87
Alex Gaynorfb8a2a12016-06-04 18:26:26 -070088 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050089
90 bio = _ffi.gc(bio, free)
91 return bio
92
93
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080094def _bio_to_string(bio):
95 """
96 Copy the contents of an OpenSSL BIO object into a Python byte string.
97 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050098 result_buffer = _ffi.new('char**')
99 buffer_length = _lib.BIO_get_mem_data(bio, result_buffer)
100 return _ffi.buffer(result_buffer[0], buffer_length)[:]
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800101
102
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800103def _set_asn1_time(boundary, when):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500104 """
105 The the time value of an ASN1 time object.
106
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900107 @param boundary: An ASN1_TIME pointer (or an object safely
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500108 castable to that type) which will have its value set.
109 @param when: A string representation of the desired time value.
110
111 @raise TypeError: If C{when} is not a L{bytes} string.
112 @raise ValueError: If C{when} does not represent a time in the required
113 format.
114 @raise RuntimeError: If the time value cannot be set for some other
115 (unspecified) reason.
116 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800117 if not isinstance(when, bytes):
118 raise TypeError("when must be a byte string")
119
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900120 set_result = _lib.ASN1_TIME_set_string(boundary, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800121 if set_result == 0:
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900122 raise ValueError("Invalid string")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800123
Alex Gaynor510293e2016-06-02 12:07:59 -0700124
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800125def _get_asn1_time(timestamp):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500126 """
127 Retrieve the time value of an ASN1 time object.
128
129 @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to
130 that type) from which the time value will be retrieved.
131
132 @return: The time value from C{timestamp} as a L{bytes} string in a certain
133 format. Or C{None} if the object contains no time value.
134 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500135 string_timestamp = _ffi.cast('ASN1_STRING*', timestamp)
136 if _lib.ASN1_STRING_length(string_timestamp) == 0:
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800137 return None
Alex Gaynor5945ea82015-09-05 14:59:06 -0400138 elif (
139 _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME
140 ):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500141 return _ffi.string(_lib.ASN1_STRING_data(string_timestamp))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800142 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500143 generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**")
144 _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp)
145 if generalized_timestamp[0] == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500146 # This may happen:
147 # - if timestamp was not an ASN1_TIME
148 # - if allocating memory for the ASN1_GENERALIZEDTIME failed
149 # - if a copy of the time data from timestamp cannot be made for
150 # the newly allocated ASN1_GENERALIZEDTIME
151 #
152 # These are difficult to test. cffi enforces the ASN1_TIME type.
153 # Memory allocation failures are a pain to trigger
154 # deterministically.
155 _untested_error("ASN1_TIME_to_generalizedtime")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800156 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500157 string_timestamp = _ffi.cast(
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800158 "ASN1_STRING*", generalized_timestamp[0])
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500159 string_data = _lib.ASN1_STRING_data(string_timestamp)
160 string_result = _ffi.string(string_data)
161 _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0])
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800162 return string_result
163
164
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800165class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200166 """
167 A class representing an DSA or RSA public key or key pair.
168 """
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800169 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800170 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800171
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800172 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500173 pkey = _lib.EVP_PKEY_new()
174 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800175 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800176
Paul Kehrer72d968b2016-07-29 15:31:04 +0800177 def to_cryptography_key(self):
178 """
179 Export as a ``cryptography`` key.
180
181 :rtype: One of ``cryptography``'s `key interfaces`_.
182
183 .. _key interfaces: https://cryptography.io/en/latest/hazmat/\
184 primitives/asymmetric/rsa/#key-interfaces
185
186 .. versionadded:: 16.1.0
187 """
Paul Kehrereb633842016-10-06 11:22:01 +0200188 backend = _get_backend()
Paul Kehrer72d968b2016-07-29 15:31:04 +0800189 if self._only_public:
190 return backend._evp_pkey_to_public_key(self._pkey)
191 else:
192 return backend._evp_pkey_to_private_key(self._pkey)
193
194 @classmethod
195 def from_cryptography_key(cls, crypto_key):
196 """
197 Construct based on a ``cryptography`` *crypto_key*.
198
199 :param crypto_key: A ``cryptography`` key.
200 :type crypto_key: One of ``cryptography``'s `key interfaces`_.
201
202 :rtype: PKey
203
204 .. versionadded:: 16.1.0
205 """
206 pkey = cls()
207 if not isinstance(crypto_key, (rsa.RSAPublicKey, rsa.RSAPrivateKey,
208 dsa.DSAPublicKey, dsa.DSAPrivateKey)):
209 raise TypeError("Unsupported key type")
210
211 pkey._pkey = crypto_key._evp_pkey
212 if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)):
213 pkey._only_public = True
214 pkey._initialized = True
215 return pkey
216
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800217 def generate_key(self, type, bits):
218 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700219 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800220
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200221 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800222
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200223 :param type: The key type.
224 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
225 :param bits: The number of bits.
226 :type bits: :py:data:`int` ``>= 0``
227 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
228 of the appropriate type.
229 :raises ValueError: If the number of bits isn't an integer of
230 the appropriate size.
Dan Sully44e767a2016-06-04 18:05:27 -0700231 :return: ``None``
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800232 """
233 if not isinstance(type, int):
234 raise TypeError("type must be an integer")
235
236 if not isinstance(bits, int):
237 raise TypeError("bits must be an integer")
238
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800239 # TODO Check error return
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500240 exponent = _lib.BN_new()
241 exponent = _ffi.gc(exponent, _lib.BN_free)
242 _lib.BN_set_word(exponent, _lib.RSA_F4)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800243
244 if type == TYPE_RSA:
245 if bits <= 0:
246 raise ValueError("Invalid number of bits")
247
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500248 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800249
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500250 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400251 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800252
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500253 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400254 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800255
256 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400257 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700258 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400259
260 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400261 res = _lib.DSA_generate_parameters_ex(
262 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
263 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700264 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400265
266 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
267 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800268 else:
269 raise Error("No such key type")
270
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800271 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800272
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800273 def check(self):
274 """
275 Check the consistency of an RSA private key.
276
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200277 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
278
Hynek Schlawack01c31672016-12-11 15:14:09 +0100279 :return: ``True`` if key is consistent.
280
281 :raise OpenSSL.crypto.Error: if the key is inconsistent.
282
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800283 :raise TypeError: if the key is of a type which cannot be checked.
284 Only RSA keys can currently be checked.
285 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800286 if self._only_public:
287 raise TypeError("public key only")
288
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100289 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800290 raise TypeError("key type unsupported")
291
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500292 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
293 rsa = _ffi.gc(rsa, _lib.RSA_free)
294 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800295 if result:
296 return True
297 _raise_current_error()
298
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800299 def type(self):
300 """
301 Returns the type of the key
302
303 :return: The type of the key.
304 """
Alex Gaynor0d2aec52017-05-31 04:26:27 -0400305 return _lib.EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800306
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800307 def bits(self):
308 """
309 Returns the number of bits of the key
310
311 :return: The number of bits of the key.
312 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500313 return _lib.EVP_PKEY_bits(self._pkey)
Alex Chanc6077062016-11-18 13:53:39 +0000314
315
Alex Gaynor10d30832017-06-29 15:31:39 -0700316PKeyType = deprecated(
317 PKey, __name__,
318 "PKeyType has been deprecated, use PKey instead",
319 DeprecationWarning
320)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800321
322
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400323class _EllipticCurve(object):
324 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400325 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400326
327 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
328 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
329 instances each of which represents one curve supported by the system.
330 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400331 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400332 _curves = None
333
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400334 if _PY3:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400335 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400336 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400337 """
338 Implement cooperation with the right-hand side argument of ``!=``.
339
340 Python 3 seems to have dropped this cooperation in this very narrow
341 circumstance.
342 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400343 if isinstance(other, _EllipticCurve):
344 return super(_EllipticCurve, self).__ne__(other)
345 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400346
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400347 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400348 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400349 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400350 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400351
352 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400353
354 :return: A :py:type:`set` of ``cls`` instances giving the names of the
355 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400356 """
Alex Chan84902a22017-04-20 11:50:47 +0100357 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
358 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
359 # The return value on this call should be num_curves again. We
360 # could check it to make sure but if it *isn't* then.. what could
361 # we do? Abort the whole process, I suppose...? -exarkun
362 lib.EC_get_builtin_curves(builtin_curves, num_curves)
363 return set(
364 cls.from_nid(lib, c.nid)
365 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400366
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400367 @classmethod
368 def _get_elliptic_curves(cls, lib):
369 """
370 Get, cache, and return the curves supported by OpenSSL.
371
372 :param lib: The OpenSSL library binding object.
373
374 :return: A :py:type:`set` of ``cls`` instances giving the names of the
375 elliptic curves the underlying library supports.
376 """
377 if cls._curves is None:
378 cls._curves = cls._load_elliptic_curves(lib)
379 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400380
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400381 @classmethod
382 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400383 """
384 Instantiate a new :py:class:`_EllipticCurve` associated with the given
385 OpenSSL NID.
386
387 :param lib: The OpenSSL library binding object.
388
389 :param nid: The OpenSSL NID the resulting curve object will represent.
390 This must be a curve NID (and not, for example, a hash NID) or
391 subsequent operations will fail in unpredictable ways.
392 :type nid: :py:class:`int`
393
394 :return: The curve object.
395 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400396 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
397
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400398 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400399 """
400 :param _lib: The :py:mod:`cryptography` binding instance used to
401 interface with OpenSSL.
402
403 :param _nid: The OpenSSL NID identifying the curve this object
404 represents.
405 :type _nid: :py:class:`int`
406
407 :param name: The OpenSSL short name identifying the curve this object
408 represents.
409 :type name: :py:class:`unicode`
410 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400411 self._lib = lib
412 self._nid = nid
413 self.name = name
414
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400415 def __repr__(self):
416 return "<Curve %r>" % (self.name,)
417
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400418 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400419 """
420 Create a new OpenSSL EC_KEY structure initialized to use this curve.
421
422 The structure is automatically garbage collected when the Python object
423 is garbage collected.
424 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400425 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
426 return _ffi.gc(key, _lib.EC_KEY_free)
427
428
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400429def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400430 """
431 Return a set of objects representing the elliptic curves supported in the
432 OpenSSL build in use.
433
434 The curve objects have a :py:class:`unicode` ``name`` attribute by which
435 they identify themselves.
436
437 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400438 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
439 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400440 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400441 return _EllipticCurve._get_elliptic_curves(_lib)
442
443
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400444def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400445 """
446 Return a single curve object selected by name.
447
448 See :py:func:`get_elliptic_curves` for information about curve objects.
449
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400450 :param name: The OpenSSL short name identifying the curve object to
451 retrieve.
452 :type name: :py:class:`unicode`
453
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400454 If the named curve is not supported then :py:class:`ValueError` is raised.
455 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400456 for curve in get_elliptic_curves():
457 if curve.name == name:
458 return curve
459 raise ValueError("unknown curve name", name)
460
461
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800462class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200463 """
464 An X.509 Distinguished Name.
465
466 :ivar countryName: The country of the entity.
467 :ivar C: Alias for :py:attr:`countryName`.
468
469 :ivar stateOrProvinceName: The state or province of the entity.
470 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
471
472 :ivar localityName: The locality of the entity.
473 :ivar L: Alias for :py:attr:`localityName`.
474
475 :ivar organizationName: The organization name of the entity.
476 :ivar O: Alias for :py:attr:`organizationName`.
477
478 :ivar organizationalUnitName: The organizational unit of the entity.
479 :ivar OU: Alias for :py:attr:`organizationalUnitName`
480
481 :ivar commonName: The common name of the entity.
482 :ivar CN: Alias for :py:attr:`commonName`.
483
484 :ivar emailAddress: The e-mail address of the entity.
485 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400486
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800487 def __init__(self, name):
488 """
489 Create a new X509Name, copying the given X509Name instance.
490
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200491 :param name: The name to copy.
492 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800493 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500494 name = _lib.X509_NAME_dup(name._name)
495 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800496
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800497 def __setattr__(self, name, value):
498 if name.startswith('_'):
499 return super(X509Name, self).__setattr__(name, value)
500
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800501 # Note: we really do not want str subclasses here, so we do not use
502 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800503 if type(name) is not str:
504 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400505 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800506
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500507 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500508 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800509 try:
510 _raise_current_error()
511 except Error:
512 pass
513 raise AttributeError("No such attribute")
514
515 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500516 for i in range(_lib.X509_NAME_entry_count(self._name)):
517 ent = _lib.X509_NAME_get_entry(self._name, i)
518 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
519 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800520 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500521 ent = _lib.X509_NAME_delete_entry(self._name, i)
522 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800523 break
524
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500525 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800526 value = value.encode('utf-8')
527
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500528 add_result = _lib.X509_NAME_add_entry_by_NID(
529 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800530 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500531 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800532
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800533 def __getattr__(self, name):
534 """
535 Find attribute. An X509Name object has the following attributes:
536 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400537 organization (alias O), organizationalUnit (alias OU), commonName
538 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800539 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500540 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500541 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800542 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
543 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
544 # push something onto the error queue. If we don't clean that up
545 # now, someone else will bump into it later and be quite confused.
546 # See lp#314814.
547 try:
548 _raise_current_error()
549 except Error:
550 pass
551 return super(X509Name, self).__getattr__(name)
552
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500553 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800554 if entry_index == -1:
555 return None
556
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500557 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
558 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800559
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500560 result_buffer = _ffi.new("unsigned char**")
561 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400562 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800563
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700564 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400565 result = _ffi.buffer(
566 result_buffer[0], data_length
567 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700568 finally:
569 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500570 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800571 return result
572
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500573 def _cmp(op):
574 def f(self, other):
575 if not isinstance(other, X509Name):
576 return NotImplemented
577 result = _lib.X509_NAME_cmp(self._name, other._name)
578 return op(result, 0)
579 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800580
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500581 __eq__ = _cmp(__eq__)
582 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800583
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500584 __lt__ = _cmp(__lt__)
585 __le__ = _cmp(__le__)
586
587 __gt__ = _cmp(__gt__)
588 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800589
590 def __repr__(self):
591 """
592 String representation of an X509Name
593 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400594 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500595 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800596 self._name, result_buffer, len(result_buffer))
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700597 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800598
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500599 return "<X509Name object '%s'>" % (
600 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800601
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800602 def hash(self):
603 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200604 Return an integer representation of the first four bytes of the
605 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800606
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200607 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
608
609 :return: The (integer) hash of this name.
610 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800611 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500612 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800613
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800614 def der(self):
615 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200616 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800617
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200618 :return: The DER encoded form of this name.
619 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800620 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500621 result_buffer = _ffi.new('unsigned char**')
622 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400623 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800624
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500625 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
626 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800627 return string_result
628
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800629 def get_components(self):
630 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200631 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800632
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200633 :return: The components of this name.
634 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800635 """
636 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500637 for i in range(_lib.X509_NAME_entry_count(self._name)):
638 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800639
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500640 fname = _lib.X509_NAME_ENTRY_get_object(ent)
641 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800642
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500643 nid = _lib.OBJ_obj2nid(fname)
644 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800645
646 result.append((
Alex Gaynora738ed52015-09-05 11:17:10 -0400647 _ffi.string(name),
648 _ffi.string(
649 _lib.ASN1_STRING_data(fval),
650 _lib.ASN1_STRING_length(fval))))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800651
652 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200653
654
Alex Gaynor10d30832017-06-29 15:31:39 -0700655X509NameType = deprecated(
656 X509Name, __name__,
657 "X509NameType has been deprecated, use X509Name instead",
658 DeprecationWarning
659)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800660
661
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800662class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200663 """
664 An X.509 v3 certificate extension.
665 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400666
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800667 def __init__(self, type_name, critical, value, subject=None, issuer=None):
668 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200669 Initializes an X509 extension.
670
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100671 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400672 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800673
Alex Gaynor5945ea82015-09-05 14:59:06 -0400674 :param bool critical: A flag indicating whether this is a critical
675 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800676
677 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200678 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800679
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200680 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800681 :type subject: :py:class:`X509`
682
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200683 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800684 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100685
Alex Chan54005ce2017-03-21 08:08:17 +0000686 .. _extension: https://www.openssl.org/docs/manmaster/man5/
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100687 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800688 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500689 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800690
Alex Gaynor5945ea82015-09-05 14:59:06 -0400691 # A context is necessary for any extension which uses the r2i
692 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
693 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500694 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800695
696 # We have no configuration database - but perhaps we should (some
697 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500698 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800699
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800700 # Initialize the subject and issuer, if appropriate. ctx is a local,
701 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400702 # any references, so no need to mess with reference counts or
703 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800704 if issuer is not None:
705 if not isinstance(issuer, X509):
706 raise TypeError("issuer must be an X509 instance")
707 ctx.issuer_cert = issuer._x509
708 if subject is not None:
709 if not isinstance(subject, X509):
710 raise TypeError("subject must be an X509 instance")
711 ctx.subject_cert = subject._x509
712
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800713 if critical:
714 # There are other OpenSSL APIs which would let us pass in critical
715 # separately, but they're harder to use, and since value is already
716 # a pile of crappy junk smuggling a ton of utterly important
717 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400718 # with strings? (However, X509V3_EXT_i2d in particular seems like
719 # it would be a better API to invoke. I do not know where to get
720 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500721 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800722
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500723 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
724 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800725 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500726 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800727
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400728 @property
729 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400730 return _lib.OBJ_obj2nid(
731 _lib.X509_EXTENSION_get_object(self._extension)
732 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400733
734 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500735 _lib.GEN_EMAIL: "email",
736 _lib.GEN_DNS: "DNS",
737 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400738 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400739
740 def _subjectAltNameString(self):
Alex Gaynord61c46a2017-06-29 22:51:33 -0700741 names = _ffi.cast(
742 "GENERAL_NAMES*", _lib.X509V3_EXT_d2i(self._extension)
743 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400744
Paul Kehrerb7d79502015-05-04 07:43:51 -0500745 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400746 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500747 for i in range(_lib.sk_GENERAL_NAME_num(names)):
748 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400749 try:
750 label = self._prefixes[name.type]
751 except KeyError:
752 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500753 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500754 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400755 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500756 value = _native(
757 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
758 parts.append(label + ":" + value)
759 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400760
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800761 def __str__(self):
762 """
763 :return: a nice text representation of the extension
764 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500765 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400766 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800767
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400768 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500769 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400770 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800771
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500772 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800773
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800774 def get_critical(self):
775 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200776 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800777
778 :return: The critical field.
779 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500780 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800781
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800782 def get_short_name(self):
783 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200784 Returns the short type name of this X.509 extension.
785
786 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800787
788 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200789 :rtype: :py:data:`bytes`
790
791 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800792 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500793 obj = _lib.X509_EXTENSION_get_object(self._extension)
794 nid = _lib.OBJ_obj2nid(obj)
795 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800796
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800797 def get_data(self):
798 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200799 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800800
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200801 :return: The ASN.1 encoded data of this X509 extension.
802 :rtype: :py:data:`bytes`
803
804 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800805 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500806 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
807 string_result = _ffi.cast('ASN1_STRING*', octet_result)
808 char_result = _lib.ASN1_STRING_data(string_result)
809 result_length = _lib.ASN1_STRING_length(string_result)
810 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800811
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200812
Alex Gaynor10d30832017-06-29 15:31:39 -0700813X509ExtensionType = deprecated(
814 X509Extension, __name__,
815 "X509ExtensionType has been deprecated, use X509Extension instead",
816 DeprecationWarning
817)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800818
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800819
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800820class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200821 """
822 An X.509 certificate signing requests.
823 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400824
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800825 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500826 req = _lib.X509_REQ_new()
827 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Alex Gaynor5af32d02016-09-24 01:52:21 -0400828 # Default to version 0.
829 self.set_version(0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800830
Paul Kehrer41c10242017-06-29 18:24:17 -0500831 def to_cryptography(self):
832 """
833 Export as a ``cryptography`` certificate signing request.
834
835 :rtype: ``cryptography.x509.CertificateSigningRequest``
836
837 .. versionadded:: 17.1.0
838 """
839 from cryptography.hazmat.backends.openssl.x509 import (
840 _CertificateSigningRequest
841 )
842 backend = _get_backend()
843 return _CertificateSigningRequest(backend, self._req)
844
845 @classmethod
846 def from_cryptography(cls, crypto_req):
847 """
848 Construct based on a ``cryptography`` *crypto_req*.
849
850 :param crypto_req: A ``cryptography`` X.509 certificate signing request
851 :type crypto_req: ``cryptography.x509.CertificateSigningRequest``
852
853 :rtype: PKey
854
855 .. versionadded:: 17.1.0
856 """
857 if not isinstance(crypto_req, x509.CertificateSigningRequest):
858 raise TypeError("Must be a certificate signing request")
859
860 req = cls()
861 req._req = crypto_req._x509_req
862 return req
863
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800864 def set_pubkey(self, pkey):
865 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200866 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800867
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200868 :param pkey: The public key to use.
869 :type pkey: :py:class:`PKey`
870
Dan Sully44e767a2016-06-04 18:05:27 -0700871 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800872 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500873 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400874 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800875
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800876 def get_pubkey(self):
877 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200878 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800879
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200880 :return: The public key.
881 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800882 """
883 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500884 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700885 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500886 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800887 pkey._only_public = True
888 return pkey
889
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800890 def set_version(self, version):
891 """
892 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
893 request.
894
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200895 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700896 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800897 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500898 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400899 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800900
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800901 def get_version(self):
902 """
903 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
904 request.
905
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200906 :return: The value of the version subfield.
907 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800908 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500909 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800910
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800911 def get_subject(self):
912 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200913 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800914
Cory Benfield881dc8d2015-12-09 08:25:14 +0000915 This creates a new :class:`X509Name` that wraps the underlying subject
916 name field on the certificate signing request. Modifying it will modify
917 the underlying signing request, and will have the effect of modifying
918 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200919
920 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000921 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800922 """
923 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500924 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700925 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800926
927 # The name is owned by the X509Req structure. As long as the X509Name
928 # Python object is alive, keep the X509Req Python object alive.
929 name._owner = self
930
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800931 return name
932
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800933 def add_extensions(self, extensions):
934 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200935 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800936
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200937 :param extensions: The X.509 extensions to add.
938 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700939 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800940 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500941 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700942 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800943
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500944 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800945
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800946 for ext in extensions:
947 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -0800948 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800949
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800950 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500951 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800952
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500953 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400954 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800955
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800956 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800957 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200958 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800959
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200960 :return: The X.509 extensions in this request.
961 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
962
963 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800964 """
965 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500966 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -0500967 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800968 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500969 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800970 exts.append(ext)
971 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800972
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800973 def sign(self, pkey, digest):
974 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -0700975 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800976
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200977 :param pkey: The key pair to sign with.
978 :type pkey: :py:class:`PKey`
979 :param digest: The name of the message digest to use for the signature,
Alex Gaynor239e2d32016-09-11 12:36:35 -0400980 e.g. :py:data:`b"sha256"`.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200981 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -0700982 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800983 """
984 if pkey._only_public:
985 raise ValueError("Key has only public part")
986
987 if not pkey._initialized:
988 raise ValueError("Key is uninitialized")
989
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500990 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500991 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800992 raise ValueError("No such digest method")
993
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500994 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400995 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800996
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800997 def verify(self, pkey):
998 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200999 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001000
Hynek Schlawack01c31672016-12-11 15:14:09 +01001001 :param PKey key: A public key.
1002
1003 :return: ``True`` if the signature is correct.
1004 :rtype: bool
1005
1006 :raises OpenSSL.crypto.Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001007 problem verifying the signature.
1008 """
1009 if not isinstance(pkey, PKey):
1010 raise TypeError("pkey must be a PKey instance")
1011
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001012 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001013 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001014 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001015
1016 return result
1017
1018
Alex Gaynor10d30832017-06-29 15:31:39 -07001019X509ReqType = deprecated(
1020 X509Req, __name__,
1021 "X509ReqType has been deprecated, use X509Req instead",
1022 DeprecationWarning
1023)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001024
1025
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001026class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001027 """
1028 An X.509 certificate.
1029 """
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001030 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001031 x509 = _lib.X509_new()
Hynek Schlawack8a2dd772016-07-31 13:46:20 +02001032 _openssl_assert(x509 != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001033 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001034
Alex Gaynor9939ba12017-06-25 16:28:24 -04001035 def to_cryptography(self):
1036 """
1037 Export as a ``cryptography`` certificate.
1038
1039 :rtype: ``cryptography.x509.Certificate``
1040
1041 .. versionadded:: 17.1.0
1042 """
1043 from cryptography.hazmat.backends.openssl.x509 import _Certificate
1044 backend = _get_backend()
1045 return _Certificate(backend, self._x509)
1046
1047 @classmethod
1048 def from_cryptography(cls, crypto_cert):
1049 """
1050 Construct based on a ``cryptography`` *crypto_cert*.
1051
1052 :param crypto_key: A ``cryptography`` X.509 certificate.
1053 :type crypto_key: ``cryptography.x509.Certificate``
1054
1055 :rtype: PKey
1056
1057 .. versionadded:: 17.1.0
1058 """
1059 if not isinstance(crypto_cert, x509.Certificate):
1060 raise TypeError("Must be a certificate")
1061
1062 cert = cls()
1063 cert._x509 = crypto_cert._x509
1064 return cert
1065
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001066 def set_version(self, version):
1067 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001068 Set the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001069
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001070 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001071 :type version: :py:class:`int`
1072
Dan Sully44e767a2016-06-04 18:05:27 -07001073 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001074 """
1075 if not isinstance(version, int):
1076 raise TypeError("version must be an integer")
1077
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001078 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001079
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001080 def get_version(self):
1081 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001082 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001083
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001084 :return: The version number of the certificate.
1085 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001086 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001087 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001088
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001089 def get_pubkey(self):
1090 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001091 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001092
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001093 :return: The public key.
1094 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001095 """
1096 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001097 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1098 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001099 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001100 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001101 pkey._only_public = True
1102 return pkey
1103
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001104 def set_pubkey(self, pkey):
1105 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001106 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001107
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001108 :param pkey: The public key.
1109 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001110
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001111 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001112 """
1113 if not isinstance(pkey, PKey):
1114 raise TypeError("pkey must be a PKey instance")
1115
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001116 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001117 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001118
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001119 def sign(self, pkey, digest):
1120 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001121 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001122
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001123 :param pkey: The key to sign with.
1124 :type pkey: :py:class:`PKey`
1125
1126 :param digest: The name of the message digest to use.
1127 :type digest: :py:class:`bytes`
1128
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001129 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001130 """
1131 if not isinstance(pkey, PKey):
1132 raise TypeError("pkey must be a PKey instance")
1133
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001134 if pkey._only_public:
1135 raise ValueError("Key only has public part")
1136
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001137 if not pkey._initialized:
1138 raise ValueError("Key is uninitialized")
1139
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001140 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001141 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001142 raise ValueError("No such digest method")
1143
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001144 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001145 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001146
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001147 def get_signature_algorithm(self):
1148 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001149 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001150
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001151 :return: The name of the algorithm.
1152 :rtype: :py:class:`bytes`
1153
1154 :raises ValueError: If the signature algorithm is undefined.
1155
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001156 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001157 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001158 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1159 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001160 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001161 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001162 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001163
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001164 def digest(self, digest_name):
1165 """
1166 Return the digest of the X509 object.
1167
1168 :param digest_name: The name of the digest algorithm to use.
1169 :type digest_name: :py:class:`bytes`
1170
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001171 :return: The digest of the object, formatted as
1172 :py:const:`b":"`-delimited hex pairs.
1173 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001174 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001175 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001176 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001177 raise ValueError("No such digest method")
1178
Paul Kehrer9f9113a2016-09-20 20:10:25 -05001179 result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001180 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001181 result_length[0] = len(result_buffer)
1182
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001183 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001184 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001185 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001186
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001187 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001188 b16encode(ch).upper() for ch
1189 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001190
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001191 def subject_name_hash(self):
1192 """
1193 Return the hash of the X509 subject.
1194
1195 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001196 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001197 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001198 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001199
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001200 def set_serial_number(self, serial):
1201 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001202 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001203
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001204 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001205 :type serial: :py:class:`int`
1206
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001207 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001208 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001209 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001210 raise TypeError("serial must be an integer")
1211
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001212 hex_serial = hex(serial)[2:]
1213 if not isinstance(hex_serial, bytes):
1214 hex_serial = hex_serial.encode('ascii')
1215
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001216 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001217
1218 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001219 # it. If bignum is still NULL after this call, then the return value
1220 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001221 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001222
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001223 if bignum_serial[0] == _ffi.NULL:
1224 set_result = _lib.ASN1_INTEGER_set(
1225 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001226 if set_result:
1227 # TODO Not tested
1228 _raise_current_error()
1229 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001230 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1231 _lib.BN_free(bignum_serial[0])
1232 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001233 # TODO Not tested
1234 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001235 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1236 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001237 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001238
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001239 def get_serial_number(self):
1240 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001241 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001242
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001243 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001244 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001245 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001246 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1247 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001248 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001249 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001250 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001251 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001252 serial = int(hexstring_serial, 16)
1253 return serial
1254 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001255 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001256 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001257 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001258
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001259 def gmtime_adj_notAfter(self, amount):
1260 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001261 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001262
Dan Sully44e767a2016-06-04 18:05:27 -07001263 :param int amount: The number of seconds by which to adjust the
1264 timestamp.
1265 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001266 """
1267 if not isinstance(amount, int):
1268 raise TypeError("amount must be an integer")
1269
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001270 notAfter = _lib.X509_get_notAfter(self._x509)
1271 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001272
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001273 def gmtime_adj_notBefore(self, amount):
1274 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001275 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001276
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001277 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001278 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001279 """
1280 if not isinstance(amount, int):
1281 raise TypeError("amount must be an integer")
1282
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001283 notBefore = _lib.X509_get_notBefore(self._x509)
1284 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001285
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001286 def has_expired(self):
1287 """
1288 Check whether the certificate has expired.
1289
Dan Sully44e767a2016-06-04 18:05:27 -07001290 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1291 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001292 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001293 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001294 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001295
Paul Kehrerfde45c92016-01-21 12:57:37 -06001296 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001297
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001298 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001299 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001300
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001301 def get_notBefore(self):
1302 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001303 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001304
Paul Kehrerce98ee62017-06-21 06:59:58 -10001305 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001306
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001307 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001308
Dan Sully44e767a2016-06-04 18:05:27 -07001309 :return: A timestamp string, or ``None`` if there is none.
1310 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001311 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001312 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001313
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001314 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001315 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001316
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001317 def set_notBefore(self, when):
1318 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001319 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001320
Paul Kehrerce98ee62017-06-21 06:59:58 -10001321 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001322
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001323 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001324
Dan Sully44e767a2016-06-04 18:05:27 -07001325 :param bytes when: A timestamp string.
1326 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001327 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001328 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001329
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001330 def get_notAfter(self):
1331 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001332 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001333
Paul Kehrerce98ee62017-06-21 06:59:58 -10001334 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001335
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001336 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001337
Dan Sully44e767a2016-06-04 18:05:27 -07001338 :return: A timestamp string, or ``None`` if there is none.
1339 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001340 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001341 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001342
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001343 def set_notAfter(self, when):
1344 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001345 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001346
Paul Kehrerce98ee62017-06-21 06:59:58 -10001347 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001348
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001349 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001350
Dan Sully44e767a2016-06-04 18:05:27 -07001351 :param bytes when: A timestamp string.
1352 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001353 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001354 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001355
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001356 def _get_name(self, which):
1357 name = X509Name.__new__(X509Name)
1358 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001359 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001360
1361 # The name is owned by the X509 structure. As long as the X509Name
1362 # Python object is alive, keep the X509 Python object alive.
1363 name._owner = self
1364
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001365 return name
1366
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001367 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001368 if not isinstance(name, X509Name):
1369 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001370 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001371 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001372
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001373 def get_issuer(self):
1374 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001375 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001376
Cory Benfielde6bcce82015-12-09 08:40:03 +00001377 This creates a new :class:`X509Name` that wraps the underlying issuer
1378 name field on the certificate. Modifying it will modify the underlying
1379 certificate, and will have the effect of modifying any other
1380 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001381
1382 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001383 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001384 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001385 return self._get_name(_lib.X509_get_issuer_name)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001386
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001387 def set_issuer(self, issuer):
1388 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001389 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001390
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001391 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001392 :type issuer: :py:class:`X509Name`
1393
Dan Sully44e767a2016-06-04 18:05:27 -07001394 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001395 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001396 return self._set_name(_lib.X509_set_issuer_name, issuer)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001397
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001398 def get_subject(self):
1399 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001400 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001401
Cory Benfielde6bcce82015-12-09 08:40:03 +00001402 This creates a new :class:`X509Name` that wraps the underlying subject
1403 name field on the certificate. Modifying it will modify the underlying
1404 certificate, and will have the effect of modifying any other
1405 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001406
1407 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001408 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001409 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001410 return self._get_name(_lib.X509_get_subject_name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001411
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001412 def set_subject(self, subject):
1413 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001414 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001415
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001416 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001417 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001418
Dan Sully44e767a2016-06-04 18:05:27 -07001419 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001420 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001421 return self._set_name(_lib.X509_set_subject_name, subject)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001422
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001423 def get_extension_count(self):
1424 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001425 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001426
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001427 :return: The number of extensions.
1428 :rtype: :py:class:`int`
1429
1430 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001431 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001432 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001433
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001434 def add_extensions(self, extensions):
1435 """
1436 Add extensions to the certificate.
1437
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001438 :param extensions: The extensions to add.
1439 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001440 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001441 """
1442 for ext in extensions:
1443 if not isinstance(ext, X509Extension):
1444 raise ValueError("One of the elements is not an X509Extension")
1445
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001446 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001447 if not add_result:
1448 _raise_current_error()
1449
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001450 def get_extension(self, index):
1451 """
1452 Get a specific extension of the certificate by index.
1453
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001454 Extensions on a certificate are kept in order. The index
1455 parameter selects which extension will be returned.
1456
1457 :param int index: The index of the extension to retrieve.
1458 :return: The extension at the specified index.
1459 :rtype: :py:class:`X509Extension`
1460 :raises IndexError: If the extension index was out of bounds.
1461
1462 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001463 """
1464 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001465 ext._extension = _lib.X509_get_ext(self._x509, index)
1466 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001467 raise IndexError("extension index out of bounds")
1468
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001469 extension = _lib.X509_EXTENSION_dup(ext._extension)
1470 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001471 return ext
1472
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001473
Alex Gaynor10d30832017-06-29 15:31:39 -07001474X509Type = deprecated(
1475 X509, __name__,
1476 "X509Type has been deprecated, use X509 instead",
1477 DeprecationWarning
1478)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001479
1480
Dan Sully44e767a2016-06-04 18:05:27 -07001481class X509StoreFlags(object):
1482 """
1483 Flags for X509 verification, used to change the behavior of
1484 :class:`X509Store`.
1485
1486 See `OpenSSL Verification Flags`_ for details.
1487
1488 .. _OpenSSL Verification Flags:
Alex Chan54005ce2017-03-21 08:08:17 +00001489 https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_flags.html
Dan Sully44e767a2016-06-04 18:05:27 -07001490 """
1491 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1492 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1493 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1494 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1495 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1496 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1497 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1498 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1499 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1500 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1501 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1502
1503
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001504class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001505 """
Dan Sully44e767a2016-06-04 18:05:27 -07001506 An X.509 store.
1507
1508 An X.509 store is used to describe a context in which to verify a
1509 certificate. A description of a context may include a set of certificates
1510 to trust, a set of certificate revocation lists, verification flags and
1511 more.
1512
1513 An X.509 store, being only a description, cannot be used by itself to
1514 verify a certificate. To carry out the actual verification process, see
1515 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001516 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001517
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001518 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001519 store = _lib.X509_STORE_new()
1520 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001521
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001522 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001523 """
Dan Sully44e767a2016-06-04 18:05:27 -07001524 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001525
Dan Sully44e767a2016-06-04 18:05:27 -07001526 Adding a certificate with this method adds this certificate as a
1527 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001528
1529 :param X509 cert: The certificate to add to this store.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001530
Dan Sully44e767a2016-06-04 18:05:27 -07001531 :raises TypeError: If the certificate is not an :class:`X509`.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001532
1533 :raises OpenSSL.crypto.Error: If OpenSSL was unhappy with your
1534 certificate.
1535
Dan Sully44e767a2016-06-04 18:05:27 -07001536 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001537 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001538 if not isinstance(cert, X509):
1539 raise TypeError()
1540
Dan Sully44e767a2016-06-04 18:05:27 -07001541 _openssl_assert(_lib.X509_STORE_add_cert(self._store, cert._x509) != 0)
1542
1543 def add_crl(self, crl):
1544 """
1545 Add a certificate revocation list to this store.
1546
1547 The certificate revocation lists added to a store will only be used if
1548 the associated flags are configured to check certificate revocation
1549 lists.
1550
1551 .. versionadded:: 16.1.0
1552
1553 :param CRL crl: The certificate revocation list to add to this store.
1554 :return: ``None`` if the certificate revocation list was added
1555 successfully.
1556 """
1557 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1558
1559 def set_flags(self, flags):
1560 """
1561 Set verification flags to this store.
1562
1563 Verification flags can be combined by oring them together.
1564
1565 .. note::
1566
1567 Setting a verification flag sometimes requires clients to add
1568 additional information to the store, otherwise a suitable error will
1569 be raised.
1570
1571 For example, in setting flags to enable CRL checking a
1572 suitable CRL must be added to the store otherwise an error will be
1573 raised.
1574
1575 .. versionadded:: 16.1.0
1576
1577 :param int flags: The verification flags to set on this store.
1578 See :class:`X509StoreFlags` for available constants.
1579 :return: ``None`` if the verification flags were successfully set.
1580 """
1581 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001582
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001583 def set_time(self, vfy_time):
1584 """
1585 Set the time against which the certificates are verified.
1586
1587 Normally the current time is used.
1588
1589 .. note::
1590
1591 For example, you can determine if a certificate was valid at a given
1592 time.
1593
Hynek Schlawackf6c96af2017-04-20 12:34:58 +02001594 .. versionadded:: 17.0.0
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001595
1596 :param datetime vfy_time: The verification time to set on this store.
1597 :return: ``None`` if the verification time was successfully set.
1598 """
1599 param = _lib.X509_VERIFY_PARAM_new()
1600 param = _ffi.gc(param, _lib.X509_VERIFY_PARAM_free)
1601
1602 _lib.X509_VERIFY_PARAM_set_time(param, int(vfy_time.strftime('%s')))
1603 _openssl_assert(_lib.X509_STORE_set1_param(self._store, param) != 0)
1604
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001605
Alex Gaynor10d30832017-06-29 15:31:39 -07001606X509StoreType = deprecated(
1607 X509Store, __name__,
1608 "X509StoreType has been deprecated, use X509Store instead",
1609 DeprecationWarning
1610)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001611
1612
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001613class X509StoreContextError(Exception):
1614 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001615 An exception raised when an error occurred while verifying a certificate
1616 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001617
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001618 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001619 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001620 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001621
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001622 def __init__(self, message, certificate):
1623 super(X509StoreContextError, self).__init__(message)
1624 self.certificate = certificate
1625
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001626
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001627class X509StoreContext(object):
1628 """
1629 An X.509 store context.
1630
Dan Sully44e767a2016-06-04 18:05:27 -07001631 An X.509 store context is used to carry out the actual verification process
1632 of a certificate in a described context. For describing such a context, see
1633 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001634
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001635 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1636 instance. It is dynamically allocated and automatically garbage
1637 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001638 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001639 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001640 :param X509Store store: The certificates which will be trusted for the
1641 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001642 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001643 """
1644
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001645 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001646 store_ctx = _lib.X509_STORE_CTX_new()
1647 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1648 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001649 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001650 # Make the store context available for use after instantiating this
1651 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001652 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001653 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001654
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001655 def _init(self):
1656 """
1657 Set up the store context for a subsequent verification operation.
1658 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001659 ret = _lib.X509_STORE_CTX_init(
1660 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1661 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001662 if ret <= 0:
1663 _raise_current_error()
1664
1665 def _cleanup(self):
1666 """
1667 Internally cleans up the store context.
1668
Dan Sully44e767a2016-06-04 18:05:27 -07001669 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001670 """
1671 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1672
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001673 def _exception_from_context(self):
1674 """
1675 Convert an OpenSSL native context error failure into a Python
1676 exception.
1677
Alex Gaynor5945ea82015-09-05 14:59:06 -04001678 When a call to native OpenSSL X509_verify_cert fails, additional
1679 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001680 """
1681 errors = [
1682 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1683 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1684 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001685 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001686 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001687 # A context error should always be associated with a certificate, so we
1688 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001689 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001690 _cert = _lib.X509_dup(_x509)
1691 pycert = X509.__new__(X509)
1692 pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001693 return X509StoreContextError(errors, pycert)
1694
Stephen Holsapple46a09252015-02-12 14:45:43 -08001695 def set_store(self, store):
1696 """
Dan Sully44e767a2016-06-04 18:05:27 -07001697 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001698
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001699 .. versionadded:: 0.15
1700
Dan Sully44e767a2016-06-04 18:05:27 -07001701 :param X509Store store: The store description which will be used for
1702 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001703 """
1704 self._store = store
1705
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001706 def verify_certificate(self):
1707 """
1708 Verify a certificate in a context.
1709
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001710 .. versionadded:: 0.15
1711
Alex Gaynorca87ff62015-09-04 23:31:03 -04001712 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001713 certificate in the context. Sets ``certificate`` attribute to
1714 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001715 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001716 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001717 # :meth:`verify_certificate` is called multiple times.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001718 self._init()
1719 ret = _lib.X509_verify_cert(self._store_ctx)
1720 self._cleanup()
1721 if ret <= 0:
1722 raise self._exception_from_context()
1723
1724
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001725def load_certificate(type, buffer):
1726 """
1727 Load a certificate from a buffer
1728
1729 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1730
Dan Sully44e767a2016-06-04 18:05:27 -07001731 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001732
1733 :return: The X509 object
1734 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001735 if isinstance(buffer, _text_type):
1736 buffer = buffer.encode("ascii")
1737
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001738 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001739
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001740 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001741 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001742 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001743 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001744 else:
1745 raise ValueError(
1746 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001747
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001748 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001749 _raise_current_error()
1750
1751 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001752 cert._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001753 return cert
1754
1755
1756def dump_certificate(type, cert):
1757 """
1758 Dump a certificate to a buffer
1759
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001760 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1761 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001762 :param cert: The certificate to dump
1763 :return: The buffer with the dumped certificate in
1764 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001765 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001766
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001767 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001768 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001769 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001770 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001771 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001772 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001773 else:
1774 raise ValueError(
1775 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1776 "FILETYPE_TEXT")
1777
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001778 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001779 return _bio_to_string(bio)
1780
1781
Cory Benfield6492f7c2015-10-27 16:57:58 +09001782def dump_publickey(type, pkey):
1783 """
Cory Benfield11c10192015-10-27 17:23:03 +09001784 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001785
Cory Benfield9c590b92015-10-28 14:55:05 +09001786 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001787 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001788 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001789 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001790 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001791 """
1792 bio = _new_mem_buf()
1793 if type == FILETYPE_PEM:
1794 write_bio = _lib.PEM_write_bio_PUBKEY
1795 elif type == FILETYPE_ASN1:
1796 write_bio = _lib.i2d_PUBKEY_bio
1797 else:
1798 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1799
1800 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001801 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001802 _raise_current_error()
1803
1804 return _bio_to_string(bio)
1805
1806
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001807def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1808 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001809 Dump the private key *pkey* into a buffer string encoded with the type
1810 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1811 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001812
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001813 :param type: The file type (one of :const:`FILETYPE_PEM`,
1814 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1815 :param PKey pkey: The PKey to dump
1816 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001817 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001818 the passphrase to use, or a callback for providing the passphrase.
1819
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001820 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001821 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001822 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001823 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001824
Paul Kehrercded9932017-06-29 18:43:42 -05001825 if not isinstance(pkey, PKey):
1826 raise TypeError("pkey must be a PKey")
1827
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001828 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001829 if passphrase is None:
1830 raise TypeError(
1831 "if a value is given for cipher "
1832 "one must also be given for passphrase")
1833 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001834 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001835 raise ValueError("Invalid cipher name")
1836 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001837 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001838
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001839 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001840 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001841 result_code = _lib.PEM_write_bio_PrivateKey(
1842 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001843 helper.callback, helper.callback_args)
1844 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001845 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001846 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001847 elif type == FILETYPE_TEXT:
Paul Kehrercded9932017-06-29 18:43:42 -05001848 if _lib.EVP_PKEY_id(pkey._pkey) != _lib.EVP_PKEY_RSA:
1849 raise TypeError("Only RSA keys are supported for FILETYPE_TEXT")
1850
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001851 rsa = _ffi.gc(
1852 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1853 _lib.RSA_free
1854 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001855 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001856 else:
1857 raise ValueError(
1858 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1859 "FILETYPE_TEXT")
1860
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001861 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001862
1863 return _bio_to_string(bio)
1864
1865
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001866class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001867 """
1868 A certificate revocation.
1869 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001870 # http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_
1871 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1872 # OCSP_crl_reason_str. We use the latter, just like the command line
1873 # program.
1874 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001875 b"unspecified",
1876 b"keyCompromise",
1877 b"CACompromise",
1878 b"affiliationChanged",
1879 b"superseded",
1880 b"cessationOfOperation",
1881 b"certificateHold",
1882 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001883 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001884
1885 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001886 revoked = _lib.X509_REVOKED_new()
1887 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001888
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001889 def set_serial(self, hex_str):
1890 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001891 Set the serial number.
1892
1893 The serial number is formatted as a hexadecimal number encoded in
1894 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001895
Dan Sully44e767a2016-06-04 18:05:27 -07001896 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001897
Dan Sully44e767a2016-06-04 18:05:27 -07001898 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001899 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001900 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1901 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001902 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001903 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001904 if not bn_result:
1905 raise ValueError("bad hex string")
1906
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001907 asn1_serial = _ffi.gc(
1908 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1909 _lib.ASN1_INTEGER_free)
1910 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001911
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001912 def get_serial(self):
1913 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001914 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001915
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001916 The serial number is formatted as a hexadecimal number encoded in
1917 ASCII.
1918
1919 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001920 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001921 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001922 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001923
Alex Gaynor67903a62016-06-02 10:37:13 -07001924 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1925 _openssl_assert(asn1_int != _ffi.NULL)
1926 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1927 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001928 return _bio_to_string(bio)
1929
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001930 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001931 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1932 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001933 obj = _lib.X509_EXTENSION_get_object(ext)
1934 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001935 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001936 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001937 break
1938
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001939 def set_reason(self, reason):
1940 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001941 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001942
Dan Sully44e767a2016-06-04 18:05:27 -07001943 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001944
1945 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07001946 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001947
Dan Sully44e767a2016-06-04 18:05:27 -07001948 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001949
1950 .. seealso::
1951
Dan Sully44e767a2016-06-04 18:05:27 -07001952 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001953 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001954 """
1955 if reason is None:
1956 self._delete_reason()
1957 elif not isinstance(reason, bytes):
1958 raise TypeError("reason must be None or a byte string")
1959 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001960 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001961 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
1962
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001963 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07001964 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001965 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001966
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001967 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001968 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001969
1970 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001971 add_result = _lib.X509_REVOKED_add1_ext_i2d(
1972 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001973 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001974
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001975 def get_reason(self):
1976 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04001977 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001978
Dan Sully44e767a2016-06-04 18:05:27 -07001979 :return: The reason, or ``None`` if there is none.
1980 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001981
1982 .. seealso::
1983
Dan Sully44e767a2016-06-04 18:05:27 -07001984 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001985 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001986 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001987 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1988 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001989 obj = _lib.X509_EXTENSION_get_object(ext)
1990 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001991 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001992
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001993 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001994 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04001995 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001996 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04001997 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04001998 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001999
2000 return _bio_to_string(bio)
2001
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002002 def all_reasons(self):
2003 """
2004 Return a list of all the supported reason strings.
2005
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002006 This list is a copy; modifying it does not change the supported reason
2007 strings.
2008
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002009 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07002010 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002011 """
2012 return self._crl_reasons[:]
2013
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002014 def set_rev_date(self, when):
2015 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002016 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002017
Dan Sully44e767a2016-06-04 18:05:27 -07002018 :param bytes when: The timestamp of the revocation,
Paul Kehrerce98ee62017-06-21 06:59:58 -10002019 as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002020 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002021 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002022 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2023 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002024
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002025 def get_rev_date(self):
2026 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002027 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002028
Paul Kehrerce98ee62017-06-21 06:59:58 -10002029 :return: The timestamp of the revocation, as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002030 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002031 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002032 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2033 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002034
2035
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002036class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002037 """
2038 A certificate revocation list.
2039 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002040
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002041 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002042 crl = _lib.X509_CRL_new()
2043 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002044
Paul Kehrer41c10242017-06-29 18:24:17 -05002045 def to_cryptography(self):
2046 """
2047 Export as a ``cryptography`` CRL.
2048
2049 :rtype: ``cryptography.x509.CertificateRevocationList``
2050
2051 .. versionadded:: 17.1.0
2052 """
2053 from cryptography.hazmat.backends.openssl.x509 import (
2054 _CertificateRevocationList
2055 )
2056 backend = _get_backend()
2057 return _CertificateRevocationList(backend, self._crl)
2058
2059 @classmethod
2060 def from_cryptography(cls, crypto_crl):
2061 """
2062 Construct based on a ``cryptography`` *crypto_crl*.
2063
2064 :param crypto_crl: A ``cryptography`` certificate revocation list
2065 :type crypto_crl: ``cryptography.x509.CertificateRevocationList``
2066
2067 :rtype: CRL
2068
2069 .. versionadded:: 17.1.0
2070 """
2071 if not isinstance(crypto_crl, x509.CertificateRevocationList):
2072 raise TypeError("Must be a certificate revocation list")
2073
2074 crl = cls()
2075 crl._crl = crypto_crl._x509_crl
2076 return crl
2077
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002078 def get_revoked(self):
2079 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002080 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002081
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002082 These revocations will be provided by value, not by reference.
2083 That means it's okay to mutate them: it won't affect this CRL.
2084
2085 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002086 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002087 """
2088 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07002089 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002090 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
2091 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04002092 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002093 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002094 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002095 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002096 if results:
2097 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002098
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002099 def add_revoked(self, revoked):
2100 """
2101 Add a revoked (by value not reference) to the CRL structure
2102
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002103 This revocation will be added by value, not by reference. That
2104 means it's okay to mutate it after adding: it won't affect
2105 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002106
Dan Sully44e767a2016-06-04 18:05:27 -07002107 :param Revoked revoked: The new revocation.
2108 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002109 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04002110 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002111 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002112
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002113 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002114 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002115
Dan Sully44e767a2016-06-04 18:05:27 -07002116 def get_issuer(self):
2117 """
2118 Get the CRL's issuer.
2119
2120 .. versionadded:: 16.1.0
2121
2122 :rtype: X509Name
2123 """
2124 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
2125 _openssl_assert(_issuer != _ffi.NULL)
2126 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
2127 issuer = X509Name.__new__(X509Name)
2128 issuer._name = _issuer
2129 return issuer
2130
2131 def set_version(self, version):
2132 """
2133 Set the CRL version.
2134
2135 .. versionadded:: 16.1.0
2136
2137 :param int version: The version of the CRL.
2138 :return: ``None``
2139 """
2140 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2141
2142 def _set_boundary_time(self, which, when):
2143 return _set_asn1_time(which(self._crl), when)
2144
2145 def set_lastUpdate(self, when):
2146 """
2147 Set when the CRL was last updated.
2148
Paul Kehrerce98ee62017-06-21 06:59:58 -10002149 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002150
2151 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002152
2153 .. versionadded:: 16.1.0
2154
2155 :param bytes when: A timestamp string.
2156 :return: ``None``
2157 """
2158 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2159
2160 def set_nextUpdate(self, when):
2161 """
2162 Set when the CRL will next be udpated.
2163
Paul Kehrerce98ee62017-06-21 06:59:58 -10002164 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002165
2166 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002167
2168 .. versionadded:: 16.1.0
2169
2170 :param bytes when: A timestamp string.
2171 :return: ``None``
2172 """
2173 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2174
2175 def sign(self, issuer_cert, issuer_key, digest):
2176 """
2177 Sign the CRL.
2178
2179 Signing a CRL enables clients to associate the CRL itself with an
2180 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2181 be signed by an issuer.
2182
2183 This method implicitly sets the issuer's name based on the issuer
2184 certificate and private key used to sign the CRL.
2185
2186 .. versionadded:: 16.1.0
2187
2188 :param X509 issuer_cert: The issuer's certificate.
2189 :param PKey issuer_key: The issuer's private key.
2190 :param bytes digest: The digest method to sign the CRL with.
2191 """
2192 digest_obj = _lib.EVP_get_digestbyname(digest)
2193 _openssl_assert(digest_obj != _ffi.NULL)
2194 _lib.X509_CRL_set_issuer_name(
2195 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2196 _lib.X509_CRL_sort(self._crl)
2197 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2198 _openssl_assert(result != 0)
2199
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002200 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002201 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002202 """
Dan Sully44e767a2016-06-04 18:05:27 -07002203 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002204
Dan Sully44e767a2016-06-04 18:05:27 -07002205 :param X509 cert: The certificate used to sign the CRL.
2206 :param PKey key: The key used to sign the CRL.
2207 :param int type: The export format, either :data:`FILETYPE_PEM`,
2208 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002209 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002210 :param bytes digest: The name of the message digest to use (eg
Alex Gaynor239e2d32016-09-11 12:36:35 -04002211 ``b"sha2566"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002212 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002213 """
Dan Sully44e767a2016-06-04 18:05:27 -07002214
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002215 if not isinstance(cert, X509):
2216 raise TypeError("cert must be an X509 instance")
2217 if not isinstance(key, PKey):
2218 raise TypeError("key must be a PKey instance")
2219 if not isinstance(type, int):
2220 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002221
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002222 if digest is _UNSPECIFIED:
Alex Gaynor173e4ba2017-06-30 08:01:12 -07002223 raise TypeError("digest must be provided")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002224
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002225 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002226 if digest_obj == _ffi.NULL:
2227 raise ValueError("No such digest method")
2228
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002229 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002230 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002231
Alex Gaynora738ed52015-09-05 11:17:10 -04002232 # A scratch time object to give different values to different CRL
2233 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002234 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002235 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002236
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002237 _lib.X509_gmtime_adj(sometime, 0)
2238 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002239
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002240 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2241 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002242
Alex Gaynor5945ea82015-09-05 14:59:06 -04002243 _lib.X509_CRL_set_issuer_name(
2244 self._crl, _lib.X509_get_subject_name(cert._x509)
2245 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002246
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002247 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002248 if not sign_result:
2249 _raise_current_error()
2250
Dominic Chenf05b2122015-10-13 16:32:35 +00002251 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002252
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002253
Alex Gaynor10d30832017-06-29 15:31:39 -07002254CRLType = deprecated(
2255 CRL, __name__,
2256 "CRLType has been deprecated, use CRL instead",
2257 DeprecationWarning
2258)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002259
2260
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002261class PKCS7(object):
2262 def type_is_signed(self):
2263 """
2264 Check if this NID_pkcs7_signed object
2265
2266 :return: True if the PKCS7 is of type signed
2267 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002268 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002269
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002270 def type_is_enveloped(self):
2271 """
2272 Check if this NID_pkcs7_enveloped object
2273
2274 :returns: True if the PKCS7 is of type enveloped
2275 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002276 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002277
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002278 def type_is_signedAndEnveloped(self):
2279 """
2280 Check if this NID_pkcs7_signedAndEnveloped object
2281
2282 :returns: True if the PKCS7 is of type signedAndEnveloped
2283 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002284 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002285
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002286 def type_is_data(self):
2287 """
2288 Check if this NID_pkcs7_data object
2289
2290 :return: True if the PKCS7 is of type data
2291 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002292 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002293
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002294 def get_type_name(self):
2295 """
2296 Returns the type name of the PKCS7 structure
2297
2298 :return: A string with the typename
2299 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002300 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2301 string_type = _lib.OBJ_nid2sn(nid)
2302 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002303
Alex Chanc6077062016-11-18 13:53:39 +00002304
Alex Gaynor10d30832017-06-29 15:31:39 -07002305PKCS7Type = deprecated(
2306 PKCS7, __name__,
2307 "PKCS7Type has been deprecated, use PKCS7 instead",
2308 DeprecationWarning
2309)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002310
2311
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002312class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002313 """
2314 A PKCS #12 archive.
2315 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002316
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002317 def __init__(self):
2318 self._pkey = None
2319 self._cert = None
2320 self._cacerts = None
2321 self._friendlyname = None
2322
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002323 def get_certificate(self):
2324 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002325 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002326
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002327 :return: The certificate, or :py:const:`None` if there is none.
2328 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002329 """
2330 return self._cert
2331
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002332 def set_certificate(self, cert):
2333 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002334 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002335
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002336 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002337 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002338
Dan Sully44e767a2016-06-04 18:05:27 -07002339 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002340 """
2341 if not isinstance(cert, X509):
2342 raise TypeError("cert must be an X509 instance")
2343 self._cert = cert
2344
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002345 def get_privatekey(self):
2346 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002347 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002348
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002349 :return: The private key, or :py:const:`None` if there is none.
2350 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002351 """
2352 return self._pkey
2353
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002354 def set_privatekey(self, pkey):
2355 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002356 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002357
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002358 :param pkey: The new private key, or :py:const:`None` to unset it.
2359 :type pkey: :py:class:`PKey` or :py:const:`None`
2360
Dan Sully44e767a2016-06-04 18:05:27 -07002361 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002362 """
2363 if not isinstance(pkey, PKey):
2364 raise TypeError("pkey must be a PKey instance")
2365 self._pkey = pkey
2366
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002367 def get_ca_certificates(self):
2368 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002369 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002370
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002371 :return: A tuple with the CA certificates in the chain, or
2372 :py:const:`None` if there are none.
2373 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002374 """
2375 if self._cacerts is not None:
2376 return tuple(self._cacerts)
2377
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002378 def set_ca_certificates(self, cacerts):
2379 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002380 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002381
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002382 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2383 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002384 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002385
Dan Sully44e767a2016-06-04 18:05:27 -07002386 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002387 """
2388 if cacerts is None:
2389 self._cacerts = None
2390 else:
2391 cacerts = list(cacerts)
2392 for cert in cacerts:
2393 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002394 raise TypeError(
2395 "iterable must only contain X509 instances"
2396 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002397 self._cacerts = cacerts
2398
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002399 def set_friendlyname(self, name):
2400 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002401 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002402
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002403 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002404 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002405
Dan Sully44e767a2016-06-04 18:05:27 -07002406 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002407 """
2408 if name is None:
2409 self._friendlyname = None
2410 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002411 raise TypeError(
2412 "name must be a byte string or None (not %r)" % (name,)
2413 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002414 self._friendlyname = name
2415
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002416 def get_friendlyname(self):
2417 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002418 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002419
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002420 :returns: The friendly name, or :py:const:`None` if there is none.
2421 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002422 """
2423 return self._friendlyname
2424
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002425 def export(self, passphrase=None, iter=2048, maciter=1):
2426 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002427 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002428
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002429 For more information, see the :c:func:`PKCS12_create` man page.
2430
2431 :param passphrase: The passphrase used to encrypt the structure. Unlike
2432 some other passphrase arguments, this *must* be a string, not a
2433 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002434 :type passphrase: :py:data:`bytes`
2435
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002436 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002437 :type iter: :py:data:`int`
2438
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002439 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002440 :type maciter: :py:data:`int`
2441
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002442 :return: The string representation of the PKCS #12 structure.
2443 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002444 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002445 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002446
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002447 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002448 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002449 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002450 cacerts = _lib.sk_X509_new_null()
2451 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002452 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002453 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002454
2455 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002456 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002457
2458 friendlyname = self._friendlyname
2459 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002460 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002461
2462 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002463 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002464 else:
2465 pkey = self._pkey._pkey
2466
2467 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002468 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002469 else:
2470 cert = self._cert._x509
2471
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002472 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002473 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002474 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2475 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002476 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002477 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002478 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002479 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002480
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002481 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002482 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002483 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002484
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002485
Alex Gaynor10d30832017-06-29 15:31:39 -07002486PKCS12Type = deprecated(
2487 PKCS12, __name__,
2488 "PKCS12Type has been deprecated, use PKCS12 instead",
2489 DeprecationWarning
2490)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002491
2492
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002493class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002494 """
2495 A Netscape SPKI object.
2496 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002497
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002498 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002499 spki = _lib.NETSCAPE_SPKI_new()
2500 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002501
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002502 def sign(self, pkey, digest):
2503 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002504 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002505
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002506 :param pkey: The private key to sign with.
2507 :type pkey: :py:class:`PKey`
2508
2509 :param digest: The message digest to use.
2510 :type digest: :py:class:`bytes`
2511
Dan Sully44e767a2016-06-04 18:05:27 -07002512 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002513 """
2514 if pkey._only_public:
2515 raise ValueError("Key has only public part")
2516
2517 if not pkey._initialized:
2518 raise ValueError("Key is uninitialized")
2519
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002520 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002521 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002522 raise ValueError("No such digest method")
2523
Alex Gaynor5945ea82015-09-05 14:59:06 -04002524 sign_result = _lib.NETSCAPE_SPKI_sign(
2525 self._spki, pkey._pkey, digest_obj
2526 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002527 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002528
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002529 def verify(self, key):
2530 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002531 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002532
Hynek Schlawack01c31672016-12-11 15:14:09 +01002533 :param PKey key: The public key that signature is supposedly from.
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002534
Hynek Schlawack01c31672016-12-11 15:14:09 +01002535 :return: ``True`` if the signature is correct.
2536 :rtype: bool
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002537
Hynek Schlawack01c31672016-12-11 15:14:09 +01002538 :raises OpenSSL.crypto.Error: If the signature is invalid, or there was
2539 a problem verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002540 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002541 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002542 if answer <= 0:
2543 _raise_current_error()
2544 return True
2545
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002546 def b64_encode(self):
2547 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002548 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002549
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002550 :return: The base64 encoded string.
2551 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002552 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002553 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2554 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002555 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002556 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002557
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002558 def get_pubkey(self):
2559 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002560 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002561
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002562 :return: The public key.
2563 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002564 """
2565 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002566 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002567 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002568 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002569 pkey._only_public = True
2570 return pkey
2571
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002572 def set_pubkey(self, pkey):
2573 """
2574 Set the public key of the certificate
2575
2576 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002577 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002578 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002579 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002580 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002581
2582
Alex Gaynor10d30832017-06-29 15:31:39 -07002583NetscapeSPKIType = deprecated(
2584 NetscapeSPKI, __name__,
2585 "NetscapeSPKIType has been deprecated, use NetscapeSPKI instead",
2586 DeprecationWarning
2587)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002588
2589
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002590class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002591 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002592 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002593 raise ValueError(
2594 "only FILETYPE_PEM key format supports encryption"
2595 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002596 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002597 self._more_args = more_args
2598 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002599 self._problems = []
2600
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002601 @property
2602 def callback(self):
2603 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002604 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002605 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002606 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002607 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002608 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002609 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002610 raise TypeError(
2611 "Last argument must be a byte string or a callable."
2612 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002613
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002614 @property
2615 def callback_args(self):
2616 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002617 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002618 elif isinstance(self._passphrase, bytes):
2619 return self._passphrase
2620 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002621 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002622 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002623 raise TypeError(
2624 "Last argument must be a byte string or a callable."
2625 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002626
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002627 def raise_if_problem(self, exceptionType=Error):
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002628 if self._problems:
Greg Bowser36eb2de2017-01-24 11:38:55 -05002629
2630 # Flush the OpenSSL error queue
2631 try:
2632 _exception_from_error_queue(exceptionType)
2633 except exceptionType:
2634 pass
2635
2636 raise self._problems.pop(0)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002637
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002638 def _read_passphrase(self, buf, size, rwflag, userdata):
2639 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002640 if self._more_args:
2641 result = self._passphrase(size, rwflag, userdata)
2642 else:
2643 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002644 if not isinstance(result, bytes):
2645 raise ValueError("String expected")
2646 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002647 if self._truncate:
2648 result = result[:size]
2649 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002650 raise ValueError(
2651 "passphrase returned by callback is too long"
2652 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002653 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002654 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002655 return len(result)
2656 except Exception as e:
2657 self._problems.append(e)
2658 return 0
2659
2660
Cory Benfield6492f7c2015-10-27 16:57:58 +09002661def load_publickey(type, buffer):
2662 """
Cory Benfield11c10192015-10-27 17:23:03 +09002663 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002664
Cory Benfield9c590b92015-10-28 14:55:05 +09002665 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002666 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002667 :param buffer: The buffer the key is stored in.
2668 :type buffer: A Python string object, either unicode or bytestring.
2669 :return: The PKey object.
2670 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002671 """
2672 if isinstance(buffer, _text_type):
2673 buffer = buffer.encode("ascii")
2674
2675 bio = _new_mem_buf(buffer)
2676
2677 if type == FILETYPE_PEM:
2678 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2679 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2680 elif type == FILETYPE_ASN1:
2681 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2682 else:
2683 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2684
2685 if evp_pkey == _ffi.NULL:
2686 _raise_current_error()
2687
2688 pkey = PKey.__new__(PKey)
2689 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002690 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002691 return pkey
2692
2693
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002694def load_privatekey(type, buffer, passphrase=None):
2695 """
2696 Load a private key from a buffer
2697
2698 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2699 :param buffer: The buffer the key is stored in
2700 :param passphrase: (optional) if encrypted PEM format, this can be
2701 either the passphrase to use, or a callback for
2702 providing the passphrase.
2703
2704 :return: The PKey object
2705 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002706 if isinstance(buffer, _text_type):
2707 buffer = buffer.encode("ascii")
2708
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002709 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002710
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002711 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002712 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002713 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2714 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002715 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002716 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002717 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002718 else:
2719 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2720
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002721 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002722 _raise_current_error()
2723
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002724 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002725 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002726 return pkey
2727
2728
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002729def dump_certificate_request(type, req):
2730 """
2731 Dump a certificate request to a buffer
2732
2733 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2734 :param req: The certificate request to dump
2735 :return: The buffer with the dumped certificate request in
2736 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002737 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002738
2739 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002740 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002741 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002742 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002743 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002744 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002745 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002746 raise ValueError(
2747 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2748 "FILETYPE_TEXT"
2749 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002750
Alex Gaynor09a386e2016-07-03 09:32:44 -04002751 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002752
2753 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002754
2755
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002756def load_certificate_request(type, buffer):
2757 """
2758 Load a certificate request from a buffer
2759
2760 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2761 :param buffer: The buffer the certificate request is stored in
2762 :return: The X509Req object
2763 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002764 if isinstance(buffer, _text_type):
2765 buffer = buffer.encode("ascii")
2766
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002767 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002768
2769 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002770 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002771 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002772 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002773 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002774 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002775
Alex Gaynoradd5b072016-06-04 21:04:00 -07002776 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002777
2778 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002779 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002780 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002781
2782
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002783def sign(pkey, data, digest):
2784 """
2785 Sign data with a digest
2786
2787 :param pkey: Pkey to sign with
2788 :param data: data to be signed
2789 :param digest: message digest to use
2790 :return: signature
2791 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002792 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002793
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002794 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002795 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002796 raise ValueError("No such digest method")
2797
Alex Gaynor67903a62016-06-02 10:37:13 -07002798 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002799 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002800
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002801 _lib.EVP_SignInit(md_ctx, digest_obj)
2802 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002803
Paul Kehrer59d26252017-07-20 10:45:54 +02002804 length = _lib.EVP_PKEY_size(pkey._pkey)
2805 _openssl_assert(length > 0)
2806 signature_buffer = _ffi.new("unsigned char[]", length)
2807 signature_length = _ffi.new("unsigned int *")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002808 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002809 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002810 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002811
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002812 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002813
2814
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002815def verify(cert, signature, data, digest):
2816 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002817 Verify a signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002818
2819 :param cert: signing certificate (X509 object)
2820 :param signature: signature returned by sign function
2821 :param data: data to be verified
2822 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002823 :return: ``None`` if the signature is correct, raise exception otherwise.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002824 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002825 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002826
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002827 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002828 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002829 raise ValueError("No such digest method")
2830
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002831 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002832 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002833 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002834
Alex Gaynor67903a62016-06-02 10:37:13 -07002835 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002836 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002837
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002838 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2839 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002840 verify_result = _lib.EVP_VerifyFinal(
2841 md_ctx, signature, len(signature), pkey
2842 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002843
2844 if verify_result != 1:
2845 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002846
2847
Dominic Chenf05b2122015-10-13 16:32:35 +00002848def dump_crl(type, crl):
2849 """
2850 Dump a certificate revocation list to a buffer.
2851
2852 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2853 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002854 :param CRL crl: The CRL to dump.
2855
Dominic Chenf05b2122015-10-13 16:32:35 +00002856 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002857 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002858 """
2859 bio = _new_mem_buf()
2860
2861 if type == FILETYPE_PEM:
2862 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2863 elif type == FILETYPE_ASN1:
2864 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2865 elif type == FILETYPE_TEXT:
2866 ret = _lib.X509_CRL_print(bio, crl._crl)
2867 else:
2868 raise ValueError(
2869 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2870 "FILETYPE_TEXT")
2871
2872 assert ret == 1
2873 return _bio_to_string(bio)
2874
2875
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002876def load_crl(type, buffer):
2877 """
2878 Load a certificate revocation list from a buffer
2879
2880 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2881 :param buffer: The buffer the CRL is stored in
2882
2883 :return: The PKey object
2884 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002885 if isinstance(buffer, _text_type):
2886 buffer = buffer.encode("ascii")
2887
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002888 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002889
2890 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002891 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002892 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002893 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002894 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002895 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2896
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002897 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002898 _raise_current_error()
2899
2900 result = CRL.__new__(CRL)
2901 result._crl = crl
2902 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002903
2904
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002905def load_pkcs7_data(type, buffer):
2906 """
2907 Load pkcs7 data from a buffer
2908
2909 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2910 :param buffer: The buffer with the pkcs7 data.
2911 :return: The PKCS7 object
2912 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002913 if isinstance(buffer, _text_type):
2914 buffer = buffer.encode("ascii")
2915
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002916 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002917
2918 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002919 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002920 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002921 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002922 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002923 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2924
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002925 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002926 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002927
2928 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002929 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002930 return pypkcs7
2931
2932
Stephen Holsapple38482622014-04-05 20:29:34 -07002933def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002934 """
2935 Load a PKCS12 object from a buffer
2936
2937 :param buffer: The buffer the certificate is stored in
2938 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2939 :returns: The PKCS12 object
2940 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002941 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002942
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002943 if isinstance(buffer, _text_type):
2944 buffer = buffer.encode("ascii")
2945
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002946 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002947
Stephen Holsapple38482622014-04-05 20:29:34 -07002948 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2949 # password based encryption no password and a zero length password are two
2950 # different things, but OpenSSL implementation will try both to figure out
2951 # which one works.
2952 if not passphrase:
2953 passphrase = _ffi.NULL
2954
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002955 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2956 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002957 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002958 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002959
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002960 pkey = _ffi.new("EVP_PKEY**")
2961 cert = _ffi.new("X509**")
2962 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002963
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002964 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002965 if not parse_result:
2966 _raise_current_error()
2967
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002968 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002969
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002970 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
2971 # queue for no particular reason. This error isn't interesting to anyone
2972 # outside this function. It's not even interesting to us. Get rid of it.
2973 try:
2974 _raise_current_error()
2975 except Error:
2976 pass
2977
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002978 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002979 pykey = None
2980 else:
2981 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002982 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002983
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002984 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002985 pycert = None
2986 friendlyname = None
2987 else:
2988 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002989 pycert._x509 = _ffi.gc(cert[0], _lib.X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002990
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002991 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04002992 friendlyname_buffer = _lib.X509_alias_get0(
2993 cert[0], friendlyname_length
2994 )
2995 friendlyname = _ffi.buffer(
2996 friendlyname_buffer, friendlyname_length[0]
2997 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002998 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002999 friendlyname = None
3000
3001 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003002 for i in range(_lib.sk_X509_num(cacerts)):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003003 pycacert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003004 pycacert._x509 = _lib.sk_X509_value(cacerts, i)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003005 pycacerts.append(pycacert)
3006 if not pycacerts:
3007 pycacerts = None
3008
3009 pkcs12 = PKCS12.__new__(PKCS12)
3010 pkcs12._pkey = pykey
3011 pkcs12._cert = pycert
3012 pkcs12._cacerts = pycacerts
3013 pkcs12._friendlyname = friendlyname
3014 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05003015
3016
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05003017# There are no direct unit tests for this initialization. It is tested
3018# indirectly since it is necessary for functions like dump_privatekey when
3019# using encryption.
3020#
3021# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
3022# and some other similar tests may fail without this (though they may not if
3023# the Python runtime has already done some initialization of the underlying
3024# OpenSSL library (and is linked against the same one that cryptography is
3025# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05003026_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05003027
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05003028# This is similar but exercised mainly by exception_from_error_queue. It calls
3029# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
3030_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003031
3032
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003033# Set the default string mask to match OpenSSL upstream (since 2005) and
3034# RFC5280 recommendations.
3035_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')