blob: 72c04b0f21251ace93d4ee11a649c00c0c3af5ed [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.
Jeremy Cline58193f12017-09-13 21:14:53 -04001658
1659 Calling this method more than once without first calling
1660 :meth:`_cleanup` will leak memory.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001661 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001662 ret = _lib.X509_STORE_CTX_init(
1663 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1664 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001665 if ret <= 0:
1666 _raise_current_error()
1667
1668 def _cleanup(self):
1669 """
1670 Internally cleans up the store context.
1671
Dan Sully44e767a2016-06-04 18:05:27 -07001672 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001673 """
1674 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1675
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001676 def _exception_from_context(self):
1677 """
1678 Convert an OpenSSL native context error failure into a Python
1679 exception.
1680
Alex Gaynor5945ea82015-09-05 14:59:06 -04001681 When a call to native OpenSSL X509_verify_cert fails, additional
1682 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001683 """
1684 errors = [
1685 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1686 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1687 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001688 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001689 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001690 # A context error should always be associated with a certificate, so we
1691 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001692 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001693 _cert = _lib.X509_dup(_x509)
1694 pycert = X509.__new__(X509)
1695 pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001696 return X509StoreContextError(errors, pycert)
1697
Stephen Holsapple46a09252015-02-12 14:45:43 -08001698 def set_store(self, store):
1699 """
Dan Sully44e767a2016-06-04 18:05:27 -07001700 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001701
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001702 .. versionadded:: 0.15
1703
Dan Sully44e767a2016-06-04 18:05:27 -07001704 :param X509Store store: The store description which will be used for
1705 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001706 """
1707 self._store = store
1708
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001709 def verify_certificate(self):
1710 """
1711 Verify a certificate in a context.
1712
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001713 .. versionadded:: 0.15
1714
Alex Gaynorca87ff62015-09-04 23:31:03 -04001715 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001716 certificate in the context. Sets ``certificate`` attribute to
1717 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001718 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001719 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001720 # :meth:`verify_certificate` is called multiple times.
Jeremy Cline58193f12017-09-13 21:14:53 -04001721 #
1722 # :meth:`_init` is called in :meth:`__init__` so _cleanup is called
1723 # before _init to ensure memory is not leaked.
1724 self._cleanup()
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001725 self._init()
1726 ret = _lib.X509_verify_cert(self._store_ctx)
1727 self._cleanup()
1728 if ret <= 0:
1729 raise self._exception_from_context()
1730
1731
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001732def load_certificate(type, buffer):
1733 """
1734 Load a certificate from a buffer
1735
1736 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1737
Dan Sully44e767a2016-06-04 18:05:27 -07001738 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001739
1740 :return: The X509 object
1741 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001742 if isinstance(buffer, _text_type):
1743 buffer = buffer.encode("ascii")
1744
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001745 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001746
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001747 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001748 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001749 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001750 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001751 else:
1752 raise ValueError(
1753 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001754
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001755 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001756 _raise_current_error()
1757
1758 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001759 cert._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001760 return cert
1761
1762
1763def dump_certificate(type, cert):
1764 """
1765 Dump a certificate to a buffer
1766
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001767 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1768 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001769 :param cert: The certificate to dump
1770 :return: The buffer with the dumped certificate in
1771 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001772 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001773
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001774 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001775 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001776 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001777 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001778 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001779 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001780 else:
1781 raise ValueError(
1782 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1783 "FILETYPE_TEXT")
1784
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001785 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001786 return _bio_to_string(bio)
1787
1788
Cory Benfield6492f7c2015-10-27 16:57:58 +09001789def dump_publickey(type, pkey):
1790 """
Cory Benfield11c10192015-10-27 17:23:03 +09001791 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001792
Cory Benfield9c590b92015-10-28 14:55:05 +09001793 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001794 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001795 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001796 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001797 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001798 """
1799 bio = _new_mem_buf()
1800 if type == FILETYPE_PEM:
1801 write_bio = _lib.PEM_write_bio_PUBKEY
1802 elif type == FILETYPE_ASN1:
1803 write_bio = _lib.i2d_PUBKEY_bio
1804 else:
1805 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1806
1807 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001808 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001809 _raise_current_error()
1810
1811 return _bio_to_string(bio)
1812
1813
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001814def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1815 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001816 Dump the private key *pkey* into a buffer string encoded with the type
1817 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1818 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001819
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001820 :param type: The file type (one of :const:`FILETYPE_PEM`,
1821 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1822 :param PKey pkey: The PKey to dump
1823 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001824 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001825 the passphrase to use, or a callback for providing the passphrase.
1826
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001827 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001828 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001829 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001830 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001831
Paul Kehrercded9932017-06-29 18:43:42 -05001832 if not isinstance(pkey, PKey):
1833 raise TypeError("pkey must be a PKey")
1834
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001835 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001836 if passphrase is None:
1837 raise TypeError(
1838 "if a value is given for cipher "
1839 "one must also be given for passphrase")
1840 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001841 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001842 raise ValueError("Invalid cipher name")
1843 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001844 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001845
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001846 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001847 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001848 result_code = _lib.PEM_write_bio_PrivateKey(
1849 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001850 helper.callback, helper.callback_args)
1851 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001852 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001853 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001854 elif type == FILETYPE_TEXT:
Paul Kehrercded9932017-06-29 18:43:42 -05001855 if _lib.EVP_PKEY_id(pkey._pkey) != _lib.EVP_PKEY_RSA:
1856 raise TypeError("Only RSA keys are supported for FILETYPE_TEXT")
1857
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001858 rsa = _ffi.gc(
1859 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1860 _lib.RSA_free
1861 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001862 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001863 else:
1864 raise ValueError(
1865 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1866 "FILETYPE_TEXT")
1867
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001868 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001869
1870 return _bio_to_string(bio)
1871
1872
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001873class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001874 """
1875 A certificate revocation.
1876 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001877 # http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_
1878 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1879 # OCSP_crl_reason_str. We use the latter, just like the command line
1880 # program.
1881 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001882 b"unspecified",
1883 b"keyCompromise",
1884 b"CACompromise",
1885 b"affiliationChanged",
1886 b"superseded",
1887 b"cessationOfOperation",
1888 b"certificateHold",
1889 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001890 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001891
1892 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001893 revoked = _lib.X509_REVOKED_new()
1894 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001895
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001896 def set_serial(self, hex_str):
1897 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001898 Set the serial number.
1899
1900 The serial number is formatted as a hexadecimal number encoded in
1901 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001902
Dan Sully44e767a2016-06-04 18:05:27 -07001903 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001904
Dan Sully44e767a2016-06-04 18:05:27 -07001905 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001906 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001907 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1908 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001909 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001910 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001911 if not bn_result:
1912 raise ValueError("bad hex string")
1913
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001914 asn1_serial = _ffi.gc(
1915 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1916 _lib.ASN1_INTEGER_free)
1917 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001918
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001919 def get_serial(self):
1920 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001921 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001922
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001923 The serial number is formatted as a hexadecimal number encoded in
1924 ASCII.
1925
1926 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001927 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001928 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001929 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001930
Alex Gaynor67903a62016-06-02 10:37:13 -07001931 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1932 _openssl_assert(asn1_int != _ffi.NULL)
1933 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1934 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001935 return _bio_to_string(bio)
1936
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001937 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001938 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1939 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001940 obj = _lib.X509_EXTENSION_get_object(ext)
1941 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001942 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001943 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001944 break
1945
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001946 def set_reason(self, reason):
1947 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001948 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001949
Dan Sully44e767a2016-06-04 18:05:27 -07001950 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001951
1952 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07001953 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001954
Dan Sully44e767a2016-06-04 18:05:27 -07001955 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001956
1957 .. seealso::
1958
Dan Sully44e767a2016-06-04 18:05:27 -07001959 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001960 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001961 """
1962 if reason is None:
1963 self._delete_reason()
1964 elif not isinstance(reason, bytes):
1965 raise TypeError("reason must be None or a byte string")
1966 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001967 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001968 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
1969
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001970 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07001971 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001972 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001973
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001974 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001975 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001976
1977 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001978 add_result = _lib.X509_REVOKED_add1_ext_i2d(
1979 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001980 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001981
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001982 def get_reason(self):
1983 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04001984 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001985
Dan Sully44e767a2016-06-04 18:05:27 -07001986 :return: The reason, or ``None`` if there is none.
1987 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001988
1989 .. seealso::
1990
Dan Sully44e767a2016-06-04 18:05:27 -07001991 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001992 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001993 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001994 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1995 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001996 obj = _lib.X509_EXTENSION_get_object(ext)
1997 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001998 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001999
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002000 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002001 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002002 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002003 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04002004 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002005 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002006
2007 return _bio_to_string(bio)
2008
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002009 def all_reasons(self):
2010 """
2011 Return a list of all the supported reason strings.
2012
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002013 This list is a copy; modifying it does not change the supported reason
2014 strings.
2015
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002016 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07002017 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002018 """
2019 return self._crl_reasons[:]
2020
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002021 def set_rev_date(self, when):
2022 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002023 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002024
Dan Sully44e767a2016-06-04 18:05:27 -07002025 :param bytes when: The timestamp of the revocation,
Paul Kehrerce98ee62017-06-21 06:59:58 -10002026 as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002027 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002028 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002029 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2030 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002031
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002032 def get_rev_date(self):
2033 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002034 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002035
Paul Kehrerce98ee62017-06-21 06:59:58 -10002036 :return: The timestamp of the revocation, as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002037 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002038 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002039 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2040 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002041
2042
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002043class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002044 """
2045 A certificate revocation list.
2046 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002047
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002048 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002049 crl = _lib.X509_CRL_new()
2050 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002051
Paul Kehrer41c10242017-06-29 18:24:17 -05002052 def to_cryptography(self):
2053 """
2054 Export as a ``cryptography`` CRL.
2055
2056 :rtype: ``cryptography.x509.CertificateRevocationList``
2057
2058 .. versionadded:: 17.1.0
2059 """
2060 from cryptography.hazmat.backends.openssl.x509 import (
2061 _CertificateRevocationList
2062 )
2063 backend = _get_backend()
2064 return _CertificateRevocationList(backend, self._crl)
2065
2066 @classmethod
2067 def from_cryptography(cls, crypto_crl):
2068 """
2069 Construct based on a ``cryptography`` *crypto_crl*.
2070
2071 :param crypto_crl: A ``cryptography`` certificate revocation list
2072 :type crypto_crl: ``cryptography.x509.CertificateRevocationList``
2073
2074 :rtype: CRL
2075
2076 .. versionadded:: 17.1.0
2077 """
2078 if not isinstance(crypto_crl, x509.CertificateRevocationList):
2079 raise TypeError("Must be a certificate revocation list")
2080
2081 crl = cls()
2082 crl._crl = crypto_crl._x509_crl
2083 return crl
2084
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002085 def get_revoked(self):
2086 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002087 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002088
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002089 These revocations will be provided by value, not by reference.
2090 That means it's okay to mutate them: it won't affect this CRL.
2091
2092 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002093 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002094 """
2095 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07002096 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002097 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
2098 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04002099 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002100 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002101 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002102 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002103 if results:
2104 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002105
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002106 def add_revoked(self, revoked):
2107 """
2108 Add a revoked (by value not reference) to the CRL structure
2109
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002110 This revocation will be added by value, not by reference. That
2111 means it's okay to mutate it after adding: it won't affect
2112 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002113
Dan Sully44e767a2016-06-04 18:05:27 -07002114 :param Revoked revoked: The new revocation.
2115 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002116 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04002117 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002118 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002119
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002120 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002121 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002122
Dan Sully44e767a2016-06-04 18:05:27 -07002123 def get_issuer(self):
2124 """
2125 Get the CRL's issuer.
2126
2127 .. versionadded:: 16.1.0
2128
2129 :rtype: X509Name
2130 """
2131 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
2132 _openssl_assert(_issuer != _ffi.NULL)
2133 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
2134 issuer = X509Name.__new__(X509Name)
2135 issuer._name = _issuer
2136 return issuer
2137
2138 def set_version(self, version):
2139 """
2140 Set the CRL version.
2141
2142 .. versionadded:: 16.1.0
2143
2144 :param int version: The version of the CRL.
2145 :return: ``None``
2146 """
2147 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2148
2149 def _set_boundary_time(self, which, when):
2150 return _set_asn1_time(which(self._crl), when)
2151
2152 def set_lastUpdate(self, when):
2153 """
2154 Set when the CRL was last updated.
2155
Paul Kehrerce98ee62017-06-21 06:59:58 -10002156 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002157
2158 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002159
2160 .. versionadded:: 16.1.0
2161
2162 :param bytes when: A timestamp string.
2163 :return: ``None``
2164 """
2165 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2166
2167 def set_nextUpdate(self, when):
2168 """
2169 Set when the CRL will next be udpated.
2170
Paul Kehrerce98ee62017-06-21 06:59:58 -10002171 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002172
2173 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002174
2175 .. versionadded:: 16.1.0
2176
2177 :param bytes when: A timestamp string.
2178 :return: ``None``
2179 """
2180 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2181
2182 def sign(self, issuer_cert, issuer_key, digest):
2183 """
2184 Sign the CRL.
2185
2186 Signing a CRL enables clients to associate the CRL itself with an
2187 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2188 be signed by an issuer.
2189
2190 This method implicitly sets the issuer's name based on the issuer
2191 certificate and private key used to sign the CRL.
2192
2193 .. versionadded:: 16.1.0
2194
2195 :param X509 issuer_cert: The issuer's certificate.
2196 :param PKey issuer_key: The issuer's private key.
2197 :param bytes digest: The digest method to sign the CRL with.
2198 """
2199 digest_obj = _lib.EVP_get_digestbyname(digest)
2200 _openssl_assert(digest_obj != _ffi.NULL)
2201 _lib.X509_CRL_set_issuer_name(
2202 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2203 _lib.X509_CRL_sort(self._crl)
2204 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2205 _openssl_assert(result != 0)
2206
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002207 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002208 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002209 """
Dan Sully44e767a2016-06-04 18:05:27 -07002210 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002211
Dan Sully44e767a2016-06-04 18:05:27 -07002212 :param X509 cert: The certificate used to sign the CRL.
2213 :param PKey key: The key used to sign the CRL.
2214 :param int type: The export format, either :data:`FILETYPE_PEM`,
2215 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002216 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002217 :param bytes digest: The name of the message digest to use (eg
Alex Gaynor239e2d32016-09-11 12:36:35 -04002218 ``b"sha2566"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002219 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002220 """
Dan Sully44e767a2016-06-04 18:05:27 -07002221
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002222 if not isinstance(cert, X509):
2223 raise TypeError("cert must be an X509 instance")
2224 if not isinstance(key, PKey):
2225 raise TypeError("key must be a PKey instance")
2226 if not isinstance(type, int):
2227 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002228
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002229 if digest is _UNSPECIFIED:
Alex Gaynor173e4ba2017-06-30 08:01:12 -07002230 raise TypeError("digest must be provided")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002231
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002232 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002233 if digest_obj == _ffi.NULL:
2234 raise ValueError("No such digest method")
2235
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002236 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002237 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002238
Alex Gaynora738ed52015-09-05 11:17:10 -04002239 # A scratch time object to give different values to different CRL
2240 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002241 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002242 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002243
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002244 _lib.X509_gmtime_adj(sometime, 0)
2245 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002246
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002247 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2248 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002249
Alex Gaynor5945ea82015-09-05 14:59:06 -04002250 _lib.X509_CRL_set_issuer_name(
2251 self._crl, _lib.X509_get_subject_name(cert._x509)
2252 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002253
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002254 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002255 if not sign_result:
2256 _raise_current_error()
2257
Dominic Chenf05b2122015-10-13 16:32:35 +00002258 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002259
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002260
Alex Gaynor10d30832017-06-29 15:31:39 -07002261CRLType = deprecated(
2262 CRL, __name__,
2263 "CRLType has been deprecated, use CRL instead",
2264 DeprecationWarning
2265)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002266
2267
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002268class PKCS7(object):
2269 def type_is_signed(self):
2270 """
2271 Check if this NID_pkcs7_signed object
2272
2273 :return: True if the PKCS7 is of type signed
2274 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002275 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002276
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002277 def type_is_enveloped(self):
2278 """
2279 Check if this NID_pkcs7_enveloped object
2280
2281 :returns: True if the PKCS7 is of type enveloped
2282 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002283 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002284
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002285 def type_is_signedAndEnveloped(self):
2286 """
2287 Check if this NID_pkcs7_signedAndEnveloped object
2288
2289 :returns: True if the PKCS7 is of type signedAndEnveloped
2290 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002291 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002292
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002293 def type_is_data(self):
2294 """
2295 Check if this NID_pkcs7_data object
2296
2297 :return: True if the PKCS7 is of type data
2298 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002299 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002300
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002301 def get_type_name(self):
2302 """
2303 Returns the type name of the PKCS7 structure
2304
2305 :return: A string with the typename
2306 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002307 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2308 string_type = _lib.OBJ_nid2sn(nid)
2309 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002310
Alex Chanc6077062016-11-18 13:53:39 +00002311
Alex Gaynor10d30832017-06-29 15:31:39 -07002312PKCS7Type = deprecated(
2313 PKCS7, __name__,
2314 "PKCS7Type has been deprecated, use PKCS7 instead",
2315 DeprecationWarning
2316)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002317
2318
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002319class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002320 """
2321 A PKCS #12 archive.
2322 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002323
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002324 def __init__(self):
2325 self._pkey = None
2326 self._cert = None
2327 self._cacerts = None
2328 self._friendlyname = None
2329
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002330 def get_certificate(self):
2331 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002332 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002333
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002334 :return: The certificate, or :py:const:`None` if there is none.
2335 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002336 """
2337 return self._cert
2338
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002339 def set_certificate(self, cert):
2340 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002341 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002342
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002343 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002344 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002345
Dan Sully44e767a2016-06-04 18:05:27 -07002346 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002347 """
2348 if not isinstance(cert, X509):
2349 raise TypeError("cert must be an X509 instance")
2350 self._cert = cert
2351
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002352 def get_privatekey(self):
2353 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002354 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002355
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002356 :return: The private key, or :py:const:`None` if there is none.
2357 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002358 """
2359 return self._pkey
2360
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002361 def set_privatekey(self, pkey):
2362 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002363 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002364
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002365 :param pkey: The new private key, or :py:const:`None` to unset it.
2366 :type pkey: :py:class:`PKey` or :py:const:`None`
2367
Dan Sully44e767a2016-06-04 18:05:27 -07002368 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002369 """
2370 if not isinstance(pkey, PKey):
2371 raise TypeError("pkey must be a PKey instance")
2372 self._pkey = pkey
2373
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002374 def get_ca_certificates(self):
2375 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002376 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002377
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002378 :return: A tuple with the CA certificates in the chain, or
2379 :py:const:`None` if there are none.
2380 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002381 """
2382 if self._cacerts is not None:
2383 return tuple(self._cacerts)
2384
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002385 def set_ca_certificates(self, cacerts):
2386 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002387 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002388
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002389 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2390 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002391 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002392
Dan Sully44e767a2016-06-04 18:05:27 -07002393 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002394 """
2395 if cacerts is None:
2396 self._cacerts = None
2397 else:
2398 cacerts = list(cacerts)
2399 for cert in cacerts:
2400 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002401 raise TypeError(
2402 "iterable must only contain X509 instances"
2403 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002404 self._cacerts = cacerts
2405
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002406 def set_friendlyname(self, name):
2407 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002408 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002409
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002410 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002411 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002412
Dan Sully44e767a2016-06-04 18:05:27 -07002413 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002414 """
2415 if name is None:
2416 self._friendlyname = None
2417 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002418 raise TypeError(
2419 "name must be a byte string or None (not %r)" % (name,)
2420 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002421 self._friendlyname = name
2422
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002423 def get_friendlyname(self):
2424 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002425 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002426
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002427 :returns: The friendly name, or :py:const:`None` if there is none.
2428 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002429 """
2430 return self._friendlyname
2431
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002432 def export(self, passphrase=None, iter=2048, maciter=1):
2433 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002434 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002435
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002436 For more information, see the :c:func:`PKCS12_create` man page.
2437
2438 :param passphrase: The passphrase used to encrypt the structure. Unlike
2439 some other passphrase arguments, this *must* be a string, not a
2440 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002441 :type passphrase: :py:data:`bytes`
2442
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002443 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002444 :type iter: :py:data:`int`
2445
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002446 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002447 :type maciter: :py:data:`int`
2448
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002449 :return: The string representation of the PKCS #12 structure.
2450 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002451 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002452 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002453
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002454 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002455 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002456 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002457 cacerts = _lib.sk_X509_new_null()
2458 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002459 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002460 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002461
2462 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002463 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002464
2465 friendlyname = self._friendlyname
2466 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002467 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002468
2469 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002470 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002471 else:
2472 pkey = self._pkey._pkey
2473
2474 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002475 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002476 else:
2477 cert = self._cert._x509
2478
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002479 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002480 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002481 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2482 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002483 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002484 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002485 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002486 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002487
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002488 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002489 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002490 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002491
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002492
Alex Gaynor10d30832017-06-29 15:31:39 -07002493PKCS12Type = deprecated(
2494 PKCS12, __name__,
2495 "PKCS12Type has been deprecated, use PKCS12 instead",
2496 DeprecationWarning
2497)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002498
2499
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002500class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002501 """
2502 A Netscape SPKI object.
2503 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002504
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002505 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002506 spki = _lib.NETSCAPE_SPKI_new()
2507 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002508
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002509 def sign(self, pkey, digest):
2510 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002511 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002512
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002513 :param pkey: The private key to sign with.
2514 :type pkey: :py:class:`PKey`
2515
2516 :param digest: The message digest to use.
2517 :type digest: :py:class:`bytes`
2518
Dan Sully44e767a2016-06-04 18:05:27 -07002519 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002520 """
2521 if pkey._only_public:
2522 raise ValueError("Key has only public part")
2523
2524 if not pkey._initialized:
2525 raise ValueError("Key is uninitialized")
2526
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002527 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002528 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002529 raise ValueError("No such digest method")
2530
Alex Gaynor5945ea82015-09-05 14:59:06 -04002531 sign_result = _lib.NETSCAPE_SPKI_sign(
2532 self._spki, pkey._pkey, digest_obj
2533 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002534 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002535
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002536 def verify(self, key):
2537 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002538 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002539
Hynek Schlawack01c31672016-12-11 15:14:09 +01002540 :param PKey key: The public key that signature is supposedly from.
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002541
Hynek Schlawack01c31672016-12-11 15:14:09 +01002542 :return: ``True`` if the signature is correct.
2543 :rtype: bool
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002544
Hynek Schlawack01c31672016-12-11 15:14:09 +01002545 :raises OpenSSL.crypto.Error: If the signature is invalid, or there was
2546 a problem verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002547 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002548 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002549 if answer <= 0:
2550 _raise_current_error()
2551 return True
2552
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002553 def b64_encode(self):
2554 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002555 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002556
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002557 :return: The base64 encoded string.
2558 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002559 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002560 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2561 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002562 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002563 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002564
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002565 def get_pubkey(self):
2566 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002567 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002568
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002569 :return: The public key.
2570 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002571 """
2572 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002573 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002574 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002575 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002576 pkey._only_public = True
2577 return pkey
2578
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002579 def set_pubkey(self, pkey):
2580 """
2581 Set the public key of the certificate
2582
2583 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002584 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002585 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002586 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002587 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002588
2589
Alex Gaynor10d30832017-06-29 15:31:39 -07002590NetscapeSPKIType = deprecated(
2591 NetscapeSPKI, __name__,
2592 "NetscapeSPKIType has been deprecated, use NetscapeSPKI instead",
2593 DeprecationWarning
2594)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002595
2596
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002597class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002598 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002599 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002600 raise ValueError(
2601 "only FILETYPE_PEM key format supports encryption"
2602 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002603 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002604 self._more_args = more_args
2605 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002606 self._problems = []
2607
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002608 @property
2609 def callback(self):
2610 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002611 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002612 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002613 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002614 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002615 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002616 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002617 raise TypeError(
2618 "Last argument must be a byte string or a callable."
2619 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002620
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002621 @property
2622 def callback_args(self):
2623 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002624 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002625 elif isinstance(self._passphrase, bytes):
2626 return self._passphrase
2627 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002628 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002629 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002630 raise TypeError(
2631 "Last argument must be a byte string or a callable."
2632 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002633
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002634 def raise_if_problem(self, exceptionType=Error):
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002635 if self._problems:
Greg Bowser36eb2de2017-01-24 11:38:55 -05002636
2637 # Flush the OpenSSL error queue
2638 try:
2639 _exception_from_error_queue(exceptionType)
2640 except exceptionType:
2641 pass
2642
2643 raise self._problems.pop(0)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002644
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002645 def _read_passphrase(self, buf, size, rwflag, userdata):
2646 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002647 if self._more_args:
2648 result = self._passphrase(size, rwflag, userdata)
2649 else:
2650 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002651 if not isinstance(result, bytes):
2652 raise ValueError("String expected")
2653 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002654 if self._truncate:
2655 result = result[:size]
2656 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002657 raise ValueError(
2658 "passphrase returned by callback is too long"
2659 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002660 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002661 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002662 return len(result)
2663 except Exception as e:
2664 self._problems.append(e)
2665 return 0
2666
2667
Cory Benfield6492f7c2015-10-27 16:57:58 +09002668def load_publickey(type, buffer):
2669 """
Cory Benfield11c10192015-10-27 17:23:03 +09002670 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002671
Cory Benfield9c590b92015-10-28 14:55:05 +09002672 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002673 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002674 :param buffer: The buffer the key is stored in.
2675 :type buffer: A Python string object, either unicode or bytestring.
2676 :return: The PKey object.
2677 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002678 """
2679 if isinstance(buffer, _text_type):
2680 buffer = buffer.encode("ascii")
2681
2682 bio = _new_mem_buf(buffer)
2683
2684 if type == FILETYPE_PEM:
2685 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2686 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2687 elif type == FILETYPE_ASN1:
2688 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2689 else:
2690 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2691
2692 if evp_pkey == _ffi.NULL:
2693 _raise_current_error()
2694
2695 pkey = PKey.__new__(PKey)
2696 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002697 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002698 return pkey
2699
2700
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002701def load_privatekey(type, buffer, passphrase=None):
2702 """
2703 Load a private key from a buffer
2704
2705 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2706 :param buffer: The buffer the key is stored in
2707 :param passphrase: (optional) if encrypted PEM format, this can be
2708 either the passphrase to use, or a callback for
2709 providing the passphrase.
2710
2711 :return: The PKey object
2712 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002713 if isinstance(buffer, _text_type):
2714 buffer = buffer.encode("ascii")
2715
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002716 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002717
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002718 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002719 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002720 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2721 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002722 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002723 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002724 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002725 else:
2726 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2727
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002728 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002729 _raise_current_error()
2730
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002731 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002732 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002733 return pkey
2734
2735
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002736def dump_certificate_request(type, req):
2737 """
2738 Dump a certificate request to a buffer
2739
2740 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2741 :param req: The certificate request to dump
2742 :return: The buffer with the dumped certificate request in
2743 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002744 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002745
2746 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002747 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002748 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002749 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002750 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002751 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002752 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002753 raise ValueError(
2754 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2755 "FILETYPE_TEXT"
2756 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002757
Alex Gaynor09a386e2016-07-03 09:32:44 -04002758 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002759
2760 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002761
2762
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002763def load_certificate_request(type, buffer):
2764 """
2765 Load a certificate request from a buffer
2766
2767 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2768 :param buffer: The buffer the certificate request is stored in
2769 :return: The X509Req object
2770 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002771 if isinstance(buffer, _text_type):
2772 buffer = buffer.encode("ascii")
2773
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002774 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002775
2776 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002777 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002778 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002779 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002780 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002781 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002782
Alex Gaynoradd5b072016-06-04 21:04:00 -07002783 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002784
2785 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002786 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002787 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002788
2789
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002790def sign(pkey, data, digest):
2791 """
2792 Sign data with a digest
2793
2794 :param pkey: Pkey to sign with
2795 :param data: data to be signed
2796 :param digest: message digest to use
2797 :return: signature
2798 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002799 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002800
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002801 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002802 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002803 raise ValueError("No such digest method")
2804
Alex Gaynor67903a62016-06-02 10:37:13 -07002805 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002806 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002807
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002808 _lib.EVP_SignInit(md_ctx, digest_obj)
2809 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002810
Paul Kehrer59d26252017-07-20 10:45:54 +02002811 length = _lib.EVP_PKEY_size(pkey._pkey)
2812 _openssl_assert(length > 0)
2813 signature_buffer = _ffi.new("unsigned char[]", length)
2814 signature_length = _ffi.new("unsigned int *")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002815 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002816 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002817 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002818
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002819 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002820
2821
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002822def verify(cert, signature, data, digest):
2823 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002824 Verify a signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002825
2826 :param cert: signing certificate (X509 object)
2827 :param signature: signature returned by sign function
2828 :param data: data to be verified
2829 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002830 :return: ``None`` if the signature is correct, raise exception otherwise.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002831 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002832 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002833
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002834 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002835 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002836 raise ValueError("No such digest method")
2837
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002838 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002839 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002840 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002841
Alex Gaynor67903a62016-06-02 10:37:13 -07002842 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002843 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002844
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002845 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2846 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002847 verify_result = _lib.EVP_VerifyFinal(
2848 md_ctx, signature, len(signature), pkey
2849 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002850
2851 if verify_result != 1:
2852 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002853
2854
Dominic Chenf05b2122015-10-13 16:32:35 +00002855def dump_crl(type, crl):
2856 """
2857 Dump a certificate revocation list to a buffer.
2858
2859 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2860 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002861 :param CRL crl: The CRL to dump.
2862
Dominic Chenf05b2122015-10-13 16:32:35 +00002863 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002864 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002865 """
2866 bio = _new_mem_buf()
2867
2868 if type == FILETYPE_PEM:
2869 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2870 elif type == FILETYPE_ASN1:
2871 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2872 elif type == FILETYPE_TEXT:
2873 ret = _lib.X509_CRL_print(bio, crl._crl)
2874 else:
2875 raise ValueError(
2876 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2877 "FILETYPE_TEXT")
2878
2879 assert ret == 1
2880 return _bio_to_string(bio)
2881
2882
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002883def load_crl(type, buffer):
2884 """
2885 Load a certificate revocation list from a buffer
2886
2887 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2888 :param buffer: The buffer the CRL is stored in
2889
2890 :return: The PKey object
2891 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002892 if isinstance(buffer, _text_type):
2893 buffer = buffer.encode("ascii")
2894
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002895 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002896
2897 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002898 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002899 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002900 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002901 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002902 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2903
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002904 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002905 _raise_current_error()
2906
2907 result = CRL.__new__(CRL)
Jeremy Cline9e15eca2017-09-07 20:11:08 -04002908 result._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002909 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002910
2911
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002912def load_pkcs7_data(type, buffer):
2913 """
2914 Load pkcs7 data from a buffer
2915
2916 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2917 :param buffer: The buffer with the pkcs7 data.
2918 :return: The PKCS7 object
2919 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002920 if isinstance(buffer, _text_type):
2921 buffer = buffer.encode("ascii")
2922
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002923 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002924
2925 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002926 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002927 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002928 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002929 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002930 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2931
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002932 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002933 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002934
2935 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002936 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002937 return pypkcs7
2938
2939
Stephen Holsapple38482622014-04-05 20:29:34 -07002940def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002941 """
2942 Load a PKCS12 object from a buffer
2943
2944 :param buffer: The buffer the certificate is stored in
2945 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2946 :returns: The PKCS12 object
2947 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002948 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002949
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002950 if isinstance(buffer, _text_type):
2951 buffer = buffer.encode("ascii")
2952
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002953 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002954
Stephen Holsapple38482622014-04-05 20:29:34 -07002955 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2956 # password based encryption no password and a zero length password are two
2957 # different things, but OpenSSL implementation will try both to figure out
2958 # which one works.
2959 if not passphrase:
2960 passphrase = _ffi.NULL
2961
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002962 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2963 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002964 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002965 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002966
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002967 pkey = _ffi.new("EVP_PKEY**")
2968 cert = _ffi.new("X509**")
2969 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002970
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002971 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002972 if not parse_result:
2973 _raise_current_error()
2974
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002975 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002976
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002977 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
2978 # queue for no particular reason. This error isn't interesting to anyone
2979 # outside this function. It's not even interesting to us. Get rid of it.
2980 try:
2981 _raise_current_error()
2982 except Error:
2983 pass
2984
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002985 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002986 pykey = None
2987 else:
2988 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002989 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002990
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002991 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002992 pycert = None
2993 friendlyname = None
2994 else:
2995 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002996 pycert._x509 = _ffi.gc(cert[0], _lib.X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002997
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002998 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04002999 friendlyname_buffer = _lib.X509_alias_get0(
3000 cert[0], friendlyname_length
3001 )
3002 friendlyname = _ffi.buffer(
3003 friendlyname_buffer, friendlyname_length[0]
3004 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003005 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003006 friendlyname = None
3007
3008 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003009 for i in range(_lib.sk_X509_num(cacerts)):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003010 pycacert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003011 pycacert._x509 = _lib.sk_X509_value(cacerts, i)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003012 pycacerts.append(pycacert)
3013 if not pycacerts:
3014 pycacerts = None
3015
3016 pkcs12 = PKCS12.__new__(PKCS12)
3017 pkcs12._pkey = pykey
3018 pkcs12._cert = pycert
3019 pkcs12._cacerts = pycacerts
3020 pkcs12._friendlyname = friendlyname
3021 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05003022
3023
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05003024# There are no direct unit tests for this initialization. It is tested
3025# indirectly since it is necessary for functions like dump_privatekey when
3026# using encryption.
3027#
3028# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
3029# and some other similar tests may fail without this (though they may not if
3030# the Python runtime has already done some initialization of the underlying
3031# OpenSSL library (and is linked against the same one that cryptography is
3032# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05003033_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05003034
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05003035# This is similar but exercised mainly by exception_from_error_queue. It calls
3036# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
3037_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003038
3039
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003040# Set the default string mask to match OpenSSL upstream (since 2005) and
3041# RFC5280 recommendations.
3042_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')