blob: b8d636f12cedc3696b2c67a77b88e1c763b703ca [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
Igr2f874f22019-01-21 21:39:37 +030074TYPE_DH = _lib.EVP_PKEY_DH
75TYPE_EC = _lib.EVP_PKEY_EC
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -080076
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080077
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050078class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050079 """
80 An error occurred in an `OpenSSL.crypto` API.
81 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050082
83
84_raise_current_error = partial(_exception_from_error_queue, Error)
Alex Gaynor67903a62016-06-02 10:37:13 -070085_openssl_assert = _make_assert(Error)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050086
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070087
Paul Kehrereb633842016-10-06 11:22:01 +020088def _get_backend():
89 """
90 Importing the backend from cryptography has the side effect of activating
91 the osrandom engine. This mutates the global state of OpenSSL in the
92 process and causes issues for various programs that use subinterpreters or
93 embed Python. By putting the import in this function we can avoid
94 triggering this side effect unless _get_backend is called.
95 """
96 from cryptography.hazmat.backends.openssl.backend import backend
97 return backend
98
99
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500100def _untested_error(where):
101 """
102 An OpenSSL API failed somehow. Additionally, the failure which was
103 encountered isn't one that's exercised by the test suite so future behavior
104 of pyOpenSSL is now somewhat less predictable.
105 """
106 raise RuntimeError("Unknown %s failure" % (where,))
107
108
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500109def _new_mem_buf(buffer=None):
110 """
111 Allocate a new OpenSSL memory BIO.
112
113 Arrange for the garbage collector to clean it up automatically.
114
115 :param buffer: None or some bytes to use to put into the BIO so that they
116 can be read out.
117 """
118 if buffer is None:
119 bio = _lib.BIO_new(_lib.BIO_s_mem())
120 free = _lib.BIO_free
121 else:
122 data = _ffi.new("char[]", buffer)
123 bio = _lib.BIO_new_mem_buf(data, len(buffer))
Alex Gaynor5945ea82015-09-05 14:59:06 -0400124
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500125 # Keep the memory alive as long as the bio is alive!
126 def free(bio, ref=data):
127 return _lib.BIO_free(bio)
128
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700129 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500130
131 bio = _ffi.gc(bio, free)
132 return bio
133
134
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800135def _bio_to_string(bio):
136 """
137 Copy the contents of an OpenSSL BIO object into a Python byte string.
138 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500139 result_buffer = _ffi.new('char**')
140 buffer_length = _lib.BIO_get_mem_data(bio, result_buffer)
141 return _ffi.buffer(result_buffer[0], buffer_length)[:]
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800142
143
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800144def _set_asn1_time(boundary, when):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500145 """
146 The the time value of an ASN1 time object.
147
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900148 @param boundary: An ASN1_TIME pointer (or an object safely
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500149 castable to that type) which will have its value set.
150 @param when: A string representation of the desired time value.
151
152 @raise TypeError: If C{when} is not a L{bytes} string.
153 @raise ValueError: If C{when} does not represent a time in the required
154 format.
155 @raise RuntimeError: If the time value cannot be set for some other
156 (unspecified) reason.
157 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800158 if not isinstance(when, bytes):
159 raise TypeError("when must be a byte string")
160
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900161 set_result = _lib.ASN1_TIME_set_string(boundary, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800162 if set_result == 0:
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900163 raise ValueError("Invalid string")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800164
Alex Gaynor510293e2016-06-02 12:07:59 -0700165
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800166def _get_asn1_time(timestamp):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500167 """
168 Retrieve the time value of an ASN1 time object.
169
170 @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to
171 that type) from which the time value will be retrieved.
172
173 @return: The time value from C{timestamp} as a L{bytes} string in a certain
174 format. Or C{None} if the object contains no time value.
175 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500176 string_timestamp = _ffi.cast('ASN1_STRING*', timestamp)
177 if _lib.ASN1_STRING_length(string_timestamp) == 0:
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800178 return None
Alex Gaynor5945ea82015-09-05 14:59:06 -0400179 elif (
180 _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME
181 ):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500182 return _ffi.string(_lib.ASN1_STRING_data(string_timestamp))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800183 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500184 generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**")
185 _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp)
186 if generalized_timestamp[0] == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500187 # This may happen:
188 # - if timestamp was not an ASN1_TIME
189 # - if allocating memory for the ASN1_GENERALIZEDTIME failed
190 # - if a copy of the time data from timestamp cannot be made for
191 # the newly allocated ASN1_GENERALIZEDTIME
192 #
193 # These are difficult to test. cffi enforces the ASN1_TIME type.
194 # Memory allocation failures are a pain to trigger
195 # deterministically.
196 _untested_error("ASN1_TIME_to_generalizedtime")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800197 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500198 string_timestamp = _ffi.cast(
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800199 "ASN1_STRING*", generalized_timestamp[0])
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500200 string_data = _lib.ASN1_STRING_data(string_timestamp)
201 string_result = _ffi.string(string_data)
202 _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0])
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800203 return string_result
204
205
Alex Gaynor4aa52c32017-11-20 09:04:08 -0500206class _X509NameInvalidator(object):
207 def __init__(self):
208 self._names = []
209
210 def add(self, name):
211 self._names.append(name)
212
213 def clear(self):
214 for name in self._names:
215 # Breaks the object, but also prevents UAF!
216 del name._name
217
218
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800219class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200220 """
221 A class representing an DSA or RSA public key or key pair.
222 """
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800223 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800224 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800225
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800226 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500227 pkey = _lib.EVP_PKEY_new()
228 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800229 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800230
Paul Kehrer72d968b2016-07-29 15:31:04 +0800231 def to_cryptography_key(self):
232 """
233 Export as a ``cryptography`` key.
234
235 :rtype: One of ``cryptography``'s `key interfaces`_.
236
237 .. _key interfaces: https://cryptography.io/en/latest/hazmat/\
238 primitives/asymmetric/rsa/#key-interfaces
239
240 .. versionadded:: 16.1.0
241 """
Paul Kehrereb633842016-10-06 11:22:01 +0200242 backend = _get_backend()
Paul Kehrer72d968b2016-07-29 15:31:04 +0800243 if self._only_public:
244 return backend._evp_pkey_to_public_key(self._pkey)
245 else:
246 return backend._evp_pkey_to_private_key(self._pkey)
247
248 @classmethod
249 def from_cryptography_key(cls, crypto_key):
250 """
251 Construct based on a ``cryptography`` *crypto_key*.
252
253 :param crypto_key: A ``cryptography`` key.
254 :type crypto_key: One of ``cryptography``'s `key interfaces`_.
255
256 :rtype: PKey
257
258 .. versionadded:: 16.1.0
259 """
260 pkey = cls()
261 if not isinstance(crypto_key, (rsa.RSAPublicKey, rsa.RSAPrivateKey,
262 dsa.DSAPublicKey, dsa.DSAPrivateKey)):
263 raise TypeError("Unsupported key type")
264
265 pkey._pkey = crypto_key._evp_pkey
266 if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)):
267 pkey._only_public = True
268 pkey._initialized = True
269 return pkey
270
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800271 def generate_key(self, type, bits):
272 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700273 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800274
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200275 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800276
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200277 :param type: The key type.
278 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
279 :param bits: The number of bits.
280 :type bits: :py:data:`int` ``>= 0``
281 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
282 of the appropriate type.
283 :raises ValueError: If the number of bits isn't an integer of
284 the appropriate size.
Dan Sully44e767a2016-06-04 18:05:27 -0700285 :return: ``None``
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800286 """
287 if not isinstance(type, int):
288 raise TypeError("type must be an integer")
289
290 if not isinstance(bits, int):
291 raise TypeError("bits must be an integer")
292
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800293 if type == TYPE_RSA:
294 if bits <= 0:
295 raise ValueError("Invalid number of bits")
296
David Benjamin179eb1d2018-06-05 17:56:07 -0400297 # TODO Check error return
298 exponent = _lib.BN_new()
299 exponent = _ffi.gc(exponent, _lib.BN_free)
300 _lib.BN_set_word(exponent, _lib.RSA_F4)
301
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500302 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800303
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500304 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400305 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800306
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500307 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400308 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800309
310 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400311 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700312 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400313
314 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400315 res = _lib.DSA_generate_parameters_ex(
316 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
317 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700318 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400319
320 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
321 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800322 else:
323 raise Error("No such key type")
324
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800325 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800326
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800327 def check(self):
328 """
329 Check the consistency of an RSA private key.
330
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200331 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
332
Hynek Schlawack01c31672016-12-11 15:14:09 +0100333 :return: ``True`` if key is consistent.
334
335 :raise OpenSSL.crypto.Error: if the key is inconsistent.
336
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800337 :raise TypeError: if the key is of a type which cannot be checked.
338 Only RSA keys can currently be checked.
339 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800340 if self._only_public:
341 raise TypeError("public key only")
342
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100343 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800344 raise TypeError("key type unsupported")
345
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500346 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
347 rsa = _ffi.gc(rsa, _lib.RSA_free)
348 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800349 if result:
350 return True
351 _raise_current_error()
352
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800353 def type(self):
354 """
355 Returns the type of the key
356
357 :return: The type of the key.
358 """
Alex Gaynor0d2aec52017-05-31 04:26:27 -0400359 return _lib.EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800360
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800361 def bits(self):
362 """
363 Returns the number of bits of the key
364
365 :return: The number of bits of the key.
366 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500367 return _lib.EVP_PKEY_bits(self._pkey)
Alex Chanc6077062016-11-18 13:53:39 +0000368
369
Alex Gaynor10d30832017-06-29 15:31:39 -0700370PKeyType = deprecated(
371 PKey, __name__,
372 "PKeyType has been deprecated, use PKey instead",
373 DeprecationWarning
374)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800375
376
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400377class _EllipticCurve(object):
378 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400379 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400380
381 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
382 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
383 instances each of which represents one curve supported by the system.
384 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400385 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400386 _curves = None
387
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400388 if _PY3:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400389 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400390 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400391 """
392 Implement cooperation with the right-hand side argument of ``!=``.
393
394 Python 3 seems to have dropped this cooperation in this very narrow
395 circumstance.
396 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400397 if isinstance(other, _EllipticCurve):
398 return super(_EllipticCurve, self).__ne__(other)
399 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400400
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400401 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400402 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400403 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400404 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400405
406 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400407
408 :return: A :py:type:`set` of ``cls`` instances giving the names of the
409 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400410 """
Alex Chan84902a22017-04-20 11:50:47 +0100411 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
412 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
413 # The return value on this call should be num_curves again. We
414 # could check it to make sure but if it *isn't* then.. what could
415 # we do? Abort the whole process, I suppose...? -exarkun
416 lib.EC_get_builtin_curves(builtin_curves, num_curves)
417 return set(
418 cls.from_nid(lib, c.nid)
419 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400420
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400421 @classmethod
422 def _get_elliptic_curves(cls, lib):
423 """
424 Get, cache, and return the curves supported by OpenSSL.
425
426 :param lib: The OpenSSL library binding object.
427
428 :return: A :py:type:`set` of ``cls`` instances giving the names of the
429 elliptic curves the underlying library supports.
430 """
431 if cls._curves is None:
432 cls._curves = cls._load_elliptic_curves(lib)
433 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400434
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400435 @classmethod
436 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400437 """
438 Instantiate a new :py:class:`_EllipticCurve` associated with the given
439 OpenSSL NID.
440
441 :param lib: The OpenSSL library binding object.
442
443 :param nid: The OpenSSL NID the resulting curve object will represent.
444 This must be a curve NID (and not, for example, a hash NID) or
445 subsequent operations will fail in unpredictable ways.
446 :type nid: :py:class:`int`
447
448 :return: The curve object.
449 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400450 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
451
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400452 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400453 """
454 :param _lib: The :py:mod:`cryptography` binding instance used to
455 interface with OpenSSL.
456
457 :param _nid: The OpenSSL NID identifying the curve this object
458 represents.
459 :type _nid: :py:class:`int`
460
461 :param name: The OpenSSL short name identifying the curve this object
462 represents.
463 :type name: :py:class:`unicode`
464 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400465 self._lib = lib
466 self._nid = nid
467 self.name = name
468
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400469 def __repr__(self):
470 return "<Curve %r>" % (self.name,)
471
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400472 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400473 """
474 Create a new OpenSSL EC_KEY structure initialized to use this curve.
475
476 The structure is automatically garbage collected when the Python object
477 is garbage collected.
478 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400479 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
480 return _ffi.gc(key, _lib.EC_KEY_free)
481
482
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400483def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400484 """
485 Return a set of objects representing the elliptic curves supported in the
486 OpenSSL build in use.
487
488 The curve objects have a :py:class:`unicode` ``name`` attribute by which
489 they identify themselves.
490
491 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400492 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
493 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400494 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400495 return _EllipticCurve._get_elliptic_curves(_lib)
496
497
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400498def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400499 """
500 Return a single curve object selected by name.
501
502 See :py:func:`get_elliptic_curves` for information about curve objects.
503
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400504 :param name: The OpenSSL short name identifying the curve object to
505 retrieve.
506 :type name: :py:class:`unicode`
507
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400508 If the named curve is not supported then :py:class:`ValueError` is raised.
509 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400510 for curve in get_elliptic_curves():
511 if curve.name == name:
512 return curve
513 raise ValueError("unknown curve name", name)
514
515
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800516class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200517 """
518 An X.509 Distinguished Name.
519
520 :ivar countryName: The country of the entity.
521 :ivar C: Alias for :py:attr:`countryName`.
522
523 :ivar stateOrProvinceName: The state or province of the entity.
524 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
525
526 :ivar localityName: The locality of the entity.
527 :ivar L: Alias for :py:attr:`localityName`.
528
529 :ivar organizationName: The organization name of the entity.
530 :ivar O: Alias for :py:attr:`organizationName`.
531
532 :ivar organizationalUnitName: The organizational unit of the entity.
533 :ivar OU: Alias for :py:attr:`organizationalUnitName`
534
535 :ivar commonName: The common name of the entity.
536 :ivar CN: Alias for :py:attr:`commonName`.
537
538 :ivar emailAddress: The e-mail address of the entity.
539 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400540
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800541 def __init__(self, name):
542 """
543 Create a new X509Name, copying the given X509Name instance.
544
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200545 :param name: The name to copy.
546 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800547 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500548 name = _lib.X509_NAME_dup(name._name)
549 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800550
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800551 def __setattr__(self, name, value):
552 if name.startswith('_'):
553 return super(X509Name, self).__setattr__(name, value)
554
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800555 # Note: we really do not want str subclasses here, so we do not use
556 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800557 if type(name) is not str:
558 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400559 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800560
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500561 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500562 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800563 try:
564 _raise_current_error()
565 except Error:
566 pass
567 raise AttributeError("No such attribute")
568
569 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500570 for i in range(_lib.X509_NAME_entry_count(self._name)):
571 ent = _lib.X509_NAME_get_entry(self._name, i)
572 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
573 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800574 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500575 ent = _lib.X509_NAME_delete_entry(self._name, i)
576 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800577 break
578
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500579 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800580 value = value.encode('utf-8')
581
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500582 add_result = _lib.X509_NAME_add_entry_by_NID(
583 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800584 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500585 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800586
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800587 def __getattr__(self, name):
588 """
589 Find attribute. An X509Name object has the following attributes:
590 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400591 organization (alias O), organizationalUnit (alias OU), commonName
592 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800593 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500594 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500595 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800596 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
597 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
598 # push something onto the error queue. If we don't clean that up
599 # now, someone else will bump into it later and be quite confused.
600 # See lp#314814.
601 try:
602 _raise_current_error()
603 except Error:
604 pass
605 return super(X509Name, self).__getattr__(name)
606
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500607 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800608 if entry_index == -1:
609 return None
610
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500611 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
612 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800613
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500614 result_buffer = _ffi.new("unsigned char**")
615 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400616 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800617
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700618 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400619 result = _ffi.buffer(
620 result_buffer[0], data_length
621 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700622 finally:
623 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500624 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800625 return result
626
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500627 def _cmp(op):
628 def f(self, other):
629 if not isinstance(other, X509Name):
630 return NotImplemented
631 result = _lib.X509_NAME_cmp(self._name, other._name)
632 return op(result, 0)
633 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800634
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500635 __eq__ = _cmp(__eq__)
636 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800637
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500638 __lt__ = _cmp(__lt__)
639 __le__ = _cmp(__le__)
640
641 __gt__ = _cmp(__gt__)
642 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800643
644 def __repr__(self):
645 """
646 String representation of an X509Name
647 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400648 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500649 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800650 self._name, result_buffer, len(result_buffer))
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700651 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800652
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500653 return "<X509Name object '%s'>" % (
654 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800655
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800656 def hash(self):
657 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200658 Return an integer representation of the first four bytes of the
659 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800660
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200661 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
662
663 :return: The (integer) hash of this name.
664 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800665 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500666 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800667
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800668 def der(self):
669 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200670 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800671
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200672 :return: The DER encoded form of this name.
673 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800674 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500675 result_buffer = _ffi.new('unsigned char**')
676 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400677 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800678
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500679 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
680 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800681 return string_result
682
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800683 def get_components(self):
684 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200685 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800686
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200687 :return: The components of this name.
688 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800689 """
690 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500691 for i in range(_lib.X509_NAME_entry_count(self._name)):
692 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800693
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500694 fname = _lib.X509_NAME_ENTRY_get_object(ent)
695 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800696
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500697 nid = _lib.OBJ_obj2nid(fname)
698 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800699
Romuald Brunet4183beb2019-01-21 19:38:33 +0100700 # ffi.string does not handle strings containing NULL bytes
701 # (which may have been generated by old, broken software)
702 value = _ffi.buffer(_lib.ASN1_STRING_data(fval),
703 _lib.ASN1_STRING_length(fval))[:]
704 result.append((_ffi.string(name), value))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800705
706 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200707
708
Alex Gaynor10d30832017-06-29 15:31:39 -0700709X509NameType = deprecated(
710 X509Name, __name__,
711 "X509NameType has been deprecated, use X509Name instead",
712 DeprecationWarning
713)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800714
715
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800716class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200717 """
718 An X.509 v3 certificate extension.
719 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400720
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800721 def __init__(self, type_name, critical, value, subject=None, issuer=None):
722 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200723 Initializes an X509 extension.
724
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100725 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400726 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800727
Alex Gaynor5945ea82015-09-05 14:59:06 -0400728 :param bool critical: A flag indicating whether this is a critical
729 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800730
731 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200732 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800733
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200734 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800735 :type subject: :py:class:`X509`
736
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200737 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800738 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100739
Alex Chan54005ce2017-03-21 08:08:17 +0000740 .. _extension: https://www.openssl.org/docs/manmaster/man5/
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100741 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800742 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500743 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800744
Alex Gaynor5945ea82015-09-05 14:59:06 -0400745 # A context is necessary for any extension which uses the r2i
746 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
747 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500748 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800749
750 # We have no configuration database - but perhaps we should (some
751 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500752 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800753
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800754 # Initialize the subject and issuer, if appropriate. ctx is a local,
755 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400756 # any references, so no need to mess with reference counts or
757 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800758 if issuer is not None:
759 if not isinstance(issuer, X509):
760 raise TypeError("issuer must be an X509 instance")
761 ctx.issuer_cert = issuer._x509
762 if subject is not None:
763 if not isinstance(subject, X509):
764 raise TypeError("subject must be an X509 instance")
765 ctx.subject_cert = subject._x509
766
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800767 if critical:
768 # There are other OpenSSL APIs which would let us pass in critical
769 # separately, but they're harder to use, and since value is already
770 # a pile of crappy junk smuggling a ton of utterly important
771 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400772 # with strings? (However, X509V3_EXT_i2d in particular seems like
773 # it would be a better API to invoke. I do not know where to get
774 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500775 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800776
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500777 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
778 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800779 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500780 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800781
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400782 @property
783 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400784 return _lib.OBJ_obj2nid(
785 _lib.X509_EXTENSION_get_object(self._extension)
786 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400787
788 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500789 _lib.GEN_EMAIL: "email",
790 _lib.GEN_DNS: "DNS",
791 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400792 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400793
794 def _subjectAltNameString(self):
Alex Gaynord61c46a2017-06-29 22:51:33 -0700795 names = _ffi.cast(
796 "GENERAL_NAMES*", _lib.X509V3_EXT_d2i(self._extension)
797 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400798
Paul Kehrerb7d79502015-05-04 07:43:51 -0500799 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400800 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500801 for i in range(_lib.sk_GENERAL_NAME_num(names)):
802 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400803 try:
804 label = self._prefixes[name.type]
805 except KeyError:
806 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500807 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500808 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400809 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500810 value = _native(
811 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
812 parts.append(label + ":" + value)
813 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400814
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800815 def __str__(self):
816 """
817 :return: a nice text representation of the extension
818 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500819 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400820 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800821
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400822 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500823 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400824 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800825
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500826 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800827
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800828 def get_critical(self):
829 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200830 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800831
832 :return: The critical field.
833 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500834 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800835
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800836 def get_short_name(self):
837 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200838 Returns the short type name of this X.509 extension.
839
840 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800841
842 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200843 :rtype: :py:data:`bytes`
844
845 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800846 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500847 obj = _lib.X509_EXTENSION_get_object(self._extension)
848 nid = _lib.OBJ_obj2nid(obj)
849 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800850
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800851 def get_data(self):
852 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200853 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800854
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200855 :return: The ASN.1 encoded data of this X509 extension.
856 :rtype: :py:data:`bytes`
857
858 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800859 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500860 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
861 string_result = _ffi.cast('ASN1_STRING*', octet_result)
862 char_result = _lib.ASN1_STRING_data(string_result)
863 result_length = _lib.ASN1_STRING_length(string_result)
864 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800865
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200866
Alex Gaynor10d30832017-06-29 15:31:39 -0700867X509ExtensionType = deprecated(
868 X509Extension, __name__,
869 "X509ExtensionType has been deprecated, use X509Extension instead",
870 DeprecationWarning
871)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800872
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800873
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800874class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200875 """
876 An X.509 certificate signing requests.
877 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400878
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800879 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500880 req = _lib.X509_REQ_new()
881 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Alex Gaynor5af32d02016-09-24 01:52:21 -0400882 # Default to version 0.
883 self.set_version(0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800884
Paul Kehrer41c10242017-06-29 18:24:17 -0500885 def to_cryptography(self):
886 """
887 Export as a ``cryptography`` certificate signing request.
888
889 :rtype: ``cryptography.x509.CertificateSigningRequest``
890
891 .. versionadded:: 17.1.0
892 """
893 from cryptography.hazmat.backends.openssl.x509 import (
894 _CertificateSigningRequest
895 )
896 backend = _get_backend()
897 return _CertificateSigningRequest(backend, self._req)
898
899 @classmethod
900 def from_cryptography(cls, crypto_req):
901 """
902 Construct based on a ``cryptography`` *crypto_req*.
903
904 :param crypto_req: A ``cryptography`` X.509 certificate signing request
905 :type crypto_req: ``cryptography.x509.CertificateSigningRequest``
906
Gaurav Malhotra4121e252019-01-22 00:09:19 +0530907 :rtype: X509Req
Paul Kehrer41c10242017-06-29 18:24:17 -0500908
909 .. versionadded:: 17.1.0
910 """
911 if not isinstance(crypto_req, x509.CertificateSigningRequest):
912 raise TypeError("Must be a certificate signing request")
913
914 req = cls()
915 req._req = crypto_req._x509_req
916 return req
917
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800918 def set_pubkey(self, pkey):
919 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200920 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800921
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200922 :param pkey: The public key to use.
923 :type pkey: :py:class:`PKey`
924
Dan Sully44e767a2016-06-04 18:05:27 -0700925 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800926 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500927 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400928 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800929
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800930 def get_pubkey(self):
931 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200932 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800933
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200934 :return: The public key.
935 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800936 """
937 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500938 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700939 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500940 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800941 pkey._only_public = True
942 return pkey
943
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800944 def set_version(self, version):
945 """
946 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
947 request.
948
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200949 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700950 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800951 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500952 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400953 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800954
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800955 def get_version(self):
956 """
957 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
958 request.
959
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200960 :return: The value of the version subfield.
961 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800962 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500963 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800964
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800965 def get_subject(self):
966 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200967 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800968
Cory Benfield881dc8d2015-12-09 08:25:14 +0000969 This creates a new :class:`X509Name` that wraps the underlying subject
970 name field on the certificate signing request. Modifying it will modify
971 the underlying signing request, and will have the effect of modifying
972 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200973
974 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000975 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800976 """
977 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500978 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700979 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800980
981 # The name is owned by the X509Req structure. As long as the X509Name
982 # Python object is alive, keep the X509Req Python object alive.
983 name._owner = self
984
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800985 return name
986
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800987 def add_extensions(self, extensions):
988 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200989 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800990
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200991 :param extensions: The X.509 extensions to add.
992 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700993 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800994 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500995 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700996 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800997
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500998 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800999
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001000 for ext in extensions:
1001 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -08001002 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001003
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001004 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001005 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001006
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001007 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001008 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001009
Stephen Holsappleadfd39d2014-01-28 17:58:31 -08001010 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001011 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001012 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -08001013
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001014 :return: The X.509 extensions in this request.
1015 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
1016
1017 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001018 """
1019 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -05001020 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -05001021 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001022 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -05001023 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001024 exts.append(ext)
1025 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -08001026
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001027 def sign(self, pkey, digest):
1028 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001029 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001030
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001031 :param pkey: The key pair to sign with.
1032 :type pkey: :py:class:`PKey`
1033 :param digest: The name of the message digest to use for the signature,
Alex Gaynor239e2d32016-09-11 12:36:35 -04001034 e.g. :py:data:`b"sha256"`.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001035 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -07001036 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001037 """
1038 if pkey._only_public:
1039 raise ValueError("Key has only public part")
1040
1041 if not pkey._initialized:
1042 raise ValueError("Key is uninitialized")
1043
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001044 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001045 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001046 raise ValueError("No such digest method")
1047
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001048 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001049 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001050
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001051 def verify(self, pkey):
1052 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001053 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001054
Hynek Schlawack01c31672016-12-11 15:14:09 +01001055 :param PKey key: A public key.
1056
1057 :return: ``True`` if the signature is correct.
1058 :rtype: bool
1059
1060 :raises OpenSSL.crypto.Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001061 problem verifying the signature.
1062 """
1063 if not isinstance(pkey, PKey):
1064 raise TypeError("pkey must be a PKey instance")
1065
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001066 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001067 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001068 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001069
1070 return result
1071
1072
Alex Gaynor10d30832017-06-29 15:31:39 -07001073X509ReqType = deprecated(
1074 X509Req, __name__,
1075 "X509ReqType has been deprecated, use X509Req instead",
1076 DeprecationWarning
1077)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001078
1079
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001080class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001081 """
1082 An X.509 certificate.
1083 """
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001084 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001085 x509 = _lib.X509_new()
Hynek Schlawack8a2dd772016-07-31 13:46:20 +02001086 _openssl_assert(x509 != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001087 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001088
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001089 self._issuer_invalidator = _X509NameInvalidator()
1090 self._subject_invalidator = _X509NameInvalidator()
1091
1092 @classmethod
1093 def _from_raw_x509_ptr(cls, x509):
1094 cert = cls.__new__(cls)
1095 cert._x509 = _ffi.gc(x509, _lib.X509_free)
1096 cert._issuer_invalidator = _X509NameInvalidator()
1097 cert._subject_invalidator = _X509NameInvalidator()
1098 return cert
1099
Alex Gaynor9939ba12017-06-25 16:28:24 -04001100 def to_cryptography(self):
1101 """
1102 Export as a ``cryptography`` certificate.
1103
1104 :rtype: ``cryptography.x509.Certificate``
1105
1106 .. versionadded:: 17.1.0
1107 """
1108 from cryptography.hazmat.backends.openssl.x509 import _Certificate
1109 backend = _get_backend()
1110 return _Certificate(backend, self._x509)
1111
1112 @classmethod
1113 def from_cryptography(cls, crypto_cert):
1114 """
1115 Construct based on a ``cryptography`` *crypto_cert*.
1116
1117 :param crypto_key: A ``cryptography`` X.509 certificate.
1118 :type crypto_key: ``cryptography.x509.Certificate``
1119
Gaurav Malhotra4121e252019-01-22 00:09:19 +05301120 :rtype: X509
Alex Gaynor9939ba12017-06-25 16:28:24 -04001121
1122 .. versionadded:: 17.1.0
1123 """
1124 if not isinstance(crypto_cert, x509.Certificate):
1125 raise TypeError("Must be a certificate")
1126
1127 cert = cls()
1128 cert._x509 = crypto_cert._x509
1129 return cert
1130
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001131 def set_version(self, version):
1132 """
Cyril Stoller6f25ced2018-08-27 13:37:51 +02001133 Set the version number of the certificate. Note that the
1134 version value is zero-based, eg. a value of 0 is V1.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001135
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001136 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001137 :type version: :py:class:`int`
1138
Dan Sully44e767a2016-06-04 18:05:27 -07001139 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001140 """
1141 if not isinstance(version, int):
1142 raise TypeError("version must be an integer")
1143
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001144 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001145
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001146 def get_version(self):
1147 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001148 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001149
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001150 :return: The version number of the certificate.
1151 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001152 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001153 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001154
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001155 def get_pubkey(self):
1156 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001157 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001158
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001159 :return: The public key.
1160 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001161 """
1162 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001163 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1164 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001165 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001166 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001167 pkey._only_public = True
1168 return pkey
1169
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001170 def set_pubkey(self, pkey):
1171 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001172 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001173
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001174 :param pkey: The public key.
1175 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001176
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001177 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001178 """
1179 if not isinstance(pkey, PKey):
1180 raise TypeError("pkey must be a PKey instance")
1181
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001182 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001183 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001184
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001185 def sign(self, pkey, digest):
1186 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001187 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001188
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001189 :param pkey: The key to sign with.
1190 :type pkey: :py:class:`PKey`
1191
1192 :param digest: The name of the message digest to use.
1193 :type digest: :py:class:`bytes`
1194
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001195 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001196 """
1197 if not isinstance(pkey, PKey):
1198 raise TypeError("pkey must be a PKey instance")
1199
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001200 if pkey._only_public:
1201 raise ValueError("Key only has public part")
1202
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001203 if not pkey._initialized:
1204 raise ValueError("Key is uninitialized")
1205
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001206 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001207 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001208 raise ValueError("No such digest method")
1209
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001210 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001211 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001212
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001213 def get_signature_algorithm(self):
1214 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001215 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001216
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001217 :return: The name of the algorithm.
1218 :rtype: :py:class:`bytes`
1219
1220 :raises ValueError: If the signature algorithm is undefined.
1221
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001222 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001223 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001224 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1225 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001226 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001227 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001228 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001229
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001230 def digest(self, digest_name):
1231 """
1232 Return the digest of the X509 object.
1233
1234 :param digest_name: The name of the digest algorithm to use.
1235 :type digest_name: :py:class:`bytes`
1236
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001237 :return: The digest of the object, formatted as
1238 :py:const:`b":"`-delimited hex pairs.
1239 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001240 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001241 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001242 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001243 raise ValueError("No such digest method")
1244
Paul Kehrer9f9113a2016-09-20 20:10:25 -05001245 result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001246 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001247 result_length[0] = len(result_buffer)
1248
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001249 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001250 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001251 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001252
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001253 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001254 b16encode(ch).upper() for ch
1255 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001256
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001257 def subject_name_hash(self):
1258 """
1259 Return the hash of the X509 subject.
1260
1261 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001262 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001263 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001264 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001265
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001266 def set_serial_number(self, serial):
1267 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001268 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001269
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001270 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001271 :type serial: :py:class:`int`
1272
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001273 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001274 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001275 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001276 raise TypeError("serial must be an integer")
1277
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001278 hex_serial = hex(serial)[2:]
1279 if not isinstance(hex_serial, bytes):
1280 hex_serial = hex_serial.encode('ascii')
1281
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001282 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001283
1284 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001285 # it. If bignum is still NULL after this call, then the return value
1286 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001287 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001288
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001289 if bignum_serial[0] == _ffi.NULL:
1290 set_result = _lib.ASN1_INTEGER_set(
1291 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001292 if set_result:
1293 # TODO Not tested
1294 _raise_current_error()
1295 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001296 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1297 _lib.BN_free(bignum_serial[0])
1298 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001299 # TODO Not tested
1300 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001301 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1302 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001303 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001304
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001305 def get_serial_number(self):
1306 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001307 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001308
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001309 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001310 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001311 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001312 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1313 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001314 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001315 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001316 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001317 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001318 serial = int(hexstring_serial, 16)
1319 return serial
1320 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001321 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001322 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001323 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001324
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001325 def gmtime_adj_notAfter(self, amount):
1326 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001327 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001328
Dan Sully44e767a2016-06-04 18:05:27 -07001329 :param int amount: The number of seconds by which to adjust the
1330 timestamp.
1331 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001332 """
1333 if not isinstance(amount, int):
1334 raise TypeError("amount must be an integer")
1335
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001336 notAfter = _lib.X509_get_notAfter(self._x509)
1337 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001338
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001339 def gmtime_adj_notBefore(self, amount):
1340 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001341 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001342
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001343 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001344 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001345 """
1346 if not isinstance(amount, int):
1347 raise TypeError("amount must be an integer")
1348
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001349 notBefore = _lib.X509_get_notBefore(self._x509)
1350 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001351
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001352 def has_expired(self):
1353 """
1354 Check whether the certificate has expired.
1355
Dan Sully44e767a2016-06-04 18:05:27 -07001356 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1357 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001358 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001359 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001360 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001361
Paul Kehrerfde45c92016-01-21 12:57:37 -06001362 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001363
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001364 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001365 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001366
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001367 def get_notBefore(self):
1368 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001369 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001370
Paul Kehrerce98ee62017-06-21 06:59:58 -10001371 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001372
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001373 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001374
Dan Sully44e767a2016-06-04 18:05:27 -07001375 :return: A timestamp string, or ``None`` if there is none.
1376 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001377 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001378 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001379
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001380 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001381 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001382
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001383 def set_notBefore(self, when):
1384 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001385 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001386
Paul Kehrerce98ee62017-06-21 06:59:58 -10001387 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001388
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001389 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001390
Dan Sully44e767a2016-06-04 18:05:27 -07001391 :param bytes when: A timestamp string.
1392 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001393 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001394 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001395
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001396 def get_notAfter(self):
1397 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001398 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001399
Paul Kehrerce98ee62017-06-21 06:59:58 -10001400 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001401
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001402 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001403
Dan Sully44e767a2016-06-04 18:05:27 -07001404 :return: A timestamp string, or ``None`` if there is none.
1405 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001406 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001407 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001408
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001409 def set_notAfter(self, when):
1410 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001411 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001412
Paul Kehrerce98ee62017-06-21 06:59:58 -10001413 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001414
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001415 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001416
Dan Sully44e767a2016-06-04 18:05:27 -07001417 :param bytes when: A timestamp string.
1418 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001419 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001420 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001421
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001422 def _get_name(self, which):
1423 name = X509Name.__new__(X509Name)
1424 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001425 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001426
1427 # The name is owned by the X509 structure. As long as the X509Name
1428 # Python object is alive, keep the X509 Python object alive.
1429 name._owner = self
1430
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001431 return name
1432
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001433 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001434 if not isinstance(name, X509Name):
1435 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001436 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001437 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001438
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001439 def get_issuer(self):
1440 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001441 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001442
Cory Benfielde6bcce82015-12-09 08:40:03 +00001443 This creates a new :class:`X509Name` that wraps the underlying issuer
1444 name field on the certificate. Modifying it will modify the underlying
1445 certificate, and will have the effect of modifying any other
1446 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001447
1448 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001449 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001450 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001451 name = self._get_name(_lib.X509_get_issuer_name)
1452 self._issuer_invalidator.add(name)
1453 return name
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001454
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001455 def set_issuer(self, issuer):
1456 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001457 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001458
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001459 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001460 :type issuer: :py:class:`X509Name`
1461
Dan Sully44e767a2016-06-04 18:05:27 -07001462 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001463 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001464 self._set_name(_lib.X509_set_issuer_name, issuer)
1465 self._issuer_invalidator.clear()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001466
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001467 def get_subject(self):
1468 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001469 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001470
Cory Benfielde6bcce82015-12-09 08:40:03 +00001471 This creates a new :class:`X509Name` that wraps the underlying subject
1472 name field on the certificate. Modifying it will modify the underlying
1473 certificate, and will have the effect of modifying any other
1474 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001475
1476 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001477 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001478 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001479 name = self._get_name(_lib.X509_get_subject_name)
1480 self._subject_invalidator.add(name)
1481 return name
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001482
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001483 def set_subject(self, subject):
1484 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001485 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001486
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001487 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001488 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001489
Dan Sully44e767a2016-06-04 18:05:27 -07001490 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001491 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001492 self._set_name(_lib.X509_set_subject_name, subject)
1493 self._subject_invalidator.clear()
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001494
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001495 def get_extension_count(self):
1496 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001497 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001498
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001499 :return: The number of extensions.
1500 :rtype: :py:class:`int`
1501
1502 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001503 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001504 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001505
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001506 def add_extensions(self, extensions):
1507 """
1508 Add extensions to the certificate.
1509
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001510 :param extensions: The extensions to add.
1511 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001512 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001513 """
1514 for ext in extensions:
1515 if not isinstance(ext, X509Extension):
1516 raise ValueError("One of the elements is not an X509Extension")
1517
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001518 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001519 if not add_result:
1520 _raise_current_error()
1521
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001522 def get_extension(self, index):
1523 """
1524 Get a specific extension of the certificate by index.
1525
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001526 Extensions on a certificate are kept in order. The index
1527 parameter selects which extension will be returned.
1528
1529 :param int index: The index of the extension to retrieve.
1530 :return: The extension at the specified index.
1531 :rtype: :py:class:`X509Extension`
1532 :raises IndexError: If the extension index was out of bounds.
1533
1534 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001535 """
1536 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001537 ext._extension = _lib.X509_get_ext(self._x509, index)
1538 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001539 raise IndexError("extension index out of bounds")
1540
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001541 extension = _lib.X509_EXTENSION_dup(ext._extension)
1542 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001543 return ext
1544
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001545
Alex Gaynor10d30832017-06-29 15:31:39 -07001546X509Type = deprecated(
1547 X509, __name__,
1548 "X509Type has been deprecated, use X509 instead",
1549 DeprecationWarning
1550)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001551
1552
Dan Sully44e767a2016-06-04 18:05:27 -07001553class X509StoreFlags(object):
1554 """
1555 Flags for X509 verification, used to change the behavior of
1556 :class:`X509Store`.
1557
1558 See `OpenSSL Verification Flags`_ for details.
1559
1560 .. _OpenSSL Verification Flags:
Alex Chan54005ce2017-03-21 08:08:17 +00001561 https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_flags.html
Dan Sully44e767a2016-06-04 18:05:27 -07001562 """
1563 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1564 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1565 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1566 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1567 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1568 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1569 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1570 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1571 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1572 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1573 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1574
1575
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001576class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001577 """
Dan Sully44e767a2016-06-04 18:05:27 -07001578 An X.509 store.
1579
1580 An X.509 store is used to describe a context in which to verify a
1581 certificate. A description of a context may include a set of certificates
1582 to trust, a set of certificate revocation lists, verification flags and
1583 more.
1584
1585 An X.509 store, being only a description, cannot be used by itself to
1586 verify a certificate. To carry out the actual verification process, see
1587 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001588 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001589
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001590 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001591 store = _lib.X509_STORE_new()
1592 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001593
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001594 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001595 """
Dan Sully44e767a2016-06-04 18:05:27 -07001596 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001597
Dan Sully44e767a2016-06-04 18:05:27 -07001598 Adding a certificate with this method adds this certificate as a
1599 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001600
1601 :param X509 cert: The certificate to add to this store.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001602
Dan Sully44e767a2016-06-04 18:05:27 -07001603 :raises TypeError: If the certificate is not an :class:`X509`.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001604
1605 :raises OpenSSL.crypto.Error: If OpenSSL was unhappy with your
1606 certificate.
1607
Dan Sully44e767a2016-06-04 18:05:27 -07001608 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001609 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001610 if not isinstance(cert, X509):
1611 raise TypeError()
1612
Paul Kehrer0e6c5532018-08-23 10:52:15 -05001613 # As of OpenSSL 1.1.0i adding the same cert to the store more than
1614 # once doesn't cause an error. Accordingly, this code now silences
1615 # the error for OpenSSL < 1.1.0i as well.
1616 if _lib.X509_STORE_add_cert(self._store, cert._x509) == 0:
1617 code = _lib.ERR_peek_error()
1618 err_reason = _lib.ERR_GET_REASON(code)
1619 _openssl_assert(
1620 err_reason == _lib.X509_R_CERT_ALREADY_IN_HASH_TABLE
1621 )
1622 _lib.ERR_clear_error()
Dan Sully44e767a2016-06-04 18:05:27 -07001623
1624 def add_crl(self, crl):
1625 """
1626 Add a certificate revocation list to this store.
1627
1628 The certificate revocation lists added to a store will only be used if
1629 the associated flags are configured to check certificate revocation
1630 lists.
1631
1632 .. versionadded:: 16.1.0
1633
1634 :param CRL crl: The certificate revocation list to add to this store.
1635 :return: ``None`` if the certificate revocation list was added
1636 successfully.
1637 """
1638 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1639
1640 def set_flags(self, flags):
1641 """
1642 Set verification flags to this store.
1643
1644 Verification flags can be combined by oring them together.
1645
1646 .. note::
1647
1648 Setting a verification flag sometimes requires clients to add
1649 additional information to the store, otherwise a suitable error will
1650 be raised.
1651
1652 For example, in setting flags to enable CRL checking a
1653 suitable CRL must be added to the store otherwise an error will be
1654 raised.
1655
1656 .. versionadded:: 16.1.0
1657
1658 :param int flags: The verification flags to set on this store.
1659 See :class:`X509StoreFlags` for available constants.
1660 :return: ``None`` if the verification flags were successfully set.
1661 """
1662 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001663
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001664 def set_time(self, vfy_time):
1665 """
1666 Set the time against which the certificates are verified.
1667
1668 Normally the current time is used.
1669
1670 .. note::
1671
1672 For example, you can determine if a certificate was valid at a given
1673 time.
1674
Hynek Schlawackf6c96af2017-04-20 12:34:58 +02001675 .. versionadded:: 17.0.0
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001676
1677 :param datetime vfy_time: The verification time to set on this store.
1678 :return: ``None`` if the verification time was successfully set.
1679 """
1680 param = _lib.X509_VERIFY_PARAM_new()
1681 param = _ffi.gc(param, _lib.X509_VERIFY_PARAM_free)
1682
1683 _lib.X509_VERIFY_PARAM_set_time(param, int(vfy_time.strftime('%s')))
1684 _openssl_assert(_lib.X509_STORE_set1_param(self._store, param) != 0)
1685
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001686
Alex Gaynor10d30832017-06-29 15:31:39 -07001687X509StoreType = deprecated(
1688 X509Store, __name__,
1689 "X509StoreType has been deprecated, use X509Store instead",
1690 DeprecationWarning
1691)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001692
1693
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001694class X509StoreContextError(Exception):
1695 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001696 An exception raised when an error occurred while verifying a certificate
1697 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001698
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001699 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001700 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001701 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001702
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001703 def __init__(self, message, certificate):
1704 super(X509StoreContextError, self).__init__(message)
1705 self.certificate = certificate
1706
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001707
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001708class X509StoreContext(object):
1709 """
1710 An X.509 store context.
1711
Dan Sully44e767a2016-06-04 18:05:27 -07001712 An X.509 store context is used to carry out the actual verification process
1713 of a certificate in a described context. For describing such a context, see
1714 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001715
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001716 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1717 instance. It is dynamically allocated and automatically garbage
1718 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001719 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001720 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001721 :param X509Store store: The certificates which will be trusted for the
1722 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001723 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001724 """
1725
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001726 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001727 store_ctx = _lib.X509_STORE_CTX_new()
1728 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1729 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001730 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001731 # Make the store context available for use after instantiating this
1732 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001733 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001734 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001735
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001736 def _init(self):
1737 """
1738 Set up the store context for a subsequent verification operation.
Jeremy Cline58193f12017-09-13 21:14:53 -04001739
1740 Calling this method more than once without first calling
1741 :meth:`_cleanup` will leak memory.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001742 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001743 ret = _lib.X509_STORE_CTX_init(
1744 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1745 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001746 if ret <= 0:
1747 _raise_current_error()
1748
1749 def _cleanup(self):
1750 """
1751 Internally cleans up the store context.
1752
Dan Sully44e767a2016-06-04 18:05:27 -07001753 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001754 """
1755 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1756
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001757 def _exception_from_context(self):
1758 """
1759 Convert an OpenSSL native context error failure into a Python
1760 exception.
1761
Alex Gaynor5945ea82015-09-05 14:59:06 -04001762 When a call to native OpenSSL X509_verify_cert fails, additional
1763 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001764 """
1765 errors = [
1766 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1767 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1768 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001769 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001770 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001771 # A context error should always be associated with a certificate, so we
1772 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001773 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001774 _cert = _lib.X509_dup(_x509)
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001775 pycert = X509._from_raw_x509_ptr(_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001776 return X509StoreContextError(errors, pycert)
1777
Stephen Holsapple46a09252015-02-12 14:45:43 -08001778 def set_store(self, store):
1779 """
Dan Sully44e767a2016-06-04 18:05:27 -07001780 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001781
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001782 .. versionadded:: 0.15
1783
Dan Sully44e767a2016-06-04 18:05:27 -07001784 :param X509Store store: The store description which will be used for
1785 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001786 """
1787 self._store = store
1788
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001789 def verify_certificate(self):
1790 """
1791 Verify a certificate in a context.
1792
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001793 .. versionadded:: 0.15
1794
Alex Gaynorca87ff62015-09-04 23:31:03 -04001795 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001796 certificate in the context. Sets ``certificate`` attribute to
1797 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001798 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001799 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001800 # :meth:`verify_certificate` is called multiple times.
Jeremy Cline58193f12017-09-13 21:14:53 -04001801 #
1802 # :meth:`_init` is called in :meth:`__init__` so _cleanup is called
1803 # before _init to ensure memory is not leaked.
1804 self._cleanup()
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001805 self._init()
1806 ret = _lib.X509_verify_cert(self._store_ctx)
1807 self._cleanup()
1808 if ret <= 0:
1809 raise self._exception_from_context()
1810
1811
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001812def load_certificate(type, buffer):
1813 """
Alex Chand072cae2018-02-15 09:57:59 +00001814 Load a certificate (X509) from the string *buffer* encoded with the
1815 type *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001816
1817 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1818
Dan Sully44e767a2016-06-04 18:05:27 -07001819 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001820
1821 :return: The X509 object
1822 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001823 if isinstance(buffer, _text_type):
1824 buffer = buffer.encode("ascii")
1825
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001826 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001827
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001828 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001829 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001830 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001831 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001832 else:
1833 raise ValueError(
1834 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001835
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001836 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001837 _raise_current_error()
1838
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001839 return X509._from_raw_x509_ptr(x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001840
1841
1842def dump_certificate(type, cert):
1843 """
Alex Chand072cae2018-02-15 09:57:59 +00001844 Dump the certificate *cert* into a buffer string encoded with the type
1845 *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001846
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001847 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1848 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001849 :param cert: The certificate to dump
1850 :return: The buffer with the dumped certificate in
1851 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001852 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001853
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001854 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001855 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001856 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001857 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001858 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001859 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001860 else:
1861 raise ValueError(
1862 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1863 "FILETYPE_TEXT")
1864
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001865 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001866 return _bio_to_string(bio)
1867
1868
Cory Benfield6492f7c2015-10-27 16:57:58 +09001869def dump_publickey(type, pkey):
1870 """
Cory Benfield11c10192015-10-27 17:23:03 +09001871 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001872
Cory Benfield9c590b92015-10-28 14:55:05 +09001873 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001874 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001875 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001876 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001877 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001878 """
1879 bio = _new_mem_buf()
1880 if type == FILETYPE_PEM:
1881 write_bio = _lib.PEM_write_bio_PUBKEY
1882 elif type == FILETYPE_ASN1:
1883 write_bio = _lib.i2d_PUBKEY_bio
1884 else:
1885 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1886
1887 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001888 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001889 _raise_current_error()
1890
1891 return _bio_to_string(bio)
1892
1893
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001894def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1895 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001896 Dump the private key *pkey* into a buffer string encoded with the type
1897 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1898 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001899
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001900 :param type: The file type (one of :const:`FILETYPE_PEM`,
1901 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1902 :param PKey pkey: The PKey to dump
1903 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001904 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001905 the passphrase to use, or a callback for providing the passphrase.
1906
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001907 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001908 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001909 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001910 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001911
Paul Kehrercded9932017-06-29 18:43:42 -05001912 if not isinstance(pkey, PKey):
1913 raise TypeError("pkey must be a PKey")
1914
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001915 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001916 if passphrase is None:
1917 raise TypeError(
1918 "if a value is given for cipher "
1919 "one must also be given for passphrase")
1920 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001921 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001922 raise ValueError("Invalid cipher name")
1923 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001924 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001925
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001926 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001927 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001928 result_code = _lib.PEM_write_bio_PrivateKey(
1929 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001930 helper.callback, helper.callback_args)
1931 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001932 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001933 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001934 elif type == FILETYPE_TEXT:
Paul Kehrercded9932017-06-29 18:43:42 -05001935 if _lib.EVP_PKEY_id(pkey._pkey) != _lib.EVP_PKEY_RSA:
1936 raise TypeError("Only RSA keys are supported for FILETYPE_TEXT")
1937
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001938 rsa = _ffi.gc(
1939 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1940 _lib.RSA_free
1941 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001942 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001943 else:
1944 raise ValueError(
1945 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1946 "FILETYPE_TEXT")
1947
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001948 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001949
1950 return _bio_to_string(bio)
1951
1952
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001953class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001954 """
1955 A certificate revocation.
1956 """
Cyril Stoller37e60222018-08-27 13:38:10 +02001957 # https://www.openssl.org/docs/manmaster/man5/x509v3_config.html#CRL-distribution-points
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001958 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1959 # OCSP_crl_reason_str. We use the latter, just like the command line
1960 # program.
1961 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001962 b"unspecified",
1963 b"keyCompromise",
1964 b"CACompromise",
1965 b"affiliationChanged",
1966 b"superseded",
1967 b"cessationOfOperation",
1968 b"certificateHold",
1969 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001970 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001971
1972 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001973 revoked = _lib.X509_REVOKED_new()
1974 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001975
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001976 def set_serial(self, hex_str):
1977 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001978 Set the serial number.
1979
1980 The serial number is formatted as a hexadecimal number encoded in
1981 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001982
Dan Sully44e767a2016-06-04 18:05:27 -07001983 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001984
Dan Sully44e767a2016-06-04 18:05:27 -07001985 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001986 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001987 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1988 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001989 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001990 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001991 if not bn_result:
1992 raise ValueError("bad hex string")
1993
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001994 asn1_serial = _ffi.gc(
1995 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1996 _lib.ASN1_INTEGER_free)
1997 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001998
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001999 def get_serial(self):
2000 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002001 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002002
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002003 The serial number is formatted as a hexadecimal number encoded in
2004 ASCII.
2005
2006 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07002007 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002008 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08002009 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002010
Alex Gaynor67903a62016-06-02 10:37:13 -07002011 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
2012 _openssl_assert(asn1_int != _ffi.NULL)
2013 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
2014 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002015 return _bio_to_string(bio)
2016
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002017 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07002018 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
2019 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002020 obj = _lib.X509_EXTENSION_get_object(ext)
2021 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002022 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07002023 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002024 break
2025
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002026 def set_reason(self, reason):
2027 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002028 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002029
Dan Sully44e767a2016-06-04 18:05:27 -07002030 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002031
2032 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07002033 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002034
Dan Sully44e767a2016-06-04 18:05:27 -07002035 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002036
2037 .. seealso::
2038
Dan Sully44e767a2016-06-04 18:05:27 -07002039 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002040 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002041 """
2042 if reason is None:
2043 self._delete_reason()
2044 elif not isinstance(reason, bytes):
2045 raise TypeError("reason must be None or a byte string")
2046 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002047 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002048 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
2049
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002050 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002051 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002052 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002053
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002054 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002055 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002056
2057 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002058 add_result = _lib.X509_REVOKED_add1_ext_i2d(
2059 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002060 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002061
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002062 def get_reason(self):
2063 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04002064 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002065
Dan Sully44e767a2016-06-04 18:05:27 -07002066 :return: The reason, or ``None`` if there is none.
2067 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002068
2069 .. seealso::
2070
Dan Sully44e767a2016-06-04 18:05:27 -07002071 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002072 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002073 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002074 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
2075 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002076 obj = _lib.X509_EXTENSION_get_object(ext)
2077 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08002078 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002079
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002080 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002081 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002082 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002083 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04002084 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002085 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002086
2087 return _bio_to_string(bio)
2088
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002089 def all_reasons(self):
2090 """
2091 Return a list of all the supported reason strings.
2092
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002093 This list is a copy; modifying it does not change the supported reason
2094 strings.
2095
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002096 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07002097 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002098 """
2099 return self._crl_reasons[:]
2100
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002101 def set_rev_date(self, when):
2102 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002103 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002104
Dan Sully44e767a2016-06-04 18:05:27 -07002105 :param bytes when: The timestamp of the revocation,
Paul Kehrerce98ee62017-06-21 06:59:58 -10002106 as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002107 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002108 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002109 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2110 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002111
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002112 def get_rev_date(self):
2113 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002114 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002115
Paul Kehrerce98ee62017-06-21 06:59:58 -10002116 :return: The timestamp of the revocation, as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002117 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002118 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002119 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2120 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002121
2122
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002123class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002124 """
2125 A certificate revocation list.
2126 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002127
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002128 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002129 crl = _lib.X509_CRL_new()
2130 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002131
Paul Kehrer41c10242017-06-29 18:24:17 -05002132 def to_cryptography(self):
2133 """
2134 Export as a ``cryptography`` CRL.
2135
2136 :rtype: ``cryptography.x509.CertificateRevocationList``
2137
2138 .. versionadded:: 17.1.0
2139 """
2140 from cryptography.hazmat.backends.openssl.x509 import (
2141 _CertificateRevocationList
2142 )
2143 backend = _get_backend()
2144 return _CertificateRevocationList(backend, self._crl)
2145
2146 @classmethod
2147 def from_cryptography(cls, crypto_crl):
2148 """
2149 Construct based on a ``cryptography`` *crypto_crl*.
2150
2151 :param crypto_crl: A ``cryptography`` certificate revocation list
2152 :type crypto_crl: ``cryptography.x509.CertificateRevocationList``
2153
2154 :rtype: CRL
2155
2156 .. versionadded:: 17.1.0
2157 """
2158 if not isinstance(crypto_crl, x509.CertificateRevocationList):
2159 raise TypeError("Must be a certificate revocation list")
2160
2161 crl = cls()
2162 crl._crl = crypto_crl._x509_crl
2163 return crl
2164
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002165 def get_revoked(self):
2166 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002167 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002168
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002169 These revocations will be provided by value, not by reference.
2170 That means it's okay to mutate them: it won't affect this CRL.
2171
2172 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002173 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002174 """
2175 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07002176 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002177 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
2178 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04002179 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002180 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002181 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002182 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002183 if results:
2184 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002185
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002186 def add_revoked(self, revoked):
2187 """
2188 Add a revoked (by value not reference) to the CRL structure
2189
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002190 This revocation will be added by value, not by reference. That
2191 means it's okay to mutate it after adding: it won't affect
2192 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002193
Dan Sully44e767a2016-06-04 18:05:27 -07002194 :param Revoked revoked: The new revocation.
2195 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002196 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04002197 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002198 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002199
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002200 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002201 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002202
Dan Sully44e767a2016-06-04 18:05:27 -07002203 def get_issuer(self):
2204 """
2205 Get the CRL's issuer.
2206
2207 .. versionadded:: 16.1.0
2208
2209 :rtype: X509Name
2210 """
2211 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
2212 _openssl_assert(_issuer != _ffi.NULL)
2213 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
2214 issuer = X509Name.__new__(X509Name)
2215 issuer._name = _issuer
2216 return issuer
2217
2218 def set_version(self, version):
2219 """
2220 Set the CRL version.
2221
2222 .. versionadded:: 16.1.0
2223
2224 :param int version: The version of the CRL.
2225 :return: ``None``
2226 """
2227 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2228
2229 def _set_boundary_time(self, which, when):
2230 return _set_asn1_time(which(self._crl), when)
2231
2232 def set_lastUpdate(self, when):
2233 """
2234 Set when the CRL was last updated.
2235
Paul Kehrerce98ee62017-06-21 06:59:58 -10002236 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002237
2238 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002239
2240 .. versionadded:: 16.1.0
2241
2242 :param bytes when: A timestamp string.
2243 :return: ``None``
2244 """
2245 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2246
2247 def set_nextUpdate(self, when):
2248 """
2249 Set when the CRL will next be udpated.
2250
Paul Kehrerce98ee62017-06-21 06:59:58 -10002251 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002252
2253 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002254
2255 .. versionadded:: 16.1.0
2256
2257 :param bytes when: A timestamp string.
2258 :return: ``None``
2259 """
2260 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2261
2262 def sign(self, issuer_cert, issuer_key, digest):
2263 """
2264 Sign the CRL.
2265
2266 Signing a CRL enables clients to associate the CRL itself with an
2267 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2268 be signed by an issuer.
2269
2270 This method implicitly sets the issuer's name based on the issuer
2271 certificate and private key used to sign the CRL.
2272
2273 .. versionadded:: 16.1.0
2274
2275 :param X509 issuer_cert: The issuer's certificate.
2276 :param PKey issuer_key: The issuer's private key.
2277 :param bytes digest: The digest method to sign the CRL with.
2278 """
2279 digest_obj = _lib.EVP_get_digestbyname(digest)
2280 _openssl_assert(digest_obj != _ffi.NULL)
2281 _lib.X509_CRL_set_issuer_name(
2282 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2283 _lib.X509_CRL_sort(self._crl)
2284 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2285 _openssl_assert(result != 0)
2286
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002287 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002288 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002289 """
Dan Sully44e767a2016-06-04 18:05:27 -07002290 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002291
Dan Sully44e767a2016-06-04 18:05:27 -07002292 :param X509 cert: The certificate used to sign the CRL.
2293 :param PKey key: The key used to sign the CRL.
2294 :param int type: The export format, either :data:`FILETYPE_PEM`,
2295 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002296 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002297 :param bytes digest: The name of the message digest to use (eg
Wayne Werner80dcf382019-01-30 15:03:16 -06002298 ``b"sha256"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002299 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002300 """
Dan Sully44e767a2016-06-04 18:05:27 -07002301
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002302 if not isinstance(cert, X509):
2303 raise TypeError("cert must be an X509 instance")
2304 if not isinstance(key, PKey):
2305 raise TypeError("key must be a PKey instance")
2306 if not isinstance(type, int):
2307 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002308
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002309 if digest is _UNSPECIFIED:
Alex Gaynor173e4ba2017-06-30 08:01:12 -07002310 raise TypeError("digest must be provided")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002311
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002312 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002313 if digest_obj == _ffi.NULL:
2314 raise ValueError("No such digest method")
2315
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002316 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002317 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002318
Alex Gaynora738ed52015-09-05 11:17:10 -04002319 # A scratch time object to give different values to different CRL
2320 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002321 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002322 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002323
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002324 _lib.X509_gmtime_adj(sometime, 0)
2325 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002326
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002327 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2328 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002329
Alex Gaynor5945ea82015-09-05 14:59:06 -04002330 _lib.X509_CRL_set_issuer_name(
2331 self._crl, _lib.X509_get_subject_name(cert._x509)
2332 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002333
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002334 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002335 if not sign_result:
2336 _raise_current_error()
2337
Dominic Chenf05b2122015-10-13 16:32:35 +00002338 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002339
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002340
Alex Gaynor10d30832017-06-29 15:31:39 -07002341CRLType = deprecated(
2342 CRL, __name__,
2343 "CRLType has been deprecated, use CRL instead",
2344 DeprecationWarning
2345)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002346
2347
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002348class PKCS7(object):
2349 def type_is_signed(self):
2350 """
2351 Check if this NID_pkcs7_signed object
2352
2353 :return: True if the PKCS7 is of type signed
2354 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002355 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002356
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002357 def type_is_enveloped(self):
2358 """
2359 Check if this NID_pkcs7_enveloped object
2360
2361 :returns: True if the PKCS7 is of type enveloped
2362 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002363 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002364
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002365 def type_is_signedAndEnveloped(self):
2366 """
2367 Check if this NID_pkcs7_signedAndEnveloped object
2368
2369 :returns: True if the PKCS7 is of type signedAndEnveloped
2370 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002371 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002372
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002373 def type_is_data(self):
2374 """
2375 Check if this NID_pkcs7_data object
2376
2377 :return: True if the PKCS7 is of type data
2378 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002379 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002380
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002381 def get_type_name(self):
2382 """
2383 Returns the type name of the PKCS7 structure
2384
2385 :return: A string with the typename
2386 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002387 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2388 string_type = _lib.OBJ_nid2sn(nid)
2389 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002390
Alex Chanc6077062016-11-18 13:53:39 +00002391
Alex Gaynor10d30832017-06-29 15:31:39 -07002392PKCS7Type = deprecated(
2393 PKCS7, __name__,
2394 "PKCS7Type has been deprecated, use PKCS7 instead",
2395 DeprecationWarning
2396)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002397
2398
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002399class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002400 """
2401 A PKCS #12 archive.
2402 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002403
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002404 def __init__(self):
2405 self._pkey = None
2406 self._cert = None
2407 self._cacerts = None
2408 self._friendlyname = None
2409
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002410 def get_certificate(self):
2411 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002412 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002413
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002414 :return: The certificate, or :py:const:`None` if there is none.
2415 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002416 """
2417 return self._cert
2418
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002419 def set_certificate(self, cert):
2420 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002421 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002422
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002423 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002424 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002425
Dan Sully44e767a2016-06-04 18:05:27 -07002426 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002427 """
2428 if not isinstance(cert, X509):
2429 raise TypeError("cert must be an X509 instance")
2430 self._cert = cert
2431
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002432 def get_privatekey(self):
2433 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002434 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002435
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002436 :return: The private key, or :py:const:`None` if there is none.
2437 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002438 """
2439 return self._pkey
2440
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002441 def set_privatekey(self, pkey):
2442 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002443 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002444
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002445 :param pkey: The new private key, or :py:const:`None` to unset it.
2446 :type pkey: :py:class:`PKey` or :py:const:`None`
2447
Dan Sully44e767a2016-06-04 18:05:27 -07002448 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002449 """
2450 if not isinstance(pkey, PKey):
2451 raise TypeError("pkey must be a PKey instance")
2452 self._pkey = pkey
2453
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002454 def get_ca_certificates(self):
2455 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002456 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002457
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002458 :return: A tuple with the CA certificates in the chain, or
2459 :py:const:`None` if there are none.
2460 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002461 """
2462 if self._cacerts is not None:
2463 return tuple(self._cacerts)
2464
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002465 def set_ca_certificates(self, cacerts):
2466 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002467 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002468
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002469 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2470 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002471 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002472
Dan Sully44e767a2016-06-04 18:05:27 -07002473 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002474 """
2475 if cacerts is None:
2476 self._cacerts = None
2477 else:
2478 cacerts = list(cacerts)
2479 for cert in cacerts:
2480 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002481 raise TypeError(
2482 "iterable must only contain X509 instances"
2483 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002484 self._cacerts = cacerts
2485
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002486 def set_friendlyname(self, name):
2487 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002488 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002489
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002490 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002491 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002492
Dan Sully44e767a2016-06-04 18:05:27 -07002493 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002494 """
2495 if name is None:
2496 self._friendlyname = None
2497 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002498 raise TypeError(
2499 "name must be a byte string or None (not %r)" % (name,)
2500 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002501 self._friendlyname = name
2502
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002503 def get_friendlyname(self):
2504 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002505 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002506
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002507 :returns: The friendly name, or :py:const:`None` if there is none.
2508 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002509 """
2510 return self._friendlyname
2511
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002512 def export(self, passphrase=None, iter=2048, maciter=1):
2513 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002514 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002515
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002516 For more information, see the :c:func:`PKCS12_create` man page.
2517
2518 :param passphrase: The passphrase used to encrypt the structure. Unlike
2519 some other passphrase arguments, this *must* be a string, not a
2520 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002521 :type passphrase: :py:data:`bytes`
2522
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002523 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002524 :type iter: :py:data:`int`
2525
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002526 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002527 :type maciter: :py:data:`int`
2528
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002529 :return: The string representation of the PKCS #12 structure.
2530 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002531 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002532 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002533
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002534 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002535 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002536 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002537 cacerts = _lib.sk_X509_new_null()
2538 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002539 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002540 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002541
2542 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002543 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002544
2545 friendlyname = self._friendlyname
2546 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002547 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002548
2549 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002550 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002551 else:
2552 pkey = self._pkey._pkey
2553
2554 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002555 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002556 else:
2557 cert = self._cert._x509
2558
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002559 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002560 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002561 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2562 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002563 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002564 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002565 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002566 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002567
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002568 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002569 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002570 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002571
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002572
Alex Gaynor10d30832017-06-29 15:31:39 -07002573PKCS12Type = deprecated(
2574 PKCS12, __name__,
2575 "PKCS12Type has been deprecated, use PKCS12 instead",
2576 DeprecationWarning
2577)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002578
2579
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002580class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002581 """
2582 A Netscape SPKI object.
2583 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002584
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002585 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002586 spki = _lib.NETSCAPE_SPKI_new()
2587 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002588
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002589 def sign(self, pkey, digest):
2590 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002591 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002592
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002593 :param pkey: The private key to sign with.
2594 :type pkey: :py:class:`PKey`
2595
2596 :param digest: The message digest to use.
2597 :type digest: :py:class:`bytes`
2598
Dan Sully44e767a2016-06-04 18:05:27 -07002599 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002600 """
2601 if pkey._only_public:
2602 raise ValueError("Key has only public part")
2603
2604 if not pkey._initialized:
2605 raise ValueError("Key is uninitialized")
2606
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002607 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002608 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002609 raise ValueError("No such digest method")
2610
Alex Gaynor5945ea82015-09-05 14:59:06 -04002611 sign_result = _lib.NETSCAPE_SPKI_sign(
2612 self._spki, pkey._pkey, digest_obj
2613 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002614 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002615
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002616 def verify(self, key):
2617 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002618 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002619
Hynek Schlawack01c31672016-12-11 15:14:09 +01002620 :param PKey key: The public key that signature is supposedly from.
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002621
Hynek Schlawack01c31672016-12-11 15:14:09 +01002622 :return: ``True`` if the signature is correct.
2623 :rtype: bool
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002624
Hynek Schlawack01c31672016-12-11 15:14:09 +01002625 :raises OpenSSL.crypto.Error: If the signature is invalid, or there was
2626 a problem verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002627 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002628 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002629 if answer <= 0:
2630 _raise_current_error()
2631 return True
2632
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002633 def b64_encode(self):
2634 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002635 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002636
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002637 :return: The base64 encoded string.
2638 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002639 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002640 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2641 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002642 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002643 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002644
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002645 def get_pubkey(self):
2646 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002647 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002648
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002649 :return: The public key.
2650 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002651 """
2652 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002653 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002654 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002655 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002656 pkey._only_public = True
2657 return pkey
2658
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002659 def set_pubkey(self, pkey):
2660 """
2661 Set the public key of the certificate
2662
2663 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002664 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002665 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002666 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002667 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002668
2669
Alex Gaynor10d30832017-06-29 15:31:39 -07002670NetscapeSPKIType = deprecated(
2671 NetscapeSPKI, __name__,
2672 "NetscapeSPKIType has been deprecated, use NetscapeSPKI instead",
2673 DeprecationWarning
2674)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002675
2676
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002677class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002678 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002679 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002680 raise ValueError(
2681 "only FILETYPE_PEM key format supports encryption"
2682 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002683 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002684 self._more_args = more_args
2685 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002686 self._problems = []
2687
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002688 @property
2689 def callback(self):
2690 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002691 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002692 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002693 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002694 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002695 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002696 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002697 raise TypeError(
2698 "Last argument must be a byte string or a callable."
2699 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002700
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002701 @property
2702 def callback_args(self):
2703 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002704 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002705 elif isinstance(self._passphrase, bytes):
2706 return self._passphrase
2707 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002708 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002709 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002710 raise TypeError(
2711 "Last argument must be a byte string or a callable."
2712 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002713
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002714 def raise_if_problem(self, exceptionType=Error):
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002715 if self._problems:
Greg Bowser36eb2de2017-01-24 11:38:55 -05002716
2717 # Flush the OpenSSL error queue
2718 try:
2719 _exception_from_error_queue(exceptionType)
2720 except exceptionType:
2721 pass
2722
2723 raise self._problems.pop(0)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002724
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002725 def _read_passphrase(self, buf, size, rwflag, userdata):
2726 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002727 if self._more_args:
2728 result = self._passphrase(size, rwflag, userdata)
2729 else:
2730 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002731 if not isinstance(result, bytes):
2732 raise ValueError("String expected")
2733 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002734 if self._truncate:
2735 result = result[:size]
2736 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002737 raise ValueError(
2738 "passphrase returned by callback is too long"
2739 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002740 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002741 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002742 return len(result)
2743 except Exception as e:
2744 self._problems.append(e)
2745 return 0
2746
2747
Cory Benfield6492f7c2015-10-27 16:57:58 +09002748def load_publickey(type, buffer):
2749 """
Cory Benfield11c10192015-10-27 17:23:03 +09002750 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002751
Cory Benfield9c590b92015-10-28 14:55:05 +09002752 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002753 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002754 :param buffer: The buffer the key is stored in.
2755 :type buffer: A Python string object, either unicode or bytestring.
2756 :return: The PKey object.
2757 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002758 """
2759 if isinstance(buffer, _text_type):
2760 buffer = buffer.encode("ascii")
2761
2762 bio = _new_mem_buf(buffer)
2763
2764 if type == FILETYPE_PEM:
2765 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2766 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2767 elif type == FILETYPE_ASN1:
2768 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2769 else:
2770 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2771
2772 if evp_pkey == _ffi.NULL:
2773 _raise_current_error()
2774
2775 pkey = PKey.__new__(PKey)
2776 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002777 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002778 return pkey
2779
2780
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002781def load_privatekey(type, buffer, passphrase=None):
2782 """
Alex Chand072cae2018-02-15 09:57:59 +00002783 Load a private key (PKey) from the string *buffer* encoded with the type
2784 *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002785
2786 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2787 :param buffer: The buffer the key is stored in
2788 :param passphrase: (optional) if encrypted PEM format, this can be
2789 either the passphrase to use, or a callback for
2790 providing the passphrase.
2791
2792 :return: The PKey object
2793 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002794 if isinstance(buffer, _text_type):
2795 buffer = buffer.encode("ascii")
2796
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002797 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002798
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002799 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002800 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002801 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2802 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002803 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002804 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002805 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002806 else:
2807 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2808
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002809 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002810 _raise_current_error()
2811
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002812 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002813 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002814 return pkey
2815
2816
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002817def dump_certificate_request(type, req):
2818 """
Alex Chand072cae2018-02-15 09:57:59 +00002819 Dump the certificate request *req* into a buffer string encoded with the
2820 type *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002821
2822 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2823 :param req: The certificate request to dump
2824 :return: The buffer with the dumped certificate request in
2825 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002826 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002827
2828 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002829 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002830 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002831 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002832 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002833 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002834 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002835 raise ValueError(
2836 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2837 "FILETYPE_TEXT"
2838 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002839
Alex Gaynor09a386e2016-07-03 09:32:44 -04002840 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002841
2842 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002843
2844
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002845def load_certificate_request(type, buffer):
2846 """
Alex Chand072cae2018-02-15 09:57:59 +00002847 Load a certificate request (X509Req) from the string *buffer* encoded with
2848 the type *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002849
2850 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2851 :param buffer: The buffer the certificate request is stored in
2852 :return: The X509Req object
2853 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002854 if isinstance(buffer, _text_type):
2855 buffer = buffer.encode("ascii")
2856
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002857 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002858
2859 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002860 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002861 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002862 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002863 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002864 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002865
Alex Gaynoradd5b072016-06-04 21:04:00 -07002866 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002867
2868 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002869 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002870 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002871
2872
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002873def sign(pkey, data, digest):
2874 """
Alex Chand072cae2018-02-15 09:57:59 +00002875 Sign a data string using the given key and message digest.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002876
Alex Chand072cae2018-02-15 09:57:59 +00002877 :param pkey: PKey to sign with
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002878 :param data: data to be signed
2879 :param digest: message digest to use
2880 :return: signature
Alex Chand072cae2018-02-15 09:57:59 +00002881
2882 .. versionadded:: 0.11
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002883 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002884 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002885
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002886 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002887 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002888 raise ValueError("No such digest method")
2889
Alex Gaynor67903a62016-06-02 10:37:13 -07002890 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002891 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002892
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002893 _lib.EVP_SignInit(md_ctx, digest_obj)
2894 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002895
Paul Kehrer59d26252017-07-20 10:45:54 +02002896 length = _lib.EVP_PKEY_size(pkey._pkey)
2897 _openssl_assert(length > 0)
2898 signature_buffer = _ffi.new("unsigned char[]", length)
2899 signature_length = _ffi.new("unsigned int *")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002900 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002901 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002902 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002903
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002904 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002905
2906
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002907def verify(cert, signature, data, digest):
2908 """
Alex Chand072cae2018-02-15 09:57:59 +00002909 Verify the signature for a data string.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002910
Alex Chand072cae2018-02-15 09:57:59 +00002911 :param cert: signing certificate (X509 object) corresponding to the
2912 private key which generated the signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002913 :param signature: signature returned by sign function
2914 :param data: data to be verified
2915 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002916 :return: ``None`` if the signature is correct, raise exception otherwise.
Alex Chand072cae2018-02-15 09:57:59 +00002917
2918 .. versionadded:: 0.11
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002919 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002920 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002921
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002922 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002923 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002924 raise ValueError("No such digest method")
2925
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002926 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002927 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002928 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002929
Alex Gaynor67903a62016-06-02 10:37:13 -07002930 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002931 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002932
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002933 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2934 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002935 verify_result = _lib.EVP_VerifyFinal(
2936 md_ctx, signature, len(signature), pkey
2937 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002938
2939 if verify_result != 1:
2940 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002941
2942
Dominic Chenf05b2122015-10-13 16:32:35 +00002943def dump_crl(type, crl):
2944 """
2945 Dump a certificate revocation list to a buffer.
2946
2947 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2948 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002949 :param CRL crl: The CRL to dump.
2950
Dominic Chenf05b2122015-10-13 16:32:35 +00002951 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002952 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002953 """
2954 bio = _new_mem_buf()
2955
2956 if type == FILETYPE_PEM:
2957 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2958 elif type == FILETYPE_ASN1:
2959 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2960 elif type == FILETYPE_TEXT:
2961 ret = _lib.X509_CRL_print(bio, crl._crl)
2962 else:
2963 raise ValueError(
2964 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2965 "FILETYPE_TEXT")
2966
2967 assert ret == 1
2968 return _bio_to_string(bio)
2969
2970
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002971def load_crl(type, buffer):
2972 """
Alex Chand072cae2018-02-15 09:57:59 +00002973 Load Certificate Revocation List (CRL) data from a string *buffer*.
2974 *buffer* encoded with the type *type*.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002975
2976 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2977 :param buffer: The buffer the CRL is stored in
2978
2979 :return: The PKey object
2980 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002981 if isinstance(buffer, _text_type):
2982 buffer = buffer.encode("ascii")
2983
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002984 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002985
2986 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002987 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002988 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002989 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002990 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002991 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2992
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002993 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002994 _raise_current_error()
2995
2996 result = CRL.__new__(CRL)
Jeremy Cline9e15eca2017-09-07 20:11:08 -04002997 result._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002998 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002999
3000
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003001def load_pkcs7_data(type, buffer):
3002 """
Alex Chand072cae2018-02-15 09:57:59 +00003003 Load pkcs7 data from the string *buffer* encoded with the type
3004 *type*.
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003005
3006 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
3007 :param buffer: The buffer with the pkcs7 data.
3008 :return: The PKCS7 object
3009 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05003010 if isinstance(buffer, _text_type):
3011 buffer = buffer.encode("ascii")
3012
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08003013 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003014
3015 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003016 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003017 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07003018 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003019 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003020 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
3021
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003022 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08003023 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003024
3025 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003026 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003027 return pypkcs7
3028
3029
Stephen Holsapple38482622014-04-05 20:29:34 -07003030def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003031 """
Alex Chand072cae2018-02-15 09:57:59 +00003032 Load pkcs12 data from the string *buffer*. If the pkcs12 structure is
3033 encrypted, a *passphrase* must be included. The MAC is always
3034 checked and thus required.
3035
3036 See also the man page for the C function :py:func:`PKCS12_parse`.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003037
3038 :param buffer: The buffer the certificate is stored in
3039 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
3040 :returns: The PKCS12 object
3041 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04003042 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00003043
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05003044 if isinstance(buffer, _text_type):
3045 buffer = buffer.encode("ascii")
3046
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08003047 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003048
Stephen Holsapple38482622014-04-05 20:29:34 -07003049 # Use null passphrase if passphrase is None or empty string. With PKCS#12
3050 # password based encryption no password and a zero length password are two
3051 # different things, but OpenSSL implementation will try both to figure out
3052 # which one works.
3053 if not passphrase:
3054 passphrase = _ffi.NULL
3055
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003056 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
3057 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003058 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003059 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003060
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003061 pkey = _ffi.new("EVP_PKEY**")
3062 cert = _ffi.new("X509**")
3063 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003064
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003065 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003066 if not parse_result:
3067 _raise_current_error()
3068
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003069 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08003070
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003071 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
3072 # queue for no particular reason. This error isn't interesting to anyone
3073 # outside this function. It's not even interesting to us. Get rid of it.
3074 try:
3075 _raise_current_error()
3076 except Error:
3077 pass
3078
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003079 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003080 pykey = None
3081 else:
3082 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003083 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003084
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003085 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003086 pycert = None
3087 friendlyname = None
3088 else:
Paul Kehrere7381862017-11-30 20:55:25 +08003089 pycert = X509._from_raw_x509_ptr(cert[0])
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003090
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003091 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04003092 friendlyname_buffer = _lib.X509_alias_get0(
3093 cert[0], friendlyname_length
3094 )
3095 friendlyname = _ffi.buffer(
3096 friendlyname_buffer, friendlyname_length[0]
3097 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003098 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003099 friendlyname = None
3100
3101 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003102 for i in range(_lib.sk_X509_num(cacerts)):
Paul Kehrere7381862017-11-30 20:55:25 +08003103 x509 = _lib.sk_X509_value(cacerts, i)
3104 pycacert = X509._from_raw_x509_ptr(x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003105 pycacerts.append(pycacert)
3106 if not pycacerts:
3107 pycacerts = None
3108
3109 pkcs12 = PKCS12.__new__(PKCS12)
3110 pkcs12._pkey = pykey
3111 pkcs12._cert = pycert
3112 pkcs12._cacerts = pycacerts
3113 pkcs12._friendlyname = friendlyname
3114 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05003115
3116
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05003117# There are no direct unit tests for this initialization. It is tested
3118# indirectly since it is necessary for functions like dump_privatekey when
3119# using encryption.
3120#
3121# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
3122# and some other similar tests may fail without this (though they may not if
3123# the Python runtime has already done some initialization of the underlying
3124# OpenSSL library (and is linked against the same one that cryptography is
3125# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05003126_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05003127
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05003128# This is similar but exercised mainly by exception_from_error_queue. It calls
3129# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
3130_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003131
3132
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003133# Set the default string mask to match OpenSSL upstream (since 2005) and
3134# RFC5280 recommendations.
3135_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')