blob: b51e12ffe12a97e1f295601b95bc76337b6fdb1d [file] [log] [blame]
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001import datetime
Paul Kehrer8d887e12015-10-24 09:09:55 -05002
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003from base64 import b16encode
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05004from functools import partial
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05005from operator import __eq__, __ne__, __lt__, __le__, __gt__, __ge__
6
7from six import (
8 integer_types as _integer_types,
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -04009 text_type as _text_type,
Alex Gaynor26f1a922019-11-18 00:37:39 -050010 PY2 as _PY2)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080011
Alex Gaynor9939ba12017-06-25 16:28:24 -040012from cryptography import x509
Paul Kehrer72d968b2016-07-29 15:31:04 +080013from cryptography.hazmat.primitives.asymmetric import dsa, rsa
14
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050015from OpenSSL._util import (
16 ffi as _ffi,
17 lib as _lib,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050018 exception_from_error_queue as _exception_from_error_queue,
19 byte_string as _byte_string,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040020 native as _native,
21 UNSPECIFIED as _UNSPECIFIED,
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -040022 text_to_bytes_and_warn as _text_to_bytes_and_warn,
Alex Gaynor67903a62016-06-02 10:37:13 -070023 make_assert as _make_assert,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040024)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080025
Nicolas Karolak736c6212017-11-26 14:40:28 +010026__all__ = [
27 'FILETYPE_PEM',
28 'FILETYPE_ASN1',
29 'FILETYPE_TEXT',
30 'TYPE_RSA',
31 'TYPE_DSA',
32 'Error',
33 'PKey',
34 'get_elliptic_curves',
35 'get_elliptic_curve',
36 'X509Name',
37 'X509Extension',
38 'X509Req',
39 'X509',
40 'X509StoreFlags',
41 'X509Store',
42 'X509StoreContextError',
43 'X509StoreContext',
44 'load_certificate',
45 'dump_certificate',
46 'dump_publickey',
47 'dump_privatekey',
48 'Revoked',
49 'CRL',
50 'PKCS7',
51 'PKCS12',
52 'NetscapeSPKI',
53 'load_publickey',
54 'load_privatekey',
55 'dump_certificate_request',
56 'load_certificate_request',
57 'sign',
58 'verify',
59 'dump_crl',
60 'load_crl',
61 'load_pkcs7_data',
62 'load_pkcs12'
63]
64
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050065FILETYPE_PEM = _lib.SSL_FILETYPE_PEM
66FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080067
68# TODO This was an API mistake. OpenSSL has no such constant.
69FILETYPE_TEXT = 2 ** 16 - 1
70
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050071TYPE_RSA = _lib.EVP_PKEY_RSA
72TYPE_DSA = _lib.EVP_PKEY_DSA
Igr2f874f22019-01-21 21:39:37 +030073TYPE_DH = _lib.EVP_PKEY_DH
74TYPE_EC = _lib.EVP_PKEY_EC
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -080075
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080076
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050077class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050078 """
79 An error occurred in an `OpenSSL.crypto` API.
80 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050081
82
83_raise_current_error = partial(_exception_from_error_queue, Error)
Alex Gaynor67903a62016-06-02 10:37:13 -070084_openssl_assert = _make_assert(Error)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050085
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070086
Paul Kehrereb633842016-10-06 11:22:01 +020087def _get_backend():
88 """
89 Importing the backend from cryptography has the side effect of activating
90 the osrandom engine. This mutates the global state of OpenSSL in the
91 process and causes issues for various programs that use subinterpreters or
92 embed Python. By putting the import in this function we can avoid
93 triggering this side effect unless _get_backend is called.
94 """
95 from cryptography.hazmat.backends.openssl.backend import backend
96 return backend
97
98
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050099def _untested_error(where):
100 """
101 An OpenSSL API failed somehow. Additionally, the failure which was
102 encountered isn't one that's exercised by the test suite so future behavior
103 of pyOpenSSL is now somewhat less predictable.
104 """
105 raise RuntimeError("Unknown %s failure" % (where,))
106
107
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500108def _new_mem_buf(buffer=None):
109 """
110 Allocate a new OpenSSL memory BIO.
111
112 Arrange for the garbage collector to clean it up automatically.
113
114 :param buffer: None or some bytes to use to put into the BIO so that they
115 can be read out.
116 """
117 if buffer is None:
118 bio = _lib.BIO_new(_lib.BIO_s_mem())
119 free = _lib.BIO_free
120 else:
121 data = _ffi.new("char[]", buffer)
122 bio = _lib.BIO_new_mem_buf(data, len(buffer))
Alex Gaynor5945ea82015-09-05 14:59:06 -0400123
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500124 # Keep the memory alive as long as the bio is alive!
125 def free(bio, ref=data):
126 return _lib.BIO_free(bio)
127
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700128 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500129
130 bio = _ffi.gc(bio, free)
131 return bio
132
133
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800134def _bio_to_string(bio):
135 """
136 Copy the contents of an OpenSSL BIO object into a Python byte string.
137 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500138 result_buffer = _ffi.new('char**')
139 buffer_length = _lib.BIO_get_mem_data(bio, result_buffer)
140 return _ffi.buffer(result_buffer[0], buffer_length)[:]
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800141
142
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800143def _set_asn1_time(boundary, when):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500144 """
145 The the time value of an ASN1 time object.
146
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900147 @param boundary: An ASN1_TIME pointer (or an object safely
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500148 castable to that type) which will have its value set.
149 @param when: A string representation of the desired time value.
150
151 @raise TypeError: If C{when} is not a L{bytes} string.
152 @raise ValueError: If C{when} does not represent a time in the required
153 format.
154 @raise RuntimeError: If the time value cannot be set for some other
155 (unspecified) reason.
156 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800157 if not isinstance(when, bytes):
158 raise TypeError("when must be a byte string")
159
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900160 set_result = _lib.ASN1_TIME_set_string(boundary, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800161 if set_result == 0:
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900162 raise ValueError("Invalid string")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800163
Alex Gaynor510293e2016-06-02 12:07:59 -0700164
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800165def _get_asn1_time(timestamp):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500166 """
167 Retrieve the time value of an ASN1 time object.
168
169 @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to
170 that type) from which the time value will be retrieved.
171
172 @return: The time value from C{timestamp} as a L{bytes} string in a certain
173 format. Or C{None} if the object contains no time value.
174 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500175 string_timestamp = _ffi.cast('ASN1_STRING*', timestamp)
176 if _lib.ASN1_STRING_length(string_timestamp) == 0:
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800177 return None
Alex Gaynor5945ea82015-09-05 14:59:06 -0400178 elif (
179 _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME
180 ):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500181 return _ffi.string(_lib.ASN1_STRING_data(string_timestamp))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800182 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500183 generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**")
184 _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp)
185 if generalized_timestamp[0] == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500186 # This may happen:
187 # - if timestamp was not an ASN1_TIME
188 # - if allocating memory for the ASN1_GENERALIZEDTIME failed
189 # - if a copy of the time data from timestamp cannot be made for
190 # the newly allocated ASN1_GENERALIZEDTIME
191 #
192 # These are difficult to test. cffi enforces the ASN1_TIME type.
193 # Memory allocation failures are a pain to trigger
194 # deterministically.
195 _untested_error("ASN1_TIME_to_generalizedtime")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800196 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500197 string_timestamp = _ffi.cast(
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800198 "ASN1_STRING*", generalized_timestamp[0])
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500199 string_data = _lib.ASN1_STRING_data(string_timestamp)
200 string_result = _ffi.string(string_data)
201 _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0])
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800202 return string_result
203
204
Alex Gaynor4aa52c32017-11-20 09:04:08 -0500205class _X509NameInvalidator(object):
206 def __init__(self):
207 self._names = []
208
209 def add(self, name):
210 self._names.append(name)
211
212 def clear(self):
213 for name in self._names:
214 # Breaks the object, but also prevents UAF!
215 del name._name
216
217
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800218class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200219 """
220 A class representing an DSA or RSA public key or key pair.
221 """
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800222 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800223 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800224
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800225 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500226 pkey = _lib.EVP_PKEY_new()
227 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800228 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800229
Paul Kehrer72d968b2016-07-29 15:31:04 +0800230 def to_cryptography_key(self):
231 """
232 Export as a ``cryptography`` key.
233
234 :rtype: One of ``cryptography``'s `key interfaces`_.
235
236 .. _key interfaces: https://cryptography.io/en/latest/hazmat/\
237 primitives/asymmetric/rsa/#key-interfaces
238
239 .. versionadded:: 16.1.0
240 """
Paul Kehrereb633842016-10-06 11:22:01 +0200241 backend = _get_backend()
Paul Kehrer72d968b2016-07-29 15:31:04 +0800242 if self._only_public:
243 return backend._evp_pkey_to_public_key(self._pkey)
244 else:
245 return backend._evp_pkey_to_private_key(self._pkey)
246
247 @classmethod
248 def from_cryptography_key(cls, crypto_key):
249 """
250 Construct based on a ``cryptography`` *crypto_key*.
251
252 :param crypto_key: A ``cryptography`` key.
253 :type crypto_key: One of ``cryptography``'s `key interfaces`_.
254
255 :rtype: PKey
256
257 .. versionadded:: 16.1.0
258 """
259 pkey = cls()
260 if not isinstance(crypto_key, (rsa.RSAPublicKey, rsa.RSAPrivateKey,
261 dsa.DSAPublicKey, dsa.DSAPrivateKey)):
262 raise TypeError("Unsupported key type")
263
264 pkey._pkey = crypto_key._evp_pkey
265 if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)):
266 pkey._only_public = True
267 pkey._initialized = True
268 return pkey
269
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800270 def generate_key(self, type, bits):
271 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700272 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800273
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200274 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800275
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200276 :param type: The key type.
277 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
278 :param bits: The number of bits.
279 :type bits: :py:data:`int` ``>= 0``
280 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
281 of the appropriate type.
282 :raises ValueError: If the number of bits isn't an integer of
283 the appropriate size.
Dan Sully44e767a2016-06-04 18:05:27 -0700284 :return: ``None``
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800285 """
286 if not isinstance(type, int):
287 raise TypeError("type must be an integer")
288
289 if not isinstance(bits, int):
290 raise TypeError("bits must be an integer")
291
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800292 if type == TYPE_RSA:
293 if bits <= 0:
294 raise ValueError("Invalid number of bits")
295
David Benjamin179eb1d2018-06-05 17:56:07 -0400296 # TODO Check error return
297 exponent = _lib.BN_new()
298 exponent = _ffi.gc(exponent, _lib.BN_free)
299 _lib.BN_set_word(exponent, _lib.RSA_F4)
300
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500301 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800302
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500303 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400304 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800305
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500306 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400307 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800308
309 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400310 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700311 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400312
313 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400314 res = _lib.DSA_generate_parameters_ex(
315 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
316 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700317 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400318
319 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
320 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800321 else:
322 raise Error("No such key type")
323
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800324 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800325
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800326 def check(self):
327 """
328 Check the consistency of an RSA private key.
329
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200330 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
331
Hynek Schlawack01c31672016-12-11 15:14:09 +0100332 :return: ``True`` if key is consistent.
333
334 :raise OpenSSL.crypto.Error: if the key is inconsistent.
335
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800336 :raise TypeError: if the key is of a type which cannot be checked.
337 Only RSA keys can currently be checked.
338 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800339 if self._only_public:
340 raise TypeError("public key only")
341
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100342 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800343 raise TypeError("key type unsupported")
344
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500345 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
346 rsa = _ffi.gc(rsa, _lib.RSA_free)
347 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800348 if result:
349 return True
350 _raise_current_error()
351
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800352 def type(self):
353 """
354 Returns the type of the key
355
356 :return: The type of the key.
357 """
Alex Gaynor0d2aec52017-05-31 04:26:27 -0400358 return _lib.EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800359
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800360 def bits(self):
361 """
362 Returns the number of bits of the key
363
364 :return: The number of bits of the key.
365 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500366 return _lib.EVP_PKEY_bits(self._pkey)
Alex Chanc6077062016-11-18 13:53:39 +0000367
368
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400369class _EllipticCurve(object):
370 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400371 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400372
373 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
374 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
375 instances each of which represents one curve supported by the system.
376 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400377 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400378 _curves = None
379
Alex Gaynor26f1a922019-11-18 00:37:39 -0500380 if not _PY2:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400381 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400382 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400383 """
384 Implement cooperation with the right-hand side argument of ``!=``.
385
386 Python 3 seems to have dropped this cooperation in this very narrow
387 circumstance.
388 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400389 if isinstance(other, _EllipticCurve):
390 return super(_EllipticCurve, self).__ne__(other)
391 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400392
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400393 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400394 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400395 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400396 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400397
398 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400399
400 :return: A :py:type:`set` of ``cls`` instances giving the names of the
401 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400402 """
Alex Chan84902a22017-04-20 11:50:47 +0100403 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
404 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
405 # The return value on this call should be num_curves again. We
406 # could check it to make sure but if it *isn't* then.. what could
407 # we do? Abort the whole process, I suppose...? -exarkun
408 lib.EC_get_builtin_curves(builtin_curves, num_curves)
409 return set(
410 cls.from_nid(lib, c.nid)
411 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400412
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400413 @classmethod
414 def _get_elliptic_curves(cls, lib):
415 """
416 Get, cache, and return the curves supported by OpenSSL.
417
418 :param lib: The OpenSSL library binding object.
419
420 :return: A :py:type:`set` of ``cls`` instances giving the names of the
421 elliptic curves the underlying library supports.
422 """
423 if cls._curves is None:
424 cls._curves = cls._load_elliptic_curves(lib)
425 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400426
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400427 @classmethod
428 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400429 """
430 Instantiate a new :py:class:`_EllipticCurve` associated with the given
431 OpenSSL NID.
432
433 :param lib: The OpenSSL library binding object.
434
435 :param nid: The OpenSSL NID the resulting curve object will represent.
436 This must be a curve NID (and not, for example, a hash NID) or
437 subsequent operations will fail in unpredictable ways.
438 :type nid: :py:class:`int`
439
440 :return: The curve object.
441 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400442 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
443
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400444 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400445 """
446 :param _lib: The :py:mod:`cryptography` binding instance used to
447 interface with OpenSSL.
448
449 :param _nid: The OpenSSL NID identifying the curve this object
450 represents.
451 :type _nid: :py:class:`int`
452
453 :param name: The OpenSSL short name identifying the curve this object
454 represents.
455 :type name: :py:class:`unicode`
456 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400457 self._lib = lib
458 self._nid = nid
459 self.name = name
460
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400461 def __repr__(self):
462 return "<Curve %r>" % (self.name,)
463
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400464 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400465 """
466 Create a new OpenSSL EC_KEY structure initialized to use this curve.
467
468 The structure is automatically garbage collected when the Python object
469 is garbage collected.
470 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400471 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
472 return _ffi.gc(key, _lib.EC_KEY_free)
473
474
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400475def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400476 """
477 Return a set of objects representing the elliptic curves supported in the
478 OpenSSL build in use.
479
480 The curve objects have a :py:class:`unicode` ``name`` attribute by which
481 they identify themselves.
482
483 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400484 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
485 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400486 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400487 return _EllipticCurve._get_elliptic_curves(_lib)
488
489
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400490def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400491 """
492 Return a single curve object selected by name.
493
494 See :py:func:`get_elliptic_curves` for information about curve objects.
495
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400496 :param name: The OpenSSL short name identifying the curve object to
497 retrieve.
498 :type name: :py:class:`unicode`
499
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400500 If the named curve is not supported then :py:class:`ValueError` is raised.
501 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400502 for curve in get_elliptic_curves():
503 if curve.name == name:
504 return curve
505 raise ValueError("unknown curve name", name)
506
507
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800508class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200509 """
510 An X.509 Distinguished Name.
511
512 :ivar countryName: The country of the entity.
513 :ivar C: Alias for :py:attr:`countryName`.
514
515 :ivar stateOrProvinceName: The state or province of the entity.
516 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
517
518 :ivar localityName: The locality of the entity.
519 :ivar L: Alias for :py:attr:`localityName`.
520
521 :ivar organizationName: The organization name of the entity.
522 :ivar O: Alias for :py:attr:`organizationName`.
523
524 :ivar organizationalUnitName: The organizational unit of the entity.
525 :ivar OU: Alias for :py:attr:`organizationalUnitName`
526
527 :ivar commonName: The common name of the entity.
528 :ivar CN: Alias for :py:attr:`commonName`.
529
530 :ivar emailAddress: The e-mail address of the entity.
531 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400532
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800533 def __init__(self, name):
534 """
535 Create a new X509Name, copying the given X509Name instance.
536
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200537 :param name: The name to copy.
538 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800539 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500540 name = _lib.X509_NAME_dup(name._name)
541 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800542
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800543 def __setattr__(self, name, value):
544 if name.startswith('_'):
545 return super(X509Name, self).__setattr__(name, value)
546
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800547 # Note: we really do not want str subclasses here, so we do not use
548 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800549 if type(name) is not str:
550 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400551 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800552
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500553 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500554 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800555 try:
556 _raise_current_error()
557 except Error:
558 pass
559 raise AttributeError("No such attribute")
560
561 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500562 for i in range(_lib.X509_NAME_entry_count(self._name)):
563 ent = _lib.X509_NAME_get_entry(self._name, i)
564 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
565 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800566 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500567 ent = _lib.X509_NAME_delete_entry(self._name, i)
568 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800569 break
570
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500571 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800572 value = value.encode('utf-8')
573
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500574 add_result = _lib.X509_NAME_add_entry_by_NID(
575 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800576 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500577 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800578
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800579 def __getattr__(self, name):
580 """
581 Find attribute. An X509Name object has the following attributes:
582 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400583 organization (alias O), organizationalUnit (alias OU), commonName
584 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800585 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500586 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500587 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800588 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
589 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
590 # push something onto the error queue. If we don't clean that up
591 # now, someone else will bump into it later and be quite confused.
592 # See lp#314814.
593 try:
594 _raise_current_error()
595 except Error:
596 pass
597 return super(X509Name, self).__getattr__(name)
598
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500599 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800600 if entry_index == -1:
601 return None
602
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500603 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
604 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800605
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500606 result_buffer = _ffi.new("unsigned char**")
607 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400608 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800609
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700610 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400611 result = _ffi.buffer(
612 result_buffer[0], data_length
613 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700614 finally:
615 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500616 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800617 return result
618
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500619 def _cmp(op):
620 def f(self, other):
621 if not isinstance(other, X509Name):
622 return NotImplemented
623 result = _lib.X509_NAME_cmp(self._name, other._name)
624 return op(result, 0)
625 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800626
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500627 __eq__ = _cmp(__eq__)
628 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800629
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500630 __lt__ = _cmp(__lt__)
631 __le__ = _cmp(__le__)
632
633 __gt__ = _cmp(__gt__)
634 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800635
636 def __repr__(self):
637 """
638 String representation of an X509Name
639 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400640 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500641 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800642 self._name, result_buffer, len(result_buffer))
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700643 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800644
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500645 return "<X509Name object '%s'>" % (
646 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800647
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800648 def hash(self):
649 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200650 Return an integer representation of the first four bytes of the
651 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800652
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200653 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
654
655 :return: The (integer) hash of this name.
656 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800657 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500658 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800659
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800660 def der(self):
661 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200662 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800663
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200664 :return: The DER encoded form of this name.
665 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800666 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500667 result_buffer = _ffi.new('unsigned char**')
668 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400669 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800670
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500671 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
672 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800673 return string_result
674
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800675 def get_components(self):
676 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200677 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800678
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200679 :return: The components of this name.
680 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800681 """
682 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500683 for i in range(_lib.X509_NAME_entry_count(self._name)):
684 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800685
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500686 fname = _lib.X509_NAME_ENTRY_get_object(ent)
687 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800688
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500689 nid = _lib.OBJ_obj2nid(fname)
690 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800691
Romuald Brunet4183beb2019-01-21 19:38:33 +0100692 # ffi.string does not handle strings containing NULL bytes
693 # (which may have been generated by old, broken software)
694 value = _ffi.buffer(_lib.ASN1_STRING_data(fval),
695 _lib.ASN1_STRING_length(fval))[:]
696 result.append((_ffi.string(name), value))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800697
698 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200699
700
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800701class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200702 """
703 An X.509 v3 certificate extension.
704 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400705
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800706 def __init__(self, type_name, critical, value, subject=None, issuer=None):
707 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200708 Initializes an X509 extension.
709
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100710 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400711 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800712
Alex Gaynor5945ea82015-09-05 14:59:06 -0400713 :param bool critical: A flag indicating whether this is a critical
714 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800715
716 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200717 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800718
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200719 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800720 :type subject: :py:class:`X509`
721
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200722 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800723 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100724
Alex Chan54005ce2017-03-21 08:08:17 +0000725 .. _extension: https://www.openssl.org/docs/manmaster/man5/
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100726 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800727 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500728 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800729
Alex Gaynor5945ea82015-09-05 14:59:06 -0400730 # A context is necessary for any extension which uses the r2i
731 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
732 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500733 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800734
735 # We have no configuration database - but perhaps we should (some
736 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500737 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800738
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800739 # Initialize the subject and issuer, if appropriate. ctx is a local,
740 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400741 # any references, so no need to mess with reference counts or
742 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800743 if issuer is not None:
744 if not isinstance(issuer, X509):
745 raise TypeError("issuer must be an X509 instance")
746 ctx.issuer_cert = issuer._x509
747 if subject is not None:
748 if not isinstance(subject, X509):
749 raise TypeError("subject must be an X509 instance")
750 ctx.subject_cert = subject._x509
751
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800752 if critical:
753 # There are other OpenSSL APIs which would let us pass in critical
754 # separately, but they're harder to use, and since value is already
755 # a pile of crappy junk smuggling a ton of utterly important
756 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400757 # with strings? (However, X509V3_EXT_i2d in particular seems like
758 # it would be a better API to invoke. I do not know where to get
759 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500760 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800761
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500762 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
763 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800764 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500765 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800766
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400767 @property
768 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400769 return _lib.OBJ_obj2nid(
770 _lib.X509_EXTENSION_get_object(self._extension)
771 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400772
773 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500774 _lib.GEN_EMAIL: "email",
775 _lib.GEN_DNS: "DNS",
776 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400777 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400778
779 def _subjectAltNameString(self):
Alex Gaynord61c46a2017-06-29 22:51:33 -0700780 names = _ffi.cast(
781 "GENERAL_NAMES*", _lib.X509V3_EXT_d2i(self._extension)
782 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400783
Paul Kehrerb7d79502015-05-04 07:43:51 -0500784 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400785 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500786 for i in range(_lib.sk_GENERAL_NAME_num(names)):
787 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400788 try:
789 label = self._prefixes[name.type]
790 except KeyError:
791 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500792 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500793 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400794 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500795 value = _native(
796 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
797 parts.append(label + ":" + value)
798 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400799
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800800 def __str__(self):
801 """
802 :return: a nice text representation of the extension
803 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500804 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400805 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800806
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400807 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500808 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400809 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800810
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500811 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800812
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800813 def get_critical(self):
814 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200815 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800816
817 :return: The critical field.
818 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500819 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800820
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800821 def get_short_name(self):
822 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200823 Returns the short type name of this X.509 extension.
824
825 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800826
827 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200828 :rtype: :py:data:`bytes`
829
830 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800831 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500832 obj = _lib.X509_EXTENSION_get_object(self._extension)
833 nid = _lib.OBJ_obj2nid(obj)
834 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800835
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800836 def get_data(self):
837 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200838 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800839
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200840 :return: The ASN.1 encoded data of this X509 extension.
841 :rtype: :py:data:`bytes`
842
843 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800844 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500845 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
846 string_result = _ffi.cast('ASN1_STRING*', octet_result)
847 char_result = _lib.ASN1_STRING_data(string_result)
848 result_length = _lib.ASN1_STRING_length(string_result)
849 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800850
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200851
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800852class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200853 """
854 An X.509 certificate signing requests.
855 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400856
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800857 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500858 req = _lib.X509_REQ_new()
859 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Alex Gaynor5af32d02016-09-24 01:52:21 -0400860 # Default to version 0.
861 self.set_version(0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800862
Paul Kehrer41c10242017-06-29 18:24:17 -0500863 def to_cryptography(self):
864 """
865 Export as a ``cryptography`` certificate signing request.
866
867 :rtype: ``cryptography.x509.CertificateSigningRequest``
868
869 .. versionadded:: 17.1.0
870 """
871 from cryptography.hazmat.backends.openssl.x509 import (
872 _CertificateSigningRequest
873 )
874 backend = _get_backend()
875 return _CertificateSigningRequest(backend, self._req)
876
877 @classmethod
878 def from_cryptography(cls, crypto_req):
879 """
880 Construct based on a ``cryptography`` *crypto_req*.
881
882 :param crypto_req: A ``cryptography`` X.509 certificate signing request
883 :type crypto_req: ``cryptography.x509.CertificateSigningRequest``
884
Gaurav Malhotra4121e252019-01-22 00:09:19 +0530885 :rtype: X509Req
Paul Kehrer41c10242017-06-29 18:24:17 -0500886
887 .. versionadded:: 17.1.0
888 """
889 if not isinstance(crypto_req, x509.CertificateSigningRequest):
890 raise TypeError("Must be a certificate signing request")
891
892 req = cls()
893 req._req = crypto_req._x509_req
894 return req
895
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800896 def set_pubkey(self, pkey):
897 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200898 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800899
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200900 :param pkey: The public key to use.
901 :type pkey: :py:class:`PKey`
902
Dan Sully44e767a2016-06-04 18:05:27 -0700903 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800904 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500905 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400906 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800907
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800908 def get_pubkey(self):
909 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200910 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800911
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200912 :return: The public key.
913 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800914 """
915 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500916 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700917 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500918 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800919 pkey._only_public = True
920 return pkey
921
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800922 def set_version(self, version):
923 """
924 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
925 request.
926
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200927 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700928 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800929 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500930 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400931 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800932
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800933 def get_version(self):
934 """
935 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
936 request.
937
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200938 :return: The value of the version subfield.
939 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800940 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500941 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800942
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800943 def get_subject(self):
944 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200945 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800946
Cory Benfield881dc8d2015-12-09 08:25:14 +0000947 This creates a new :class:`X509Name` that wraps the underlying subject
948 name field on the certificate signing request. Modifying it will modify
949 the underlying signing request, and will have the effect of modifying
950 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200951
952 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000953 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800954 """
955 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500956 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700957 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800958
959 # The name is owned by the X509Req structure. As long as the X509Name
960 # Python object is alive, keep the X509Req Python object alive.
961 name._owner = self
962
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800963 return name
964
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800965 def add_extensions(self, extensions):
966 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200967 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800968
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200969 :param extensions: The X.509 extensions to add.
970 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700971 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800972 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500973 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700974 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800975
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500976 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800977
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800978 for ext in extensions:
979 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -0800980 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800981
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800982 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500983 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800984
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500985 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400986 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800987
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800988 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800989 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200990 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800991
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200992 :return: The X.509 extensions in this request.
993 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
994
995 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800996 """
997 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500998 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -0500999 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001000 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -05001001 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -08001002 exts.append(ext)
1003 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -08001004
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001005 def sign(self, pkey, digest):
1006 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001007 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001008
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001009 :param pkey: The key pair to sign with.
1010 :type pkey: :py:class:`PKey`
1011 :param digest: The name of the message digest to use for the signature,
Alex Gaynor239e2d32016-09-11 12:36:35 -04001012 e.g. :py:data:`b"sha256"`.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001013 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -07001014 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001015 """
1016 if pkey._only_public:
1017 raise ValueError("Key has only public part")
1018
1019 if not pkey._initialized:
1020 raise ValueError("Key is uninitialized")
1021
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001022 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001023 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001024 raise ValueError("No such digest method")
1025
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001026 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001027 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -08001028
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001029 def verify(self, pkey):
1030 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +02001031 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001032
Hynek Schlawack01c31672016-12-11 15:14:09 +01001033 :param PKey key: A public key.
1034
1035 :return: ``True`` if the signature is correct.
1036 :rtype: bool
1037
1038 :raises OpenSSL.crypto.Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001039 problem verifying the signature.
1040 """
1041 if not isinstance(pkey, PKey):
1042 raise TypeError("pkey must be a PKey instance")
1043
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001044 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001045 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001046 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -08001047
1048 return result
1049
1050
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001051class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001052 """
1053 An X.509 certificate.
1054 """
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001055 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001056 x509 = _lib.X509_new()
Hynek Schlawack8a2dd772016-07-31 13:46:20 +02001057 _openssl_assert(x509 != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001058 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001059
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001060 self._issuer_invalidator = _X509NameInvalidator()
1061 self._subject_invalidator = _X509NameInvalidator()
1062
1063 @classmethod
1064 def _from_raw_x509_ptr(cls, x509):
1065 cert = cls.__new__(cls)
1066 cert._x509 = _ffi.gc(x509, _lib.X509_free)
1067 cert._issuer_invalidator = _X509NameInvalidator()
1068 cert._subject_invalidator = _X509NameInvalidator()
1069 return cert
1070
Alex Gaynor9939ba12017-06-25 16:28:24 -04001071 def to_cryptography(self):
1072 """
1073 Export as a ``cryptography`` certificate.
1074
1075 :rtype: ``cryptography.x509.Certificate``
1076
1077 .. versionadded:: 17.1.0
1078 """
1079 from cryptography.hazmat.backends.openssl.x509 import _Certificate
1080 backend = _get_backend()
1081 return _Certificate(backend, self._x509)
1082
1083 @classmethod
1084 def from_cryptography(cls, crypto_cert):
1085 """
1086 Construct based on a ``cryptography`` *crypto_cert*.
1087
1088 :param crypto_key: A ``cryptography`` X.509 certificate.
1089 :type crypto_key: ``cryptography.x509.Certificate``
1090
Gaurav Malhotra4121e252019-01-22 00:09:19 +05301091 :rtype: X509
Alex Gaynor9939ba12017-06-25 16:28:24 -04001092
1093 .. versionadded:: 17.1.0
1094 """
1095 if not isinstance(crypto_cert, x509.Certificate):
1096 raise TypeError("Must be a certificate")
1097
1098 cert = cls()
1099 cert._x509 = crypto_cert._x509
1100 return cert
1101
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001102 def set_version(self, version):
1103 """
Cyril Stoller6f25ced2018-08-27 13:37:51 +02001104 Set the version number of the certificate. Note that the
1105 version value is zero-based, eg. a value of 0 is V1.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001106
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001107 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001108 :type version: :py:class:`int`
1109
Dan Sully44e767a2016-06-04 18:05:27 -07001110 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001111 """
1112 if not isinstance(version, int):
1113 raise TypeError("version must be an integer")
1114
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001115 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001116
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001117 def get_version(self):
1118 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001119 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001120
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001121 :return: The version number of the certificate.
1122 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001123 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001124 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001125
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001126 def get_pubkey(self):
1127 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001128 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001129
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001130 :return: The public key.
1131 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001132 """
1133 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001134 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1135 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001136 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001137 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001138 pkey._only_public = True
1139 return pkey
1140
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001141 def set_pubkey(self, pkey):
1142 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001143 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001144
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001145 :param pkey: The public key.
1146 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001147
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001148 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001149 """
1150 if not isinstance(pkey, PKey):
1151 raise TypeError("pkey must be a PKey instance")
1152
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001153 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001154 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001155
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001156 def sign(self, pkey, digest):
1157 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001158 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001159
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001160 :param pkey: The key to sign with.
1161 :type pkey: :py:class:`PKey`
1162
1163 :param digest: The name of the message digest to use.
1164 :type digest: :py:class:`bytes`
1165
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001166 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001167 """
1168 if not isinstance(pkey, PKey):
1169 raise TypeError("pkey must be a PKey instance")
1170
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001171 if pkey._only_public:
1172 raise ValueError("Key only has public part")
1173
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001174 if not pkey._initialized:
1175 raise ValueError("Key is uninitialized")
1176
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001177 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001178 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001179 raise ValueError("No such digest method")
1180
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001181 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001182 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001183
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001184 def get_signature_algorithm(self):
1185 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001186 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001187
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001188 :return: The name of the algorithm.
1189 :rtype: :py:class:`bytes`
1190
1191 :raises ValueError: If the signature algorithm is undefined.
1192
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001193 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001194 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001195 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1196 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001197 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001198 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001199 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001200
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001201 def digest(self, digest_name):
1202 """
1203 Return the digest of the X509 object.
1204
1205 :param digest_name: The name of the digest algorithm to use.
1206 :type digest_name: :py:class:`bytes`
1207
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001208 :return: The digest of the object, formatted as
1209 :py:const:`b":"`-delimited hex pairs.
1210 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001211 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001212 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001213 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001214 raise ValueError("No such digest method")
1215
Paul Kehrer9f9113a2016-09-20 20:10:25 -05001216 result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001217 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001218 result_length[0] = len(result_buffer)
1219
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001220 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001221 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001222 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001223
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001224 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001225 b16encode(ch).upper() for ch
1226 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001227
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001228 def subject_name_hash(self):
1229 """
1230 Return the hash of the X509 subject.
1231
1232 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001233 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001234 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001235 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001236
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001237 def set_serial_number(self, serial):
1238 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001239 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001240
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001241 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001242 :type serial: :py:class:`int`
1243
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001244 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001245 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001246 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001247 raise TypeError("serial must be an integer")
1248
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001249 hex_serial = hex(serial)[2:]
1250 if not isinstance(hex_serial, bytes):
1251 hex_serial = hex_serial.encode('ascii')
1252
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001253 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001254
1255 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001256 # it. If bignum is still NULL after this call, then the return value
1257 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001258 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001259
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001260 if bignum_serial[0] == _ffi.NULL:
1261 set_result = _lib.ASN1_INTEGER_set(
1262 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001263 if set_result:
1264 # TODO Not tested
1265 _raise_current_error()
1266 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001267 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1268 _lib.BN_free(bignum_serial[0])
1269 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001270 # TODO Not tested
1271 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001272 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1273 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001274 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001275
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001276 def get_serial_number(self):
1277 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001278 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001279
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001280 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001281 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001282 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001283 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1284 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001285 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001286 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001287 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001288 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001289 serial = int(hexstring_serial, 16)
1290 return serial
1291 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001292 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001293 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001294 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001295
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001296 def gmtime_adj_notAfter(self, amount):
1297 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001298 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001299
Dan Sully44e767a2016-06-04 18:05:27 -07001300 :param int amount: The number of seconds by which to adjust the
1301 timestamp.
1302 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001303 """
1304 if not isinstance(amount, int):
1305 raise TypeError("amount must be an integer")
1306
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001307 notAfter = _lib.X509_get_notAfter(self._x509)
1308 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001309
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001310 def gmtime_adj_notBefore(self, amount):
1311 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001312 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001313
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001314 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001315 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001316 """
1317 if not isinstance(amount, int):
1318 raise TypeError("amount must be an integer")
1319
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001320 notBefore = _lib.X509_get_notBefore(self._x509)
1321 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001322
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001323 def has_expired(self):
1324 """
1325 Check whether the certificate has expired.
1326
Dan Sully44e767a2016-06-04 18:05:27 -07001327 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1328 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001329 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001330 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001331 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001332
Paul Kehrerfde45c92016-01-21 12:57:37 -06001333 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001334
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001335 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001336 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001337
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001338 def get_notBefore(self):
1339 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001340 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001341
Paul Kehrerce98ee62017-06-21 06:59:58 -10001342 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001343
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001344 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001345
Dan Sully44e767a2016-06-04 18:05:27 -07001346 :return: A timestamp string, or ``None`` if there is none.
1347 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001348 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001349 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001350
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001351 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001352 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001353
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001354 def set_notBefore(self, when):
1355 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001356 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001357
Paul Kehrerce98ee62017-06-21 06:59:58 -10001358 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001359
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001360 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001361
Dan Sully44e767a2016-06-04 18:05:27 -07001362 :param bytes when: A timestamp string.
1363 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001364 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001365 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001366
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001367 def get_notAfter(self):
1368 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001369 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001370
Paul Kehrerce98ee62017-06-21 06:59:58 -10001371 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001372
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001373 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001374
Dan Sully44e767a2016-06-04 18:05:27 -07001375 :return: A timestamp string, or ``None`` if there is none.
1376 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001377 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001378 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001379
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001380 def set_notAfter(self, when):
1381 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001382 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001383
Paul Kehrerce98ee62017-06-21 06:59:58 -10001384 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001385
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001386 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001387
Dan Sully44e767a2016-06-04 18:05:27 -07001388 :param bytes when: A timestamp string.
1389 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001390 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001391 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001392
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001393 def _get_name(self, which):
1394 name = X509Name.__new__(X509Name)
1395 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001396 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001397
1398 # The name is owned by the X509 structure. As long as the X509Name
1399 # Python object is alive, keep the X509 Python object alive.
1400 name._owner = self
1401
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001402 return name
1403
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001404 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001405 if not isinstance(name, X509Name):
1406 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001407 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001408 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001409
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001410 def get_issuer(self):
1411 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001412 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001413
Cory Benfielde6bcce82015-12-09 08:40:03 +00001414 This creates a new :class:`X509Name` that wraps the underlying issuer
1415 name field on the certificate. Modifying it will modify the underlying
1416 certificate, and will have the effect of modifying any other
1417 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001418
1419 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001420 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001421 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001422 name = self._get_name(_lib.X509_get_issuer_name)
1423 self._issuer_invalidator.add(name)
1424 return name
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001425
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001426 def set_issuer(self, issuer):
1427 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001428 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001429
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001430 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001431 :type issuer: :py:class:`X509Name`
1432
Dan Sully44e767a2016-06-04 18:05:27 -07001433 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001434 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001435 self._set_name(_lib.X509_set_issuer_name, issuer)
1436 self._issuer_invalidator.clear()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001437
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001438 def get_subject(self):
1439 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001440 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001441
Cory Benfielde6bcce82015-12-09 08:40:03 +00001442 This creates a new :class:`X509Name` that wraps the underlying subject
1443 name field on the certificate. Modifying it will modify the underlying
1444 certificate, and will have the effect of modifying any other
1445 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001446
1447 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001448 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001449 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001450 name = self._get_name(_lib.X509_get_subject_name)
1451 self._subject_invalidator.add(name)
1452 return name
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001453
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001454 def set_subject(self, subject):
1455 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001456 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001457
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001458 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001459 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001460
Dan Sully44e767a2016-06-04 18:05:27 -07001461 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001462 """
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001463 self._set_name(_lib.X509_set_subject_name, subject)
1464 self._subject_invalidator.clear()
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001465
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001466 def get_extension_count(self):
1467 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001468 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001469
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001470 :return: The number of extensions.
1471 :rtype: :py:class:`int`
1472
1473 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001474 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001475 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001476
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001477 def add_extensions(self, extensions):
1478 """
1479 Add extensions to the certificate.
1480
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001481 :param extensions: The extensions to add.
1482 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001483 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001484 """
1485 for ext in extensions:
1486 if not isinstance(ext, X509Extension):
1487 raise ValueError("One of the elements is not an X509Extension")
1488
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001489 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001490 if not add_result:
1491 _raise_current_error()
1492
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001493 def get_extension(self, index):
1494 """
1495 Get a specific extension of the certificate by index.
1496
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001497 Extensions on a certificate are kept in order. The index
1498 parameter selects which extension will be returned.
1499
1500 :param int index: The index of the extension to retrieve.
1501 :return: The extension at the specified index.
1502 :rtype: :py:class:`X509Extension`
1503 :raises IndexError: If the extension index was out of bounds.
1504
1505 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001506 """
1507 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001508 ext._extension = _lib.X509_get_ext(self._x509, index)
1509 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001510 raise IndexError("extension index out of bounds")
1511
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001512 extension = _lib.X509_EXTENSION_dup(ext._extension)
1513 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001514 return ext
1515
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001516
Dan Sully44e767a2016-06-04 18:05:27 -07001517class X509StoreFlags(object):
1518 """
1519 Flags for X509 verification, used to change the behavior of
1520 :class:`X509Store`.
1521
1522 See `OpenSSL Verification Flags`_ for details.
1523
1524 .. _OpenSSL Verification Flags:
Alex Chan54005ce2017-03-21 08:08:17 +00001525 https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_flags.html
Dan Sully44e767a2016-06-04 18:05:27 -07001526 """
1527 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1528 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1529 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1530 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1531 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1532 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1533 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1534 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1535 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1536 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1537 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1538
1539
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001540class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001541 """
Dan Sully44e767a2016-06-04 18:05:27 -07001542 An X.509 store.
1543
1544 An X.509 store is used to describe a context in which to verify a
1545 certificate. A description of a context may include a set of certificates
1546 to trust, a set of certificate revocation lists, verification flags and
1547 more.
1548
1549 An X.509 store, being only a description, cannot be used by itself to
1550 verify a certificate. To carry out the actual verification process, see
1551 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001552 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001553
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001554 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001555 store = _lib.X509_STORE_new()
1556 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001557
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001558 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001559 """
Dan Sully44e767a2016-06-04 18:05:27 -07001560 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001561
Dan Sully44e767a2016-06-04 18:05:27 -07001562 Adding a certificate with this method adds this certificate as a
1563 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001564
1565 :param X509 cert: The certificate to add to this store.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001566
Dan Sully44e767a2016-06-04 18:05:27 -07001567 :raises TypeError: If the certificate is not an :class:`X509`.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001568
1569 :raises OpenSSL.crypto.Error: If OpenSSL was unhappy with your
1570 certificate.
1571
Dan Sully44e767a2016-06-04 18:05:27 -07001572 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001573 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001574 if not isinstance(cert, X509):
1575 raise TypeError()
1576
Paul Kehrer0e6c5532018-08-23 10:52:15 -05001577 # As of OpenSSL 1.1.0i adding the same cert to the store more than
1578 # once doesn't cause an error. Accordingly, this code now silences
1579 # the error for OpenSSL < 1.1.0i as well.
1580 if _lib.X509_STORE_add_cert(self._store, cert._x509) == 0:
1581 code = _lib.ERR_peek_error()
1582 err_reason = _lib.ERR_GET_REASON(code)
1583 _openssl_assert(
1584 err_reason == _lib.X509_R_CERT_ALREADY_IN_HASH_TABLE
1585 )
1586 _lib.ERR_clear_error()
Dan Sully44e767a2016-06-04 18:05:27 -07001587
1588 def add_crl(self, crl):
1589 """
1590 Add a certificate revocation list to this store.
1591
1592 The certificate revocation lists added to a store will only be used if
1593 the associated flags are configured to check certificate revocation
1594 lists.
1595
1596 .. versionadded:: 16.1.0
1597
1598 :param CRL crl: The certificate revocation list to add to this store.
1599 :return: ``None`` if the certificate revocation list was added
1600 successfully.
1601 """
1602 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1603
1604 def set_flags(self, flags):
1605 """
1606 Set verification flags to this store.
1607
1608 Verification flags can be combined by oring them together.
1609
1610 .. note::
1611
1612 Setting a verification flag sometimes requires clients to add
1613 additional information to the store, otherwise a suitable error will
1614 be raised.
1615
1616 For example, in setting flags to enable CRL checking a
1617 suitable CRL must be added to the store otherwise an error will be
1618 raised.
1619
1620 .. versionadded:: 16.1.0
1621
1622 :param int flags: The verification flags to set on this store.
1623 See :class:`X509StoreFlags` for available constants.
1624 :return: ``None`` if the verification flags were successfully set.
1625 """
1626 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001627
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001628 def set_time(self, vfy_time):
1629 """
1630 Set the time against which the certificates are verified.
1631
1632 Normally the current time is used.
1633
1634 .. note::
1635
1636 For example, you can determine if a certificate was valid at a given
1637 time.
1638
Hynek Schlawackf6c96af2017-04-20 12:34:58 +02001639 .. versionadded:: 17.0.0
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001640
1641 :param datetime vfy_time: The verification time to set on this store.
1642 :return: ``None`` if the verification time was successfully set.
1643 """
1644 param = _lib.X509_VERIFY_PARAM_new()
1645 param = _ffi.gc(param, _lib.X509_VERIFY_PARAM_free)
1646
1647 _lib.X509_VERIFY_PARAM_set_time(param, int(vfy_time.strftime('%s')))
1648 _openssl_assert(_lib.X509_STORE_set1_param(self._store, param) != 0)
1649
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001650
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001651class X509StoreContextError(Exception):
1652 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001653 An exception raised when an error occurred while verifying a certificate
1654 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001655
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001656 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001657 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001658 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001659
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001660 def __init__(self, message, certificate):
1661 super(X509StoreContextError, self).__init__(message)
1662 self.certificate = certificate
1663
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001664
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001665class X509StoreContext(object):
1666 """
1667 An X.509 store context.
1668
Dan Sully44e767a2016-06-04 18:05:27 -07001669 An X.509 store context is used to carry out the actual verification process
1670 of a certificate in a described context. For describing such a context, see
1671 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001672
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001673 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1674 instance. It is dynamically allocated and automatically garbage
1675 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001676 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001677 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001678 :param X509Store store: The certificates which will be trusted for the
1679 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001680 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001681 """
1682
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001683 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001684 store_ctx = _lib.X509_STORE_CTX_new()
1685 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1686 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001687 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001688 # Make the store context available for use after instantiating this
1689 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001690 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001691 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001692
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001693 def _init(self):
1694 """
1695 Set up the store context for a subsequent verification operation.
Jeremy Cline58193f12017-09-13 21:14:53 -04001696
1697 Calling this method more than once without first calling
1698 :meth:`_cleanup` will leak memory.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001699 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001700 ret = _lib.X509_STORE_CTX_init(
1701 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1702 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001703 if ret <= 0:
1704 _raise_current_error()
1705
1706 def _cleanup(self):
1707 """
1708 Internally cleans up the store context.
1709
Dan Sully44e767a2016-06-04 18:05:27 -07001710 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001711 """
1712 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1713
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001714 def _exception_from_context(self):
1715 """
1716 Convert an OpenSSL native context error failure into a Python
1717 exception.
1718
Alex Gaynor5945ea82015-09-05 14:59:06 -04001719 When a call to native OpenSSL X509_verify_cert fails, additional
1720 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001721 """
1722 errors = [
1723 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1724 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1725 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001726 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001727 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001728 # A context error should always be associated with a certificate, so we
1729 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001730 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001731 _cert = _lib.X509_dup(_x509)
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001732 pycert = X509._from_raw_x509_ptr(_cert)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001733 return X509StoreContextError(errors, pycert)
1734
Stephen Holsapple46a09252015-02-12 14:45:43 -08001735 def set_store(self, store):
1736 """
Dan Sully44e767a2016-06-04 18:05:27 -07001737 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001738
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001739 .. versionadded:: 0.15
1740
Dan Sully44e767a2016-06-04 18:05:27 -07001741 :param X509Store store: The store description which will be used for
1742 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001743 """
1744 self._store = store
1745
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001746 def verify_certificate(self):
1747 """
1748 Verify a certificate in a context.
1749
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001750 .. versionadded:: 0.15
1751
Alex Gaynorca87ff62015-09-04 23:31:03 -04001752 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001753 certificate in the context. Sets ``certificate`` attribute to
1754 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001755 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001756 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001757 # :meth:`verify_certificate` is called multiple times.
Jeremy Cline58193f12017-09-13 21:14:53 -04001758 #
1759 # :meth:`_init` is called in :meth:`__init__` so _cleanup is called
1760 # before _init to ensure memory is not leaked.
1761 self._cleanup()
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001762 self._init()
1763 ret = _lib.X509_verify_cert(self._store_ctx)
1764 self._cleanup()
1765 if ret <= 0:
1766 raise self._exception_from_context()
1767
1768
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001769def load_certificate(type, buffer):
1770 """
Alex Chand072cae2018-02-15 09:57:59 +00001771 Load a certificate (X509) from the string *buffer* encoded with the
1772 type *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001773
1774 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1775
Dan Sully44e767a2016-06-04 18:05:27 -07001776 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001777
1778 :return: The X509 object
1779 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001780 if isinstance(buffer, _text_type):
1781 buffer = buffer.encode("ascii")
1782
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001783 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001784
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001785 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001786 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001787 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001788 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001789 else:
1790 raise ValueError(
1791 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001792
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001793 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001794 _raise_current_error()
1795
Alex Gaynor4aa52c32017-11-20 09:04:08 -05001796 return X509._from_raw_x509_ptr(x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001797
1798
1799def dump_certificate(type, cert):
1800 """
Alex Chand072cae2018-02-15 09:57:59 +00001801 Dump the certificate *cert* into a buffer string encoded with the type
1802 *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001803
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001804 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1805 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001806 :param cert: The certificate to dump
1807 :return: The buffer with the dumped certificate in
1808 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001809 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001810
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001811 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001812 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001813 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001814 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001815 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001816 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001817 else:
1818 raise ValueError(
1819 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1820 "FILETYPE_TEXT")
1821
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001822 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001823 return _bio_to_string(bio)
1824
1825
Cory Benfield6492f7c2015-10-27 16:57:58 +09001826def dump_publickey(type, pkey):
1827 """
Cory Benfield11c10192015-10-27 17:23:03 +09001828 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001829
Cory Benfield9c590b92015-10-28 14:55:05 +09001830 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001831 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001832 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001833 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001834 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001835 """
1836 bio = _new_mem_buf()
1837 if type == FILETYPE_PEM:
1838 write_bio = _lib.PEM_write_bio_PUBKEY
1839 elif type == FILETYPE_ASN1:
1840 write_bio = _lib.i2d_PUBKEY_bio
1841 else:
1842 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1843
1844 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001845 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001846 _raise_current_error()
1847
1848 return _bio_to_string(bio)
1849
1850
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001851def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1852 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001853 Dump the private key *pkey* into a buffer string encoded with the type
1854 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1855 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001856
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001857 :param type: The file type (one of :const:`FILETYPE_PEM`,
1858 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1859 :param PKey pkey: The PKey to dump
1860 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001861 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001862 the passphrase to use, or a callback for providing the passphrase.
1863
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001864 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001865 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001866 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001867 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001868
Paul Kehrercded9932017-06-29 18:43:42 -05001869 if not isinstance(pkey, PKey):
1870 raise TypeError("pkey must be a PKey")
1871
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001872 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001873 if passphrase is None:
1874 raise TypeError(
1875 "if a value is given for cipher "
1876 "one must also be given for passphrase")
1877 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001878 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001879 raise ValueError("Invalid cipher name")
1880 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001881 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001882
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001883 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001884 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001885 result_code = _lib.PEM_write_bio_PrivateKey(
1886 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001887 helper.callback, helper.callback_args)
1888 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001889 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001890 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001891 elif type == FILETYPE_TEXT:
Paul Kehrercded9932017-06-29 18:43:42 -05001892 if _lib.EVP_PKEY_id(pkey._pkey) != _lib.EVP_PKEY_RSA:
1893 raise TypeError("Only RSA keys are supported for FILETYPE_TEXT")
1894
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001895 rsa = _ffi.gc(
1896 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1897 _lib.RSA_free
1898 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001899 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001900 else:
1901 raise ValueError(
1902 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1903 "FILETYPE_TEXT")
1904
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001905 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001906
1907 return _bio_to_string(bio)
1908
1909
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001910class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001911 """
1912 A certificate revocation.
1913 """
Cyril Stoller37e60222018-08-27 13:38:10 +02001914 # https://www.openssl.org/docs/manmaster/man5/x509v3_config.html#CRL-distribution-points
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001915 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1916 # OCSP_crl_reason_str. We use the latter, just like the command line
1917 # program.
1918 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001919 b"unspecified",
1920 b"keyCompromise",
1921 b"CACompromise",
1922 b"affiliationChanged",
1923 b"superseded",
1924 b"cessationOfOperation",
1925 b"certificateHold",
1926 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001927 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001928
1929 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001930 revoked = _lib.X509_REVOKED_new()
1931 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001932
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001933 def set_serial(self, hex_str):
1934 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001935 Set the serial number.
1936
1937 The serial number is formatted as a hexadecimal number encoded in
1938 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001939
Dan Sully44e767a2016-06-04 18:05:27 -07001940 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001941
Dan Sully44e767a2016-06-04 18:05:27 -07001942 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001943 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001944 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1945 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001946 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001947 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001948 if not bn_result:
1949 raise ValueError("bad hex string")
1950
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001951 asn1_serial = _ffi.gc(
1952 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1953 _lib.ASN1_INTEGER_free)
1954 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001955
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001956 def get_serial(self):
1957 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001958 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001959
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001960 The serial number is formatted as a hexadecimal number encoded in
1961 ASCII.
1962
1963 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001964 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001965 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001966 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001967
Alex Gaynor67903a62016-06-02 10:37:13 -07001968 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1969 _openssl_assert(asn1_int != _ffi.NULL)
1970 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1971 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001972 return _bio_to_string(bio)
1973
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001974 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001975 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1976 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001977 obj = _lib.X509_EXTENSION_get_object(ext)
1978 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001979 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001980 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001981 break
1982
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001983 def set_reason(self, reason):
1984 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001985 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001986
Dan Sully44e767a2016-06-04 18:05:27 -07001987 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001988
1989 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07001990 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001991
Dan Sully44e767a2016-06-04 18:05:27 -07001992 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001993
1994 .. seealso::
1995
Dan Sully44e767a2016-06-04 18:05:27 -07001996 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001997 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001998 """
1999 if reason is None:
2000 self._delete_reason()
2001 elif not isinstance(reason, bytes):
2002 raise TypeError("reason must be None or a byte string")
2003 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002004 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002005 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
2006
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002007 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002008 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002009 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002010
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002011 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002012 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002013
2014 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002015 add_result = _lib.X509_REVOKED_add1_ext_i2d(
2016 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002017 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002018
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002019 def get_reason(self):
2020 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04002021 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002022
Dan Sully44e767a2016-06-04 18:05:27 -07002023 :return: The reason, or ``None`` if there is none.
2024 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002025
2026 .. seealso::
2027
Dan Sully44e767a2016-06-04 18:05:27 -07002028 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002029 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002030 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002031 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
2032 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002033 obj = _lib.X509_EXTENSION_get_object(ext)
2034 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08002035 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002036
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002037 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002038 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002039 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04002040 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04002041 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002042 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002043
2044 return _bio_to_string(bio)
2045
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002046 def all_reasons(self):
2047 """
2048 Return a list of all the supported reason strings.
2049
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002050 This list is a copy; modifying it does not change the supported reason
2051 strings.
2052
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002053 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07002054 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002055 """
2056 return self._crl_reasons[:]
2057
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002058 def set_rev_date(self, when):
2059 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002060 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002061
Dan Sully44e767a2016-06-04 18:05:27 -07002062 :param bytes when: The timestamp of the revocation,
Paul Kehrerce98ee62017-06-21 06:59:58 -10002063 as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002064 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002065 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002066 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2067 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002068
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002069 def get_rev_date(self):
2070 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02002071 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002072
Paul Kehrerce98ee62017-06-21 06:59:58 -10002073 :return: The timestamp of the revocation, as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07002074 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002075 """
Alex Gaynor67903a62016-06-02 10:37:13 -07002076 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
2077 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002078
2079
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002080class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002081 """
2082 A certificate revocation list.
2083 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002084
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002085 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002086 crl = _lib.X509_CRL_new()
2087 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002088
Paul Kehrer41c10242017-06-29 18:24:17 -05002089 def to_cryptography(self):
2090 """
2091 Export as a ``cryptography`` CRL.
2092
2093 :rtype: ``cryptography.x509.CertificateRevocationList``
2094
2095 .. versionadded:: 17.1.0
2096 """
2097 from cryptography.hazmat.backends.openssl.x509 import (
2098 _CertificateRevocationList
2099 )
2100 backend = _get_backend()
2101 return _CertificateRevocationList(backend, self._crl)
2102
2103 @classmethod
2104 def from_cryptography(cls, crypto_crl):
2105 """
2106 Construct based on a ``cryptography`` *crypto_crl*.
2107
2108 :param crypto_crl: A ``cryptography`` certificate revocation list
2109 :type crypto_crl: ``cryptography.x509.CertificateRevocationList``
2110
2111 :rtype: CRL
2112
2113 .. versionadded:: 17.1.0
2114 """
2115 if not isinstance(crypto_crl, x509.CertificateRevocationList):
2116 raise TypeError("Must be a certificate revocation list")
2117
2118 crl = cls()
2119 crl._crl = crypto_crl._x509_crl
2120 return crl
2121
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002122 def get_revoked(self):
2123 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002124 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002125
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002126 These revocations will be provided by value, not by reference.
2127 That means it's okay to mutate them: it won't affect this CRL.
2128
2129 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002130 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002131 """
2132 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07002133 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002134 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
2135 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04002136 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002137 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002138 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002139 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002140 if results:
2141 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002142
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002143 def add_revoked(self, revoked):
2144 """
2145 Add a revoked (by value not reference) to the CRL structure
2146
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002147 This revocation will be added by value, not by reference. That
2148 means it's okay to mutate it after adding: it won't affect
2149 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002150
Dan Sully44e767a2016-06-04 18:05:27 -07002151 :param Revoked revoked: The new revocation.
2152 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002153 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04002154 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002155 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002156
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002157 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002158 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002159
Dan Sully44e767a2016-06-04 18:05:27 -07002160 def get_issuer(self):
2161 """
2162 Get the CRL's issuer.
2163
2164 .. versionadded:: 16.1.0
2165
2166 :rtype: X509Name
2167 """
2168 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
2169 _openssl_assert(_issuer != _ffi.NULL)
2170 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
2171 issuer = X509Name.__new__(X509Name)
2172 issuer._name = _issuer
2173 return issuer
2174
2175 def set_version(self, version):
2176 """
2177 Set the CRL version.
2178
2179 .. versionadded:: 16.1.0
2180
2181 :param int version: The version of the CRL.
2182 :return: ``None``
2183 """
2184 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2185
2186 def _set_boundary_time(self, which, when):
2187 return _set_asn1_time(which(self._crl), when)
2188
2189 def set_lastUpdate(self, when):
2190 """
2191 Set when the CRL was last updated.
2192
Paul Kehrerce98ee62017-06-21 06:59:58 -10002193 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002194
2195 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002196
2197 .. versionadded:: 16.1.0
2198
2199 :param bytes when: A timestamp string.
2200 :return: ``None``
2201 """
2202 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2203
2204 def set_nextUpdate(self, when):
2205 """
2206 Set when the CRL will next be udpated.
2207
Paul Kehrerce98ee62017-06-21 06:59:58 -10002208 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002209
2210 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002211
2212 .. versionadded:: 16.1.0
2213
2214 :param bytes when: A timestamp string.
2215 :return: ``None``
2216 """
2217 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2218
2219 def sign(self, issuer_cert, issuer_key, digest):
2220 """
2221 Sign the CRL.
2222
2223 Signing a CRL enables clients to associate the CRL itself with an
2224 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2225 be signed by an issuer.
2226
2227 This method implicitly sets the issuer's name based on the issuer
2228 certificate and private key used to sign the CRL.
2229
2230 .. versionadded:: 16.1.0
2231
2232 :param X509 issuer_cert: The issuer's certificate.
2233 :param PKey issuer_key: The issuer's private key.
2234 :param bytes digest: The digest method to sign the CRL with.
2235 """
2236 digest_obj = _lib.EVP_get_digestbyname(digest)
2237 _openssl_assert(digest_obj != _ffi.NULL)
2238 _lib.X509_CRL_set_issuer_name(
2239 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2240 _lib.X509_CRL_sort(self._crl)
2241 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2242 _openssl_assert(result != 0)
2243
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002244 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002245 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002246 """
Dan Sully44e767a2016-06-04 18:05:27 -07002247 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002248
Dan Sully44e767a2016-06-04 18:05:27 -07002249 :param X509 cert: The certificate used to sign the CRL.
2250 :param PKey key: The key used to sign the CRL.
2251 :param int type: The export format, either :data:`FILETYPE_PEM`,
2252 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002253 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002254 :param bytes digest: The name of the message digest to use (eg
Wayne Werner80dcf382019-01-30 15:03:16 -06002255 ``b"sha256"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002256 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002257 """
Dan Sully44e767a2016-06-04 18:05:27 -07002258
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002259 if not isinstance(cert, X509):
2260 raise TypeError("cert must be an X509 instance")
2261 if not isinstance(key, PKey):
2262 raise TypeError("key must be a PKey instance")
2263 if not isinstance(type, int):
2264 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002265
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002266 if digest is _UNSPECIFIED:
Alex Gaynor173e4ba2017-06-30 08:01:12 -07002267 raise TypeError("digest must be provided")
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002268
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002269 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002270 if digest_obj == _ffi.NULL:
2271 raise ValueError("No such digest method")
2272
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002273 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002274 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002275
Alex Gaynora738ed52015-09-05 11:17:10 -04002276 # A scratch time object to give different values to different CRL
2277 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002278 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002279 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002280
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002281 _lib.X509_gmtime_adj(sometime, 0)
2282 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002283
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002284 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2285 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002286
Alex Gaynor5945ea82015-09-05 14:59:06 -04002287 _lib.X509_CRL_set_issuer_name(
2288 self._crl, _lib.X509_get_subject_name(cert._x509)
2289 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002290
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002291 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002292 if not sign_result:
2293 _raise_current_error()
2294
Dominic Chenf05b2122015-10-13 16:32:35 +00002295 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002296
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002297
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002298class PKCS7(object):
2299 def type_is_signed(self):
2300 """
2301 Check if this NID_pkcs7_signed object
2302
2303 :return: True if the PKCS7 is of type signed
2304 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002305 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002306
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002307 def type_is_enveloped(self):
2308 """
2309 Check if this NID_pkcs7_enveloped object
2310
2311 :returns: True if the PKCS7 is of type enveloped
2312 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002313 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002314
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002315 def type_is_signedAndEnveloped(self):
2316 """
2317 Check if this NID_pkcs7_signedAndEnveloped object
2318
2319 :returns: True if the PKCS7 is of type signedAndEnveloped
2320 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002321 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002322
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002323 def type_is_data(self):
2324 """
2325 Check if this NID_pkcs7_data object
2326
2327 :return: True if the PKCS7 is of type data
2328 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002329 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002330
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002331 def get_type_name(self):
2332 """
2333 Returns the type name of the PKCS7 structure
2334
2335 :return: A string with the typename
2336 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002337 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2338 string_type = _lib.OBJ_nid2sn(nid)
2339 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002340
Alex Chanc6077062016-11-18 13:53:39 +00002341
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002342class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002343 """
2344 A PKCS #12 archive.
2345 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002346
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002347 def __init__(self):
2348 self._pkey = None
2349 self._cert = None
2350 self._cacerts = None
2351 self._friendlyname = None
2352
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002353 def get_certificate(self):
2354 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002355 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002356
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002357 :return: The certificate, or :py:const:`None` if there is none.
2358 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002359 """
2360 return self._cert
2361
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002362 def set_certificate(self, cert):
2363 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002364 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002365
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002366 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002367 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002368
Dan Sully44e767a2016-06-04 18:05:27 -07002369 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002370 """
2371 if not isinstance(cert, X509):
2372 raise TypeError("cert must be an X509 instance")
2373 self._cert = cert
2374
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002375 def get_privatekey(self):
2376 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002377 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002378
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002379 :return: The private key, or :py:const:`None` if there is none.
2380 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002381 """
2382 return self._pkey
2383
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002384 def set_privatekey(self, pkey):
2385 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002386 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002387
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002388 :param pkey: The new private key, or :py:const:`None` to unset it.
2389 :type pkey: :py:class:`PKey` or :py:const:`None`
2390
Dan Sully44e767a2016-06-04 18:05:27 -07002391 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002392 """
2393 if not isinstance(pkey, PKey):
2394 raise TypeError("pkey must be a PKey instance")
2395 self._pkey = pkey
2396
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002397 def get_ca_certificates(self):
2398 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002399 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002400
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002401 :return: A tuple with the CA certificates in the chain, or
2402 :py:const:`None` if there are none.
2403 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002404 """
2405 if self._cacerts is not None:
2406 return tuple(self._cacerts)
2407
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002408 def set_ca_certificates(self, cacerts):
2409 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002410 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002411
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002412 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2413 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002414 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002415
Dan Sully44e767a2016-06-04 18:05:27 -07002416 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002417 """
2418 if cacerts is None:
2419 self._cacerts = None
2420 else:
2421 cacerts = list(cacerts)
2422 for cert in cacerts:
2423 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002424 raise TypeError(
2425 "iterable must only contain X509 instances"
2426 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002427 self._cacerts = cacerts
2428
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002429 def set_friendlyname(self, name):
2430 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002431 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002432
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002433 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002434 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002435
Dan Sully44e767a2016-06-04 18:05:27 -07002436 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002437 """
2438 if name is None:
2439 self._friendlyname = None
2440 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002441 raise TypeError(
2442 "name must be a byte string or None (not %r)" % (name,)
2443 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002444 self._friendlyname = name
2445
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002446 def get_friendlyname(self):
2447 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002448 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002449
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002450 :returns: The friendly name, or :py:const:`None` if there is none.
2451 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002452 """
2453 return self._friendlyname
2454
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002455 def export(self, passphrase=None, iter=2048, maciter=1):
2456 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002457 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002458
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002459 For more information, see the :c:func:`PKCS12_create` man page.
2460
2461 :param passphrase: The passphrase used to encrypt the structure. Unlike
2462 some other passphrase arguments, this *must* be a string, not a
2463 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002464 :type passphrase: :py:data:`bytes`
2465
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002466 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002467 :type iter: :py:data:`int`
2468
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002469 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002470 :type maciter: :py:data:`int`
2471
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002472 :return: The string representation of the PKCS #12 structure.
2473 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002474 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002475 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002476
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002477 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002478 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002479 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002480 cacerts = _lib.sk_X509_new_null()
2481 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002482 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002483 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002484
2485 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002486 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002487
2488 friendlyname = self._friendlyname
2489 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002490 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002491
2492 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002493 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002494 else:
2495 pkey = self._pkey._pkey
2496
2497 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002498 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002499 else:
2500 cert = self._cert._x509
2501
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002502 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002503 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002504 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2505 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002506 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002507 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002508 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002509 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002510
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002511 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002512 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002513 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002514
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002515
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002516class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002517 """
2518 A Netscape SPKI object.
2519 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002520
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002521 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002522 spki = _lib.NETSCAPE_SPKI_new()
2523 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002524
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002525 def sign(self, pkey, digest):
2526 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002527 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002528
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002529 :param pkey: The private key to sign with.
2530 :type pkey: :py:class:`PKey`
2531
2532 :param digest: The message digest to use.
2533 :type digest: :py:class:`bytes`
2534
Dan Sully44e767a2016-06-04 18:05:27 -07002535 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002536 """
2537 if pkey._only_public:
2538 raise ValueError("Key has only public part")
2539
2540 if not pkey._initialized:
2541 raise ValueError("Key is uninitialized")
2542
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002543 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002544 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002545 raise ValueError("No such digest method")
2546
Alex Gaynor5945ea82015-09-05 14:59:06 -04002547 sign_result = _lib.NETSCAPE_SPKI_sign(
2548 self._spki, pkey._pkey, digest_obj
2549 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002550 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002551
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002552 def verify(self, key):
2553 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002554 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002555
Hynek Schlawack01c31672016-12-11 15:14:09 +01002556 :param PKey key: The public key that signature is supposedly from.
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002557
Hynek Schlawack01c31672016-12-11 15:14:09 +01002558 :return: ``True`` if the signature is correct.
2559 :rtype: bool
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002560
Hynek Schlawack01c31672016-12-11 15:14:09 +01002561 :raises OpenSSL.crypto.Error: If the signature is invalid, or there was
2562 a problem verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002563 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002564 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002565 if answer <= 0:
2566 _raise_current_error()
2567 return True
2568
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002569 def b64_encode(self):
2570 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002571 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002572
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002573 :return: The base64 encoded string.
2574 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002575 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002576 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2577 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002578 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002579 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002580
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002581 def get_pubkey(self):
2582 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002583 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002584
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002585 :return: The public key.
2586 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002587 """
2588 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002589 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002590 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002591 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002592 pkey._only_public = True
2593 return pkey
2594
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002595 def set_pubkey(self, pkey):
2596 """
2597 Set the public key of the certificate
2598
2599 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002600 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002601 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002602 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002603 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002604
2605
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002606class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002607 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002608 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002609 raise ValueError(
2610 "only FILETYPE_PEM key format supports encryption"
2611 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002612 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002613 self._more_args = more_args
2614 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002615 self._problems = []
2616
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002617 @property
2618 def callback(self):
2619 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002620 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002621 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002622 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002623 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002624 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002625 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002626 raise TypeError(
2627 "Last argument must be a byte string or a callable."
2628 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002629
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002630 @property
2631 def callback_args(self):
2632 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002633 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002634 elif isinstance(self._passphrase, bytes):
2635 return self._passphrase
2636 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002637 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002638 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002639 raise TypeError(
2640 "Last argument must be a byte string or a callable."
2641 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002642
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002643 def raise_if_problem(self, exceptionType=Error):
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002644 if self._problems:
Greg Bowser36eb2de2017-01-24 11:38:55 -05002645
2646 # Flush the OpenSSL error queue
2647 try:
2648 _exception_from_error_queue(exceptionType)
2649 except exceptionType:
2650 pass
2651
2652 raise self._problems.pop(0)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002653
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002654 def _read_passphrase(self, buf, size, rwflag, userdata):
2655 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002656 if self._more_args:
2657 result = self._passphrase(size, rwflag, userdata)
2658 else:
2659 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002660 if not isinstance(result, bytes):
2661 raise ValueError("String expected")
2662 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002663 if self._truncate:
2664 result = result[:size]
2665 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002666 raise ValueError(
2667 "passphrase returned by callback is too long"
2668 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002669 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002670 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002671 return len(result)
2672 except Exception as e:
2673 self._problems.append(e)
2674 return 0
2675
2676
Cory Benfield6492f7c2015-10-27 16:57:58 +09002677def load_publickey(type, buffer):
2678 """
Cory Benfield11c10192015-10-27 17:23:03 +09002679 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002680
Cory Benfield9c590b92015-10-28 14:55:05 +09002681 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002682 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002683 :param buffer: The buffer the key is stored in.
2684 :type buffer: A Python string object, either unicode or bytestring.
2685 :return: The PKey object.
2686 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002687 """
2688 if isinstance(buffer, _text_type):
2689 buffer = buffer.encode("ascii")
2690
2691 bio = _new_mem_buf(buffer)
2692
2693 if type == FILETYPE_PEM:
2694 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2695 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2696 elif type == FILETYPE_ASN1:
2697 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2698 else:
2699 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2700
2701 if evp_pkey == _ffi.NULL:
2702 _raise_current_error()
2703
2704 pkey = PKey.__new__(PKey)
2705 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002706 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002707 return pkey
2708
2709
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002710def load_privatekey(type, buffer, passphrase=None):
2711 """
Alex Chand072cae2018-02-15 09:57:59 +00002712 Load a private key (PKey) from the string *buffer* encoded with the type
2713 *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002714
2715 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2716 :param buffer: The buffer the key is stored in
2717 :param passphrase: (optional) if encrypted PEM format, this can be
2718 either the passphrase to use, or a callback for
2719 providing the passphrase.
2720
2721 :return: The PKey object
2722 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002723 if isinstance(buffer, _text_type):
2724 buffer = buffer.encode("ascii")
2725
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002726 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002727
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002728 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002729 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002730 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2731 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002732 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002733 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002734 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002735 else:
2736 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2737
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002738 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002739 _raise_current_error()
2740
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002741 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002742 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002743 return pkey
2744
2745
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002746def dump_certificate_request(type, req):
2747 """
Alex Chand072cae2018-02-15 09:57:59 +00002748 Dump the certificate request *req* into a buffer string encoded with the
2749 type *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002750
2751 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2752 :param req: The certificate request to dump
2753 :return: The buffer with the dumped certificate request in
2754 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002755 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002756
2757 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002758 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002759 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002760 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002761 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002762 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002763 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002764 raise ValueError(
2765 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2766 "FILETYPE_TEXT"
2767 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002768
Alex Gaynor09a386e2016-07-03 09:32:44 -04002769 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002770
2771 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002772
2773
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002774def load_certificate_request(type, buffer):
2775 """
Alex Chand072cae2018-02-15 09:57:59 +00002776 Load a certificate request (X509Req) from the string *buffer* encoded with
2777 the type *type*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002778
2779 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2780 :param buffer: The buffer the certificate request is stored in
2781 :return: The X509Req object
2782 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002783 if isinstance(buffer, _text_type):
2784 buffer = buffer.encode("ascii")
2785
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002786 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002787
2788 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002789 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002790 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002791 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002792 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002793 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002794
Alex Gaynoradd5b072016-06-04 21:04:00 -07002795 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002796
2797 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002798 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002799 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002800
2801
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002802def sign(pkey, data, digest):
2803 """
Alex Chand072cae2018-02-15 09:57:59 +00002804 Sign a data string using the given key and message digest.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002805
Alex Chand072cae2018-02-15 09:57:59 +00002806 :param pkey: PKey to sign with
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002807 :param data: data to be signed
2808 :param digest: message digest to use
2809 :return: signature
Alex Chand072cae2018-02-15 09:57:59 +00002810
2811 .. versionadded:: 0.11
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002812 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002813 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002814
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002815 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002816 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002817 raise ValueError("No such digest method")
2818
Alex Gaynor67903a62016-06-02 10:37:13 -07002819 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002820 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002821
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002822 _lib.EVP_SignInit(md_ctx, digest_obj)
2823 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002824
Paul Kehrer59d26252017-07-20 10:45:54 +02002825 length = _lib.EVP_PKEY_size(pkey._pkey)
2826 _openssl_assert(length > 0)
2827 signature_buffer = _ffi.new("unsigned char[]", length)
2828 signature_length = _ffi.new("unsigned int *")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002829 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002830 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002831 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002832
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002833 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002834
2835
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002836def verify(cert, signature, data, digest):
2837 """
Alex Chand072cae2018-02-15 09:57:59 +00002838 Verify the signature for a data string.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002839
Alex Chand072cae2018-02-15 09:57:59 +00002840 :param cert: signing certificate (X509 object) corresponding to the
2841 private key which generated the signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002842 :param signature: signature returned by sign function
2843 :param data: data to be verified
2844 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002845 :return: ``None`` if the signature is correct, raise exception otherwise.
Alex Chand072cae2018-02-15 09:57:59 +00002846
2847 .. versionadded:: 0.11
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002848 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002849 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002850
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002851 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002852 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002853 raise ValueError("No such digest method")
2854
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002855 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002856 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002857 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002858
Alex Gaynor67903a62016-06-02 10:37:13 -07002859 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002860 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002861
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002862 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2863 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002864 verify_result = _lib.EVP_VerifyFinal(
2865 md_ctx, signature, len(signature), pkey
2866 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002867
2868 if verify_result != 1:
2869 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002870
2871
Dominic Chenf05b2122015-10-13 16:32:35 +00002872def dump_crl(type, crl):
2873 """
2874 Dump a certificate revocation list to a buffer.
2875
2876 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2877 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002878 :param CRL crl: The CRL to dump.
2879
Dominic Chenf05b2122015-10-13 16:32:35 +00002880 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002881 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002882 """
2883 bio = _new_mem_buf()
2884
2885 if type == FILETYPE_PEM:
2886 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2887 elif type == FILETYPE_ASN1:
2888 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2889 elif type == FILETYPE_TEXT:
2890 ret = _lib.X509_CRL_print(bio, crl._crl)
2891 else:
2892 raise ValueError(
2893 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2894 "FILETYPE_TEXT")
2895
2896 assert ret == 1
2897 return _bio_to_string(bio)
2898
2899
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002900def load_crl(type, buffer):
2901 """
Alex Chand072cae2018-02-15 09:57:59 +00002902 Load Certificate Revocation List (CRL) data from a string *buffer*.
2903 *buffer* encoded with the type *type*.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002904
2905 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2906 :param buffer: The buffer the CRL is stored in
2907
2908 :return: The PKey object
2909 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002910 if isinstance(buffer, _text_type):
2911 buffer = buffer.encode("ascii")
2912
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002913 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002914
2915 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002916 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002917 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002918 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002919 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002920 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2921
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002922 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002923 _raise_current_error()
2924
2925 result = CRL.__new__(CRL)
Jeremy Cline9e15eca2017-09-07 20:11:08 -04002926 result._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002927 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002928
2929
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002930def load_pkcs7_data(type, buffer):
2931 """
Alex Chand072cae2018-02-15 09:57:59 +00002932 Load pkcs7 data from the string *buffer* encoded with the type
2933 *type*.
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002934
2935 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2936 :param buffer: The buffer with the pkcs7 data.
2937 :return: The PKCS7 object
2938 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002939 if isinstance(buffer, _text_type):
2940 buffer = buffer.encode("ascii")
2941
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002942 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002943
2944 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002945 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002946 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002947 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002948 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002949 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2950
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002951 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002952 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002953
2954 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002955 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002956 return pypkcs7
2957
2958
Stephen Holsapple38482622014-04-05 20:29:34 -07002959def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002960 """
Alex Chand072cae2018-02-15 09:57:59 +00002961 Load pkcs12 data from the string *buffer*. If the pkcs12 structure is
2962 encrypted, a *passphrase* must be included. The MAC is always
2963 checked and thus required.
2964
2965 See also the man page for the C function :py:func:`PKCS12_parse`.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002966
2967 :param buffer: The buffer the certificate is stored in
2968 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2969 :returns: The PKCS12 object
2970 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002971 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002972
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002973 if isinstance(buffer, _text_type):
2974 buffer = buffer.encode("ascii")
2975
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002976 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002977
Stephen Holsapple38482622014-04-05 20:29:34 -07002978 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2979 # password based encryption no password and a zero length password are two
2980 # different things, but OpenSSL implementation will try both to figure out
2981 # which one works.
2982 if not passphrase:
2983 passphrase = _ffi.NULL
2984
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002985 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2986 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002987 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002988 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002989
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002990 pkey = _ffi.new("EVP_PKEY**")
2991 cert = _ffi.new("X509**")
2992 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002993
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002994 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002995 if not parse_result:
2996 _raise_current_error()
2997
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002998 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002999
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003000 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
3001 # queue for no particular reason. This error isn't interesting to anyone
3002 # outside this function. It's not even interesting to us. Get rid of it.
3003 try:
3004 _raise_current_error()
3005 except Error:
3006 pass
3007
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003008 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003009 pykey = None
3010 else:
3011 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003012 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003013
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003014 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003015 pycert = None
3016 friendlyname = None
3017 else:
Paul Kehrere7381862017-11-30 20:55:25 +08003018 pycert = X509._from_raw_x509_ptr(cert[0])
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003019
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003020 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04003021 friendlyname_buffer = _lib.X509_alias_get0(
3022 cert[0], friendlyname_length
3023 )
3024 friendlyname = _ffi.buffer(
3025 friendlyname_buffer, friendlyname_length[0]
3026 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003027 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003028 friendlyname = None
3029
3030 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05003031 for i in range(_lib.sk_X509_num(cacerts)):
Paul Kehrere7381862017-11-30 20:55:25 +08003032 x509 = _lib.sk_X509_value(cacerts, i)
3033 pycacert = X509._from_raw_x509_ptr(x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08003034 pycacerts.append(pycacert)
3035 if not pycacerts:
3036 pycacerts = None
3037
3038 pkcs12 = PKCS12.__new__(PKCS12)
3039 pkcs12._pkey = pykey
3040 pkcs12._cert = pycert
3041 pkcs12._cacerts = pycacerts
3042 pkcs12._friendlyname = friendlyname
3043 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05003044
3045
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05003046# There are no direct unit tests for this initialization. It is tested
3047# indirectly since it is necessary for functions like dump_privatekey when
3048# using encryption.
3049#
3050# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
3051# and some other similar tests may fail without this (though they may not if
3052# the Python runtime has already done some initialization of the underlying
3053# OpenSSL library (and is linked against the same one that cryptography is
3054# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05003055_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05003056
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05003057# This is similar but exercised mainly by exception_from_error_queue. It calls
3058# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
3059_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003060
3061
D.S. Ljungmark349e1362014-05-31 18:40:38 +02003062# Set the default string mask to match OpenSSL upstream (since 2005) and
3063# RFC5280 recommendations.
3064_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')