blob: 426552569882211792be73fe81edeb1ae1a2ba7c [file] [log] [blame]
jalberdi004669dcc32020-10-18 17:55:40 +02001import calendar
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05002import datetime
Paul Kehrer8d887e12015-10-24 09:09:55 -05003
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05004from base64 import b16encode
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05005from functools import partial
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05006from operator import __eq__, __ne__, __lt__, __le__, __gt__, __ge__
7
8from six import (
9 integer_types as _integer_types,
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -040010 text_type as _text_type,
Alex Gaynor03737182020-07-23 20:40:46 -040011 PY2 as _PY2,
12)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080013
Alex Gaynorbb971ae2020-08-05 01:14:16 -040014from cryptography import utils, x509
Paul Kehrer72d968b2016-07-29 15:31:04 +080015from cryptography.hazmat.primitives.asymmetric import dsa, rsa
16
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050017from OpenSSL._util import (
18 ffi as _ffi,
19 lib as _lib,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050020 exception_from_error_queue as _exception_from_error_queue,
21 byte_string as _byte_string,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040022 native as _native,
Sándor Oroszi43c97762020-09-11 17:17:31 +020023 path_string as _path_string,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040024 UNSPECIFIED as _UNSPECIFIED,
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -040025 text_to_bytes_and_warn as _text_to_bytes_and_warn,
Alex Gaynor67903a62016-06-02 10:37:13 -070026 make_assert as _make_assert,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040027)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080028
Nicolas Karolak736c6212017-11-26 14:40:28 +010029__all__ = [
Alex Gaynor03737182020-07-23 20:40:46 -040030 "FILETYPE_PEM",
31 "FILETYPE_ASN1",
32 "FILETYPE_TEXT",
33 "TYPE_RSA",
34 "TYPE_DSA",
35 "Error",
36 "PKey",
37 "get_elliptic_curves",
38 "get_elliptic_curve",
39 "X509Name",
40 "X509Extension",
41 "X509Req",
42 "X509",
43 "X509StoreFlags",
44 "X509Store",
45 "X509StoreContextError",
46 "X509StoreContext",
47 "load_certificate",
48 "dump_certificate",
49 "dump_publickey",
50 "dump_privatekey",
51 "Revoked",
52 "CRL",
53 "PKCS7",
54 "PKCS12",
55 "NetscapeSPKI",
56 "load_publickey",
57 "load_privatekey",
58 "dump_certificate_request",
59 "load_certificate_request",
60 "sign",
61 "verify",
62 "dump_crl",
63 "load_crl",
64 "load_pkcs7_data",
65 "load_pkcs12",
Nicolas Karolak736c6212017-11-26 14:40:28 +010066]
67
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050068FILETYPE_PEM = _lib.SSL_FILETYPE_PEM
69FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080070
71# TODO This was an API mistake. OpenSSL has no such constant.
72FILETYPE_TEXT = 2 ** 16 - 1
73
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050074TYPE_RSA = _lib.EVP_PKEY_RSA
75TYPE_DSA = _lib.EVP_PKEY_DSA
Igr2f874f22019-01-21 21:39:37 +030076TYPE_DH = _lib.EVP_PKEY_DH
77TYPE_EC = _lib.EVP_PKEY_EC
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -080078
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080079
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050080class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050081 """
82 An error occurred in an `OpenSSL.crypto` API.
83 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050084
85
86_raise_current_error = partial(_exception_from_error_queue, Error)
Alex Gaynor67903a62016-06-02 10:37:13 -070087_openssl_assert = _make_assert(Error)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050088
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070089
Paul Kehrereb633842016-10-06 11:22:01 +020090def _get_backend():
91 """
92 Importing the backend from cryptography has the side effect of activating
93 the osrandom engine. This mutates the global state of OpenSSL in the
94 process and causes issues for various programs that use subinterpreters or
95 embed Python. By putting the import in this function we can avoid
96 triggering this side effect unless _get_backend is called.
97 """
98 from cryptography.hazmat.backends.openssl.backend import backend
Alex Gaynor03737182020-07-23 20:40:46 -040099
Paul Kehrereb633842016-10-06 11:22:01 +0200100 return backend
101
102
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500103def _untested_error(where):
104 """
105 An OpenSSL API failed somehow. Additionally, the failure which was
106 encountered isn't one that's exercised by the test suite so future behavior
107 of pyOpenSSL is now somewhat less predictable.
108 """
109 raise RuntimeError("Unknown %s failure" % (where,))
110
111
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500112def _new_mem_buf(buffer=None):
113 """
114 Allocate a new OpenSSL memory BIO.
115
116 Arrange for the garbage collector to clean it up automatically.
117
118 :param buffer: None or some bytes to use to put into the BIO so that they
119 can be read out.
120 """
121 if buffer is None:
122 bio = _lib.BIO_new(_lib.BIO_s_mem())
123 free = _lib.BIO_free
124 else:
125 data = _ffi.new("char[]", buffer)
126 bio = _lib.BIO_new_mem_buf(data, len(buffer))
Alex Gaynor5945ea82015-09-05 14:59:06 -0400127
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500128 # Keep the memory alive as long as the bio is alive!
129 def free(bio, ref=data):
130 return _lib.BIO_free(bio)
131
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700132 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500133
134 bio = _ffi.gc(bio, free)
135 return bio
136
137
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800138def _bio_to_string(bio):
139 """
140 Copy the contents of an OpenSSL BIO object into a Python byte string.
141 """
Alex Gaynor03737182020-07-23 20:40:46 -0400142 result_buffer = _ffi.new("char**")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500143 buffer_length = _lib.BIO_get_mem_data(bio, result_buffer)
144 return _ffi.buffer(result_buffer[0], buffer_length)[:]
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800145
146
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800147def _set_asn1_time(boundary, when):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500148 """
149 The the time value of an ASN1 time object.
150
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900151 @param boundary: An ASN1_TIME pointer (or an object safely
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500152 castable to that type) which will have its value set.
153 @param when: A string representation of the desired time value.
154
155 @raise TypeError: If C{when} is not a L{bytes} string.
156 @raise ValueError: If C{when} does not represent a time in the required
157 format.
158 @raise RuntimeError: If the time value cannot be set for some other
159 (unspecified) reason.
160 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800161 if not isinstance(when, bytes):
162 raise TypeError("when must be a byte string")
163
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900164 set_result = _lib.ASN1_TIME_set_string(boundary, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800165 if set_result == 0:
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900166 raise ValueError("Invalid string")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800167
Alex Gaynor510293e2016-06-02 12:07:59 -0700168
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800169def _get_asn1_time(timestamp):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500170 """
171 Retrieve the time value of an ASN1 time object.
172
173 @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to
174 that type) from which the time value will be retrieved.
175
176 @return: The time value from C{timestamp} as a L{bytes} string in a certain
177 format. Or C{None} if the object contains no time value.
178 """
Alex Gaynor03737182020-07-23 20:40:46 -0400179 string_timestamp = _ffi.cast("ASN1_STRING*", timestamp)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500180 if _lib.ASN1_STRING_length(string_timestamp) == 0:
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800181 return None
Alex Gaynor5945ea82015-09-05 14:59:06 -0400182 elif (
183 _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME
184 ):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500185 return _ffi.string(_lib.ASN1_STRING_data(string_timestamp))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800186 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500187 generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**")
188 _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp)
189 if generalized_timestamp[0] == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500190 # This may happen:
191 # - if timestamp was not an ASN1_TIME
192 # - if allocating memory for the ASN1_GENERALIZEDTIME failed
193 # - if a copy of the time data from timestamp cannot be made for
194 # the newly allocated ASN1_GENERALIZEDTIME
195 #
196 # These are difficult to test. cffi enforces the ASN1_TIME type.
197 # Memory allocation failures are a pain to trigger
198 # deterministically.
199 _untested_error("ASN1_TIME_to_generalizedtime")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800200 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500201 string_timestamp = _ffi.cast(
Alex Gaynor03737182020-07-23 20:40:46 -0400202 "ASN1_STRING*", generalized_timestamp[0]
203 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500204 string_data = _lib.ASN1_STRING_data(string_timestamp)
205 string_result = _ffi.string(string_data)
206 _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0])
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800207 return string_result
208
209
Alex Gaynor4aa52c32017-11-20 09:04:08 -0500210class _X509NameInvalidator(object):
211 def __init__(self):
212 self._names = []
213
214 def add(self, name):
215 self._names.append(name)
216
217 def clear(self):
218 for name in self._names:
219 # Breaks the object, but also prevents UAF!
220 del name._name
221
222
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800223class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200224 """
225 A class representing an DSA or RSA public key or key pair.
226 """
Alex Gaynor03737182020-07-23 20:40:46 -0400227
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800228 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800229 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800230
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800231 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500232 pkey = _lib.EVP_PKEY_new()
233 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800234 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800235
Paul Kehrer72d968b2016-07-29 15:31:04 +0800236 def to_cryptography_key(self):
237 """
238 Export as a ``cryptography`` key.
239
240 :rtype: One of ``cryptography``'s `key interfaces`_.
241
242 .. _key interfaces: https://cryptography.io/en/latest/hazmat/\
243 primitives/asymmetric/rsa/#key-interfaces
244
245 .. versionadded:: 16.1.0
246 """
Paul Kehrereb633842016-10-06 11:22:01 +0200247 backend = _get_backend()
Paul Kehrer72d968b2016-07-29 15:31:04 +0800248 if self._only_public:
249 return backend._evp_pkey_to_public_key(self._pkey)
250 else:
251 return backend._evp_pkey_to_private_key(self._pkey)
252
253 @classmethod
254 def from_cryptography_key(cls, crypto_key):
255 """
256 Construct based on a ``cryptography`` *crypto_key*.
257
258 :param crypto_key: A ``cryptography`` key.
259 :type crypto_key: One of ``cryptography``'s `key interfaces`_.
260
261 :rtype: PKey
262
263 .. versionadded:: 16.1.0
264 """
265 pkey = cls()
Alex Gaynor03737182020-07-23 20:40:46 -0400266 if not isinstance(
267 crypto_key,
268 (
269 rsa.RSAPublicKey,
270 rsa.RSAPrivateKey,
271 dsa.DSAPublicKey,
272 dsa.DSAPrivateKey,
273 ),
274 ):
Paul Kehrer72d968b2016-07-29 15:31:04 +0800275 raise TypeError("Unsupported key type")
276
277 pkey._pkey = crypto_key._evp_pkey
278 if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)):
279 pkey._only_public = True
280 pkey._initialized = True
281 return pkey
282
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800283 def generate_key(self, type, bits):
284 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700285 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800286
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200287 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800288
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200289 :param type: The key type.
290 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
291 :param bits: The number of bits.
292 :type bits: :py:data:`int` ``>= 0``
293 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
294 of the appropriate type.
295 :raises ValueError: If the number of bits isn't an integer of
296 the appropriate size.
Dan Sully44e767a2016-06-04 18:05:27 -0700297 :return: ``None``
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800298 """
299 if not isinstance(type, int):
300 raise TypeError("type must be an integer")
301
302 if not isinstance(bits, int):
303 raise TypeError("bits must be an integer")
304
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800305 if type == TYPE_RSA:
306 if bits <= 0:
307 raise ValueError("Invalid number of bits")
308
David Benjamin179eb1d2018-06-05 17:56:07 -0400309 # TODO Check error return
310 exponent = _lib.BN_new()
311 exponent = _ffi.gc(exponent, _lib.BN_free)
312 _lib.BN_set_word(exponent, _lib.RSA_F4)
313
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500314 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800315
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500316 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400317 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800318
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500319 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400320 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800321
322 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400323 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700324 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400325
326 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400327 res = _lib.DSA_generate_parameters_ex(
328 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
329 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700330 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400331
332 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
333 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800334 else:
335 raise Error("No such key type")
336
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800337 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800338
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800339 def check(self):
340 """
341 Check the consistency of an RSA private key.
342
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200343 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
344
Hynek Schlawack01c31672016-12-11 15:14:09 +0100345 :return: ``True`` if key is consistent.
346
347 :raise OpenSSL.crypto.Error: if the key is inconsistent.
348
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800349 :raise TypeError: if the key is of a type which cannot be checked.
350 Only RSA keys can currently be checked.
351 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800352 if self._only_public:
353 raise TypeError("public key only")
354
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100355 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800356 raise TypeError("key type unsupported")
357
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500358 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
359 rsa = _ffi.gc(rsa, _lib.RSA_free)
360 result = _lib.RSA_check_key(rsa)
Mrmaxmeier8cd3b172020-03-11 22:03:59 +0100361 if result == 1:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800362 return True
363 _raise_current_error()
364
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800365 def type(self):
366 """
367 Returns the type of the key
368
369 :return: The type of the key.
370 """
Alex Gaynor0d2aec52017-05-31 04:26:27 -0400371 return _lib.EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800372
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800373 def bits(self):
374 """
375 Returns the number of bits of the key
376
377 :return: The number of bits of the key.
378 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500379 return _lib.EVP_PKEY_bits(self._pkey)
Alex Chanc6077062016-11-18 13:53:39 +0000380
381
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400382class _EllipticCurve(object):
383 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400384 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400385
386 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
387 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
388 instances each of which represents one curve supported by the system.
389 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400390 """
Alex Gaynor03737182020-07-23 20:40:46 -0400391
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400392 _curves = None
393
Alex Gaynor26f1a922019-11-18 00:37:39 -0500394 if not _PY2:
Felix Yan3db93f12020-10-15 03:41:20 +0800395 # This only necessary on Python 3. Moreover, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400396 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400397 """
398 Implement cooperation with the right-hand side argument of ``!=``.
399
400 Python 3 seems to have dropped this cooperation in this very narrow
401 circumstance.
402 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400403 if isinstance(other, _EllipticCurve):
404 return super(_EllipticCurve, self).__ne__(other)
405 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400406
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400407 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400408 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400409 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400410 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400411
412 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400413
414 :return: A :py:type:`set` of ``cls`` instances giving the names of the
415 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400416 """
Alex Chan84902a22017-04-20 11:50:47 +0100417 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
Alex Gaynor03737182020-07-23 20:40:46 -0400418 builtin_curves = _ffi.new("EC_builtin_curve[]", num_curves)
Alex Chan84902a22017-04-20 11:50:47 +0100419 # The return value on this call should be num_curves again. We
420 # could check it to make sure but if it *isn't* then.. what could
421 # we do? Abort the whole process, I suppose...? -exarkun
422 lib.EC_get_builtin_curves(builtin_curves, num_curves)
Alex Gaynor03737182020-07-23 20:40:46 -0400423 return set(cls.from_nid(lib, c.nid) for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400424
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400425 @classmethod
426 def _get_elliptic_curves(cls, lib):
427 """
428 Get, cache, and return the curves supported by OpenSSL.
429
430 :param lib: The OpenSSL library binding object.
431
432 :return: A :py:type:`set` of ``cls`` instances giving the names of the
433 elliptic curves the underlying library supports.
434 """
435 if cls._curves is None:
436 cls._curves = cls._load_elliptic_curves(lib)
437 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400438
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400439 @classmethod
440 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400441 """
442 Instantiate a new :py:class:`_EllipticCurve` associated with the given
443 OpenSSL NID.
444
445 :param lib: The OpenSSL library binding object.
446
447 :param nid: The OpenSSL NID the resulting curve object will represent.
448 This must be a curve NID (and not, for example, a hash NID) or
449 subsequent operations will fail in unpredictable ways.
450 :type nid: :py:class:`int`
451
452 :return: The curve object.
453 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400454 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
455
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400456 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400457 """
458 :param _lib: The :py:mod:`cryptography` binding instance used to
459 interface with OpenSSL.
460
461 :param _nid: The OpenSSL NID identifying the curve this object
462 represents.
463 :type _nid: :py:class:`int`
464
465 :param name: The OpenSSL short name identifying the curve this object
466 represents.
467 :type name: :py:class:`unicode`
468 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400469 self._lib = lib
470 self._nid = nid
471 self.name = name
472
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400473 def __repr__(self):
474 return "<Curve %r>" % (self.name,)
475
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400476 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400477 """
478 Create a new OpenSSL EC_KEY structure initialized to use this curve.
479
480 The structure is automatically garbage collected when the Python object
481 is garbage collected.
482 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400483 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
484 return _ffi.gc(key, _lib.EC_KEY_free)
485
486
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400487def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400488 """
489 Return a set of objects representing the elliptic curves supported in the
490 OpenSSL build in use.
491
492 The curve objects have a :py:class:`unicode` ``name`` attribute by which
493 they identify themselves.
494
495 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400496 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
497 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400498 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400499 return _EllipticCurve._get_elliptic_curves(_lib)
500
501
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400502def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400503 """
504 Return a single curve object selected by name.
505
506 See :py:func:`get_elliptic_curves` for information about curve objects.
507
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400508 :param name: The OpenSSL short name identifying the curve object to
509 retrieve.
510 :type name: :py:class:`unicode`
511
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400512 If the named curve is not supported then :py:class:`ValueError` is raised.
513 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400514 for curve in get_elliptic_curves():
515 if curve.name == name:
516 return curve
517 raise ValueError("unknown curve name", name)
518
519
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800520class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200521 """
522 An X.509 Distinguished Name.
523
524 :ivar countryName: The country of the entity.
525 :ivar C: Alias for :py:attr:`countryName`.
526
527 :ivar stateOrProvinceName: The state or province of the entity.
528 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
529
530 :ivar localityName: The locality of the entity.
531 :ivar L: Alias for :py:attr:`localityName`.
532
533 :ivar organizationName: The organization name of the entity.
534 :ivar O: Alias for :py:attr:`organizationName`.
535
536 :ivar organizationalUnitName: The organizational unit of the entity.
537 :ivar OU: Alias for :py:attr:`organizationalUnitName`
538
539 :ivar commonName: The common name of the entity.
540 :ivar CN: Alias for :py:attr:`commonName`.
541
542 :ivar emailAddress: The e-mail address of the entity.
543 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400544
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800545 def __init__(self, name):
546 """
547 Create a new X509Name, copying the given X509Name instance.
548
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200549 :param name: The name to copy.
550 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800551 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500552 name = _lib.X509_NAME_dup(name._name)
553 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800554
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800555 def __setattr__(self, name, value):
Alex Gaynor03737182020-07-23 20:40:46 -0400556 if name.startswith("_"):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800557 return super(X509Name, self).__setattr__(name, value)
558
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800559 # Note: we really do not want str subclasses here, so we do not use
560 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800561 if type(name) is not str:
Alex Gaynor03737182020-07-23 20:40:46 -0400562 raise TypeError(
563 "attribute name must be string, not '%.200s'"
564 % (type(value).__name__,)
565 )
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800566
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500567 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500568 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800569 try:
570 _raise_current_error()
571 except Error:
572 pass
573 raise AttributeError("No such attribute")
574
575 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500576 for i in range(_lib.X509_NAME_entry_count(self._name)):
577 ent = _lib.X509_NAME_get_entry(self._name, i)
578 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
579 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800580 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500581 ent = _lib.X509_NAME_delete_entry(self._name, i)
582 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800583 break
584
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500585 if isinstance(value, _text_type):
Alex Gaynor03737182020-07-23 20:40:46 -0400586 value = value.encode("utf-8")
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800587
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500588 add_result = _lib.X509_NAME_add_entry_by_NID(
Alex Gaynor03737182020-07-23 20:40:46 -0400589 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0
590 )
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800591 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500592 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800593
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800594 def __getattr__(self, name):
595 """
596 Find attribute. An X509Name object has the following attributes:
597 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400598 organization (alias O), organizationalUnit (alias OU), commonName
599 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800600 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500601 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500602 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800603 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
604 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
605 # push something onto the error queue. If we don't clean that up
606 # now, someone else will bump into it later and be quite confused.
607 # See lp#314814.
608 try:
609 _raise_current_error()
610 except Error:
611 pass
612 return super(X509Name, self).__getattr__(name)
613
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500614 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800615 if entry_index == -1:
616 return None
617
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500618 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
619 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800620
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500621 result_buffer = _ffi.new("unsigned char**")
622 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400623 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800624
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700625 try:
Alex Gaynor03737182020-07-23 20:40:46 -0400626 result = _ffi.buffer(result_buffer[0], data_length)[:].decode(
627 "utf-8"
628 )
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700629 finally:
630 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500631 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800632 return result
633
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500634 def _cmp(op):
635 def f(self, other):
636 if not isinstance(other, X509Name):
637 return NotImplemented
638 result = _lib.X509_NAME_cmp(self._name, other._name)
639 return op(result, 0)
Alex Gaynor03737182020-07-23 20:40:46 -0400640
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500641 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800642
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500643 __eq__ = _cmp(__eq__)
644 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800645
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500646 __lt__ = _cmp(__lt__)
647 __le__ = _cmp(__le__)
648
649 __gt__ = _cmp(__gt__)
650 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800651
652 def __repr__(self):
653 """
654 String representation of an X509Name
655 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400656 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500657 format_result = _lib.X509_NAME_oneline(
Alex Gaynor03737182020-07-23 20:40:46 -0400658 self._name, result_buffer, len(result_buffer)
659 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700660 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800661
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500662 return "<X509Name object '%s'>" % (
Alex Gaynor03737182020-07-23 20:40:46 -0400663 _native(_ffi.string(result_buffer)),
664 )
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800665
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800666 def hash(self):
667 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200668 Return an integer representation of the first four bytes of the
669 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800670
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200671 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
672
673 :return: The (integer) hash of this name.
674 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800675 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500676 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800677
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800678 def der(self):
679 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200680 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800681
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200682 :return: The DER encoded form of this name.
683 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800684 """
Alex Gaynor03737182020-07-23 20:40:46 -0400685 result_buffer = _ffi.new("unsigned char**")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500686 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400687 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800688
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500689 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
690 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800691 return string_result
692
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800693 def get_components(self):
694 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200695 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800696
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200697 :return: The components of this name.
698 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800699 """
700 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500701 for i in range(_lib.X509_NAME_entry_count(self._name)):
702 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800703
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500704 fname = _lib.X509_NAME_ENTRY_get_object(ent)
705 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800706
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500707 nid = _lib.OBJ_obj2nid(fname)
708 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800709
Romuald Brunet4183beb2019-01-21 19:38:33 +0100710 # ffi.string does not handle strings containing NULL bytes
711 # (which may have been generated by old, broken software)
Alex Gaynor03737182020-07-23 20:40:46 -0400712 value = _ffi.buffer(
713 _lib.ASN1_STRING_data(fval), _lib.ASN1_STRING_length(fval)
714 )[:]
Romuald Brunet4183beb2019-01-21 19:38:33 +0100715 result.append((_ffi.string(name), value))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800716
717 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200718
719
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800720class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200721 """
722 An X.509 v3 certificate extension.
723 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400724
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800725 def __init__(self, type_name, critical, value, subject=None, issuer=None):
726 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200727 Initializes an X509 extension.
728
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100729 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400730 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800731
Alex Gaynor5945ea82015-09-05 14:59:06 -0400732 :param bool critical: A flag indicating whether this is a critical
733 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800734
735 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200736 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800737
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200738 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800739 :type subject: :py:class:`X509`
740
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200741 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800742 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100743
Alex Chan54005ce2017-03-21 08:08:17 +0000744 .. _extension: https://www.openssl.org/docs/manmaster/man5/
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100745 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800746 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500747 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800748
Alex Gaynor5945ea82015-09-05 14:59:06 -0400749 # A context is necessary for any extension which uses the r2i
750 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
751 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500752 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800753
754 # We have no configuration database - but perhaps we should (some
755 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500756 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800757
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800758 # Initialize the subject and issuer, if appropriate. ctx is a local,
759 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400760 # any references, so no need to mess with reference counts or
761 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800762 if issuer is not None:
763 if not isinstance(issuer, X509):
764 raise TypeError("issuer must be an X509 instance")
765 ctx.issuer_cert = issuer._x509
766 if subject is not None:
767 if not isinstance(subject, X509):
768 raise TypeError("subject must be an X509 instance")
769 ctx.subject_cert = subject._x509
770
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800771 if critical:
772 # There are other OpenSSL APIs which would let us pass in critical
773 # separately, but they're harder to use, and since value is already
774 # a pile of crappy junk smuggling a ton of utterly important
775 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400776 # with strings? (However, X509V3_EXT_i2d in particular seems like
777 # it would be a better API to invoke. I do not know where to get
778 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500779 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800780
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500781 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
782 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800783 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500784 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800785
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400786 @property
787 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400788 return _lib.OBJ_obj2nid(
789 _lib.X509_EXTENSION_get_object(self._extension)
790 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400791
792 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500793 _lib.GEN_EMAIL: "email",
794 _lib.GEN_DNS: "DNS",
795 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400796 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400797
798 def _subjectAltNameString(self):
Alex Gaynord61c46a2017-06-29 22:51:33 -0700799 names = _ffi.cast(
800 "GENERAL_NAMES*", _lib.X509V3_EXT_d2i(self._extension)
801 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400802
Paul Kehrerb7d79502015-05-04 07:43:51 -0500803 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400804 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500805 for i in range(_lib.sk_GENERAL_NAME_num(names)):
806 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400807 try:
808 label = self._prefixes[name.type]
809 except KeyError:
810 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500811 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500812 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400813 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500814 value = _native(
Alex Gaynor03737182020-07-23 20:40:46 -0400815 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:]
816 )
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500817 parts.append(label + ":" + value)
818 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400819
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800820 def __str__(self):
821 """
822 :return: a nice text representation of the extension
823 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500824 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400825 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800826
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400827 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500828 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400829 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800830
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500831 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800832
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800833 def get_critical(self):
834 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200835 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800836
837 :return: The critical field.
838 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500839 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800840
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800841 def get_short_name(self):
842 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200843 Returns the short type name of this X.509 extension.
844
845 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800846
847 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200848 :rtype: :py:data:`bytes`
849
850 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800851 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500852 obj = _lib.X509_EXTENSION_get_object(self._extension)
853 nid = _lib.OBJ_obj2nid(obj)
854 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800855
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800856 def get_data(self):
857 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200858 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800859
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200860 :return: The ASN.1 encoded data of this X509 extension.
861 :rtype: :py:data:`bytes`
862
863 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800864 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500865 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
Alex Gaynor03737182020-07-23 20:40:46 -0400866 string_result = _ffi.cast("ASN1_STRING*", octet_result)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500867 char_result = _lib.ASN1_STRING_data(string_result)
868 result_length = _lib.ASN1_STRING_length(string_result)
869 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800870
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200871
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800872class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200873 """
874 An X.509 certificate signing requests.
875 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400876
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800877 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500878 req = _lib.X509_REQ_new()
879 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Alex Gaynor5af32d02016-09-24 01:52:21 -0400880 # Default to version 0.
881 self.set_version(0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800882
Paul Kehrer41c10242017-06-29 18:24:17 -0500883 def to_cryptography(self):
884 """
885 Export as a ``cryptography`` certificate signing request.
886
887 :rtype: ``cryptography.x509.CertificateSigningRequest``
888
889 .. versionadded:: 17.1.0
890 """
891 from cryptography.hazmat.backends.openssl.x509 import (
Alex Gaynor03737182020-07-23 20:40:46 -0400892 _CertificateSigningRequest,
Paul Kehrer41c10242017-06-29 18:24:17 -0500893 )
Alex Gaynor03737182020-07-23 20:40:46 -0400894
Paul Kehrer41c10242017-06-29 18:24:17 -0500895 backend = _get_backend()
896 return _CertificateSigningRequest(backend, self._req)
897
898 @classmethod
899 def from_cryptography(cls, crypto_req):
900 """
901 Construct based on a ``cryptography`` *crypto_req*.
902
903 :param crypto_req: A ``cryptography`` X.509 certificate signing request
904 :type crypto_req: ``cryptography.x509.CertificateSigningRequest``
905
Gaurav Malhotra4121e252019-01-22 00:09:19 +0530906 :rtype: X509Req
Paul Kehrer41c10242017-06-29 18:24:17 -0500907
908 .. versionadded:: 17.1.0
909 """
910 if not isinstance(crypto_req, x509.CertificateSigningRequest):
911 raise TypeError("Must be a certificate signing request")
912
913 req = cls()
914 req._req = crypto_req._x509_req
915 return req
916
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800917 def set_pubkey(self, pkey):
918 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200919 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800920
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200921 :param pkey: The public key to use.
922 :type pkey: :py:class:`PKey`
923
Dan Sully44e767a2016-06-04 18:05:27 -0700924 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800925 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500926 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400927 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800928
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800929 def get_pubkey(self):
930 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200931 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800932
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200933 :return: The public key.
934 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800935 """
936 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500937 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700938 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500939 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800940 pkey._only_public = True
941 return pkey
942
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800943 def set_version(self, version):
944 """
945 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
946 request.
947
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200948 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700949 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800950 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500951 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400952 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800953
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800954 def get_version(self):
955 """
956 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
957 request.
958
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200959 :return: The value of the version subfield.
960 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800961 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500962 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800963
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800964 def get_subject(self):
965 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200966 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800967
Cory Benfield881dc8d2015-12-09 08:25:14 +0000968 This creates a new :class:`X509Name` that wraps the underlying subject
969 name field on the certificate signing request. Modifying it will modify
970 the underlying signing request, and will have the effect of modifying
971 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200972
973 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000974 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800975 """
976 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500977 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700978 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800979
980 # The name is owned by the X509Req structure. As long as the X509Name
981 # Python object is alive, keep the X509Req Python object alive.
982 name._owner = self
983
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800984 return name
985
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800986 def add_extensions(self, extensions):
987 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200988 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800989
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200990 :param extensions: The X.509 extensions to add.
991 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700992 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800993 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500994 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700995 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800996
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500997 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800998
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800999 for ext in extensions:
1000 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -08001001 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001002
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001003 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001004 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001005
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001006 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001007 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001008
Stephen Holsappleadfd39d2014-01-28 17:58:31 -08001009 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001010 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001011 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -08001012
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001013 :return: The X.509 extensions in this request.
1014 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
1015
1016 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001017 """
1018 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -05001019 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Paul Kehrer09b5d702020-11-27 15:22:30 -06001020 native_exts_obj = _ffi.gc(
1021 native_exts_obj,
1022 lambda x: _lib.sk_X509_EXTENSION_pop_free(
1023 x,
1024 _ffi.addressof(_lib._original_lib, "X509_EXTENSION_free"),
1025 ),
1026 )
1027
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -05001028 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001029 ext = X509Extension.__new__(X509Extension)
Paul Kehrer09b5d702020-11-27 15:22:30 -06001030 extension = _lib.X509_EXTENSION_dup(
1031 _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
1032 )
1033 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001034 exts.append(ext)
1035 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -08001036
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001037 def sign(self, pkey, digest):
1038 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001039 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001040
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001041 :param pkey: The key pair to sign with.
1042 :type pkey: :py:class:`PKey`
1043 :param digest: The name of the message digest to use for the signature,
Alex Gaynor239e2d32016-09-11 12:36:35 -04001044 e.g. :py:data:`b"sha256"`.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001045 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -07001046 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001047 """
1048 if pkey._only_public:
1049 raise ValueError("Key has only public part")
1050
1051 if not pkey._initialized:
1052 raise ValueError("Key is uninitialized")
1053
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001054 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001055 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001056 raise ValueError("No such digest method")
1057
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001058 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001059 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001060
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001061 def verify(self, pkey):
1062 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001063 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001064
Hynek Schlawack01c31672016-12-11 15:14:09 +01001065 :param PKey key: A public key.
1066
1067 :return: ``True`` if the signature is correct.
1068 :rtype: bool
1069
1070 :raises OpenSSL.crypto.Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001071 problem verifying the signature.
1072 """
1073 if not isinstance(pkey, PKey):
1074 raise TypeError("pkey must be a PKey instance")
1075
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001076 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001077 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001078 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001079
1080 return result
1081
1082
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001083class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001084 """
1085 An X.509 certificate.
1086 """
Alex Gaynor03737182020-07-23 20:40:46 -04001087
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001088 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001089 x509 = _lib.X509_new()
Hynek Schlawack8a2dd772016-07-31 13:46:20 +02001090 _openssl_assert(x509 != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001091 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001092
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001093 self._issuer_invalidator = _X509NameInvalidator()
1094 self._subject_invalidator = _X509NameInvalidator()
1095
1096 @classmethod
1097 def _from_raw_x509_ptr(cls, x509):
1098 cert = cls.__new__(cls)
1099 cert._x509 = _ffi.gc(x509, _lib.X509_free)
1100 cert._issuer_invalidator = _X509NameInvalidator()
1101 cert._subject_invalidator = _X509NameInvalidator()
1102 return cert
1103
Alex Gaynor9939ba12017-06-25 16:28:24 -04001104 def to_cryptography(self):
1105 """
1106 Export as a ``cryptography`` certificate.
1107
1108 :rtype: ``cryptography.x509.Certificate``
1109
1110 .. versionadded:: 17.1.0
1111 """
1112 from cryptography.hazmat.backends.openssl.x509 import _Certificate
Alex Gaynor03737182020-07-23 20:40:46 -04001113
Alex Gaynor9939ba12017-06-25 16:28:24 -04001114 backend = _get_backend()
1115 return _Certificate(backend, self._x509)
1116
1117 @classmethod
1118 def from_cryptography(cls, crypto_cert):
1119 """
1120 Construct based on a ``cryptography`` *crypto_cert*.
1121
1122 :param crypto_key: A ``cryptography`` X.509 certificate.
1123 :type crypto_key: ``cryptography.x509.Certificate``
1124
Gaurav Malhotra4121e252019-01-22 00:09:19 +05301125 :rtype: X509
Alex Gaynor9939ba12017-06-25 16:28:24 -04001126
1127 .. versionadded:: 17.1.0
1128 """
1129 if not isinstance(crypto_cert, x509.Certificate):
1130 raise TypeError("Must be a certificate")
1131
1132 cert = cls()
1133 cert._x509 = crypto_cert._x509
1134 return cert
1135
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001136 def set_version(self, version):
1137 """
Cyril Stoller6f25ced2018-08-27 13:37:51 +02001138 Set the version number of the certificate. Note that the
1139 version value is zero-based, eg. a value of 0 is V1.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001140
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001141 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001142 :type version: :py:class:`int`
1143
Dan Sully44e767a2016-06-04 18:05:27 -07001144 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001145 """
1146 if not isinstance(version, int):
1147 raise TypeError("version must be an integer")
1148
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001149 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001150
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001151 def get_version(self):
1152 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001153 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001154
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001155 :return: The version number of the certificate.
1156 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001157 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001158 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001159
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001160 def get_pubkey(self):
1161 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001162 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001163
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001164 :return: The public key.
1165 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001166 """
1167 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001168 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1169 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001170 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001171 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001172 pkey._only_public = True
1173 return pkey
1174
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001175 def set_pubkey(self, pkey):
1176 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001177 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001178
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001179 :param pkey: The public key.
1180 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001181
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001182 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001183 """
1184 if not isinstance(pkey, PKey):
1185 raise TypeError("pkey must be a PKey instance")
1186
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001187 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001188 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001189
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001190 def sign(self, pkey, digest):
1191 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001192 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001193
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001194 :param pkey: The key to sign with.
1195 :type pkey: :py:class:`PKey`
1196
1197 :param digest: The name of the message digest to use.
1198 :type digest: :py:class:`bytes`
1199
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001200 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001201 """
1202 if not isinstance(pkey, PKey):
1203 raise TypeError("pkey must be a PKey instance")
1204
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001205 if pkey._only_public:
1206 raise ValueError("Key only has public part")
1207
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001208 if not pkey._initialized:
1209 raise ValueError("Key is uninitialized")
1210
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001211 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001212 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001213 raise ValueError("No such digest method")
1214
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001215 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001216 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001217
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001218 def get_signature_algorithm(self):
1219 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001220 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001221
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001222 :return: The name of the algorithm.
1223 :rtype: :py:class:`bytes`
1224
1225 :raises ValueError: If the signature algorithm is undefined.
1226
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001227 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001228 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001229 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1230 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001231 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001232 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001233 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001234
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001235 def digest(self, digest_name):
1236 """
1237 Return the digest of the X509 object.
1238
1239 :param digest_name: The name of the digest algorithm to use.
1240 :type digest_name: :py:class:`bytes`
1241
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001242 :return: The digest of the object, formatted as
1243 :py:const:`b":"`-delimited hex pairs.
1244 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001245 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001246 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001247 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001248 raise ValueError("No such digest method")
1249
Paul Kehrer9f9113a2016-09-20 20:10:25 -05001250 result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001251 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001252 result_length[0] = len(result_buffer)
1253
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001254 digest_result = _lib.X509_digest(
Alex Gaynor03737182020-07-23 20:40:46 -04001255 self._x509, digest, result_buffer, result_length
1256 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04001257 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001258
Alex Gaynor03737182020-07-23 20:40:46 -04001259 return b":".join(
1260 [
1261 b16encode(ch).upper()
1262 for ch in _ffi.buffer(result_buffer, result_length[0])
1263 ]
1264 )
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001265
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001266 def subject_name_hash(self):
1267 """
1268 Return the hash of the X509 subject.
1269
1270 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001271 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001272 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001273 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001274
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001275 def set_serial_number(self, serial):
1276 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001277 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001278
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001279 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001280 :type serial: :py:class:`int`
1281
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001282 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001283 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001284 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001285 raise TypeError("serial must be an integer")
1286
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001287 hex_serial = hex(serial)[2:]
1288 if not isinstance(hex_serial, bytes):
Alex Gaynor03737182020-07-23 20:40:46 -04001289 hex_serial = hex_serial.encode("ascii")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001290
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001291 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001292
1293 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001294 # it. If bignum is still NULL after this call, then the return value
1295 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001296 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001297
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001298 if bignum_serial[0] == _ffi.NULL:
1299 set_result = _lib.ASN1_INTEGER_set(
Alex Gaynor03737182020-07-23 20:40:46 -04001300 _lib.X509_get_serialNumber(self._x509), small_serial
1301 )
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001302 if set_result:
1303 # TODO Not tested
1304 _raise_current_error()
1305 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001306 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1307 _lib.BN_free(bignum_serial[0])
1308 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001309 # TODO Not tested
1310 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001311 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1312 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001313 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001314
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001315 def get_serial_number(self):
1316 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001317 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001318
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001319 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001320 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001321 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001322 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1323 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001324 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001325 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001326 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001327 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001328 serial = int(hexstring_serial, 16)
1329 return serial
1330 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001331 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001332 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001333 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001334
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001335 def gmtime_adj_notAfter(self, amount):
1336 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001337 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001338
Dan Sully44e767a2016-06-04 18:05:27 -07001339 :param int amount: The number of seconds by which to adjust the
1340 timestamp.
1341 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001342 """
1343 if not isinstance(amount, int):
1344 raise TypeError("amount must be an integer")
1345
Rosen Penev43a23a32020-08-13 12:07:12 -07001346 notAfter = _lib.X509_getm_notAfter(self._x509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001347 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001348
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001349 def gmtime_adj_notBefore(self, amount):
1350 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001351 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001352
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001353 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001354 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001355 """
1356 if not isinstance(amount, int):
1357 raise TypeError("amount must be an integer")
1358
Rosen Penev43a23a32020-08-13 12:07:12 -07001359 notBefore = _lib.X509_getm_notBefore(self._x509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001360 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001361
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001362 def has_expired(self):
1363 """
1364 Check whether the certificate has expired.
1365
Dan Sully44e767a2016-06-04 18:05:27 -07001366 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1367 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001368 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001369 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001370 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001371
Paul Kehrerfde45c92016-01-21 12:57:37 -06001372 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001373
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001374 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001375 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001376
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001377 def get_notBefore(self):
1378 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001379 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001380
Paul Kehrerce98ee62017-06-21 06:59:58 -10001381 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001382
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001383 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001384
Dan Sully44e767a2016-06-04 18:05:27 -07001385 :return: A timestamp string, or ``None`` if there is none.
1386 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001387 """
Rosen Penev43a23a32020-08-13 12:07:12 -07001388 return self._get_boundary_time(_lib.X509_getm_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001389
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001390 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001391 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001392
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001393 def set_notBefore(self, when):
1394 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001395 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001396
Paul Kehrerce98ee62017-06-21 06:59:58 -10001397 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001398
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001399 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001400
Dan Sully44e767a2016-06-04 18:05:27 -07001401 :param bytes when: A timestamp string.
1402 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001403 """
Rosen Penev43a23a32020-08-13 12:07:12 -07001404 return self._set_boundary_time(_lib.X509_getm_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001405
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001406 def get_notAfter(self):
1407 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001408 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001409
Paul Kehrerce98ee62017-06-21 06:59:58 -10001410 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001411
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001412 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001413
Dan Sully44e767a2016-06-04 18:05:27 -07001414 :return: A timestamp string, or ``None`` if there is none.
1415 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001416 """
Rosen Penev43a23a32020-08-13 12:07:12 -07001417 return self._get_boundary_time(_lib.X509_getm_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001418
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001419 def set_notAfter(self, when):
1420 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001421 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001422
Paul Kehrerce98ee62017-06-21 06:59:58 -10001423 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001424
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001425 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001426
Dan Sully44e767a2016-06-04 18:05:27 -07001427 :param bytes when: A timestamp string.
1428 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001429 """
Rosen Penev43a23a32020-08-13 12:07:12 -07001430 return self._set_boundary_time(_lib.X509_getm_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001431
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001432 def _get_name(self, which):
1433 name = X509Name.__new__(X509Name)
1434 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001435 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001436
1437 # The name is owned by the X509 structure. As long as the X509Name
1438 # Python object is alive, keep the X509 Python object alive.
1439 name._owner = self
1440
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001441 return name
1442
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001443 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001444 if not isinstance(name, X509Name):
1445 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001446 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001447 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001448
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001449 def get_issuer(self):
1450 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001451 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001452
Cory Benfielde6bcce82015-12-09 08:40:03 +00001453 This creates a new :class:`X509Name` that wraps the underlying issuer
1454 name field on the certificate. Modifying it will modify the underlying
1455 certificate, and will have the effect of modifying any other
1456 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001457
1458 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001459 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001460 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001461 name = self._get_name(_lib.X509_get_issuer_name)
1462 self._issuer_invalidator.add(name)
1463 return name
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001464
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001465 def set_issuer(self, issuer):
1466 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001467 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001468
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001469 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001470 :type issuer: :py:class:`X509Name`
1471
Dan Sully44e767a2016-06-04 18:05:27 -07001472 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001473 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001474 self._set_name(_lib.X509_set_issuer_name, issuer)
1475 self._issuer_invalidator.clear()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001476
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001477 def get_subject(self):
1478 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001479 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001480
Cory Benfielde6bcce82015-12-09 08:40:03 +00001481 This creates a new :class:`X509Name` that wraps the underlying subject
1482 name field on the certificate. Modifying it will modify the underlying
1483 certificate, and will have the effect of modifying any other
1484 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001485
1486 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001487 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001488 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001489 name = self._get_name(_lib.X509_get_subject_name)
1490 self._subject_invalidator.add(name)
1491 return name
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001492
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001493 def set_subject(self, subject):
1494 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001495 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001496
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001497 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001498 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001499
Dan Sully44e767a2016-06-04 18:05:27 -07001500 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001501 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001502 self._set_name(_lib.X509_set_subject_name, subject)
1503 self._subject_invalidator.clear()
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001504
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001505 def get_extension_count(self):
1506 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001507 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001508
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001509 :return: The number of extensions.
1510 :rtype: :py:class:`int`
1511
1512 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001513 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001514 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001515
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001516 def add_extensions(self, extensions):
1517 """
1518 Add extensions to the certificate.
1519
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001520 :param extensions: The extensions to add.
1521 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001522 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001523 """
1524 for ext in extensions:
1525 if not isinstance(ext, X509Extension):
1526 raise ValueError("One of the elements is not an X509Extension")
1527
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001528 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001529 if not add_result:
1530 _raise_current_error()
1531
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001532 def get_extension(self, index):
1533 """
1534 Get a specific extension of the certificate by index.
1535
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001536 Extensions on a certificate are kept in order. The index
1537 parameter selects which extension will be returned.
1538
1539 :param int index: The index of the extension to retrieve.
1540 :return: The extension at the specified index.
1541 :rtype: :py:class:`X509Extension`
1542 :raises IndexError: If the extension index was out of bounds.
1543
1544 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001545 """
1546 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001547 ext._extension = _lib.X509_get_ext(self._x509, index)
1548 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001549 raise IndexError("extension index out of bounds")
1550
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001551 extension = _lib.X509_EXTENSION_dup(ext._extension)
1552 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001553 return ext
1554
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001555
Dan Sully44e767a2016-06-04 18:05:27 -07001556class X509StoreFlags(object):
1557 """
1558 Flags for X509 verification, used to change the behavior of
1559 :class:`X509Store`.
1560
1561 See `OpenSSL Verification Flags`_ for details.
1562
1563 .. _OpenSSL Verification Flags:
Alex Chan54005ce2017-03-21 08:08:17 +00001564 https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_flags.html
Dan Sully44e767a2016-06-04 18:05:27 -07001565 """
Alex Gaynor03737182020-07-23 20:40:46 -04001566
Dan Sully44e767a2016-06-04 18:05:27 -07001567 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1568 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1569 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1570 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1571 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1572 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1573 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1574 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1575 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1576 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1577 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1578
1579
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001580class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001581 """
Dan Sully44e767a2016-06-04 18:05:27 -07001582 An X.509 store.
1583
1584 An X.509 store is used to describe a context in which to verify a
1585 certificate. A description of a context may include a set of certificates
1586 to trust, a set of certificate revocation lists, verification flags and
1587 more.
1588
1589 An X.509 store, being only a description, cannot be used by itself to
1590 verify a certificate. To carry out the actual verification process, see
1591 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001592 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001593
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001594 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001595 store = _lib.X509_STORE_new()
1596 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001597
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001598 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001599 """
Dan Sully44e767a2016-06-04 18:05:27 -07001600 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001601
Dan Sully44e767a2016-06-04 18:05:27 -07001602 Adding a certificate with this method adds this certificate as a
1603 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001604
1605 :param X509 cert: The certificate to add to this store.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001606
Dan Sully44e767a2016-06-04 18:05:27 -07001607 :raises TypeError: If the certificate is not an :class:`X509`.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001608
1609 :raises OpenSSL.crypto.Error: If OpenSSL was unhappy with your
1610 certificate.
1611
Dan Sully44e767a2016-06-04 18:05:27 -07001612 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001613 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001614 if not isinstance(cert, X509):
1615 raise TypeError()
1616
Alex Gaynor124a0132020-10-27 00:15:17 -04001617 res = _lib.X509_STORE_add_cert(self._store, cert._x509)
1618 _openssl_assert(res == 1)
Dan Sully44e767a2016-06-04 18:05:27 -07001619
1620 def add_crl(self, crl):
1621 """
1622 Add a certificate revocation list to this store.
1623
1624 The certificate revocation lists added to a store will only be used if
1625 the associated flags are configured to check certificate revocation
1626 lists.
1627
1628 .. versionadded:: 16.1.0
1629
1630 :param CRL crl: The certificate revocation list to add to this store.
1631 :return: ``None`` if the certificate revocation list was added
1632 successfully.
1633 """
1634 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1635
1636 def set_flags(self, flags):
1637 """
1638 Set verification flags to this store.
1639
1640 Verification flags can be combined by oring them together.
1641
1642 .. note::
1643
1644 Setting a verification flag sometimes requires clients to add
1645 additional information to the store, otherwise a suitable error will
1646 be raised.
1647
1648 For example, in setting flags to enable CRL checking a
1649 suitable CRL must be added to the store otherwise an error will be
1650 raised.
1651
1652 .. versionadded:: 16.1.0
1653
1654 :param int flags: The verification flags to set on this store.
1655 See :class:`X509StoreFlags` for available constants.
1656 :return: ``None`` if the verification flags were successfully set.
1657 """
1658 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001659
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001660 def set_time(self, vfy_time):
1661 """
1662 Set the time against which the certificates are verified.
1663
1664 Normally the current time is used.
1665
1666 .. note::
1667
1668 For example, you can determine if a certificate was valid at a given
1669 time.
1670
Hynek Schlawackf6c96af2017-04-20 12:34:58 +02001671 .. versionadded:: 17.0.0
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001672
1673 :param datetime vfy_time: The verification time to set on this store.
1674 :return: ``None`` if the verification time was successfully set.
1675 """
1676 param = _lib.X509_VERIFY_PARAM_new()
1677 param = _ffi.gc(param, _lib.X509_VERIFY_PARAM_free)
1678
jalberdi004669dcc32020-10-18 17:55:40 +02001679 _lib.X509_VERIFY_PARAM_set_time(
1680 param, calendar.timegm(vfy_time.timetuple())
1681 )
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001682 _openssl_assert(_lib.X509_STORE_set1_param(self._store, param) != 0)
1683
Sándor Oroszi43c97762020-09-11 17:17:31 +02001684 def load_locations(self, cafile, capath=None):
1685 """
1686 Let X509Store know where we can find trusted certificates for the
1687 certificate chain. Note that the certificates have to be in PEM
1688 format.
1689
1690 If *capath* is passed, it must be a directory prepared using the
1691 ``c_rehash`` tool included with OpenSSL. Either, but not both, of
1692 *cafile* or *capath* may be ``None``.
1693
1694 .. note::
1695
1696 Both *cafile* and *capath* may be set simultaneously.
1697
1698 Call this method multiple times to add more than one location.
1699 For example, CA certificates, and certificate revocation list bundles
1700 may be passed in *cafile* in subsequent calls to this method.
1701
1702 .. versionadded:: 20.0
1703
1704 :param cafile: In which file we can find the certificates (``bytes`` or
1705 ``unicode``).
1706 :param capath: In which directory we can find the certificates
1707 (``bytes`` or ``unicode``).
1708
1709 :return: ``None`` if the locations were set successfully.
1710
1711 :raises OpenSSL.crypto.Error: If both *cafile* and *capath* is ``None``
1712 or the locations could not be set for any reason.
1713
1714 """
1715 if cafile is None:
1716 cafile = _ffi.NULL
1717 else:
1718 cafile = _path_string(cafile)
1719
1720 if capath is None:
1721 capath = _ffi.NULL
1722 else:
1723 capath = _path_string(capath)
1724
1725 load_result = _lib.X509_STORE_load_locations(
1726 self._store, cafile, capath
1727 )
1728 if not load_result:
1729 _raise_current_error()
1730
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001731
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001732class X509StoreContextError(Exception):
1733 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001734 An exception raised when an error occurred while verifying a certificate
1735 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001736
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001737 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001738 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001739 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001740
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001741 def __init__(self, message, certificate):
1742 super(X509StoreContextError, self).__init__(message)
1743 self.certificate = certificate
1744
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001745
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001746class X509StoreContext(object):
1747 """
1748 An X.509 store context.
1749
Dan Sully44e767a2016-06-04 18:05:27 -07001750 An X.509 store context is used to carry out the actual verification process
1751 of a certificate in a described context. For describing such a context, see
1752 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001753
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001754 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1755 instance. It is dynamically allocated and automatically garbage
1756 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001757 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001758 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Sándor Oroszi83ef2302020-10-12 15:42:23 +02001759 :ivar _chain: See the ``chain`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001760 :param X509Store store: The certificates which will be trusted for the
1761 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001762 :param X509 certificate: The certificate to be verified.
Sándor Oroszi83ef2302020-10-12 15:42:23 +02001763 :param chain: List of untrusted certificates that may be used for building
1764 the certificate chain. May be ``None``.
1765 :type chain: :class:`list` of :class:`X509`
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001766 """
1767
Sándor Oroszi83ef2302020-10-12 15:42:23 +02001768 def __init__(self, store, certificate, chain=None):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001769 store_ctx = _lib.X509_STORE_CTX_new()
1770 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1771 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001772 self._cert = certificate
Sándor Oroszi83ef2302020-10-12 15:42:23 +02001773 self._chain = self._build_certificate_stack(chain)
Stephen Holsapple46a09252015-02-12 14:45:43 -08001774 # Make the store context available for use after instantiating this
1775 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001776 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001777 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001778
Sándor Oroszi83ef2302020-10-12 15:42:23 +02001779 @staticmethod
1780 def _build_certificate_stack(certificates):
1781 def cleanup(s):
1782 # Equivalent to sk_X509_pop_free, but we don't
1783 # currently have a CFFI binding for that available
1784 for i in range(_lib.sk_X509_num(s)):
1785 x = _lib.sk_X509_value(s, i)
1786 _lib.X509_free(x)
1787 _lib.sk_X509_free(s)
1788
1789 if certificates is None or len(certificates) == 0:
1790 return _ffi.NULL
1791
1792 stack = _lib.sk_X509_new_null()
1793 _openssl_assert(stack != _ffi.NULL)
1794 stack = _ffi.gc(stack, cleanup)
1795
1796 for cert in certificates:
1797 if not isinstance(cert, X509):
1798 raise TypeError("One of the elements is not an X509 instance")
1799
1800 _openssl_assert(_lib.X509_up_ref(cert._x509) > 0)
1801 if _lib.sk_X509_push(stack, cert._x509) <= 0:
1802 _lib.X509_free(cert._x509)
1803 _raise_current_error()
1804
1805 return stack
1806
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001807 def _init(self):
1808 """
1809 Set up the store context for a subsequent verification operation.
Jeremy Cline58193f12017-09-13 21:14:53 -04001810
1811 Calling this method more than once without first calling
1812 :meth:`_cleanup` will leak memory.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001813 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001814 ret = _lib.X509_STORE_CTX_init(
Shane Harvey33c54992020-08-05 16:48:51 -07001815 self._store_ctx, self._store._store, self._cert._x509, self._chain
Alex Gaynor5945ea82015-09-05 14:59:06 -04001816 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001817 if ret <= 0:
1818 _raise_current_error()
1819
1820 def _cleanup(self):
1821 """
1822 Internally cleans up the store context.
1823
Dan Sully44e767a2016-06-04 18:05:27 -07001824 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001825 """
1826 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1827
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001828 def _exception_from_context(self):
1829 """
1830 Convert an OpenSSL native context error failure into a Python
1831 exception.
1832
Alex Gaynor5945ea82015-09-05 14:59:06 -04001833 When a call to native OpenSSL X509_verify_cert fails, additional
1834 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001835 """
1836 errors = [
1837 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1838 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
Alex Gaynor03737182020-07-23 20:40:46 -04001839 _native(
1840 _ffi.string(
1841 _lib.X509_verify_cert_error_string(
1842 _lib.X509_STORE_CTX_get_error(self._store_ctx)
1843 )
1844 )
1845 ),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001846 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001847 # A context error should always be associated with a certificate, so we
1848 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001849 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001850 _cert = _lib.X509_dup(_x509)
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001851 pycert = X509._from_raw_x509_ptr(_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001852 return X509StoreContextError(errors, pycert)
1853
Stephen Holsapple46a09252015-02-12 14:45:43 -08001854 def set_store(self, store):
1855 """
Dan Sully44e767a2016-06-04 18:05:27 -07001856 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001857
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001858 .. versionadded:: 0.15
1859
Dan Sully44e767a2016-06-04 18:05:27 -07001860 :param X509Store store: The store description which will be used for
1861 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001862 """
1863 self._store = store
1864
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001865 def verify_certificate(self):
1866 """
1867 Verify a certificate in a context.
1868
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001869 .. versionadded:: 0.15
1870
Alex Gaynorca87ff62015-09-04 23:31:03 -04001871 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001872 certificate in the context. Sets ``certificate`` attribute to
1873 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001874 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001875 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001876 # :meth:`verify_certificate` is called multiple times.
Jeremy Cline58193f12017-09-13 21:14:53 -04001877 #
1878 # :meth:`_init` is called in :meth:`__init__` so _cleanup is called
1879 # before _init to ensure memory is not leaked.
1880 self._cleanup()
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001881 self._init()
1882 ret = _lib.X509_verify_cert(self._store_ctx)
1883 self._cleanup()
1884 if ret <= 0:
1885 raise self._exception_from_context()
1886
Shane Harvey33c54992020-08-05 16:48:51 -07001887 def get_verified_chain(self):
1888 """
1889 Verify a certificate in a context and return the complete validated
1890 chain.
1891
1892 :raises X509StoreContextError: If an error occurred when validating a
1893 certificate in the context. Sets ``certificate`` attribute to
1894 indicate which certificate caused the error.
1895
1896 .. versionadded:: 20.0
1897 """
1898 # Always re-initialize the store context in case
1899 # :meth:`verify_certificate` is called multiple times.
1900 #
1901 # :meth:`_init` is called in :meth:`__init__` so _cleanup is called
1902 # before _init to ensure memory is not leaked.
1903 self._cleanup()
1904 self._init()
1905 ret = _lib.X509_verify_cert(self._store_ctx)
1906 if ret <= 0:
1907 self._cleanup()
1908 raise self._exception_from_context()
1909
1910 # Note: X509_STORE_CTX_get1_chain returns a deep copy of the chain.
1911 cert_stack = _lib.X509_STORE_CTX_get1_chain(self._store_ctx)
1912 _openssl_assert(cert_stack != _ffi.NULL)
1913
1914 result = []
1915 for i in range(_lib.sk_X509_num(cert_stack)):
1916 cert = _lib.sk_X509_value(cert_stack, i)
1917 _openssl_assert(cert != _ffi.NULL)
1918 pycert = X509._from_raw_x509_ptr(cert)
1919 result.append(pycert)
1920
1921 # Free the stack but not the members which are freed by the X509 class.
1922 _lib.sk_X509_free(cert_stack)
1923 self._cleanup()
1924 return result
1925
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001926
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001927def load_certificate(type, buffer):
1928 """
Alex Chand072cae2018-02-15 09:57:59 +00001929 Load a certificate (X509) from the string *buffer* encoded with the
1930 type *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001931
1932 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1933
Dan Sully44e767a2016-06-04 18:05:27 -07001934 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001935
1936 :return: The X509 object
1937 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001938 if isinstance(buffer, _text_type):
1939 buffer = buffer.encode("ascii")
1940
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001941 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001942
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001943 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001944 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001945 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001946 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001947 else:
Alex Gaynor03737182020-07-23 20:40:46 -04001948 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001949
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001950 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001951 _raise_current_error()
1952
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001953 return X509._from_raw_x509_ptr(x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001954
1955
1956def dump_certificate(type, cert):
1957 """
Alex Chand072cae2018-02-15 09:57:59 +00001958 Dump the certificate *cert* into a buffer string encoded with the type
1959 *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001960
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001961 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1962 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001963 :param cert: The certificate to dump
1964 :return: The buffer with the dumped certificate in
1965 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001966 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001967
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001968 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001969 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001970 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001971 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001972 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001973 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001974 else:
1975 raise ValueError(
1976 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
Alex Gaynor03737182020-07-23 20:40:46 -04001977 "FILETYPE_TEXT"
1978 )
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001979
Adrián Chaves98c57be2020-03-31 16:14:50 +02001980 _openssl_assert(result_code == 1)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001981 return _bio_to_string(bio)
1982
1983
Cory Benfield6492f7c2015-10-27 16:57:58 +09001984def dump_publickey(type, pkey):
1985 """
Cory Benfield11c10192015-10-27 17:23:03 +09001986 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001987
Cory Benfield9c590b92015-10-28 14:55:05 +09001988 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001989 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001990 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001991 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001992 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001993 """
1994 bio = _new_mem_buf()
1995 if type == FILETYPE_PEM:
1996 write_bio = _lib.PEM_write_bio_PUBKEY
1997 elif type == FILETYPE_ASN1:
1998 write_bio = _lib.i2d_PUBKEY_bio
1999 else:
2000 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2001
2002 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09002003 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09002004 _raise_current_error()
2005
2006 return _bio_to_string(bio)
2007
2008
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002009def dump_privatekey(type, pkey, cipher=None, passphrase=None):
2010 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02002011 Dump the private key *pkey* into a buffer string encoded with the type
2012 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
2013 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002014
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02002015 :param type: The file type (one of :const:`FILETYPE_PEM`,
2016 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
2017 :param PKey pkey: The PKey to dump
2018 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002019 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02002020 the passphrase to use, or a callback for providing the passphrase.
2021
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002022 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07002023 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002024 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002025 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002026
Paul Kehrercded9932017-06-29 18:43:42 -05002027 if not isinstance(pkey, PKey):
2028 raise TypeError("pkey must be a PKey")
2029
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002030 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002031 if passphrase is None:
2032 raise TypeError(
2033 "if a value is given for cipher "
Alex Gaynor03737182020-07-23 20:40:46 -04002034 "one must also be given for passphrase"
2035 )
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002036 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002037 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002038 raise ValueError("Invalid cipher name")
2039 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002040 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002041
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002042 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002043 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002044 result_code = _lib.PEM_write_bio_PrivateKey(
Alex Gaynor03737182020-07-23 20:40:46 -04002045 bio,
2046 pkey._pkey,
2047 cipher_obj,
2048 _ffi.NULL,
2049 0,
2050 helper.callback,
2051 helper.callback_args,
2052 )
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002053 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002054 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002055 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002056 elif type == FILETYPE_TEXT:
Paul Kehrercded9932017-06-29 18:43:42 -05002057 if _lib.EVP_PKEY_id(pkey._pkey) != _lib.EVP_PKEY_RSA:
2058 raise TypeError("Only RSA keys are supported for FILETYPE_TEXT")
2059
Alex Gaynor03737182020-07-23 20:40:46 -04002060 rsa = _ffi.gc(_lib.EVP_PKEY_get1_RSA(pkey._pkey), _lib.RSA_free)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002061 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002062 else:
2063 raise ValueError(
2064 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
Alex Gaynor03737182020-07-23 20:40:46 -04002065 "FILETYPE_TEXT"
2066 )
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002067
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02002068 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002069
2070 return _bio_to_string(bio)
2071
2072
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002073class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002074 """
2075 A certificate revocation.
2076 """
Alex Gaynor03737182020-07-23 20:40:46 -04002077
Cyril Stoller37e60222018-08-27 13:38:10 +02002078 # https://www.openssl.org/docs/manmaster/man5/x509v3_config.html#CRL-distribution-points
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002079 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
2080 # OCSP_crl_reason_str. We use the latter, just like the command line
2081 # program.
2082 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002083 b"unspecified",
2084 b"keyCompromise",
2085 b"CACompromise",
2086 b"affiliationChanged",
2087 b"superseded",
2088 b"cessationOfOperation",
2089 b"certificateHold",
2090 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04002091 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002092
2093 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002094 revoked = _lib.X509_REVOKED_new()
2095 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002096
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002097 def set_serial(self, hex_str):
2098 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002099 Set the serial number.
2100
2101 The serial number is formatted as a hexadecimal number encoded in
2102 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002103
Dan Sully44e767a2016-06-04 18:05:27 -07002104 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002105
Dan Sully44e767a2016-06-04 18:05:27 -07002106 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002107 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002108 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
2109 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08002110 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002111 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002112 if not bn_result:
2113 raise ValueError("bad hex string")
2114
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002115 asn1_serial = _ffi.gc(
2116 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
Alex Gaynor03737182020-07-23 20:40:46 -04002117 _lib.ASN1_INTEGER_free,
2118 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002119 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002120
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002121 def get_serial(self):
2122 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002123 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002124
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002125 The serial number is formatted as a hexadecimal number encoded in
2126 ASCII.
2127
2128 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07002129 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002130 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08002131 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002132
Alex Gaynor67903a62016-06-02 10:37:13 -07002133 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
2134 _openssl_assert(asn1_int != _ffi.NULL)
2135 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
2136 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002137 return _bio_to_string(bio)
2138
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002139 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07002140 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
2141 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002142 obj = _lib.X509_EXTENSION_get_object(ext)
2143 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002144 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07002145 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002146 break
2147
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002148 def set_reason(self, reason):
2149 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002150 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002151
Dan Sully44e767a2016-06-04 18:05:27 -07002152 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002153
2154 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07002155 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002156
Dan Sully44e767a2016-06-04 18:05:27 -07002157 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002158
2159 .. seealso::
2160
Dan Sully44e767a2016-06-04 18:05:27 -07002161 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002162 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002163 """
2164 if reason is None:
2165 self._delete_reason()
2166 elif not isinstance(reason, bytes):
2167 raise TypeError("reason must be None or a byte string")
2168 else:
Alex Gaynor03737182020-07-23 20:40:46 -04002169 reason = reason.lower().replace(b" ", b"")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002170 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
2171
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002172 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002173 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002174 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002175
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002176 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002177 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002178
2179 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002180 add_result = _lib.X509_REVOKED_add1_ext_i2d(
Alex Gaynor03737182020-07-23 20:40:46 -04002181 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0
2182 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002183 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002184
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002185 def get_reason(self):
2186 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04002187 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002188
Dan Sully44e767a2016-06-04 18:05:27 -07002189 :return: The reason, or ``None`` if there is none.
2190 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002191
2192 .. seealso::
2193
Dan Sully44e767a2016-06-04 18:05:27 -07002194 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002195 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002196 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002197 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
2198 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002199 obj = _lib.X509_EXTENSION_get_object(ext)
2200 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08002201 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002202
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002203 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002204 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002205 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002206 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04002207 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002208 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002209
2210 return _bio_to_string(bio)
2211
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002212 def all_reasons(self):
2213 """
2214 Return a list of all the supported reason strings.
2215
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002216 This list is a copy; modifying it does not change the supported reason
2217 strings.
2218
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002219 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07002220 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002221 """
2222 return self._crl_reasons[:]
2223
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002224 def set_rev_date(self, when):
2225 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002226 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002227
Dan Sully44e767a2016-06-04 18:05:27 -07002228 :param bytes when: The timestamp of the revocation,
Paul Kehrerce98ee62017-06-21 06:59:58 -10002229 as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002230 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002231 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002232 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2233 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002234
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002235 def get_rev_date(self):
2236 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002237 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002238
Paul Kehrerce98ee62017-06-21 06:59:58 -10002239 :return: The timestamp of the revocation, as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002240 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002241 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002242 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2243 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002244
2245
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002246class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002247 """
2248 A certificate revocation list.
2249 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002250
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002251 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002252 crl = _lib.X509_CRL_new()
2253 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002254
Paul Kehrer41c10242017-06-29 18:24:17 -05002255 def to_cryptography(self):
2256 """
2257 Export as a ``cryptography`` CRL.
2258
2259 :rtype: ``cryptography.x509.CertificateRevocationList``
2260
2261 .. versionadded:: 17.1.0
2262 """
2263 from cryptography.hazmat.backends.openssl.x509 import (
Alex Gaynor03737182020-07-23 20:40:46 -04002264 _CertificateRevocationList,
Paul Kehrer41c10242017-06-29 18:24:17 -05002265 )
Alex Gaynor03737182020-07-23 20:40:46 -04002266
Paul Kehrer41c10242017-06-29 18:24:17 -05002267 backend = _get_backend()
2268 return _CertificateRevocationList(backend, self._crl)
2269
2270 @classmethod
2271 def from_cryptography(cls, crypto_crl):
2272 """
2273 Construct based on a ``cryptography`` *crypto_crl*.
2274
2275 :param crypto_crl: A ``cryptography`` certificate revocation list
2276 :type crypto_crl: ``cryptography.x509.CertificateRevocationList``
2277
2278 :rtype: CRL
2279
2280 .. versionadded:: 17.1.0
2281 """
2282 if not isinstance(crypto_crl, x509.CertificateRevocationList):
2283 raise TypeError("Must be a certificate revocation list")
2284
2285 crl = cls()
2286 crl._crl = crypto_crl._x509_crl
2287 return crl
2288
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002289 def get_revoked(self):
2290 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002291 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002292
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002293 These revocations will be provided by value, not by reference.
2294 That means it's okay to mutate them: it won't affect this CRL.
2295
2296 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002297 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002298 """
2299 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07002300 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002301 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
2302 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04002303 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002304 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002305 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002306 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002307 if results:
2308 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002309
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002310 def add_revoked(self, revoked):
2311 """
2312 Add a revoked (by value not reference) to the CRL structure
2313
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002314 This revocation will be added by value, not by reference. That
2315 means it's okay to mutate it after adding: it won't affect
2316 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002317
Dan Sully44e767a2016-06-04 18:05:27 -07002318 :param Revoked revoked: The new revocation.
2319 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002320 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04002321 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002322 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002323
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002324 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002325 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002326
Dan Sully44e767a2016-06-04 18:05:27 -07002327 def get_issuer(self):
2328 """
2329 Get the CRL's issuer.
2330
2331 .. versionadded:: 16.1.0
2332
2333 :rtype: X509Name
2334 """
2335 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
2336 _openssl_assert(_issuer != _ffi.NULL)
2337 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
2338 issuer = X509Name.__new__(X509Name)
2339 issuer._name = _issuer
2340 return issuer
2341
2342 def set_version(self, version):
2343 """
2344 Set the CRL version.
2345
2346 .. versionadded:: 16.1.0
2347
2348 :param int version: The version of the CRL.
2349 :return: ``None``
2350 """
2351 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2352
2353 def _set_boundary_time(self, which, when):
2354 return _set_asn1_time(which(self._crl), when)
2355
2356 def set_lastUpdate(self, when):
2357 """
2358 Set when the CRL was last updated.
2359
Paul Kehrerce98ee62017-06-21 06:59:58 -10002360 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002361
2362 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002363
2364 .. versionadded:: 16.1.0
2365
2366 :param bytes when: A timestamp string.
2367 :return: ``None``
2368 """
2369 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2370
2371 def set_nextUpdate(self, when):
2372 """
Felix Yan3db93f12020-10-15 03:41:20 +08002373 Set when the CRL will next be updated.
Dan Sully44e767a2016-06-04 18:05:27 -07002374
Paul Kehrerce98ee62017-06-21 06:59:58 -10002375 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002376
2377 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002378
2379 .. versionadded:: 16.1.0
2380
2381 :param bytes when: A timestamp string.
2382 :return: ``None``
2383 """
2384 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2385
2386 def sign(self, issuer_cert, issuer_key, digest):
2387 """
2388 Sign the CRL.
2389
2390 Signing a CRL enables clients to associate the CRL itself with an
2391 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2392 be signed by an issuer.
2393
2394 This method implicitly sets the issuer's name based on the issuer
2395 certificate and private key used to sign the CRL.
2396
2397 .. versionadded:: 16.1.0
2398
2399 :param X509 issuer_cert: The issuer's certificate.
2400 :param PKey issuer_key: The issuer's private key.
2401 :param bytes digest: The digest method to sign the CRL with.
2402 """
2403 digest_obj = _lib.EVP_get_digestbyname(digest)
2404 _openssl_assert(digest_obj != _ffi.NULL)
2405 _lib.X509_CRL_set_issuer_name(
Alex Gaynor03737182020-07-23 20:40:46 -04002406 self._crl, _lib.X509_get_subject_name(issuer_cert._x509)
2407 )
Dan Sully44e767a2016-06-04 18:05:27 -07002408 _lib.X509_CRL_sort(self._crl)
2409 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2410 _openssl_assert(result != 0)
2411
Alex Gaynor03737182020-07-23 20:40:46 -04002412 def export(
2413 self, cert, key, type=FILETYPE_PEM, days=100, digest=_UNSPECIFIED
2414 ):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002415 """
Dan Sully44e767a2016-06-04 18:05:27 -07002416 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002417
Dan Sully44e767a2016-06-04 18:05:27 -07002418 :param X509 cert: The certificate used to sign the CRL.
2419 :param PKey key: The key used to sign the CRL.
2420 :param int type: The export format, either :data:`FILETYPE_PEM`,
2421 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002422 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002423 :param bytes digest: The name of the message digest to use (eg
Wayne Werner80dcf382019-01-30 15:03:16 -06002424 ``b"sha256"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002425 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002426 """
Dan Sully44e767a2016-06-04 18:05:27 -07002427
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002428 if not isinstance(cert, X509):
2429 raise TypeError("cert must be an X509 instance")
2430 if not isinstance(key, PKey):
2431 raise TypeError("key must be a PKey instance")
2432 if not isinstance(type, int):
2433 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002434
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002435 if digest is _UNSPECIFIED:
Alex Gaynor173e4ba2017-06-30 08:01:12 -07002436 raise TypeError("digest must be provided")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002437
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002438 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002439 if digest_obj == _ffi.NULL:
2440 raise ValueError("No such digest method")
2441
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002442 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002443 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002444
Alex Gaynora738ed52015-09-05 11:17:10 -04002445 # A scratch time object to give different values to different CRL
2446 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002447 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002448 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002449
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002450 _lib.X509_gmtime_adj(sometime, 0)
2451 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002452
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002453 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2454 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002455
Alex Gaynor5945ea82015-09-05 14:59:06 -04002456 _lib.X509_CRL_set_issuer_name(
2457 self._crl, _lib.X509_get_subject_name(cert._x509)
2458 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002459
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002460 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002461 if not sign_result:
2462 _raise_current_error()
2463
Dominic Chenf05b2122015-10-13 16:32:35 +00002464 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002465
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002466
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002467class PKCS7(object):
2468 def type_is_signed(self):
2469 """
2470 Check if this NID_pkcs7_signed object
2471
2472 :return: True if the PKCS7 is of type signed
2473 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002474 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002475
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002476 def type_is_enveloped(self):
2477 """
2478 Check if this NID_pkcs7_enveloped object
2479
2480 :returns: True if the PKCS7 is of type enveloped
2481 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002482 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002483
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002484 def type_is_signedAndEnveloped(self):
2485 """
2486 Check if this NID_pkcs7_signedAndEnveloped object
2487
2488 :returns: True if the PKCS7 is of type signedAndEnveloped
2489 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002490 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002491
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002492 def type_is_data(self):
2493 """
2494 Check if this NID_pkcs7_data object
2495
2496 :return: True if the PKCS7 is of type data
2497 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002498 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002499
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002500 def get_type_name(self):
2501 """
2502 Returns the type name of the PKCS7 structure
2503
2504 :return: A string with the typename
2505 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002506 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2507 string_type = _lib.OBJ_nid2sn(nid)
2508 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002509
Alex Chanc6077062016-11-18 13:53:39 +00002510
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002511class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002512 """
2513 A PKCS #12 archive.
2514 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002515
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002516 def __init__(self):
2517 self._pkey = None
2518 self._cert = None
2519 self._cacerts = None
2520 self._friendlyname = None
2521
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002522 def get_certificate(self):
2523 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002524 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002525
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002526 :return: The certificate, or :py:const:`None` if there is none.
2527 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002528 """
2529 return self._cert
2530
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002531 def set_certificate(self, cert):
2532 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002533 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002534
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002535 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002536 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002537
Dan Sully44e767a2016-06-04 18:05:27 -07002538 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002539 """
2540 if not isinstance(cert, X509):
2541 raise TypeError("cert must be an X509 instance")
2542 self._cert = cert
2543
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002544 def get_privatekey(self):
2545 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002546 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002547
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002548 :return: The private key, or :py:const:`None` if there is none.
2549 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002550 """
2551 return self._pkey
2552
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002553 def set_privatekey(self, pkey):
2554 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002555 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002556
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002557 :param pkey: The new private key, or :py:const:`None` to unset it.
2558 :type pkey: :py:class:`PKey` or :py:const:`None`
2559
Dan Sully44e767a2016-06-04 18:05:27 -07002560 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002561 """
2562 if not isinstance(pkey, PKey):
2563 raise TypeError("pkey must be a PKey instance")
2564 self._pkey = pkey
2565
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002566 def get_ca_certificates(self):
2567 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002568 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002569
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002570 :return: A tuple with the CA certificates in the chain, or
2571 :py:const:`None` if there are none.
2572 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002573 """
2574 if self._cacerts is not None:
2575 return tuple(self._cacerts)
2576
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002577 def set_ca_certificates(self, cacerts):
2578 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002579 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002580
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002581 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2582 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002583 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002584
Dan Sully44e767a2016-06-04 18:05:27 -07002585 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002586 """
2587 if cacerts is None:
2588 self._cacerts = None
2589 else:
2590 cacerts = list(cacerts)
2591 for cert in cacerts:
2592 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002593 raise TypeError(
2594 "iterable must only contain X509 instances"
2595 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002596 self._cacerts = cacerts
2597
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002598 def set_friendlyname(self, name):
2599 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002600 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002601
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002602 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002603 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002604
Dan Sully44e767a2016-06-04 18:05:27 -07002605 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002606 """
2607 if name is None:
2608 self._friendlyname = None
2609 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002610 raise TypeError(
2611 "name must be a byte string or None (not %r)" % (name,)
2612 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002613 self._friendlyname = name
2614
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002615 def get_friendlyname(self):
2616 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002617 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002618
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002619 :returns: The friendly name, or :py:const:`None` if there is none.
2620 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002621 """
2622 return self._friendlyname
2623
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002624 def export(self, passphrase=None, iter=2048, maciter=1):
2625 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002626 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002627
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002628 For more information, see the :c:func:`PKCS12_create` man page.
2629
2630 :param passphrase: The passphrase used to encrypt the structure. Unlike
2631 some other passphrase arguments, this *must* be a string, not a
2632 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002633 :type passphrase: :py:data:`bytes`
2634
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002635 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002636 :type iter: :py:data:`int`
2637
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002638 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002639 :type maciter: :py:data:`int`
2640
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002641 :return: The string representation of the PKCS #12 structure.
2642 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002643 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002644 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002645
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002646 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002647 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002648 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002649 cacerts = _lib.sk_X509_new_null()
2650 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002651 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002652 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002653
2654 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002655 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002656
2657 friendlyname = self._friendlyname
2658 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002659 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002660
2661 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002662 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002663 else:
2664 pkey = self._pkey._pkey
2665
2666 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002667 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002668 else:
2669 cert = self._cert._x509
2670
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002671 pkcs12 = _lib.PKCS12_create(
Alex Gaynor03737182020-07-23 20:40:46 -04002672 passphrase,
2673 friendlyname,
2674 pkey,
2675 cert,
2676 cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002677 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2678 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Alex Gaynor03737182020-07-23 20:40:46 -04002679 iter,
2680 maciter,
2681 0,
2682 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002683 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002684 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002685 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002686
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002687 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002688 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002689 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002690
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002691
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002692class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002693 """
2694 A Netscape SPKI object.
2695 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002696
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002697 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002698 spki = _lib.NETSCAPE_SPKI_new()
2699 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002700
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002701 def sign(self, pkey, digest):
2702 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002703 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002704
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002705 :param pkey: The private key to sign with.
2706 :type pkey: :py:class:`PKey`
2707
2708 :param digest: The message digest to use.
2709 :type digest: :py:class:`bytes`
2710
Dan Sully44e767a2016-06-04 18:05:27 -07002711 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002712 """
2713 if pkey._only_public:
2714 raise ValueError("Key has only public part")
2715
2716 if not pkey._initialized:
2717 raise ValueError("Key is uninitialized")
2718
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002719 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002720 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002721 raise ValueError("No such digest method")
2722
Alex Gaynor5945ea82015-09-05 14:59:06 -04002723 sign_result = _lib.NETSCAPE_SPKI_sign(
2724 self._spki, pkey._pkey, digest_obj
2725 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002726 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002727
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002728 def verify(self, key):
2729 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002730 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002731
Hynek Schlawack01c31672016-12-11 15:14:09 +01002732 :param PKey key: The public key that signature is supposedly from.
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002733
Hynek Schlawack01c31672016-12-11 15:14:09 +01002734 :return: ``True`` if the signature is correct.
2735 :rtype: bool
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002736
Hynek Schlawack01c31672016-12-11 15:14:09 +01002737 :raises OpenSSL.crypto.Error: If the signature is invalid, or there was
2738 a problem verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002739 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002740 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002741 if answer <= 0:
2742 _raise_current_error()
2743 return True
2744
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002745 def b64_encode(self):
2746 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002747 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002748
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002749 :return: The base64 encoded string.
2750 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002751 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002752 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2753 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002754 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002755 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002756
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002757 def get_pubkey(self):
2758 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002759 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002760
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002761 :return: The public key.
2762 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002763 """
2764 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002765 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002766 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002767 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002768 pkey._only_public = True
2769 return pkey
2770
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002771 def set_pubkey(self, pkey):
2772 """
2773 Set the public key of the certificate
2774
2775 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002776 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002777 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002778 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002779 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002780
2781
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002782class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002783 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002784 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002785 raise ValueError(
2786 "only FILETYPE_PEM key format supports encryption"
2787 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002788 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002789 self._more_args = more_args
2790 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002791 self._problems = []
2792
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002793 @property
2794 def callback(self):
2795 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002796 return _ffi.NULL
Huw Jonescdd66962020-10-13 05:14:19 +01002797 elif isinstance(self._passphrase, bytes) or callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002798 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002799 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002800 raise TypeError(
2801 "Last argument must be a byte string or a callable."
2802 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002803
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002804 @property
2805 def callback_args(self):
2806 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002807 return _ffi.NULL
Huw Jonescdd66962020-10-13 05:14:19 +01002808 elif isinstance(self._passphrase, bytes) or callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002809 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002810 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002811 raise TypeError(
2812 "Last argument must be a byte string or a callable."
2813 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002814
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002815 def raise_if_problem(self, exceptionType=Error):
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002816 if self._problems:
Greg Bowser36eb2de2017-01-24 11:38:55 -05002817
2818 # Flush the OpenSSL error queue
2819 try:
2820 _exception_from_error_queue(exceptionType)
2821 except exceptionType:
2822 pass
2823
2824 raise self._problems.pop(0)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002825
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002826 def _read_passphrase(self, buf, size, rwflag, userdata):
2827 try:
Huw Jonescdd66962020-10-13 05:14:19 +01002828 if callable(self._passphrase):
2829 if self._more_args:
2830 result = self._passphrase(size, rwflag, userdata)
2831 else:
2832 result = self._passphrase(rwflag)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002833 else:
Huw Jonescdd66962020-10-13 05:14:19 +01002834 result = self._passphrase
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002835 if not isinstance(result, bytes):
Huw Jonescdd66962020-10-13 05:14:19 +01002836 raise ValueError("Bytes expected")
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002837 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002838 if self._truncate:
2839 result = result[:size]
2840 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002841 raise ValueError(
2842 "passphrase returned by callback is too long"
2843 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002844 for i in range(len(result)):
Alex Gaynor03737182020-07-23 20:40:46 -04002845 buf[i] = result[i : i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002846 return len(result)
2847 except Exception as e:
2848 self._problems.append(e)
2849 return 0
2850
2851
Cory Benfield6492f7c2015-10-27 16:57:58 +09002852def load_publickey(type, buffer):
2853 """
Cory Benfield11c10192015-10-27 17:23:03 +09002854 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002855
Cory Benfield9c590b92015-10-28 14:55:05 +09002856 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002857 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002858 :param buffer: The buffer the key is stored in.
2859 :type buffer: A Python string object, either unicode or bytestring.
2860 :return: The PKey object.
2861 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002862 """
2863 if isinstance(buffer, _text_type):
2864 buffer = buffer.encode("ascii")
2865
2866 bio = _new_mem_buf(buffer)
2867
2868 if type == FILETYPE_PEM:
2869 evp_pkey = _lib.PEM_read_bio_PUBKEY(
Alex Gaynor03737182020-07-23 20:40:46 -04002870 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL
2871 )
Cory Benfield6492f7c2015-10-27 16:57:58 +09002872 elif type == FILETYPE_ASN1:
2873 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2874 else:
2875 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2876
2877 if evp_pkey == _ffi.NULL:
2878 _raise_current_error()
2879
2880 pkey = PKey.__new__(PKey)
2881 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002882 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002883 return pkey
2884
2885
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002886def load_privatekey(type, buffer, passphrase=None):
2887 """
Alex Chand072cae2018-02-15 09:57:59 +00002888 Load a private key (PKey) from the string *buffer* encoded with the type
2889 *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002890
2891 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2892 :param buffer: The buffer the key is stored in
2893 :param passphrase: (optional) if encrypted PEM format, this can be
2894 either the passphrase to use, or a callback for
2895 providing the passphrase.
2896
2897 :return: The PKey object
2898 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002899 if isinstance(buffer, _text_type):
2900 buffer = buffer.encode("ascii")
2901
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002902 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002903
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002904 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002905 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002906 evp_pkey = _lib.PEM_read_bio_PrivateKey(
Alex Gaynor03737182020-07-23 20:40:46 -04002907 bio, _ffi.NULL, helper.callback, helper.callback_args
2908 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002909 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002910 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002911 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002912 else:
2913 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2914
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002915 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002916 _raise_current_error()
2917
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002918 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002919 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002920 return pkey
2921
2922
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002923def dump_certificate_request(type, req):
2924 """
Alex Chand072cae2018-02-15 09:57:59 +00002925 Dump the certificate request *req* into a buffer string encoded with the
2926 type *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002927
2928 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2929 :param req: The certificate request to dump
2930 :return: The buffer with the dumped certificate request in
2931 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002932 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002933
2934 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002935 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002936 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002937 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002938 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002939 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002940 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002941 raise ValueError(
2942 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2943 "FILETYPE_TEXT"
2944 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002945
Alex Gaynor09a386e2016-07-03 09:32:44 -04002946 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002947
2948 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002949
2950
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002951def load_certificate_request(type, buffer):
2952 """
Alex Chand072cae2018-02-15 09:57:59 +00002953 Load a certificate request (X509Req) from the string *buffer* encoded with
2954 the type *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002955
2956 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2957 :param buffer: The buffer the certificate request is stored in
2958 :return: The X509Req object
2959 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002960 if isinstance(buffer, _text_type):
2961 buffer = buffer.encode("ascii")
2962
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002963 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002964
2965 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002966 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002967 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002968 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002969 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002970 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002971
Alex Gaynoradd5b072016-06-04 21:04:00 -07002972 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002973
2974 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002975 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002976 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002977
2978
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002979def sign(pkey, data, digest):
2980 """
Alex Chand072cae2018-02-15 09:57:59 +00002981 Sign a data string using the given key and message digest.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002982
Alex Chand072cae2018-02-15 09:57:59 +00002983 :param pkey: PKey to sign with
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002984 :param data: data to be signed
2985 :param digest: message digest to use
2986 :return: signature
Alex Chand072cae2018-02-15 09:57:59 +00002987
2988 .. versionadded:: 0.11
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002989 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002990 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002991
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002992 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002993 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002994 raise ValueError("No such digest method")
2995
Alex Gaynor67903a62016-06-02 10:37:13 -07002996 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002997 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002998
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002999 _lib.EVP_SignInit(md_ctx, digest_obj)
3000 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08003001
Paul Kehrer59d26252017-07-20 10:45:54 +02003002 length = _lib.EVP_PKEY_size(pkey._pkey)
3003 _openssl_assert(length > 0)
3004 signature_buffer = _ffi.new("unsigned char[]", length)
3005 signature_length = _ffi.new("unsigned int *")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003006 final_result = _lib.EVP_SignFinal(
Alex Gaynor03737182020-07-23 20:40:46 -04003007 md_ctx, signature_buffer, signature_length, pkey._pkey
3008 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04003009 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08003010
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003011 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08003012
3013
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08003014def verify(cert, signature, data, digest):
3015 """
Alex Chand072cae2018-02-15 09:57:59 +00003016 Verify the signature for a data string.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08003017
Alex Chand072cae2018-02-15 09:57:59 +00003018 :param cert: signing certificate (X509 object) corresponding to the
3019 private key which generated the signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08003020 :param signature: signature returned by sign function
3021 :param data: data to be verified
3022 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07003023 :return: ``None`` if the signature is correct, raise exception otherwise.
Alex Chand072cae2018-02-15 09:57:59 +00003024
3025 .. versionadded:: 0.11
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08003026 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04003027 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00003028
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003029 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003030 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08003031 raise ValueError("No such digest method")
3032
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003033 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07003034 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003035 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08003036
Alex Gaynor67903a62016-06-02 10:37:13 -07003037 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07003038 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08003039
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003040 _lib.EVP_VerifyInit(md_ctx, digest_obj)
3041 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04003042 verify_result = _lib.EVP_VerifyFinal(
3043 md_ctx, signature, len(signature), pkey
3044 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08003045
3046 if verify_result != 1:
3047 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08003048
3049
Dominic Chenf05b2122015-10-13 16:32:35 +00003050def dump_crl(type, crl):
3051 """
3052 Dump a certificate revocation list to a buffer.
3053
3054 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
3055 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02003056 :param CRL crl: The CRL to dump.
3057
Dominic Chenf05b2122015-10-13 16:32:35 +00003058 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07003059 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00003060 """
3061 bio = _new_mem_buf()
3062
3063 if type == FILETYPE_PEM:
3064 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
3065 elif type == FILETYPE_ASN1:
3066 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
3067 elif type == FILETYPE_TEXT:
3068 ret = _lib.X509_CRL_print(bio, crl._crl)
3069 else:
3070 raise ValueError(
3071 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
Alex Gaynor03737182020-07-23 20:40:46 -04003072 "FILETYPE_TEXT"
3073 )
Dominic Chenf05b2122015-10-13 16:32:35 +00003074
Adrián Chaves98c57be2020-03-31 16:14:50 +02003075 _openssl_assert(ret == 1)
Dominic Chenf05b2122015-10-13 16:32:35 +00003076 return _bio_to_string(bio)
3077
3078
Jean-Paul Calderone57122982013-02-21 08:47:05 -08003079def load_crl(type, buffer):
3080 """
Alex Chand072cae2018-02-15 09:57:59 +00003081 Load Certificate Revocation List (CRL) data from a string *buffer*.
3082 *buffer* encoded with the type *type*.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08003083
3084 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
3085 :param buffer: The buffer the CRL is stored in
3086
3087 :return: The PKey object
3088 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05003089 if isinstance(buffer, _text_type):
3090 buffer = buffer.encode("ascii")
3091
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08003092 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08003093
3094 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003095 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08003096 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003097 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08003098 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08003099 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
3100
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003101 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08003102 _raise_current_error()
3103
3104 result = CRL.__new__(CRL)
Jeremy Cline9e15eca2017-09-07 20:11:08 -04003105 result._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08003106 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003107
3108
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003109def load_pkcs7_data(type, buffer):
3110 """
Alex Chand072cae2018-02-15 09:57:59 +00003111 Load pkcs7 data from the string *buffer* encoded with the type
3112 *type*.
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003113
3114 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
3115 :param buffer: The buffer with the pkcs7 data.
3116 :return: The PKCS7 object
3117 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05003118 if isinstance(buffer, _text_type):
3119 buffer = buffer.encode("ascii")
3120
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08003121 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003122
3123 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003124 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003125 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07003126 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003127 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003128 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
3129
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003130 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08003131 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003132
3133 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003134 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08003135 return pypkcs7
3136
3137
Alex Gaynorbb971ae2020-08-05 01:14:16 -04003138load_pkcs7_data = utils.deprecated(
3139 load_pkcs7_data,
3140 __name__,
3141 (
3142 "PKCS#7 support in pyOpenSSL is deprecated. You should use the APIs "
3143 "in cryptography."
3144 ),
3145 DeprecationWarning,
3146)
3147
3148
Stephen Holsapple38482622014-04-05 20:29:34 -07003149def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003150 """
Alex Chand072cae2018-02-15 09:57:59 +00003151 Load pkcs12 data from the string *buffer*. If the pkcs12 structure is
3152 encrypted, a *passphrase* must be included. The MAC is always
3153 checked and thus required.
3154
3155 See also the man page for the C function :py:func:`PKCS12_parse`.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003156
3157 :param buffer: The buffer the certificate is stored in
3158 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
3159 :returns: The PKCS12 object
3160 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04003161 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00003162
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05003163 if isinstance(buffer, _text_type):
3164 buffer = buffer.encode("ascii")
3165
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08003166 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003167
Stephen Holsapple38482622014-04-05 20:29:34 -07003168 # Use null passphrase if passphrase is None or empty string. With PKCS#12
3169 # password based encryption no password and a zero length password are two
3170 # different things, but OpenSSL implementation will try both to figure out
3171 # which one works.
3172 if not passphrase:
3173 passphrase = _ffi.NULL
3174
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003175 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
3176 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003177 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003178 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003179
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003180 pkey = _ffi.new("EVP_PKEY**")
3181 cert = _ffi.new("X509**")
3182 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003183
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003184 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003185 if not parse_result:
3186 _raise_current_error()
3187
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003188 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08003189
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003190 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
3191 # queue for no particular reason. This error isn't interesting to anyone
3192 # outside this function. It's not even interesting to us. Get rid of it.
3193 try:
3194 _raise_current_error()
3195 except Error:
3196 pass
3197
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003198 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003199 pykey = None
3200 else:
3201 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003202 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003203
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003204 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003205 pycert = None
3206 friendlyname = None
3207 else:
Paul Kehrere7381862017-11-30 20:55:25 +08003208 pycert = X509._from_raw_x509_ptr(cert[0])
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003209
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003210 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04003211 friendlyname_buffer = _lib.X509_alias_get0(
3212 cert[0], friendlyname_length
3213 )
3214 friendlyname = _ffi.buffer(
3215 friendlyname_buffer, friendlyname_length[0]
3216 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003217 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003218 friendlyname = None
3219
3220 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003221 for i in range(_lib.sk_X509_num(cacerts)):
Paul Kehrere7381862017-11-30 20:55:25 +08003222 x509 = _lib.sk_X509_value(cacerts, i)
3223 pycacert = X509._from_raw_x509_ptr(x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003224 pycacerts.append(pycacert)
3225 if not pycacerts:
3226 pycacerts = None
3227
3228 pkcs12 = PKCS12.__new__(PKCS12)
3229 pkcs12._pkey = pykey
3230 pkcs12._cert = pycert
3231 pkcs12._cacerts = pycacerts
3232 pkcs12._friendlyname = friendlyname
3233 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05003234
3235
Alex Gaynorbb971ae2020-08-05 01:14:16 -04003236load_pkcs12 = utils.deprecated(
3237 load_pkcs12,
3238 __name__,
3239 (
3240 "PKCS#12 support in pyOpenSSL is deprecated. You should use the APIs "
3241 "in cryptography."
3242 ),
3243 DeprecationWarning,
3244)
3245
3246
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05003247# There are no direct unit tests for this initialization. It is tested
3248# indirectly since it is necessary for functions like dump_privatekey when
3249# using encryption.
3250#
3251# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
3252# and some other similar tests may fail without this (though they may not if
3253# the Python runtime has already done some initialization of the underlying
3254# OpenSSL library (and is linked against the same one that cryptography is
3255# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05003256_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05003257
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05003258# This is similar but exercised mainly by exception_from_error_queue. It calls
3259# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
3260_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003261
3262
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003263# Set the default string mask to match OpenSSL upstream (since 2005) and
3264# RFC5280 recommendations.
Alex Gaynor03737182020-07-23 20:40:46 -04003265_lib.ASN1_STRING_set_default_mask_asc(b"utf8only")