blob: ba918cc2531068b339d05af780a982894bef7d2a [file] [log] [blame]
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001import datetime
Paul Kehrer8d887e12015-10-24 09:09:55 -05002
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003from base64 import b16encode
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05004from functools import partial
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05005from operator import __eq__, __ne__, __lt__, __le__, __gt__, __ge__
Jean-Paul Calderone60432792015-04-13 12:26:07 -04006from warnings import warn as _warn
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05007
8from six import (
9 integer_types as _integer_types,
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -040010 text_type as _text_type,
11 PY3 as _PY3)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080012
Alex Gaynor9939ba12017-06-25 16:28:24 -040013from cryptography import x509
Paul Kehrer72d968b2016-07-29 15:31:04 +080014from cryptography.hazmat.primitives.asymmetric import dsa, rsa
Alex Gaynor10d30832017-06-29 15:31:39 -070015from cryptography.utils import deprecated
Paul Kehrer72d968b2016-07-29 15:31:04 +080016
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050017from OpenSSL._util import (
18 ffi as _ffi,
19 lib as _lib,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050020 exception_from_error_queue as _exception_from_error_queue,
21 byte_string as _byte_string,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040022 native as _native,
23 UNSPECIFIED as _UNSPECIFIED,
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -040024 text_to_bytes_and_warn as _text_to_bytes_and_warn,
Alex Gaynor67903a62016-06-02 10:37:13 -070025 make_assert as _make_assert,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040026)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080027
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050028FILETYPE_PEM = _lib.SSL_FILETYPE_PEM
29FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080030
31# TODO This was an API mistake. OpenSSL has no such constant.
32FILETYPE_TEXT = 2 ** 16 - 1
33
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050034TYPE_RSA = _lib.EVP_PKEY_RSA
35TYPE_DSA = _lib.EVP_PKEY_DSA
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -080036
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080037
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050038class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050039 """
40 An error occurred in an `OpenSSL.crypto` API.
41 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050042
43
44_raise_current_error = partial(_exception_from_error_queue, Error)
Alex Gaynor67903a62016-06-02 10:37:13 -070045_openssl_assert = _make_assert(Error)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050046
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070047
Paul Kehrereb633842016-10-06 11:22:01 +020048def _get_backend():
49 """
50 Importing the backend from cryptography has the side effect of activating
51 the osrandom engine. This mutates the global state of OpenSSL in the
52 process and causes issues for various programs that use subinterpreters or
53 embed Python. By putting the import in this function we can avoid
54 triggering this side effect unless _get_backend is called.
55 """
56 from cryptography.hazmat.backends.openssl.backend import backend
57 return backend
58
59
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050060def _untested_error(where):
61 """
62 An OpenSSL API failed somehow. Additionally, the failure which was
63 encountered isn't one that's exercised by the test suite so future behavior
64 of pyOpenSSL is now somewhat less predictable.
65 """
66 raise RuntimeError("Unknown %s failure" % (where,))
67
68
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050069def _new_mem_buf(buffer=None):
70 """
71 Allocate a new OpenSSL memory BIO.
72
73 Arrange for the garbage collector to clean it up automatically.
74
75 :param buffer: None or some bytes to use to put into the BIO so that they
76 can be read out.
77 """
78 if buffer is None:
79 bio = _lib.BIO_new(_lib.BIO_s_mem())
80 free = _lib.BIO_free
81 else:
82 data = _ffi.new("char[]", buffer)
83 bio = _lib.BIO_new_mem_buf(data, len(buffer))
Alex Gaynor5945ea82015-09-05 14:59:06 -040084
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050085 # Keep the memory alive as long as the bio is alive!
86 def free(bio, ref=data):
87 return _lib.BIO_free(bio)
88
Alex Gaynorfb8a2a12016-06-04 18:26:26 -070089 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050090
91 bio = _ffi.gc(bio, free)
92 return bio
93
94
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080095def _bio_to_string(bio):
96 """
97 Copy the contents of an OpenSSL BIO object into a Python byte string.
98 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050099 result_buffer = _ffi.new('char**')
100 buffer_length = _lib.BIO_get_mem_data(bio, result_buffer)
101 return _ffi.buffer(result_buffer[0], buffer_length)[:]
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800102
103
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800104def _set_asn1_time(boundary, when):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500105 """
106 The the time value of an ASN1 time object.
107
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900108 @param boundary: An ASN1_TIME pointer (or an object safely
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500109 castable to that type) which will have its value set.
110 @param when: A string representation of the desired time value.
111
112 @raise TypeError: If C{when} is not a L{bytes} string.
113 @raise ValueError: If C{when} does not represent a time in the required
114 format.
115 @raise RuntimeError: If the time value cannot be set for some other
116 (unspecified) reason.
117 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800118 if not isinstance(when, bytes):
119 raise TypeError("when must be a byte string")
120
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900121 set_result = _lib.ASN1_TIME_set_string(boundary, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800122 if set_result == 0:
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900123 raise ValueError("Invalid string")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800124
Alex Gaynor510293e2016-06-02 12:07:59 -0700125
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800126def _get_asn1_time(timestamp):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500127 """
128 Retrieve the time value of an ASN1 time object.
129
130 @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to
131 that type) from which the time value will be retrieved.
132
133 @return: The time value from C{timestamp} as a L{bytes} string in a certain
134 format. Or C{None} if the object contains no time value.
135 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500136 string_timestamp = _ffi.cast('ASN1_STRING*', timestamp)
137 if _lib.ASN1_STRING_length(string_timestamp) == 0:
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800138 return None
Alex Gaynor5945ea82015-09-05 14:59:06 -0400139 elif (
140 _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME
141 ):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500142 return _ffi.string(_lib.ASN1_STRING_data(string_timestamp))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800143 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500144 generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**")
145 _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp)
146 if generalized_timestamp[0] == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500147 # This may happen:
148 # - if timestamp was not an ASN1_TIME
149 # - if allocating memory for the ASN1_GENERALIZEDTIME failed
150 # - if a copy of the time data from timestamp cannot be made for
151 # the newly allocated ASN1_GENERALIZEDTIME
152 #
153 # These are difficult to test. cffi enforces the ASN1_TIME type.
154 # Memory allocation failures are a pain to trigger
155 # deterministically.
156 _untested_error("ASN1_TIME_to_generalizedtime")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800157 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500158 string_timestamp = _ffi.cast(
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800159 "ASN1_STRING*", generalized_timestamp[0])
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500160 string_data = _lib.ASN1_STRING_data(string_timestamp)
161 string_result = _ffi.string(string_data)
162 _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0])
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800163 return string_result
164
165
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800166class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200167 """
168 A class representing an DSA or RSA public key or key pair.
169 """
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800170 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800171 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800172
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800173 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500174 pkey = _lib.EVP_PKEY_new()
175 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800176 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800177
Paul Kehrer72d968b2016-07-29 15:31:04 +0800178 def to_cryptography_key(self):
179 """
180 Export as a ``cryptography`` key.
181
182 :rtype: One of ``cryptography``'s `key interfaces`_.
183
184 .. _key interfaces: https://cryptography.io/en/latest/hazmat/\
185 primitives/asymmetric/rsa/#key-interfaces
186
187 .. versionadded:: 16.1.0
188 """
Paul Kehrereb633842016-10-06 11:22:01 +0200189 backend = _get_backend()
Paul Kehrer72d968b2016-07-29 15:31:04 +0800190 if self._only_public:
191 return backend._evp_pkey_to_public_key(self._pkey)
192 else:
193 return backend._evp_pkey_to_private_key(self._pkey)
194
195 @classmethod
196 def from_cryptography_key(cls, crypto_key):
197 """
198 Construct based on a ``cryptography`` *crypto_key*.
199
200 :param crypto_key: A ``cryptography`` key.
201 :type crypto_key: One of ``cryptography``'s `key interfaces`_.
202
203 :rtype: PKey
204
205 .. versionadded:: 16.1.0
206 """
207 pkey = cls()
208 if not isinstance(crypto_key, (rsa.RSAPublicKey, rsa.RSAPrivateKey,
209 dsa.DSAPublicKey, dsa.DSAPrivateKey)):
210 raise TypeError("Unsupported key type")
211
212 pkey._pkey = crypto_key._evp_pkey
213 if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)):
214 pkey._only_public = True
215 pkey._initialized = True
216 return pkey
217
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800218 def generate_key(self, type, bits):
219 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700220 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800221
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200222 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800223
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200224 :param type: The key type.
225 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
226 :param bits: The number of bits.
227 :type bits: :py:data:`int` ``>= 0``
228 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
229 of the appropriate type.
230 :raises ValueError: If the number of bits isn't an integer of
231 the appropriate size.
Dan Sully44e767a2016-06-04 18:05:27 -0700232 :return: ``None``
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800233 """
234 if not isinstance(type, int):
235 raise TypeError("type must be an integer")
236
237 if not isinstance(bits, int):
238 raise TypeError("bits must be an integer")
239
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800240 # TODO Check error return
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500241 exponent = _lib.BN_new()
242 exponent = _ffi.gc(exponent, _lib.BN_free)
243 _lib.BN_set_word(exponent, _lib.RSA_F4)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800244
245 if type == TYPE_RSA:
246 if bits <= 0:
247 raise ValueError("Invalid number of bits")
248
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500249 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800250
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500251 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400252 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800253
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500254 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400255 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800256
257 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400258 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700259 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400260
261 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400262 res = _lib.DSA_generate_parameters_ex(
263 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
264 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700265 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400266
267 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
268 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800269 else:
270 raise Error("No such key type")
271
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800272 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800273
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800274 def check(self):
275 """
276 Check the consistency of an RSA private key.
277
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200278 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
279
Hynek Schlawack01c31672016-12-11 15:14:09 +0100280 :return: ``True`` if key is consistent.
281
282 :raise OpenSSL.crypto.Error: if the key is inconsistent.
283
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800284 :raise TypeError: if the key is of a type which cannot be checked.
285 Only RSA keys can currently be checked.
286 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800287 if self._only_public:
288 raise TypeError("public key only")
289
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100290 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800291 raise TypeError("key type unsupported")
292
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500293 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
294 rsa = _ffi.gc(rsa, _lib.RSA_free)
295 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800296 if result:
297 return True
298 _raise_current_error()
299
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800300 def type(self):
301 """
302 Returns the type of the key
303
304 :return: The type of the key.
305 """
Alex Gaynor0d2aec52017-05-31 04:26:27 -0400306 return _lib.EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800307
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800308 def bits(self):
309 """
310 Returns the number of bits of the key
311
312 :return: The number of bits of the key.
313 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500314 return _lib.EVP_PKEY_bits(self._pkey)
Alex Chanc6077062016-11-18 13:53:39 +0000315
316
Alex Gaynor10d30832017-06-29 15:31:39 -0700317PKeyType = deprecated(
318 PKey, __name__,
319 "PKeyType has been deprecated, use PKey instead",
320 DeprecationWarning
321)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800322
323
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400324class _EllipticCurve(object):
325 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400326 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400327
328 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
329 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
330 instances each of which represents one curve supported by the system.
331 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400332 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400333 _curves = None
334
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400335 if _PY3:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400336 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400337 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400338 """
339 Implement cooperation with the right-hand side argument of ``!=``.
340
341 Python 3 seems to have dropped this cooperation in this very narrow
342 circumstance.
343 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400344 if isinstance(other, _EllipticCurve):
345 return super(_EllipticCurve, self).__ne__(other)
346 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400347
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400348 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400349 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400350 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400351 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400352
353 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400354
355 :return: A :py:type:`set` of ``cls`` instances giving the names of the
356 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400357 """
Alex Chan84902a22017-04-20 11:50:47 +0100358 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
359 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
360 # The return value on this call should be num_curves again. We
361 # could check it to make sure but if it *isn't* then.. what could
362 # we do? Abort the whole process, I suppose...? -exarkun
363 lib.EC_get_builtin_curves(builtin_curves, num_curves)
364 return set(
365 cls.from_nid(lib, c.nid)
366 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400367
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400368 @classmethod
369 def _get_elliptic_curves(cls, lib):
370 """
371 Get, cache, and return the curves supported by OpenSSL.
372
373 :param lib: The OpenSSL library binding object.
374
375 :return: A :py:type:`set` of ``cls`` instances giving the names of the
376 elliptic curves the underlying library supports.
377 """
378 if cls._curves is None:
379 cls._curves = cls._load_elliptic_curves(lib)
380 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400381
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400382 @classmethod
383 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400384 """
385 Instantiate a new :py:class:`_EllipticCurve` associated with the given
386 OpenSSL NID.
387
388 :param lib: The OpenSSL library binding object.
389
390 :param nid: The OpenSSL NID the resulting curve object will represent.
391 This must be a curve NID (and not, for example, a hash NID) or
392 subsequent operations will fail in unpredictable ways.
393 :type nid: :py:class:`int`
394
395 :return: The curve object.
396 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400397 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
398
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400399 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400400 """
401 :param _lib: The :py:mod:`cryptography` binding instance used to
402 interface with OpenSSL.
403
404 :param _nid: The OpenSSL NID identifying the curve this object
405 represents.
406 :type _nid: :py:class:`int`
407
408 :param name: The OpenSSL short name identifying the curve this object
409 represents.
410 :type name: :py:class:`unicode`
411 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400412 self._lib = lib
413 self._nid = nid
414 self.name = name
415
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400416 def __repr__(self):
417 return "<Curve %r>" % (self.name,)
418
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400419 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400420 """
421 Create a new OpenSSL EC_KEY structure initialized to use this curve.
422
423 The structure is automatically garbage collected when the Python object
424 is garbage collected.
425 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400426 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
427 return _ffi.gc(key, _lib.EC_KEY_free)
428
429
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400430def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400431 """
432 Return a set of objects representing the elliptic curves supported in the
433 OpenSSL build in use.
434
435 The curve objects have a :py:class:`unicode` ``name`` attribute by which
436 they identify themselves.
437
438 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400439 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
440 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400441 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400442 return _EllipticCurve._get_elliptic_curves(_lib)
443
444
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400445def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400446 """
447 Return a single curve object selected by name.
448
449 See :py:func:`get_elliptic_curves` for information about curve objects.
450
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400451 :param name: The OpenSSL short name identifying the curve object to
452 retrieve.
453 :type name: :py:class:`unicode`
454
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400455 If the named curve is not supported then :py:class:`ValueError` is raised.
456 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400457 for curve in get_elliptic_curves():
458 if curve.name == name:
459 return curve
460 raise ValueError("unknown curve name", name)
461
462
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800463class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200464 """
465 An X.509 Distinguished Name.
466
467 :ivar countryName: The country of the entity.
468 :ivar C: Alias for :py:attr:`countryName`.
469
470 :ivar stateOrProvinceName: The state or province of the entity.
471 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
472
473 :ivar localityName: The locality of the entity.
474 :ivar L: Alias for :py:attr:`localityName`.
475
476 :ivar organizationName: The organization name of the entity.
477 :ivar O: Alias for :py:attr:`organizationName`.
478
479 :ivar organizationalUnitName: The organizational unit of the entity.
480 :ivar OU: Alias for :py:attr:`organizationalUnitName`
481
482 :ivar commonName: The common name of the entity.
483 :ivar CN: Alias for :py:attr:`commonName`.
484
485 :ivar emailAddress: The e-mail address of the entity.
486 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400487
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800488 def __init__(self, name):
489 """
490 Create a new X509Name, copying the given X509Name instance.
491
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200492 :param name: The name to copy.
493 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800494 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500495 name = _lib.X509_NAME_dup(name._name)
496 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800497
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800498 def __setattr__(self, name, value):
499 if name.startswith('_'):
500 return super(X509Name, self).__setattr__(name, value)
501
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800502 # Note: we really do not want str subclasses here, so we do not use
503 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800504 if type(name) is not str:
505 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400506 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800507
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500508 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500509 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800510 try:
511 _raise_current_error()
512 except Error:
513 pass
514 raise AttributeError("No such attribute")
515
516 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500517 for i in range(_lib.X509_NAME_entry_count(self._name)):
518 ent = _lib.X509_NAME_get_entry(self._name, i)
519 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
520 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800521 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500522 ent = _lib.X509_NAME_delete_entry(self._name, i)
523 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800524 break
525
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500526 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800527 value = value.encode('utf-8')
528
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500529 add_result = _lib.X509_NAME_add_entry_by_NID(
530 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800531 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500532 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800533
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800534 def __getattr__(self, name):
535 """
536 Find attribute. An X509Name object has the following attributes:
537 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400538 organization (alias O), organizationalUnit (alias OU), commonName
539 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800540 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500541 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500542 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800543 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
544 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
545 # push something onto the error queue. If we don't clean that up
546 # now, someone else will bump into it later and be quite confused.
547 # See lp#314814.
548 try:
549 _raise_current_error()
550 except Error:
551 pass
552 return super(X509Name, self).__getattr__(name)
553
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500554 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800555 if entry_index == -1:
556 return None
557
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500558 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
559 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800560
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500561 result_buffer = _ffi.new("unsigned char**")
562 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400563 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800564
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700565 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400566 result = _ffi.buffer(
567 result_buffer[0], data_length
568 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700569 finally:
570 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500571 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800572 return result
573
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500574 def _cmp(op):
575 def f(self, other):
576 if not isinstance(other, X509Name):
577 return NotImplemented
578 result = _lib.X509_NAME_cmp(self._name, other._name)
579 return op(result, 0)
580 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800581
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500582 __eq__ = _cmp(__eq__)
583 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800584
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500585 __lt__ = _cmp(__lt__)
586 __le__ = _cmp(__le__)
587
588 __gt__ = _cmp(__gt__)
589 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800590
591 def __repr__(self):
592 """
593 String representation of an X509Name
594 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400595 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500596 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800597 self._name, result_buffer, len(result_buffer))
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700598 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800599
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500600 return "<X509Name object '%s'>" % (
601 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800602
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800603 def hash(self):
604 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200605 Return an integer representation of the first four bytes of the
606 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800607
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200608 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
609
610 :return: The (integer) hash of this name.
611 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800612 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500613 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800614
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800615 def der(self):
616 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200617 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800618
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200619 :return: The DER encoded form of this name.
620 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800621 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500622 result_buffer = _ffi.new('unsigned char**')
623 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400624 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800625
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500626 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
627 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800628 return string_result
629
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800630 def get_components(self):
631 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200632 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800633
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200634 :return: The components of this name.
635 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800636 """
637 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500638 for i in range(_lib.X509_NAME_entry_count(self._name)):
639 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800640
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500641 fname = _lib.X509_NAME_ENTRY_get_object(ent)
642 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800643
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500644 nid = _lib.OBJ_obj2nid(fname)
645 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800646
647 result.append((
Alex Gaynora738ed52015-09-05 11:17:10 -0400648 _ffi.string(name),
649 _ffi.string(
650 _lib.ASN1_STRING_data(fval),
651 _lib.ASN1_STRING_length(fval))))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800652
653 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200654
655
Alex Gaynor10d30832017-06-29 15:31:39 -0700656X509NameType = deprecated(
657 X509Name, __name__,
658 "X509NameType has been deprecated, use X509Name instead",
659 DeprecationWarning
660)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800661
662
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800663class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200664 """
665 An X.509 v3 certificate extension.
666 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400667
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800668 def __init__(self, type_name, critical, value, subject=None, issuer=None):
669 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200670 Initializes an X509 extension.
671
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100672 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400673 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800674
Alex Gaynor5945ea82015-09-05 14:59:06 -0400675 :param bool critical: A flag indicating whether this is a critical
676 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800677
678 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200679 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800680
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200681 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800682 :type subject: :py:class:`X509`
683
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200684 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800685 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100686
Alex Chan54005ce2017-03-21 08:08:17 +0000687 .. _extension: https://www.openssl.org/docs/manmaster/man5/
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100688 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800689 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500690 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800691
Alex Gaynor5945ea82015-09-05 14:59:06 -0400692 # A context is necessary for any extension which uses the r2i
693 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
694 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500695 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800696
697 # We have no configuration database - but perhaps we should (some
698 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500699 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800700
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800701 # Initialize the subject and issuer, if appropriate. ctx is a local,
702 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400703 # any references, so no need to mess with reference counts or
704 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800705 if issuer is not None:
706 if not isinstance(issuer, X509):
707 raise TypeError("issuer must be an X509 instance")
708 ctx.issuer_cert = issuer._x509
709 if subject is not None:
710 if not isinstance(subject, X509):
711 raise TypeError("subject must be an X509 instance")
712 ctx.subject_cert = subject._x509
713
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800714 if critical:
715 # There are other OpenSSL APIs which would let us pass in critical
716 # separately, but they're harder to use, and since value is already
717 # a pile of crappy junk smuggling a ton of utterly important
718 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400719 # with strings? (However, X509V3_EXT_i2d in particular seems like
720 # it would be a better API to invoke. I do not know where to get
721 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500722 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800723
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500724 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
725 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800726 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500727 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800728
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400729 @property
730 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400731 return _lib.OBJ_obj2nid(
732 _lib.X509_EXTENSION_get_object(self._extension)
733 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400734
735 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500736 _lib.GEN_EMAIL: "email",
737 _lib.GEN_DNS: "DNS",
738 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400739 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400740
741 def _subjectAltNameString(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500742 method = _lib.X509V3_EXT_get(self._extension)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700743 _openssl_assert(method != _ffi.NULL)
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400744 ext_data = _lib.X509_EXTENSION_get_data(self._extension)
745 payload = ext_data.data
746 length = ext_data.length
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400747
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500748 payloadptr = _ffi.new("unsigned char**")
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400749 payloadptr[0] = payload
750
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500751 if method.it != _ffi.NULL:
752 ptr = _lib.ASN1_ITEM_ptr(method.it)
753 data = _lib.ASN1_item_d2i(_ffi.NULL, payloadptr, length, ptr)
754 names = _ffi.cast("GENERAL_NAMES*", data)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400755 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500756 names = _ffi.cast(
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400757 "GENERAL_NAMES*",
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500758 method.d2i(_ffi.NULL, payloadptr, length))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400759
Paul Kehrerb7d79502015-05-04 07:43:51 -0500760 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400761 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500762 for i in range(_lib.sk_GENERAL_NAME_num(names)):
763 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400764 try:
765 label = self._prefixes[name.type]
766 except KeyError:
767 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500768 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500769 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400770 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500771 value = _native(
772 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
773 parts.append(label + ":" + value)
774 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400775
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800776 def __str__(self):
777 """
778 :return: a nice text representation of the extension
779 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500780 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400781 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800782
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400783 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500784 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400785 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800786
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500787 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800788
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800789 def get_critical(self):
790 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200791 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800792
793 :return: The critical field.
794 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500795 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800796
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800797 def get_short_name(self):
798 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200799 Returns the short type name of this X.509 extension.
800
801 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800802
803 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200804 :rtype: :py:data:`bytes`
805
806 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800807 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500808 obj = _lib.X509_EXTENSION_get_object(self._extension)
809 nid = _lib.OBJ_obj2nid(obj)
810 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800811
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800812 def get_data(self):
813 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200814 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800815
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200816 :return: The ASN.1 encoded data of this X509 extension.
817 :rtype: :py:data:`bytes`
818
819 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800820 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500821 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
822 string_result = _ffi.cast('ASN1_STRING*', octet_result)
823 char_result = _lib.ASN1_STRING_data(string_result)
824 result_length = _lib.ASN1_STRING_length(string_result)
825 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800826
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200827
Alex Gaynor10d30832017-06-29 15:31:39 -0700828X509ExtensionType = deprecated(
829 X509Extension, __name__,
830 "X509ExtensionType has been deprecated, use X509Extension instead",
831 DeprecationWarning
832)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800833
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800834
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800835class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200836 """
837 An X.509 certificate signing requests.
838 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400839
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800840 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500841 req = _lib.X509_REQ_new()
842 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Alex Gaynor5af32d02016-09-24 01:52:21 -0400843 # Default to version 0.
844 self.set_version(0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800845
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800846 def set_pubkey(self, pkey):
847 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200848 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800849
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200850 :param pkey: The public key to use.
851 :type pkey: :py:class:`PKey`
852
Dan Sully44e767a2016-06-04 18:05:27 -0700853 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800854 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500855 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400856 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800857
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800858 def get_pubkey(self):
859 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200860 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800861
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200862 :return: The public key.
863 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800864 """
865 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500866 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700867 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500868 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800869 pkey._only_public = True
870 return pkey
871
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800872 def set_version(self, version):
873 """
874 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
875 request.
876
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200877 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700878 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800879 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500880 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400881 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800882
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800883 def get_version(self):
884 """
885 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
886 request.
887
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200888 :return: The value of the version subfield.
889 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800890 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500891 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800892
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800893 def get_subject(self):
894 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200895 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800896
Cory Benfield881dc8d2015-12-09 08:25:14 +0000897 This creates a new :class:`X509Name` that wraps the underlying subject
898 name field on the certificate signing request. Modifying it will modify
899 the underlying signing request, and will have the effect of modifying
900 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200901
902 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000903 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800904 """
905 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500906 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700907 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800908
909 # The name is owned by the X509Req structure. As long as the X509Name
910 # Python object is alive, keep the X509Req Python object alive.
911 name._owner = self
912
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800913 return name
914
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800915 def add_extensions(self, extensions):
916 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200917 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800918
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200919 :param extensions: The X.509 extensions to add.
920 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700921 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800922 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500923 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700924 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800925
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500926 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800927
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800928 for ext in extensions:
929 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -0800930 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800931
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800932 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500933 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800934
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500935 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400936 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800937
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800938 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800939 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200940 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800941
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200942 :return: The X.509 extensions in this request.
943 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
944
945 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800946 """
947 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500948 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -0500949 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800950 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500951 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800952 exts.append(ext)
953 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800954
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800955 def sign(self, pkey, digest):
956 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -0700957 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800958
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200959 :param pkey: The key pair to sign with.
960 :type pkey: :py:class:`PKey`
961 :param digest: The name of the message digest to use for the signature,
Alex Gaynor239e2d32016-09-11 12:36:35 -0400962 e.g. :py:data:`b"sha256"`.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200963 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -0700964 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800965 """
966 if pkey._only_public:
967 raise ValueError("Key has only public part")
968
969 if not pkey._initialized:
970 raise ValueError("Key is uninitialized")
971
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500972 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500973 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800974 raise ValueError("No such digest method")
975
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500976 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400977 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800978
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800979 def verify(self, pkey):
980 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200981 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800982
Hynek Schlawack01c31672016-12-11 15:14:09 +0100983 :param PKey key: A public key.
984
985 :return: ``True`` if the signature is correct.
986 :rtype: bool
987
988 :raises OpenSSL.crypto.Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800989 problem verifying the signature.
990 """
991 if not isinstance(pkey, PKey):
992 raise TypeError("pkey must be a PKey instance")
993
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500994 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800995 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500996 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800997
998 return result
999
1000
Alex Gaynor10d30832017-06-29 15:31:39 -07001001X509ReqType = deprecated(
1002 X509Req, __name__,
1003 "X509ReqType has been deprecated, use X509Req instead",
1004 DeprecationWarning
1005)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001006
1007
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001008class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001009 """
1010 An X.509 certificate.
1011 """
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001012 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001013 x509 = _lib.X509_new()
Hynek Schlawack8a2dd772016-07-31 13:46:20 +02001014 _openssl_assert(x509 != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001015 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001016
Alex Gaynor9939ba12017-06-25 16:28:24 -04001017 def to_cryptography(self):
1018 """
1019 Export as a ``cryptography`` certificate.
1020
1021 :rtype: ``cryptography.x509.Certificate``
1022
1023 .. versionadded:: 17.1.0
1024 """
1025 from cryptography.hazmat.backends.openssl.x509 import _Certificate
1026 backend = _get_backend()
1027 return _Certificate(backend, self._x509)
1028
1029 @classmethod
1030 def from_cryptography(cls, crypto_cert):
1031 """
1032 Construct based on a ``cryptography`` *crypto_cert*.
1033
1034 :param crypto_key: A ``cryptography`` X.509 certificate.
1035 :type crypto_key: ``cryptography.x509.Certificate``
1036
1037 :rtype: PKey
1038
1039 .. versionadded:: 17.1.0
1040 """
1041 if not isinstance(crypto_cert, x509.Certificate):
1042 raise TypeError("Must be a certificate")
1043
1044 cert = cls()
1045 cert._x509 = crypto_cert._x509
1046 return cert
1047
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001048 def set_version(self, version):
1049 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001050 Set the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001051
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001052 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001053 :type version: :py:class:`int`
1054
Dan Sully44e767a2016-06-04 18:05:27 -07001055 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001056 """
1057 if not isinstance(version, int):
1058 raise TypeError("version must be an integer")
1059
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001060 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001061
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001062 def get_version(self):
1063 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001064 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001065
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001066 :return: The version number of the certificate.
1067 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001068 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001069 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001070
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001071 def get_pubkey(self):
1072 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001073 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001074
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001075 :return: The public key.
1076 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001077 """
1078 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001079 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1080 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001081 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001082 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001083 pkey._only_public = True
1084 return pkey
1085
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001086 def set_pubkey(self, pkey):
1087 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001088 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001089
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001090 :param pkey: The public key.
1091 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001092
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001093 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001094 """
1095 if not isinstance(pkey, PKey):
1096 raise TypeError("pkey must be a PKey instance")
1097
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001098 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001099 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001100
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001101 def sign(self, pkey, digest):
1102 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001103 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001104
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001105 :param pkey: The key to sign with.
1106 :type pkey: :py:class:`PKey`
1107
1108 :param digest: The name of the message digest to use.
1109 :type digest: :py:class:`bytes`
1110
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001111 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001112 """
1113 if not isinstance(pkey, PKey):
1114 raise TypeError("pkey must be a PKey instance")
1115
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001116 if pkey._only_public:
1117 raise ValueError("Key only has public part")
1118
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001119 if not pkey._initialized:
1120 raise ValueError("Key is uninitialized")
1121
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001122 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001123 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001124 raise ValueError("No such digest method")
1125
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001126 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001127 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001128
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001129 def get_signature_algorithm(self):
1130 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001131 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001132
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001133 :return: The name of the algorithm.
1134 :rtype: :py:class:`bytes`
1135
1136 :raises ValueError: If the signature algorithm is undefined.
1137
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001138 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001139 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001140 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1141 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001142 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001143 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001144 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001145
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001146 def digest(self, digest_name):
1147 """
1148 Return the digest of the X509 object.
1149
1150 :param digest_name: The name of the digest algorithm to use.
1151 :type digest_name: :py:class:`bytes`
1152
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001153 :return: The digest of the object, formatted as
1154 :py:const:`b":"`-delimited hex pairs.
1155 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001156 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001157 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001158 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001159 raise ValueError("No such digest method")
1160
Paul Kehrer9f9113a2016-09-20 20:10:25 -05001161 result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001162 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001163 result_length[0] = len(result_buffer)
1164
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001165 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001166 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001167 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001168
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001169 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001170 b16encode(ch).upper() for ch
1171 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001172
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001173 def subject_name_hash(self):
1174 """
1175 Return the hash of the X509 subject.
1176
1177 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001178 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001179 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001180 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001181
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001182 def set_serial_number(self, serial):
1183 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001184 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001185
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001186 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001187 :type serial: :py:class:`int`
1188
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001189 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001190 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001191 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001192 raise TypeError("serial must be an integer")
1193
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001194 hex_serial = hex(serial)[2:]
1195 if not isinstance(hex_serial, bytes):
1196 hex_serial = hex_serial.encode('ascii')
1197
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001198 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001199
1200 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001201 # it. If bignum is still NULL after this call, then the return value
1202 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001203 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001204
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001205 if bignum_serial[0] == _ffi.NULL:
1206 set_result = _lib.ASN1_INTEGER_set(
1207 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001208 if set_result:
1209 # TODO Not tested
1210 _raise_current_error()
1211 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001212 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1213 _lib.BN_free(bignum_serial[0])
1214 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001215 # TODO Not tested
1216 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001217 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1218 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001219 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001220
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001221 def get_serial_number(self):
1222 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001223 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001224
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001225 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001226 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001227 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001228 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1229 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001230 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001231 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001232 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001233 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001234 serial = int(hexstring_serial, 16)
1235 return serial
1236 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001237 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001238 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001239 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001240
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001241 def gmtime_adj_notAfter(self, amount):
1242 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001243 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001244
Dan Sully44e767a2016-06-04 18:05:27 -07001245 :param int amount: The number of seconds by which to adjust the
1246 timestamp.
1247 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001248 """
1249 if not isinstance(amount, int):
1250 raise TypeError("amount must be an integer")
1251
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001252 notAfter = _lib.X509_get_notAfter(self._x509)
1253 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001254
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001255 def gmtime_adj_notBefore(self, amount):
1256 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001257 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001258
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001259 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001260 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001261 """
1262 if not isinstance(amount, int):
1263 raise TypeError("amount must be an integer")
1264
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001265 notBefore = _lib.X509_get_notBefore(self._x509)
1266 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001267
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001268 def has_expired(self):
1269 """
1270 Check whether the certificate has expired.
1271
Dan Sully44e767a2016-06-04 18:05:27 -07001272 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1273 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001274 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001275 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001276 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001277
Paul Kehrerfde45c92016-01-21 12:57:37 -06001278 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001279
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001280 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001281 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001282
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001283 def get_notBefore(self):
1284 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001285 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001286
Paul Kehrerce98ee62017-06-21 06:59:58 -10001287 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001288
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001289 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001290
Dan Sully44e767a2016-06-04 18:05:27 -07001291 :return: A timestamp string, or ``None`` if there is none.
1292 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001293 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001294 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001295
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001296 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001297 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001298
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001299 def set_notBefore(self, when):
1300 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001301 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001302
Paul Kehrerce98ee62017-06-21 06:59:58 -10001303 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001304
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001305 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001306
Dan Sully44e767a2016-06-04 18:05:27 -07001307 :param bytes when: A timestamp string.
1308 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001309 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001310 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001311
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001312 def get_notAfter(self):
1313 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001314 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001315
Paul Kehrerce98ee62017-06-21 06:59:58 -10001316 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001317
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001318 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001319
Dan Sully44e767a2016-06-04 18:05:27 -07001320 :return: A timestamp string, or ``None`` if there is none.
1321 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001322 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001323 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001324
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001325 def set_notAfter(self, when):
1326 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001327 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001328
Paul Kehrerce98ee62017-06-21 06:59:58 -10001329 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001330
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001331 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001332
Dan Sully44e767a2016-06-04 18:05:27 -07001333 :param bytes when: A timestamp string.
1334 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001335 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001336 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001337
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001338 def _get_name(self, which):
1339 name = X509Name.__new__(X509Name)
1340 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001341 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001342
1343 # The name is owned by the X509 structure. As long as the X509Name
1344 # Python object is alive, keep the X509 Python object alive.
1345 name._owner = self
1346
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001347 return name
1348
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001349 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001350 if not isinstance(name, X509Name):
1351 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001352 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001353 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001354
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001355 def get_issuer(self):
1356 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001357 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001358
Cory Benfielde6bcce82015-12-09 08:40:03 +00001359 This creates a new :class:`X509Name` that wraps the underlying issuer
1360 name field on the certificate. Modifying it will modify the underlying
1361 certificate, and will have the effect of modifying any other
1362 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001363
1364 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001365 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001366 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001367 return self._get_name(_lib.X509_get_issuer_name)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001368
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001369 def set_issuer(self, issuer):
1370 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001371 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001372
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001373 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001374 :type issuer: :py:class:`X509Name`
1375
Dan Sully44e767a2016-06-04 18:05:27 -07001376 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001377 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001378 return self._set_name(_lib.X509_set_issuer_name, issuer)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001379
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001380 def get_subject(self):
1381 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001382 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001383
Cory Benfielde6bcce82015-12-09 08:40:03 +00001384 This creates a new :class:`X509Name` that wraps the underlying subject
1385 name field on the certificate. Modifying it will modify the underlying
1386 certificate, and will have the effect of modifying any other
1387 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001388
1389 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001390 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001391 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001392 return self._get_name(_lib.X509_get_subject_name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001393
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001394 def set_subject(self, subject):
1395 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001396 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001397
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001398 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001399 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001400
Dan Sully44e767a2016-06-04 18:05:27 -07001401 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001402 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001403 return self._set_name(_lib.X509_set_subject_name, subject)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001404
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001405 def get_extension_count(self):
1406 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001407 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001408
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001409 :return: The number of extensions.
1410 :rtype: :py:class:`int`
1411
1412 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001413 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001414 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001415
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001416 def add_extensions(self, extensions):
1417 """
1418 Add extensions to the certificate.
1419
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001420 :param extensions: The extensions to add.
1421 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001422 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001423 """
1424 for ext in extensions:
1425 if not isinstance(ext, X509Extension):
1426 raise ValueError("One of the elements is not an X509Extension")
1427
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001428 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001429 if not add_result:
1430 _raise_current_error()
1431
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001432 def get_extension(self, index):
1433 """
1434 Get a specific extension of the certificate by index.
1435
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001436 Extensions on a certificate are kept in order. The index
1437 parameter selects which extension will be returned.
1438
1439 :param int index: The index of the extension to retrieve.
1440 :return: The extension at the specified index.
1441 :rtype: :py:class:`X509Extension`
1442 :raises IndexError: If the extension index was out of bounds.
1443
1444 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001445 """
1446 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001447 ext._extension = _lib.X509_get_ext(self._x509, index)
1448 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001449 raise IndexError("extension index out of bounds")
1450
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001451 extension = _lib.X509_EXTENSION_dup(ext._extension)
1452 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001453 return ext
1454
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001455
Alex Gaynor10d30832017-06-29 15:31:39 -07001456X509Type = deprecated(
1457 X509, __name__,
1458 "X509Type has been deprecated, use X509 instead",
1459 DeprecationWarning
1460)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001461
1462
Dan Sully44e767a2016-06-04 18:05:27 -07001463class X509StoreFlags(object):
1464 """
1465 Flags for X509 verification, used to change the behavior of
1466 :class:`X509Store`.
1467
1468 See `OpenSSL Verification Flags`_ for details.
1469
1470 .. _OpenSSL Verification Flags:
Alex Chan54005ce2017-03-21 08:08:17 +00001471 https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_flags.html
Dan Sully44e767a2016-06-04 18:05:27 -07001472 """
1473 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1474 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1475 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1476 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1477 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1478 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1479 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1480 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1481 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1482 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1483 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1484
1485
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001486class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001487 """
Dan Sully44e767a2016-06-04 18:05:27 -07001488 An X.509 store.
1489
1490 An X.509 store is used to describe a context in which to verify a
1491 certificate. A description of a context may include a set of certificates
1492 to trust, a set of certificate revocation lists, verification flags and
1493 more.
1494
1495 An X.509 store, being only a description, cannot be used by itself to
1496 verify a certificate. To carry out the actual verification process, see
1497 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001498 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001499
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001500 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001501 store = _lib.X509_STORE_new()
1502 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001503
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001504 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001505 """
Dan Sully44e767a2016-06-04 18:05:27 -07001506 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001507
Dan Sully44e767a2016-06-04 18:05:27 -07001508 Adding a certificate with this method adds this certificate as a
1509 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001510
1511 :param X509 cert: The certificate to add to this store.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001512
Dan Sully44e767a2016-06-04 18:05:27 -07001513 :raises TypeError: If the certificate is not an :class:`X509`.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001514
1515 :raises OpenSSL.crypto.Error: If OpenSSL was unhappy with your
1516 certificate.
1517
Dan Sully44e767a2016-06-04 18:05:27 -07001518 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001519 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001520 if not isinstance(cert, X509):
1521 raise TypeError()
1522
Dan Sully44e767a2016-06-04 18:05:27 -07001523 _openssl_assert(_lib.X509_STORE_add_cert(self._store, cert._x509) != 0)
1524
1525 def add_crl(self, crl):
1526 """
1527 Add a certificate revocation list to this store.
1528
1529 The certificate revocation lists added to a store will only be used if
1530 the associated flags are configured to check certificate revocation
1531 lists.
1532
1533 .. versionadded:: 16.1.0
1534
1535 :param CRL crl: The certificate revocation list to add to this store.
1536 :return: ``None`` if the certificate revocation list was added
1537 successfully.
1538 """
1539 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1540
1541 def set_flags(self, flags):
1542 """
1543 Set verification flags to this store.
1544
1545 Verification flags can be combined by oring them together.
1546
1547 .. note::
1548
1549 Setting a verification flag sometimes requires clients to add
1550 additional information to the store, otherwise a suitable error will
1551 be raised.
1552
1553 For example, in setting flags to enable CRL checking a
1554 suitable CRL must be added to the store otherwise an error will be
1555 raised.
1556
1557 .. versionadded:: 16.1.0
1558
1559 :param int flags: The verification flags to set on this store.
1560 See :class:`X509StoreFlags` for available constants.
1561 :return: ``None`` if the verification flags were successfully set.
1562 """
1563 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001564
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001565 def set_time(self, vfy_time):
1566 """
1567 Set the time against which the certificates are verified.
1568
1569 Normally the current time is used.
1570
1571 .. note::
1572
1573 For example, you can determine if a certificate was valid at a given
1574 time.
1575
Hynek Schlawackf6c96af2017-04-20 12:34:58 +02001576 .. versionadded:: 17.0.0
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001577
1578 :param datetime vfy_time: The verification time to set on this store.
1579 :return: ``None`` if the verification time was successfully set.
1580 """
1581 param = _lib.X509_VERIFY_PARAM_new()
1582 param = _ffi.gc(param, _lib.X509_VERIFY_PARAM_free)
1583
1584 _lib.X509_VERIFY_PARAM_set_time(param, int(vfy_time.strftime('%s')))
1585 _openssl_assert(_lib.X509_STORE_set1_param(self._store, param) != 0)
1586
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001587
Alex Gaynor10d30832017-06-29 15:31:39 -07001588X509StoreType = deprecated(
1589 X509Store, __name__,
1590 "X509StoreType has been deprecated, use X509Store instead",
1591 DeprecationWarning
1592)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001593
1594
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001595class X509StoreContextError(Exception):
1596 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001597 An exception raised when an error occurred while verifying a certificate
1598 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001599
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001600 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001601 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001602 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001603
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001604 def __init__(self, message, certificate):
1605 super(X509StoreContextError, self).__init__(message)
1606 self.certificate = certificate
1607
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001608
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001609class X509StoreContext(object):
1610 """
1611 An X.509 store context.
1612
Dan Sully44e767a2016-06-04 18:05:27 -07001613 An X.509 store context is used to carry out the actual verification process
1614 of a certificate in a described context. For describing such a context, see
1615 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001616
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001617 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1618 instance. It is dynamically allocated and automatically garbage
1619 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001620 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001621 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001622 :param X509Store store: The certificates which will be trusted for the
1623 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001624 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001625 """
1626
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001627 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001628 store_ctx = _lib.X509_STORE_CTX_new()
1629 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1630 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001631 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001632 # Make the store context available for use after instantiating this
1633 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001634 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001635 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001636
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001637 def _init(self):
1638 """
1639 Set up the store context for a subsequent verification operation.
1640 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001641 ret = _lib.X509_STORE_CTX_init(
1642 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1643 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001644 if ret <= 0:
1645 _raise_current_error()
1646
1647 def _cleanup(self):
1648 """
1649 Internally cleans up the store context.
1650
Dan Sully44e767a2016-06-04 18:05:27 -07001651 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001652 """
1653 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1654
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001655 def _exception_from_context(self):
1656 """
1657 Convert an OpenSSL native context error failure into a Python
1658 exception.
1659
Alex Gaynor5945ea82015-09-05 14:59:06 -04001660 When a call to native OpenSSL X509_verify_cert fails, additional
1661 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001662 """
1663 errors = [
1664 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1665 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1666 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001667 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001668 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001669 # A context error should always be associated with a certificate, so we
1670 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001671 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001672 _cert = _lib.X509_dup(_x509)
1673 pycert = X509.__new__(X509)
1674 pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001675 return X509StoreContextError(errors, pycert)
1676
Stephen Holsapple46a09252015-02-12 14:45:43 -08001677 def set_store(self, store):
1678 """
Dan Sully44e767a2016-06-04 18:05:27 -07001679 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001680
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001681 .. versionadded:: 0.15
1682
Dan Sully44e767a2016-06-04 18:05:27 -07001683 :param X509Store store: The store description which will be used for
1684 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001685 """
1686 self._store = store
1687
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001688 def verify_certificate(self):
1689 """
1690 Verify a certificate in a context.
1691
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001692 .. versionadded:: 0.15
1693
Alex Gaynorca87ff62015-09-04 23:31:03 -04001694 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001695 certificate in the context. Sets ``certificate`` attribute to
1696 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001697 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001698 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001699 # :meth:`verify_certificate` is called multiple times.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001700 self._init()
1701 ret = _lib.X509_verify_cert(self._store_ctx)
1702 self._cleanup()
1703 if ret <= 0:
1704 raise self._exception_from_context()
1705
1706
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001707def load_certificate(type, buffer):
1708 """
1709 Load a certificate from a buffer
1710
1711 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1712
Dan Sully44e767a2016-06-04 18:05:27 -07001713 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001714
1715 :return: The X509 object
1716 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001717 if isinstance(buffer, _text_type):
1718 buffer = buffer.encode("ascii")
1719
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001720 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001721
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001722 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001723 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001724 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001725 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001726 else:
1727 raise ValueError(
1728 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001729
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001730 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001731 _raise_current_error()
1732
1733 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001734 cert._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001735 return cert
1736
1737
1738def dump_certificate(type, cert):
1739 """
1740 Dump a certificate to a buffer
1741
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001742 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1743 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001744 :param cert: The certificate to dump
1745 :return: The buffer with the dumped certificate in
1746 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001747 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001748
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001749 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001750 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001751 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001752 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001753 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001754 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001755 else:
1756 raise ValueError(
1757 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1758 "FILETYPE_TEXT")
1759
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001760 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001761 return _bio_to_string(bio)
1762
1763
Cory Benfield6492f7c2015-10-27 16:57:58 +09001764def dump_publickey(type, pkey):
1765 """
Cory Benfield11c10192015-10-27 17:23:03 +09001766 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001767
Cory Benfield9c590b92015-10-28 14:55:05 +09001768 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001769 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001770 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001771 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001772 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001773 """
1774 bio = _new_mem_buf()
1775 if type == FILETYPE_PEM:
1776 write_bio = _lib.PEM_write_bio_PUBKEY
1777 elif type == FILETYPE_ASN1:
1778 write_bio = _lib.i2d_PUBKEY_bio
1779 else:
1780 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1781
1782 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001783 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001784 _raise_current_error()
1785
1786 return _bio_to_string(bio)
1787
1788
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001789def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1790 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001791 Dump the private key *pkey* into a buffer string encoded with the type
1792 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1793 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001794
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001795 :param type: The file type (one of :const:`FILETYPE_PEM`,
1796 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1797 :param PKey pkey: The PKey to dump
1798 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001799 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001800 the passphrase to use, or a callback for providing the passphrase.
1801
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001802 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001803 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001804 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001805 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001806
1807 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001808 if passphrase is None:
1809 raise TypeError(
1810 "if a value is given for cipher "
1811 "one must also be given for passphrase")
1812 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001813 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001814 raise ValueError("Invalid cipher name")
1815 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001816 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001817
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001818 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001819 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001820 result_code = _lib.PEM_write_bio_PrivateKey(
1821 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001822 helper.callback, helper.callback_args)
1823 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001824 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001825 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001826 elif type == FILETYPE_TEXT:
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001827 rsa = _ffi.gc(
1828 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1829 _lib.RSA_free
1830 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001831 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001832 else:
1833 raise ValueError(
1834 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1835 "FILETYPE_TEXT")
1836
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001837 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001838
1839 return _bio_to_string(bio)
1840
1841
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001842class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001843 """
1844 A certificate revocation.
1845 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001846 # http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_
1847 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1848 # OCSP_crl_reason_str. We use the latter, just like the command line
1849 # program.
1850 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001851 b"unspecified",
1852 b"keyCompromise",
1853 b"CACompromise",
1854 b"affiliationChanged",
1855 b"superseded",
1856 b"cessationOfOperation",
1857 b"certificateHold",
1858 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001859 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001860
1861 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001862 revoked = _lib.X509_REVOKED_new()
1863 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001864
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001865 def set_serial(self, hex_str):
1866 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001867 Set the serial number.
1868
1869 The serial number is formatted as a hexadecimal number encoded in
1870 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001871
Dan Sully44e767a2016-06-04 18:05:27 -07001872 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001873
Dan Sully44e767a2016-06-04 18:05:27 -07001874 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001875 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001876 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1877 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001878 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001879 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001880 if not bn_result:
1881 raise ValueError("bad hex string")
1882
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001883 asn1_serial = _ffi.gc(
1884 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1885 _lib.ASN1_INTEGER_free)
1886 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001887
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001888 def get_serial(self):
1889 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001890 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001891
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001892 The serial number is formatted as a hexadecimal number encoded in
1893 ASCII.
1894
1895 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001896 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001897 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001898 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001899
Alex Gaynor67903a62016-06-02 10:37:13 -07001900 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1901 _openssl_assert(asn1_int != _ffi.NULL)
1902 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1903 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001904 return _bio_to_string(bio)
1905
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001906 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001907 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1908 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001909 obj = _lib.X509_EXTENSION_get_object(ext)
1910 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001911 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001912 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001913 break
1914
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001915 def set_reason(self, reason):
1916 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001917 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001918
Dan Sully44e767a2016-06-04 18:05:27 -07001919 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001920
1921 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07001922 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001923
Dan Sully44e767a2016-06-04 18:05:27 -07001924 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001925
1926 .. seealso::
1927
Dan Sully44e767a2016-06-04 18:05:27 -07001928 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001929 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001930 """
1931 if reason is None:
1932 self._delete_reason()
1933 elif not isinstance(reason, bytes):
1934 raise TypeError("reason must be None or a byte string")
1935 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001936 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001937 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
1938
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001939 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07001940 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001941 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001942
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001943 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001944 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001945
1946 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001947 add_result = _lib.X509_REVOKED_add1_ext_i2d(
1948 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001949 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001950
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001951 def get_reason(self):
1952 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04001953 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001954
Dan Sully44e767a2016-06-04 18:05:27 -07001955 :return: The reason, or ``None`` if there is none.
1956 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001957
1958 .. seealso::
1959
Dan Sully44e767a2016-06-04 18:05:27 -07001960 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001961 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001962 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001963 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1964 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001965 obj = _lib.X509_EXTENSION_get_object(ext)
1966 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001967 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001968
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001969 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001970 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04001971 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001972 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04001973 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04001974 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001975
1976 return _bio_to_string(bio)
1977
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001978 def all_reasons(self):
1979 """
1980 Return a list of all the supported reason strings.
1981
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001982 This list is a copy; modifying it does not change the supported reason
1983 strings.
1984
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001985 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07001986 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001987 """
1988 return self._crl_reasons[:]
1989
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001990 def set_rev_date(self, when):
1991 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001992 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001993
Dan Sully44e767a2016-06-04 18:05:27 -07001994 :param bytes when: The timestamp of the revocation,
Paul Kehrerce98ee62017-06-21 06:59:58 -10001995 as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07001996 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001997 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001998 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1999 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002000
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002001 def get_rev_date(self):
2002 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002003 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002004
Paul Kehrerce98ee62017-06-21 06:59:58 -10002005 :return: The timestamp of the revocation, as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002006 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002007 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002008 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2009 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002010
2011
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002012class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002013 """
2014 A certificate revocation list.
2015 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002016
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002017 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002018 crl = _lib.X509_CRL_new()
2019 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002020
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002021 def get_revoked(self):
2022 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002023 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002024
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002025 These revocations will be provided by value, not by reference.
2026 That means it's okay to mutate them: it won't affect this CRL.
2027
2028 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002029 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002030 """
2031 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07002032 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002033 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
2034 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04002035 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002036 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002037 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002038 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002039 if results:
2040 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002041
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002042 def add_revoked(self, revoked):
2043 """
2044 Add a revoked (by value not reference) to the CRL structure
2045
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002046 This revocation will be added by value, not by reference. That
2047 means it's okay to mutate it after adding: it won't affect
2048 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002049
Dan Sully44e767a2016-06-04 18:05:27 -07002050 :param Revoked revoked: The new revocation.
2051 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002052 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04002053 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002054 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002055
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002056 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002057 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002058
Dan Sully44e767a2016-06-04 18:05:27 -07002059 def get_issuer(self):
2060 """
2061 Get the CRL's issuer.
2062
2063 .. versionadded:: 16.1.0
2064
2065 :rtype: X509Name
2066 """
2067 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
2068 _openssl_assert(_issuer != _ffi.NULL)
2069 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
2070 issuer = X509Name.__new__(X509Name)
2071 issuer._name = _issuer
2072 return issuer
2073
2074 def set_version(self, version):
2075 """
2076 Set the CRL version.
2077
2078 .. versionadded:: 16.1.0
2079
2080 :param int version: The version of the CRL.
2081 :return: ``None``
2082 """
2083 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2084
2085 def _set_boundary_time(self, which, when):
2086 return _set_asn1_time(which(self._crl), when)
2087
2088 def set_lastUpdate(self, when):
2089 """
2090 Set when the CRL was last updated.
2091
Paul Kehrerce98ee62017-06-21 06:59:58 -10002092 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002093
2094 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002095
2096 .. versionadded:: 16.1.0
2097
2098 :param bytes when: A timestamp string.
2099 :return: ``None``
2100 """
2101 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2102
2103 def set_nextUpdate(self, when):
2104 """
2105 Set when the CRL will next be udpated.
2106
Paul Kehrerce98ee62017-06-21 06:59:58 -10002107 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002108
2109 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002110
2111 .. versionadded:: 16.1.0
2112
2113 :param bytes when: A timestamp string.
2114 :return: ``None``
2115 """
2116 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2117
2118 def sign(self, issuer_cert, issuer_key, digest):
2119 """
2120 Sign the CRL.
2121
2122 Signing a CRL enables clients to associate the CRL itself with an
2123 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2124 be signed by an issuer.
2125
2126 This method implicitly sets the issuer's name based on the issuer
2127 certificate and private key used to sign the CRL.
2128
2129 .. versionadded:: 16.1.0
2130
2131 :param X509 issuer_cert: The issuer's certificate.
2132 :param PKey issuer_key: The issuer's private key.
2133 :param bytes digest: The digest method to sign the CRL with.
2134 """
2135 digest_obj = _lib.EVP_get_digestbyname(digest)
2136 _openssl_assert(digest_obj != _ffi.NULL)
2137 _lib.X509_CRL_set_issuer_name(
2138 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2139 _lib.X509_CRL_sort(self._crl)
2140 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2141 _openssl_assert(result != 0)
2142
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002143 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002144 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002145 """
Dan Sully44e767a2016-06-04 18:05:27 -07002146 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002147
Dan Sully44e767a2016-06-04 18:05:27 -07002148 :param X509 cert: The certificate used to sign the CRL.
2149 :param PKey key: The key used to sign the CRL.
2150 :param int type: The export format, either :data:`FILETYPE_PEM`,
2151 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002152 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002153 :param bytes digest: The name of the message digest to use (eg
Alex Gaynor239e2d32016-09-11 12:36:35 -04002154 ``b"sha2566"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002155 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002156 """
Dan Sully44e767a2016-06-04 18:05:27 -07002157
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002158 if not isinstance(cert, X509):
2159 raise TypeError("cert must be an X509 instance")
2160 if not isinstance(key, PKey):
2161 raise TypeError("key must be a PKey instance")
2162 if not isinstance(type, int):
2163 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002164
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002165 if digest is _UNSPECIFIED:
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002166 _warn(
2167 "The default message digest (md5) is deprecated. "
2168 "Pass the name of a message digest explicitly.",
2169 category=DeprecationWarning,
2170 stacklevel=2,
2171 )
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002172 digest = b"md5"
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002173
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002174 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002175 if digest_obj == _ffi.NULL:
2176 raise ValueError("No such digest method")
2177
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002178 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002179 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002180
Alex Gaynora738ed52015-09-05 11:17:10 -04002181 # A scratch time object to give different values to different CRL
2182 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002183 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002184 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002185
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002186 _lib.X509_gmtime_adj(sometime, 0)
2187 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002188
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002189 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2190 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002191
Alex Gaynor5945ea82015-09-05 14:59:06 -04002192 _lib.X509_CRL_set_issuer_name(
2193 self._crl, _lib.X509_get_subject_name(cert._x509)
2194 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002195
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002196 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002197 if not sign_result:
2198 _raise_current_error()
2199
Dominic Chenf05b2122015-10-13 16:32:35 +00002200 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002201
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002202
Alex Gaynor10d30832017-06-29 15:31:39 -07002203CRLType = deprecated(
2204 CRL, __name__,
2205 "CRLType has been deprecated, use CRL instead",
2206 DeprecationWarning
2207)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002208
2209
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002210class PKCS7(object):
2211 def type_is_signed(self):
2212 """
2213 Check if this NID_pkcs7_signed object
2214
2215 :return: True if the PKCS7 is of type signed
2216 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002217 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002218
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002219 def type_is_enveloped(self):
2220 """
2221 Check if this NID_pkcs7_enveloped object
2222
2223 :returns: True if the PKCS7 is of type enveloped
2224 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002225 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002226
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002227 def type_is_signedAndEnveloped(self):
2228 """
2229 Check if this NID_pkcs7_signedAndEnveloped object
2230
2231 :returns: True if the PKCS7 is of type signedAndEnveloped
2232 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002233 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002234
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002235 def type_is_data(self):
2236 """
2237 Check if this NID_pkcs7_data object
2238
2239 :return: True if the PKCS7 is of type data
2240 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002241 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002242
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002243 def get_type_name(self):
2244 """
2245 Returns the type name of the PKCS7 structure
2246
2247 :return: A string with the typename
2248 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002249 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2250 string_type = _lib.OBJ_nid2sn(nid)
2251 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002252
Alex Chanc6077062016-11-18 13:53:39 +00002253
Alex Gaynor10d30832017-06-29 15:31:39 -07002254PKCS7Type = deprecated(
2255 PKCS7, __name__,
2256 "PKCS7Type has been deprecated, use PKCS7 instead",
2257 DeprecationWarning
2258)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002259
2260
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002261class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002262 """
2263 A PKCS #12 archive.
2264 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002265
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002266 def __init__(self):
2267 self._pkey = None
2268 self._cert = None
2269 self._cacerts = None
2270 self._friendlyname = None
2271
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002272 def get_certificate(self):
2273 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002274 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002275
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002276 :return: The certificate, or :py:const:`None` if there is none.
2277 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002278 """
2279 return self._cert
2280
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002281 def set_certificate(self, cert):
2282 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002283 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002284
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002285 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002286 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002287
Dan Sully44e767a2016-06-04 18:05:27 -07002288 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002289 """
2290 if not isinstance(cert, X509):
2291 raise TypeError("cert must be an X509 instance")
2292 self._cert = cert
2293
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002294 def get_privatekey(self):
2295 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002296 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002297
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002298 :return: The private key, or :py:const:`None` if there is none.
2299 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002300 """
2301 return self._pkey
2302
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002303 def set_privatekey(self, pkey):
2304 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002305 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002306
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002307 :param pkey: The new private key, or :py:const:`None` to unset it.
2308 :type pkey: :py:class:`PKey` or :py:const:`None`
2309
Dan Sully44e767a2016-06-04 18:05:27 -07002310 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002311 """
2312 if not isinstance(pkey, PKey):
2313 raise TypeError("pkey must be a PKey instance")
2314 self._pkey = pkey
2315
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002316 def get_ca_certificates(self):
2317 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002318 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002319
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002320 :return: A tuple with the CA certificates in the chain, or
2321 :py:const:`None` if there are none.
2322 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002323 """
2324 if self._cacerts is not None:
2325 return tuple(self._cacerts)
2326
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002327 def set_ca_certificates(self, cacerts):
2328 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002329 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002330
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002331 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2332 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002333 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002334
Dan Sully44e767a2016-06-04 18:05:27 -07002335 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002336 """
2337 if cacerts is None:
2338 self._cacerts = None
2339 else:
2340 cacerts = list(cacerts)
2341 for cert in cacerts:
2342 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002343 raise TypeError(
2344 "iterable must only contain X509 instances"
2345 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002346 self._cacerts = cacerts
2347
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002348 def set_friendlyname(self, name):
2349 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002350 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002351
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002352 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002353 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002354
Dan Sully44e767a2016-06-04 18:05:27 -07002355 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002356 """
2357 if name is None:
2358 self._friendlyname = None
2359 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002360 raise TypeError(
2361 "name must be a byte string or None (not %r)" % (name,)
2362 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002363 self._friendlyname = name
2364
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002365 def get_friendlyname(self):
2366 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002367 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002368
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002369 :returns: The friendly name, or :py:const:`None` if there is none.
2370 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002371 """
2372 return self._friendlyname
2373
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002374 def export(self, passphrase=None, iter=2048, maciter=1):
2375 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002376 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002377
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002378 For more information, see the :c:func:`PKCS12_create` man page.
2379
2380 :param passphrase: The passphrase used to encrypt the structure. Unlike
2381 some other passphrase arguments, this *must* be a string, not a
2382 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002383 :type passphrase: :py:data:`bytes`
2384
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002385 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002386 :type iter: :py:data:`int`
2387
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002388 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002389 :type maciter: :py:data:`int`
2390
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002391 :return: The string representation of the PKCS #12 structure.
2392 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002393 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002394 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002395
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002396 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002397 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002398 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002399 cacerts = _lib.sk_X509_new_null()
2400 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002401 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002402 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002403
2404 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002405 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002406
2407 friendlyname = self._friendlyname
2408 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002409 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002410
2411 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002412 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002413 else:
2414 pkey = self._pkey._pkey
2415
2416 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002417 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002418 else:
2419 cert = self._cert._x509
2420
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002421 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002422 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002423 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2424 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002425 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002426 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002427 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002428 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002429
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002430 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002431 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002432 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002433
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002434
Alex Gaynor10d30832017-06-29 15:31:39 -07002435PKCS12Type = deprecated(
2436 PKCS12, __name__,
2437 "PKCS12Type has been deprecated, use PKCS12 instead",
2438 DeprecationWarning
2439)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002440
2441
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002442class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002443 """
2444 A Netscape SPKI object.
2445 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002446
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002447 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002448 spki = _lib.NETSCAPE_SPKI_new()
2449 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002450
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002451 def sign(self, pkey, digest):
2452 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002453 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002454
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002455 :param pkey: The private key to sign with.
2456 :type pkey: :py:class:`PKey`
2457
2458 :param digest: The message digest to use.
2459 :type digest: :py:class:`bytes`
2460
Dan Sully44e767a2016-06-04 18:05:27 -07002461 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002462 """
2463 if pkey._only_public:
2464 raise ValueError("Key has only public part")
2465
2466 if not pkey._initialized:
2467 raise ValueError("Key is uninitialized")
2468
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002469 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002470 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002471 raise ValueError("No such digest method")
2472
Alex Gaynor5945ea82015-09-05 14:59:06 -04002473 sign_result = _lib.NETSCAPE_SPKI_sign(
2474 self._spki, pkey._pkey, digest_obj
2475 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002476 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002477
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002478 def verify(self, key):
2479 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002480 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002481
Hynek Schlawack01c31672016-12-11 15:14:09 +01002482 :param PKey key: The public key that signature is supposedly from.
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002483
Hynek Schlawack01c31672016-12-11 15:14:09 +01002484 :return: ``True`` if the signature is correct.
2485 :rtype: bool
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002486
Hynek Schlawack01c31672016-12-11 15:14:09 +01002487 :raises OpenSSL.crypto.Error: If the signature is invalid, or there was
2488 a problem verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002489 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002490 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002491 if answer <= 0:
2492 _raise_current_error()
2493 return True
2494
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002495 def b64_encode(self):
2496 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002497 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002498
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002499 :return: The base64 encoded string.
2500 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002501 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002502 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2503 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002504 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002505 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002506
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002507 def get_pubkey(self):
2508 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002509 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002510
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002511 :return: The public key.
2512 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002513 """
2514 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002515 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002516 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002517 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002518 pkey._only_public = True
2519 return pkey
2520
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002521 def set_pubkey(self, pkey):
2522 """
2523 Set the public key of the certificate
2524
2525 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002526 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002527 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002528 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002529 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002530
2531
Alex Gaynor10d30832017-06-29 15:31:39 -07002532NetscapeSPKIType = deprecated(
2533 NetscapeSPKI, __name__,
2534 "NetscapeSPKIType has been deprecated, use NetscapeSPKI instead",
2535 DeprecationWarning
2536)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002537
2538
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002539class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002540 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002541 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002542 raise ValueError(
2543 "only FILETYPE_PEM key format supports encryption"
2544 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002545 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002546 self._more_args = more_args
2547 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002548 self._problems = []
2549
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002550 @property
2551 def callback(self):
2552 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002553 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002554 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002555 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002556 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002557 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002558 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002559 raise TypeError(
2560 "Last argument must be a byte string or a callable."
2561 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002562
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002563 @property
2564 def callback_args(self):
2565 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002566 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002567 elif isinstance(self._passphrase, bytes):
2568 return self._passphrase
2569 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002570 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002571 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002572 raise TypeError(
2573 "Last argument must be a byte string or a callable."
2574 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002575
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002576 def raise_if_problem(self, exceptionType=Error):
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002577 if self._problems:
Greg Bowser36eb2de2017-01-24 11:38:55 -05002578
2579 # Flush the OpenSSL error queue
2580 try:
2581 _exception_from_error_queue(exceptionType)
2582 except exceptionType:
2583 pass
2584
2585 raise self._problems.pop(0)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002586
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002587 def _read_passphrase(self, buf, size, rwflag, userdata):
2588 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002589 if self._more_args:
2590 result = self._passphrase(size, rwflag, userdata)
2591 else:
2592 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002593 if not isinstance(result, bytes):
2594 raise ValueError("String expected")
2595 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002596 if self._truncate:
2597 result = result[:size]
2598 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002599 raise ValueError(
2600 "passphrase returned by callback is too long"
2601 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002602 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002603 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002604 return len(result)
2605 except Exception as e:
2606 self._problems.append(e)
2607 return 0
2608
2609
Cory Benfield6492f7c2015-10-27 16:57:58 +09002610def load_publickey(type, buffer):
2611 """
Cory Benfield11c10192015-10-27 17:23:03 +09002612 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002613
Cory Benfield9c590b92015-10-28 14:55:05 +09002614 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002615 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002616 :param buffer: The buffer the key is stored in.
2617 :type buffer: A Python string object, either unicode or bytestring.
2618 :return: The PKey object.
2619 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002620 """
2621 if isinstance(buffer, _text_type):
2622 buffer = buffer.encode("ascii")
2623
2624 bio = _new_mem_buf(buffer)
2625
2626 if type == FILETYPE_PEM:
2627 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2628 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2629 elif type == FILETYPE_ASN1:
2630 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2631 else:
2632 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2633
2634 if evp_pkey == _ffi.NULL:
2635 _raise_current_error()
2636
2637 pkey = PKey.__new__(PKey)
2638 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002639 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002640 return pkey
2641
2642
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002643def load_privatekey(type, buffer, passphrase=None):
2644 """
2645 Load a private key from a buffer
2646
2647 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2648 :param buffer: The buffer the key is stored in
2649 :param passphrase: (optional) if encrypted PEM format, this can be
2650 either the passphrase to use, or a callback for
2651 providing the passphrase.
2652
2653 :return: The PKey object
2654 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002655 if isinstance(buffer, _text_type):
2656 buffer = buffer.encode("ascii")
2657
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002658 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002659
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002660 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002661 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002662 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2663 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002664 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002665 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002666 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002667 else:
2668 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2669
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002670 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002671 _raise_current_error()
2672
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002673 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002674 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002675 return pkey
2676
2677
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002678def dump_certificate_request(type, req):
2679 """
2680 Dump a certificate request to a buffer
2681
2682 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2683 :param req: The certificate request to dump
2684 :return: The buffer with the dumped certificate request in
2685 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002686 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002687
2688 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002689 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002690 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002691 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002692 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002693 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002694 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002695 raise ValueError(
2696 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2697 "FILETYPE_TEXT"
2698 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002699
Alex Gaynor09a386e2016-07-03 09:32:44 -04002700 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002701
2702 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002703
2704
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002705def load_certificate_request(type, buffer):
2706 """
2707 Load a certificate request from a buffer
2708
2709 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2710 :param buffer: The buffer the certificate request is stored in
2711 :return: The X509Req 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 Calderone066f0572013-02-20 13:43:44 -08002717
2718 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002719 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002720 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002721 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002722 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002723 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002724
Alex Gaynoradd5b072016-06-04 21:04:00 -07002725 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002726
2727 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002728 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002729 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002730
2731
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002732def sign(pkey, data, digest):
2733 """
2734 Sign data with a digest
2735
2736 :param pkey: Pkey to sign with
2737 :param data: data to be signed
2738 :param digest: message digest to use
2739 :return: signature
2740 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002741 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002742
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002743 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002744 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002745 raise ValueError("No such digest method")
2746
Alex Gaynor67903a62016-06-02 10:37:13 -07002747 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002748 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002749
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002750 _lib.EVP_SignInit(md_ctx, digest_obj)
2751 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002752
Colleen Murphye09399b2016-03-01 17:40:49 -08002753 pkey_length = (PKey.bits(pkey) + 7) // 8
2754 signature_buffer = _ffi.new("unsigned char[]", pkey_length)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002755 signature_length = _ffi.new("unsigned int*")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002756 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002757 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002758 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002759
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002760 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002761
2762
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002763def verify(cert, signature, data, digest):
2764 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002765 Verify a signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002766
2767 :param cert: signing certificate (X509 object)
2768 :param signature: signature returned by sign function
2769 :param data: data to be verified
2770 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002771 :return: ``None`` if the signature is correct, raise exception otherwise.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002772 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002773 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002774
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002775 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002776 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002777 raise ValueError("No such digest method")
2778
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002779 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002780 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002781 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002782
Alex Gaynor67903a62016-06-02 10:37:13 -07002783 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002784 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002785
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002786 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2787 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002788 verify_result = _lib.EVP_VerifyFinal(
2789 md_ctx, signature, len(signature), pkey
2790 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002791
2792 if verify_result != 1:
2793 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002794
2795
Dominic Chenf05b2122015-10-13 16:32:35 +00002796def dump_crl(type, crl):
2797 """
2798 Dump a certificate revocation list to a buffer.
2799
2800 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2801 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002802 :param CRL crl: The CRL to dump.
2803
Dominic Chenf05b2122015-10-13 16:32:35 +00002804 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002805 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002806 """
2807 bio = _new_mem_buf()
2808
2809 if type == FILETYPE_PEM:
2810 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2811 elif type == FILETYPE_ASN1:
2812 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2813 elif type == FILETYPE_TEXT:
2814 ret = _lib.X509_CRL_print(bio, crl._crl)
2815 else:
2816 raise ValueError(
2817 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2818 "FILETYPE_TEXT")
2819
2820 assert ret == 1
2821 return _bio_to_string(bio)
2822
2823
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002824def load_crl(type, buffer):
2825 """
2826 Load a certificate revocation list from a buffer
2827
2828 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2829 :param buffer: The buffer the CRL is stored in
2830
2831 :return: The PKey object
2832 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002833 if isinstance(buffer, _text_type):
2834 buffer = buffer.encode("ascii")
2835
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002836 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002837
2838 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002839 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002840 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002841 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002842 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002843 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2844
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002845 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002846 _raise_current_error()
2847
2848 result = CRL.__new__(CRL)
2849 result._crl = crl
2850 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002851
2852
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002853def load_pkcs7_data(type, buffer):
2854 """
2855 Load pkcs7 data from a buffer
2856
2857 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2858 :param buffer: The buffer with the pkcs7 data.
2859 :return: The PKCS7 object
2860 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002861 if isinstance(buffer, _text_type):
2862 buffer = buffer.encode("ascii")
2863
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002864 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002865
2866 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002867 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002868 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002869 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002870 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002871 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2872
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002873 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002874 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002875
2876 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002877 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002878 return pypkcs7
2879
2880
Stephen Holsapple38482622014-04-05 20:29:34 -07002881def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002882 """
2883 Load a PKCS12 object from a buffer
2884
2885 :param buffer: The buffer the certificate is stored in
2886 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2887 :returns: The PKCS12 object
2888 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002889 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002890
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 Calderonee5912ce2013-02-21 10:49:35 -08002895
Stephen Holsapple38482622014-04-05 20:29:34 -07002896 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2897 # password based encryption no password and a zero length password are two
2898 # different things, but OpenSSL implementation will try both to figure out
2899 # which one works.
2900 if not passphrase:
2901 passphrase = _ffi.NULL
2902
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002903 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2904 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002905 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002906 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002907
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002908 pkey = _ffi.new("EVP_PKEY**")
2909 cert = _ffi.new("X509**")
2910 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002911
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002912 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002913 if not parse_result:
2914 _raise_current_error()
2915
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002916 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002917
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002918 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
2919 # queue for no particular reason. This error isn't interesting to anyone
2920 # outside this function. It's not even interesting to us. Get rid of it.
2921 try:
2922 _raise_current_error()
2923 except Error:
2924 pass
2925
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002926 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002927 pykey = None
2928 else:
2929 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002930 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002931
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002932 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002933 pycert = None
2934 friendlyname = None
2935 else:
2936 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002937 pycert._x509 = _ffi.gc(cert[0], _lib.X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002938
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002939 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04002940 friendlyname_buffer = _lib.X509_alias_get0(
2941 cert[0], friendlyname_length
2942 )
2943 friendlyname = _ffi.buffer(
2944 friendlyname_buffer, friendlyname_length[0]
2945 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002946 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002947 friendlyname = None
2948
2949 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002950 for i in range(_lib.sk_X509_num(cacerts)):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002951 pycacert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002952 pycacert._x509 = _lib.sk_X509_value(cacerts, i)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002953 pycacerts.append(pycacert)
2954 if not pycacerts:
2955 pycacerts = None
2956
2957 pkcs12 = PKCS12.__new__(PKCS12)
2958 pkcs12._pkey = pykey
2959 pkcs12._cert = pycert
2960 pkcs12._cacerts = pycacerts
2961 pkcs12._friendlyname = friendlyname
2962 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05002963
2964
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05002965# There are no direct unit tests for this initialization. It is tested
2966# indirectly since it is necessary for functions like dump_privatekey when
2967# using encryption.
2968#
2969# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
2970# and some other similar tests may fail without this (though they may not if
2971# the Python runtime has already done some initialization of the underlying
2972# OpenSSL library (and is linked against the same one that cryptography is
2973# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05002974_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05002975
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05002976# This is similar but exercised mainly by exception_from_error_queue. It calls
2977# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
2978_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002979
2980
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002981# Set the default string mask to match OpenSSL upstream (since 2005) and
2982# RFC5280 recommendations.
2983_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')