blob: d555083f1488279d385f28dcdd0901dc1d518a1a [file] [log] [blame]
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001import datetime
Paul Kehrer8d887e12015-10-24 09:09:55 -05002
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003from base64 import b16encode
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05004from functools import partial
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05005from operator import __eq__, __ne__, __lt__, __le__, __gt__, __ge__
6
7from six import (
8 integer_types as _integer_types,
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -04009 text_type as _text_type,
10 PY3 as _PY3)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080011
Alex Gaynor9939ba12017-06-25 16:28:24 -040012from cryptography import x509
Paul Kehrer72d968b2016-07-29 15:31:04 +080013from cryptography.hazmat.primitives.asymmetric import dsa, rsa
Alex Gaynor10d30832017-06-29 15:31:39 -070014from cryptography.utils import deprecated
Paul Kehrer72d968b2016-07-29 15:31:04 +080015
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050016from OpenSSL._util import (
17 ffi as _ffi,
18 lib as _lib,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050019 exception_from_error_queue as _exception_from_error_queue,
20 byte_string as _byte_string,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040021 native as _native,
22 UNSPECIFIED as _UNSPECIFIED,
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -040023 text_to_bytes_and_warn as _text_to_bytes_and_warn,
Alex Gaynor67903a62016-06-02 10:37:13 -070024 make_assert as _make_assert,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040025)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080026
Nicolas Karolak736c6212017-11-26 14:40:28 +010027__all__ = [
28 'FILETYPE_PEM',
29 'FILETYPE_ASN1',
30 'FILETYPE_TEXT',
31 'TYPE_RSA',
32 'TYPE_DSA',
33 'Error',
34 'PKey',
35 'get_elliptic_curves',
36 'get_elliptic_curve',
37 'X509Name',
38 'X509Extension',
39 'X509Req',
40 'X509',
41 'X509StoreFlags',
42 'X509Store',
43 'X509StoreContextError',
44 'X509StoreContext',
45 'load_certificate',
46 'dump_certificate',
47 'dump_publickey',
48 'dump_privatekey',
49 'Revoked',
50 'CRL',
51 'PKCS7',
52 'PKCS12',
53 'NetscapeSPKI',
54 'load_publickey',
55 'load_privatekey',
56 'dump_certificate_request',
57 'load_certificate_request',
58 'sign',
59 'verify',
60 'dump_crl',
61 'load_crl',
62 'load_pkcs7_data',
63 'load_pkcs12'
64]
65
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050066FILETYPE_PEM = _lib.SSL_FILETYPE_PEM
67FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080068
69# TODO This was an API mistake. OpenSSL has no such constant.
70FILETYPE_TEXT = 2 ** 16 - 1
71
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050072TYPE_RSA = _lib.EVP_PKEY_RSA
73TYPE_DSA = _lib.EVP_PKEY_DSA
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -080074
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080075
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050076class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050077 """
78 An error occurred in an `OpenSSL.crypto` API.
79 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050080
81
82_raise_current_error = partial(_exception_from_error_queue, Error)
Alex Gaynor67903a62016-06-02 10:37:13 -070083_openssl_assert = _make_assert(Error)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050084
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070085
Paul Kehrereb633842016-10-06 11:22:01 +020086def _get_backend():
87 """
88 Importing the backend from cryptography has the side effect of activating
89 the osrandom engine. This mutates the global state of OpenSSL in the
90 process and causes issues for various programs that use subinterpreters or
91 embed Python. By putting the import in this function we can avoid
92 triggering this side effect unless _get_backend is called.
93 """
94 from cryptography.hazmat.backends.openssl.backend import backend
95 return backend
96
97
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050098def _untested_error(where):
99 """
100 An OpenSSL API failed somehow. Additionally, the failure which was
101 encountered isn't one that's exercised by the test suite so future behavior
102 of pyOpenSSL is now somewhat less predictable.
103 """
104 raise RuntimeError("Unknown %s failure" % (where,))
105
106
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500107def _new_mem_buf(buffer=None):
108 """
109 Allocate a new OpenSSL memory BIO.
110
111 Arrange for the garbage collector to clean it up automatically.
112
113 :param buffer: None or some bytes to use to put into the BIO so that they
114 can be read out.
115 """
116 if buffer is None:
117 bio = _lib.BIO_new(_lib.BIO_s_mem())
118 free = _lib.BIO_free
119 else:
120 data = _ffi.new("char[]", buffer)
121 bio = _lib.BIO_new_mem_buf(data, len(buffer))
Alex Gaynor5945ea82015-09-05 14:59:06 -0400122
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500123 # Keep the memory alive as long as the bio is alive!
124 def free(bio, ref=data):
125 return _lib.BIO_free(bio)
126
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700127 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500128
129 bio = _ffi.gc(bio, free)
130 return bio
131
132
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800133def _bio_to_string(bio):
134 """
135 Copy the contents of an OpenSSL BIO object into a Python byte string.
136 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500137 result_buffer = _ffi.new('char**')
138 buffer_length = _lib.BIO_get_mem_data(bio, result_buffer)
139 return _ffi.buffer(result_buffer[0], buffer_length)[:]
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800140
141
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800142def _set_asn1_time(boundary, when):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500143 """
144 The the time value of an ASN1 time object.
145
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900146 @param boundary: An ASN1_TIME pointer (or an object safely
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500147 castable to that type) which will have its value set.
148 @param when: A string representation of the desired time value.
149
150 @raise TypeError: If C{when} is not a L{bytes} string.
151 @raise ValueError: If C{when} does not represent a time in the required
152 format.
153 @raise RuntimeError: If the time value cannot be set for some other
154 (unspecified) reason.
155 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800156 if not isinstance(when, bytes):
157 raise TypeError("when must be a byte string")
158
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900159 set_result = _lib.ASN1_TIME_set_string(boundary, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800160 if set_result == 0:
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900161 raise ValueError("Invalid string")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800162
Alex Gaynor510293e2016-06-02 12:07:59 -0700163
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800164def _get_asn1_time(timestamp):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500165 """
166 Retrieve the time value of an ASN1 time object.
167
168 @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to
169 that type) from which the time value will be retrieved.
170
171 @return: The time value from C{timestamp} as a L{bytes} string in a certain
172 format. Or C{None} if the object contains no time value.
173 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500174 string_timestamp = _ffi.cast('ASN1_STRING*', timestamp)
175 if _lib.ASN1_STRING_length(string_timestamp) == 0:
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800176 return None
Alex Gaynor5945ea82015-09-05 14:59:06 -0400177 elif (
178 _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME
179 ):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500180 return _ffi.string(_lib.ASN1_STRING_data(string_timestamp))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800181 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500182 generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**")
183 _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp)
184 if generalized_timestamp[0] == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500185 # This may happen:
186 # - if timestamp was not an ASN1_TIME
187 # - if allocating memory for the ASN1_GENERALIZEDTIME failed
188 # - if a copy of the time data from timestamp cannot be made for
189 # the newly allocated ASN1_GENERALIZEDTIME
190 #
191 # These are difficult to test. cffi enforces the ASN1_TIME type.
192 # Memory allocation failures are a pain to trigger
193 # deterministically.
194 _untested_error("ASN1_TIME_to_generalizedtime")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800195 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500196 string_timestamp = _ffi.cast(
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800197 "ASN1_STRING*", generalized_timestamp[0])
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500198 string_data = _lib.ASN1_STRING_data(string_timestamp)
199 string_result = _ffi.string(string_data)
200 _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0])
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800201 return string_result
202
203
Alex Gaynor4aa52c32017-11-20 09:04:08 -0500204class _X509NameInvalidator(object):
205 def __init__(self):
206 self._names = []
207
208 def add(self, name):
209 self._names.append(name)
210
211 def clear(self):
212 for name in self._names:
213 # Breaks the object, but also prevents UAF!
214 del name._name
215
216
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800217class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200218 """
219 A class representing an DSA or RSA public key or key pair.
220 """
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800221 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800222 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800223
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800224 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500225 pkey = _lib.EVP_PKEY_new()
226 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800227 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800228
Paul Kehrer72d968b2016-07-29 15:31:04 +0800229 def to_cryptography_key(self):
230 """
231 Export as a ``cryptography`` key.
232
233 :rtype: One of ``cryptography``'s `key interfaces`_.
234
235 .. _key interfaces: https://cryptography.io/en/latest/hazmat/\
236 primitives/asymmetric/rsa/#key-interfaces
237
238 .. versionadded:: 16.1.0
239 """
Paul Kehrereb633842016-10-06 11:22:01 +0200240 backend = _get_backend()
Paul Kehrer72d968b2016-07-29 15:31:04 +0800241 if self._only_public:
242 return backend._evp_pkey_to_public_key(self._pkey)
243 else:
244 return backend._evp_pkey_to_private_key(self._pkey)
245
246 @classmethod
247 def from_cryptography_key(cls, crypto_key):
248 """
249 Construct based on a ``cryptography`` *crypto_key*.
250
251 :param crypto_key: A ``cryptography`` key.
252 :type crypto_key: One of ``cryptography``'s `key interfaces`_.
253
254 :rtype: PKey
255
256 .. versionadded:: 16.1.0
257 """
258 pkey = cls()
259 if not isinstance(crypto_key, (rsa.RSAPublicKey, rsa.RSAPrivateKey,
260 dsa.DSAPublicKey, dsa.DSAPrivateKey)):
261 raise TypeError("Unsupported key type")
262
263 pkey._pkey = crypto_key._evp_pkey
264 if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)):
265 pkey._only_public = True
266 pkey._initialized = True
267 return pkey
268
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800269 def generate_key(self, type, bits):
270 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700271 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800272
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200273 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800274
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200275 :param type: The key type.
276 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
277 :param bits: The number of bits.
278 :type bits: :py:data:`int` ``>= 0``
279 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
280 of the appropriate type.
281 :raises ValueError: If the number of bits isn't an integer of
282 the appropriate size.
Dan Sully44e767a2016-06-04 18:05:27 -0700283 :return: ``None``
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800284 """
285 if not isinstance(type, int):
286 raise TypeError("type must be an integer")
287
288 if not isinstance(bits, int):
289 raise TypeError("bits must be an integer")
290
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800291 if type == TYPE_RSA:
292 if bits <= 0:
293 raise ValueError("Invalid number of bits")
294
David Benjamin179eb1d2018-06-05 17:56:07 -0400295 # TODO Check error return
296 exponent = _lib.BN_new()
297 exponent = _ffi.gc(exponent, _lib.BN_free)
298 _lib.BN_set_word(exponent, _lib.RSA_F4)
299
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500300 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800301
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500302 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400303 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800304
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500305 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400306 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800307
308 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400309 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700310 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400311
312 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400313 res = _lib.DSA_generate_parameters_ex(
314 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
315 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700316 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400317
318 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
319 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800320 else:
321 raise Error("No such key type")
322
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800323 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800324
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800325 def check(self):
326 """
327 Check the consistency of an RSA private key.
328
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200329 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
330
Hynek Schlawack01c31672016-12-11 15:14:09 +0100331 :return: ``True`` if key is consistent.
332
333 :raise OpenSSL.crypto.Error: if the key is inconsistent.
334
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800335 :raise TypeError: if the key is of a type which cannot be checked.
336 Only RSA keys can currently be checked.
337 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800338 if self._only_public:
339 raise TypeError("public key only")
340
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100341 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800342 raise TypeError("key type unsupported")
343
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500344 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
345 rsa = _ffi.gc(rsa, _lib.RSA_free)
346 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800347 if result:
348 return True
349 _raise_current_error()
350
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800351 def type(self):
352 """
353 Returns the type of the key
354
355 :return: The type of the key.
356 """
Alex Gaynor0d2aec52017-05-31 04:26:27 -0400357 return _lib.EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800358
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800359 def bits(self):
360 """
361 Returns the number of bits of the key
362
363 :return: The number of bits of the key.
364 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500365 return _lib.EVP_PKEY_bits(self._pkey)
Alex Chanc6077062016-11-18 13:53:39 +0000366
367
Alex Gaynor10d30832017-06-29 15:31:39 -0700368PKeyType = deprecated(
369 PKey, __name__,
370 "PKeyType has been deprecated, use PKey instead",
371 DeprecationWarning
372)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800373
374
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400375class _EllipticCurve(object):
376 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400377 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400378
379 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
380 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
381 instances each of which represents one curve supported by the system.
382 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400383 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400384 _curves = None
385
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400386 if _PY3:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400387 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400388 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400389 """
390 Implement cooperation with the right-hand side argument of ``!=``.
391
392 Python 3 seems to have dropped this cooperation in this very narrow
393 circumstance.
394 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400395 if isinstance(other, _EllipticCurve):
396 return super(_EllipticCurve, self).__ne__(other)
397 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400398
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400399 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400400 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400401 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400402 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400403
404 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400405
406 :return: A :py:type:`set` of ``cls`` instances giving the names of the
407 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400408 """
Alex Chan84902a22017-04-20 11:50:47 +0100409 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
410 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
411 # The return value on this call should be num_curves again. We
412 # could check it to make sure but if it *isn't* then.. what could
413 # we do? Abort the whole process, I suppose...? -exarkun
414 lib.EC_get_builtin_curves(builtin_curves, num_curves)
415 return set(
416 cls.from_nid(lib, c.nid)
417 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400418
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400419 @classmethod
420 def _get_elliptic_curves(cls, lib):
421 """
422 Get, cache, and return the curves supported by OpenSSL.
423
424 :param lib: The OpenSSL library binding object.
425
426 :return: A :py:type:`set` of ``cls`` instances giving the names of the
427 elliptic curves the underlying library supports.
428 """
429 if cls._curves is None:
430 cls._curves = cls._load_elliptic_curves(lib)
431 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400432
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400433 @classmethod
434 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400435 """
436 Instantiate a new :py:class:`_EllipticCurve` associated with the given
437 OpenSSL NID.
438
439 :param lib: The OpenSSL library binding object.
440
441 :param nid: The OpenSSL NID the resulting curve object will represent.
442 This must be a curve NID (and not, for example, a hash NID) or
443 subsequent operations will fail in unpredictable ways.
444 :type nid: :py:class:`int`
445
446 :return: The curve object.
447 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400448 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
449
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400450 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400451 """
452 :param _lib: The :py:mod:`cryptography` binding instance used to
453 interface with OpenSSL.
454
455 :param _nid: The OpenSSL NID identifying the curve this object
456 represents.
457 :type _nid: :py:class:`int`
458
459 :param name: The OpenSSL short name identifying the curve this object
460 represents.
461 :type name: :py:class:`unicode`
462 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400463 self._lib = lib
464 self._nid = nid
465 self.name = name
466
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400467 def __repr__(self):
468 return "<Curve %r>" % (self.name,)
469
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400470 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400471 """
472 Create a new OpenSSL EC_KEY structure initialized to use this curve.
473
474 The structure is automatically garbage collected when the Python object
475 is garbage collected.
476 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400477 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
478 return _ffi.gc(key, _lib.EC_KEY_free)
479
480
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400481def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400482 """
483 Return a set of objects representing the elliptic curves supported in the
484 OpenSSL build in use.
485
486 The curve objects have a :py:class:`unicode` ``name`` attribute by which
487 they identify themselves.
488
489 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400490 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
491 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400492 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400493 return _EllipticCurve._get_elliptic_curves(_lib)
494
495
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400496def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400497 """
498 Return a single curve object selected by name.
499
500 See :py:func:`get_elliptic_curves` for information about curve objects.
501
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400502 :param name: The OpenSSL short name identifying the curve object to
503 retrieve.
504 :type name: :py:class:`unicode`
505
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400506 If the named curve is not supported then :py:class:`ValueError` is raised.
507 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400508 for curve in get_elliptic_curves():
509 if curve.name == name:
510 return curve
511 raise ValueError("unknown curve name", name)
512
513
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800514class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200515 """
516 An X.509 Distinguished Name.
517
518 :ivar countryName: The country of the entity.
519 :ivar C: Alias for :py:attr:`countryName`.
520
521 :ivar stateOrProvinceName: The state or province of the entity.
522 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
523
524 :ivar localityName: The locality of the entity.
525 :ivar L: Alias for :py:attr:`localityName`.
526
527 :ivar organizationName: The organization name of the entity.
528 :ivar O: Alias for :py:attr:`organizationName`.
529
530 :ivar organizationalUnitName: The organizational unit of the entity.
531 :ivar OU: Alias for :py:attr:`organizationalUnitName`
532
533 :ivar commonName: The common name of the entity.
534 :ivar CN: Alias for :py:attr:`commonName`.
535
536 :ivar emailAddress: The e-mail address of the entity.
537 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400538
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800539 def __init__(self, name):
540 """
541 Create a new X509Name, copying the given X509Name instance.
542
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200543 :param name: The name to copy.
544 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800545 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500546 name = _lib.X509_NAME_dup(name._name)
547 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800548
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800549 def __setattr__(self, name, value):
550 if name.startswith('_'):
551 return super(X509Name, self).__setattr__(name, value)
552
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800553 # Note: we really do not want str subclasses here, so we do not use
554 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800555 if type(name) is not str:
556 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400557 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800558
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500559 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500560 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800561 try:
562 _raise_current_error()
563 except Error:
564 pass
565 raise AttributeError("No such attribute")
566
567 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500568 for i in range(_lib.X509_NAME_entry_count(self._name)):
569 ent = _lib.X509_NAME_get_entry(self._name, i)
570 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
571 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800572 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500573 ent = _lib.X509_NAME_delete_entry(self._name, i)
574 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800575 break
576
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500577 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800578 value = value.encode('utf-8')
579
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500580 add_result = _lib.X509_NAME_add_entry_by_NID(
581 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800582 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500583 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800584
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800585 def __getattr__(self, name):
586 """
587 Find attribute. An X509Name object has the following attributes:
588 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400589 organization (alias O), organizationalUnit (alias OU), commonName
590 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800591 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500592 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500593 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800594 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
595 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
596 # push something onto the error queue. If we don't clean that up
597 # now, someone else will bump into it later and be quite confused.
598 # See lp#314814.
599 try:
600 _raise_current_error()
601 except Error:
602 pass
603 return super(X509Name, self).__getattr__(name)
604
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500605 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800606 if entry_index == -1:
607 return None
608
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500609 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
610 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800611
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500612 result_buffer = _ffi.new("unsigned char**")
613 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400614 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800615
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700616 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400617 result = _ffi.buffer(
618 result_buffer[0], data_length
619 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700620 finally:
621 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500622 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800623 return result
624
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500625 def _cmp(op):
626 def f(self, other):
627 if not isinstance(other, X509Name):
628 return NotImplemented
629 result = _lib.X509_NAME_cmp(self._name, other._name)
630 return op(result, 0)
631 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800632
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500633 __eq__ = _cmp(__eq__)
634 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800635
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500636 __lt__ = _cmp(__lt__)
637 __le__ = _cmp(__le__)
638
639 __gt__ = _cmp(__gt__)
640 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800641
642 def __repr__(self):
643 """
644 String representation of an X509Name
645 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400646 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500647 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800648 self._name, result_buffer, len(result_buffer))
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700649 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800650
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500651 return "<X509Name object '%s'>" % (
652 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800653
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800654 def hash(self):
655 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200656 Return an integer representation of the first four bytes of the
657 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800658
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200659 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
660
661 :return: The (integer) hash of this name.
662 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800663 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500664 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800665
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800666 def der(self):
667 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200668 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800669
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200670 :return: The DER encoded form of this name.
671 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800672 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500673 result_buffer = _ffi.new('unsigned char**')
674 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400675 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800676
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500677 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
678 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800679 return string_result
680
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800681 def get_components(self):
682 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200683 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800684
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200685 :return: The components of this name.
686 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800687 """
688 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500689 for i in range(_lib.X509_NAME_entry_count(self._name)):
690 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800691
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500692 fname = _lib.X509_NAME_ENTRY_get_object(ent)
693 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800694
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500695 nid = _lib.OBJ_obj2nid(fname)
696 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800697
698 result.append((
Alex Gaynora738ed52015-09-05 11:17:10 -0400699 _ffi.string(name),
700 _ffi.string(
701 _lib.ASN1_STRING_data(fval),
702 _lib.ASN1_STRING_length(fval))))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800703
704 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200705
706
Alex Gaynor10d30832017-06-29 15:31:39 -0700707X509NameType = deprecated(
708 X509Name, __name__,
709 "X509NameType has been deprecated, use X509Name instead",
710 DeprecationWarning
711)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800712
713
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800714class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200715 """
716 An X.509 v3 certificate extension.
717 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400718
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800719 def __init__(self, type_name, critical, value, subject=None, issuer=None):
720 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200721 Initializes an X509 extension.
722
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100723 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400724 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800725
Alex Gaynor5945ea82015-09-05 14:59:06 -0400726 :param bool critical: A flag indicating whether this is a critical
727 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800728
729 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200730 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800731
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200732 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800733 :type subject: :py:class:`X509`
734
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200735 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800736 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100737
Alex Chan54005ce2017-03-21 08:08:17 +0000738 .. _extension: https://www.openssl.org/docs/manmaster/man5/
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100739 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800740 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500741 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800742
Alex Gaynor5945ea82015-09-05 14:59:06 -0400743 # A context is necessary for any extension which uses the r2i
744 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
745 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500746 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800747
748 # We have no configuration database - but perhaps we should (some
749 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500750 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800751
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800752 # Initialize the subject and issuer, if appropriate. ctx is a local,
753 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400754 # any references, so no need to mess with reference counts or
755 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800756 if issuer is not None:
757 if not isinstance(issuer, X509):
758 raise TypeError("issuer must be an X509 instance")
759 ctx.issuer_cert = issuer._x509
760 if subject is not None:
761 if not isinstance(subject, X509):
762 raise TypeError("subject must be an X509 instance")
763 ctx.subject_cert = subject._x509
764
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800765 if critical:
766 # There are other OpenSSL APIs which would let us pass in critical
767 # separately, but they're harder to use, and since value is already
768 # a pile of crappy junk smuggling a ton of utterly important
769 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400770 # with strings? (However, X509V3_EXT_i2d in particular seems like
771 # it would be a better API to invoke. I do not know where to get
772 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500773 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800774
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500775 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
776 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800777 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500778 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800779
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400780 @property
781 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400782 return _lib.OBJ_obj2nid(
783 _lib.X509_EXTENSION_get_object(self._extension)
784 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400785
786 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500787 _lib.GEN_EMAIL: "email",
788 _lib.GEN_DNS: "DNS",
789 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400790 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400791
792 def _subjectAltNameString(self):
Alex Gaynord61c46a2017-06-29 22:51:33 -0700793 names = _ffi.cast(
794 "GENERAL_NAMES*", _lib.X509V3_EXT_d2i(self._extension)
795 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400796
Paul Kehrerb7d79502015-05-04 07:43:51 -0500797 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400798 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500799 for i in range(_lib.sk_GENERAL_NAME_num(names)):
800 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400801 try:
802 label = self._prefixes[name.type]
803 except KeyError:
804 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500805 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500806 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400807 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500808 value = _native(
809 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
810 parts.append(label + ":" + value)
811 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400812
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800813 def __str__(self):
814 """
815 :return: a nice text representation of the extension
816 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500817 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400818 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800819
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400820 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500821 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400822 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800823
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500824 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800825
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800826 def get_critical(self):
827 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200828 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800829
830 :return: The critical field.
831 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500832 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800833
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800834 def get_short_name(self):
835 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200836 Returns the short type name of this X.509 extension.
837
838 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800839
840 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200841 :rtype: :py:data:`bytes`
842
843 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800844 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500845 obj = _lib.X509_EXTENSION_get_object(self._extension)
846 nid = _lib.OBJ_obj2nid(obj)
847 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800848
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800849 def get_data(self):
850 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200851 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800852
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200853 :return: The ASN.1 encoded data of this X509 extension.
854 :rtype: :py:data:`bytes`
855
856 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800857 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500858 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
859 string_result = _ffi.cast('ASN1_STRING*', octet_result)
860 char_result = _lib.ASN1_STRING_data(string_result)
861 result_length = _lib.ASN1_STRING_length(string_result)
862 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800863
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200864
Alex Gaynor10d30832017-06-29 15:31:39 -0700865X509ExtensionType = deprecated(
866 X509Extension, __name__,
867 "X509ExtensionType has been deprecated, use X509Extension instead",
868 DeprecationWarning
869)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800870
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800871
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800872class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200873 """
874 An X.509 certificate signing requests.
875 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400876
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800877 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500878 req = _lib.X509_REQ_new()
879 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Alex Gaynor5af32d02016-09-24 01:52:21 -0400880 # Default to version 0.
881 self.set_version(0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800882
Paul Kehrer41c10242017-06-29 18:24:17 -0500883 def to_cryptography(self):
884 """
885 Export as a ``cryptography`` certificate signing request.
886
887 :rtype: ``cryptography.x509.CertificateSigningRequest``
888
889 .. versionadded:: 17.1.0
890 """
891 from cryptography.hazmat.backends.openssl.x509 import (
892 _CertificateSigningRequest
893 )
894 backend = _get_backend()
895 return _CertificateSigningRequest(backend, self._req)
896
897 @classmethod
898 def from_cryptography(cls, crypto_req):
899 """
900 Construct based on a ``cryptography`` *crypto_req*.
901
902 :param crypto_req: A ``cryptography`` X.509 certificate signing request
903 :type crypto_req: ``cryptography.x509.CertificateSigningRequest``
904
905 :rtype: PKey
906
907 .. versionadded:: 17.1.0
908 """
909 if not isinstance(crypto_req, x509.CertificateSigningRequest):
910 raise TypeError("Must be a certificate signing request")
911
912 req = cls()
913 req._req = crypto_req._x509_req
914 return req
915
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800916 def set_pubkey(self, pkey):
917 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200918 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800919
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200920 :param pkey: The public key to use.
921 :type pkey: :py:class:`PKey`
922
Dan Sully44e767a2016-06-04 18:05:27 -0700923 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800924 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500925 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400926 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800927
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800928 def get_pubkey(self):
929 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200930 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800931
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200932 :return: The public key.
933 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800934 """
935 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500936 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700937 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500938 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800939 pkey._only_public = True
940 return pkey
941
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800942 def set_version(self, version):
943 """
944 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
945 request.
946
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200947 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700948 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800949 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500950 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400951 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800952
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800953 def get_version(self):
954 """
955 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
956 request.
957
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200958 :return: The value of the version subfield.
959 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800960 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500961 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800962
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800963 def get_subject(self):
964 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200965 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800966
Cory Benfield881dc8d2015-12-09 08:25:14 +0000967 This creates a new :class:`X509Name` that wraps the underlying subject
968 name field on the certificate signing request. Modifying it will modify
969 the underlying signing request, and will have the effect of modifying
970 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200971
972 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000973 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800974 """
975 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500976 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700977 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800978
979 # The name is owned by the X509Req structure. As long as the X509Name
980 # Python object is alive, keep the X509Req Python object alive.
981 name._owner = self
982
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800983 return name
984
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800985 def add_extensions(self, extensions):
986 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200987 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800988
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200989 :param extensions: The X.509 extensions to add.
990 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700991 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800992 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500993 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700994 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800995
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500996 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800997
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800998 for ext in extensions:
999 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -08001000 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001001
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001002 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001003 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001004
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001005 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001006 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001007
Stephen Holsappleadfd39d2014-01-28 17:58:31 -08001008 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001009 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001010 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -08001011
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001012 :return: The X.509 extensions in this request.
1013 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
1014
1015 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001016 """
1017 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -05001018 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -05001019 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001020 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -05001021 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001022 exts.append(ext)
1023 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -08001024
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001025 def sign(self, pkey, digest):
1026 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001027 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001028
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001029 :param pkey: The key pair to sign with.
1030 :type pkey: :py:class:`PKey`
1031 :param digest: The name of the message digest to use for the signature,
Alex Gaynor239e2d32016-09-11 12:36:35 -04001032 e.g. :py:data:`b"sha256"`.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001033 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -07001034 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001035 """
1036 if pkey._only_public:
1037 raise ValueError("Key has only public part")
1038
1039 if not pkey._initialized:
1040 raise ValueError("Key is uninitialized")
1041
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001042 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001043 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001044 raise ValueError("No such digest method")
1045
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001046 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001047 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001048
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001049 def verify(self, pkey):
1050 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001051 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001052
Hynek Schlawack01c31672016-12-11 15:14:09 +01001053 :param PKey key: A public key.
1054
1055 :return: ``True`` if the signature is correct.
1056 :rtype: bool
1057
1058 :raises OpenSSL.crypto.Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001059 problem verifying the signature.
1060 """
1061 if not isinstance(pkey, PKey):
1062 raise TypeError("pkey must be a PKey instance")
1063
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001064 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001065 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001066 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001067
1068 return result
1069
1070
Alex Gaynor10d30832017-06-29 15:31:39 -07001071X509ReqType = deprecated(
1072 X509Req, __name__,
1073 "X509ReqType has been deprecated, use X509Req instead",
1074 DeprecationWarning
1075)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001076
1077
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001078class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001079 """
1080 An X.509 certificate.
1081 """
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001082 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001083 x509 = _lib.X509_new()
Hynek Schlawack8a2dd772016-07-31 13:46:20 +02001084 _openssl_assert(x509 != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001085 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001086
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001087 self._issuer_invalidator = _X509NameInvalidator()
1088 self._subject_invalidator = _X509NameInvalidator()
1089
1090 @classmethod
1091 def _from_raw_x509_ptr(cls, x509):
1092 cert = cls.__new__(cls)
1093 cert._x509 = _ffi.gc(x509, _lib.X509_free)
1094 cert._issuer_invalidator = _X509NameInvalidator()
1095 cert._subject_invalidator = _X509NameInvalidator()
1096 return cert
1097
Alex Gaynor9939ba12017-06-25 16:28:24 -04001098 def to_cryptography(self):
1099 """
1100 Export as a ``cryptography`` certificate.
1101
1102 :rtype: ``cryptography.x509.Certificate``
1103
1104 .. versionadded:: 17.1.0
1105 """
1106 from cryptography.hazmat.backends.openssl.x509 import _Certificate
1107 backend = _get_backend()
1108 return _Certificate(backend, self._x509)
1109
1110 @classmethod
1111 def from_cryptography(cls, crypto_cert):
1112 """
1113 Construct based on a ``cryptography`` *crypto_cert*.
1114
1115 :param crypto_key: A ``cryptography`` X.509 certificate.
1116 :type crypto_key: ``cryptography.x509.Certificate``
1117
1118 :rtype: PKey
1119
1120 .. versionadded:: 17.1.0
1121 """
1122 if not isinstance(crypto_cert, x509.Certificate):
1123 raise TypeError("Must be a certificate")
1124
1125 cert = cls()
1126 cert._x509 = crypto_cert._x509
1127 return cert
1128
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001129 def set_version(self, version):
1130 """
Cyril Stoller6f25ced2018-08-27 13:37:51 +02001131 Set the version number of the certificate. Note that the
1132 version value is zero-based, eg. a value of 0 is V1.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001133
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001134 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001135 :type version: :py:class:`int`
1136
Dan Sully44e767a2016-06-04 18:05:27 -07001137 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001138 """
1139 if not isinstance(version, int):
1140 raise TypeError("version must be an integer")
1141
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001142 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001143
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001144 def get_version(self):
1145 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001146 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001147
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001148 :return: The version number of the certificate.
1149 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001150 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001151 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001152
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001153 def get_pubkey(self):
1154 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001155 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001156
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001157 :return: The public key.
1158 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001159 """
1160 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001161 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1162 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001163 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001164 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001165 pkey._only_public = True
1166 return pkey
1167
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001168 def set_pubkey(self, pkey):
1169 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001170 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001171
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001172 :param pkey: The public key.
1173 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001174
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001175 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001176 """
1177 if not isinstance(pkey, PKey):
1178 raise TypeError("pkey must be a PKey instance")
1179
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001180 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001181 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001182
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001183 def sign(self, pkey, digest):
1184 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001185 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001186
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001187 :param pkey: The key to sign with.
1188 :type pkey: :py:class:`PKey`
1189
1190 :param digest: The name of the message digest to use.
1191 :type digest: :py:class:`bytes`
1192
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001193 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001194 """
1195 if not isinstance(pkey, PKey):
1196 raise TypeError("pkey must be a PKey instance")
1197
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001198 if pkey._only_public:
1199 raise ValueError("Key only has public part")
1200
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001201 if not pkey._initialized:
1202 raise ValueError("Key is uninitialized")
1203
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001204 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001205 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001206 raise ValueError("No such digest method")
1207
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001208 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001209 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001210
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001211 def get_signature_algorithm(self):
1212 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001213 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001214
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001215 :return: The name of the algorithm.
1216 :rtype: :py:class:`bytes`
1217
1218 :raises ValueError: If the signature algorithm is undefined.
1219
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001220 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001221 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001222 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1223 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001224 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001225 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001226 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001227
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001228 def digest(self, digest_name):
1229 """
1230 Return the digest of the X509 object.
1231
1232 :param digest_name: The name of the digest algorithm to use.
1233 :type digest_name: :py:class:`bytes`
1234
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001235 :return: The digest of the object, formatted as
1236 :py:const:`b":"`-delimited hex pairs.
1237 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001238 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001239 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001240 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001241 raise ValueError("No such digest method")
1242
Paul Kehrer9f9113a2016-09-20 20:10:25 -05001243 result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001244 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001245 result_length[0] = len(result_buffer)
1246
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001247 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001248 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001249 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001250
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001251 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001252 b16encode(ch).upper() for ch
1253 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001254
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001255 def subject_name_hash(self):
1256 """
1257 Return the hash of the X509 subject.
1258
1259 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001260 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001261 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001262 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001263
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001264 def set_serial_number(self, serial):
1265 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001266 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001267
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001268 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001269 :type serial: :py:class:`int`
1270
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001271 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001272 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001273 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001274 raise TypeError("serial must be an integer")
1275
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001276 hex_serial = hex(serial)[2:]
1277 if not isinstance(hex_serial, bytes):
1278 hex_serial = hex_serial.encode('ascii')
1279
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001280 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001281
1282 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001283 # it. If bignum is still NULL after this call, then the return value
1284 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001285 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001286
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001287 if bignum_serial[0] == _ffi.NULL:
1288 set_result = _lib.ASN1_INTEGER_set(
1289 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001290 if set_result:
1291 # TODO Not tested
1292 _raise_current_error()
1293 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001294 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1295 _lib.BN_free(bignum_serial[0])
1296 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001297 # TODO Not tested
1298 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001299 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1300 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001301 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001302
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001303 def get_serial_number(self):
1304 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001305 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001306
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001307 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001308 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001309 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001310 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1311 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001312 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001313 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001314 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001315 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001316 serial = int(hexstring_serial, 16)
1317 return serial
1318 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001319 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001320 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001321 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001322
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001323 def gmtime_adj_notAfter(self, amount):
1324 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001325 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001326
Dan Sully44e767a2016-06-04 18:05:27 -07001327 :param int amount: The number of seconds by which to adjust the
1328 timestamp.
1329 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001330 """
1331 if not isinstance(amount, int):
1332 raise TypeError("amount must be an integer")
1333
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001334 notAfter = _lib.X509_get_notAfter(self._x509)
1335 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001336
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001337 def gmtime_adj_notBefore(self, amount):
1338 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001339 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001340
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001341 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001342 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001343 """
1344 if not isinstance(amount, int):
1345 raise TypeError("amount must be an integer")
1346
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001347 notBefore = _lib.X509_get_notBefore(self._x509)
1348 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001349
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001350 def has_expired(self):
1351 """
1352 Check whether the certificate has expired.
1353
Dan Sully44e767a2016-06-04 18:05:27 -07001354 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1355 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001356 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001357 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001358 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001359
Paul Kehrerfde45c92016-01-21 12:57:37 -06001360 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001361
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001362 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001363 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001364
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001365 def get_notBefore(self):
1366 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001367 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001368
Paul Kehrerce98ee62017-06-21 06:59:58 -10001369 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001370
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001371 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001372
Dan Sully44e767a2016-06-04 18:05:27 -07001373 :return: A timestamp string, or ``None`` if there is none.
1374 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001375 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001376 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001377
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001378 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001379 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001380
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001381 def set_notBefore(self, when):
1382 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001383 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001384
Paul Kehrerce98ee62017-06-21 06:59:58 -10001385 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001386
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001387 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001388
Dan Sully44e767a2016-06-04 18:05:27 -07001389 :param bytes when: A timestamp string.
1390 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001391 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001392 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001393
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001394 def get_notAfter(self):
1395 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001396 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001397
Paul Kehrerce98ee62017-06-21 06:59:58 -10001398 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001399
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001400 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001401
Dan Sully44e767a2016-06-04 18:05:27 -07001402 :return: A timestamp string, or ``None`` if there is none.
1403 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001404 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001405 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001406
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001407 def set_notAfter(self, when):
1408 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001409 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001410
Paul Kehrerce98ee62017-06-21 06:59:58 -10001411 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001412
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001413 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001414
Dan Sully44e767a2016-06-04 18:05:27 -07001415 :param bytes when: A timestamp string.
1416 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001417 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001418 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001419
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001420 def _get_name(self, which):
1421 name = X509Name.__new__(X509Name)
1422 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001423 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001424
1425 # The name is owned by the X509 structure. As long as the X509Name
1426 # Python object is alive, keep the X509 Python object alive.
1427 name._owner = self
1428
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001429 return name
1430
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001431 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001432 if not isinstance(name, X509Name):
1433 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001434 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001435 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001436
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001437 def get_issuer(self):
1438 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001439 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001440
Cory Benfielde6bcce82015-12-09 08:40:03 +00001441 This creates a new :class:`X509Name` that wraps the underlying issuer
1442 name field on the certificate. Modifying it will modify the underlying
1443 certificate, and will have the effect of modifying any other
1444 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001445
1446 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001447 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001448 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001449 name = self._get_name(_lib.X509_get_issuer_name)
1450 self._issuer_invalidator.add(name)
1451 return name
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001452
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001453 def set_issuer(self, issuer):
1454 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001455 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001456
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001457 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001458 :type issuer: :py:class:`X509Name`
1459
Dan Sully44e767a2016-06-04 18:05:27 -07001460 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001461 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001462 self._set_name(_lib.X509_set_issuer_name, issuer)
1463 self._issuer_invalidator.clear()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001464
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001465 def get_subject(self):
1466 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001467 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001468
Cory Benfielde6bcce82015-12-09 08:40:03 +00001469 This creates a new :class:`X509Name` that wraps the underlying subject
1470 name field on the certificate. Modifying it will modify the underlying
1471 certificate, and will have the effect of modifying any other
1472 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001473
1474 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001475 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001476 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001477 name = self._get_name(_lib.X509_get_subject_name)
1478 self._subject_invalidator.add(name)
1479 return name
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001480
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001481 def set_subject(self, subject):
1482 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001483 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001484
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001485 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001486 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001487
Dan Sully44e767a2016-06-04 18:05:27 -07001488 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001489 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001490 self._set_name(_lib.X509_set_subject_name, subject)
1491 self._subject_invalidator.clear()
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001492
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001493 def get_extension_count(self):
1494 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001495 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001496
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001497 :return: The number of extensions.
1498 :rtype: :py:class:`int`
1499
1500 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001501 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001502 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001503
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001504 def add_extensions(self, extensions):
1505 """
1506 Add extensions to the certificate.
1507
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001508 :param extensions: The extensions to add.
1509 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001510 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001511 """
1512 for ext in extensions:
1513 if not isinstance(ext, X509Extension):
1514 raise ValueError("One of the elements is not an X509Extension")
1515
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001516 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001517 if not add_result:
1518 _raise_current_error()
1519
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001520 def get_extension(self, index):
1521 """
1522 Get a specific extension of the certificate by index.
1523
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001524 Extensions on a certificate are kept in order. The index
1525 parameter selects which extension will be returned.
1526
1527 :param int index: The index of the extension to retrieve.
1528 :return: The extension at the specified index.
1529 :rtype: :py:class:`X509Extension`
1530 :raises IndexError: If the extension index was out of bounds.
1531
1532 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001533 """
1534 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001535 ext._extension = _lib.X509_get_ext(self._x509, index)
1536 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001537 raise IndexError("extension index out of bounds")
1538
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001539 extension = _lib.X509_EXTENSION_dup(ext._extension)
1540 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001541 return ext
1542
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001543
Alex Gaynor10d30832017-06-29 15:31:39 -07001544X509Type = deprecated(
1545 X509, __name__,
1546 "X509Type has been deprecated, use X509 instead",
1547 DeprecationWarning
1548)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001549
1550
Dan Sully44e767a2016-06-04 18:05:27 -07001551class X509StoreFlags(object):
1552 """
1553 Flags for X509 verification, used to change the behavior of
1554 :class:`X509Store`.
1555
1556 See `OpenSSL Verification Flags`_ for details.
1557
1558 .. _OpenSSL Verification Flags:
Alex Chan54005ce2017-03-21 08:08:17 +00001559 https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_flags.html
Dan Sully44e767a2016-06-04 18:05:27 -07001560 """
1561 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1562 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1563 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1564 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1565 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1566 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1567 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1568 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1569 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1570 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1571 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1572
1573
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001574class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001575 """
Dan Sully44e767a2016-06-04 18:05:27 -07001576 An X.509 store.
1577
1578 An X.509 store is used to describe a context in which to verify a
1579 certificate. A description of a context may include a set of certificates
1580 to trust, a set of certificate revocation lists, verification flags and
1581 more.
1582
1583 An X.509 store, being only a description, cannot be used by itself to
1584 verify a certificate. To carry out the actual verification process, see
1585 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001586 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001587
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001588 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001589 store = _lib.X509_STORE_new()
1590 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001591
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001592 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001593 """
Dan Sully44e767a2016-06-04 18:05:27 -07001594 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001595
Dan Sully44e767a2016-06-04 18:05:27 -07001596 Adding a certificate with this method adds this certificate as a
1597 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001598
1599 :param X509 cert: The certificate to add to this store.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001600
Dan Sully44e767a2016-06-04 18:05:27 -07001601 :raises TypeError: If the certificate is not an :class:`X509`.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001602
1603 :raises OpenSSL.crypto.Error: If OpenSSL was unhappy with your
1604 certificate.
1605
Dan Sully44e767a2016-06-04 18:05:27 -07001606 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001607 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001608 if not isinstance(cert, X509):
1609 raise TypeError()
1610
Paul Kehrer0e6c5532018-08-23 10:52:15 -05001611 # As of OpenSSL 1.1.0i adding the same cert to the store more than
1612 # once doesn't cause an error. Accordingly, this code now silences
1613 # the error for OpenSSL < 1.1.0i as well.
1614 if _lib.X509_STORE_add_cert(self._store, cert._x509) == 0:
1615 code = _lib.ERR_peek_error()
1616 err_reason = _lib.ERR_GET_REASON(code)
1617 _openssl_assert(
1618 err_reason == _lib.X509_R_CERT_ALREADY_IN_HASH_TABLE
1619 )
1620 _lib.ERR_clear_error()
Dan Sully44e767a2016-06-04 18:05:27 -07001621
1622 def add_crl(self, crl):
1623 """
1624 Add a certificate revocation list to this store.
1625
1626 The certificate revocation lists added to a store will only be used if
1627 the associated flags are configured to check certificate revocation
1628 lists.
1629
1630 .. versionadded:: 16.1.0
1631
1632 :param CRL crl: The certificate revocation list to add to this store.
1633 :return: ``None`` if the certificate revocation list was added
1634 successfully.
1635 """
1636 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1637
1638 def set_flags(self, flags):
1639 """
1640 Set verification flags to this store.
1641
1642 Verification flags can be combined by oring them together.
1643
1644 .. note::
1645
1646 Setting a verification flag sometimes requires clients to add
1647 additional information to the store, otherwise a suitable error will
1648 be raised.
1649
1650 For example, in setting flags to enable CRL checking a
1651 suitable CRL must be added to the store otherwise an error will be
1652 raised.
1653
1654 .. versionadded:: 16.1.0
1655
1656 :param int flags: The verification flags to set on this store.
1657 See :class:`X509StoreFlags` for available constants.
1658 :return: ``None`` if the verification flags were successfully set.
1659 """
1660 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001661
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001662 def set_time(self, vfy_time):
1663 """
1664 Set the time against which the certificates are verified.
1665
1666 Normally the current time is used.
1667
1668 .. note::
1669
1670 For example, you can determine if a certificate was valid at a given
1671 time.
1672
Hynek Schlawackf6c96af2017-04-20 12:34:58 +02001673 .. versionadded:: 17.0.0
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001674
1675 :param datetime vfy_time: The verification time to set on this store.
1676 :return: ``None`` if the verification time was successfully set.
1677 """
1678 param = _lib.X509_VERIFY_PARAM_new()
1679 param = _ffi.gc(param, _lib.X509_VERIFY_PARAM_free)
1680
1681 _lib.X509_VERIFY_PARAM_set_time(param, int(vfy_time.strftime('%s')))
1682 _openssl_assert(_lib.X509_STORE_set1_param(self._store, param) != 0)
1683
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001684
Alex Gaynor10d30832017-06-29 15:31:39 -07001685X509StoreType = deprecated(
1686 X509Store, __name__,
1687 "X509StoreType has been deprecated, use X509Store instead",
1688 DeprecationWarning
1689)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001690
1691
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001692class X509StoreContextError(Exception):
1693 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001694 An exception raised when an error occurred while verifying a certificate
1695 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001696
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001697 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001698 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001699 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001700
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001701 def __init__(self, message, certificate):
1702 super(X509StoreContextError, self).__init__(message)
1703 self.certificate = certificate
1704
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001705
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001706class X509StoreContext(object):
1707 """
1708 An X.509 store context.
1709
Dan Sully44e767a2016-06-04 18:05:27 -07001710 An X.509 store context is used to carry out the actual verification process
1711 of a certificate in a described context. For describing such a context, see
1712 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001713
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001714 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1715 instance. It is dynamically allocated and automatically garbage
1716 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001717 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001718 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001719 :param X509Store store: The certificates which will be trusted for the
1720 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001721 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001722 """
1723
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001724 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001725 store_ctx = _lib.X509_STORE_CTX_new()
1726 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1727 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001728 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001729 # Make the store context available for use after instantiating this
1730 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001731 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001732 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001733
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001734 def _init(self):
1735 """
1736 Set up the store context for a subsequent verification operation.
Jeremy Cline58193f12017-09-13 21:14:53 -04001737
1738 Calling this method more than once without first calling
1739 :meth:`_cleanup` will leak memory.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001740 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001741 ret = _lib.X509_STORE_CTX_init(
1742 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1743 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001744 if ret <= 0:
1745 _raise_current_error()
1746
1747 def _cleanup(self):
1748 """
1749 Internally cleans up the store context.
1750
Dan Sully44e767a2016-06-04 18:05:27 -07001751 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001752 """
1753 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1754
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001755 def _exception_from_context(self):
1756 """
1757 Convert an OpenSSL native context error failure into a Python
1758 exception.
1759
Alex Gaynor5945ea82015-09-05 14:59:06 -04001760 When a call to native OpenSSL X509_verify_cert fails, additional
1761 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001762 """
1763 errors = [
1764 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1765 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1766 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001767 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001768 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001769 # A context error should always be associated with a certificate, so we
1770 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001771 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001772 _cert = _lib.X509_dup(_x509)
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001773 pycert = X509._from_raw_x509_ptr(_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001774 return X509StoreContextError(errors, pycert)
1775
Stephen Holsapple46a09252015-02-12 14:45:43 -08001776 def set_store(self, store):
1777 """
Dan Sully44e767a2016-06-04 18:05:27 -07001778 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001779
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001780 .. versionadded:: 0.15
1781
Dan Sully44e767a2016-06-04 18:05:27 -07001782 :param X509Store store: The store description which will be used for
1783 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001784 """
1785 self._store = store
1786
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001787 def verify_certificate(self):
1788 """
1789 Verify a certificate in a context.
1790
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001791 .. versionadded:: 0.15
1792
Alex Gaynorca87ff62015-09-04 23:31:03 -04001793 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001794 certificate in the context. Sets ``certificate`` attribute to
1795 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001796 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001797 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001798 # :meth:`verify_certificate` is called multiple times.
Jeremy Cline58193f12017-09-13 21:14:53 -04001799 #
1800 # :meth:`_init` is called in :meth:`__init__` so _cleanup is called
1801 # before _init to ensure memory is not leaked.
1802 self._cleanup()
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001803 self._init()
1804 ret = _lib.X509_verify_cert(self._store_ctx)
1805 self._cleanup()
1806 if ret <= 0:
1807 raise self._exception_from_context()
1808
1809
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001810def load_certificate(type, buffer):
1811 """
Alex Chand072cae2018-02-15 09:57:59 +00001812 Load a certificate (X509) from the string *buffer* encoded with the
1813 type *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001814
1815 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1816
Dan Sully44e767a2016-06-04 18:05:27 -07001817 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001818
1819 :return: The X509 object
1820 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001821 if isinstance(buffer, _text_type):
1822 buffer = buffer.encode("ascii")
1823
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001824 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001825
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001826 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001827 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001828 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001829 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001830 else:
1831 raise ValueError(
1832 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001833
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001834 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001835 _raise_current_error()
1836
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001837 return X509._from_raw_x509_ptr(x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001838
1839
1840def dump_certificate(type, cert):
1841 """
Alex Chand072cae2018-02-15 09:57:59 +00001842 Dump the certificate *cert* into a buffer string encoded with the type
1843 *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001844
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001845 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1846 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001847 :param cert: The certificate to dump
1848 :return: The buffer with the dumped certificate in
1849 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001850 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001851
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001852 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001853 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001854 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001855 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001856 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001857 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001858 else:
1859 raise ValueError(
1860 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1861 "FILETYPE_TEXT")
1862
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001863 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001864 return _bio_to_string(bio)
1865
1866
Cory Benfield6492f7c2015-10-27 16:57:58 +09001867def dump_publickey(type, pkey):
1868 """
Cory Benfield11c10192015-10-27 17:23:03 +09001869 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001870
Cory Benfield9c590b92015-10-28 14:55:05 +09001871 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001872 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001873 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001874 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001875 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001876 """
1877 bio = _new_mem_buf()
1878 if type == FILETYPE_PEM:
1879 write_bio = _lib.PEM_write_bio_PUBKEY
1880 elif type == FILETYPE_ASN1:
1881 write_bio = _lib.i2d_PUBKEY_bio
1882 else:
1883 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1884
1885 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001886 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001887 _raise_current_error()
1888
1889 return _bio_to_string(bio)
1890
1891
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001892def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1893 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001894 Dump the private key *pkey* into a buffer string encoded with the type
1895 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1896 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001897
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001898 :param type: The file type (one of :const:`FILETYPE_PEM`,
1899 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1900 :param PKey pkey: The PKey to dump
1901 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001902 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001903 the passphrase to use, or a callback for providing the passphrase.
1904
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001905 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001906 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001907 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001908 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001909
Paul Kehrercded9932017-06-29 18:43:42 -05001910 if not isinstance(pkey, PKey):
1911 raise TypeError("pkey must be a PKey")
1912
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001913 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001914 if passphrase is None:
1915 raise TypeError(
1916 "if a value is given for cipher "
1917 "one must also be given for passphrase")
1918 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001919 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001920 raise ValueError("Invalid cipher name")
1921 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001922 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001923
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001924 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001925 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001926 result_code = _lib.PEM_write_bio_PrivateKey(
1927 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001928 helper.callback, helper.callback_args)
1929 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001930 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001931 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001932 elif type == FILETYPE_TEXT:
Paul Kehrercded9932017-06-29 18:43:42 -05001933 if _lib.EVP_PKEY_id(pkey._pkey) != _lib.EVP_PKEY_RSA:
1934 raise TypeError("Only RSA keys are supported for FILETYPE_TEXT")
1935
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001936 rsa = _ffi.gc(
1937 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1938 _lib.RSA_free
1939 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001940 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001941 else:
1942 raise ValueError(
1943 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1944 "FILETYPE_TEXT")
1945
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001946 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001947
1948 return _bio_to_string(bio)
1949
1950
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001951class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001952 """
1953 A certificate revocation.
1954 """
Cyril Stoller37e60222018-08-27 13:38:10 +02001955 # https://www.openssl.org/docs/manmaster/man5/x509v3_config.html#CRL-distribution-points
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001956 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1957 # OCSP_crl_reason_str. We use the latter, just like the command line
1958 # program.
1959 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001960 b"unspecified",
1961 b"keyCompromise",
1962 b"CACompromise",
1963 b"affiliationChanged",
1964 b"superseded",
1965 b"cessationOfOperation",
1966 b"certificateHold",
1967 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001968 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001969
1970 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001971 revoked = _lib.X509_REVOKED_new()
1972 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001973
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001974 def set_serial(self, hex_str):
1975 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001976 Set the serial number.
1977
1978 The serial number is formatted as a hexadecimal number encoded in
1979 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001980
Dan Sully44e767a2016-06-04 18:05:27 -07001981 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001982
Dan Sully44e767a2016-06-04 18:05:27 -07001983 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001984 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001985 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1986 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001987 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001988 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001989 if not bn_result:
1990 raise ValueError("bad hex string")
1991
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001992 asn1_serial = _ffi.gc(
1993 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1994 _lib.ASN1_INTEGER_free)
1995 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001996
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001997 def get_serial(self):
1998 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001999 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002000
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002001 The serial number is formatted as a hexadecimal number encoded in
2002 ASCII.
2003
2004 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07002005 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002006 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08002007 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002008
Alex Gaynor67903a62016-06-02 10:37:13 -07002009 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
2010 _openssl_assert(asn1_int != _ffi.NULL)
2011 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
2012 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002013 return _bio_to_string(bio)
2014
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002015 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07002016 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
2017 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002018 obj = _lib.X509_EXTENSION_get_object(ext)
2019 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002020 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07002021 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002022 break
2023
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002024 def set_reason(self, reason):
2025 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002026 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002027
Dan Sully44e767a2016-06-04 18:05:27 -07002028 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002029
2030 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07002031 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002032
Dan Sully44e767a2016-06-04 18:05:27 -07002033 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002034
2035 .. seealso::
2036
Dan Sully44e767a2016-06-04 18:05:27 -07002037 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002038 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002039 """
2040 if reason is None:
2041 self._delete_reason()
2042 elif not isinstance(reason, bytes):
2043 raise TypeError("reason must be None or a byte string")
2044 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002045 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002046 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
2047
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002048 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002049 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002050 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002051
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002052 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002053 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002054
2055 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002056 add_result = _lib.X509_REVOKED_add1_ext_i2d(
2057 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002058 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002059
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002060 def get_reason(self):
2061 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04002062 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002063
Dan Sully44e767a2016-06-04 18:05:27 -07002064 :return: The reason, or ``None`` if there is none.
2065 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002066
2067 .. seealso::
2068
Dan Sully44e767a2016-06-04 18:05:27 -07002069 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002070 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002071 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002072 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
2073 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002074 obj = _lib.X509_EXTENSION_get_object(ext)
2075 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08002076 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002077
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002078 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002079 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002080 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002081 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04002082 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002083 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002084
2085 return _bio_to_string(bio)
2086
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002087 def all_reasons(self):
2088 """
2089 Return a list of all the supported reason strings.
2090
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002091 This list is a copy; modifying it does not change the supported reason
2092 strings.
2093
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002094 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07002095 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002096 """
2097 return self._crl_reasons[:]
2098
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002099 def set_rev_date(self, when):
2100 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002101 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002102
Dan Sully44e767a2016-06-04 18:05:27 -07002103 :param bytes when: The timestamp of the revocation,
Paul Kehrerce98ee62017-06-21 06:59:58 -10002104 as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002105 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002106 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002107 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2108 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002109
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002110 def get_rev_date(self):
2111 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002112 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002113
Paul Kehrerce98ee62017-06-21 06:59:58 -10002114 :return: The timestamp of the revocation, as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002115 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002116 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002117 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2118 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002119
2120
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002121class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002122 """
2123 A certificate revocation list.
2124 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002125
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002126 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002127 crl = _lib.X509_CRL_new()
2128 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002129
Paul Kehrer41c10242017-06-29 18:24:17 -05002130 def to_cryptography(self):
2131 """
2132 Export as a ``cryptography`` CRL.
2133
2134 :rtype: ``cryptography.x509.CertificateRevocationList``
2135
2136 .. versionadded:: 17.1.0
2137 """
2138 from cryptography.hazmat.backends.openssl.x509 import (
2139 _CertificateRevocationList
2140 )
2141 backend = _get_backend()
2142 return _CertificateRevocationList(backend, self._crl)
2143
2144 @classmethod
2145 def from_cryptography(cls, crypto_crl):
2146 """
2147 Construct based on a ``cryptography`` *crypto_crl*.
2148
2149 :param crypto_crl: A ``cryptography`` certificate revocation list
2150 :type crypto_crl: ``cryptography.x509.CertificateRevocationList``
2151
2152 :rtype: CRL
2153
2154 .. versionadded:: 17.1.0
2155 """
2156 if not isinstance(crypto_crl, x509.CertificateRevocationList):
2157 raise TypeError("Must be a certificate revocation list")
2158
2159 crl = cls()
2160 crl._crl = crypto_crl._x509_crl
2161 return crl
2162
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002163 def get_revoked(self):
2164 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002165 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002166
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002167 These revocations will be provided by value, not by reference.
2168 That means it's okay to mutate them: it won't affect this CRL.
2169
2170 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002171 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002172 """
2173 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07002174 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002175 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
2176 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04002177 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002178 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002179 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002180 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002181 if results:
2182 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002183
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002184 def add_revoked(self, revoked):
2185 """
2186 Add a revoked (by value not reference) to the CRL structure
2187
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002188 This revocation will be added by value, not by reference. That
2189 means it's okay to mutate it after adding: it won't affect
2190 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002191
Dan Sully44e767a2016-06-04 18:05:27 -07002192 :param Revoked revoked: The new revocation.
2193 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002194 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04002195 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002196 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002197
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002198 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002199 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002200
Dan Sully44e767a2016-06-04 18:05:27 -07002201 def get_issuer(self):
2202 """
2203 Get the CRL's issuer.
2204
2205 .. versionadded:: 16.1.0
2206
2207 :rtype: X509Name
2208 """
2209 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
2210 _openssl_assert(_issuer != _ffi.NULL)
2211 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
2212 issuer = X509Name.__new__(X509Name)
2213 issuer._name = _issuer
2214 return issuer
2215
2216 def set_version(self, version):
2217 """
2218 Set the CRL version.
2219
2220 .. versionadded:: 16.1.0
2221
2222 :param int version: The version of the CRL.
2223 :return: ``None``
2224 """
2225 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2226
2227 def _set_boundary_time(self, which, when):
2228 return _set_asn1_time(which(self._crl), when)
2229
2230 def set_lastUpdate(self, when):
2231 """
2232 Set when the CRL was last updated.
2233
Paul Kehrerce98ee62017-06-21 06:59:58 -10002234 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002235
2236 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002237
2238 .. versionadded:: 16.1.0
2239
2240 :param bytes when: A timestamp string.
2241 :return: ``None``
2242 """
2243 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2244
2245 def set_nextUpdate(self, when):
2246 """
2247 Set when the CRL will next be udpated.
2248
Paul Kehrerce98ee62017-06-21 06:59:58 -10002249 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002250
2251 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002252
2253 .. versionadded:: 16.1.0
2254
2255 :param bytes when: A timestamp string.
2256 :return: ``None``
2257 """
2258 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2259
2260 def sign(self, issuer_cert, issuer_key, digest):
2261 """
2262 Sign the CRL.
2263
2264 Signing a CRL enables clients to associate the CRL itself with an
2265 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2266 be signed by an issuer.
2267
2268 This method implicitly sets the issuer's name based on the issuer
2269 certificate and private key used to sign the CRL.
2270
2271 .. versionadded:: 16.1.0
2272
2273 :param X509 issuer_cert: The issuer's certificate.
2274 :param PKey issuer_key: The issuer's private key.
2275 :param bytes digest: The digest method to sign the CRL with.
2276 """
2277 digest_obj = _lib.EVP_get_digestbyname(digest)
2278 _openssl_assert(digest_obj != _ffi.NULL)
2279 _lib.X509_CRL_set_issuer_name(
2280 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2281 _lib.X509_CRL_sort(self._crl)
2282 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2283 _openssl_assert(result != 0)
2284
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002285 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002286 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002287 """
Dan Sully44e767a2016-06-04 18:05:27 -07002288 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002289
Dan Sully44e767a2016-06-04 18:05:27 -07002290 :param X509 cert: The certificate used to sign the CRL.
2291 :param PKey key: The key used to sign the CRL.
2292 :param int type: The export format, either :data:`FILETYPE_PEM`,
2293 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002294 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002295 :param bytes digest: The name of the message digest to use (eg
Alex Gaynor239e2d32016-09-11 12:36:35 -04002296 ``b"sha2566"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002297 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002298 """
Dan Sully44e767a2016-06-04 18:05:27 -07002299
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002300 if not isinstance(cert, X509):
2301 raise TypeError("cert must be an X509 instance")
2302 if not isinstance(key, PKey):
2303 raise TypeError("key must be a PKey instance")
2304 if not isinstance(type, int):
2305 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002306
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002307 if digest is _UNSPECIFIED:
Alex Gaynor173e4ba2017-06-30 08:01:12 -07002308 raise TypeError("digest must be provided")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002309
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002310 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002311 if digest_obj == _ffi.NULL:
2312 raise ValueError("No such digest method")
2313
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002314 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002315 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002316
Alex Gaynora738ed52015-09-05 11:17:10 -04002317 # A scratch time object to give different values to different CRL
2318 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002319 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002320 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002321
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002322 _lib.X509_gmtime_adj(sometime, 0)
2323 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002324
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002325 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2326 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002327
Alex Gaynor5945ea82015-09-05 14:59:06 -04002328 _lib.X509_CRL_set_issuer_name(
2329 self._crl, _lib.X509_get_subject_name(cert._x509)
2330 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002331
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002332 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002333 if not sign_result:
2334 _raise_current_error()
2335
Dominic Chenf05b2122015-10-13 16:32:35 +00002336 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002337
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002338
Alex Gaynor10d30832017-06-29 15:31:39 -07002339CRLType = deprecated(
2340 CRL, __name__,
2341 "CRLType has been deprecated, use CRL instead",
2342 DeprecationWarning
2343)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002344
2345
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002346class PKCS7(object):
2347 def type_is_signed(self):
2348 """
2349 Check if this NID_pkcs7_signed object
2350
2351 :return: True if the PKCS7 is of type signed
2352 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002353 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002354
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002355 def type_is_enveloped(self):
2356 """
2357 Check if this NID_pkcs7_enveloped object
2358
2359 :returns: True if the PKCS7 is of type enveloped
2360 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002361 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002362
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002363 def type_is_signedAndEnveloped(self):
2364 """
2365 Check if this NID_pkcs7_signedAndEnveloped object
2366
2367 :returns: True if the PKCS7 is of type signedAndEnveloped
2368 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002369 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002370
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002371 def type_is_data(self):
2372 """
2373 Check if this NID_pkcs7_data object
2374
2375 :return: True if the PKCS7 is of type data
2376 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002377 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002378
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002379 def get_type_name(self):
2380 """
2381 Returns the type name of the PKCS7 structure
2382
2383 :return: A string with the typename
2384 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002385 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2386 string_type = _lib.OBJ_nid2sn(nid)
2387 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002388
Alex Chanc6077062016-11-18 13:53:39 +00002389
Alex Gaynor10d30832017-06-29 15:31:39 -07002390PKCS7Type = deprecated(
2391 PKCS7, __name__,
2392 "PKCS7Type has been deprecated, use PKCS7 instead",
2393 DeprecationWarning
2394)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002395
2396
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002397class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002398 """
2399 A PKCS #12 archive.
2400 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002401
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002402 def __init__(self):
2403 self._pkey = None
2404 self._cert = None
2405 self._cacerts = None
2406 self._friendlyname = None
2407
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002408 def get_certificate(self):
2409 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002410 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002411
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002412 :return: The certificate, or :py:const:`None` if there is none.
2413 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002414 """
2415 return self._cert
2416
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002417 def set_certificate(self, cert):
2418 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002419 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002420
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002421 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002422 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002423
Dan Sully44e767a2016-06-04 18:05:27 -07002424 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002425 """
2426 if not isinstance(cert, X509):
2427 raise TypeError("cert must be an X509 instance")
2428 self._cert = cert
2429
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002430 def get_privatekey(self):
2431 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002432 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002433
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002434 :return: The private key, or :py:const:`None` if there is none.
2435 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002436 """
2437 return self._pkey
2438
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002439 def set_privatekey(self, pkey):
2440 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002441 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002442
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002443 :param pkey: The new private key, or :py:const:`None` to unset it.
2444 :type pkey: :py:class:`PKey` or :py:const:`None`
2445
Dan Sully44e767a2016-06-04 18:05:27 -07002446 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002447 """
2448 if not isinstance(pkey, PKey):
2449 raise TypeError("pkey must be a PKey instance")
2450 self._pkey = pkey
2451
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002452 def get_ca_certificates(self):
2453 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002454 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002455
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002456 :return: A tuple with the CA certificates in the chain, or
2457 :py:const:`None` if there are none.
2458 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002459 """
2460 if self._cacerts is not None:
2461 return tuple(self._cacerts)
2462
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002463 def set_ca_certificates(self, cacerts):
2464 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002465 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002466
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002467 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2468 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002469 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002470
Dan Sully44e767a2016-06-04 18:05:27 -07002471 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002472 """
2473 if cacerts is None:
2474 self._cacerts = None
2475 else:
2476 cacerts = list(cacerts)
2477 for cert in cacerts:
2478 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002479 raise TypeError(
2480 "iterable must only contain X509 instances"
2481 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002482 self._cacerts = cacerts
2483
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002484 def set_friendlyname(self, name):
2485 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002486 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002487
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002488 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002489 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002490
Dan Sully44e767a2016-06-04 18:05:27 -07002491 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002492 """
2493 if name is None:
2494 self._friendlyname = None
2495 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002496 raise TypeError(
2497 "name must be a byte string or None (not %r)" % (name,)
2498 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002499 self._friendlyname = name
2500
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002501 def get_friendlyname(self):
2502 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002503 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002504
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002505 :returns: The friendly name, or :py:const:`None` if there is none.
2506 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002507 """
2508 return self._friendlyname
2509
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002510 def export(self, passphrase=None, iter=2048, maciter=1):
2511 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002512 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002513
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002514 For more information, see the :c:func:`PKCS12_create` man page.
2515
2516 :param passphrase: The passphrase used to encrypt the structure. Unlike
2517 some other passphrase arguments, this *must* be a string, not a
2518 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002519 :type passphrase: :py:data:`bytes`
2520
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002521 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002522 :type iter: :py:data:`int`
2523
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002524 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002525 :type maciter: :py:data:`int`
2526
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002527 :return: The string representation of the PKCS #12 structure.
2528 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002529 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002530 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002531
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002532 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002533 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002534 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002535 cacerts = _lib.sk_X509_new_null()
2536 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002537 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002538 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002539
2540 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002541 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002542
2543 friendlyname = self._friendlyname
2544 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002545 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002546
2547 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002548 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002549 else:
2550 pkey = self._pkey._pkey
2551
2552 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002553 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002554 else:
2555 cert = self._cert._x509
2556
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002557 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002558 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002559 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2560 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002561 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002562 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002563 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002564 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002565
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002566 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002567 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002568 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002569
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002570
Alex Gaynor10d30832017-06-29 15:31:39 -07002571PKCS12Type = deprecated(
2572 PKCS12, __name__,
2573 "PKCS12Type has been deprecated, use PKCS12 instead",
2574 DeprecationWarning
2575)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002576
2577
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002578class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002579 """
2580 A Netscape SPKI object.
2581 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002582
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002583 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002584 spki = _lib.NETSCAPE_SPKI_new()
2585 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002586
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002587 def sign(self, pkey, digest):
2588 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002589 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002590
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002591 :param pkey: The private key to sign with.
2592 :type pkey: :py:class:`PKey`
2593
2594 :param digest: The message digest to use.
2595 :type digest: :py:class:`bytes`
2596
Dan Sully44e767a2016-06-04 18:05:27 -07002597 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002598 """
2599 if pkey._only_public:
2600 raise ValueError("Key has only public part")
2601
2602 if not pkey._initialized:
2603 raise ValueError("Key is uninitialized")
2604
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002605 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002606 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002607 raise ValueError("No such digest method")
2608
Alex Gaynor5945ea82015-09-05 14:59:06 -04002609 sign_result = _lib.NETSCAPE_SPKI_sign(
2610 self._spki, pkey._pkey, digest_obj
2611 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002612 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002613
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002614 def verify(self, key):
2615 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002616 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002617
Hynek Schlawack01c31672016-12-11 15:14:09 +01002618 :param PKey key: The public key that signature is supposedly from.
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002619
Hynek Schlawack01c31672016-12-11 15:14:09 +01002620 :return: ``True`` if the signature is correct.
2621 :rtype: bool
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002622
Hynek Schlawack01c31672016-12-11 15:14:09 +01002623 :raises OpenSSL.crypto.Error: If the signature is invalid, or there was
2624 a problem verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002625 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002626 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002627 if answer <= 0:
2628 _raise_current_error()
2629 return True
2630
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002631 def b64_encode(self):
2632 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002633 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002634
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002635 :return: The base64 encoded string.
2636 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002637 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002638 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2639 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002640 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002641 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002642
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002643 def get_pubkey(self):
2644 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002645 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002646
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002647 :return: The public key.
2648 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002649 """
2650 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002651 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002652 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002653 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002654 pkey._only_public = True
2655 return pkey
2656
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002657 def set_pubkey(self, pkey):
2658 """
2659 Set the public key of the certificate
2660
2661 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002662 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002663 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002664 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002665 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002666
2667
Alex Gaynor10d30832017-06-29 15:31:39 -07002668NetscapeSPKIType = deprecated(
2669 NetscapeSPKI, __name__,
2670 "NetscapeSPKIType has been deprecated, use NetscapeSPKI instead",
2671 DeprecationWarning
2672)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002673
2674
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002675class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002676 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002677 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002678 raise ValueError(
2679 "only FILETYPE_PEM key format supports encryption"
2680 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002681 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002682 self._more_args = more_args
2683 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002684 self._problems = []
2685
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002686 @property
2687 def callback(self):
2688 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002689 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002690 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002691 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002692 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002693 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002694 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002695 raise TypeError(
2696 "Last argument must be a byte string or a callable."
2697 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002698
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002699 @property
2700 def callback_args(self):
2701 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002702 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002703 elif isinstance(self._passphrase, bytes):
2704 return self._passphrase
2705 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002706 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002707 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002708 raise TypeError(
2709 "Last argument must be a byte string or a callable."
2710 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002711
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002712 def raise_if_problem(self, exceptionType=Error):
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002713 if self._problems:
Greg Bowser36eb2de2017-01-24 11:38:55 -05002714
2715 # Flush the OpenSSL error queue
2716 try:
2717 _exception_from_error_queue(exceptionType)
2718 except exceptionType:
2719 pass
2720
2721 raise self._problems.pop(0)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002722
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002723 def _read_passphrase(self, buf, size, rwflag, userdata):
2724 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002725 if self._more_args:
2726 result = self._passphrase(size, rwflag, userdata)
2727 else:
2728 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002729 if not isinstance(result, bytes):
2730 raise ValueError("String expected")
2731 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002732 if self._truncate:
2733 result = result[:size]
2734 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002735 raise ValueError(
2736 "passphrase returned by callback is too long"
2737 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002738 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002739 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002740 return len(result)
2741 except Exception as e:
2742 self._problems.append(e)
2743 return 0
2744
2745
Cory Benfield6492f7c2015-10-27 16:57:58 +09002746def load_publickey(type, buffer):
2747 """
Cory Benfield11c10192015-10-27 17:23:03 +09002748 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002749
Cory Benfield9c590b92015-10-28 14:55:05 +09002750 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002751 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002752 :param buffer: The buffer the key is stored in.
2753 :type buffer: A Python string object, either unicode or bytestring.
2754 :return: The PKey object.
2755 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002756 """
2757 if isinstance(buffer, _text_type):
2758 buffer = buffer.encode("ascii")
2759
2760 bio = _new_mem_buf(buffer)
2761
2762 if type == FILETYPE_PEM:
2763 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2764 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2765 elif type == FILETYPE_ASN1:
2766 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2767 else:
2768 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2769
2770 if evp_pkey == _ffi.NULL:
2771 _raise_current_error()
2772
2773 pkey = PKey.__new__(PKey)
2774 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002775 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002776 return pkey
2777
2778
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002779def load_privatekey(type, buffer, passphrase=None):
2780 """
Alex Chand072cae2018-02-15 09:57:59 +00002781 Load a private key (PKey) from the string *buffer* encoded with the type
2782 *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002783
2784 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2785 :param buffer: The buffer the key is stored in
2786 :param passphrase: (optional) if encrypted PEM format, this can be
2787 either the passphrase to use, or a callback for
2788 providing the passphrase.
2789
2790 :return: The PKey object
2791 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002792 if isinstance(buffer, _text_type):
2793 buffer = buffer.encode("ascii")
2794
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002795 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002796
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002797 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002798 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002799 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2800 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002801 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002802 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002803 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002804 else:
2805 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2806
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002807 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002808 _raise_current_error()
2809
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002810 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002811 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002812 return pkey
2813
2814
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002815def dump_certificate_request(type, req):
2816 """
Alex Chand072cae2018-02-15 09:57:59 +00002817 Dump the certificate request *req* into a buffer string encoded with the
2818 type *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002819
2820 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2821 :param req: The certificate request to dump
2822 :return: The buffer with the dumped certificate request in
2823 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002824 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002825
2826 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002827 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002828 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002829 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002830 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002831 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002832 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002833 raise ValueError(
2834 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2835 "FILETYPE_TEXT"
2836 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002837
Alex Gaynor09a386e2016-07-03 09:32:44 -04002838 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002839
2840 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002841
2842
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002843def load_certificate_request(type, buffer):
2844 """
Alex Chand072cae2018-02-15 09:57:59 +00002845 Load a certificate request (X509Req) from the string *buffer* encoded with
2846 the type *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002847
2848 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2849 :param buffer: The buffer the certificate request is stored in
2850 :return: The X509Req object
2851 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002852 if isinstance(buffer, _text_type):
2853 buffer = buffer.encode("ascii")
2854
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002855 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002856
2857 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002858 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002859 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002860 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002861 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002862 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002863
Alex Gaynoradd5b072016-06-04 21:04:00 -07002864 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002865
2866 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002867 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002868 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002869
2870
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002871def sign(pkey, data, digest):
2872 """
Alex Chand072cae2018-02-15 09:57:59 +00002873 Sign a data string using the given key and message digest.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002874
Alex Chand072cae2018-02-15 09:57:59 +00002875 :param pkey: PKey to sign with
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002876 :param data: data to be signed
2877 :param digest: message digest to use
2878 :return: signature
Alex Chand072cae2018-02-15 09:57:59 +00002879
2880 .. versionadded:: 0.11
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002881 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002882 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002883
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002884 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002885 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002886 raise ValueError("No such digest method")
2887
Alex Gaynor67903a62016-06-02 10:37:13 -07002888 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002889 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002890
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002891 _lib.EVP_SignInit(md_ctx, digest_obj)
2892 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002893
Paul Kehrer59d26252017-07-20 10:45:54 +02002894 length = _lib.EVP_PKEY_size(pkey._pkey)
2895 _openssl_assert(length > 0)
2896 signature_buffer = _ffi.new("unsigned char[]", length)
2897 signature_length = _ffi.new("unsigned int *")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002898 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002899 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002900 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002901
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002902 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002903
2904
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002905def verify(cert, signature, data, digest):
2906 """
Alex Chand072cae2018-02-15 09:57:59 +00002907 Verify the signature for a data string.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002908
Alex Chand072cae2018-02-15 09:57:59 +00002909 :param cert: signing certificate (X509 object) corresponding to the
2910 private key which generated the signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002911 :param signature: signature returned by sign function
2912 :param data: data to be verified
2913 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002914 :return: ``None`` if the signature is correct, raise exception otherwise.
Alex Chand072cae2018-02-15 09:57:59 +00002915
2916 .. versionadded:: 0.11
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002917 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002918 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002919
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002920 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002921 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002922 raise ValueError("No such digest method")
2923
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002924 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002925 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002926 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002927
Alex Gaynor67903a62016-06-02 10:37:13 -07002928 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002929 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002930
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002931 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2932 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002933 verify_result = _lib.EVP_VerifyFinal(
2934 md_ctx, signature, len(signature), pkey
2935 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002936
2937 if verify_result != 1:
2938 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002939
2940
Dominic Chenf05b2122015-10-13 16:32:35 +00002941def dump_crl(type, crl):
2942 """
2943 Dump a certificate revocation list to a buffer.
2944
2945 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2946 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002947 :param CRL crl: The CRL to dump.
2948
Dominic Chenf05b2122015-10-13 16:32:35 +00002949 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002950 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002951 """
2952 bio = _new_mem_buf()
2953
2954 if type == FILETYPE_PEM:
2955 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2956 elif type == FILETYPE_ASN1:
2957 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2958 elif type == FILETYPE_TEXT:
2959 ret = _lib.X509_CRL_print(bio, crl._crl)
2960 else:
2961 raise ValueError(
2962 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2963 "FILETYPE_TEXT")
2964
2965 assert ret == 1
2966 return _bio_to_string(bio)
2967
2968
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002969def load_crl(type, buffer):
2970 """
Alex Chand072cae2018-02-15 09:57:59 +00002971 Load Certificate Revocation List (CRL) data from a string *buffer*.
2972 *buffer* encoded with the type *type*.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002973
2974 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2975 :param buffer: The buffer the CRL is stored in
2976
2977 :return: The PKey object
2978 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002979 if isinstance(buffer, _text_type):
2980 buffer = buffer.encode("ascii")
2981
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002982 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002983
2984 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002985 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002986 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002987 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002988 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002989 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2990
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002991 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002992 _raise_current_error()
2993
2994 result = CRL.__new__(CRL)
Jeremy Cline9e15eca2017-09-07 20:11:08 -04002995 result._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002996 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002997
2998
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002999def load_pkcs7_data(type, buffer):
3000 """
Alex Chand072cae2018-02-15 09:57:59 +00003001 Load pkcs7 data from the string *buffer* encoded with the type
3002 *type*.
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003003
3004 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
3005 :param buffer: The buffer with the pkcs7 data.
3006 :return: The PKCS7 object
3007 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05003008 if isinstance(buffer, _text_type):
3009 buffer = buffer.encode("ascii")
3010
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08003011 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003012
3013 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003014 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003015 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07003016 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003017 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003018 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
3019
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003020 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08003021 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003022
3023 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003024 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003025 return pypkcs7
3026
3027
Stephen Holsapple38482622014-04-05 20:29:34 -07003028def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003029 """
Alex Chand072cae2018-02-15 09:57:59 +00003030 Load pkcs12 data from the string *buffer*. If the pkcs12 structure is
3031 encrypted, a *passphrase* must be included. The MAC is always
3032 checked and thus required.
3033
3034 See also the man page for the C function :py:func:`PKCS12_parse`.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003035
3036 :param buffer: The buffer the certificate is stored in
3037 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
3038 :returns: The PKCS12 object
3039 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04003040 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00003041
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05003042 if isinstance(buffer, _text_type):
3043 buffer = buffer.encode("ascii")
3044
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08003045 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003046
Stephen Holsapple38482622014-04-05 20:29:34 -07003047 # Use null passphrase if passphrase is None or empty string. With PKCS#12
3048 # password based encryption no password and a zero length password are two
3049 # different things, but OpenSSL implementation will try both to figure out
3050 # which one works.
3051 if not passphrase:
3052 passphrase = _ffi.NULL
3053
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003054 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
3055 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003056 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003057 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003058
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003059 pkey = _ffi.new("EVP_PKEY**")
3060 cert = _ffi.new("X509**")
3061 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003062
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003063 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003064 if not parse_result:
3065 _raise_current_error()
3066
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003067 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08003068
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003069 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
3070 # queue for no particular reason. This error isn't interesting to anyone
3071 # outside this function. It's not even interesting to us. Get rid of it.
3072 try:
3073 _raise_current_error()
3074 except Error:
3075 pass
3076
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003077 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003078 pykey = None
3079 else:
3080 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003081 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003082
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003083 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003084 pycert = None
3085 friendlyname = None
3086 else:
Paul Kehrere7381862017-11-30 20:55:25 +08003087 pycert = X509._from_raw_x509_ptr(cert[0])
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003088
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003089 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04003090 friendlyname_buffer = _lib.X509_alias_get0(
3091 cert[0], friendlyname_length
3092 )
3093 friendlyname = _ffi.buffer(
3094 friendlyname_buffer, friendlyname_length[0]
3095 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003096 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003097 friendlyname = None
3098
3099 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003100 for i in range(_lib.sk_X509_num(cacerts)):
Paul Kehrere7381862017-11-30 20:55:25 +08003101 x509 = _lib.sk_X509_value(cacerts, i)
3102 pycacert = X509._from_raw_x509_ptr(x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003103 pycacerts.append(pycacert)
3104 if not pycacerts:
3105 pycacerts = None
3106
3107 pkcs12 = PKCS12.__new__(PKCS12)
3108 pkcs12._pkey = pykey
3109 pkcs12._cert = pycert
3110 pkcs12._cacerts = pycacerts
3111 pkcs12._friendlyname = friendlyname
3112 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05003113
3114
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05003115# There are no direct unit tests for this initialization. It is tested
3116# indirectly since it is necessary for functions like dump_privatekey when
3117# using encryption.
3118#
3119# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
3120# and some other similar tests may fail without this (though they may not if
3121# the Python runtime has already done some initialization of the underlying
3122# OpenSSL library (and is linked against the same one that cryptography is
3123# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05003124_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05003125
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05003126# This is similar but exercised mainly by exception_from_error_queue. It calls
3127# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
3128_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003129
3130
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003131# Set the default string mask to match OpenSSL upstream (since 2005) and
3132# RFC5280 recommendations.
3133_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')