blob: ef2dcdf3fe6b5d975dbf8ce0c066e6e5bd1b92da [file] [log] [blame]
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001import datetime
Paul Kehrer8d887e12015-10-24 09:09:55 -05002
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003from base64 import b16encode
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05004from functools import partial
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05005from operator import __eq__, __ne__, __lt__, __le__, __gt__, __ge__
Jean-Paul Calderone60432792015-04-13 12:26:07 -04006from warnings import warn as _warn
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05007
8from six import (
9 integer_types as _integer_types,
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -040010 text_type as _text_type,
11 PY3 as _PY3)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080012
Alex Gaynor9939ba12017-06-25 16:28:24 -040013from cryptography import x509
Paul Kehrer72d968b2016-07-29 15:31:04 +080014from cryptography.hazmat.primitives.asymmetric import dsa, rsa
Alex Gaynor10d30832017-06-29 15:31:39 -070015from cryptography.utils import deprecated
Paul Kehrer72d968b2016-07-29 15:31:04 +080016
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050017from OpenSSL._util import (
18 ffi as _ffi,
19 lib as _lib,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050020 exception_from_error_queue as _exception_from_error_queue,
21 byte_string as _byte_string,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040022 native as _native,
23 UNSPECIFIED as _UNSPECIFIED,
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -040024 text_to_bytes_and_warn as _text_to_bytes_and_warn,
Alex Gaynor67903a62016-06-02 10:37:13 -070025 make_assert as _make_assert,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040026)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080027
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050028FILETYPE_PEM = _lib.SSL_FILETYPE_PEM
29FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080030
31# TODO This was an API mistake. OpenSSL has no such constant.
32FILETYPE_TEXT = 2 ** 16 - 1
33
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050034TYPE_RSA = _lib.EVP_PKEY_RSA
35TYPE_DSA = _lib.EVP_PKEY_DSA
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -080036
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080037
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050038class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050039 """
40 An error occurred in an `OpenSSL.crypto` API.
41 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050042
43
44_raise_current_error = partial(_exception_from_error_queue, Error)
Alex Gaynor67903a62016-06-02 10:37:13 -070045_openssl_assert = _make_assert(Error)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050046
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070047
Paul Kehrereb633842016-10-06 11:22:01 +020048def _get_backend():
49 """
50 Importing the backend from cryptography has the side effect of activating
51 the osrandom engine. This mutates the global state of OpenSSL in the
52 process and causes issues for various programs that use subinterpreters or
53 embed Python. By putting the import in this function we can avoid
54 triggering this side effect unless _get_backend is called.
55 """
56 from cryptography.hazmat.backends.openssl.backend import backend
57 return backend
58
59
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050060def _untested_error(where):
61 """
62 An OpenSSL API failed somehow. Additionally, the failure which was
63 encountered isn't one that's exercised by the test suite so future behavior
64 of pyOpenSSL is now somewhat less predictable.
65 """
66 raise RuntimeError("Unknown %s failure" % (where,))
67
68
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050069def _new_mem_buf(buffer=None):
70 """
71 Allocate a new OpenSSL memory BIO.
72
73 Arrange for the garbage collector to clean it up automatically.
74
75 :param buffer: None or some bytes to use to put into the BIO so that they
76 can be read out.
77 """
78 if buffer is None:
79 bio = _lib.BIO_new(_lib.BIO_s_mem())
80 free = _lib.BIO_free
81 else:
82 data = _ffi.new("char[]", buffer)
83 bio = _lib.BIO_new_mem_buf(data, len(buffer))
Alex Gaynor5945ea82015-09-05 14:59:06 -040084
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050085 # Keep the memory alive as long as the bio is alive!
86 def free(bio, ref=data):
87 return _lib.BIO_free(bio)
88
Alex Gaynorfb8a2a12016-06-04 18:26:26 -070089 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050090
91 bio = _ffi.gc(bio, free)
92 return bio
93
94
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080095def _bio_to_string(bio):
96 """
97 Copy the contents of an OpenSSL BIO object into a Python byte string.
98 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050099 result_buffer = _ffi.new('char**')
100 buffer_length = _lib.BIO_get_mem_data(bio, result_buffer)
101 return _ffi.buffer(result_buffer[0], buffer_length)[:]
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800102
103
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800104def _set_asn1_time(boundary, when):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500105 """
106 The the time value of an ASN1 time object.
107
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900108 @param boundary: An ASN1_TIME pointer (or an object safely
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500109 castable to that type) which will have its value set.
110 @param when: A string representation of the desired time value.
111
112 @raise TypeError: If C{when} is not a L{bytes} string.
113 @raise ValueError: If C{when} does not represent a time in the required
114 format.
115 @raise RuntimeError: If the time value cannot be set for some other
116 (unspecified) reason.
117 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800118 if not isinstance(when, bytes):
119 raise TypeError("when must be a byte string")
120
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900121 set_result = _lib.ASN1_TIME_set_string(boundary, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800122 if set_result == 0:
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900123 raise ValueError("Invalid string")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800124
Alex Gaynor510293e2016-06-02 12:07:59 -0700125
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800126def _get_asn1_time(timestamp):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500127 """
128 Retrieve the time value of an ASN1 time object.
129
130 @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to
131 that type) from which the time value will be retrieved.
132
133 @return: The time value from C{timestamp} as a L{bytes} string in a certain
134 format. Or C{None} if the object contains no time value.
135 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500136 string_timestamp = _ffi.cast('ASN1_STRING*', timestamp)
137 if _lib.ASN1_STRING_length(string_timestamp) == 0:
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800138 return None
Alex Gaynor5945ea82015-09-05 14:59:06 -0400139 elif (
140 _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME
141 ):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500142 return _ffi.string(_lib.ASN1_STRING_data(string_timestamp))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800143 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500144 generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**")
145 _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp)
146 if generalized_timestamp[0] == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500147 # This may happen:
148 # - if timestamp was not an ASN1_TIME
149 # - if allocating memory for the ASN1_GENERALIZEDTIME failed
150 # - if a copy of the time data from timestamp cannot be made for
151 # the newly allocated ASN1_GENERALIZEDTIME
152 #
153 # These are difficult to test. cffi enforces the ASN1_TIME type.
154 # Memory allocation failures are a pain to trigger
155 # deterministically.
156 _untested_error("ASN1_TIME_to_generalizedtime")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800157 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500158 string_timestamp = _ffi.cast(
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800159 "ASN1_STRING*", generalized_timestamp[0])
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500160 string_data = _lib.ASN1_STRING_data(string_timestamp)
161 string_result = _ffi.string(string_data)
162 _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0])
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800163 return string_result
164
165
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800166class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200167 """
168 A class representing an DSA or RSA public key or key pair.
169 """
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800170 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800171 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800172
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800173 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500174 pkey = _lib.EVP_PKEY_new()
175 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800176 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800177
Paul Kehrer72d968b2016-07-29 15:31:04 +0800178 def to_cryptography_key(self):
179 """
180 Export as a ``cryptography`` key.
181
182 :rtype: One of ``cryptography``'s `key interfaces`_.
183
184 .. _key interfaces: https://cryptography.io/en/latest/hazmat/\
185 primitives/asymmetric/rsa/#key-interfaces
186
187 .. versionadded:: 16.1.0
188 """
Paul Kehrereb633842016-10-06 11:22:01 +0200189 backend = _get_backend()
Paul Kehrer72d968b2016-07-29 15:31:04 +0800190 if self._only_public:
191 return backend._evp_pkey_to_public_key(self._pkey)
192 else:
193 return backend._evp_pkey_to_private_key(self._pkey)
194
195 @classmethod
196 def from_cryptography_key(cls, crypto_key):
197 """
198 Construct based on a ``cryptography`` *crypto_key*.
199
200 :param crypto_key: A ``cryptography`` key.
201 :type crypto_key: One of ``cryptography``'s `key interfaces`_.
202
203 :rtype: PKey
204
205 .. versionadded:: 16.1.0
206 """
207 pkey = cls()
208 if not isinstance(crypto_key, (rsa.RSAPublicKey, rsa.RSAPrivateKey,
209 dsa.DSAPublicKey, dsa.DSAPrivateKey)):
210 raise TypeError("Unsupported key type")
211
212 pkey._pkey = crypto_key._evp_pkey
213 if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)):
214 pkey._only_public = True
215 pkey._initialized = True
216 return pkey
217
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800218 def generate_key(self, type, bits):
219 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700220 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800221
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200222 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800223
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200224 :param type: The key type.
225 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
226 :param bits: The number of bits.
227 :type bits: :py:data:`int` ``>= 0``
228 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
229 of the appropriate type.
230 :raises ValueError: If the number of bits isn't an integer of
231 the appropriate size.
Dan Sully44e767a2016-06-04 18:05:27 -0700232 :return: ``None``
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800233 """
234 if not isinstance(type, int):
235 raise TypeError("type must be an integer")
236
237 if not isinstance(bits, int):
238 raise TypeError("bits must be an integer")
239
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800240 # TODO Check error return
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500241 exponent = _lib.BN_new()
242 exponent = _ffi.gc(exponent, _lib.BN_free)
243 _lib.BN_set_word(exponent, _lib.RSA_F4)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800244
245 if type == TYPE_RSA:
246 if bits <= 0:
247 raise ValueError("Invalid number of bits")
248
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500249 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800250
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500251 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400252 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800253
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500254 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400255 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800256
257 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400258 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700259 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400260
261 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400262 res = _lib.DSA_generate_parameters_ex(
263 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
264 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700265 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400266
267 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
268 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800269 else:
270 raise Error("No such key type")
271
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800272 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800273
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800274 def check(self):
275 """
276 Check the consistency of an RSA private key.
277
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200278 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
279
Hynek Schlawack01c31672016-12-11 15:14:09 +0100280 :return: ``True`` if key is consistent.
281
282 :raise OpenSSL.crypto.Error: if the key is inconsistent.
283
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800284 :raise TypeError: if the key is of a type which cannot be checked.
285 Only RSA keys can currently be checked.
286 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800287 if self._only_public:
288 raise TypeError("public key only")
289
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100290 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800291 raise TypeError("key type unsupported")
292
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500293 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
294 rsa = _ffi.gc(rsa, _lib.RSA_free)
295 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800296 if result:
297 return True
298 _raise_current_error()
299
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800300 def type(self):
301 """
302 Returns the type of the key
303
304 :return: The type of the key.
305 """
Alex Gaynor0d2aec52017-05-31 04:26:27 -0400306 return _lib.EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800307
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800308 def bits(self):
309 """
310 Returns the number of bits of the key
311
312 :return: The number of bits of the key.
313 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500314 return _lib.EVP_PKEY_bits(self._pkey)
Alex Chanc6077062016-11-18 13:53:39 +0000315
316
Alex Gaynor10d30832017-06-29 15:31:39 -0700317PKeyType = deprecated(
318 PKey, __name__,
319 "PKeyType has been deprecated, use PKey instead",
320 DeprecationWarning
321)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800322
323
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400324class _EllipticCurve(object):
325 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400326 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400327
328 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
329 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
330 instances each of which represents one curve supported by the system.
331 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400332 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400333 _curves = None
334
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400335 if _PY3:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400336 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400337 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400338 """
339 Implement cooperation with the right-hand side argument of ``!=``.
340
341 Python 3 seems to have dropped this cooperation in this very narrow
342 circumstance.
343 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400344 if isinstance(other, _EllipticCurve):
345 return super(_EllipticCurve, self).__ne__(other)
346 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400347
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400348 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400349 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400350 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400351 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400352
353 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400354
355 :return: A :py:type:`set` of ``cls`` instances giving the names of the
356 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400357 """
Alex Chan84902a22017-04-20 11:50:47 +0100358 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
359 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
360 # The return value on this call should be num_curves again. We
361 # could check it to make sure but if it *isn't* then.. what could
362 # we do? Abort the whole process, I suppose...? -exarkun
363 lib.EC_get_builtin_curves(builtin_curves, num_curves)
364 return set(
365 cls.from_nid(lib, c.nid)
366 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400367
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400368 @classmethod
369 def _get_elliptic_curves(cls, lib):
370 """
371 Get, cache, and return the curves supported by OpenSSL.
372
373 :param lib: The OpenSSL library binding object.
374
375 :return: A :py:type:`set` of ``cls`` instances giving the names of the
376 elliptic curves the underlying library supports.
377 """
378 if cls._curves is None:
379 cls._curves = cls._load_elliptic_curves(lib)
380 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400381
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400382 @classmethod
383 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400384 """
385 Instantiate a new :py:class:`_EllipticCurve` associated with the given
386 OpenSSL NID.
387
388 :param lib: The OpenSSL library binding object.
389
390 :param nid: The OpenSSL NID the resulting curve object will represent.
391 This must be a curve NID (and not, for example, a hash NID) or
392 subsequent operations will fail in unpredictable ways.
393 :type nid: :py:class:`int`
394
395 :return: The curve object.
396 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400397 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
398
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400399 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400400 """
401 :param _lib: The :py:mod:`cryptography` binding instance used to
402 interface with OpenSSL.
403
404 :param _nid: The OpenSSL NID identifying the curve this object
405 represents.
406 :type _nid: :py:class:`int`
407
408 :param name: The OpenSSL short name identifying the curve this object
409 represents.
410 :type name: :py:class:`unicode`
411 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400412 self._lib = lib
413 self._nid = nid
414 self.name = name
415
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400416 def __repr__(self):
417 return "<Curve %r>" % (self.name,)
418
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400419 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400420 """
421 Create a new OpenSSL EC_KEY structure initialized to use this curve.
422
423 The structure is automatically garbage collected when the Python object
424 is garbage collected.
425 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400426 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
427 return _ffi.gc(key, _lib.EC_KEY_free)
428
429
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400430def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400431 """
432 Return a set of objects representing the elliptic curves supported in the
433 OpenSSL build in use.
434
435 The curve objects have a :py:class:`unicode` ``name`` attribute by which
436 they identify themselves.
437
438 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400439 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
440 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400441 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400442 return _EllipticCurve._get_elliptic_curves(_lib)
443
444
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400445def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400446 """
447 Return a single curve object selected by name.
448
449 See :py:func:`get_elliptic_curves` for information about curve objects.
450
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400451 :param name: The OpenSSL short name identifying the curve object to
452 retrieve.
453 :type name: :py:class:`unicode`
454
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400455 If the named curve is not supported then :py:class:`ValueError` is raised.
456 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400457 for curve in get_elliptic_curves():
458 if curve.name == name:
459 return curve
460 raise ValueError("unknown curve name", name)
461
462
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800463class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200464 """
465 An X.509 Distinguished Name.
466
467 :ivar countryName: The country of the entity.
468 :ivar C: Alias for :py:attr:`countryName`.
469
470 :ivar stateOrProvinceName: The state or province of the entity.
471 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
472
473 :ivar localityName: The locality of the entity.
474 :ivar L: Alias for :py:attr:`localityName`.
475
476 :ivar organizationName: The organization name of the entity.
477 :ivar O: Alias for :py:attr:`organizationName`.
478
479 :ivar organizationalUnitName: The organizational unit of the entity.
480 :ivar OU: Alias for :py:attr:`organizationalUnitName`
481
482 :ivar commonName: The common name of the entity.
483 :ivar CN: Alias for :py:attr:`commonName`.
484
485 :ivar emailAddress: The e-mail address of the entity.
486 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400487
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800488 def __init__(self, name):
489 """
490 Create a new X509Name, copying the given X509Name instance.
491
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200492 :param name: The name to copy.
493 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800494 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500495 name = _lib.X509_NAME_dup(name._name)
496 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800497
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800498 def __setattr__(self, name, value):
499 if name.startswith('_'):
500 return super(X509Name, self).__setattr__(name, value)
501
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800502 # Note: we really do not want str subclasses here, so we do not use
503 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800504 if type(name) is not str:
505 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400506 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800507
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500508 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500509 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800510 try:
511 _raise_current_error()
512 except Error:
513 pass
514 raise AttributeError("No such attribute")
515
516 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500517 for i in range(_lib.X509_NAME_entry_count(self._name)):
518 ent = _lib.X509_NAME_get_entry(self._name, i)
519 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
520 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800521 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500522 ent = _lib.X509_NAME_delete_entry(self._name, i)
523 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800524 break
525
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500526 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800527 value = value.encode('utf-8')
528
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500529 add_result = _lib.X509_NAME_add_entry_by_NID(
530 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800531 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500532 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800533
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800534 def __getattr__(self, name):
535 """
536 Find attribute. An X509Name object has the following attributes:
537 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400538 organization (alias O), organizationalUnit (alias OU), commonName
539 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800540 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500541 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500542 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800543 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
544 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
545 # push something onto the error queue. If we don't clean that up
546 # now, someone else will bump into it later and be quite confused.
547 # See lp#314814.
548 try:
549 _raise_current_error()
550 except Error:
551 pass
552 return super(X509Name, self).__getattr__(name)
553
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500554 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800555 if entry_index == -1:
556 return None
557
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500558 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
559 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800560
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500561 result_buffer = _ffi.new("unsigned char**")
562 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400563 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800564
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700565 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400566 result = _ffi.buffer(
567 result_buffer[0], data_length
568 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700569 finally:
570 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500571 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800572 return result
573
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500574 def _cmp(op):
575 def f(self, other):
576 if not isinstance(other, X509Name):
577 return NotImplemented
578 result = _lib.X509_NAME_cmp(self._name, other._name)
579 return op(result, 0)
580 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800581
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500582 __eq__ = _cmp(__eq__)
583 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800584
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500585 __lt__ = _cmp(__lt__)
586 __le__ = _cmp(__le__)
587
588 __gt__ = _cmp(__gt__)
589 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800590
591 def __repr__(self):
592 """
593 String representation of an X509Name
594 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400595 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500596 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800597 self._name, result_buffer, len(result_buffer))
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700598 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800599
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500600 return "<X509Name object '%s'>" % (
601 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800602
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800603 def hash(self):
604 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200605 Return an integer representation of the first four bytes of the
606 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800607
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200608 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
609
610 :return: The (integer) hash of this name.
611 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800612 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500613 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800614
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800615 def der(self):
616 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200617 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800618
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200619 :return: The DER encoded form of this name.
620 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800621 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500622 result_buffer = _ffi.new('unsigned char**')
623 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400624 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800625
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500626 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
627 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800628 return string_result
629
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800630 def get_components(self):
631 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200632 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800633
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200634 :return: The components of this name.
635 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800636 """
637 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500638 for i in range(_lib.X509_NAME_entry_count(self._name)):
639 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800640
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500641 fname = _lib.X509_NAME_ENTRY_get_object(ent)
642 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800643
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500644 nid = _lib.OBJ_obj2nid(fname)
645 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800646
647 result.append((
Alex Gaynora738ed52015-09-05 11:17:10 -0400648 _ffi.string(name),
649 _ffi.string(
650 _lib.ASN1_STRING_data(fval),
651 _lib.ASN1_STRING_length(fval))))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800652
653 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200654
655
Alex Gaynor10d30832017-06-29 15:31:39 -0700656X509NameType = deprecated(
657 X509Name, __name__,
658 "X509NameType has been deprecated, use X509Name instead",
659 DeprecationWarning
660)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800661
662
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800663class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200664 """
665 An X.509 v3 certificate extension.
666 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400667
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800668 def __init__(self, type_name, critical, value, subject=None, issuer=None):
669 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200670 Initializes an X509 extension.
671
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100672 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400673 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800674
Alex Gaynor5945ea82015-09-05 14:59:06 -0400675 :param bool critical: A flag indicating whether this is a critical
676 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800677
678 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200679 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800680
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200681 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800682 :type subject: :py:class:`X509`
683
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200684 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800685 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100686
Alex Chan54005ce2017-03-21 08:08:17 +0000687 .. _extension: https://www.openssl.org/docs/manmaster/man5/
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100688 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800689 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500690 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800691
Alex Gaynor5945ea82015-09-05 14:59:06 -0400692 # A context is necessary for any extension which uses the r2i
693 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
694 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500695 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800696
697 # We have no configuration database - but perhaps we should (some
698 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500699 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800700
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800701 # Initialize the subject and issuer, if appropriate. ctx is a local,
702 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400703 # any references, so no need to mess with reference counts or
704 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800705 if issuer is not None:
706 if not isinstance(issuer, X509):
707 raise TypeError("issuer must be an X509 instance")
708 ctx.issuer_cert = issuer._x509
709 if subject is not None:
710 if not isinstance(subject, X509):
711 raise TypeError("subject must be an X509 instance")
712 ctx.subject_cert = subject._x509
713
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800714 if critical:
715 # There are other OpenSSL APIs which would let us pass in critical
716 # separately, but they're harder to use, and since value is already
717 # a pile of crappy junk smuggling a ton of utterly important
718 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400719 # with strings? (However, X509V3_EXT_i2d in particular seems like
720 # it would be a better API to invoke. I do not know where to get
721 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500722 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800723
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500724 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
725 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800726 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500727 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800728
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400729 @property
730 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400731 return _lib.OBJ_obj2nid(
732 _lib.X509_EXTENSION_get_object(self._extension)
733 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400734
735 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500736 _lib.GEN_EMAIL: "email",
737 _lib.GEN_DNS: "DNS",
738 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400739 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400740
741 def _subjectAltNameString(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500742 method = _lib.X509V3_EXT_get(self._extension)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700743 _openssl_assert(method != _ffi.NULL)
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400744 ext_data = _lib.X509_EXTENSION_get_data(self._extension)
745 payload = ext_data.data
746 length = ext_data.length
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400747
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500748 payloadptr = _ffi.new("unsigned char**")
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400749 payloadptr[0] = payload
750
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500751 if method.it != _ffi.NULL:
752 ptr = _lib.ASN1_ITEM_ptr(method.it)
753 data = _lib.ASN1_item_d2i(_ffi.NULL, payloadptr, length, ptr)
754 names = _ffi.cast("GENERAL_NAMES*", data)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400755 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500756 names = _ffi.cast(
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400757 "GENERAL_NAMES*",
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500758 method.d2i(_ffi.NULL, payloadptr, length))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400759
Paul Kehrerb7d79502015-05-04 07:43:51 -0500760 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400761 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500762 for i in range(_lib.sk_GENERAL_NAME_num(names)):
763 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400764 try:
765 label = self._prefixes[name.type]
766 except KeyError:
767 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500768 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500769 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400770 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500771 value = _native(
772 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
773 parts.append(label + ":" + value)
774 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400775
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800776 def __str__(self):
777 """
778 :return: a nice text representation of the extension
779 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500780 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400781 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800782
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400783 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500784 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400785 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800786
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500787 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800788
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800789 def get_critical(self):
790 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200791 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800792
793 :return: The critical field.
794 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500795 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800796
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800797 def get_short_name(self):
798 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200799 Returns the short type name of this X.509 extension.
800
801 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800802
803 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200804 :rtype: :py:data:`bytes`
805
806 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800807 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500808 obj = _lib.X509_EXTENSION_get_object(self._extension)
809 nid = _lib.OBJ_obj2nid(obj)
810 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800811
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800812 def get_data(self):
813 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200814 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800815
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200816 :return: The ASN.1 encoded data of this X509 extension.
817 :rtype: :py:data:`bytes`
818
819 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800820 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500821 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
822 string_result = _ffi.cast('ASN1_STRING*', octet_result)
823 char_result = _lib.ASN1_STRING_data(string_result)
824 result_length = _lib.ASN1_STRING_length(string_result)
825 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800826
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200827
Alex Gaynor10d30832017-06-29 15:31:39 -0700828X509ExtensionType = deprecated(
829 X509Extension, __name__,
830 "X509ExtensionType has been deprecated, use X509Extension instead",
831 DeprecationWarning
832)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800833
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800834
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800835class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200836 """
837 An X.509 certificate signing requests.
838 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400839
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800840 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500841 req = _lib.X509_REQ_new()
842 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Alex Gaynor5af32d02016-09-24 01:52:21 -0400843 # Default to version 0.
844 self.set_version(0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800845
Paul Kehrer41c10242017-06-29 18:24:17 -0500846 def to_cryptography(self):
847 """
848 Export as a ``cryptography`` certificate signing request.
849
850 :rtype: ``cryptography.x509.CertificateSigningRequest``
851
852 .. versionadded:: 17.1.0
853 """
854 from cryptography.hazmat.backends.openssl.x509 import (
855 _CertificateSigningRequest
856 )
857 backend = _get_backend()
858 return _CertificateSigningRequest(backend, self._req)
859
860 @classmethod
861 def from_cryptography(cls, crypto_req):
862 """
863 Construct based on a ``cryptography`` *crypto_req*.
864
865 :param crypto_req: A ``cryptography`` X.509 certificate signing request
866 :type crypto_req: ``cryptography.x509.CertificateSigningRequest``
867
868 :rtype: PKey
869
870 .. versionadded:: 17.1.0
871 """
872 if not isinstance(crypto_req, x509.CertificateSigningRequest):
873 raise TypeError("Must be a certificate signing request")
874
875 req = cls()
876 req._req = crypto_req._x509_req
877 return req
878
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800879 def set_pubkey(self, pkey):
880 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200881 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800882
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200883 :param pkey: The public key to use.
884 :type pkey: :py:class:`PKey`
885
Dan Sully44e767a2016-06-04 18:05:27 -0700886 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800887 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500888 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400889 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800890
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800891 def get_pubkey(self):
892 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200893 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800894
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200895 :return: The public key.
896 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800897 """
898 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500899 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700900 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500901 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800902 pkey._only_public = True
903 return pkey
904
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800905 def set_version(self, version):
906 """
907 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
908 request.
909
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200910 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700911 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800912 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500913 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400914 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800915
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800916 def get_version(self):
917 """
918 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
919 request.
920
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200921 :return: The value of the version subfield.
922 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800923 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500924 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800925
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800926 def get_subject(self):
927 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200928 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800929
Cory Benfield881dc8d2015-12-09 08:25:14 +0000930 This creates a new :class:`X509Name` that wraps the underlying subject
931 name field on the certificate signing request. Modifying it will modify
932 the underlying signing request, and will have the effect of modifying
933 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200934
935 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000936 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800937 """
938 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500939 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700940 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800941
942 # The name is owned by the X509Req structure. As long as the X509Name
943 # Python object is alive, keep the X509Req Python object alive.
944 name._owner = self
945
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800946 return name
947
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800948 def add_extensions(self, extensions):
949 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200950 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800951
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200952 :param extensions: The X.509 extensions to add.
953 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700954 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800955 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500956 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700957 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800958
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500959 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800960
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800961 for ext in extensions:
962 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -0800963 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800964
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800965 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500966 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800967
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500968 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400969 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800970
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800971 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800972 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200973 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800974
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200975 :return: The X.509 extensions in this request.
976 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
977
978 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800979 """
980 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500981 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -0500982 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800983 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500984 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800985 exts.append(ext)
986 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800987
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800988 def sign(self, pkey, digest):
989 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -0700990 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800991
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200992 :param pkey: The key pair to sign with.
993 :type pkey: :py:class:`PKey`
994 :param digest: The name of the message digest to use for the signature,
Alex Gaynor239e2d32016-09-11 12:36:35 -0400995 e.g. :py:data:`b"sha256"`.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200996 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -0700997 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800998 """
999 if pkey._only_public:
1000 raise ValueError("Key has only public part")
1001
1002 if not pkey._initialized:
1003 raise ValueError("Key is uninitialized")
1004
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001005 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001006 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001007 raise ValueError("No such digest method")
1008
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001009 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001010 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001011
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001012 def verify(self, pkey):
1013 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001014 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001015
Hynek Schlawack01c31672016-12-11 15:14:09 +01001016 :param PKey key: A public key.
1017
1018 :return: ``True`` if the signature is correct.
1019 :rtype: bool
1020
1021 :raises OpenSSL.crypto.Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001022 problem verifying the signature.
1023 """
1024 if not isinstance(pkey, PKey):
1025 raise TypeError("pkey must be a PKey instance")
1026
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001027 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001028 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001029 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001030
1031 return result
1032
1033
Alex Gaynor10d30832017-06-29 15:31:39 -07001034X509ReqType = deprecated(
1035 X509Req, __name__,
1036 "X509ReqType has been deprecated, use X509Req instead",
1037 DeprecationWarning
1038)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001039
1040
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001041class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001042 """
1043 An X.509 certificate.
1044 """
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001045 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001046 x509 = _lib.X509_new()
Hynek Schlawack8a2dd772016-07-31 13:46:20 +02001047 _openssl_assert(x509 != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001048 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001049
Alex Gaynor9939ba12017-06-25 16:28:24 -04001050 def to_cryptography(self):
1051 """
1052 Export as a ``cryptography`` certificate.
1053
1054 :rtype: ``cryptography.x509.Certificate``
1055
1056 .. versionadded:: 17.1.0
1057 """
1058 from cryptography.hazmat.backends.openssl.x509 import _Certificate
1059 backend = _get_backend()
1060 return _Certificate(backend, self._x509)
1061
1062 @classmethod
1063 def from_cryptography(cls, crypto_cert):
1064 """
1065 Construct based on a ``cryptography`` *crypto_cert*.
1066
1067 :param crypto_key: A ``cryptography`` X.509 certificate.
1068 :type crypto_key: ``cryptography.x509.Certificate``
1069
1070 :rtype: PKey
1071
1072 .. versionadded:: 17.1.0
1073 """
1074 if not isinstance(crypto_cert, x509.Certificate):
1075 raise TypeError("Must be a certificate")
1076
1077 cert = cls()
1078 cert._x509 = crypto_cert._x509
1079 return cert
1080
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001081 def set_version(self, version):
1082 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001083 Set the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001084
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001085 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001086 :type version: :py:class:`int`
1087
Dan Sully44e767a2016-06-04 18:05:27 -07001088 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001089 """
1090 if not isinstance(version, int):
1091 raise TypeError("version must be an integer")
1092
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001093 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001094
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001095 def get_version(self):
1096 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001097 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001098
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001099 :return: The version number of the certificate.
1100 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001101 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001102 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001103
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001104 def get_pubkey(self):
1105 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001106 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001107
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001108 :return: The public key.
1109 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001110 """
1111 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001112 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1113 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001114 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001115 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001116 pkey._only_public = True
1117 return pkey
1118
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001119 def set_pubkey(self, pkey):
1120 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001121 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001122
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001123 :param pkey: The public key.
1124 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001125
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001126 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001127 """
1128 if not isinstance(pkey, PKey):
1129 raise TypeError("pkey must be a PKey instance")
1130
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001131 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001132 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001133
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001134 def sign(self, pkey, digest):
1135 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001136 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001137
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001138 :param pkey: The key to sign with.
1139 :type pkey: :py:class:`PKey`
1140
1141 :param digest: The name of the message digest to use.
1142 :type digest: :py:class:`bytes`
1143
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001144 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001145 """
1146 if not isinstance(pkey, PKey):
1147 raise TypeError("pkey must be a PKey instance")
1148
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001149 if pkey._only_public:
1150 raise ValueError("Key only has public part")
1151
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001152 if not pkey._initialized:
1153 raise ValueError("Key is uninitialized")
1154
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001155 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001156 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001157 raise ValueError("No such digest method")
1158
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001159 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001160 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001161
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001162 def get_signature_algorithm(self):
1163 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001164 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001165
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001166 :return: The name of the algorithm.
1167 :rtype: :py:class:`bytes`
1168
1169 :raises ValueError: If the signature algorithm is undefined.
1170
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001171 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001172 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001173 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1174 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001175 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001176 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001177 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001178
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001179 def digest(self, digest_name):
1180 """
1181 Return the digest of the X509 object.
1182
1183 :param digest_name: The name of the digest algorithm to use.
1184 :type digest_name: :py:class:`bytes`
1185
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001186 :return: The digest of the object, formatted as
1187 :py:const:`b":"`-delimited hex pairs.
1188 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001189 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001190 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001191 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001192 raise ValueError("No such digest method")
1193
Paul Kehrer9f9113a2016-09-20 20:10:25 -05001194 result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001195 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001196 result_length[0] = len(result_buffer)
1197
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001198 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001199 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001200 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001201
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001202 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001203 b16encode(ch).upper() for ch
1204 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001205
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001206 def subject_name_hash(self):
1207 """
1208 Return the hash of the X509 subject.
1209
1210 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001211 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001212 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001213 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001214
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001215 def set_serial_number(self, serial):
1216 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001217 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001218
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001219 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001220 :type serial: :py:class:`int`
1221
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001222 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001223 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001224 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001225 raise TypeError("serial must be an integer")
1226
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001227 hex_serial = hex(serial)[2:]
1228 if not isinstance(hex_serial, bytes):
1229 hex_serial = hex_serial.encode('ascii')
1230
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001231 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001232
1233 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001234 # it. If bignum is still NULL after this call, then the return value
1235 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001236 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001237
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001238 if bignum_serial[0] == _ffi.NULL:
1239 set_result = _lib.ASN1_INTEGER_set(
1240 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001241 if set_result:
1242 # TODO Not tested
1243 _raise_current_error()
1244 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001245 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1246 _lib.BN_free(bignum_serial[0])
1247 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001248 # TODO Not tested
1249 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001250 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1251 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001252 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001253
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001254 def get_serial_number(self):
1255 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001256 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001257
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001258 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001259 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001260 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001261 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1262 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001263 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001264 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001265 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001266 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001267 serial = int(hexstring_serial, 16)
1268 return serial
1269 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001270 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001271 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001272 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001273
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001274 def gmtime_adj_notAfter(self, amount):
1275 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001276 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001277
Dan Sully44e767a2016-06-04 18:05:27 -07001278 :param int amount: The number of seconds by which to adjust the
1279 timestamp.
1280 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001281 """
1282 if not isinstance(amount, int):
1283 raise TypeError("amount must be an integer")
1284
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001285 notAfter = _lib.X509_get_notAfter(self._x509)
1286 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001287
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001288 def gmtime_adj_notBefore(self, amount):
1289 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001290 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001291
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001292 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001293 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001294 """
1295 if not isinstance(amount, int):
1296 raise TypeError("amount must be an integer")
1297
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001298 notBefore = _lib.X509_get_notBefore(self._x509)
1299 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001300
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001301 def has_expired(self):
1302 """
1303 Check whether the certificate has expired.
1304
Dan Sully44e767a2016-06-04 18:05:27 -07001305 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1306 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001307 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001308 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001309 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001310
Paul Kehrerfde45c92016-01-21 12:57:37 -06001311 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001312
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001313 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001314 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001315
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001316 def get_notBefore(self):
1317 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001318 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001319
Paul Kehrerce98ee62017-06-21 06:59:58 -10001320 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001321
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001322 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001323
Dan Sully44e767a2016-06-04 18:05:27 -07001324 :return: A timestamp string, or ``None`` if there is none.
1325 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001326 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001327 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001328
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001329 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001330 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001331
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001332 def set_notBefore(self, when):
1333 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001334 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001335
Paul Kehrerce98ee62017-06-21 06:59:58 -10001336 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001337
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001338 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001339
Dan Sully44e767a2016-06-04 18:05:27 -07001340 :param bytes when: A timestamp string.
1341 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001342 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001343 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001344
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001345 def get_notAfter(self):
1346 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001347 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001348
Paul Kehrerce98ee62017-06-21 06:59:58 -10001349 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001350
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001351 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001352
Dan Sully44e767a2016-06-04 18:05:27 -07001353 :return: A timestamp string, or ``None`` if there is none.
1354 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001355 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001356 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001357
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001358 def set_notAfter(self, when):
1359 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001360 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001361
Paul Kehrerce98ee62017-06-21 06:59:58 -10001362 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001363
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001364 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001365
Dan Sully44e767a2016-06-04 18:05:27 -07001366 :param bytes when: A timestamp string.
1367 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001368 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001369 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001370
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001371 def _get_name(self, which):
1372 name = X509Name.__new__(X509Name)
1373 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001374 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001375
1376 # The name is owned by the X509 structure. As long as the X509Name
1377 # Python object is alive, keep the X509 Python object alive.
1378 name._owner = self
1379
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001380 return name
1381
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001382 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001383 if not isinstance(name, X509Name):
1384 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001385 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001386 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001387
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001388 def get_issuer(self):
1389 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001390 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001391
Cory Benfielde6bcce82015-12-09 08:40:03 +00001392 This creates a new :class:`X509Name` that wraps the underlying issuer
1393 name field on the certificate. Modifying it will modify the underlying
1394 certificate, and will have the effect of modifying any other
1395 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001396
1397 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001398 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001399 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001400 return self._get_name(_lib.X509_get_issuer_name)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001401
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001402 def set_issuer(self, issuer):
1403 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001404 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001405
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001406 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001407 :type issuer: :py:class:`X509Name`
1408
Dan Sully44e767a2016-06-04 18:05:27 -07001409 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001410 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001411 return self._set_name(_lib.X509_set_issuer_name, issuer)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001412
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001413 def get_subject(self):
1414 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001415 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001416
Cory Benfielde6bcce82015-12-09 08:40:03 +00001417 This creates a new :class:`X509Name` that wraps the underlying subject
1418 name field on the certificate. Modifying it will modify the underlying
1419 certificate, and will have the effect of modifying any other
1420 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001421
1422 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001423 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001424 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001425 return self._get_name(_lib.X509_get_subject_name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001426
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001427 def set_subject(self, subject):
1428 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001429 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001430
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001431 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001432 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001433
Dan Sully44e767a2016-06-04 18:05:27 -07001434 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001435 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001436 return self._set_name(_lib.X509_set_subject_name, subject)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001437
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001438 def get_extension_count(self):
1439 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001440 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001441
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001442 :return: The number of extensions.
1443 :rtype: :py:class:`int`
1444
1445 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001446 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001447 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001448
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001449 def add_extensions(self, extensions):
1450 """
1451 Add extensions to the certificate.
1452
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001453 :param extensions: The extensions to add.
1454 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001455 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001456 """
1457 for ext in extensions:
1458 if not isinstance(ext, X509Extension):
1459 raise ValueError("One of the elements is not an X509Extension")
1460
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001461 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001462 if not add_result:
1463 _raise_current_error()
1464
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001465 def get_extension(self, index):
1466 """
1467 Get a specific extension of the certificate by index.
1468
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001469 Extensions on a certificate are kept in order. The index
1470 parameter selects which extension will be returned.
1471
1472 :param int index: The index of the extension to retrieve.
1473 :return: The extension at the specified index.
1474 :rtype: :py:class:`X509Extension`
1475 :raises IndexError: If the extension index was out of bounds.
1476
1477 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001478 """
1479 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001480 ext._extension = _lib.X509_get_ext(self._x509, index)
1481 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001482 raise IndexError("extension index out of bounds")
1483
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001484 extension = _lib.X509_EXTENSION_dup(ext._extension)
1485 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001486 return ext
1487
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001488
Alex Gaynor10d30832017-06-29 15:31:39 -07001489X509Type = deprecated(
1490 X509, __name__,
1491 "X509Type has been deprecated, use X509 instead",
1492 DeprecationWarning
1493)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001494
1495
Dan Sully44e767a2016-06-04 18:05:27 -07001496class X509StoreFlags(object):
1497 """
1498 Flags for X509 verification, used to change the behavior of
1499 :class:`X509Store`.
1500
1501 See `OpenSSL Verification Flags`_ for details.
1502
1503 .. _OpenSSL Verification Flags:
Alex Chan54005ce2017-03-21 08:08:17 +00001504 https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_flags.html
Dan Sully44e767a2016-06-04 18:05:27 -07001505 """
1506 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1507 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1508 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1509 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1510 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1511 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1512 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1513 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1514 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1515 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1516 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1517
1518
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001519class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001520 """
Dan Sully44e767a2016-06-04 18:05:27 -07001521 An X.509 store.
1522
1523 An X.509 store is used to describe a context in which to verify a
1524 certificate. A description of a context may include a set of certificates
1525 to trust, a set of certificate revocation lists, verification flags and
1526 more.
1527
1528 An X.509 store, being only a description, cannot be used by itself to
1529 verify a certificate. To carry out the actual verification process, see
1530 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001531 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001532
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001533 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001534 store = _lib.X509_STORE_new()
1535 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001536
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001537 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001538 """
Dan Sully44e767a2016-06-04 18:05:27 -07001539 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001540
Dan Sully44e767a2016-06-04 18:05:27 -07001541 Adding a certificate with this method adds this certificate as a
1542 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001543
1544 :param X509 cert: The certificate to add to this store.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001545
Dan Sully44e767a2016-06-04 18:05:27 -07001546 :raises TypeError: If the certificate is not an :class:`X509`.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001547
1548 :raises OpenSSL.crypto.Error: If OpenSSL was unhappy with your
1549 certificate.
1550
Dan Sully44e767a2016-06-04 18:05:27 -07001551 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001552 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001553 if not isinstance(cert, X509):
1554 raise TypeError()
1555
Dan Sully44e767a2016-06-04 18:05:27 -07001556 _openssl_assert(_lib.X509_STORE_add_cert(self._store, cert._x509) != 0)
1557
1558 def add_crl(self, crl):
1559 """
1560 Add a certificate revocation list to this store.
1561
1562 The certificate revocation lists added to a store will only be used if
1563 the associated flags are configured to check certificate revocation
1564 lists.
1565
1566 .. versionadded:: 16.1.0
1567
1568 :param CRL crl: The certificate revocation list to add to this store.
1569 :return: ``None`` if the certificate revocation list was added
1570 successfully.
1571 """
1572 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1573
1574 def set_flags(self, flags):
1575 """
1576 Set verification flags to this store.
1577
1578 Verification flags can be combined by oring them together.
1579
1580 .. note::
1581
1582 Setting a verification flag sometimes requires clients to add
1583 additional information to the store, otherwise a suitable error will
1584 be raised.
1585
1586 For example, in setting flags to enable CRL checking a
1587 suitable CRL must be added to the store otherwise an error will be
1588 raised.
1589
1590 .. versionadded:: 16.1.0
1591
1592 :param int flags: The verification flags to set on this store.
1593 See :class:`X509StoreFlags` for available constants.
1594 :return: ``None`` if the verification flags were successfully set.
1595 """
1596 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001597
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001598 def set_time(self, vfy_time):
1599 """
1600 Set the time against which the certificates are verified.
1601
1602 Normally the current time is used.
1603
1604 .. note::
1605
1606 For example, you can determine if a certificate was valid at a given
1607 time.
1608
Hynek Schlawackf6c96af2017-04-20 12:34:58 +02001609 .. versionadded:: 17.0.0
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001610
1611 :param datetime vfy_time: The verification time to set on this store.
1612 :return: ``None`` if the verification time was successfully set.
1613 """
1614 param = _lib.X509_VERIFY_PARAM_new()
1615 param = _ffi.gc(param, _lib.X509_VERIFY_PARAM_free)
1616
1617 _lib.X509_VERIFY_PARAM_set_time(param, int(vfy_time.strftime('%s')))
1618 _openssl_assert(_lib.X509_STORE_set1_param(self._store, param) != 0)
1619
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001620
Alex Gaynor10d30832017-06-29 15:31:39 -07001621X509StoreType = deprecated(
1622 X509Store, __name__,
1623 "X509StoreType has been deprecated, use X509Store instead",
1624 DeprecationWarning
1625)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001626
1627
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001628class X509StoreContextError(Exception):
1629 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001630 An exception raised when an error occurred while verifying a certificate
1631 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001632
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001633 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001634 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001635 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001636
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001637 def __init__(self, message, certificate):
1638 super(X509StoreContextError, self).__init__(message)
1639 self.certificate = certificate
1640
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001641
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001642class X509StoreContext(object):
1643 """
1644 An X.509 store context.
1645
Dan Sully44e767a2016-06-04 18:05:27 -07001646 An X.509 store context is used to carry out the actual verification process
1647 of a certificate in a described context. For describing such a context, see
1648 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001649
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001650 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1651 instance. It is dynamically allocated and automatically garbage
1652 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001653 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001654 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001655 :param X509Store store: The certificates which will be trusted for the
1656 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001657 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001658 """
1659
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001660 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001661 store_ctx = _lib.X509_STORE_CTX_new()
1662 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1663 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001664 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001665 # Make the store context available for use after instantiating this
1666 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001667 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001668 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001669
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001670 def _init(self):
1671 """
1672 Set up the store context for a subsequent verification operation.
1673 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001674 ret = _lib.X509_STORE_CTX_init(
1675 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1676 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001677 if ret <= 0:
1678 _raise_current_error()
1679
1680 def _cleanup(self):
1681 """
1682 Internally cleans up the store context.
1683
Dan Sully44e767a2016-06-04 18:05:27 -07001684 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001685 """
1686 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1687
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001688 def _exception_from_context(self):
1689 """
1690 Convert an OpenSSL native context error failure into a Python
1691 exception.
1692
Alex Gaynor5945ea82015-09-05 14:59:06 -04001693 When a call to native OpenSSL X509_verify_cert fails, additional
1694 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001695 """
1696 errors = [
1697 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1698 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1699 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001700 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001701 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001702 # A context error should always be associated with a certificate, so we
1703 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001704 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001705 _cert = _lib.X509_dup(_x509)
1706 pycert = X509.__new__(X509)
1707 pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001708 return X509StoreContextError(errors, pycert)
1709
Stephen Holsapple46a09252015-02-12 14:45:43 -08001710 def set_store(self, store):
1711 """
Dan Sully44e767a2016-06-04 18:05:27 -07001712 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001713
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001714 .. versionadded:: 0.15
1715
Dan Sully44e767a2016-06-04 18:05:27 -07001716 :param X509Store store: The store description which will be used for
1717 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001718 """
1719 self._store = store
1720
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001721 def verify_certificate(self):
1722 """
1723 Verify a certificate in a context.
1724
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001725 .. versionadded:: 0.15
1726
Alex Gaynorca87ff62015-09-04 23:31:03 -04001727 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001728 certificate in the context. Sets ``certificate`` attribute to
1729 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001730 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001731 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001732 # :meth:`verify_certificate` is called multiple times.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001733 self._init()
1734 ret = _lib.X509_verify_cert(self._store_ctx)
1735 self._cleanup()
1736 if ret <= 0:
1737 raise self._exception_from_context()
1738
1739
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001740def load_certificate(type, buffer):
1741 """
1742 Load a certificate from a buffer
1743
1744 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1745
Dan Sully44e767a2016-06-04 18:05:27 -07001746 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001747
1748 :return: The X509 object
1749 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001750 if isinstance(buffer, _text_type):
1751 buffer = buffer.encode("ascii")
1752
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001753 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001754
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001755 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001756 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001757 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001758 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001759 else:
1760 raise ValueError(
1761 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001762
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001763 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001764 _raise_current_error()
1765
1766 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001767 cert._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001768 return cert
1769
1770
1771def dump_certificate(type, cert):
1772 """
1773 Dump a certificate to a buffer
1774
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001775 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1776 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001777 :param cert: The certificate to dump
1778 :return: The buffer with the dumped certificate in
1779 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001780 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001781
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001782 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001783 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001784 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001785 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001786 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001787 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001788 else:
1789 raise ValueError(
1790 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1791 "FILETYPE_TEXT")
1792
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001793 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001794 return _bio_to_string(bio)
1795
1796
Cory Benfield6492f7c2015-10-27 16:57:58 +09001797def dump_publickey(type, pkey):
1798 """
Cory Benfield11c10192015-10-27 17:23:03 +09001799 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001800
Cory Benfield9c590b92015-10-28 14:55:05 +09001801 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001802 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001803 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001804 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001805 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001806 """
1807 bio = _new_mem_buf()
1808 if type == FILETYPE_PEM:
1809 write_bio = _lib.PEM_write_bio_PUBKEY
1810 elif type == FILETYPE_ASN1:
1811 write_bio = _lib.i2d_PUBKEY_bio
1812 else:
1813 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1814
1815 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001816 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001817 _raise_current_error()
1818
1819 return _bio_to_string(bio)
1820
1821
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001822def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1823 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001824 Dump the private key *pkey* into a buffer string encoded with the type
1825 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1826 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001827
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001828 :param type: The file type (one of :const:`FILETYPE_PEM`,
1829 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1830 :param PKey pkey: The PKey to dump
1831 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001832 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001833 the passphrase to use, or a callback for providing the passphrase.
1834
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001835 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001836 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001837 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001838 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001839
1840 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001841 if passphrase is None:
1842 raise TypeError(
1843 "if a value is given for cipher "
1844 "one must also be given for passphrase")
1845 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001846 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001847 raise ValueError("Invalid cipher name")
1848 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001849 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001850
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001851 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001852 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001853 result_code = _lib.PEM_write_bio_PrivateKey(
1854 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001855 helper.callback, helper.callback_args)
1856 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001857 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001858 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001859 elif type == FILETYPE_TEXT:
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001860 rsa = _ffi.gc(
1861 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1862 _lib.RSA_free
1863 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001864 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001865 else:
1866 raise ValueError(
1867 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1868 "FILETYPE_TEXT")
1869
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001870 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001871
1872 return _bio_to_string(bio)
1873
1874
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001875class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001876 """
1877 A certificate revocation.
1878 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001879 # http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_
1880 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1881 # OCSP_crl_reason_str. We use the latter, just like the command line
1882 # program.
1883 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001884 b"unspecified",
1885 b"keyCompromise",
1886 b"CACompromise",
1887 b"affiliationChanged",
1888 b"superseded",
1889 b"cessationOfOperation",
1890 b"certificateHold",
1891 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001892 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001893
1894 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001895 revoked = _lib.X509_REVOKED_new()
1896 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001897
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001898 def set_serial(self, hex_str):
1899 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001900 Set the serial number.
1901
1902 The serial number is formatted as a hexadecimal number encoded in
1903 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001904
Dan Sully44e767a2016-06-04 18:05:27 -07001905 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001906
Dan Sully44e767a2016-06-04 18:05:27 -07001907 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001908 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001909 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1910 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001911 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001912 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001913 if not bn_result:
1914 raise ValueError("bad hex string")
1915
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001916 asn1_serial = _ffi.gc(
1917 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1918 _lib.ASN1_INTEGER_free)
1919 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001920
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001921 def get_serial(self):
1922 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001923 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001924
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001925 The serial number is formatted as a hexadecimal number encoded in
1926 ASCII.
1927
1928 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001929 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001930 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001931 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001932
Alex Gaynor67903a62016-06-02 10:37:13 -07001933 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1934 _openssl_assert(asn1_int != _ffi.NULL)
1935 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1936 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001937 return _bio_to_string(bio)
1938
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001939 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001940 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1941 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001942 obj = _lib.X509_EXTENSION_get_object(ext)
1943 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001944 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001945 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001946 break
1947
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001948 def set_reason(self, reason):
1949 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001950 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001951
Dan Sully44e767a2016-06-04 18:05:27 -07001952 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001953
1954 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07001955 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001956
Dan Sully44e767a2016-06-04 18:05:27 -07001957 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001958
1959 .. seealso::
1960
Dan Sully44e767a2016-06-04 18:05:27 -07001961 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001962 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001963 """
1964 if reason is None:
1965 self._delete_reason()
1966 elif not isinstance(reason, bytes):
1967 raise TypeError("reason must be None or a byte string")
1968 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001969 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001970 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
1971
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001972 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07001973 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001974 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001975
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001976 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001977 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001978
1979 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001980 add_result = _lib.X509_REVOKED_add1_ext_i2d(
1981 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001982 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001983
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001984 def get_reason(self):
1985 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04001986 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001987
Dan Sully44e767a2016-06-04 18:05:27 -07001988 :return: The reason, or ``None`` if there is none.
1989 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001990
1991 .. seealso::
1992
Dan Sully44e767a2016-06-04 18:05:27 -07001993 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001994 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001995 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001996 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1997 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001998 obj = _lib.X509_EXTENSION_get_object(ext)
1999 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08002000 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002001
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002002 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002003 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002004 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002005 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04002006 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002007 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002008
2009 return _bio_to_string(bio)
2010
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002011 def all_reasons(self):
2012 """
2013 Return a list of all the supported reason strings.
2014
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002015 This list is a copy; modifying it does not change the supported reason
2016 strings.
2017
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002018 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07002019 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002020 """
2021 return self._crl_reasons[:]
2022
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002023 def set_rev_date(self, when):
2024 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002025 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002026
Dan Sully44e767a2016-06-04 18:05:27 -07002027 :param bytes when: The timestamp of the revocation,
Paul Kehrerce98ee62017-06-21 06:59:58 -10002028 as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002029 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002030 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002031 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2032 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002033
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002034 def get_rev_date(self):
2035 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002036 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002037
Paul Kehrerce98ee62017-06-21 06:59:58 -10002038 :return: The timestamp of the revocation, as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002039 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002040 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002041 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2042 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002043
2044
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002045class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002046 """
2047 A certificate revocation list.
2048 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002049
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002050 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002051 crl = _lib.X509_CRL_new()
2052 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002053
Paul Kehrer41c10242017-06-29 18:24:17 -05002054 def to_cryptography(self):
2055 """
2056 Export as a ``cryptography`` CRL.
2057
2058 :rtype: ``cryptography.x509.CertificateRevocationList``
2059
2060 .. versionadded:: 17.1.0
2061 """
2062 from cryptography.hazmat.backends.openssl.x509 import (
2063 _CertificateRevocationList
2064 )
2065 backend = _get_backend()
2066 return _CertificateRevocationList(backend, self._crl)
2067
2068 @classmethod
2069 def from_cryptography(cls, crypto_crl):
2070 """
2071 Construct based on a ``cryptography`` *crypto_crl*.
2072
2073 :param crypto_crl: A ``cryptography`` certificate revocation list
2074 :type crypto_crl: ``cryptography.x509.CertificateRevocationList``
2075
2076 :rtype: CRL
2077
2078 .. versionadded:: 17.1.0
2079 """
2080 if not isinstance(crypto_crl, x509.CertificateRevocationList):
2081 raise TypeError("Must be a certificate revocation list")
2082
2083 crl = cls()
2084 crl._crl = crypto_crl._x509_crl
2085 return crl
2086
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002087 def get_revoked(self):
2088 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002089 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002090
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002091 These revocations will be provided by value, not by reference.
2092 That means it's okay to mutate them: it won't affect this CRL.
2093
2094 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002095 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002096 """
2097 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07002098 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002099 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
2100 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04002101 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002102 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002103 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002104 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002105 if results:
2106 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002107
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002108 def add_revoked(self, revoked):
2109 """
2110 Add a revoked (by value not reference) to the CRL structure
2111
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002112 This revocation will be added by value, not by reference. That
2113 means it's okay to mutate it after adding: it won't affect
2114 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002115
Dan Sully44e767a2016-06-04 18:05:27 -07002116 :param Revoked revoked: The new revocation.
2117 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002118 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04002119 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002120 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002121
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002122 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002123 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002124
Dan Sully44e767a2016-06-04 18:05:27 -07002125 def get_issuer(self):
2126 """
2127 Get the CRL's issuer.
2128
2129 .. versionadded:: 16.1.0
2130
2131 :rtype: X509Name
2132 """
2133 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
2134 _openssl_assert(_issuer != _ffi.NULL)
2135 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
2136 issuer = X509Name.__new__(X509Name)
2137 issuer._name = _issuer
2138 return issuer
2139
2140 def set_version(self, version):
2141 """
2142 Set the CRL version.
2143
2144 .. versionadded:: 16.1.0
2145
2146 :param int version: The version of the CRL.
2147 :return: ``None``
2148 """
2149 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2150
2151 def _set_boundary_time(self, which, when):
2152 return _set_asn1_time(which(self._crl), when)
2153
2154 def set_lastUpdate(self, when):
2155 """
2156 Set when the CRL was last updated.
2157
Paul Kehrerce98ee62017-06-21 06:59:58 -10002158 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002159
2160 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002161
2162 .. versionadded:: 16.1.0
2163
2164 :param bytes when: A timestamp string.
2165 :return: ``None``
2166 """
2167 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2168
2169 def set_nextUpdate(self, when):
2170 """
2171 Set when the CRL will next be udpated.
2172
Paul Kehrerce98ee62017-06-21 06:59:58 -10002173 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002174
2175 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002176
2177 .. versionadded:: 16.1.0
2178
2179 :param bytes when: A timestamp string.
2180 :return: ``None``
2181 """
2182 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2183
2184 def sign(self, issuer_cert, issuer_key, digest):
2185 """
2186 Sign the CRL.
2187
2188 Signing a CRL enables clients to associate the CRL itself with an
2189 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2190 be signed by an issuer.
2191
2192 This method implicitly sets the issuer's name based on the issuer
2193 certificate and private key used to sign the CRL.
2194
2195 .. versionadded:: 16.1.0
2196
2197 :param X509 issuer_cert: The issuer's certificate.
2198 :param PKey issuer_key: The issuer's private key.
2199 :param bytes digest: The digest method to sign the CRL with.
2200 """
2201 digest_obj = _lib.EVP_get_digestbyname(digest)
2202 _openssl_assert(digest_obj != _ffi.NULL)
2203 _lib.X509_CRL_set_issuer_name(
2204 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2205 _lib.X509_CRL_sort(self._crl)
2206 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2207 _openssl_assert(result != 0)
2208
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002209 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002210 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002211 """
Dan Sully44e767a2016-06-04 18:05:27 -07002212 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002213
Dan Sully44e767a2016-06-04 18:05:27 -07002214 :param X509 cert: The certificate used to sign the CRL.
2215 :param PKey key: The key used to sign the CRL.
2216 :param int type: The export format, either :data:`FILETYPE_PEM`,
2217 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002218 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002219 :param bytes digest: The name of the message digest to use (eg
Alex Gaynor239e2d32016-09-11 12:36:35 -04002220 ``b"sha2566"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002221 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002222 """
Dan Sully44e767a2016-06-04 18:05:27 -07002223
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002224 if not isinstance(cert, X509):
2225 raise TypeError("cert must be an X509 instance")
2226 if not isinstance(key, PKey):
2227 raise TypeError("key must be a PKey instance")
2228 if not isinstance(type, int):
2229 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002230
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002231 if digest is _UNSPECIFIED:
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002232 _warn(
2233 "The default message digest (md5) is deprecated. "
2234 "Pass the name of a message digest explicitly.",
2235 category=DeprecationWarning,
2236 stacklevel=2,
2237 )
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002238 digest = b"md5"
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002239
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002240 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002241 if digest_obj == _ffi.NULL:
2242 raise ValueError("No such digest method")
2243
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002244 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002245 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002246
Alex Gaynora738ed52015-09-05 11:17:10 -04002247 # A scratch time object to give different values to different CRL
2248 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002249 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002250 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002251
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002252 _lib.X509_gmtime_adj(sometime, 0)
2253 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002254
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002255 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2256 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002257
Alex Gaynor5945ea82015-09-05 14:59:06 -04002258 _lib.X509_CRL_set_issuer_name(
2259 self._crl, _lib.X509_get_subject_name(cert._x509)
2260 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002261
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002262 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002263 if not sign_result:
2264 _raise_current_error()
2265
Dominic Chenf05b2122015-10-13 16:32:35 +00002266 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002267
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002268
Alex Gaynor10d30832017-06-29 15:31:39 -07002269CRLType = deprecated(
2270 CRL, __name__,
2271 "CRLType has been deprecated, use CRL instead",
2272 DeprecationWarning
2273)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002274
2275
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002276class PKCS7(object):
2277 def type_is_signed(self):
2278 """
2279 Check if this NID_pkcs7_signed object
2280
2281 :return: True if the PKCS7 is of type signed
2282 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002283 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002284
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002285 def type_is_enveloped(self):
2286 """
2287 Check if this NID_pkcs7_enveloped object
2288
2289 :returns: True if the PKCS7 is of type enveloped
2290 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002291 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002292
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002293 def type_is_signedAndEnveloped(self):
2294 """
2295 Check if this NID_pkcs7_signedAndEnveloped object
2296
2297 :returns: True if the PKCS7 is of type signedAndEnveloped
2298 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002299 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002300
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002301 def type_is_data(self):
2302 """
2303 Check if this NID_pkcs7_data object
2304
2305 :return: True if the PKCS7 is of type data
2306 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002307 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002308
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002309 def get_type_name(self):
2310 """
2311 Returns the type name of the PKCS7 structure
2312
2313 :return: A string with the typename
2314 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002315 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2316 string_type = _lib.OBJ_nid2sn(nid)
2317 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002318
Alex Chanc6077062016-11-18 13:53:39 +00002319
Alex Gaynor10d30832017-06-29 15:31:39 -07002320PKCS7Type = deprecated(
2321 PKCS7, __name__,
2322 "PKCS7Type has been deprecated, use PKCS7 instead",
2323 DeprecationWarning
2324)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002325
2326
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002327class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002328 """
2329 A PKCS #12 archive.
2330 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002331
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002332 def __init__(self):
2333 self._pkey = None
2334 self._cert = None
2335 self._cacerts = None
2336 self._friendlyname = None
2337
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002338 def get_certificate(self):
2339 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002340 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002341
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002342 :return: The certificate, or :py:const:`None` if there is none.
2343 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002344 """
2345 return self._cert
2346
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002347 def set_certificate(self, cert):
2348 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002349 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002350
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002351 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002352 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002353
Dan Sully44e767a2016-06-04 18:05:27 -07002354 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002355 """
2356 if not isinstance(cert, X509):
2357 raise TypeError("cert must be an X509 instance")
2358 self._cert = cert
2359
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002360 def get_privatekey(self):
2361 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002362 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002363
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002364 :return: The private key, or :py:const:`None` if there is none.
2365 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002366 """
2367 return self._pkey
2368
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002369 def set_privatekey(self, pkey):
2370 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002371 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002372
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002373 :param pkey: The new private key, or :py:const:`None` to unset it.
2374 :type pkey: :py:class:`PKey` or :py:const:`None`
2375
Dan Sully44e767a2016-06-04 18:05:27 -07002376 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002377 """
2378 if not isinstance(pkey, PKey):
2379 raise TypeError("pkey must be a PKey instance")
2380 self._pkey = pkey
2381
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002382 def get_ca_certificates(self):
2383 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002384 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002385
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002386 :return: A tuple with the CA certificates in the chain, or
2387 :py:const:`None` if there are none.
2388 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002389 """
2390 if self._cacerts is not None:
2391 return tuple(self._cacerts)
2392
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002393 def set_ca_certificates(self, cacerts):
2394 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002395 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002396
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002397 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2398 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002399 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002400
Dan Sully44e767a2016-06-04 18:05:27 -07002401 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002402 """
2403 if cacerts is None:
2404 self._cacerts = None
2405 else:
2406 cacerts = list(cacerts)
2407 for cert in cacerts:
2408 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002409 raise TypeError(
2410 "iterable must only contain X509 instances"
2411 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002412 self._cacerts = cacerts
2413
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002414 def set_friendlyname(self, name):
2415 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002416 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002417
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002418 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002419 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002420
Dan Sully44e767a2016-06-04 18:05:27 -07002421 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002422 """
2423 if name is None:
2424 self._friendlyname = None
2425 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002426 raise TypeError(
2427 "name must be a byte string or None (not %r)" % (name,)
2428 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002429 self._friendlyname = name
2430
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002431 def get_friendlyname(self):
2432 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002433 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002434
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002435 :returns: The friendly name, or :py:const:`None` if there is none.
2436 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002437 """
2438 return self._friendlyname
2439
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002440 def export(self, passphrase=None, iter=2048, maciter=1):
2441 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002442 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002443
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002444 For more information, see the :c:func:`PKCS12_create` man page.
2445
2446 :param passphrase: The passphrase used to encrypt the structure. Unlike
2447 some other passphrase arguments, this *must* be a string, not a
2448 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002449 :type passphrase: :py:data:`bytes`
2450
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002451 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002452 :type iter: :py:data:`int`
2453
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002454 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002455 :type maciter: :py:data:`int`
2456
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002457 :return: The string representation of the PKCS #12 structure.
2458 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002459 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002460 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002461
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002462 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002463 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002464 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002465 cacerts = _lib.sk_X509_new_null()
2466 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002467 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002468 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002469
2470 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002471 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002472
2473 friendlyname = self._friendlyname
2474 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002475 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002476
2477 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002478 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002479 else:
2480 pkey = self._pkey._pkey
2481
2482 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002483 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002484 else:
2485 cert = self._cert._x509
2486
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002487 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002488 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002489 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2490 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002491 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002492 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002493 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002494 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002495
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002496 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002497 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002498 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002499
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002500
Alex Gaynor10d30832017-06-29 15:31:39 -07002501PKCS12Type = deprecated(
2502 PKCS12, __name__,
2503 "PKCS12Type has been deprecated, use PKCS12 instead",
2504 DeprecationWarning
2505)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002506
2507
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002508class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002509 """
2510 A Netscape SPKI object.
2511 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002512
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002513 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002514 spki = _lib.NETSCAPE_SPKI_new()
2515 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002516
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002517 def sign(self, pkey, digest):
2518 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002519 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002520
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002521 :param pkey: The private key to sign with.
2522 :type pkey: :py:class:`PKey`
2523
2524 :param digest: The message digest to use.
2525 :type digest: :py:class:`bytes`
2526
Dan Sully44e767a2016-06-04 18:05:27 -07002527 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002528 """
2529 if pkey._only_public:
2530 raise ValueError("Key has only public part")
2531
2532 if not pkey._initialized:
2533 raise ValueError("Key is uninitialized")
2534
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002535 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002536 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002537 raise ValueError("No such digest method")
2538
Alex Gaynor5945ea82015-09-05 14:59:06 -04002539 sign_result = _lib.NETSCAPE_SPKI_sign(
2540 self._spki, pkey._pkey, digest_obj
2541 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002542 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002543
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002544 def verify(self, key):
2545 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002546 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002547
Hynek Schlawack01c31672016-12-11 15:14:09 +01002548 :param PKey key: The public key that signature is supposedly from.
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002549
Hynek Schlawack01c31672016-12-11 15:14:09 +01002550 :return: ``True`` if the signature is correct.
2551 :rtype: bool
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002552
Hynek Schlawack01c31672016-12-11 15:14:09 +01002553 :raises OpenSSL.crypto.Error: If the signature is invalid, or there was
2554 a problem verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002555 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002556 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002557 if answer <= 0:
2558 _raise_current_error()
2559 return True
2560
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002561 def b64_encode(self):
2562 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002563 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002564
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002565 :return: The base64 encoded string.
2566 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002567 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002568 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2569 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002570 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002571 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002572
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002573 def get_pubkey(self):
2574 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002575 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002576
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002577 :return: The public key.
2578 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002579 """
2580 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002581 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002582 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002583 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002584 pkey._only_public = True
2585 return pkey
2586
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002587 def set_pubkey(self, pkey):
2588 """
2589 Set the public key of the certificate
2590
2591 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002592 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002593 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002594 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002595 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002596
2597
Alex Gaynor10d30832017-06-29 15:31:39 -07002598NetscapeSPKIType = deprecated(
2599 NetscapeSPKI, __name__,
2600 "NetscapeSPKIType has been deprecated, use NetscapeSPKI instead",
2601 DeprecationWarning
2602)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002603
2604
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002605class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002606 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002607 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002608 raise ValueError(
2609 "only FILETYPE_PEM key format supports encryption"
2610 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002611 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002612 self._more_args = more_args
2613 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002614 self._problems = []
2615
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002616 @property
2617 def callback(self):
2618 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002619 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002620 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002621 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002622 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002623 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002624 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002625 raise TypeError(
2626 "Last argument must be a byte string or a callable."
2627 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002628
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002629 @property
2630 def callback_args(self):
2631 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002632 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002633 elif isinstance(self._passphrase, bytes):
2634 return self._passphrase
2635 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002636 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002637 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002638 raise TypeError(
2639 "Last argument must be a byte string or a callable."
2640 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002641
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002642 def raise_if_problem(self, exceptionType=Error):
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002643 if self._problems:
Greg Bowser36eb2de2017-01-24 11:38:55 -05002644
2645 # Flush the OpenSSL error queue
2646 try:
2647 _exception_from_error_queue(exceptionType)
2648 except exceptionType:
2649 pass
2650
2651 raise self._problems.pop(0)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002652
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002653 def _read_passphrase(self, buf, size, rwflag, userdata):
2654 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002655 if self._more_args:
2656 result = self._passphrase(size, rwflag, userdata)
2657 else:
2658 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002659 if not isinstance(result, bytes):
2660 raise ValueError("String expected")
2661 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002662 if self._truncate:
2663 result = result[:size]
2664 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002665 raise ValueError(
2666 "passphrase returned by callback is too long"
2667 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002668 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002669 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002670 return len(result)
2671 except Exception as e:
2672 self._problems.append(e)
2673 return 0
2674
2675
Cory Benfield6492f7c2015-10-27 16:57:58 +09002676def load_publickey(type, buffer):
2677 """
Cory Benfield11c10192015-10-27 17:23:03 +09002678 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002679
Cory Benfield9c590b92015-10-28 14:55:05 +09002680 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002681 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002682 :param buffer: The buffer the key is stored in.
2683 :type buffer: A Python string object, either unicode or bytestring.
2684 :return: The PKey object.
2685 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002686 """
2687 if isinstance(buffer, _text_type):
2688 buffer = buffer.encode("ascii")
2689
2690 bio = _new_mem_buf(buffer)
2691
2692 if type == FILETYPE_PEM:
2693 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2694 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2695 elif type == FILETYPE_ASN1:
2696 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2697 else:
2698 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2699
2700 if evp_pkey == _ffi.NULL:
2701 _raise_current_error()
2702
2703 pkey = PKey.__new__(PKey)
2704 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002705 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002706 return pkey
2707
2708
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002709def load_privatekey(type, buffer, passphrase=None):
2710 """
2711 Load a private key from a buffer
2712
2713 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2714 :param buffer: The buffer the key is stored in
2715 :param passphrase: (optional) if encrypted PEM format, this can be
2716 either the passphrase to use, or a callback for
2717 providing the passphrase.
2718
2719 :return: The PKey object
2720 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002721 if isinstance(buffer, _text_type):
2722 buffer = buffer.encode("ascii")
2723
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002724 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002725
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002726 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002727 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002728 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2729 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002730 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002731 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002732 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002733 else:
2734 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2735
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002736 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002737 _raise_current_error()
2738
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002739 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002740 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002741 return pkey
2742
2743
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002744def dump_certificate_request(type, req):
2745 """
2746 Dump a certificate request to a buffer
2747
2748 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2749 :param req: The certificate request to dump
2750 :return: The buffer with the dumped certificate request in
2751 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002752 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002753
2754 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002755 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002756 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002757 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002758 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002759 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002760 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002761 raise ValueError(
2762 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2763 "FILETYPE_TEXT"
2764 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002765
Alex Gaynor09a386e2016-07-03 09:32:44 -04002766 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002767
2768 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002769
2770
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002771def load_certificate_request(type, buffer):
2772 """
2773 Load a certificate request from a buffer
2774
2775 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2776 :param buffer: The buffer the certificate request is stored in
2777 :return: The X509Req object
2778 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002779 if isinstance(buffer, _text_type):
2780 buffer = buffer.encode("ascii")
2781
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002782 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002783
2784 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002785 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002786 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002787 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002788 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002789 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002790
Alex Gaynoradd5b072016-06-04 21:04:00 -07002791 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002792
2793 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002794 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002795 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002796
2797
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002798def sign(pkey, data, digest):
2799 """
2800 Sign data with a digest
2801
2802 :param pkey: Pkey to sign with
2803 :param data: data to be signed
2804 :param digest: message digest to use
2805 :return: signature
2806 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002807 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002808
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002809 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002810 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002811 raise ValueError("No such digest method")
2812
Alex Gaynor67903a62016-06-02 10:37:13 -07002813 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002814 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002815
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002816 _lib.EVP_SignInit(md_ctx, digest_obj)
2817 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002818
Colleen Murphye09399b2016-03-01 17:40:49 -08002819 pkey_length = (PKey.bits(pkey) + 7) // 8
2820 signature_buffer = _ffi.new("unsigned char[]", pkey_length)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002821 signature_length = _ffi.new("unsigned int*")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002822 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002823 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002824 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002825
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002826 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002827
2828
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002829def verify(cert, signature, data, digest):
2830 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002831 Verify a signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002832
2833 :param cert: signing certificate (X509 object)
2834 :param signature: signature returned by sign function
2835 :param data: data to be verified
2836 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002837 :return: ``None`` if the signature is correct, raise exception otherwise.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002838 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002839 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002840
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002841 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002842 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002843 raise ValueError("No such digest method")
2844
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002845 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002846 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002847 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002848
Alex Gaynor67903a62016-06-02 10:37:13 -07002849 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002850 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002851
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002852 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2853 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002854 verify_result = _lib.EVP_VerifyFinal(
2855 md_ctx, signature, len(signature), pkey
2856 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002857
2858 if verify_result != 1:
2859 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002860
2861
Dominic Chenf05b2122015-10-13 16:32:35 +00002862def dump_crl(type, crl):
2863 """
2864 Dump a certificate revocation list to a buffer.
2865
2866 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2867 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002868 :param CRL crl: The CRL to dump.
2869
Dominic Chenf05b2122015-10-13 16:32:35 +00002870 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002871 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002872 """
2873 bio = _new_mem_buf()
2874
2875 if type == FILETYPE_PEM:
2876 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2877 elif type == FILETYPE_ASN1:
2878 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2879 elif type == FILETYPE_TEXT:
2880 ret = _lib.X509_CRL_print(bio, crl._crl)
2881 else:
2882 raise ValueError(
2883 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2884 "FILETYPE_TEXT")
2885
2886 assert ret == 1
2887 return _bio_to_string(bio)
2888
2889
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002890def load_crl(type, buffer):
2891 """
2892 Load a certificate revocation list from a buffer
2893
2894 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2895 :param buffer: The buffer the CRL is stored in
2896
2897 :return: The PKey object
2898 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002899 if isinstance(buffer, _text_type):
2900 buffer = buffer.encode("ascii")
2901
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002902 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002903
2904 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002905 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002906 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002907 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002908 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002909 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2910
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002911 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002912 _raise_current_error()
2913
2914 result = CRL.__new__(CRL)
2915 result._crl = crl
2916 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002917
2918
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002919def load_pkcs7_data(type, buffer):
2920 """
2921 Load pkcs7 data from a buffer
2922
2923 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2924 :param buffer: The buffer with the pkcs7 data.
2925 :return: The PKCS7 object
2926 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002927 if isinstance(buffer, _text_type):
2928 buffer = buffer.encode("ascii")
2929
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002930 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002931
2932 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002933 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002934 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002935 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002936 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002937 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2938
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002939 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002940 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002941
2942 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002943 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002944 return pypkcs7
2945
2946
Stephen Holsapple38482622014-04-05 20:29:34 -07002947def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002948 """
2949 Load a PKCS12 object from a buffer
2950
2951 :param buffer: The buffer the certificate is stored in
2952 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2953 :returns: The PKCS12 object
2954 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002955 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002956
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002957 if isinstance(buffer, _text_type):
2958 buffer = buffer.encode("ascii")
2959
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002960 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002961
Stephen Holsapple38482622014-04-05 20:29:34 -07002962 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2963 # password based encryption no password and a zero length password are two
2964 # different things, but OpenSSL implementation will try both to figure out
2965 # which one works.
2966 if not passphrase:
2967 passphrase = _ffi.NULL
2968
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002969 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2970 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002971 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002972 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002973
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002974 pkey = _ffi.new("EVP_PKEY**")
2975 cert = _ffi.new("X509**")
2976 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002977
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002978 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002979 if not parse_result:
2980 _raise_current_error()
2981
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002982 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002983
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002984 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
2985 # queue for no particular reason. This error isn't interesting to anyone
2986 # outside this function. It's not even interesting to us. Get rid of it.
2987 try:
2988 _raise_current_error()
2989 except Error:
2990 pass
2991
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002992 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002993 pykey = None
2994 else:
2995 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002996 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002997
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002998 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002999 pycert = None
3000 friendlyname = None
3001 else:
3002 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003003 pycert._x509 = _ffi.gc(cert[0], _lib.X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003004
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003005 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04003006 friendlyname_buffer = _lib.X509_alias_get0(
3007 cert[0], friendlyname_length
3008 )
3009 friendlyname = _ffi.buffer(
3010 friendlyname_buffer, friendlyname_length[0]
3011 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003012 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003013 friendlyname = None
3014
3015 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003016 for i in range(_lib.sk_X509_num(cacerts)):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003017 pycacert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003018 pycacert._x509 = _lib.sk_X509_value(cacerts, i)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003019 pycacerts.append(pycacert)
3020 if not pycacerts:
3021 pycacerts = None
3022
3023 pkcs12 = PKCS12.__new__(PKCS12)
3024 pkcs12._pkey = pykey
3025 pkcs12._cert = pycert
3026 pkcs12._cacerts = pycacerts
3027 pkcs12._friendlyname = friendlyname
3028 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05003029
3030
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05003031# There are no direct unit tests for this initialization. It is tested
3032# indirectly since it is necessary for functions like dump_privatekey when
3033# using encryption.
3034#
3035# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
3036# and some other similar tests may fail without this (though they may not if
3037# the Python runtime has already done some initialization of the underlying
3038# OpenSSL library (and is linked against the same one that cryptography is
3039# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05003040_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05003041
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05003042# This is similar but exercised mainly by exception_from_error_queue. It calls
3043# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
3044_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003045
3046
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003047# Set the default string mask to match OpenSSL upstream (since 2005) and
3048# RFC5280 recommendations.
3049_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')