blob: e58a4553864483e58a7964b29fb98fd8e5f60e0d [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):
Alex Gaynord61c46a2017-06-29 22:51:33 -0700742 names = _ffi.cast(
743 "GENERAL_NAMES*", _lib.X509V3_EXT_d2i(self._extension)
744 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400745
Paul Kehrerb7d79502015-05-04 07:43:51 -0500746 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400747 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500748 for i in range(_lib.sk_GENERAL_NAME_num(names)):
749 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400750 try:
751 label = self._prefixes[name.type]
752 except KeyError:
753 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500754 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500755 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400756 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500757 value = _native(
758 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
759 parts.append(label + ":" + value)
760 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400761
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800762 def __str__(self):
763 """
764 :return: a nice text representation of the extension
765 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500766 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400767 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800768
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400769 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500770 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400771 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800772
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500773 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800774
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800775 def get_critical(self):
776 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200777 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800778
779 :return: The critical field.
780 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500781 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800782
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800783 def get_short_name(self):
784 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200785 Returns the short type name of this X.509 extension.
786
787 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800788
789 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200790 :rtype: :py:data:`bytes`
791
792 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800793 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500794 obj = _lib.X509_EXTENSION_get_object(self._extension)
795 nid = _lib.OBJ_obj2nid(obj)
796 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800797
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800798 def get_data(self):
799 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200800 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800801
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200802 :return: The ASN.1 encoded data of this X509 extension.
803 :rtype: :py:data:`bytes`
804
805 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800806 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500807 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
808 string_result = _ffi.cast('ASN1_STRING*', octet_result)
809 char_result = _lib.ASN1_STRING_data(string_result)
810 result_length = _lib.ASN1_STRING_length(string_result)
811 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800812
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200813
Alex Gaynor10d30832017-06-29 15:31:39 -0700814X509ExtensionType = deprecated(
815 X509Extension, __name__,
816 "X509ExtensionType has been deprecated, use X509Extension instead",
817 DeprecationWarning
818)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800819
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800820
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800821class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200822 """
823 An X.509 certificate signing requests.
824 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400825
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800826 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500827 req = _lib.X509_REQ_new()
828 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Alex Gaynor5af32d02016-09-24 01:52:21 -0400829 # Default to version 0.
830 self.set_version(0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800831
Paul Kehrer41c10242017-06-29 18:24:17 -0500832 def to_cryptography(self):
833 """
834 Export as a ``cryptography`` certificate signing request.
835
836 :rtype: ``cryptography.x509.CertificateSigningRequest``
837
838 .. versionadded:: 17.1.0
839 """
840 from cryptography.hazmat.backends.openssl.x509 import (
841 _CertificateSigningRequest
842 )
843 backend = _get_backend()
844 return _CertificateSigningRequest(backend, self._req)
845
846 @classmethod
847 def from_cryptography(cls, crypto_req):
848 """
849 Construct based on a ``cryptography`` *crypto_req*.
850
851 :param crypto_req: A ``cryptography`` X.509 certificate signing request
852 :type crypto_req: ``cryptography.x509.CertificateSigningRequest``
853
854 :rtype: PKey
855
856 .. versionadded:: 17.1.0
857 """
858 if not isinstance(crypto_req, x509.CertificateSigningRequest):
859 raise TypeError("Must be a certificate signing request")
860
861 req = cls()
862 req._req = crypto_req._x509_req
863 return req
864
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800865 def set_pubkey(self, pkey):
866 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200867 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800868
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200869 :param pkey: The public key to use.
870 :type pkey: :py:class:`PKey`
871
Dan Sully44e767a2016-06-04 18:05:27 -0700872 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800873 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500874 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400875 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800876
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800877 def get_pubkey(self):
878 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200879 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800880
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200881 :return: The public key.
882 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800883 """
884 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500885 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700886 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500887 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800888 pkey._only_public = True
889 return pkey
890
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800891 def set_version(self, version):
892 """
893 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
894 request.
895
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200896 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700897 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800898 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500899 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400900 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800901
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800902 def get_version(self):
903 """
904 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
905 request.
906
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200907 :return: The value of the version subfield.
908 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800909 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500910 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800911
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800912 def get_subject(self):
913 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200914 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800915
Cory Benfield881dc8d2015-12-09 08:25:14 +0000916 This creates a new :class:`X509Name` that wraps the underlying subject
917 name field on the certificate signing request. Modifying it will modify
918 the underlying signing request, and will have the effect of modifying
919 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200920
921 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000922 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800923 """
924 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500925 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700926 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800927
928 # The name is owned by the X509Req structure. As long as the X509Name
929 # Python object is alive, keep the X509Req Python object alive.
930 name._owner = self
931
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800932 return name
933
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800934 def add_extensions(self, extensions):
935 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200936 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800937
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200938 :param extensions: The X.509 extensions to add.
939 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700940 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800941 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500942 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700943 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800944
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500945 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800946
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800947 for ext in extensions:
948 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -0800949 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800950
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800951 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500952 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800953
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500954 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400955 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800956
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800957 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800958 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200959 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800960
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200961 :return: The X.509 extensions in this request.
962 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
963
964 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800965 """
966 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500967 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -0500968 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800969 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500970 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800971 exts.append(ext)
972 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800973
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800974 def sign(self, pkey, digest):
975 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -0700976 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800977
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200978 :param pkey: The key pair to sign with.
979 :type pkey: :py:class:`PKey`
980 :param digest: The name of the message digest to use for the signature,
Alex Gaynor239e2d32016-09-11 12:36:35 -0400981 e.g. :py:data:`b"sha256"`.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200982 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -0700983 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800984 """
985 if pkey._only_public:
986 raise ValueError("Key has only public part")
987
988 if not pkey._initialized:
989 raise ValueError("Key is uninitialized")
990
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500991 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500992 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800993 raise ValueError("No such digest method")
994
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500995 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400996 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800997
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800998 def verify(self, pkey):
999 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001000 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001001
Hynek Schlawack01c31672016-12-11 15:14:09 +01001002 :param PKey key: A public key.
1003
1004 :return: ``True`` if the signature is correct.
1005 :rtype: bool
1006
1007 :raises OpenSSL.crypto.Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001008 problem verifying the signature.
1009 """
1010 if not isinstance(pkey, PKey):
1011 raise TypeError("pkey must be a PKey instance")
1012
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001013 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001014 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001015 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001016
1017 return result
1018
1019
Alex Gaynor10d30832017-06-29 15:31:39 -07001020X509ReqType = deprecated(
1021 X509Req, __name__,
1022 "X509ReqType has been deprecated, use X509Req instead",
1023 DeprecationWarning
1024)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001025
1026
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001027class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001028 """
1029 An X.509 certificate.
1030 """
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001031 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001032 x509 = _lib.X509_new()
Hynek Schlawack8a2dd772016-07-31 13:46:20 +02001033 _openssl_assert(x509 != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001034 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001035
Alex Gaynor9939ba12017-06-25 16:28:24 -04001036 def to_cryptography(self):
1037 """
1038 Export as a ``cryptography`` certificate.
1039
1040 :rtype: ``cryptography.x509.Certificate``
1041
1042 .. versionadded:: 17.1.0
1043 """
1044 from cryptography.hazmat.backends.openssl.x509 import _Certificate
1045 backend = _get_backend()
1046 return _Certificate(backend, self._x509)
1047
1048 @classmethod
1049 def from_cryptography(cls, crypto_cert):
1050 """
1051 Construct based on a ``cryptography`` *crypto_cert*.
1052
1053 :param crypto_key: A ``cryptography`` X.509 certificate.
1054 :type crypto_key: ``cryptography.x509.Certificate``
1055
1056 :rtype: PKey
1057
1058 .. versionadded:: 17.1.0
1059 """
1060 if not isinstance(crypto_cert, x509.Certificate):
1061 raise TypeError("Must be a certificate")
1062
1063 cert = cls()
1064 cert._x509 = crypto_cert._x509
1065 return cert
1066
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001067 def set_version(self, version):
1068 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001069 Set the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001070
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001071 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001072 :type version: :py:class:`int`
1073
Dan Sully44e767a2016-06-04 18:05:27 -07001074 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001075 """
1076 if not isinstance(version, int):
1077 raise TypeError("version must be an integer")
1078
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001079 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001080
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001081 def get_version(self):
1082 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001083 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001084
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001085 :return: The version number of the certificate.
1086 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001087 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001088 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001089
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001090 def get_pubkey(self):
1091 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001092 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001093
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001094 :return: The public key.
1095 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001096 """
1097 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001098 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1099 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001100 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001101 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001102 pkey._only_public = True
1103 return pkey
1104
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001105 def set_pubkey(self, pkey):
1106 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001107 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001108
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001109 :param pkey: The public key.
1110 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001111
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001112 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001113 """
1114 if not isinstance(pkey, PKey):
1115 raise TypeError("pkey must be a PKey instance")
1116
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001117 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001118 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001119
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001120 def sign(self, pkey, digest):
1121 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001122 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001123
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001124 :param pkey: The key to sign with.
1125 :type pkey: :py:class:`PKey`
1126
1127 :param digest: The name of the message digest to use.
1128 :type digest: :py:class:`bytes`
1129
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001130 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001131 """
1132 if not isinstance(pkey, PKey):
1133 raise TypeError("pkey must be a PKey instance")
1134
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001135 if pkey._only_public:
1136 raise ValueError("Key only has public part")
1137
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001138 if not pkey._initialized:
1139 raise ValueError("Key is uninitialized")
1140
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001141 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001142 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001143 raise ValueError("No such digest method")
1144
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001145 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001146 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001147
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001148 def get_signature_algorithm(self):
1149 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001150 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001151
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001152 :return: The name of the algorithm.
1153 :rtype: :py:class:`bytes`
1154
1155 :raises ValueError: If the signature algorithm is undefined.
1156
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001157 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001158 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001159 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1160 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001161 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001162 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001163 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001164
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001165 def digest(self, digest_name):
1166 """
1167 Return the digest of the X509 object.
1168
1169 :param digest_name: The name of the digest algorithm to use.
1170 :type digest_name: :py:class:`bytes`
1171
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001172 :return: The digest of the object, formatted as
1173 :py:const:`b":"`-delimited hex pairs.
1174 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001175 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001176 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001177 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001178 raise ValueError("No such digest method")
1179
Paul Kehrer9f9113a2016-09-20 20:10:25 -05001180 result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001181 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001182 result_length[0] = len(result_buffer)
1183
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001184 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001185 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001186 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001187
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001188 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001189 b16encode(ch).upper() for ch
1190 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001191
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001192 def subject_name_hash(self):
1193 """
1194 Return the hash of the X509 subject.
1195
1196 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001197 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001198 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001199 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001200
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001201 def set_serial_number(self, serial):
1202 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001203 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001204
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001205 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001206 :type serial: :py:class:`int`
1207
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001208 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001209 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001210 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001211 raise TypeError("serial must be an integer")
1212
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001213 hex_serial = hex(serial)[2:]
1214 if not isinstance(hex_serial, bytes):
1215 hex_serial = hex_serial.encode('ascii')
1216
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001217 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001218
1219 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001220 # it. If bignum is still NULL after this call, then the return value
1221 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001222 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001223
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001224 if bignum_serial[0] == _ffi.NULL:
1225 set_result = _lib.ASN1_INTEGER_set(
1226 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001227 if set_result:
1228 # TODO Not tested
1229 _raise_current_error()
1230 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001231 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1232 _lib.BN_free(bignum_serial[0])
1233 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001234 # TODO Not tested
1235 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001236 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1237 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001238 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001239
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001240 def get_serial_number(self):
1241 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001242 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001243
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001244 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001245 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001246 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001247 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1248 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001249 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001250 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001251 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001252 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001253 serial = int(hexstring_serial, 16)
1254 return serial
1255 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001256 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001257 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001258 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001259
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001260 def gmtime_adj_notAfter(self, amount):
1261 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001262 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001263
Dan Sully44e767a2016-06-04 18:05:27 -07001264 :param int amount: The number of seconds by which to adjust the
1265 timestamp.
1266 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001267 """
1268 if not isinstance(amount, int):
1269 raise TypeError("amount must be an integer")
1270
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001271 notAfter = _lib.X509_get_notAfter(self._x509)
1272 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001273
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001274 def gmtime_adj_notBefore(self, amount):
1275 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001276 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001277
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001278 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001279 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001280 """
1281 if not isinstance(amount, int):
1282 raise TypeError("amount must be an integer")
1283
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001284 notBefore = _lib.X509_get_notBefore(self._x509)
1285 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001286
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001287 def has_expired(self):
1288 """
1289 Check whether the certificate has expired.
1290
Dan Sully44e767a2016-06-04 18:05:27 -07001291 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1292 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001293 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001294 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001295 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001296
Paul Kehrerfde45c92016-01-21 12:57:37 -06001297 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001298
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001299 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001300 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001301
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001302 def get_notBefore(self):
1303 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001304 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001305
Paul Kehrerce98ee62017-06-21 06:59:58 -10001306 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001307
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001308 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001309
Dan Sully44e767a2016-06-04 18:05:27 -07001310 :return: A timestamp string, or ``None`` if there is none.
1311 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001312 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001313 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001314
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001315 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001316 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001317
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001318 def set_notBefore(self, when):
1319 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001320 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001321
Paul Kehrerce98ee62017-06-21 06:59:58 -10001322 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001323
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001324 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001325
Dan Sully44e767a2016-06-04 18:05:27 -07001326 :param bytes when: A timestamp string.
1327 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001328 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001329 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001330
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001331 def get_notAfter(self):
1332 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001333 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001334
Paul Kehrerce98ee62017-06-21 06:59:58 -10001335 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001336
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001337 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001338
Dan Sully44e767a2016-06-04 18:05:27 -07001339 :return: A timestamp string, or ``None`` if there is none.
1340 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001341 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001342 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001343
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001344 def set_notAfter(self, when):
1345 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001346 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001347
Paul Kehrerce98ee62017-06-21 06:59:58 -10001348 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001349
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001350 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001351
Dan Sully44e767a2016-06-04 18:05:27 -07001352 :param bytes when: A timestamp string.
1353 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001354 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001355 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001356
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001357 def _get_name(self, which):
1358 name = X509Name.__new__(X509Name)
1359 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001360 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001361
1362 # The name is owned by the X509 structure. As long as the X509Name
1363 # Python object is alive, keep the X509 Python object alive.
1364 name._owner = self
1365
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001366 return name
1367
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001368 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001369 if not isinstance(name, X509Name):
1370 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001371 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001372 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001373
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001374 def get_issuer(self):
1375 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001376 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001377
Cory Benfielde6bcce82015-12-09 08:40:03 +00001378 This creates a new :class:`X509Name` that wraps the underlying issuer
1379 name field on the certificate. Modifying it will modify the underlying
1380 certificate, and will have the effect of modifying any other
1381 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001382
1383 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001384 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001385 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001386 return self._get_name(_lib.X509_get_issuer_name)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001387
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001388 def set_issuer(self, issuer):
1389 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001390 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001391
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001392 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001393 :type issuer: :py:class:`X509Name`
1394
Dan Sully44e767a2016-06-04 18:05:27 -07001395 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001396 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001397 return self._set_name(_lib.X509_set_issuer_name, issuer)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001398
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001399 def get_subject(self):
1400 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001401 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001402
Cory Benfielde6bcce82015-12-09 08:40:03 +00001403 This creates a new :class:`X509Name` that wraps the underlying subject
1404 name field on the certificate. Modifying it will modify the underlying
1405 certificate, and will have the effect of modifying any other
1406 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001407
1408 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001409 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001410 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001411 return self._get_name(_lib.X509_get_subject_name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001412
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001413 def set_subject(self, subject):
1414 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001415 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001416
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001417 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001418 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001419
Dan Sully44e767a2016-06-04 18:05:27 -07001420 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001421 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001422 return self._set_name(_lib.X509_set_subject_name, subject)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001423
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001424 def get_extension_count(self):
1425 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001426 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001427
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001428 :return: The number of extensions.
1429 :rtype: :py:class:`int`
1430
1431 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001432 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001433 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001434
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001435 def add_extensions(self, extensions):
1436 """
1437 Add extensions to the certificate.
1438
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001439 :param extensions: The extensions to add.
1440 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001441 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001442 """
1443 for ext in extensions:
1444 if not isinstance(ext, X509Extension):
1445 raise ValueError("One of the elements is not an X509Extension")
1446
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001447 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001448 if not add_result:
1449 _raise_current_error()
1450
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001451 def get_extension(self, index):
1452 """
1453 Get a specific extension of the certificate by index.
1454
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001455 Extensions on a certificate are kept in order. The index
1456 parameter selects which extension will be returned.
1457
1458 :param int index: The index of the extension to retrieve.
1459 :return: The extension at the specified index.
1460 :rtype: :py:class:`X509Extension`
1461 :raises IndexError: If the extension index was out of bounds.
1462
1463 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001464 """
1465 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001466 ext._extension = _lib.X509_get_ext(self._x509, index)
1467 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001468 raise IndexError("extension index out of bounds")
1469
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001470 extension = _lib.X509_EXTENSION_dup(ext._extension)
1471 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001472 return ext
1473
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001474
Alex Gaynor10d30832017-06-29 15:31:39 -07001475X509Type = deprecated(
1476 X509, __name__,
1477 "X509Type has been deprecated, use X509 instead",
1478 DeprecationWarning
1479)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001480
1481
Dan Sully44e767a2016-06-04 18:05:27 -07001482class X509StoreFlags(object):
1483 """
1484 Flags for X509 verification, used to change the behavior of
1485 :class:`X509Store`.
1486
1487 See `OpenSSL Verification Flags`_ for details.
1488
1489 .. _OpenSSL Verification Flags:
Alex Chan54005ce2017-03-21 08:08:17 +00001490 https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_flags.html
Dan Sully44e767a2016-06-04 18:05:27 -07001491 """
1492 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1493 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1494 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1495 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1496 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1497 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1498 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1499 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1500 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1501 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1502 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1503
1504
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001505class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001506 """
Dan Sully44e767a2016-06-04 18:05:27 -07001507 An X.509 store.
1508
1509 An X.509 store is used to describe a context in which to verify a
1510 certificate. A description of a context may include a set of certificates
1511 to trust, a set of certificate revocation lists, verification flags and
1512 more.
1513
1514 An X.509 store, being only a description, cannot be used by itself to
1515 verify a certificate. To carry out the actual verification process, see
1516 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001517 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001518
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001519 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001520 store = _lib.X509_STORE_new()
1521 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001522
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001523 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001524 """
Dan Sully44e767a2016-06-04 18:05:27 -07001525 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001526
Dan Sully44e767a2016-06-04 18:05:27 -07001527 Adding a certificate with this method adds this certificate as a
1528 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001529
1530 :param X509 cert: The certificate to add to this store.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001531
Dan Sully44e767a2016-06-04 18:05:27 -07001532 :raises TypeError: If the certificate is not an :class:`X509`.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001533
1534 :raises OpenSSL.crypto.Error: If OpenSSL was unhappy with your
1535 certificate.
1536
Dan Sully44e767a2016-06-04 18:05:27 -07001537 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001538 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001539 if not isinstance(cert, X509):
1540 raise TypeError()
1541
Dan Sully44e767a2016-06-04 18:05:27 -07001542 _openssl_assert(_lib.X509_STORE_add_cert(self._store, cert._x509) != 0)
1543
1544 def add_crl(self, crl):
1545 """
1546 Add a certificate revocation list to this store.
1547
1548 The certificate revocation lists added to a store will only be used if
1549 the associated flags are configured to check certificate revocation
1550 lists.
1551
1552 .. versionadded:: 16.1.0
1553
1554 :param CRL crl: The certificate revocation list to add to this store.
1555 :return: ``None`` if the certificate revocation list was added
1556 successfully.
1557 """
1558 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1559
1560 def set_flags(self, flags):
1561 """
1562 Set verification flags to this store.
1563
1564 Verification flags can be combined by oring them together.
1565
1566 .. note::
1567
1568 Setting a verification flag sometimes requires clients to add
1569 additional information to the store, otherwise a suitable error will
1570 be raised.
1571
1572 For example, in setting flags to enable CRL checking a
1573 suitable CRL must be added to the store otherwise an error will be
1574 raised.
1575
1576 .. versionadded:: 16.1.0
1577
1578 :param int flags: The verification flags to set on this store.
1579 See :class:`X509StoreFlags` for available constants.
1580 :return: ``None`` if the verification flags were successfully set.
1581 """
1582 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001583
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001584 def set_time(self, vfy_time):
1585 """
1586 Set the time against which the certificates are verified.
1587
1588 Normally the current time is used.
1589
1590 .. note::
1591
1592 For example, you can determine if a certificate was valid at a given
1593 time.
1594
Hynek Schlawackf6c96af2017-04-20 12:34:58 +02001595 .. versionadded:: 17.0.0
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001596
1597 :param datetime vfy_time: The verification time to set on this store.
1598 :return: ``None`` if the verification time was successfully set.
1599 """
1600 param = _lib.X509_VERIFY_PARAM_new()
1601 param = _ffi.gc(param, _lib.X509_VERIFY_PARAM_free)
1602
1603 _lib.X509_VERIFY_PARAM_set_time(param, int(vfy_time.strftime('%s')))
1604 _openssl_assert(_lib.X509_STORE_set1_param(self._store, param) != 0)
1605
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001606
Alex Gaynor10d30832017-06-29 15:31:39 -07001607X509StoreType = deprecated(
1608 X509Store, __name__,
1609 "X509StoreType has been deprecated, use X509Store instead",
1610 DeprecationWarning
1611)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001612
1613
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001614class X509StoreContextError(Exception):
1615 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001616 An exception raised when an error occurred while verifying a certificate
1617 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001618
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001619 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001620 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001621 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001622
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001623 def __init__(self, message, certificate):
1624 super(X509StoreContextError, self).__init__(message)
1625 self.certificate = certificate
1626
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001627
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001628class X509StoreContext(object):
1629 """
1630 An X.509 store context.
1631
Dan Sully44e767a2016-06-04 18:05:27 -07001632 An X.509 store context is used to carry out the actual verification process
1633 of a certificate in a described context. For describing such a context, see
1634 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001635
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001636 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1637 instance. It is dynamically allocated and automatically garbage
1638 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001639 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001640 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001641 :param X509Store store: The certificates which will be trusted for the
1642 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001643 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001644 """
1645
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001646 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001647 store_ctx = _lib.X509_STORE_CTX_new()
1648 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1649 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001650 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001651 # Make the store context available for use after instantiating this
1652 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001653 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001654 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001655
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001656 def _init(self):
1657 """
1658 Set up the store context for a subsequent verification operation.
1659 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001660 ret = _lib.X509_STORE_CTX_init(
1661 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1662 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001663 if ret <= 0:
1664 _raise_current_error()
1665
1666 def _cleanup(self):
1667 """
1668 Internally cleans up the store context.
1669
Dan Sully44e767a2016-06-04 18:05:27 -07001670 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001671 """
1672 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1673
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001674 def _exception_from_context(self):
1675 """
1676 Convert an OpenSSL native context error failure into a Python
1677 exception.
1678
Alex Gaynor5945ea82015-09-05 14:59:06 -04001679 When a call to native OpenSSL X509_verify_cert fails, additional
1680 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001681 """
1682 errors = [
1683 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1684 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1685 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001686 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001687 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001688 # A context error should always be associated with a certificate, so we
1689 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001690 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001691 _cert = _lib.X509_dup(_x509)
1692 pycert = X509.__new__(X509)
1693 pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001694 return X509StoreContextError(errors, pycert)
1695
Stephen Holsapple46a09252015-02-12 14:45:43 -08001696 def set_store(self, store):
1697 """
Dan Sully44e767a2016-06-04 18:05:27 -07001698 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001699
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001700 .. versionadded:: 0.15
1701
Dan Sully44e767a2016-06-04 18:05:27 -07001702 :param X509Store store: The store description which will be used for
1703 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001704 """
1705 self._store = store
1706
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001707 def verify_certificate(self):
1708 """
1709 Verify a certificate in a context.
1710
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001711 .. versionadded:: 0.15
1712
Alex Gaynorca87ff62015-09-04 23:31:03 -04001713 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001714 certificate in the context. Sets ``certificate`` attribute to
1715 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001716 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001717 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001718 # :meth:`verify_certificate` is called multiple times.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001719 self._init()
1720 ret = _lib.X509_verify_cert(self._store_ctx)
1721 self._cleanup()
1722 if ret <= 0:
1723 raise self._exception_from_context()
1724
1725
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001726def load_certificate(type, buffer):
1727 """
1728 Load a certificate from a buffer
1729
1730 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1731
Dan Sully44e767a2016-06-04 18:05:27 -07001732 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001733
1734 :return: The X509 object
1735 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001736 if isinstance(buffer, _text_type):
1737 buffer = buffer.encode("ascii")
1738
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001739 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001740
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001741 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001742 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001743 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001744 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001745 else:
1746 raise ValueError(
1747 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001748
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001749 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001750 _raise_current_error()
1751
1752 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001753 cert._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001754 return cert
1755
1756
1757def dump_certificate(type, cert):
1758 """
1759 Dump a certificate to a buffer
1760
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001761 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1762 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001763 :param cert: The certificate to dump
1764 :return: The buffer with the dumped certificate in
1765 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001766 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001767
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001768 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001769 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001770 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001771 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001772 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001773 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001774 else:
1775 raise ValueError(
1776 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1777 "FILETYPE_TEXT")
1778
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001779 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001780 return _bio_to_string(bio)
1781
1782
Cory Benfield6492f7c2015-10-27 16:57:58 +09001783def dump_publickey(type, pkey):
1784 """
Cory Benfield11c10192015-10-27 17:23:03 +09001785 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001786
Cory Benfield9c590b92015-10-28 14:55:05 +09001787 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001788 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001789 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001790 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001791 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001792 """
1793 bio = _new_mem_buf()
1794 if type == FILETYPE_PEM:
1795 write_bio = _lib.PEM_write_bio_PUBKEY
1796 elif type == FILETYPE_ASN1:
1797 write_bio = _lib.i2d_PUBKEY_bio
1798 else:
1799 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1800
1801 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001802 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001803 _raise_current_error()
1804
1805 return _bio_to_string(bio)
1806
1807
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001808def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1809 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001810 Dump the private key *pkey* into a buffer string encoded with the type
1811 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1812 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001813
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001814 :param type: The file type (one of :const:`FILETYPE_PEM`,
1815 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1816 :param PKey pkey: The PKey to dump
1817 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001818 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001819 the passphrase to use, or a callback for providing the passphrase.
1820
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001821 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001822 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001823 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001824 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001825
Paul Kehrercded9932017-06-29 18:43:42 -05001826 if not isinstance(pkey, PKey):
1827 raise TypeError("pkey must be a PKey")
1828
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001829 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001830 if passphrase is None:
1831 raise TypeError(
1832 "if a value is given for cipher "
1833 "one must also be given for passphrase")
1834 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001835 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001836 raise ValueError("Invalid cipher name")
1837 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001838 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001839
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001840 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001841 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001842 result_code = _lib.PEM_write_bio_PrivateKey(
1843 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001844 helper.callback, helper.callback_args)
1845 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001846 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001847 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001848 elif type == FILETYPE_TEXT:
Paul Kehrercded9932017-06-29 18:43:42 -05001849 if _lib.EVP_PKEY_id(pkey._pkey) != _lib.EVP_PKEY_RSA:
1850 raise TypeError("Only RSA keys are supported for FILETYPE_TEXT")
1851
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001852 rsa = _ffi.gc(
1853 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1854 _lib.RSA_free
1855 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001856 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001857 else:
1858 raise ValueError(
1859 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1860 "FILETYPE_TEXT")
1861
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001862 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001863
1864 return _bio_to_string(bio)
1865
1866
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001867class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001868 """
1869 A certificate revocation.
1870 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001871 # http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_
1872 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1873 # OCSP_crl_reason_str. We use the latter, just like the command line
1874 # program.
1875 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001876 b"unspecified",
1877 b"keyCompromise",
1878 b"CACompromise",
1879 b"affiliationChanged",
1880 b"superseded",
1881 b"cessationOfOperation",
1882 b"certificateHold",
1883 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001884 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001885
1886 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001887 revoked = _lib.X509_REVOKED_new()
1888 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001889
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001890 def set_serial(self, hex_str):
1891 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001892 Set the serial number.
1893
1894 The serial number is formatted as a hexadecimal number encoded in
1895 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001896
Dan Sully44e767a2016-06-04 18:05:27 -07001897 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001898
Dan Sully44e767a2016-06-04 18:05:27 -07001899 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001900 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001901 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1902 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001903 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001904 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001905 if not bn_result:
1906 raise ValueError("bad hex string")
1907
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001908 asn1_serial = _ffi.gc(
1909 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1910 _lib.ASN1_INTEGER_free)
1911 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001912
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001913 def get_serial(self):
1914 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001915 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001916
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001917 The serial number is formatted as a hexadecimal number encoded in
1918 ASCII.
1919
1920 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001921 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001922 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001923 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001924
Alex Gaynor67903a62016-06-02 10:37:13 -07001925 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1926 _openssl_assert(asn1_int != _ffi.NULL)
1927 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1928 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001929 return _bio_to_string(bio)
1930
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001931 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001932 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1933 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001934 obj = _lib.X509_EXTENSION_get_object(ext)
1935 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001936 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001937 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001938 break
1939
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001940 def set_reason(self, reason):
1941 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001942 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001943
Dan Sully44e767a2016-06-04 18:05:27 -07001944 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001945
1946 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07001947 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001948
Dan Sully44e767a2016-06-04 18:05:27 -07001949 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001950
1951 .. seealso::
1952
Dan Sully44e767a2016-06-04 18:05:27 -07001953 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001954 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001955 """
1956 if reason is None:
1957 self._delete_reason()
1958 elif not isinstance(reason, bytes):
1959 raise TypeError("reason must be None or a byte string")
1960 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001961 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001962 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
1963
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001964 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07001965 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001966 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001967
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001968 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001969 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001970
1971 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001972 add_result = _lib.X509_REVOKED_add1_ext_i2d(
1973 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001974 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001975
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001976 def get_reason(self):
1977 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04001978 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001979
Dan Sully44e767a2016-06-04 18:05:27 -07001980 :return: The reason, or ``None`` if there is none.
1981 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001982
1983 .. seealso::
1984
Dan Sully44e767a2016-06-04 18:05:27 -07001985 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001986 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001987 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001988 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1989 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001990 obj = _lib.X509_EXTENSION_get_object(ext)
1991 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001992 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001993
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001994 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001995 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04001996 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001997 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04001998 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04001999 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002000
2001 return _bio_to_string(bio)
2002
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002003 def all_reasons(self):
2004 """
2005 Return a list of all the supported reason strings.
2006
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002007 This list is a copy; modifying it does not change the supported reason
2008 strings.
2009
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002010 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07002011 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002012 """
2013 return self._crl_reasons[:]
2014
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002015 def set_rev_date(self, when):
2016 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002017 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002018
Dan Sully44e767a2016-06-04 18:05:27 -07002019 :param bytes when: The timestamp of the revocation,
Paul Kehrerce98ee62017-06-21 06:59:58 -10002020 as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002021 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002022 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002023 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2024 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002025
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002026 def get_rev_date(self):
2027 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002028 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002029
Paul Kehrerce98ee62017-06-21 06:59:58 -10002030 :return: The timestamp of the revocation, as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002031 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002032 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002033 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2034 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002035
2036
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002037class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002038 """
2039 A certificate revocation list.
2040 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002041
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002042 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002043 crl = _lib.X509_CRL_new()
2044 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002045
Paul Kehrer41c10242017-06-29 18:24:17 -05002046 def to_cryptography(self):
2047 """
2048 Export as a ``cryptography`` CRL.
2049
2050 :rtype: ``cryptography.x509.CertificateRevocationList``
2051
2052 .. versionadded:: 17.1.0
2053 """
2054 from cryptography.hazmat.backends.openssl.x509 import (
2055 _CertificateRevocationList
2056 )
2057 backend = _get_backend()
2058 return _CertificateRevocationList(backend, self._crl)
2059
2060 @classmethod
2061 def from_cryptography(cls, crypto_crl):
2062 """
2063 Construct based on a ``cryptography`` *crypto_crl*.
2064
2065 :param crypto_crl: A ``cryptography`` certificate revocation list
2066 :type crypto_crl: ``cryptography.x509.CertificateRevocationList``
2067
2068 :rtype: CRL
2069
2070 .. versionadded:: 17.1.0
2071 """
2072 if not isinstance(crypto_crl, x509.CertificateRevocationList):
2073 raise TypeError("Must be a certificate revocation list")
2074
2075 crl = cls()
2076 crl._crl = crypto_crl._x509_crl
2077 return crl
2078
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002079 def get_revoked(self):
2080 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002081 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002082
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002083 These revocations will be provided by value, not by reference.
2084 That means it's okay to mutate them: it won't affect this CRL.
2085
2086 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002087 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002088 """
2089 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07002090 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002091 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
2092 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04002093 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002094 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002095 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002096 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002097 if results:
2098 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002099
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002100 def add_revoked(self, revoked):
2101 """
2102 Add a revoked (by value not reference) to the CRL structure
2103
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002104 This revocation will be added by value, not by reference. That
2105 means it's okay to mutate it after adding: it won't affect
2106 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002107
Dan Sully44e767a2016-06-04 18:05:27 -07002108 :param Revoked revoked: The new revocation.
2109 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002110 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04002111 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002112 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002113
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002114 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002115 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002116
Dan Sully44e767a2016-06-04 18:05:27 -07002117 def get_issuer(self):
2118 """
2119 Get the CRL's issuer.
2120
2121 .. versionadded:: 16.1.0
2122
2123 :rtype: X509Name
2124 """
2125 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
2126 _openssl_assert(_issuer != _ffi.NULL)
2127 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
2128 issuer = X509Name.__new__(X509Name)
2129 issuer._name = _issuer
2130 return issuer
2131
2132 def set_version(self, version):
2133 """
2134 Set the CRL version.
2135
2136 .. versionadded:: 16.1.0
2137
2138 :param int version: The version of the CRL.
2139 :return: ``None``
2140 """
2141 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2142
2143 def _set_boundary_time(self, which, when):
2144 return _set_asn1_time(which(self._crl), when)
2145
2146 def set_lastUpdate(self, when):
2147 """
2148 Set when the CRL was last updated.
2149
Paul Kehrerce98ee62017-06-21 06:59:58 -10002150 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002151
2152 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002153
2154 .. versionadded:: 16.1.0
2155
2156 :param bytes when: A timestamp string.
2157 :return: ``None``
2158 """
2159 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2160
2161 def set_nextUpdate(self, when):
2162 """
2163 Set when the CRL will next be udpated.
2164
Paul Kehrerce98ee62017-06-21 06:59:58 -10002165 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002166
2167 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002168
2169 .. versionadded:: 16.1.0
2170
2171 :param bytes when: A timestamp string.
2172 :return: ``None``
2173 """
2174 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2175
2176 def sign(self, issuer_cert, issuer_key, digest):
2177 """
2178 Sign the CRL.
2179
2180 Signing a CRL enables clients to associate the CRL itself with an
2181 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2182 be signed by an issuer.
2183
2184 This method implicitly sets the issuer's name based on the issuer
2185 certificate and private key used to sign the CRL.
2186
2187 .. versionadded:: 16.1.0
2188
2189 :param X509 issuer_cert: The issuer's certificate.
2190 :param PKey issuer_key: The issuer's private key.
2191 :param bytes digest: The digest method to sign the CRL with.
2192 """
2193 digest_obj = _lib.EVP_get_digestbyname(digest)
2194 _openssl_assert(digest_obj != _ffi.NULL)
2195 _lib.X509_CRL_set_issuer_name(
2196 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2197 _lib.X509_CRL_sort(self._crl)
2198 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2199 _openssl_assert(result != 0)
2200
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002201 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002202 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002203 """
Dan Sully44e767a2016-06-04 18:05:27 -07002204 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002205
Dan Sully44e767a2016-06-04 18:05:27 -07002206 :param X509 cert: The certificate used to sign the CRL.
2207 :param PKey key: The key used to sign the CRL.
2208 :param int type: The export format, either :data:`FILETYPE_PEM`,
2209 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002210 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002211 :param bytes digest: The name of the message digest to use (eg
Alex Gaynor239e2d32016-09-11 12:36:35 -04002212 ``b"sha2566"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002213 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002214 """
Dan Sully44e767a2016-06-04 18:05:27 -07002215
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002216 if not isinstance(cert, X509):
2217 raise TypeError("cert must be an X509 instance")
2218 if not isinstance(key, PKey):
2219 raise TypeError("key must be a PKey instance")
2220 if not isinstance(type, int):
2221 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002222
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002223 if digest is _UNSPECIFIED:
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002224 _warn(
2225 "The default message digest (md5) is deprecated. "
2226 "Pass the name of a message digest explicitly.",
2227 category=DeprecationWarning,
2228 stacklevel=2,
2229 )
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002230 digest = b"md5"
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002231
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002232 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002233 if digest_obj == _ffi.NULL:
2234 raise ValueError("No such digest method")
2235
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002236 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002237 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002238
Alex Gaynora738ed52015-09-05 11:17:10 -04002239 # A scratch time object to give different values to different CRL
2240 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002241 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002242 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002243
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002244 _lib.X509_gmtime_adj(sometime, 0)
2245 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002246
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002247 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2248 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002249
Alex Gaynor5945ea82015-09-05 14:59:06 -04002250 _lib.X509_CRL_set_issuer_name(
2251 self._crl, _lib.X509_get_subject_name(cert._x509)
2252 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002253
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002254 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002255 if not sign_result:
2256 _raise_current_error()
2257
Dominic Chenf05b2122015-10-13 16:32:35 +00002258 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002259
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002260
Alex Gaynor10d30832017-06-29 15:31:39 -07002261CRLType = deprecated(
2262 CRL, __name__,
2263 "CRLType has been deprecated, use CRL instead",
2264 DeprecationWarning
2265)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002266
2267
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002268class PKCS7(object):
2269 def type_is_signed(self):
2270 """
2271 Check if this NID_pkcs7_signed object
2272
2273 :return: True if the PKCS7 is of type signed
2274 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002275 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002276
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002277 def type_is_enveloped(self):
2278 """
2279 Check if this NID_pkcs7_enveloped object
2280
2281 :returns: True if the PKCS7 is of type enveloped
2282 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002283 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002284
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002285 def type_is_signedAndEnveloped(self):
2286 """
2287 Check if this NID_pkcs7_signedAndEnveloped object
2288
2289 :returns: True if the PKCS7 is of type signedAndEnveloped
2290 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002291 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002292
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002293 def type_is_data(self):
2294 """
2295 Check if this NID_pkcs7_data object
2296
2297 :return: True if the PKCS7 is of type data
2298 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002299 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002300
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002301 def get_type_name(self):
2302 """
2303 Returns the type name of the PKCS7 structure
2304
2305 :return: A string with the typename
2306 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002307 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2308 string_type = _lib.OBJ_nid2sn(nid)
2309 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002310
Alex Chanc6077062016-11-18 13:53:39 +00002311
Alex Gaynor10d30832017-06-29 15:31:39 -07002312PKCS7Type = deprecated(
2313 PKCS7, __name__,
2314 "PKCS7Type has been deprecated, use PKCS7 instead",
2315 DeprecationWarning
2316)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002317
2318
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002319class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002320 """
2321 A PKCS #12 archive.
2322 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002323
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002324 def __init__(self):
2325 self._pkey = None
2326 self._cert = None
2327 self._cacerts = None
2328 self._friendlyname = None
2329
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002330 def get_certificate(self):
2331 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002332 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002333
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002334 :return: The certificate, or :py:const:`None` if there is none.
2335 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002336 """
2337 return self._cert
2338
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002339 def set_certificate(self, cert):
2340 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002341 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002342
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002343 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002344 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002345
Dan Sully44e767a2016-06-04 18:05:27 -07002346 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002347 """
2348 if not isinstance(cert, X509):
2349 raise TypeError("cert must be an X509 instance")
2350 self._cert = cert
2351
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002352 def get_privatekey(self):
2353 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002354 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002355
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002356 :return: The private key, or :py:const:`None` if there is none.
2357 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002358 """
2359 return self._pkey
2360
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002361 def set_privatekey(self, pkey):
2362 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002363 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002364
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002365 :param pkey: The new private key, or :py:const:`None` to unset it.
2366 :type pkey: :py:class:`PKey` or :py:const:`None`
2367
Dan Sully44e767a2016-06-04 18:05:27 -07002368 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002369 """
2370 if not isinstance(pkey, PKey):
2371 raise TypeError("pkey must be a PKey instance")
2372 self._pkey = pkey
2373
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002374 def get_ca_certificates(self):
2375 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002376 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002377
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002378 :return: A tuple with the CA certificates in the chain, or
2379 :py:const:`None` if there are none.
2380 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002381 """
2382 if self._cacerts is not None:
2383 return tuple(self._cacerts)
2384
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002385 def set_ca_certificates(self, cacerts):
2386 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002387 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002388
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002389 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2390 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002391 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002392
Dan Sully44e767a2016-06-04 18:05:27 -07002393 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002394 """
2395 if cacerts is None:
2396 self._cacerts = None
2397 else:
2398 cacerts = list(cacerts)
2399 for cert in cacerts:
2400 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002401 raise TypeError(
2402 "iterable must only contain X509 instances"
2403 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002404 self._cacerts = cacerts
2405
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002406 def set_friendlyname(self, name):
2407 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002408 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002409
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002410 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002411 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002412
Dan Sully44e767a2016-06-04 18:05:27 -07002413 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002414 """
2415 if name is None:
2416 self._friendlyname = None
2417 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002418 raise TypeError(
2419 "name must be a byte string or None (not %r)" % (name,)
2420 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002421 self._friendlyname = name
2422
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002423 def get_friendlyname(self):
2424 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002425 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002426
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002427 :returns: The friendly name, or :py:const:`None` if there is none.
2428 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002429 """
2430 return self._friendlyname
2431
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002432 def export(self, passphrase=None, iter=2048, maciter=1):
2433 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002434 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002435
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002436 For more information, see the :c:func:`PKCS12_create` man page.
2437
2438 :param passphrase: The passphrase used to encrypt the structure. Unlike
2439 some other passphrase arguments, this *must* be a string, not a
2440 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002441 :type passphrase: :py:data:`bytes`
2442
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002443 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002444 :type iter: :py:data:`int`
2445
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002446 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002447 :type maciter: :py:data:`int`
2448
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002449 :return: The string representation of the PKCS #12 structure.
2450 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002451 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002452 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002453
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002454 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002455 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002456 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002457 cacerts = _lib.sk_X509_new_null()
2458 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002459 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002460 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002461
2462 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002463 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002464
2465 friendlyname = self._friendlyname
2466 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002467 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002468
2469 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002470 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002471 else:
2472 pkey = self._pkey._pkey
2473
2474 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002475 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002476 else:
2477 cert = self._cert._x509
2478
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002479 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002480 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002481 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2482 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002483 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002484 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002485 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002486 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002487
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002488 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002489 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002490 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002491
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002492
Alex Gaynor10d30832017-06-29 15:31:39 -07002493PKCS12Type = deprecated(
2494 PKCS12, __name__,
2495 "PKCS12Type has been deprecated, use PKCS12 instead",
2496 DeprecationWarning
2497)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002498
2499
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002500class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002501 """
2502 A Netscape SPKI object.
2503 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002504
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002505 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002506 spki = _lib.NETSCAPE_SPKI_new()
2507 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002508
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002509 def sign(self, pkey, digest):
2510 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002511 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002512
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002513 :param pkey: The private key to sign with.
2514 :type pkey: :py:class:`PKey`
2515
2516 :param digest: The message digest to use.
2517 :type digest: :py:class:`bytes`
2518
Dan Sully44e767a2016-06-04 18:05:27 -07002519 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002520 """
2521 if pkey._only_public:
2522 raise ValueError("Key has only public part")
2523
2524 if not pkey._initialized:
2525 raise ValueError("Key is uninitialized")
2526
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002527 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002528 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002529 raise ValueError("No such digest method")
2530
Alex Gaynor5945ea82015-09-05 14:59:06 -04002531 sign_result = _lib.NETSCAPE_SPKI_sign(
2532 self._spki, pkey._pkey, digest_obj
2533 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002534 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002535
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002536 def verify(self, key):
2537 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002538 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002539
Hynek Schlawack01c31672016-12-11 15:14:09 +01002540 :param PKey key: The public key that signature is supposedly from.
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002541
Hynek Schlawack01c31672016-12-11 15:14:09 +01002542 :return: ``True`` if the signature is correct.
2543 :rtype: bool
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002544
Hynek Schlawack01c31672016-12-11 15:14:09 +01002545 :raises OpenSSL.crypto.Error: If the signature is invalid, or there was
2546 a problem verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002547 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002548 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002549 if answer <= 0:
2550 _raise_current_error()
2551 return True
2552
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002553 def b64_encode(self):
2554 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002555 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002556
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002557 :return: The base64 encoded string.
2558 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002559 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002560 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2561 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002562 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002563 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002564
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002565 def get_pubkey(self):
2566 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002567 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002568
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002569 :return: The public key.
2570 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002571 """
2572 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002573 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002574 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002575 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002576 pkey._only_public = True
2577 return pkey
2578
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002579 def set_pubkey(self, pkey):
2580 """
2581 Set the public key of the certificate
2582
2583 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002584 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002585 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002586 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002587 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002588
2589
Alex Gaynor10d30832017-06-29 15:31:39 -07002590NetscapeSPKIType = deprecated(
2591 NetscapeSPKI, __name__,
2592 "NetscapeSPKIType has been deprecated, use NetscapeSPKI instead",
2593 DeprecationWarning
2594)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002595
2596
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002597class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002598 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002599 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002600 raise ValueError(
2601 "only FILETYPE_PEM key format supports encryption"
2602 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002603 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002604 self._more_args = more_args
2605 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002606 self._problems = []
2607
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002608 @property
2609 def callback(self):
2610 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002611 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002612 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002613 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002614 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002615 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002616 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002617 raise TypeError(
2618 "Last argument must be a byte string or a callable."
2619 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002620
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002621 @property
2622 def callback_args(self):
2623 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002624 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002625 elif isinstance(self._passphrase, bytes):
2626 return self._passphrase
2627 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002628 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002629 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002630 raise TypeError(
2631 "Last argument must be a byte string or a callable."
2632 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002633
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002634 def raise_if_problem(self, exceptionType=Error):
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002635 if self._problems:
Greg Bowser36eb2de2017-01-24 11:38:55 -05002636
2637 # Flush the OpenSSL error queue
2638 try:
2639 _exception_from_error_queue(exceptionType)
2640 except exceptionType:
2641 pass
2642
2643 raise self._problems.pop(0)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002644
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002645 def _read_passphrase(self, buf, size, rwflag, userdata):
2646 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002647 if self._more_args:
2648 result = self._passphrase(size, rwflag, userdata)
2649 else:
2650 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002651 if not isinstance(result, bytes):
2652 raise ValueError("String expected")
2653 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002654 if self._truncate:
2655 result = result[:size]
2656 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002657 raise ValueError(
2658 "passphrase returned by callback is too long"
2659 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002660 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002661 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002662 return len(result)
2663 except Exception as e:
2664 self._problems.append(e)
2665 return 0
2666
2667
Cory Benfield6492f7c2015-10-27 16:57:58 +09002668def load_publickey(type, buffer):
2669 """
Cory Benfield11c10192015-10-27 17:23:03 +09002670 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002671
Cory Benfield9c590b92015-10-28 14:55:05 +09002672 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002673 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002674 :param buffer: The buffer the key is stored in.
2675 :type buffer: A Python string object, either unicode or bytestring.
2676 :return: The PKey object.
2677 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002678 """
2679 if isinstance(buffer, _text_type):
2680 buffer = buffer.encode("ascii")
2681
2682 bio = _new_mem_buf(buffer)
2683
2684 if type == FILETYPE_PEM:
2685 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2686 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2687 elif type == FILETYPE_ASN1:
2688 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2689 else:
2690 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2691
2692 if evp_pkey == _ffi.NULL:
2693 _raise_current_error()
2694
2695 pkey = PKey.__new__(PKey)
2696 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002697 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002698 return pkey
2699
2700
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002701def load_privatekey(type, buffer, passphrase=None):
2702 """
2703 Load a private key from a buffer
2704
2705 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2706 :param buffer: The buffer the key is stored in
2707 :param passphrase: (optional) if encrypted PEM format, this can be
2708 either the passphrase to use, or a callback for
2709 providing the passphrase.
2710
2711 :return: The PKey object
2712 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002713 if isinstance(buffer, _text_type):
2714 buffer = buffer.encode("ascii")
2715
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002716 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002717
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002718 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002719 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002720 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2721 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002722 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002723 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002724 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002725 else:
2726 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2727
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002728 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002729 _raise_current_error()
2730
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002731 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002732 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002733 return pkey
2734
2735
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002736def dump_certificate_request(type, req):
2737 """
2738 Dump a certificate request to a buffer
2739
2740 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2741 :param req: The certificate request to dump
2742 :return: The buffer with the dumped certificate request in
2743 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002744 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002745
2746 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002747 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002748 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002749 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002750 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002751 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002752 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002753 raise ValueError(
2754 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2755 "FILETYPE_TEXT"
2756 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002757
Alex Gaynor09a386e2016-07-03 09:32:44 -04002758 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002759
2760 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002761
2762
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002763def load_certificate_request(type, buffer):
2764 """
2765 Load a certificate request from a buffer
2766
2767 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2768 :param buffer: The buffer the certificate request is stored in
2769 :return: The X509Req object
2770 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002771 if isinstance(buffer, _text_type):
2772 buffer = buffer.encode("ascii")
2773
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002774 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002775
2776 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002777 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002778 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002779 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002780 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002781 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002782
Alex Gaynoradd5b072016-06-04 21:04:00 -07002783 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002784
2785 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002786 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002787 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002788
2789
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002790def sign(pkey, data, digest):
2791 """
2792 Sign data with a digest
2793
2794 :param pkey: Pkey to sign with
2795 :param data: data to be signed
2796 :param digest: message digest to use
2797 :return: signature
2798 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002799 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002800
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002801 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002802 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002803 raise ValueError("No such digest method")
2804
Alex Gaynor67903a62016-06-02 10:37:13 -07002805 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002806 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002807
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002808 _lib.EVP_SignInit(md_ctx, digest_obj)
2809 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002810
Colleen Murphye09399b2016-03-01 17:40:49 -08002811 pkey_length = (PKey.bits(pkey) + 7) // 8
2812 signature_buffer = _ffi.new("unsigned char[]", pkey_length)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002813 signature_length = _ffi.new("unsigned int*")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002814 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002815 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002816 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002817
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002818 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002819
2820
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002821def verify(cert, signature, data, digest):
2822 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002823 Verify a signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002824
2825 :param cert: signing certificate (X509 object)
2826 :param signature: signature returned by sign function
2827 :param data: data to be verified
2828 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002829 :return: ``None`` if the signature is correct, raise exception otherwise.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002830 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002831 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002832
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002833 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002834 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002835 raise ValueError("No such digest method")
2836
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002837 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002838 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002839 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002840
Alex Gaynor67903a62016-06-02 10:37:13 -07002841 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002842 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002843
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002844 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2845 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002846 verify_result = _lib.EVP_VerifyFinal(
2847 md_ctx, signature, len(signature), pkey
2848 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002849
2850 if verify_result != 1:
2851 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002852
2853
Dominic Chenf05b2122015-10-13 16:32:35 +00002854def dump_crl(type, crl):
2855 """
2856 Dump a certificate revocation list to a buffer.
2857
2858 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2859 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002860 :param CRL crl: The CRL to dump.
2861
Dominic Chenf05b2122015-10-13 16:32:35 +00002862 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002863 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002864 """
2865 bio = _new_mem_buf()
2866
2867 if type == FILETYPE_PEM:
2868 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2869 elif type == FILETYPE_ASN1:
2870 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2871 elif type == FILETYPE_TEXT:
2872 ret = _lib.X509_CRL_print(bio, crl._crl)
2873 else:
2874 raise ValueError(
2875 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2876 "FILETYPE_TEXT")
2877
2878 assert ret == 1
2879 return _bio_to_string(bio)
2880
2881
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002882def load_crl(type, buffer):
2883 """
2884 Load a certificate revocation list from a buffer
2885
2886 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2887 :param buffer: The buffer the CRL is stored in
2888
2889 :return: The PKey object
2890 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002891 if isinstance(buffer, _text_type):
2892 buffer = buffer.encode("ascii")
2893
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002894 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002895
2896 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002897 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002898 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002899 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002900 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002901 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2902
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002903 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002904 _raise_current_error()
2905
2906 result = CRL.__new__(CRL)
2907 result._crl = crl
2908 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002909
2910
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002911def load_pkcs7_data(type, buffer):
2912 """
2913 Load pkcs7 data from a buffer
2914
2915 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2916 :param buffer: The buffer with the pkcs7 data.
2917 :return: The PKCS7 object
2918 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002919 if isinstance(buffer, _text_type):
2920 buffer = buffer.encode("ascii")
2921
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002922 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002923
2924 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002925 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002926 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002927 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002928 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002929 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2930
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002931 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002932 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002933
2934 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002935 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002936 return pypkcs7
2937
2938
Stephen Holsapple38482622014-04-05 20:29:34 -07002939def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002940 """
2941 Load a PKCS12 object from a buffer
2942
2943 :param buffer: The buffer the certificate is stored in
2944 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2945 :returns: The PKCS12 object
2946 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002947 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002948
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002949 if isinstance(buffer, _text_type):
2950 buffer = buffer.encode("ascii")
2951
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002952 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002953
Stephen Holsapple38482622014-04-05 20:29:34 -07002954 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2955 # password based encryption no password and a zero length password are two
2956 # different things, but OpenSSL implementation will try both to figure out
2957 # which one works.
2958 if not passphrase:
2959 passphrase = _ffi.NULL
2960
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002961 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2962 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002963 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002964 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002965
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002966 pkey = _ffi.new("EVP_PKEY**")
2967 cert = _ffi.new("X509**")
2968 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002969
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002970 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002971 if not parse_result:
2972 _raise_current_error()
2973
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002974 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002975
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002976 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
2977 # queue for no particular reason. This error isn't interesting to anyone
2978 # outside this function. It's not even interesting to us. Get rid of it.
2979 try:
2980 _raise_current_error()
2981 except Error:
2982 pass
2983
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002984 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002985 pykey = None
2986 else:
2987 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002988 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002989
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002990 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002991 pycert = None
2992 friendlyname = None
2993 else:
2994 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002995 pycert._x509 = _ffi.gc(cert[0], _lib.X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002996
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002997 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04002998 friendlyname_buffer = _lib.X509_alias_get0(
2999 cert[0], friendlyname_length
3000 )
3001 friendlyname = _ffi.buffer(
3002 friendlyname_buffer, friendlyname_length[0]
3003 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003004 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003005 friendlyname = None
3006
3007 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003008 for i in range(_lib.sk_X509_num(cacerts)):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003009 pycacert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003010 pycacert._x509 = _lib.sk_X509_value(cacerts, i)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003011 pycacerts.append(pycacert)
3012 if not pycacerts:
3013 pycacerts = None
3014
3015 pkcs12 = PKCS12.__new__(PKCS12)
3016 pkcs12._pkey = pykey
3017 pkcs12._cert = pycert
3018 pkcs12._cacerts = pycacerts
3019 pkcs12._friendlyname = friendlyname
3020 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05003021
3022
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05003023# There are no direct unit tests for this initialization. It is tested
3024# indirectly since it is necessary for functions like dump_privatekey when
3025# using encryption.
3026#
3027# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
3028# and some other similar tests may fail without this (though they may not if
3029# the Python runtime has already done some initialization of the underlying
3030# OpenSSL library (and is linked against the same one that cryptography is
3031# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05003032_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05003033
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05003034# This is similar but exercised mainly by exception_from_error_queue. It calls
3035# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
3036_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003037
3038
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003039# Set the default string mask to match OpenSSL upstream (since 2005) and
3040# RFC5280 recommendations.
3041_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')