blob: ee422cbaab6889b7a25aba54b61a93ffd3e0ea22 [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
Alex Gaynor4aa52c32017-11-20 09:04:08 -0500165class _X509NameInvalidator(object):
166 def __init__(self):
167 self._names = []
168
169 def add(self, name):
170 self._names.append(name)
171
172 def clear(self):
173 for name in self._names:
174 # Breaks the object, but also prevents UAF!
175 del name._name
176
177
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800178class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200179 """
180 A class representing an DSA or RSA public key or key pair.
181 """
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800182 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800183 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800184
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800185 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500186 pkey = _lib.EVP_PKEY_new()
187 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800188 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800189
Paul Kehrer72d968b2016-07-29 15:31:04 +0800190 def to_cryptography_key(self):
191 """
192 Export as a ``cryptography`` key.
193
194 :rtype: One of ``cryptography``'s `key interfaces`_.
195
196 .. _key interfaces: https://cryptography.io/en/latest/hazmat/\
197 primitives/asymmetric/rsa/#key-interfaces
198
199 .. versionadded:: 16.1.0
200 """
Paul Kehrereb633842016-10-06 11:22:01 +0200201 backend = _get_backend()
Paul Kehrer72d968b2016-07-29 15:31:04 +0800202 if self._only_public:
203 return backend._evp_pkey_to_public_key(self._pkey)
204 else:
205 return backend._evp_pkey_to_private_key(self._pkey)
206
207 @classmethod
208 def from_cryptography_key(cls, crypto_key):
209 """
210 Construct based on a ``cryptography`` *crypto_key*.
211
212 :param crypto_key: A ``cryptography`` key.
213 :type crypto_key: One of ``cryptography``'s `key interfaces`_.
214
215 :rtype: PKey
216
217 .. versionadded:: 16.1.0
218 """
219 pkey = cls()
220 if not isinstance(crypto_key, (rsa.RSAPublicKey, rsa.RSAPrivateKey,
221 dsa.DSAPublicKey, dsa.DSAPrivateKey)):
222 raise TypeError("Unsupported key type")
223
224 pkey._pkey = crypto_key._evp_pkey
225 if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)):
226 pkey._only_public = True
227 pkey._initialized = True
228 return pkey
229
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800230 def generate_key(self, type, bits):
231 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700232 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800233
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200234 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800235
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200236 :param type: The key type.
237 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
238 :param bits: The number of bits.
239 :type bits: :py:data:`int` ``>= 0``
240 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
241 of the appropriate type.
242 :raises ValueError: If the number of bits isn't an integer of
243 the appropriate size.
Dan Sully44e767a2016-06-04 18:05:27 -0700244 :return: ``None``
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800245 """
246 if not isinstance(type, int):
247 raise TypeError("type must be an integer")
248
249 if not isinstance(bits, int):
250 raise TypeError("bits must be an integer")
251
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800252 # TODO Check error return
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500253 exponent = _lib.BN_new()
254 exponent = _ffi.gc(exponent, _lib.BN_free)
255 _lib.BN_set_word(exponent, _lib.RSA_F4)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800256
257 if type == TYPE_RSA:
258 if bits <= 0:
259 raise ValueError("Invalid number of bits")
260
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500261 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800262
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500263 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400264 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800265
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500266 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400267 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800268
269 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400270 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700271 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400272
273 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400274 res = _lib.DSA_generate_parameters_ex(
275 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
276 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700277 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400278
279 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
280 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800281 else:
282 raise Error("No such key type")
283
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800284 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800285
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800286 def check(self):
287 """
288 Check the consistency of an RSA private key.
289
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200290 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
291
Hynek Schlawack01c31672016-12-11 15:14:09 +0100292 :return: ``True`` if key is consistent.
293
294 :raise OpenSSL.crypto.Error: if the key is inconsistent.
295
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800296 :raise TypeError: if the key is of a type which cannot be checked.
297 Only RSA keys can currently be checked.
298 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800299 if self._only_public:
300 raise TypeError("public key only")
301
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100302 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800303 raise TypeError("key type unsupported")
304
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500305 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
306 rsa = _ffi.gc(rsa, _lib.RSA_free)
307 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800308 if result:
309 return True
310 _raise_current_error()
311
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800312 def type(self):
313 """
314 Returns the type of the key
315
316 :return: The type of the key.
317 """
Alex Gaynor0d2aec52017-05-31 04:26:27 -0400318 return _lib.EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800319
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800320 def bits(self):
321 """
322 Returns the number of bits of the key
323
324 :return: The number of bits of the key.
325 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500326 return _lib.EVP_PKEY_bits(self._pkey)
Alex Chanc6077062016-11-18 13:53:39 +0000327
328
Alex Gaynor10d30832017-06-29 15:31:39 -0700329PKeyType = deprecated(
330 PKey, __name__,
331 "PKeyType has been deprecated, use PKey instead",
332 DeprecationWarning
333)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800334
335
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400336class _EllipticCurve(object):
337 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400338 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400339
340 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
341 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
342 instances each of which represents one curve supported by the system.
343 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400344 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400345 _curves = None
346
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400347 if _PY3:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400348 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400349 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400350 """
351 Implement cooperation with the right-hand side argument of ``!=``.
352
353 Python 3 seems to have dropped this cooperation in this very narrow
354 circumstance.
355 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400356 if isinstance(other, _EllipticCurve):
357 return super(_EllipticCurve, self).__ne__(other)
358 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400359
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400360 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400361 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400362 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400363 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400364
365 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400366
367 :return: A :py:type:`set` of ``cls`` instances giving the names of the
368 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400369 """
Alex Chan84902a22017-04-20 11:50:47 +0100370 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
371 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
372 # The return value on this call should be num_curves again. We
373 # could check it to make sure but if it *isn't* then.. what could
374 # we do? Abort the whole process, I suppose...? -exarkun
375 lib.EC_get_builtin_curves(builtin_curves, num_curves)
376 return set(
377 cls.from_nid(lib, c.nid)
378 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400379
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400380 @classmethod
381 def _get_elliptic_curves(cls, lib):
382 """
383 Get, cache, and return the curves supported by OpenSSL.
384
385 :param lib: The OpenSSL library binding object.
386
387 :return: A :py:type:`set` of ``cls`` instances giving the names of the
388 elliptic curves the underlying library supports.
389 """
390 if cls._curves is None:
391 cls._curves = cls._load_elliptic_curves(lib)
392 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400393
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400394 @classmethod
395 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400396 """
397 Instantiate a new :py:class:`_EllipticCurve` associated with the given
398 OpenSSL NID.
399
400 :param lib: The OpenSSL library binding object.
401
402 :param nid: The OpenSSL NID the resulting curve object will represent.
403 This must be a curve NID (and not, for example, a hash NID) or
404 subsequent operations will fail in unpredictable ways.
405 :type nid: :py:class:`int`
406
407 :return: The curve object.
408 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400409 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
410
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400411 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400412 """
413 :param _lib: The :py:mod:`cryptography` binding instance used to
414 interface with OpenSSL.
415
416 :param _nid: The OpenSSL NID identifying the curve this object
417 represents.
418 :type _nid: :py:class:`int`
419
420 :param name: The OpenSSL short name identifying the curve this object
421 represents.
422 :type name: :py:class:`unicode`
423 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400424 self._lib = lib
425 self._nid = nid
426 self.name = name
427
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400428 def __repr__(self):
429 return "<Curve %r>" % (self.name,)
430
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400431 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400432 """
433 Create a new OpenSSL EC_KEY structure initialized to use this curve.
434
435 The structure is automatically garbage collected when the Python object
436 is garbage collected.
437 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400438 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
439 return _ffi.gc(key, _lib.EC_KEY_free)
440
441
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400442def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400443 """
444 Return a set of objects representing the elliptic curves supported in the
445 OpenSSL build in use.
446
447 The curve objects have a :py:class:`unicode` ``name`` attribute by which
448 they identify themselves.
449
450 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400451 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
452 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400453 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400454 return _EllipticCurve._get_elliptic_curves(_lib)
455
456
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400457def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400458 """
459 Return a single curve object selected by name.
460
461 See :py:func:`get_elliptic_curves` for information about curve objects.
462
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400463 :param name: The OpenSSL short name identifying the curve object to
464 retrieve.
465 :type name: :py:class:`unicode`
466
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400467 If the named curve is not supported then :py:class:`ValueError` is raised.
468 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400469 for curve in get_elliptic_curves():
470 if curve.name == name:
471 return curve
472 raise ValueError("unknown curve name", name)
473
474
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800475class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200476 """
477 An X.509 Distinguished Name.
478
479 :ivar countryName: The country of the entity.
480 :ivar C: Alias for :py:attr:`countryName`.
481
482 :ivar stateOrProvinceName: The state or province of the entity.
483 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
484
485 :ivar localityName: The locality of the entity.
486 :ivar L: Alias for :py:attr:`localityName`.
487
488 :ivar organizationName: The organization name of the entity.
489 :ivar O: Alias for :py:attr:`organizationName`.
490
491 :ivar organizationalUnitName: The organizational unit of the entity.
492 :ivar OU: Alias for :py:attr:`organizationalUnitName`
493
494 :ivar commonName: The common name of the entity.
495 :ivar CN: Alias for :py:attr:`commonName`.
496
497 :ivar emailAddress: The e-mail address of the entity.
498 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400499
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800500 def __init__(self, name):
501 """
502 Create a new X509Name, copying the given X509Name instance.
503
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200504 :param name: The name to copy.
505 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800506 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500507 name = _lib.X509_NAME_dup(name._name)
508 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800509
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800510 def __setattr__(self, name, value):
511 if name.startswith('_'):
512 return super(X509Name, self).__setattr__(name, value)
513
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800514 # Note: we really do not want str subclasses here, so we do not use
515 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800516 if type(name) is not str:
517 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400518 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800519
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500520 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500521 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800522 try:
523 _raise_current_error()
524 except Error:
525 pass
526 raise AttributeError("No such attribute")
527
528 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500529 for i in range(_lib.X509_NAME_entry_count(self._name)):
530 ent = _lib.X509_NAME_get_entry(self._name, i)
531 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
532 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800533 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500534 ent = _lib.X509_NAME_delete_entry(self._name, i)
535 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800536 break
537
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500538 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800539 value = value.encode('utf-8')
540
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500541 add_result = _lib.X509_NAME_add_entry_by_NID(
542 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800543 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500544 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800545
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800546 def __getattr__(self, name):
547 """
548 Find attribute. An X509Name object has the following attributes:
549 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400550 organization (alias O), organizationalUnit (alias OU), commonName
551 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800552 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500553 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500554 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800555 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
556 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
557 # push something onto the error queue. If we don't clean that up
558 # now, someone else will bump into it later and be quite confused.
559 # See lp#314814.
560 try:
561 _raise_current_error()
562 except Error:
563 pass
564 return super(X509Name, self).__getattr__(name)
565
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500566 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800567 if entry_index == -1:
568 return None
569
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500570 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
571 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800572
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500573 result_buffer = _ffi.new("unsigned char**")
574 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400575 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800576
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700577 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400578 result = _ffi.buffer(
579 result_buffer[0], data_length
580 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700581 finally:
582 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500583 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800584 return result
585
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500586 def _cmp(op):
587 def f(self, other):
588 if not isinstance(other, X509Name):
589 return NotImplemented
590 result = _lib.X509_NAME_cmp(self._name, other._name)
591 return op(result, 0)
592 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800593
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500594 __eq__ = _cmp(__eq__)
595 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800596
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500597 __lt__ = _cmp(__lt__)
598 __le__ = _cmp(__le__)
599
600 __gt__ = _cmp(__gt__)
601 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800602
603 def __repr__(self):
604 """
605 String representation of an X509Name
606 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400607 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500608 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800609 self._name, result_buffer, len(result_buffer))
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700610 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800611
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500612 return "<X509Name object '%s'>" % (
613 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800614
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800615 def hash(self):
616 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200617 Return an integer representation of the first four bytes of the
618 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800619
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200620 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
621
622 :return: The (integer) hash of this name.
623 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800624 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500625 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800626
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800627 def der(self):
628 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200629 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800630
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200631 :return: The DER encoded form of this name.
632 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800633 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500634 result_buffer = _ffi.new('unsigned char**')
635 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400636 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800637
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500638 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
639 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800640 return string_result
641
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800642 def get_components(self):
643 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200644 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800645
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200646 :return: The components of this name.
647 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800648 """
649 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500650 for i in range(_lib.X509_NAME_entry_count(self._name)):
651 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800652
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500653 fname = _lib.X509_NAME_ENTRY_get_object(ent)
654 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800655
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500656 nid = _lib.OBJ_obj2nid(fname)
657 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800658
659 result.append((
Alex Gaynora738ed52015-09-05 11:17:10 -0400660 _ffi.string(name),
661 _ffi.string(
662 _lib.ASN1_STRING_data(fval),
663 _lib.ASN1_STRING_length(fval))))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800664
665 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200666
667
Alex Gaynor10d30832017-06-29 15:31:39 -0700668X509NameType = deprecated(
669 X509Name, __name__,
670 "X509NameType has been deprecated, use X509Name instead",
671 DeprecationWarning
672)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800673
674
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800675class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200676 """
677 An X.509 v3 certificate extension.
678 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400679
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800680 def __init__(self, type_name, critical, value, subject=None, issuer=None):
681 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200682 Initializes an X509 extension.
683
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100684 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400685 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800686
Alex Gaynor5945ea82015-09-05 14:59:06 -0400687 :param bool critical: A flag indicating whether this is a critical
688 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800689
690 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200691 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800692
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200693 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800694 :type subject: :py:class:`X509`
695
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200696 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800697 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100698
Alex Chan54005ce2017-03-21 08:08:17 +0000699 .. _extension: https://www.openssl.org/docs/manmaster/man5/
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100700 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800701 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500702 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800703
Alex Gaynor5945ea82015-09-05 14:59:06 -0400704 # A context is necessary for any extension which uses the r2i
705 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
706 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500707 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800708
709 # We have no configuration database - but perhaps we should (some
710 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500711 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800712
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800713 # Initialize the subject and issuer, if appropriate. ctx is a local,
714 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400715 # any references, so no need to mess with reference counts or
716 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800717 if issuer is not None:
718 if not isinstance(issuer, X509):
719 raise TypeError("issuer must be an X509 instance")
720 ctx.issuer_cert = issuer._x509
721 if subject is not None:
722 if not isinstance(subject, X509):
723 raise TypeError("subject must be an X509 instance")
724 ctx.subject_cert = subject._x509
725
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800726 if critical:
727 # There are other OpenSSL APIs which would let us pass in critical
728 # separately, but they're harder to use, and since value is already
729 # a pile of crappy junk smuggling a ton of utterly important
730 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400731 # with strings? (However, X509V3_EXT_i2d in particular seems like
732 # it would be a better API to invoke. I do not know where to get
733 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500734 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800735
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500736 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
737 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800738 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500739 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800740
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400741 @property
742 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400743 return _lib.OBJ_obj2nid(
744 _lib.X509_EXTENSION_get_object(self._extension)
745 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400746
747 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500748 _lib.GEN_EMAIL: "email",
749 _lib.GEN_DNS: "DNS",
750 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400751 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400752
753 def _subjectAltNameString(self):
Alex Gaynord61c46a2017-06-29 22:51:33 -0700754 names = _ffi.cast(
755 "GENERAL_NAMES*", _lib.X509V3_EXT_d2i(self._extension)
756 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400757
Paul Kehrerb7d79502015-05-04 07:43:51 -0500758 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400759 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500760 for i in range(_lib.sk_GENERAL_NAME_num(names)):
761 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400762 try:
763 label = self._prefixes[name.type]
764 except KeyError:
765 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500766 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500767 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400768 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500769 value = _native(
770 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
771 parts.append(label + ":" + value)
772 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400773
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800774 def __str__(self):
775 """
776 :return: a nice text representation of the extension
777 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500778 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400779 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800780
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400781 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500782 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400783 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800784
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500785 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800786
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800787 def get_critical(self):
788 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200789 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800790
791 :return: The critical field.
792 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500793 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800794
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800795 def get_short_name(self):
796 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200797 Returns the short type name of this X.509 extension.
798
799 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800800
801 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200802 :rtype: :py:data:`bytes`
803
804 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800805 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500806 obj = _lib.X509_EXTENSION_get_object(self._extension)
807 nid = _lib.OBJ_obj2nid(obj)
808 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800809
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800810 def get_data(self):
811 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200812 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800813
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200814 :return: The ASN.1 encoded data of this X509 extension.
815 :rtype: :py:data:`bytes`
816
817 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800818 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500819 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
820 string_result = _ffi.cast('ASN1_STRING*', octet_result)
821 char_result = _lib.ASN1_STRING_data(string_result)
822 result_length = _lib.ASN1_STRING_length(string_result)
823 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800824
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200825
Alex Gaynor10d30832017-06-29 15:31:39 -0700826X509ExtensionType = deprecated(
827 X509Extension, __name__,
828 "X509ExtensionType has been deprecated, use X509Extension instead",
829 DeprecationWarning
830)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800831
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800832
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800833class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200834 """
835 An X.509 certificate signing requests.
836 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400837
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800838 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500839 req = _lib.X509_REQ_new()
840 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Alex Gaynor5af32d02016-09-24 01:52:21 -0400841 # Default to version 0.
842 self.set_version(0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800843
Paul Kehrer41c10242017-06-29 18:24:17 -0500844 def to_cryptography(self):
845 """
846 Export as a ``cryptography`` certificate signing request.
847
848 :rtype: ``cryptography.x509.CertificateSigningRequest``
849
850 .. versionadded:: 17.1.0
851 """
852 from cryptography.hazmat.backends.openssl.x509 import (
853 _CertificateSigningRequest
854 )
855 backend = _get_backend()
856 return _CertificateSigningRequest(backend, self._req)
857
858 @classmethod
859 def from_cryptography(cls, crypto_req):
860 """
861 Construct based on a ``cryptography`` *crypto_req*.
862
863 :param crypto_req: A ``cryptography`` X.509 certificate signing request
864 :type crypto_req: ``cryptography.x509.CertificateSigningRequest``
865
866 :rtype: PKey
867
868 .. versionadded:: 17.1.0
869 """
870 if not isinstance(crypto_req, x509.CertificateSigningRequest):
871 raise TypeError("Must be a certificate signing request")
872
873 req = cls()
874 req._req = crypto_req._x509_req
875 return req
876
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800877 def set_pubkey(self, pkey):
878 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200879 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800880
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200881 :param pkey: The public key to use.
882 :type pkey: :py:class:`PKey`
883
Dan Sully44e767a2016-06-04 18:05:27 -0700884 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800885 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500886 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400887 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800888
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800889 def get_pubkey(self):
890 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200891 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800892
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200893 :return: The public key.
894 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800895 """
896 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500897 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700898 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500899 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800900 pkey._only_public = True
901 return pkey
902
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800903 def set_version(self, version):
904 """
905 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
906 request.
907
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200908 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700909 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800910 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500911 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400912 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800913
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800914 def get_version(self):
915 """
916 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
917 request.
918
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200919 :return: The value of the version subfield.
920 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800921 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500922 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800923
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800924 def get_subject(self):
925 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200926 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800927
Cory Benfield881dc8d2015-12-09 08:25:14 +0000928 This creates a new :class:`X509Name` that wraps the underlying subject
929 name field on the certificate signing request. Modifying it will modify
930 the underlying signing request, and will have the effect of modifying
931 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200932
933 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000934 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800935 """
936 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500937 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700938 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800939
940 # The name is owned by the X509Req structure. As long as the X509Name
941 # Python object is alive, keep the X509Req Python object alive.
942 name._owner = self
943
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800944 return name
945
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800946 def add_extensions(self, extensions):
947 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200948 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800949
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200950 :param extensions: The X.509 extensions to add.
951 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700952 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800953 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500954 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700955 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800956
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500957 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800958
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800959 for ext in extensions:
960 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -0800961 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800962
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800963 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500964 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800965
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500966 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400967 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800968
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800969 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800970 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200971 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800972
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200973 :return: The X.509 extensions in this request.
974 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
975
976 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800977 """
978 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500979 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -0500980 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800981 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500982 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800983 exts.append(ext)
984 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800985
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800986 def sign(self, pkey, digest):
987 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -0700988 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800989
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200990 :param pkey: The key pair to sign with.
991 :type pkey: :py:class:`PKey`
992 :param digest: The name of the message digest to use for the signature,
Alex Gaynor239e2d32016-09-11 12:36:35 -0400993 e.g. :py:data:`b"sha256"`.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200994 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -0700995 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800996 """
997 if pkey._only_public:
998 raise ValueError("Key has only public part")
999
1000 if not pkey._initialized:
1001 raise ValueError("Key is uninitialized")
1002
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001003 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001004 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001005 raise ValueError("No such digest method")
1006
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001007 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001008 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001009
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001010 def verify(self, pkey):
1011 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001012 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001013
Hynek Schlawack01c31672016-12-11 15:14:09 +01001014 :param PKey key: A public key.
1015
1016 :return: ``True`` if the signature is correct.
1017 :rtype: bool
1018
1019 :raises OpenSSL.crypto.Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001020 problem verifying the signature.
1021 """
1022 if not isinstance(pkey, PKey):
1023 raise TypeError("pkey must be a PKey instance")
1024
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001025 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001026 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001027 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001028
1029 return result
1030
1031
Alex Gaynor10d30832017-06-29 15:31:39 -07001032X509ReqType = deprecated(
1033 X509Req, __name__,
1034 "X509ReqType has been deprecated, use X509Req instead",
1035 DeprecationWarning
1036)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001037
1038
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001039class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001040 """
1041 An X.509 certificate.
1042 """
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001043 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001044 x509 = _lib.X509_new()
Hynek Schlawack8a2dd772016-07-31 13:46:20 +02001045 _openssl_assert(x509 != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001046 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001047
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001048 self._issuer_invalidator = _X509NameInvalidator()
1049 self._subject_invalidator = _X509NameInvalidator()
1050
1051 @classmethod
1052 def _from_raw_x509_ptr(cls, x509):
1053 cert = cls.__new__(cls)
1054 cert._x509 = _ffi.gc(x509, _lib.X509_free)
1055 cert._issuer_invalidator = _X509NameInvalidator()
1056 cert._subject_invalidator = _X509NameInvalidator()
1057 return cert
1058
Alex Gaynor9939ba12017-06-25 16:28:24 -04001059 def to_cryptography(self):
1060 """
1061 Export as a ``cryptography`` certificate.
1062
1063 :rtype: ``cryptography.x509.Certificate``
1064
1065 .. versionadded:: 17.1.0
1066 """
1067 from cryptography.hazmat.backends.openssl.x509 import _Certificate
1068 backend = _get_backend()
1069 return _Certificate(backend, self._x509)
1070
1071 @classmethod
1072 def from_cryptography(cls, crypto_cert):
1073 """
1074 Construct based on a ``cryptography`` *crypto_cert*.
1075
1076 :param crypto_key: A ``cryptography`` X.509 certificate.
1077 :type crypto_key: ``cryptography.x509.Certificate``
1078
1079 :rtype: PKey
1080
1081 .. versionadded:: 17.1.0
1082 """
1083 if not isinstance(crypto_cert, x509.Certificate):
1084 raise TypeError("Must be a certificate")
1085
1086 cert = cls()
1087 cert._x509 = crypto_cert._x509
1088 return cert
1089
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001090 def set_version(self, version):
1091 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001092 Set the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001093
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001094 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001095 :type version: :py:class:`int`
1096
Dan Sully44e767a2016-06-04 18:05:27 -07001097 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001098 """
1099 if not isinstance(version, int):
1100 raise TypeError("version must be an integer")
1101
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001102 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001103
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001104 def get_version(self):
1105 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001106 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001107
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001108 :return: The version number of the certificate.
1109 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001110 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001111 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001112
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001113 def get_pubkey(self):
1114 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001115 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001116
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001117 :return: The public key.
1118 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001119 """
1120 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001121 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1122 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001123 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001124 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001125 pkey._only_public = True
1126 return pkey
1127
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001128 def set_pubkey(self, pkey):
1129 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001130 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001131
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001132 :param pkey: The public key.
1133 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001134
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001135 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001136 """
1137 if not isinstance(pkey, PKey):
1138 raise TypeError("pkey must be a PKey instance")
1139
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001140 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001141 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001142
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001143 def sign(self, pkey, digest):
1144 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001145 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001146
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001147 :param pkey: The key to sign with.
1148 :type pkey: :py:class:`PKey`
1149
1150 :param digest: The name of the message digest to use.
1151 :type digest: :py:class:`bytes`
1152
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001153 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001154 """
1155 if not isinstance(pkey, PKey):
1156 raise TypeError("pkey must be a PKey instance")
1157
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001158 if pkey._only_public:
1159 raise ValueError("Key only has public part")
1160
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001161 if not pkey._initialized:
1162 raise ValueError("Key is uninitialized")
1163
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001164 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001165 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001166 raise ValueError("No such digest method")
1167
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001168 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001169 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001170
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001171 def get_signature_algorithm(self):
1172 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001173 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001174
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001175 :return: The name of the algorithm.
1176 :rtype: :py:class:`bytes`
1177
1178 :raises ValueError: If the signature algorithm is undefined.
1179
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001180 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001181 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001182 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1183 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001184 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001185 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001186 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001187
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001188 def digest(self, digest_name):
1189 """
1190 Return the digest of the X509 object.
1191
1192 :param digest_name: The name of the digest algorithm to use.
1193 :type digest_name: :py:class:`bytes`
1194
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001195 :return: The digest of the object, formatted as
1196 :py:const:`b":"`-delimited hex pairs.
1197 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001198 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001199 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001200 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001201 raise ValueError("No such digest method")
1202
Paul Kehrer9f9113a2016-09-20 20:10:25 -05001203 result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001204 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001205 result_length[0] = len(result_buffer)
1206
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001207 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001208 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001209 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001210
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001211 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001212 b16encode(ch).upper() for ch
1213 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001214
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001215 def subject_name_hash(self):
1216 """
1217 Return the hash of the X509 subject.
1218
1219 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001220 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001221 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001222 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001223
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001224 def set_serial_number(self, serial):
1225 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001226 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001227
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001228 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001229 :type serial: :py:class:`int`
1230
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001231 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001232 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001233 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001234 raise TypeError("serial must be an integer")
1235
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001236 hex_serial = hex(serial)[2:]
1237 if not isinstance(hex_serial, bytes):
1238 hex_serial = hex_serial.encode('ascii')
1239
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001240 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001241
1242 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001243 # it. If bignum is still NULL after this call, then the return value
1244 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001245 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001246
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001247 if bignum_serial[0] == _ffi.NULL:
1248 set_result = _lib.ASN1_INTEGER_set(
1249 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001250 if set_result:
1251 # TODO Not tested
1252 _raise_current_error()
1253 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001254 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1255 _lib.BN_free(bignum_serial[0])
1256 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001257 # TODO Not tested
1258 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001259 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1260 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001261 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001262
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001263 def get_serial_number(self):
1264 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001265 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001266
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001267 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001268 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001269 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001270 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1271 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001272 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001273 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001274 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001275 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001276 serial = int(hexstring_serial, 16)
1277 return serial
1278 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001279 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001280 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001281 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001282
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001283 def gmtime_adj_notAfter(self, amount):
1284 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001285 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001286
Dan Sully44e767a2016-06-04 18:05:27 -07001287 :param int amount: The number of seconds by which to adjust the
1288 timestamp.
1289 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001290 """
1291 if not isinstance(amount, int):
1292 raise TypeError("amount must be an integer")
1293
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001294 notAfter = _lib.X509_get_notAfter(self._x509)
1295 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001296
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001297 def gmtime_adj_notBefore(self, amount):
1298 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001299 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001300
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001301 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001302 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001303 """
1304 if not isinstance(amount, int):
1305 raise TypeError("amount must be an integer")
1306
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001307 notBefore = _lib.X509_get_notBefore(self._x509)
1308 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001309
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001310 def has_expired(self):
1311 """
1312 Check whether the certificate has expired.
1313
Dan Sully44e767a2016-06-04 18:05:27 -07001314 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1315 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001316 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001317 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001318 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001319
Paul Kehrerfde45c92016-01-21 12:57:37 -06001320 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001321
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001322 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001323 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001324
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001325 def get_notBefore(self):
1326 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001327 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001328
Paul Kehrerce98ee62017-06-21 06:59:58 -10001329 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001330
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001331 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001332
Dan Sully44e767a2016-06-04 18:05:27 -07001333 :return: A timestamp string, or ``None`` if there is none.
1334 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001335 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001336 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001337
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001338 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001339 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001340
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001341 def set_notBefore(self, when):
1342 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001343 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001344
Paul Kehrerce98ee62017-06-21 06:59:58 -10001345 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001346
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001347 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001348
Dan Sully44e767a2016-06-04 18:05:27 -07001349 :param bytes when: A timestamp string.
1350 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001351 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001352 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001353
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001354 def get_notAfter(self):
1355 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001356 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001357
Paul Kehrerce98ee62017-06-21 06:59:58 -10001358 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001359
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001360 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001361
Dan Sully44e767a2016-06-04 18:05:27 -07001362 :return: A timestamp string, or ``None`` if there is none.
1363 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001364 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001365 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001366
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001367 def set_notAfter(self, when):
1368 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001369 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001370
Paul Kehrerce98ee62017-06-21 06:59:58 -10001371 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001372
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001373 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001374
Dan Sully44e767a2016-06-04 18:05:27 -07001375 :param bytes when: A timestamp string.
1376 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001377 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001378 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001379
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001380 def _get_name(self, which):
1381 name = X509Name.__new__(X509Name)
1382 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001383 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001384
1385 # The name is owned by the X509 structure. As long as the X509Name
1386 # Python object is alive, keep the X509 Python object alive.
1387 name._owner = self
1388
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001389 return name
1390
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001391 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001392 if not isinstance(name, X509Name):
1393 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001394 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001395 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001396
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001397 def get_issuer(self):
1398 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001399 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001400
Cory Benfielde6bcce82015-12-09 08:40:03 +00001401 This creates a new :class:`X509Name` that wraps the underlying issuer
1402 name field on the certificate. Modifying it will modify the underlying
1403 certificate, and will have the effect of modifying any other
1404 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001405
1406 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001407 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001408 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001409 name = self._get_name(_lib.X509_get_issuer_name)
1410 self._issuer_invalidator.add(name)
1411 return name
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001412
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001413 def set_issuer(self, issuer):
1414 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001415 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001416
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001417 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001418 :type issuer: :py:class:`X509Name`
1419
Dan Sully44e767a2016-06-04 18:05:27 -07001420 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001421 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001422 self._set_name(_lib.X509_set_issuer_name, issuer)
1423 self._issuer_invalidator.clear()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001424
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001425 def get_subject(self):
1426 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001427 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001428
Cory Benfielde6bcce82015-12-09 08:40:03 +00001429 This creates a new :class:`X509Name` that wraps the underlying subject
1430 name field on the certificate. Modifying it will modify the underlying
1431 certificate, and will have the effect of modifying any other
1432 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001433
1434 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001435 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001436 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001437 name = self._get_name(_lib.X509_get_subject_name)
1438 self._subject_invalidator.add(name)
1439 return name
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001440
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001441 def set_subject(self, subject):
1442 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001443 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001444
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001445 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001446 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001447
Dan Sully44e767a2016-06-04 18:05:27 -07001448 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001449 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001450 self._set_name(_lib.X509_set_subject_name, subject)
1451 self._subject_invalidator.clear()
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001452
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001453 def get_extension_count(self):
1454 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001455 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001456
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001457 :return: The number of extensions.
1458 :rtype: :py:class:`int`
1459
1460 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001461 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001462 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001463
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001464 def add_extensions(self, extensions):
1465 """
1466 Add extensions to the certificate.
1467
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001468 :param extensions: The extensions to add.
1469 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001470 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001471 """
1472 for ext in extensions:
1473 if not isinstance(ext, X509Extension):
1474 raise ValueError("One of the elements is not an X509Extension")
1475
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001476 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001477 if not add_result:
1478 _raise_current_error()
1479
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001480 def get_extension(self, index):
1481 """
1482 Get a specific extension of the certificate by index.
1483
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001484 Extensions on a certificate are kept in order. The index
1485 parameter selects which extension will be returned.
1486
1487 :param int index: The index of the extension to retrieve.
1488 :return: The extension at the specified index.
1489 :rtype: :py:class:`X509Extension`
1490 :raises IndexError: If the extension index was out of bounds.
1491
1492 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001493 """
1494 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001495 ext._extension = _lib.X509_get_ext(self._x509, index)
1496 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001497 raise IndexError("extension index out of bounds")
1498
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001499 extension = _lib.X509_EXTENSION_dup(ext._extension)
1500 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001501 return ext
1502
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001503
Alex Gaynor10d30832017-06-29 15:31:39 -07001504X509Type = deprecated(
1505 X509, __name__,
1506 "X509Type has been deprecated, use X509 instead",
1507 DeprecationWarning
1508)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001509
1510
Dan Sully44e767a2016-06-04 18:05:27 -07001511class X509StoreFlags(object):
1512 """
1513 Flags for X509 verification, used to change the behavior of
1514 :class:`X509Store`.
1515
1516 See `OpenSSL Verification Flags`_ for details.
1517
1518 .. _OpenSSL Verification Flags:
Alex Chan54005ce2017-03-21 08:08:17 +00001519 https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_flags.html
Dan Sully44e767a2016-06-04 18:05:27 -07001520 """
1521 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1522 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1523 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1524 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1525 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1526 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1527 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1528 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1529 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1530 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1531 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1532
1533
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001534class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001535 """
Dan Sully44e767a2016-06-04 18:05:27 -07001536 An X.509 store.
1537
1538 An X.509 store is used to describe a context in which to verify a
1539 certificate. A description of a context may include a set of certificates
1540 to trust, a set of certificate revocation lists, verification flags and
1541 more.
1542
1543 An X.509 store, being only a description, cannot be used by itself to
1544 verify a certificate. To carry out the actual verification process, see
1545 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001546 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001547
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001548 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001549 store = _lib.X509_STORE_new()
1550 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001551
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001552 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001553 """
Dan Sully44e767a2016-06-04 18:05:27 -07001554 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001555
Dan Sully44e767a2016-06-04 18:05:27 -07001556 Adding a certificate with this method adds this certificate as a
1557 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001558
1559 :param X509 cert: The certificate to add to this store.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001560
Dan Sully44e767a2016-06-04 18:05:27 -07001561 :raises TypeError: If the certificate is not an :class:`X509`.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001562
1563 :raises OpenSSL.crypto.Error: If OpenSSL was unhappy with your
1564 certificate.
1565
Dan Sully44e767a2016-06-04 18:05:27 -07001566 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001567 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001568 if not isinstance(cert, X509):
1569 raise TypeError()
1570
Dan Sully44e767a2016-06-04 18:05:27 -07001571 _openssl_assert(_lib.X509_STORE_add_cert(self._store, cert._x509) != 0)
1572
1573 def add_crl(self, crl):
1574 """
1575 Add a certificate revocation list to this store.
1576
1577 The certificate revocation lists added to a store will only be used if
1578 the associated flags are configured to check certificate revocation
1579 lists.
1580
1581 .. versionadded:: 16.1.0
1582
1583 :param CRL crl: The certificate revocation list to add to this store.
1584 :return: ``None`` if the certificate revocation list was added
1585 successfully.
1586 """
1587 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1588
1589 def set_flags(self, flags):
1590 """
1591 Set verification flags to this store.
1592
1593 Verification flags can be combined by oring them together.
1594
1595 .. note::
1596
1597 Setting a verification flag sometimes requires clients to add
1598 additional information to the store, otherwise a suitable error will
1599 be raised.
1600
1601 For example, in setting flags to enable CRL checking a
1602 suitable CRL must be added to the store otherwise an error will be
1603 raised.
1604
1605 .. versionadded:: 16.1.0
1606
1607 :param int flags: The verification flags to set on this store.
1608 See :class:`X509StoreFlags` for available constants.
1609 :return: ``None`` if the verification flags were successfully set.
1610 """
1611 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001612
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001613 def set_time(self, vfy_time):
1614 """
1615 Set the time against which the certificates are verified.
1616
1617 Normally the current time is used.
1618
1619 .. note::
1620
1621 For example, you can determine if a certificate was valid at a given
1622 time.
1623
Hynek Schlawackf6c96af2017-04-20 12:34:58 +02001624 .. versionadded:: 17.0.0
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001625
1626 :param datetime vfy_time: The verification time to set on this store.
1627 :return: ``None`` if the verification time was successfully set.
1628 """
1629 param = _lib.X509_VERIFY_PARAM_new()
1630 param = _ffi.gc(param, _lib.X509_VERIFY_PARAM_free)
1631
1632 _lib.X509_VERIFY_PARAM_set_time(param, int(vfy_time.strftime('%s')))
1633 _openssl_assert(_lib.X509_STORE_set1_param(self._store, param) != 0)
1634
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001635
Alex Gaynor10d30832017-06-29 15:31:39 -07001636X509StoreType = deprecated(
1637 X509Store, __name__,
1638 "X509StoreType has been deprecated, use X509Store instead",
1639 DeprecationWarning
1640)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001641
1642
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001643class X509StoreContextError(Exception):
1644 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001645 An exception raised when an error occurred while verifying a certificate
1646 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001647
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001648 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001649 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001650 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001651
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001652 def __init__(self, message, certificate):
1653 super(X509StoreContextError, self).__init__(message)
1654 self.certificate = certificate
1655
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001656
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001657class X509StoreContext(object):
1658 """
1659 An X.509 store context.
1660
Dan Sully44e767a2016-06-04 18:05:27 -07001661 An X.509 store context is used to carry out the actual verification process
1662 of a certificate in a described context. For describing such a context, see
1663 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001664
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001665 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1666 instance. It is dynamically allocated and automatically garbage
1667 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001668 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001669 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001670 :param X509Store store: The certificates which will be trusted for the
1671 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001672 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001673 """
1674
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001675 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001676 store_ctx = _lib.X509_STORE_CTX_new()
1677 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1678 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001679 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001680 # Make the store context available for use after instantiating this
1681 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001682 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001683 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001684
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001685 def _init(self):
1686 """
1687 Set up the store context for a subsequent verification operation.
Jeremy Cline58193f12017-09-13 21:14:53 -04001688
1689 Calling this method more than once without first calling
1690 :meth:`_cleanup` will leak memory.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001691 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001692 ret = _lib.X509_STORE_CTX_init(
1693 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1694 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001695 if ret <= 0:
1696 _raise_current_error()
1697
1698 def _cleanup(self):
1699 """
1700 Internally cleans up the store context.
1701
Dan Sully44e767a2016-06-04 18:05:27 -07001702 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001703 """
1704 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1705
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001706 def _exception_from_context(self):
1707 """
1708 Convert an OpenSSL native context error failure into a Python
1709 exception.
1710
Alex Gaynor5945ea82015-09-05 14:59:06 -04001711 When a call to native OpenSSL X509_verify_cert fails, additional
1712 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001713 """
1714 errors = [
1715 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1716 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1717 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001718 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001719 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001720 # A context error should always be associated with a certificate, so we
1721 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001722 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001723 _cert = _lib.X509_dup(_x509)
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001724 pycert = X509._from_raw_x509_ptr(_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001725 return X509StoreContextError(errors, pycert)
1726
Stephen Holsapple46a09252015-02-12 14:45:43 -08001727 def set_store(self, store):
1728 """
Dan Sully44e767a2016-06-04 18:05:27 -07001729 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001730
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001731 .. versionadded:: 0.15
1732
Dan Sully44e767a2016-06-04 18:05:27 -07001733 :param X509Store store: The store description which will be used for
1734 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001735 """
1736 self._store = store
1737
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001738 def verify_certificate(self):
1739 """
1740 Verify a certificate in a context.
1741
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001742 .. versionadded:: 0.15
1743
Alex Gaynorca87ff62015-09-04 23:31:03 -04001744 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001745 certificate in the context. Sets ``certificate`` attribute to
1746 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001747 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001748 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001749 # :meth:`verify_certificate` is called multiple times.
Jeremy Cline58193f12017-09-13 21:14:53 -04001750 #
1751 # :meth:`_init` is called in :meth:`__init__` so _cleanup is called
1752 # before _init to ensure memory is not leaked.
1753 self._cleanup()
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001754 self._init()
1755 ret = _lib.X509_verify_cert(self._store_ctx)
1756 self._cleanup()
1757 if ret <= 0:
1758 raise self._exception_from_context()
1759
1760
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001761def load_certificate(type, buffer):
1762 """
1763 Load a certificate from a buffer
1764
1765 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1766
Dan Sully44e767a2016-06-04 18:05:27 -07001767 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001768
1769 :return: The X509 object
1770 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001771 if isinstance(buffer, _text_type):
1772 buffer = buffer.encode("ascii")
1773
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001774 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001775
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001776 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001777 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001778 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001779 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001780 else:
1781 raise ValueError(
1782 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001783
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001784 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001785 _raise_current_error()
1786
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001787 return X509._from_raw_x509_ptr(x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001788
1789
1790def dump_certificate(type, cert):
1791 """
1792 Dump a certificate to a buffer
1793
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001794 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1795 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001796 :param cert: The certificate to dump
1797 :return: The buffer with the dumped certificate in
1798 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001799 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001800
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001801 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001802 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001803 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001804 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001805 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001806 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001807 else:
1808 raise ValueError(
1809 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1810 "FILETYPE_TEXT")
1811
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001812 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001813 return _bio_to_string(bio)
1814
1815
Cory Benfield6492f7c2015-10-27 16:57:58 +09001816def dump_publickey(type, pkey):
1817 """
Cory Benfield11c10192015-10-27 17:23:03 +09001818 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001819
Cory Benfield9c590b92015-10-28 14:55:05 +09001820 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001821 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001822 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001823 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001824 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001825 """
1826 bio = _new_mem_buf()
1827 if type == FILETYPE_PEM:
1828 write_bio = _lib.PEM_write_bio_PUBKEY
1829 elif type == FILETYPE_ASN1:
1830 write_bio = _lib.i2d_PUBKEY_bio
1831 else:
1832 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1833
1834 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001835 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001836 _raise_current_error()
1837
1838 return _bio_to_string(bio)
1839
1840
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001841def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1842 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001843 Dump the private key *pkey* into a buffer string encoded with the type
1844 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1845 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001846
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001847 :param type: The file type (one of :const:`FILETYPE_PEM`,
1848 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1849 :param PKey pkey: The PKey to dump
1850 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001851 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001852 the passphrase to use, or a callback for providing the passphrase.
1853
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001854 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001855 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001856 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001857 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001858
Paul Kehrercded9932017-06-29 18:43:42 -05001859 if not isinstance(pkey, PKey):
1860 raise TypeError("pkey must be a PKey")
1861
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001862 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001863 if passphrase is None:
1864 raise TypeError(
1865 "if a value is given for cipher "
1866 "one must also be given for passphrase")
1867 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001868 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001869 raise ValueError("Invalid cipher name")
1870 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001871 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001872
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001873 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001874 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001875 result_code = _lib.PEM_write_bio_PrivateKey(
1876 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001877 helper.callback, helper.callback_args)
1878 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001879 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001880 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001881 elif type == FILETYPE_TEXT:
Paul Kehrercded9932017-06-29 18:43:42 -05001882 if _lib.EVP_PKEY_id(pkey._pkey) != _lib.EVP_PKEY_RSA:
1883 raise TypeError("Only RSA keys are supported for FILETYPE_TEXT")
1884
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001885 rsa = _ffi.gc(
1886 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1887 _lib.RSA_free
1888 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001889 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001890 else:
1891 raise ValueError(
1892 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1893 "FILETYPE_TEXT")
1894
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001895 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001896
1897 return _bio_to_string(bio)
1898
1899
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001900class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001901 """
1902 A certificate revocation.
1903 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001904 # http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_
1905 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1906 # OCSP_crl_reason_str. We use the latter, just like the command line
1907 # program.
1908 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001909 b"unspecified",
1910 b"keyCompromise",
1911 b"CACompromise",
1912 b"affiliationChanged",
1913 b"superseded",
1914 b"cessationOfOperation",
1915 b"certificateHold",
1916 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001917 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001918
1919 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001920 revoked = _lib.X509_REVOKED_new()
1921 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001922
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001923 def set_serial(self, hex_str):
1924 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001925 Set the serial number.
1926
1927 The serial number is formatted as a hexadecimal number encoded in
1928 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001929
Dan Sully44e767a2016-06-04 18:05:27 -07001930 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001931
Dan Sully44e767a2016-06-04 18:05:27 -07001932 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001933 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001934 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1935 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001936 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001937 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001938 if not bn_result:
1939 raise ValueError("bad hex string")
1940
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001941 asn1_serial = _ffi.gc(
1942 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1943 _lib.ASN1_INTEGER_free)
1944 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001945
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001946 def get_serial(self):
1947 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001948 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001949
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001950 The serial number is formatted as a hexadecimal number encoded in
1951 ASCII.
1952
1953 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001954 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001955 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001956 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001957
Alex Gaynor67903a62016-06-02 10:37:13 -07001958 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1959 _openssl_assert(asn1_int != _ffi.NULL)
1960 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1961 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001962 return _bio_to_string(bio)
1963
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001964 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001965 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1966 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001967 obj = _lib.X509_EXTENSION_get_object(ext)
1968 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001969 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001970 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001971 break
1972
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001973 def set_reason(self, reason):
1974 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001975 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001976
Dan Sully44e767a2016-06-04 18:05:27 -07001977 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001978
1979 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07001980 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001981
Dan Sully44e767a2016-06-04 18:05:27 -07001982 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001983
1984 .. seealso::
1985
Dan Sully44e767a2016-06-04 18:05:27 -07001986 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001987 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001988 """
1989 if reason is None:
1990 self._delete_reason()
1991 elif not isinstance(reason, bytes):
1992 raise TypeError("reason must be None or a byte string")
1993 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001994 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001995 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
1996
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001997 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07001998 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001999 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002000
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002001 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002002 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002003
2004 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002005 add_result = _lib.X509_REVOKED_add1_ext_i2d(
2006 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002007 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002008
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002009 def get_reason(self):
2010 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04002011 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002012
Dan Sully44e767a2016-06-04 18:05:27 -07002013 :return: The reason, or ``None`` if there is none.
2014 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002015
2016 .. seealso::
2017
Dan Sully44e767a2016-06-04 18:05:27 -07002018 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002019 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002020 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002021 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
2022 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002023 obj = _lib.X509_EXTENSION_get_object(ext)
2024 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08002025 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002026
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002027 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002028 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002029 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002030 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04002031 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002032 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002033
2034 return _bio_to_string(bio)
2035
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002036 def all_reasons(self):
2037 """
2038 Return a list of all the supported reason strings.
2039
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002040 This list is a copy; modifying it does not change the supported reason
2041 strings.
2042
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002043 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07002044 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002045 """
2046 return self._crl_reasons[:]
2047
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002048 def set_rev_date(self, when):
2049 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002050 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002051
Dan Sully44e767a2016-06-04 18:05:27 -07002052 :param bytes when: The timestamp of the revocation,
Paul Kehrerce98ee62017-06-21 06:59:58 -10002053 as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002054 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002055 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002056 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2057 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002058
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002059 def get_rev_date(self):
2060 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002061 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002062
Paul Kehrerce98ee62017-06-21 06:59:58 -10002063 :return: The timestamp of the revocation, as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002064 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002065 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002066 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2067 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002068
2069
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002070class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002071 """
2072 A certificate revocation list.
2073 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002074
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002075 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002076 crl = _lib.X509_CRL_new()
2077 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002078
Paul Kehrer41c10242017-06-29 18:24:17 -05002079 def to_cryptography(self):
2080 """
2081 Export as a ``cryptography`` CRL.
2082
2083 :rtype: ``cryptography.x509.CertificateRevocationList``
2084
2085 .. versionadded:: 17.1.0
2086 """
2087 from cryptography.hazmat.backends.openssl.x509 import (
2088 _CertificateRevocationList
2089 )
2090 backend = _get_backend()
2091 return _CertificateRevocationList(backend, self._crl)
2092
2093 @classmethod
2094 def from_cryptography(cls, crypto_crl):
2095 """
2096 Construct based on a ``cryptography`` *crypto_crl*.
2097
2098 :param crypto_crl: A ``cryptography`` certificate revocation list
2099 :type crypto_crl: ``cryptography.x509.CertificateRevocationList``
2100
2101 :rtype: CRL
2102
2103 .. versionadded:: 17.1.0
2104 """
2105 if not isinstance(crypto_crl, x509.CertificateRevocationList):
2106 raise TypeError("Must be a certificate revocation list")
2107
2108 crl = cls()
2109 crl._crl = crypto_crl._x509_crl
2110 return crl
2111
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002112 def get_revoked(self):
2113 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002114 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002115
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002116 These revocations will be provided by value, not by reference.
2117 That means it's okay to mutate them: it won't affect this CRL.
2118
2119 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002120 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002121 """
2122 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07002123 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002124 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
2125 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04002126 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002127 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002128 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002129 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002130 if results:
2131 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002132
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002133 def add_revoked(self, revoked):
2134 """
2135 Add a revoked (by value not reference) to the CRL structure
2136
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002137 This revocation will be added by value, not by reference. That
2138 means it's okay to mutate it after adding: it won't affect
2139 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002140
Dan Sully44e767a2016-06-04 18:05:27 -07002141 :param Revoked revoked: The new revocation.
2142 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002143 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04002144 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002145 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002146
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002147 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002148 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002149
Dan Sully44e767a2016-06-04 18:05:27 -07002150 def get_issuer(self):
2151 """
2152 Get the CRL's issuer.
2153
2154 .. versionadded:: 16.1.0
2155
2156 :rtype: X509Name
2157 """
2158 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
2159 _openssl_assert(_issuer != _ffi.NULL)
2160 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
2161 issuer = X509Name.__new__(X509Name)
2162 issuer._name = _issuer
2163 return issuer
2164
2165 def set_version(self, version):
2166 """
2167 Set the CRL version.
2168
2169 .. versionadded:: 16.1.0
2170
2171 :param int version: The version of the CRL.
2172 :return: ``None``
2173 """
2174 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2175
2176 def _set_boundary_time(self, which, when):
2177 return _set_asn1_time(which(self._crl), when)
2178
2179 def set_lastUpdate(self, when):
2180 """
2181 Set when the CRL was last updated.
2182
Paul Kehrerce98ee62017-06-21 06:59:58 -10002183 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002184
2185 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002186
2187 .. versionadded:: 16.1.0
2188
2189 :param bytes when: A timestamp string.
2190 :return: ``None``
2191 """
2192 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2193
2194 def set_nextUpdate(self, when):
2195 """
2196 Set when the CRL will next be udpated.
2197
Paul Kehrerce98ee62017-06-21 06:59:58 -10002198 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002199
2200 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002201
2202 .. versionadded:: 16.1.0
2203
2204 :param bytes when: A timestamp string.
2205 :return: ``None``
2206 """
2207 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2208
2209 def sign(self, issuer_cert, issuer_key, digest):
2210 """
2211 Sign the CRL.
2212
2213 Signing a CRL enables clients to associate the CRL itself with an
2214 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2215 be signed by an issuer.
2216
2217 This method implicitly sets the issuer's name based on the issuer
2218 certificate and private key used to sign the CRL.
2219
2220 .. versionadded:: 16.1.0
2221
2222 :param X509 issuer_cert: The issuer's certificate.
2223 :param PKey issuer_key: The issuer's private key.
2224 :param bytes digest: The digest method to sign the CRL with.
2225 """
2226 digest_obj = _lib.EVP_get_digestbyname(digest)
2227 _openssl_assert(digest_obj != _ffi.NULL)
2228 _lib.X509_CRL_set_issuer_name(
2229 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2230 _lib.X509_CRL_sort(self._crl)
2231 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2232 _openssl_assert(result != 0)
2233
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002234 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002235 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002236 """
Dan Sully44e767a2016-06-04 18:05:27 -07002237 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002238
Dan Sully44e767a2016-06-04 18:05:27 -07002239 :param X509 cert: The certificate used to sign the CRL.
2240 :param PKey key: The key used to sign the CRL.
2241 :param int type: The export format, either :data:`FILETYPE_PEM`,
2242 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002243 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002244 :param bytes digest: The name of the message digest to use (eg
Alex Gaynor239e2d32016-09-11 12:36:35 -04002245 ``b"sha2566"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002246 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002247 """
Dan Sully44e767a2016-06-04 18:05:27 -07002248
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002249 if not isinstance(cert, X509):
2250 raise TypeError("cert must be an X509 instance")
2251 if not isinstance(key, PKey):
2252 raise TypeError("key must be a PKey instance")
2253 if not isinstance(type, int):
2254 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002255
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002256 if digest is _UNSPECIFIED:
Alex Gaynor173e4ba2017-06-30 08:01:12 -07002257 raise TypeError("digest must be provided")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002258
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002259 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002260 if digest_obj == _ffi.NULL:
2261 raise ValueError("No such digest method")
2262
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002263 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002264 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002265
Alex Gaynora738ed52015-09-05 11:17:10 -04002266 # A scratch time object to give different values to different CRL
2267 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002268 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002269 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002270
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002271 _lib.X509_gmtime_adj(sometime, 0)
2272 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002273
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002274 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2275 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002276
Alex Gaynor5945ea82015-09-05 14:59:06 -04002277 _lib.X509_CRL_set_issuer_name(
2278 self._crl, _lib.X509_get_subject_name(cert._x509)
2279 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002280
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002281 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002282 if not sign_result:
2283 _raise_current_error()
2284
Dominic Chenf05b2122015-10-13 16:32:35 +00002285 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002286
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002287
Alex Gaynor10d30832017-06-29 15:31:39 -07002288CRLType = deprecated(
2289 CRL, __name__,
2290 "CRLType has been deprecated, use CRL instead",
2291 DeprecationWarning
2292)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002293
2294
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002295class PKCS7(object):
2296 def type_is_signed(self):
2297 """
2298 Check if this NID_pkcs7_signed object
2299
2300 :return: True if the PKCS7 is of type signed
2301 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002302 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002303
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002304 def type_is_enveloped(self):
2305 """
2306 Check if this NID_pkcs7_enveloped object
2307
2308 :returns: True if the PKCS7 is of type enveloped
2309 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002310 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002311
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002312 def type_is_signedAndEnveloped(self):
2313 """
2314 Check if this NID_pkcs7_signedAndEnveloped object
2315
2316 :returns: True if the PKCS7 is of type signedAndEnveloped
2317 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002318 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002319
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002320 def type_is_data(self):
2321 """
2322 Check if this NID_pkcs7_data object
2323
2324 :return: True if the PKCS7 is of type data
2325 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002326 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002327
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002328 def get_type_name(self):
2329 """
2330 Returns the type name of the PKCS7 structure
2331
2332 :return: A string with the typename
2333 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002334 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2335 string_type = _lib.OBJ_nid2sn(nid)
2336 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002337
Alex Chanc6077062016-11-18 13:53:39 +00002338
Alex Gaynor10d30832017-06-29 15:31:39 -07002339PKCS7Type = deprecated(
2340 PKCS7, __name__,
2341 "PKCS7Type has been deprecated, use PKCS7 instead",
2342 DeprecationWarning
2343)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002344
2345
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002346class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002347 """
2348 A PKCS #12 archive.
2349 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002350
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002351 def __init__(self):
2352 self._pkey = None
2353 self._cert = None
2354 self._cacerts = None
2355 self._friendlyname = None
2356
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002357 def get_certificate(self):
2358 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002359 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002360
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002361 :return: The certificate, or :py:const:`None` if there is none.
2362 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002363 """
2364 return self._cert
2365
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002366 def set_certificate(self, cert):
2367 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002368 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002369
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002370 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002371 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002372
Dan Sully44e767a2016-06-04 18:05:27 -07002373 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002374 """
2375 if not isinstance(cert, X509):
2376 raise TypeError("cert must be an X509 instance")
2377 self._cert = cert
2378
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002379 def get_privatekey(self):
2380 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002381 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002382
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002383 :return: The private key, or :py:const:`None` if there is none.
2384 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002385 """
2386 return self._pkey
2387
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002388 def set_privatekey(self, pkey):
2389 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002390 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002391
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002392 :param pkey: The new private key, or :py:const:`None` to unset it.
2393 :type pkey: :py:class:`PKey` or :py:const:`None`
2394
Dan Sully44e767a2016-06-04 18:05:27 -07002395 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002396 """
2397 if not isinstance(pkey, PKey):
2398 raise TypeError("pkey must be a PKey instance")
2399 self._pkey = pkey
2400
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002401 def get_ca_certificates(self):
2402 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002403 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002404
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002405 :return: A tuple with the CA certificates in the chain, or
2406 :py:const:`None` if there are none.
2407 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002408 """
2409 if self._cacerts is not None:
2410 return tuple(self._cacerts)
2411
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002412 def set_ca_certificates(self, cacerts):
2413 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002414 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002415
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002416 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2417 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002418 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002419
Dan Sully44e767a2016-06-04 18:05:27 -07002420 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002421 """
2422 if cacerts is None:
2423 self._cacerts = None
2424 else:
2425 cacerts = list(cacerts)
2426 for cert in cacerts:
2427 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002428 raise TypeError(
2429 "iterable must only contain X509 instances"
2430 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002431 self._cacerts = cacerts
2432
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002433 def set_friendlyname(self, name):
2434 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002435 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002436
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002437 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002438 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002439
Dan Sully44e767a2016-06-04 18:05:27 -07002440 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002441 """
2442 if name is None:
2443 self._friendlyname = None
2444 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002445 raise TypeError(
2446 "name must be a byte string or None (not %r)" % (name,)
2447 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002448 self._friendlyname = name
2449
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002450 def get_friendlyname(self):
2451 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002452 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002453
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002454 :returns: The friendly name, or :py:const:`None` if there is none.
2455 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002456 """
2457 return self._friendlyname
2458
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002459 def export(self, passphrase=None, iter=2048, maciter=1):
2460 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002461 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002462
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002463 For more information, see the :c:func:`PKCS12_create` man page.
2464
2465 :param passphrase: The passphrase used to encrypt the structure. Unlike
2466 some other passphrase arguments, this *must* be a string, not a
2467 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002468 :type passphrase: :py:data:`bytes`
2469
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002470 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002471 :type iter: :py:data:`int`
2472
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002473 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002474 :type maciter: :py:data:`int`
2475
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002476 :return: The string representation of the PKCS #12 structure.
2477 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002478 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002479 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002480
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002481 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002482 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002483 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002484 cacerts = _lib.sk_X509_new_null()
2485 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002486 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002487 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002488
2489 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002490 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002491
2492 friendlyname = self._friendlyname
2493 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002494 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002495
2496 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002497 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002498 else:
2499 pkey = self._pkey._pkey
2500
2501 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002502 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002503 else:
2504 cert = self._cert._x509
2505
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002506 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002507 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002508 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2509 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002510 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002511 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002512 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002513 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002514
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002515 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002516 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002517 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002518
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002519
Alex Gaynor10d30832017-06-29 15:31:39 -07002520PKCS12Type = deprecated(
2521 PKCS12, __name__,
2522 "PKCS12Type has been deprecated, use PKCS12 instead",
2523 DeprecationWarning
2524)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002525
2526
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002527class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002528 """
2529 A Netscape SPKI object.
2530 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002531
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002532 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002533 spki = _lib.NETSCAPE_SPKI_new()
2534 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002535
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002536 def sign(self, pkey, digest):
2537 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002538 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002539
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002540 :param pkey: The private key to sign with.
2541 :type pkey: :py:class:`PKey`
2542
2543 :param digest: The message digest to use.
2544 :type digest: :py:class:`bytes`
2545
Dan Sully44e767a2016-06-04 18:05:27 -07002546 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002547 """
2548 if pkey._only_public:
2549 raise ValueError("Key has only public part")
2550
2551 if not pkey._initialized:
2552 raise ValueError("Key is uninitialized")
2553
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002554 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002555 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002556 raise ValueError("No such digest method")
2557
Alex Gaynor5945ea82015-09-05 14:59:06 -04002558 sign_result = _lib.NETSCAPE_SPKI_sign(
2559 self._spki, pkey._pkey, digest_obj
2560 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002561 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002562
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002563 def verify(self, key):
2564 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002565 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002566
Hynek Schlawack01c31672016-12-11 15:14:09 +01002567 :param PKey key: The public key that signature is supposedly from.
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002568
Hynek Schlawack01c31672016-12-11 15:14:09 +01002569 :return: ``True`` if the signature is correct.
2570 :rtype: bool
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002571
Hynek Schlawack01c31672016-12-11 15:14:09 +01002572 :raises OpenSSL.crypto.Error: If the signature is invalid, or there was
2573 a problem verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002574 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002575 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002576 if answer <= 0:
2577 _raise_current_error()
2578 return True
2579
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002580 def b64_encode(self):
2581 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002582 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002583
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002584 :return: The base64 encoded string.
2585 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002586 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002587 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2588 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002589 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002590 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002591
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002592 def get_pubkey(self):
2593 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002594 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002595
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002596 :return: The public key.
2597 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002598 """
2599 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002600 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002601 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002602 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002603 pkey._only_public = True
2604 return pkey
2605
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002606 def set_pubkey(self, pkey):
2607 """
2608 Set the public key of the certificate
2609
2610 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002611 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002612 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002613 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002614 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002615
2616
Alex Gaynor10d30832017-06-29 15:31:39 -07002617NetscapeSPKIType = deprecated(
2618 NetscapeSPKI, __name__,
2619 "NetscapeSPKIType has been deprecated, use NetscapeSPKI instead",
2620 DeprecationWarning
2621)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002622
2623
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002624class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002625 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002626 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002627 raise ValueError(
2628 "only FILETYPE_PEM key format supports encryption"
2629 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002630 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002631 self._more_args = more_args
2632 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002633 self._problems = []
2634
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002635 @property
2636 def callback(self):
2637 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002638 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002639 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002640 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002641 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002642 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002643 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002644 raise TypeError(
2645 "Last argument must be a byte string or a callable."
2646 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002647
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002648 @property
2649 def callback_args(self):
2650 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002651 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002652 elif isinstance(self._passphrase, bytes):
2653 return self._passphrase
2654 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002655 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002656 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002657 raise TypeError(
2658 "Last argument must be a byte string or a callable."
2659 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002660
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002661 def raise_if_problem(self, exceptionType=Error):
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002662 if self._problems:
Greg Bowser36eb2de2017-01-24 11:38:55 -05002663
2664 # Flush the OpenSSL error queue
2665 try:
2666 _exception_from_error_queue(exceptionType)
2667 except exceptionType:
2668 pass
2669
2670 raise self._problems.pop(0)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002671
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002672 def _read_passphrase(self, buf, size, rwflag, userdata):
2673 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002674 if self._more_args:
2675 result = self._passphrase(size, rwflag, userdata)
2676 else:
2677 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002678 if not isinstance(result, bytes):
2679 raise ValueError("String expected")
2680 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002681 if self._truncate:
2682 result = result[:size]
2683 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002684 raise ValueError(
2685 "passphrase returned by callback is too long"
2686 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002687 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002688 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002689 return len(result)
2690 except Exception as e:
2691 self._problems.append(e)
2692 return 0
2693
2694
Cory Benfield6492f7c2015-10-27 16:57:58 +09002695def load_publickey(type, buffer):
2696 """
Cory Benfield11c10192015-10-27 17:23:03 +09002697 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002698
Cory Benfield9c590b92015-10-28 14:55:05 +09002699 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002700 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002701 :param buffer: The buffer the key is stored in.
2702 :type buffer: A Python string object, either unicode or bytestring.
2703 :return: The PKey object.
2704 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002705 """
2706 if isinstance(buffer, _text_type):
2707 buffer = buffer.encode("ascii")
2708
2709 bio = _new_mem_buf(buffer)
2710
2711 if type == FILETYPE_PEM:
2712 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2713 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2714 elif type == FILETYPE_ASN1:
2715 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2716 else:
2717 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2718
2719 if evp_pkey == _ffi.NULL:
2720 _raise_current_error()
2721
2722 pkey = PKey.__new__(PKey)
2723 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002724 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002725 return pkey
2726
2727
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002728def load_privatekey(type, buffer, passphrase=None):
2729 """
2730 Load a private key from a buffer
2731
2732 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2733 :param buffer: The buffer the key is stored in
2734 :param passphrase: (optional) if encrypted PEM format, this can be
2735 either the passphrase to use, or a callback for
2736 providing the passphrase.
2737
2738 :return: The PKey object
2739 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002740 if isinstance(buffer, _text_type):
2741 buffer = buffer.encode("ascii")
2742
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002743 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002744
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002745 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002746 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002747 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2748 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002749 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002750 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002751 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002752 else:
2753 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2754
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002755 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002756 _raise_current_error()
2757
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002758 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002759 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002760 return pkey
2761
2762
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002763def dump_certificate_request(type, req):
2764 """
2765 Dump a certificate request to a buffer
2766
2767 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2768 :param req: The certificate request to dump
2769 :return: The buffer with the dumped certificate request in
2770 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002771 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002772
2773 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002774 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002775 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002776 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002777 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002778 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002779 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002780 raise ValueError(
2781 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2782 "FILETYPE_TEXT"
2783 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002784
Alex Gaynor09a386e2016-07-03 09:32:44 -04002785 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002786
2787 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002788
2789
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002790def load_certificate_request(type, buffer):
2791 """
2792 Load a certificate request from a buffer
2793
2794 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2795 :param buffer: The buffer the certificate request is stored in
2796 :return: The X509Req object
2797 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002798 if isinstance(buffer, _text_type):
2799 buffer = buffer.encode("ascii")
2800
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002801 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002802
2803 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002804 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002805 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002806 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002807 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002808 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002809
Alex Gaynoradd5b072016-06-04 21:04:00 -07002810 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002811
2812 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002813 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002814 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002815
2816
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002817def sign(pkey, data, digest):
2818 """
2819 Sign data with a digest
2820
2821 :param pkey: Pkey to sign with
2822 :param data: data to be signed
2823 :param digest: message digest to use
2824 :return: signature
2825 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002826 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002827
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002828 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002829 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002830 raise ValueError("No such digest method")
2831
Alex Gaynor67903a62016-06-02 10:37:13 -07002832 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002833 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002834
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002835 _lib.EVP_SignInit(md_ctx, digest_obj)
2836 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002837
Paul Kehrer59d26252017-07-20 10:45:54 +02002838 length = _lib.EVP_PKEY_size(pkey._pkey)
2839 _openssl_assert(length > 0)
2840 signature_buffer = _ffi.new("unsigned char[]", length)
2841 signature_length = _ffi.new("unsigned int *")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002842 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002843 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002844 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002845
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002846 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002847
2848
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002849def verify(cert, signature, data, digest):
2850 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002851 Verify a signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002852
2853 :param cert: signing certificate (X509 object)
2854 :param signature: signature returned by sign function
2855 :param data: data to be verified
2856 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002857 :return: ``None`` if the signature is correct, raise exception otherwise.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002858 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002859 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002860
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002861 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002862 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002863 raise ValueError("No such digest method")
2864
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002865 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002866 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002867 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002868
Alex Gaynor67903a62016-06-02 10:37:13 -07002869 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002870 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002871
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002872 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2873 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002874 verify_result = _lib.EVP_VerifyFinal(
2875 md_ctx, signature, len(signature), pkey
2876 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002877
2878 if verify_result != 1:
2879 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002880
2881
Dominic Chenf05b2122015-10-13 16:32:35 +00002882def dump_crl(type, crl):
2883 """
2884 Dump a certificate revocation list to a buffer.
2885
2886 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2887 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002888 :param CRL crl: The CRL to dump.
2889
Dominic Chenf05b2122015-10-13 16:32:35 +00002890 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002891 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002892 """
2893 bio = _new_mem_buf()
2894
2895 if type == FILETYPE_PEM:
2896 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2897 elif type == FILETYPE_ASN1:
2898 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2899 elif type == FILETYPE_TEXT:
2900 ret = _lib.X509_CRL_print(bio, crl._crl)
2901 else:
2902 raise ValueError(
2903 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2904 "FILETYPE_TEXT")
2905
2906 assert ret == 1
2907 return _bio_to_string(bio)
2908
2909
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002910def load_crl(type, buffer):
2911 """
2912 Load a certificate revocation list from a buffer
2913
2914 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2915 :param buffer: The buffer the CRL is stored in
2916
2917 :return: The PKey object
2918 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002919 if isinstance(buffer, _text_type):
2920 buffer = buffer.encode("ascii")
2921
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002922 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002923
2924 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002925 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002926 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002927 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002928 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002929 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2930
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002931 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002932 _raise_current_error()
2933
2934 result = CRL.__new__(CRL)
Jeremy Cline9e15eca2017-09-07 20:11:08 -04002935 result._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002936 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002937
2938
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002939def load_pkcs7_data(type, buffer):
2940 """
2941 Load pkcs7 data from a buffer
2942
2943 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2944 :param buffer: The buffer with the pkcs7 data.
2945 :return: The PKCS7 object
2946 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002947 if isinstance(buffer, _text_type):
2948 buffer = buffer.encode("ascii")
2949
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002950 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002951
2952 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002953 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002954 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002955 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002956 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002957 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2958
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002959 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002960 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002961
2962 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002963 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002964 return pypkcs7
2965
2966
Stephen Holsapple38482622014-04-05 20:29:34 -07002967def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002968 """
2969 Load a PKCS12 object from a buffer
2970
2971 :param buffer: The buffer the certificate is stored in
2972 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2973 :returns: The PKCS12 object
2974 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002975 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002976
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002977 if isinstance(buffer, _text_type):
2978 buffer = buffer.encode("ascii")
2979
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002980 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002981
Stephen Holsapple38482622014-04-05 20:29:34 -07002982 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2983 # password based encryption no password and a zero length password are two
2984 # different things, but OpenSSL implementation will try both to figure out
2985 # which one works.
2986 if not passphrase:
2987 passphrase = _ffi.NULL
2988
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002989 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2990 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002991 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002992 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002993
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002994 pkey = _ffi.new("EVP_PKEY**")
2995 cert = _ffi.new("X509**")
2996 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002997
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002998 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002999 if not parse_result:
3000 _raise_current_error()
3001
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003002 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08003003
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003004 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
3005 # queue for no particular reason. This error isn't interesting to anyone
3006 # outside this function. It's not even interesting to us. Get rid of it.
3007 try:
3008 _raise_current_error()
3009 except Error:
3010 pass
3011
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003012 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003013 pykey = None
3014 else:
3015 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003016 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003017
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003018 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003019 pycert = None
3020 friendlyname = None
3021 else:
3022 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003023 pycert._x509 = _ffi.gc(cert[0], _lib.X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003024
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003025 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04003026 friendlyname_buffer = _lib.X509_alias_get0(
3027 cert[0], friendlyname_length
3028 )
3029 friendlyname = _ffi.buffer(
3030 friendlyname_buffer, friendlyname_length[0]
3031 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003032 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003033 friendlyname = None
3034
3035 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003036 for i in range(_lib.sk_X509_num(cacerts)):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003037 pycacert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003038 pycacert._x509 = _lib.sk_X509_value(cacerts, i)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003039 pycacerts.append(pycacert)
3040 if not pycacerts:
3041 pycacerts = None
3042
3043 pkcs12 = PKCS12.__new__(PKCS12)
3044 pkcs12._pkey = pykey
3045 pkcs12._cert = pycert
3046 pkcs12._cacerts = pycacerts
3047 pkcs12._friendlyname = friendlyname
3048 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05003049
3050
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05003051# There are no direct unit tests for this initialization. It is tested
3052# indirectly since it is necessary for functions like dump_privatekey when
3053# using encryption.
3054#
3055# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
3056# and some other similar tests may fail without this (though they may not if
3057# the Python runtime has already done some initialization of the underlying
3058# OpenSSL library (and is linked against the same one that cryptography is
3059# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05003060_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05003061
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05003062# This is similar but exercised mainly by exception_from_error_queue. It calls
3063# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
3064_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003065
3066
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003067# Set the default string mask to match OpenSSL upstream (since 2005) and
3068# RFC5280 recommendations.
3069_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')