blob: cdbcc2299be317dfa9121ee608093bef7db244ee [file] [log] [blame]
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001import datetime
Paul Kehrer8d887e12015-10-24 09:09:55 -05002
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003from base64 import b16encode
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05004from functools import partial
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05005from operator import __eq__, __ne__, __lt__, __le__, __gt__, __ge__
Jean-Paul Calderone60432792015-04-13 12:26:07 -04006from warnings import warn as _warn
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05007
8from six import (
9 integer_types as _integer_types,
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -040010 text_type as _text_type,
11 PY3 as _PY3)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080012
Alex Gaynor9939ba12017-06-25 16:28:24 -040013from cryptography import x509
Paul Kehrer72d968b2016-07-29 15:31:04 +080014from cryptography.hazmat.primitives.asymmetric import dsa, rsa
15
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050016from OpenSSL._util import (
17 ffi as _ffi,
18 lib as _lib,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050019 exception_from_error_queue as _exception_from_error_queue,
20 byte_string as _byte_string,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040021 native as _native,
22 UNSPECIFIED as _UNSPECIFIED,
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -040023 text_to_bytes_and_warn as _text_to_bytes_and_warn,
Alex Gaynor67903a62016-06-02 10:37:13 -070024 make_assert as _make_assert,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040025)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080026
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050027FILETYPE_PEM = _lib.SSL_FILETYPE_PEM
28FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080029
30# TODO This was an API mistake. OpenSSL has no such constant.
31FILETYPE_TEXT = 2 ** 16 - 1
32
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050033TYPE_RSA = _lib.EVP_PKEY_RSA
34TYPE_DSA = _lib.EVP_PKEY_DSA
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -080035
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080036
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050037class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050038 """
39 An error occurred in an `OpenSSL.crypto` API.
40 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050041
42
43_raise_current_error = partial(_exception_from_error_queue, Error)
Alex Gaynor67903a62016-06-02 10:37:13 -070044_openssl_assert = _make_assert(Error)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050045
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070046
Paul Kehrereb633842016-10-06 11:22:01 +020047def _get_backend():
48 """
49 Importing the backend from cryptography has the side effect of activating
50 the osrandom engine. This mutates the global state of OpenSSL in the
51 process and causes issues for various programs that use subinterpreters or
52 embed Python. By putting the import in this function we can avoid
53 triggering this side effect unless _get_backend is called.
54 """
55 from cryptography.hazmat.backends.openssl.backend import backend
56 return backend
57
58
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050059def _untested_error(where):
60 """
61 An OpenSSL API failed somehow. Additionally, the failure which was
62 encountered isn't one that's exercised by the test suite so future behavior
63 of pyOpenSSL is now somewhat less predictable.
64 """
65 raise RuntimeError("Unknown %s failure" % (where,))
66
67
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050068def _new_mem_buf(buffer=None):
69 """
70 Allocate a new OpenSSL memory BIO.
71
72 Arrange for the garbage collector to clean it up automatically.
73
74 :param buffer: None or some bytes to use to put into the BIO so that they
75 can be read out.
76 """
77 if buffer is None:
78 bio = _lib.BIO_new(_lib.BIO_s_mem())
79 free = _lib.BIO_free
80 else:
81 data = _ffi.new("char[]", buffer)
82 bio = _lib.BIO_new_mem_buf(data, len(buffer))
Alex Gaynor5945ea82015-09-05 14:59:06 -040083
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050084 # Keep the memory alive as long as the bio is alive!
85 def free(bio, ref=data):
86 return _lib.BIO_free(bio)
87
Alex Gaynorfb8a2a12016-06-04 18:26:26 -070088 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050089
90 bio = _ffi.gc(bio, free)
91 return bio
92
93
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080094def _bio_to_string(bio):
95 """
96 Copy the contents of an OpenSSL BIO object into a Python byte string.
97 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050098 result_buffer = _ffi.new('char**')
99 buffer_length = _lib.BIO_get_mem_data(bio, result_buffer)
100 return _ffi.buffer(result_buffer[0], buffer_length)[:]
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800101
102
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800103def _set_asn1_time(boundary, when):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500104 """
105 The the time value of an ASN1 time object.
106
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900107 @param boundary: An ASN1_TIME pointer (or an object safely
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500108 castable to that type) which will have its value set.
109 @param when: A string representation of the desired time value.
110
111 @raise TypeError: If C{when} is not a L{bytes} string.
112 @raise ValueError: If C{when} does not represent a time in the required
113 format.
114 @raise RuntimeError: If the time value cannot be set for some other
115 (unspecified) reason.
116 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800117 if not isinstance(when, bytes):
118 raise TypeError("when must be a byte string")
119
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900120 set_result = _lib.ASN1_TIME_set_string(boundary, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800121 if set_result == 0:
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900122 raise ValueError("Invalid string")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800123
Alex Gaynor510293e2016-06-02 12:07:59 -0700124
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800125def _get_asn1_time(timestamp):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500126 """
127 Retrieve the time value of an ASN1 time object.
128
129 @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to
130 that type) from which the time value will be retrieved.
131
132 @return: The time value from C{timestamp} as a L{bytes} string in a certain
133 format. Or C{None} if the object contains no time value.
134 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500135 string_timestamp = _ffi.cast('ASN1_STRING*', timestamp)
136 if _lib.ASN1_STRING_length(string_timestamp) == 0:
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800137 return None
Alex Gaynor5945ea82015-09-05 14:59:06 -0400138 elif (
139 _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME
140 ):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500141 return _ffi.string(_lib.ASN1_STRING_data(string_timestamp))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800142 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500143 generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**")
144 _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp)
145 if generalized_timestamp[0] == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500146 # This may happen:
147 # - if timestamp was not an ASN1_TIME
148 # - if allocating memory for the ASN1_GENERALIZEDTIME failed
149 # - if a copy of the time data from timestamp cannot be made for
150 # the newly allocated ASN1_GENERALIZEDTIME
151 #
152 # These are difficult to test. cffi enforces the ASN1_TIME type.
153 # Memory allocation failures are a pain to trigger
154 # deterministically.
155 _untested_error("ASN1_TIME_to_generalizedtime")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800156 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500157 string_timestamp = _ffi.cast(
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800158 "ASN1_STRING*", generalized_timestamp[0])
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500159 string_data = _lib.ASN1_STRING_data(string_timestamp)
160 string_result = _ffi.string(string_data)
161 _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0])
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800162 return string_result
163
164
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800165class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200166 """
167 A class representing an DSA or RSA public key or key pair.
168 """
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800169 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800170 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800171
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800172 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500173 pkey = _lib.EVP_PKEY_new()
174 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800175 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800176
Paul Kehrer72d968b2016-07-29 15:31:04 +0800177 def to_cryptography_key(self):
178 """
179 Export as a ``cryptography`` key.
180
181 :rtype: One of ``cryptography``'s `key interfaces`_.
182
183 .. _key interfaces: https://cryptography.io/en/latest/hazmat/\
184 primitives/asymmetric/rsa/#key-interfaces
185
186 .. versionadded:: 16.1.0
187 """
Paul Kehrereb633842016-10-06 11:22:01 +0200188 backend = _get_backend()
Paul Kehrer72d968b2016-07-29 15:31:04 +0800189 if self._only_public:
190 return backend._evp_pkey_to_public_key(self._pkey)
191 else:
192 return backend._evp_pkey_to_private_key(self._pkey)
193
194 @classmethod
195 def from_cryptography_key(cls, crypto_key):
196 """
197 Construct based on a ``cryptography`` *crypto_key*.
198
199 :param crypto_key: A ``cryptography`` key.
200 :type crypto_key: One of ``cryptography``'s `key interfaces`_.
201
202 :rtype: PKey
203
204 .. versionadded:: 16.1.0
205 """
206 pkey = cls()
207 if not isinstance(crypto_key, (rsa.RSAPublicKey, rsa.RSAPrivateKey,
208 dsa.DSAPublicKey, dsa.DSAPrivateKey)):
209 raise TypeError("Unsupported key type")
210
211 pkey._pkey = crypto_key._evp_pkey
212 if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)):
213 pkey._only_public = True
214 pkey._initialized = True
215 return pkey
216
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800217 def generate_key(self, type, bits):
218 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700219 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800220
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200221 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800222
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200223 :param type: The key type.
224 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
225 :param bits: The number of bits.
226 :type bits: :py:data:`int` ``>= 0``
227 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
228 of the appropriate type.
229 :raises ValueError: If the number of bits isn't an integer of
230 the appropriate size.
Dan Sully44e767a2016-06-04 18:05:27 -0700231 :return: ``None``
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800232 """
233 if not isinstance(type, int):
234 raise TypeError("type must be an integer")
235
236 if not isinstance(bits, int):
237 raise TypeError("bits must be an integer")
238
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800239 # TODO Check error return
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500240 exponent = _lib.BN_new()
241 exponent = _ffi.gc(exponent, _lib.BN_free)
242 _lib.BN_set_word(exponent, _lib.RSA_F4)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800243
244 if type == TYPE_RSA:
245 if bits <= 0:
246 raise ValueError("Invalid number of bits")
247
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500248 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800249
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500250 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400251 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800252
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500253 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400254 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800255
256 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400257 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700258 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400259
260 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400261 res = _lib.DSA_generate_parameters_ex(
262 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
263 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700264 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400265
266 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
267 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800268 else:
269 raise Error("No such key type")
270
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800271 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800272
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800273 def check(self):
274 """
275 Check the consistency of an RSA private key.
276
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200277 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
278
Hynek Schlawack01c31672016-12-11 15:14:09 +0100279 :return: ``True`` if key is consistent.
280
281 :raise OpenSSL.crypto.Error: if the key is inconsistent.
282
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800283 :raise TypeError: if the key is of a type which cannot be checked.
284 Only RSA keys can currently be checked.
285 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800286 if self._only_public:
287 raise TypeError("public key only")
288
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100289 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800290 raise TypeError("key type unsupported")
291
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500292 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
293 rsa = _ffi.gc(rsa, _lib.RSA_free)
294 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800295 if result:
296 return True
297 _raise_current_error()
298
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800299 def type(self):
300 """
301 Returns the type of the key
302
303 :return: The type of the key.
304 """
Alex Gaynor0d2aec52017-05-31 04:26:27 -0400305 return _lib.EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800306
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800307 def bits(self):
308 """
309 Returns the number of bits of the key
310
311 :return: The number of bits of the key.
312 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500313 return _lib.EVP_PKEY_bits(self._pkey)
Alex Chanc6077062016-11-18 13:53:39 +0000314
315
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800316PKeyType = PKey
317
318
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400319class _EllipticCurve(object):
320 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400321 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400322
323 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
324 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
325 instances each of which represents one curve supported by the system.
326 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400327 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400328 _curves = None
329
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400330 if _PY3:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400331 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400332 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400333 """
334 Implement cooperation with the right-hand side argument of ``!=``.
335
336 Python 3 seems to have dropped this cooperation in this very narrow
337 circumstance.
338 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400339 if isinstance(other, _EllipticCurve):
340 return super(_EllipticCurve, self).__ne__(other)
341 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400342
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400343 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400344 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400345 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400346 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400347
348 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400349
350 :return: A :py:type:`set` of ``cls`` instances giving the names of the
351 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400352 """
Alex Chan84902a22017-04-20 11:50:47 +0100353 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
354 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
355 # The return value on this call should be num_curves again. We
356 # could check it to make sure but if it *isn't* then.. what could
357 # we do? Abort the whole process, I suppose...? -exarkun
358 lib.EC_get_builtin_curves(builtin_curves, num_curves)
359 return set(
360 cls.from_nid(lib, c.nid)
361 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400362
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400363 @classmethod
364 def _get_elliptic_curves(cls, lib):
365 """
366 Get, cache, and return the curves supported by OpenSSL.
367
368 :param lib: The OpenSSL library binding object.
369
370 :return: A :py:type:`set` of ``cls`` instances giving the names of the
371 elliptic curves the underlying library supports.
372 """
373 if cls._curves is None:
374 cls._curves = cls._load_elliptic_curves(lib)
375 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400376
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400377 @classmethod
378 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400379 """
380 Instantiate a new :py:class:`_EllipticCurve` associated with the given
381 OpenSSL NID.
382
383 :param lib: The OpenSSL library binding object.
384
385 :param nid: The OpenSSL NID the resulting curve object will represent.
386 This must be a curve NID (and not, for example, a hash NID) or
387 subsequent operations will fail in unpredictable ways.
388 :type nid: :py:class:`int`
389
390 :return: The curve object.
391 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400392 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
393
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400394 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400395 """
396 :param _lib: The :py:mod:`cryptography` binding instance used to
397 interface with OpenSSL.
398
399 :param _nid: The OpenSSL NID identifying the curve this object
400 represents.
401 :type _nid: :py:class:`int`
402
403 :param name: The OpenSSL short name identifying the curve this object
404 represents.
405 :type name: :py:class:`unicode`
406 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400407 self._lib = lib
408 self._nid = nid
409 self.name = name
410
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400411 def __repr__(self):
412 return "<Curve %r>" % (self.name,)
413
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400414 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400415 """
416 Create a new OpenSSL EC_KEY structure initialized to use this curve.
417
418 The structure is automatically garbage collected when the Python object
419 is garbage collected.
420 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400421 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
422 return _ffi.gc(key, _lib.EC_KEY_free)
423
424
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400425def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400426 """
427 Return a set of objects representing the elliptic curves supported in the
428 OpenSSL build in use.
429
430 The curve objects have a :py:class:`unicode` ``name`` attribute by which
431 they identify themselves.
432
433 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400434 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
435 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400436 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400437 return _EllipticCurve._get_elliptic_curves(_lib)
438
439
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400440def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400441 """
442 Return a single curve object selected by name.
443
444 See :py:func:`get_elliptic_curves` for information about curve objects.
445
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400446 :param name: The OpenSSL short name identifying the curve object to
447 retrieve.
448 :type name: :py:class:`unicode`
449
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400450 If the named curve is not supported then :py:class:`ValueError` is raised.
451 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400452 for curve in get_elliptic_curves():
453 if curve.name == name:
454 return curve
455 raise ValueError("unknown curve name", name)
456
457
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800458class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200459 """
460 An X.509 Distinguished Name.
461
462 :ivar countryName: The country of the entity.
463 :ivar C: Alias for :py:attr:`countryName`.
464
465 :ivar stateOrProvinceName: The state or province of the entity.
466 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
467
468 :ivar localityName: The locality of the entity.
469 :ivar L: Alias for :py:attr:`localityName`.
470
471 :ivar organizationName: The organization name of the entity.
472 :ivar O: Alias for :py:attr:`organizationName`.
473
474 :ivar organizationalUnitName: The organizational unit of the entity.
475 :ivar OU: Alias for :py:attr:`organizationalUnitName`
476
477 :ivar commonName: The common name of the entity.
478 :ivar CN: Alias for :py:attr:`commonName`.
479
480 :ivar emailAddress: The e-mail address of the entity.
481 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400482
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800483 def __init__(self, name):
484 """
485 Create a new X509Name, copying the given X509Name instance.
486
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200487 :param name: The name to copy.
488 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800489 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500490 name = _lib.X509_NAME_dup(name._name)
491 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800492
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800493 def __setattr__(self, name, value):
494 if name.startswith('_'):
495 return super(X509Name, self).__setattr__(name, value)
496
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800497 # Note: we really do not want str subclasses here, so we do not use
498 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800499 if type(name) is not str:
500 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400501 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800502
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500503 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500504 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800505 try:
506 _raise_current_error()
507 except Error:
508 pass
509 raise AttributeError("No such attribute")
510
511 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500512 for i in range(_lib.X509_NAME_entry_count(self._name)):
513 ent = _lib.X509_NAME_get_entry(self._name, i)
514 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
515 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800516 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500517 ent = _lib.X509_NAME_delete_entry(self._name, i)
518 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800519 break
520
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500521 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800522 value = value.encode('utf-8')
523
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500524 add_result = _lib.X509_NAME_add_entry_by_NID(
525 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800526 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500527 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800528
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800529 def __getattr__(self, name):
530 """
531 Find attribute. An X509Name object has the following attributes:
532 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400533 organization (alias O), organizationalUnit (alias OU), commonName
534 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800535 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500536 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500537 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800538 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
539 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
540 # push something onto the error queue. If we don't clean that up
541 # now, someone else will bump into it later and be quite confused.
542 # See lp#314814.
543 try:
544 _raise_current_error()
545 except Error:
546 pass
547 return super(X509Name, self).__getattr__(name)
548
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500549 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800550 if entry_index == -1:
551 return None
552
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500553 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
554 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800555
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500556 result_buffer = _ffi.new("unsigned char**")
557 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400558 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800559
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700560 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400561 result = _ffi.buffer(
562 result_buffer[0], data_length
563 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700564 finally:
565 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500566 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800567 return result
568
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500569 def _cmp(op):
570 def f(self, other):
571 if not isinstance(other, X509Name):
572 return NotImplemented
573 result = _lib.X509_NAME_cmp(self._name, other._name)
574 return op(result, 0)
575 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800576
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500577 __eq__ = _cmp(__eq__)
578 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800579
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500580 __lt__ = _cmp(__lt__)
581 __le__ = _cmp(__le__)
582
583 __gt__ = _cmp(__gt__)
584 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800585
586 def __repr__(self):
587 """
588 String representation of an X509Name
589 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400590 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500591 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800592 self._name, result_buffer, len(result_buffer))
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700593 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800594
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500595 return "<X509Name object '%s'>" % (
596 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800597
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800598 def hash(self):
599 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200600 Return an integer representation of the first four bytes of the
601 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800602
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200603 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
604
605 :return: The (integer) hash of this name.
606 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800607 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500608 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800609
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800610 def der(self):
611 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200612 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800613
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200614 :return: The DER encoded form of this name.
615 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800616 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500617 result_buffer = _ffi.new('unsigned char**')
618 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400619 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800620
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500621 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
622 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800623 return string_result
624
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800625 def get_components(self):
626 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200627 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800628
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200629 :return: The components of this name.
630 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800631 """
632 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500633 for i in range(_lib.X509_NAME_entry_count(self._name)):
634 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800635
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500636 fname = _lib.X509_NAME_ENTRY_get_object(ent)
637 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800638
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500639 nid = _lib.OBJ_obj2nid(fname)
640 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800641
642 result.append((
Alex Gaynora738ed52015-09-05 11:17:10 -0400643 _ffi.string(name),
644 _ffi.string(
645 _lib.ASN1_STRING_data(fval),
646 _lib.ASN1_STRING_length(fval))))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800647
648 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200649
650
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800651X509NameType = X509Name
652
653
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800654class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200655 """
656 An X.509 v3 certificate extension.
657 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400658
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800659 def __init__(self, type_name, critical, value, subject=None, issuer=None):
660 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200661 Initializes an X509 extension.
662
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100663 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400664 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800665
Alex Gaynor5945ea82015-09-05 14:59:06 -0400666 :param bool critical: A flag indicating whether this is a critical
667 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800668
669 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200670 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800671
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200672 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800673 :type subject: :py:class:`X509`
674
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200675 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800676 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100677
Alex Chan54005ce2017-03-21 08:08:17 +0000678 .. _extension: https://www.openssl.org/docs/manmaster/man5/
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100679 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800680 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500681 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800682
Alex Gaynor5945ea82015-09-05 14:59:06 -0400683 # A context is necessary for any extension which uses the r2i
684 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
685 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500686 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800687
688 # We have no configuration database - but perhaps we should (some
689 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500690 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800691
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800692 # Initialize the subject and issuer, if appropriate. ctx is a local,
693 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400694 # any references, so no need to mess with reference counts or
695 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800696 if issuer is not None:
697 if not isinstance(issuer, X509):
698 raise TypeError("issuer must be an X509 instance")
699 ctx.issuer_cert = issuer._x509
700 if subject is not None:
701 if not isinstance(subject, X509):
702 raise TypeError("subject must be an X509 instance")
703 ctx.subject_cert = subject._x509
704
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800705 if critical:
706 # There are other OpenSSL APIs which would let us pass in critical
707 # separately, but they're harder to use, and since value is already
708 # a pile of crappy junk smuggling a ton of utterly important
709 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400710 # with strings? (However, X509V3_EXT_i2d in particular seems like
711 # it would be a better API to invoke. I do not know where to get
712 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500713 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800714
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500715 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
716 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800717 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500718 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800719
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400720 @property
721 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400722 return _lib.OBJ_obj2nid(
723 _lib.X509_EXTENSION_get_object(self._extension)
724 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400725
726 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500727 _lib.GEN_EMAIL: "email",
728 _lib.GEN_DNS: "DNS",
729 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400730 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400731
732 def _subjectAltNameString(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500733 method = _lib.X509V3_EXT_get(self._extension)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700734 _openssl_assert(method != _ffi.NULL)
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400735 ext_data = _lib.X509_EXTENSION_get_data(self._extension)
736 payload = ext_data.data
737 length = ext_data.length
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400738
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500739 payloadptr = _ffi.new("unsigned char**")
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400740 payloadptr[0] = payload
741
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500742 if method.it != _ffi.NULL:
743 ptr = _lib.ASN1_ITEM_ptr(method.it)
744 data = _lib.ASN1_item_d2i(_ffi.NULL, payloadptr, length, ptr)
745 names = _ffi.cast("GENERAL_NAMES*", data)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400746 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500747 names = _ffi.cast(
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400748 "GENERAL_NAMES*",
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500749 method.d2i(_ffi.NULL, payloadptr, length))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400750
Paul Kehrerb7d79502015-05-04 07:43:51 -0500751 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400752 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500753 for i in range(_lib.sk_GENERAL_NAME_num(names)):
754 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400755 try:
756 label = self._prefixes[name.type]
757 except KeyError:
758 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500759 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500760 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400761 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500762 value = _native(
763 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
764 parts.append(label + ":" + value)
765 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400766
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800767 def __str__(self):
768 """
769 :return: a nice text representation of the extension
770 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500771 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400772 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800773
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400774 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500775 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400776 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800777
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500778 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800779
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800780 def get_critical(self):
781 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200782 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800783
784 :return: The critical field.
785 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500786 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800787
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800788 def get_short_name(self):
789 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200790 Returns the short type name of this X.509 extension.
791
792 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800793
794 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200795 :rtype: :py:data:`bytes`
796
797 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800798 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500799 obj = _lib.X509_EXTENSION_get_object(self._extension)
800 nid = _lib.OBJ_obj2nid(obj)
801 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800802
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800803 def get_data(self):
804 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200805 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800806
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200807 :return: The ASN.1 encoded data of this X509 extension.
808 :rtype: :py:data:`bytes`
809
810 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800811 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500812 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
813 string_result = _ffi.cast('ASN1_STRING*', octet_result)
814 char_result = _lib.ASN1_STRING_data(string_result)
815 result_length = _lib.ASN1_STRING_length(string_result)
816 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800817
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200818
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800819X509ExtensionType = X509Extension
820
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800821
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800822class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200823 """
824 An X.509 certificate signing requests.
825 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400826
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800827 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500828 req = _lib.X509_REQ_new()
829 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Alex Gaynor5af32d02016-09-24 01:52:21 -0400830 # Default to version 0.
831 self.set_version(0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800832
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800833 def set_pubkey(self, pkey):
834 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200835 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800836
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200837 :param pkey: The public key to use.
838 :type pkey: :py:class:`PKey`
839
Dan Sully44e767a2016-06-04 18:05:27 -0700840 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800841 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500842 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400843 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800844
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800845 def get_pubkey(self):
846 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200847 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800848
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200849 :return: The public key.
850 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800851 """
852 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500853 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700854 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500855 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800856 pkey._only_public = True
857 return pkey
858
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800859 def set_version(self, version):
860 """
861 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
862 request.
863
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200864 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700865 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800866 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500867 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400868 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800869
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800870 def get_version(self):
871 """
872 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
873 request.
874
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200875 :return: The value of the version subfield.
876 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800877 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500878 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800879
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800880 def get_subject(self):
881 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200882 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800883
Cory Benfield881dc8d2015-12-09 08:25:14 +0000884 This creates a new :class:`X509Name` that wraps the underlying subject
885 name field on the certificate signing request. Modifying it will modify
886 the underlying signing request, and will have the effect of modifying
887 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200888
889 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000890 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800891 """
892 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500893 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700894 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800895
896 # The name is owned by the X509Req structure. As long as the X509Name
897 # Python object is alive, keep the X509Req Python object alive.
898 name._owner = self
899
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800900 return name
901
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800902 def add_extensions(self, extensions):
903 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200904 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800905
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200906 :param extensions: The X.509 extensions to add.
907 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700908 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800909 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500910 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700911 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800912
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500913 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800914
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800915 for ext in extensions:
916 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -0800917 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800918
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800919 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500920 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800921
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500922 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400923 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800924
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800925 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800926 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200927 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800928
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200929 :return: The X.509 extensions in this request.
930 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
931
932 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800933 """
934 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500935 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -0500936 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800937 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500938 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800939 exts.append(ext)
940 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800941
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800942 def sign(self, pkey, digest):
943 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -0700944 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800945
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200946 :param pkey: The key pair to sign with.
947 :type pkey: :py:class:`PKey`
948 :param digest: The name of the message digest to use for the signature,
Alex Gaynor239e2d32016-09-11 12:36:35 -0400949 e.g. :py:data:`b"sha256"`.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200950 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -0700951 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800952 """
953 if pkey._only_public:
954 raise ValueError("Key has only public part")
955
956 if not pkey._initialized:
957 raise ValueError("Key is uninitialized")
958
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500959 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500960 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800961 raise ValueError("No such digest method")
962
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500963 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400964 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800965
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800966 def verify(self, pkey):
967 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200968 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800969
Hynek Schlawack01c31672016-12-11 15:14:09 +0100970 :param PKey key: A public key.
971
972 :return: ``True`` if the signature is correct.
973 :rtype: bool
974
975 :raises OpenSSL.crypto.Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800976 problem verifying the signature.
977 """
978 if not isinstance(pkey, PKey):
979 raise TypeError("pkey must be a PKey instance")
980
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500981 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800982 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500983 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800984
985 return result
986
987
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800988X509ReqType = X509Req
989
990
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800991class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200992 """
993 An X.509 certificate.
994 """
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800995 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500996 x509 = _lib.X509_new()
Hynek Schlawack8a2dd772016-07-31 13:46:20 +0200997 _openssl_assert(x509 != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500998 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800999
Alex Gaynor9939ba12017-06-25 16:28:24 -04001000 def to_cryptography(self):
1001 """
1002 Export as a ``cryptography`` certificate.
1003
1004 :rtype: ``cryptography.x509.Certificate``
1005
1006 .. versionadded:: 17.1.0
1007 """
1008 from cryptography.hazmat.backends.openssl.x509 import _Certificate
1009 backend = _get_backend()
1010 return _Certificate(backend, self._x509)
1011
1012 @classmethod
1013 def from_cryptography(cls, crypto_cert):
1014 """
1015 Construct based on a ``cryptography`` *crypto_cert*.
1016
1017 :param crypto_key: A ``cryptography`` X.509 certificate.
1018 :type crypto_key: ``cryptography.x509.Certificate``
1019
1020 :rtype: PKey
1021
1022 .. versionadded:: 17.1.0
1023 """
1024 if not isinstance(crypto_cert, x509.Certificate):
1025 raise TypeError("Must be a certificate")
1026
1027 cert = cls()
1028 cert._x509 = crypto_cert._x509
1029 return cert
1030
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001031 def set_version(self, version):
1032 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001033 Set the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001034
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001035 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001036 :type version: :py:class:`int`
1037
Dan Sully44e767a2016-06-04 18:05:27 -07001038 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001039 """
1040 if not isinstance(version, int):
1041 raise TypeError("version must be an integer")
1042
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001043 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001044
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001045 def get_version(self):
1046 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001047 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001048
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001049 :return: The version number of the certificate.
1050 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001051 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001052 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001053
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001054 def get_pubkey(self):
1055 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001056 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001057
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001058 :return: The public key.
1059 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001060 """
1061 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001062 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1063 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001064 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001065 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001066 pkey._only_public = True
1067 return pkey
1068
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001069 def set_pubkey(self, pkey):
1070 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001071 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001072
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001073 :param pkey: The public key.
1074 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001075
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001076 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001077 """
1078 if not isinstance(pkey, PKey):
1079 raise TypeError("pkey must be a PKey instance")
1080
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001081 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001082 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001083
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001084 def sign(self, pkey, digest):
1085 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001086 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001087
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001088 :param pkey: The key to sign with.
1089 :type pkey: :py:class:`PKey`
1090
1091 :param digest: The name of the message digest to use.
1092 :type digest: :py:class:`bytes`
1093
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001094 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001095 """
1096 if not isinstance(pkey, PKey):
1097 raise TypeError("pkey must be a PKey instance")
1098
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001099 if pkey._only_public:
1100 raise ValueError("Key only has public part")
1101
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001102 if not pkey._initialized:
1103 raise ValueError("Key is uninitialized")
1104
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001105 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001106 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001107 raise ValueError("No such digest method")
1108
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001109 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001110 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001111
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001112 def get_signature_algorithm(self):
1113 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001114 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001115
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001116 :return: The name of the algorithm.
1117 :rtype: :py:class:`bytes`
1118
1119 :raises ValueError: If the signature algorithm is undefined.
1120
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001121 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001122 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001123 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1124 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001125 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001126 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001127 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001128
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001129 def digest(self, digest_name):
1130 """
1131 Return the digest of the X509 object.
1132
1133 :param digest_name: The name of the digest algorithm to use.
1134 :type digest_name: :py:class:`bytes`
1135
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001136 :return: The digest of the object, formatted as
1137 :py:const:`b":"`-delimited hex pairs.
1138 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001139 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001140 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001141 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001142 raise ValueError("No such digest method")
1143
Paul Kehrer9f9113a2016-09-20 20:10:25 -05001144 result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001145 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001146 result_length[0] = len(result_buffer)
1147
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001148 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001149 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001150 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001151
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001152 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001153 b16encode(ch).upper() for ch
1154 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001155
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001156 def subject_name_hash(self):
1157 """
1158 Return the hash of the X509 subject.
1159
1160 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001161 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001162 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001163 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001164
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001165 def set_serial_number(self, serial):
1166 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001167 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001168
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001169 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001170 :type serial: :py:class:`int`
1171
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001172 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001173 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001174 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001175 raise TypeError("serial must be an integer")
1176
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001177 hex_serial = hex(serial)[2:]
1178 if not isinstance(hex_serial, bytes):
1179 hex_serial = hex_serial.encode('ascii')
1180
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001181 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001182
1183 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001184 # it. If bignum is still NULL after this call, then the return value
1185 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001186 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001187
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001188 if bignum_serial[0] == _ffi.NULL:
1189 set_result = _lib.ASN1_INTEGER_set(
1190 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001191 if set_result:
1192 # TODO Not tested
1193 _raise_current_error()
1194 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001195 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1196 _lib.BN_free(bignum_serial[0])
1197 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001198 # TODO Not tested
1199 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001200 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1201 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001202 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001203
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001204 def get_serial_number(self):
1205 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001206 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001207
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001208 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001209 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001210 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001211 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1212 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001213 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001214 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001215 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001216 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001217 serial = int(hexstring_serial, 16)
1218 return serial
1219 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001220 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001221 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001222 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001223
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001224 def gmtime_adj_notAfter(self, amount):
1225 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001226 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001227
Dan Sully44e767a2016-06-04 18:05:27 -07001228 :param int amount: The number of seconds by which to adjust the
1229 timestamp.
1230 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001231 """
1232 if not isinstance(amount, int):
1233 raise TypeError("amount must be an integer")
1234
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001235 notAfter = _lib.X509_get_notAfter(self._x509)
1236 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001237
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001238 def gmtime_adj_notBefore(self, amount):
1239 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001240 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001241
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001242 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001243 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001244 """
1245 if not isinstance(amount, int):
1246 raise TypeError("amount must be an integer")
1247
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001248 notBefore = _lib.X509_get_notBefore(self._x509)
1249 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001250
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001251 def has_expired(self):
1252 """
1253 Check whether the certificate has expired.
1254
Dan Sully44e767a2016-06-04 18:05:27 -07001255 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1256 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001257 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001258 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001259 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001260
Paul Kehrerfde45c92016-01-21 12:57:37 -06001261 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001262
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001263 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001264 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001265
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001266 def get_notBefore(self):
1267 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001268 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001269
Paul Kehrerce98ee62017-06-21 06:59:58 -10001270 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001271
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001272 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001273
Dan Sully44e767a2016-06-04 18:05:27 -07001274 :return: A timestamp string, or ``None`` if there is none.
1275 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001276 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001277 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001278
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001279 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001280 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001281
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001282 def set_notBefore(self, when):
1283 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001284 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001285
Paul Kehrerce98ee62017-06-21 06:59:58 -10001286 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001287
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001288 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001289
Dan Sully44e767a2016-06-04 18:05:27 -07001290 :param bytes when: A timestamp string.
1291 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001292 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001293 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001294
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001295 def get_notAfter(self):
1296 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001297 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001298
Paul Kehrerce98ee62017-06-21 06:59:58 -10001299 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001300
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001301 YYYYMMDDhhmmssZ
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001302
Dan Sully44e767a2016-06-04 18:05:27 -07001303 :return: A timestamp string, or ``None`` if there is none.
1304 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001305 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001306 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001307
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001308 def set_notAfter(self, when):
1309 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001310 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001311
Paul Kehrerce98ee62017-06-21 06:59:58 -10001312 The timestamp is formatted as an ASN.1 TIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001313
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001314 YYYYMMDDhhmmssZ
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001315
Dan Sully44e767a2016-06-04 18:05:27 -07001316 :param bytes when: A timestamp string.
1317 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001318 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001319 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001320
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001321 def _get_name(self, which):
1322 name = X509Name.__new__(X509Name)
1323 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001324 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001325
1326 # The name is owned by the X509 structure. As long as the X509Name
1327 # Python object is alive, keep the X509 Python object alive.
1328 name._owner = self
1329
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001330 return name
1331
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001332 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001333 if not isinstance(name, X509Name):
1334 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001335 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001336 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001337
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001338 def get_issuer(self):
1339 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001340 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001341
Cory Benfielde6bcce82015-12-09 08:40:03 +00001342 This creates a new :class:`X509Name` that wraps the underlying issuer
1343 name field on the certificate. Modifying it will modify the underlying
1344 certificate, and will have the effect of modifying any other
1345 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001346
1347 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001348 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001349 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001350 return self._get_name(_lib.X509_get_issuer_name)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001351
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001352 def set_issuer(self, issuer):
1353 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001354 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001355
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001356 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001357 :type issuer: :py:class:`X509Name`
1358
Dan Sully44e767a2016-06-04 18:05:27 -07001359 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001360 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001361 return self._set_name(_lib.X509_set_issuer_name, issuer)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001362
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001363 def get_subject(self):
1364 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001365 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001366
Cory Benfielde6bcce82015-12-09 08:40:03 +00001367 This creates a new :class:`X509Name` that wraps the underlying subject
1368 name field on the certificate. Modifying it will modify the underlying
1369 certificate, and will have the effect of modifying any other
1370 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001371
1372 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001373 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001374 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001375 return self._get_name(_lib.X509_get_subject_name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001376
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001377 def set_subject(self, subject):
1378 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001379 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001380
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001381 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001382 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001383
Dan Sully44e767a2016-06-04 18:05:27 -07001384 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001385 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001386 return self._set_name(_lib.X509_set_subject_name, subject)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001387
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001388 def get_extension_count(self):
1389 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001390 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001391
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001392 :return: The number of extensions.
1393 :rtype: :py:class:`int`
1394
1395 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001396 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001397 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001398
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001399 def add_extensions(self, extensions):
1400 """
1401 Add extensions to the certificate.
1402
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001403 :param extensions: The extensions to add.
1404 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001405 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001406 """
1407 for ext in extensions:
1408 if not isinstance(ext, X509Extension):
1409 raise ValueError("One of the elements is not an X509Extension")
1410
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001411 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001412 if not add_result:
1413 _raise_current_error()
1414
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001415 def get_extension(self, index):
1416 """
1417 Get a specific extension of the certificate by index.
1418
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001419 Extensions on a certificate are kept in order. The index
1420 parameter selects which extension will be returned.
1421
1422 :param int index: The index of the extension to retrieve.
1423 :return: The extension at the specified index.
1424 :rtype: :py:class:`X509Extension`
1425 :raises IndexError: If the extension index was out of bounds.
1426
1427 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001428 """
1429 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001430 ext._extension = _lib.X509_get_ext(self._x509, index)
1431 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001432 raise IndexError("extension index out of bounds")
1433
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001434 extension = _lib.X509_EXTENSION_dup(ext._extension)
1435 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001436 return ext
1437
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001438
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001439X509Type = X509
1440
1441
Dan Sully44e767a2016-06-04 18:05:27 -07001442class X509StoreFlags(object):
1443 """
1444 Flags for X509 verification, used to change the behavior of
1445 :class:`X509Store`.
1446
1447 See `OpenSSL Verification Flags`_ for details.
1448
1449 .. _OpenSSL Verification Flags:
Alex Chan54005ce2017-03-21 08:08:17 +00001450 https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_flags.html
Dan Sully44e767a2016-06-04 18:05:27 -07001451 """
1452 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1453 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1454 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1455 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1456 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1457 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1458 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1459 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1460 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1461 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1462 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1463
1464
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001465class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001466 """
Dan Sully44e767a2016-06-04 18:05:27 -07001467 An X.509 store.
1468
1469 An X.509 store is used to describe a context in which to verify a
1470 certificate. A description of a context may include a set of certificates
1471 to trust, a set of certificate revocation lists, verification flags and
1472 more.
1473
1474 An X.509 store, being only a description, cannot be used by itself to
1475 verify a certificate. To carry out the actual verification process, see
1476 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001477 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001478
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001479 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001480 store = _lib.X509_STORE_new()
1481 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001482
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001483 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001484 """
Dan Sully44e767a2016-06-04 18:05:27 -07001485 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001486
Dan Sully44e767a2016-06-04 18:05:27 -07001487 Adding a certificate with this method adds this certificate as a
1488 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001489
1490 :param X509 cert: The certificate to add to this store.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001491
Dan Sully44e767a2016-06-04 18:05:27 -07001492 :raises TypeError: If the certificate is not an :class:`X509`.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001493
1494 :raises OpenSSL.crypto.Error: If OpenSSL was unhappy with your
1495 certificate.
1496
Dan Sully44e767a2016-06-04 18:05:27 -07001497 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001498 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001499 if not isinstance(cert, X509):
1500 raise TypeError()
1501
Dan Sully44e767a2016-06-04 18:05:27 -07001502 _openssl_assert(_lib.X509_STORE_add_cert(self._store, cert._x509) != 0)
1503
1504 def add_crl(self, crl):
1505 """
1506 Add a certificate revocation list to this store.
1507
1508 The certificate revocation lists added to a store will only be used if
1509 the associated flags are configured to check certificate revocation
1510 lists.
1511
1512 .. versionadded:: 16.1.0
1513
1514 :param CRL crl: The certificate revocation list to add to this store.
1515 :return: ``None`` if the certificate revocation list was added
1516 successfully.
1517 """
1518 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1519
1520 def set_flags(self, flags):
1521 """
1522 Set verification flags to this store.
1523
1524 Verification flags can be combined by oring them together.
1525
1526 .. note::
1527
1528 Setting a verification flag sometimes requires clients to add
1529 additional information to the store, otherwise a suitable error will
1530 be raised.
1531
1532 For example, in setting flags to enable CRL checking a
1533 suitable CRL must be added to the store otherwise an error will be
1534 raised.
1535
1536 .. versionadded:: 16.1.0
1537
1538 :param int flags: The verification flags to set on this store.
1539 See :class:`X509StoreFlags` for available constants.
1540 :return: ``None`` if the verification flags were successfully set.
1541 """
1542 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001543
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001544 def set_time(self, vfy_time):
1545 """
1546 Set the time against which the certificates are verified.
1547
1548 Normally the current time is used.
1549
1550 .. note::
1551
1552 For example, you can determine if a certificate was valid at a given
1553 time.
1554
Hynek Schlawackf6c96af2017-04-20 12:34:58 +02001555 .. versionadded:: 17.0.0
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001556
1557 :param datetime vfy_time: The verification time to set on this store.
1558 :return: ``None`` if the verification time was successfully set.
1559 """
1560 param = _lib.X509_VERIFY_PARAM_new()
1561 param = _ffi.gc(param, _lib.X509_VERIFY_PARAM_free)
1562
1563 _lib.X509_VERIFY_PARAM_set_time(param, int(vfy_time.strftime('%s')))
1564 _openssl_assert(_lib.X509_STORE_set1_param(self._store, param) != 0)
1565
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001566
1567X509StoreType = X509Store
1568
1569
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001570class X509StoreContextError(Exception):
1571 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001572 An exception raised when an error occurred while verifying a certificate
1573 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001574
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001575 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001576 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001577 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001578
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001579 def __init__(self, message, certificate):
1580 super(X509StoreContextError, self).__init__(message)
1581 self.certificate = certificate
1582
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001583
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001584class X509StoreContext(object):
1585 """
1586 An X.509 store context.
1587
Dan Sully44e767a2016-06-04 18:05:27 -07001588 An X.509 store context is used to carry out the actual verification process
1589 of a certificate in a described context. For describing such a context, see
1590 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001591
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001592 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1593 instance. It is dynamically allocated and automatically garbage
1594 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001595 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001596 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001597 :param X509Store store: The certificates which will be trusted for the
1598 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001599 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001600 """
1601
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001602 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001603 store_ctx = _lib.X509_STORE_CTX_new()
1604 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1605 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001606 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001607 # Make the store context available for use after instantiating this
1608 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001609 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001610 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001611
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001612 def _init(self):
1613 """
1614 Set up the store context for a subsequent verification operation.
1615 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001616 ret = _lib.X509_STORE_CTX_init(
1617 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1618 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001619 if ret <= 0:
1620 _raise_current_error()
1621
1622 def _cleanup(self):
1623 """
1624 Internally cleans up the store context.
1625
Dan Sully44e767a2016-06-04 18:05:27 -07001626 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001627 """
1628 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1629
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001630 def _exception_from_context(self):
1631 """
1632 Convert an OpenSSL native context error failure into a Python
1633 exception.
1634
Alex Gaynor5945ea82015-09-05 14:59:06 -04001635 When a call to native OpenSSL X509_verify_cert fails, additional
1636 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001637 """
1638 errors = [
1639 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1640 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1641 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001642 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001643 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001644 # A context error should always be associated with a certificate, so we
1645 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001646 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001647 _cert = _lib.X509_dup(_x509)
1648 pycert = X509.__new__(X509)
1649 pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001650 return X509StoreContextError(errors, pycert)
1651
Stephen Holsapple46a09252015-02-12 14:45:43 -08001652 def set_store(self, store):
1653 """
Dan Sully44e767a2016-06-04 18:05:27 -07001654 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001655
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001656 .. versionadded:: 0.15
1657
Dan Sully44e767a2016-06-04 18:05:27 -07001658 :param X509Store store: The store description which will be used for
1659 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001660 """
1661 self._store = store
1662
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001663 def verify_certificate(self):
1664 """
1665 Verify a certificate in a context.
1666
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001667 .. versionadded:: 0.15
1668
Alex Gaynorca87ff62015-09-04 23:31:03 -04001669 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001670 certificate in the context. Sets ``certificate`` attribute to
1671 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001672 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001673 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001674 # :meth:`verify_certificate` is called multiple times.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001675 self._init()
1676 ret = _lib.X509_verify_cert(self._store_ctx)
1677 self._cleanup()
1678 if ret <= 0:
1679 raise self._exception_from_context()
1680
1681
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001682def load_certificate(type, buffer):
1683 """
1684 Load a certificate from a buffer
1685
1686 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1687
Dan Sully44e767a2016-06-04 18:05:27 -07001688 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001689
1690 :return: The X509 object
1691 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001692 if isinstance(buffer, _text_type):
1693 buffer = buffer.encode("ascii")
1694
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001695 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001696
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001697 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001698 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001699 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001700 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001701 else:
1702 raise ValueError(
1703 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001704
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001705 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001706 _raise_current_error()
1707
1708 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001709 cert._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001710 return cert
1711
1712
1713def dump_certificate(type, cert):
1714 """
1715 Dump a certificate to a buffer
1716
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001717 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1718 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001719 :param cert: The certificate to dump
1720 :return: The buffer with the dumped certificate in
1721 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001722 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001723
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001724 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001725 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001726 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001727 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001728 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001729 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001730 else:
1731 raise ValueError(
1732 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1733 "FILETYPE_TEXT")
1734
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001735 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001736 return _bio_to_string(bio)
1737
1738
Cory Benfield6492f7c2015-10-27 16:57:58 +09001739def dump_publickey(type, pkey):
1740 """
Cory Benfield11c10192015-10-27 17:23:03 +09001741 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001742
Cory Benfield9c590b92015-10-28 14:55:05 +09001743 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001744 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001745 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001746 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001747 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001748 """
1749 bio = _new_mem_buf()
1750 if type == FILETYPE_PEM:
1751 write_bio = _lib.PEM_write_bio_PUBKEY
1752 elif type == FILETYPE_ASN1:
1753 write_bio = _lib.i2d_PUBKEY_bio
1754 else:
1755 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1756
1757 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001758 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001759 _raise_current_error()
1760
1761 return _bio_to_string(bio)
1762
1763
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001764def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1765 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001766 Dump the private key *pkey* into a buffer string encoded with the type
1767 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1768 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001769
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001770 :param type: The file type (one of :const:`FILETYPE_PEM`,
1771 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1772 :param PKey pkey: The PKey to dump
1773 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001774 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001775 the passphrase to use, or a callback for providing the passphrase.
1776
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001777 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001778 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001779 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001780 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001781
1782 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001783 if passphrase is None:
1784 raise TypeError(
1785 "if a value is given for cipher "
1786 "one must also be given for passphrase")
1787 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001788 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001789 raise ValueError("Invalid cipher name")
1790 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001791 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001792
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001793 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001794 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001795 result_code = _lib.PEM_write_bio_PrivateKey(
1796 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001797 helper.callback, helper.callback_args)
1798 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001799 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001800 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001801 elif type == FILETYPE_TEXT:
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001802 rsa = _ffi.gc(
1803 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1804 _lib.RSA_free
1805 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001806 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001807 else:
1808 raise ValueError(
1809 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1810 "FILETYPE_TEXT")
1811
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001812 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001813
1814 return _bio_to_string(bio)
1815
1816
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001817class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001818 """
1819 A certificate revocation.
1820 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001821 # http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_
1822 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1823 # OCSP_crl_reason_str. We use the latter, just like the command line
1824 # program.
1825 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001826 b"unspecified",
1827 b"keyCompromise",
1828 b"CACompromise",
1829 b"affiliationChanged",
1830 b"superseded",
1831 b"cessationOfOperation",
1832 b"certificateHold",
1833 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001834 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001835
1836 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001837 revoked = _lib.X509_REVOKED_new()
1838 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001839
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001840 def set_serial(self, hex_str):
1841 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001842 Set the serial number.
1843
1844 The serial number is formatted as a hexadecimal number encoded in
1845 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001846
Dan Sully44e767a2016-06-04 18:05:27 -07001847 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001848
Dan Sully44e767a2016-06-04 18:05:27 -07001849 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001850 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001851 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1852 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001853 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001854 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001855 if not bn_result:
1856 raise ValueError("bad hex string")
1857
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001858 asn1_serial = _ffi.gc(
1859 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1860 _lib.ASN1_INTEGER_free)
1861 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001862
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001863 def get_serial(self):
1864 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001865 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001866
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001867 The serial number is formatted as a hexadecimal number encoded in
1868 ASCII.
1869
1870 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001871 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001872 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001873 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001874
Alex Gaynor67903a62016-06-02 10:37:13 -07001875 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1876 _openssl_assert(asn1_int != _ffi.NULL)
1877 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1878 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001879 return _bio_to_string(bio)
1880
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001881 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001882 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1883 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001884 obj = _lib.X509_EXTENSION_get_object(ext)
1885 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001886 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001887 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001888 break
1889
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001890 def set_reason(self, reason):
1891 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001892 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001893
Dan Sully44e767a2016-06-04 18:05:27 -07001894 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001895
1896 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07001897 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001898
Dan Sully44e767a2016-06-04 18:05:27 -07001899 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001900
1901 .. seealso::
1902
Dan Sully44e767a2016-06-04 18:05:27 -07001903 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001904 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001905 """
1906 if reason is None:
1907 self._delete_reason()
1908 elif not isinstance(reason, bytes):
1909 raise TypeError("reason must be None or a byte string")
1910 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001911 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001912 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
1913
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001914 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07001915 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001916 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001917
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001918 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001919 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001920
1921 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001922 add_result = _lib.X509_REVOKED_add1_ext_i2d(
1923 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001924 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001925
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001926 def get_reason(self):
1927 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04001928 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001929
Dan Sully44e767a2016-06-04 18:05:27 -07001930 :return: The reason, or ``None`` if there is none.
1931 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001932
1933 .. seealso::
1934
Dan Sully44e767a2016-06-04 18:05:27 -07001935 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001936 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001937 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001938 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1939 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001940 obj = _lib.X509_EXTENSION_get_object(ext)
1941 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001942 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001943
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001944 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001945 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04001946 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001947 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04001948 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04001949 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001950
1951 return _bio_to_string(bio)
1952
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001953 def all_reasons(self):
1954 """
1955 Return a list of all the supported reason strings.
1956
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001957 This list is a copy; modifying it does not change the supported reason
1958 strings.
1959
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001960 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07001961 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001962 """
1963 return self._crl_reasons[:]
1964
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001965 def set_rev_date(self, when):
1966 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001967 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001968
Dan Sully44e767a2016-06-04 18:05:27 -07001969 :param bytes when: The timestamp of the revocation,
Paul Kehrerce98ee62017-06-21 06:59:58 -10001970 as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07001971 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001972 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001973 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1974 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001975
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001976 def get_rev_date(self):
1977 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001978 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001979
Paul Kehrerce98ee62017-06-21 06:59:58 -10001980 :return: The timestamp of the revocation, as ASN.1 TIME.
Dan Sully44e767a2016-06-04 18:05:27 -07001981 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001982 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001983 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1984 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001985
1986
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001987class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001988 """
1989 A certificate revocation list.
1990 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001991
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001992 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001993 crl = _lib.X509_CRL_new()
1994 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001995
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001996 def get_revoked(self):
1997 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001998 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001999
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002000 These revocations will be provided by value, not by reference.
2001 That means it's okay to mutate them: it won't affect this CRL.
2002
2003 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002004 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002005 """
2006 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07002007 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002008 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
2009 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04002010 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002011 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002012 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002013 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002014 if results:
2015 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002016
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002017 def add_revoked(self, revoked):
2018 """
2019 Add a revoked (by value not reference) to the CRL structure
2020
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002021 This revocation will be added by value, not by reference. That
2022 means it's okay to mutate it after adding: it won't affect
2023 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002024
Dan Sully44e767a2016-06-04 18:05:27 -07002025 :param Revoked revoked: The new revocation.
2026 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002027 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04002028 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002029 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002030
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002031 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002032 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002033
Dan Sully44e767a2016-06-04 18:05:27 -07002034 def get_issuer(self):
2035 """
2036 Get the CRL's issuer.
2037
2038 .. versionadded:: 16.1.0
2039
2040 :rtype: X509Name
2041 """
2042 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
2043 _openssl_assert(_issuer != _ffi.NULL)
2044 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
2045 issuer = X509Name.__new__(X509Name)
2046 issuer._name = _issuer
2047 return issuer
2048
2049 def set_version(self, version):
2050 """
2051 Set the CRL version.
2052
2053 .. versionadded:: 16.1.0
2054
2055 :param int version: The version of the CRL.
2056 :return: ``None``
2057 """
2058 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2059
2060 def _set_boundary_time(self, which, when):
2061 return _set_asn1_time(which(self._crl), when)
2062
2063 def set_lastUpdate(self, when):
2064 """
2065 Set when the CRL was last updated.
2066
Paul Kehrerce98ee62017-06-21 06:59:58 -10002067 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002068
2069 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002070
2071 .. versionadded:: 16.1.0
2072
2073 :param bytes when: A timestamp string.
2074 :return: ``None``
2075 """
2076 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2077
2078 def set_nextUpdate(self, when):
2079 """
2080 Set when the CRL will next be udpated.
2081
Paul Kehrerce98ee62017-06-21 06:59:58 -10002082 The timestamp is formatted as an ASN.1 TIME::
Dan Sully44e767a2016-06-04 18:05:27 -07002083
2084 YYYYMMDDhhmmssZ
Dan Sully44e767a2016-06-04 18:05:27 -07002085
2086 .. versionadded:: 16.1.0
2087
2088 :param bytes when: A timestamp string.
2089 :return: ``None``
2090 """
2091 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2092
2093 def sign(self, issuer_cert, issuer_key, digest):
2094 """
2095 Sign the CRL.
2096
2097 Signing a CRL enables clients to associate the CRL itself with an
2098 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2099 be signed by an issuer.
2100
2101 This method implicitly sets the issuer's name based on the issuer
2102 certificate and private key used to sign the CRL.
2103
2104 .. versionadded:: 16.1.0
2105
2106 :param X509 issuer_cert: The issuer's certificate.
2107 :param PKey issuer_key: The issuer's private key.
2108 :param bytes digest: The digest method to sign the CRL with.
2109 """
2110 digest_obj = _lib.EVP_get_digestbyname(digest)
2111 _openssl_assert(digest_obj != _ffi.NULL)
2112 _lib.X509_CRL_set_issuer_name(
2113 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2114 _lib.X509_CRL_sort(self._crl)
2115 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2116 _openssl_assert(result != 0)
2117
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002118 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002119 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002120 """
Dan Sully44e767a2016-06-04 18:05:27 -07002121 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002122
Dan Sully44e767a2016-06-04 18:05:27 -07002123 :param X509 cert: The certificate used to sign the CRL.
2124 :param PKey key: The key used to sign the CRL.
2125 :param int type: The export format, either :data:`FILETYPE_PEM`,
2126 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002127 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002128 :param bytes digest: The name of the message digest to use (eg
Alex Gaynor239e2d32016-09-11 12:36:35 -04002129 ``b"sha2566"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002130 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002131 """
Dan Sully44e767a2016-06-04 18:05:27 -07002132
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002133 if not isinstance(cert, X509):
2134 raise TypeError("cert must be an X509 instance")
2135 if not isinstance(key, PKey):
2136 raise TypeError("key must be a PKey instance")
2137 if not isinstance(type, int):
2138 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002139
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002140 if digest is _UNSPECIFIED:
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002141 _warn(
2142 "The default message digest (md5) is deprecated. "
2143 "Pass the name of a message digest explicitly.",
2144 category=DeprecationWarning,
2145 stacklevel=2,
2146 )
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002147 digest = b"md5"
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002148
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002149 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002150 if digest_obj == _ffi.NULL:
2151 raise ValueError("No such digest method")
2152
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002153 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002154 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002155
Alex Gaynora738ed52015-09-05 11:17:10 -04002156 # A scratch time object to give different values to different CRL
2157 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002158 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002159 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002160
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002161 _lib.X509_gmtime_adj(sometime, 0)
2162 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002163
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002164 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2165 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002166
Alex Gaynor5945ea82015-09-05 14:59:06 -04002167 _lib.X509_CRL_set_issuer_name(
2168 self._crl, _lib.X509_get_subject_name(cert._x509)
2169 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002170
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002171 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002172 if not sign_result:
2173 _raise_current_error()
2174
Dominic Chenf05b2122015-10-13 16:32:35 +00002175 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002176
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002177
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002178CRLType = CRL
2179
2180
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002181class PKCS7(object):
2182 def type_is_signed(self):
2183 """
2184 Check if this NID_pkcs7_signed object
2185
2186 :return: True if the PKCS7 is of type signed
2187 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002188 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002189
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002190 def type_is_enveloped(self):
2191 """
2192 Check if this NID_pkcs7_enveloped object
2193
2194 :returns: True if the PKCS7 is of type enveloped
2195 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002196 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002197
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002198 def type_is_signedAndEnveloped(self):
2199 """
2200 Check if this NID_pkcs7_signedAndEnveloped object
2201
2202 :returns: True if the PKCS7 is of type signedAndEnveloped
2203 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002204 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002205
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002206 def type_is_data(self):
2207 """
2208 Check if this NID_pkcs7_data object
2209
2210 :return: True if the PKCS7 is of type data
2211 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002212 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002213
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002214 def get_type_name(self):
2215 """
2216 Returns the type name of the PKCS7 structure
2217
2218 :return: A string with the typename
2219 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002220 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2221 string_type = _lib.OBJ_nid2sn(nid)
2222 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002223
Alex Chanc6077062016-11-18 13:53:39 +00002224
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002225PKCS7Type = PKCS7
2226
2227
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002228class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002229 """
2230 A PKCS #12 archive.
2231 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002232
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002233 def __init__(self):
2234 self._pkey = None
2235 self._cert = None
2236 self._cacerts = None
2237 self._friendlyname = None
2238
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002239 def get_certificate(self):
2240 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002241 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002242
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002243 :return: The certificate, or :py:const:`None` if there is none.
2244 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002245 """
2246 return self._cert
2247
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002248 def set_certificate(self, cert):
2249 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002250 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002251
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002252 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002253 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002254
Dan Sully44e767a2016-06-04 18:05:27 -07002255 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002256 """
2257 if not isinstance(cert, X509):
2258 raise TypeError("cert must be an X509 instance")
2259 self._cert = cert
2260
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002261 def get_privatekey(self):
2262 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002263 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002264
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002265 :return: The private key, or :py:const:`None` if there is none.
2266 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002267 """
2268 return self._pkey
2269
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002270 def set_privatekey(self, pkey):
2271 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002272 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002273
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002274 :param pkey: The new private key, or :py:const:`None` to unset it.
2275 :type pkey: :py:class:`PKey` or :py:const:`None`
2276
Dan Sully44e767a2016-06-04 18:05:27 -07002277 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002278 """
2279 if not isinstance(pkey, PKey):
2280 raise TypeError("pkey must be a PKey instance")
2281 self._pkey = pkey
2282
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002283 def get_ca_certificates(self):
2284 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002285 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002286
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002287 :return: A tuple with the CA certificates in the chain, or
2288 :py:const:`None` if there are none.
2289 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002290 """
2291 if self._cacerts is not None:
2292 return tuple(self._cacerts)
2293
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002294 def set_ca_certificates(self, cacerts):
2295 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002296 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002297
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002298 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2299 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002300 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002301
Dan Sully44e767a2016-06-04 18:05:27 -07002302 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002303 """
2304 if cacerts is None:
2305 self._cacerts = None
2306 else:
2307 cacerts = list(cacerts)
2308 for cert in cacerts:
2309 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002310 raise TypeError(
2311 "iterable must only contain X509 instances"
2312 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002313 self._cacerts = cacerts
2314
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002315 def set_friendlyname(self, name):
2316 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002317 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002318
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002319 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002320 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002321
Dan Sully44e767a2016-06-04 18:05:27 -07002322 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002323 """
2324 if name is None:
2325 self._friendlyname = None
2326 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002327 raise TypeError(
2328 "name must be a byte string or None (not %r)" % (name,)
2329 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002330 self._friendlyname = name
2331
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002332 def get_friendlyname(self):
2333 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002334 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002335
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002336 :returns: The friendly name, or :py:const:`None` if there is none.
2337 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002338 """
2339 return self._friendlyname
2340
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002341 def export(self, passphrase=None, iter=2048, maciter=1):
2342 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002343 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002344
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002345 For more information, see the :c:func:`PKCS12_create` man page.
2346
2347 :param passphrase: The passphrase used to encrypt the structure. Unlike
2348 some other passphrase arguments, this *must* be a string, not a
2349 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002350 :type passphrase: :py:data:`bytes`
2351
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002352 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002353 :type iter: :py:data:`int`
2354
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002355 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002356 :type maciter: :py:data:`int`
2357
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002358 :return: The string representation of the PKCS #12 structure.
2359 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002360 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002361 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002362
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002363 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002364 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002365 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002366 cacerts = _lib.sk_X509_new_null()
2367 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002368 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002369 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002370
2371 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002372 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002373
2374 friendlyname = self._friendlyname
2375 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002376 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002377
2378 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002379 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002380 else:
2381 pkey = self._pkey._pkey
2382
2383 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002384 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002385 else:
2386 cert = self._cert._x509
2387
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002388 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002389 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002390 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2391 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002392 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002393 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002394 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002395 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002396
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002397 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002398 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002399 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002400
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002401
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002402PKCS12Type = PKCS12
2403
2404
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002405class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002406 """
2407 A Netscape SPKI object.
2408 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002409
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002410 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002411 spki = _lib.NETSCAPE_SPKI_new()
2412 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002413
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002414 def sign(self, pkey, digest):
2415 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002416 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002417
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002418 :param pkey: The private key to sign with.
2419 :type pkey: :py:class:`PKey`
2420
2421 :param digest: The message digest to use.
2422 :type digest: :py:class:`bytes`
2423
Dan Sully44e767a2016-06-04 18:05:27 -07002424 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002425 """
2426 if pkey._only_public:
2427 raise ValueError("Key has only public part")
2428
2429 if not pkey._initialized:
2430 raise ValueError("Key is uninitialized")
2431
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002432 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002433 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002434 raise ValueError("No such digest method")
2435
Alex Gaynor5945ea82015-09-05 14:59:06 -04002436 sign_result = _lib.NETSCAPE_SPKI_sign(
2437 self._spki, pkey._pkey, digest_obj
2438 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002439 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002440
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002441 def verify(self, key):
2442 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002443 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002444
Hynek Schlawack01c31672016-12-11 15:14:09 +01002445 :param PKey key: The public key that signature is supposedly from.
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002446
Hynek Schlawack01c31672016-12-11 15:14:09 +01002447 :return: ``True`` if the signature is correct.
2448 :rtype: bool
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002449
Hynek Schlawack01c31672016-12-11 15:14:09 +01002450 :raises OpenSSL.crypto.Error: If the signature is invalid, or there was
2451 a problem verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002452 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002453 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002454 if answer <= 0:
2455 _raise_current_error()
2456 return True
2457
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002458 def b64_encode(self):
2459 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002460 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002461
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002462 :return: The base64 encoded string.
2463 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002464 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002465 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2466 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002467 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002468 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002469
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002470 def get_pubkey(self):
2471 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002472 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002473
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002474 :return: The public key.
2475 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002476 """
2477 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002478 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002479 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002480 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002481 pkey._only_public = True
2482 return pkey
2483
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002484 def set_pubkey(self, pkey):
2485 """
2486 Set the public key of the certificate
2487
2488 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002489 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002490 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002491 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002492 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002493
2494
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002495NetscapeSPKIType = NetscapeSPKI
2496
2497
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002498class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002499 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002500 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002501 raise ValueError(
2502 "only FILETYPE_PEM key format supports encryption"
2503 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002504 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002505 self._more_args = more_args
2506 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002507 self._problems = []
2508
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002509 @property
2510 def callback(self):
2511 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002512 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002513 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002514 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002515 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002516 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002517 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002518 raise TypeError(
2519 "Last argument must be a byte string or a callable."
2520 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002521
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002522 @property
2523 def callback_args(self):
2524 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002525 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002526 elif isinstance(self._passphrase, bytes):
2527 return self._passphrase
2528 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002529 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002530 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002531 raise TypeError(
2532 "Last argument must be a byte string or a callable."
2533 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002534
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002535 def raise_if_problem(self, exceptionType=Error):
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002536 if self._problems:
Greg Bowser36eb2de2017-01-24 11:38:55 -05002537
2538 # Flush the OpenSSL error queue
2539 try:
2540 _exception_from_error_queue(exceptionType)
2541 except exceptionType:
2542 pass
2543
2544 raise self._problems.pop(0)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002545
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002546 def _read_passphrase(self, buf, size, rwflag, userdata):
2547 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002548 if self._more_args:
2549 result = self._passphrase(size, rwflag, userdata)
2550 else:
2551 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002552 if not isinstance(result, bytes):
2553 raise ValueError("String expected")
2554 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002555 if self._truncate:
2556 result = result[:size]
2557 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002558 raise ValueError(
2559 "passphrase returned by callback is too long"
2560 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002561 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002562 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002563 return len(result)
2564 except Exception as e:
2565 self._problems.append(e)
2566 return 0
2567
2568
Cory Benfield6492f7c2015-10-27 16:57:58 +09002569def load_publickey(type, buffer):
2570 """
Cory Benfield11c10192015-10-27 17:23:03 +09002571 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002572
Cory Benfield9c590b92015-10-28 14:55:05 +09002573 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002574 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002575 :param buffer: The buffer the key is stored in.
2576 :type buffer: A Python string object, either unicode or bytestring.
2577 :return: The PKey object.
2578 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002579 """
2580 if isinstance(buffer, _text_type):
2581 buffer = buffer.encode("ascii")
2582
2583 bio = _new_mem_buf(buffer)
2584
2585 if type == FILETYPE_PEM:
2586 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2587 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2588 elif type == FILETYPE_ASN1:
2589 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2590 else:
2591 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2592
2593 if evp_pkey == _ffi.NULL:
2594 _raise_current_error()
2595
2596 pkey = PKey.__new__(PKey)
2597 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002598 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002599 return pkey
2600
2601
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002602def load_privatekey(type, buffer, passphrase=None):
2603 """
2604 Load a private key from a buffer
2605
2606 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2607 :param buffer: The buffer the key is stored in
2608 :param passphrase: (optional) if encrypted PEM format, this can be
2609 either the passphrase to use, or a callback for
2610 providing the passphrase.
2611
2612 :return: The PKey object
2613 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002614 if isinstance(buffer, _text_type):
2615 buffer = buffer.encode("ascii")
2616
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002617 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002618
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002619 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002620 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002621 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2622 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002623 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002624 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002625 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002626 else:
2627 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2628
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002629 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002630 _raise_current_error()
2631
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002632 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002633 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002634 return pkey
2635
2636
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002637def dump_certificate_request(type, req):
2638 """
2639 Dump a certificate request to a buffer
2640
2641 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2642 :param req: The certificate request to dump
2643 :return: The buffer with the dumped certificate request in
2644 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002645 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002646
2647 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002648 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002649 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002650 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002651 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002652 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002653 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002654 raise ValueError(
2655 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2656 "FILETYPE_TEXT"
2657 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002658
Alex Gaynor09a386e2016-07-03 09:32:44 -04002659 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002660
2661 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002662
2663
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002664def load_certificate_request(type, buffer):
2665 """
2666 Load a certificate request from a buffer
2667
2668 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2669 :param buffer: The buffer the certificate request is stored in
2670 :return: The X509Req object
2671 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002672 if isinstance(buffer, _text_type):
2673 buffer = buffer.encode("ascii")
2674
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002675 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002676
2677 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002678 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002679 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002680 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002681 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002682 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002683
Alex Gaynoradd5b072016-06-04 21:04:00 -07002684 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002685
2686 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002687 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002688 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002689
2690
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002691def sign(pkey, data, digest):
2692 """
2693 Sign data with a digest
2694
2695 :param pkey: Pkey to sign with
2696 :param data: data to be signed
2697 :param digest: message digest to use
2698 :return: signature
2699 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002700 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002701
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002702 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002703 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002704 raise ValueError("No such digest method")
2705
Alex Gaynor67903a62016-06-02 10:37:13 -07002706 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002707 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002708
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002709 _lib.EVP_SignInit(md_ctx, digest_obj)
2710 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002711
Colleen Murphye09399b2016-03-01 17:40:49 -08002712 pkey_length = (PKey.bits(pkey) + 7) // 8
2713 signature_buffer = _ffi.new("unsigned char[]", pkey_length)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002714 signature_length = _ffi.new("unsigned int*")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002715 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002716 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002717 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002718
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002719 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002720
2721
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002722def verify(cert, signature, data, digest):
2723 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002724 Verify a signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002725
2726 :param cert: signing certificate (X509 object)
2727 :param signature: signature returned by sign function
2728 :param data: data to be verified
2729 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002730 :return: ``None`` if the signature is correct, raise exception otherwise.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002731 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002732 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002733
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002734 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002735 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002736 raise ValueError("No such digest method")
2737
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002738 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002739 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002740 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002741
Alex Gaynor67903a62016-06-02 10:37:13 -07002742 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002743 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002744
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002745 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2746 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002747 verify_result = _lib.EVP_VerifyFinal(
2748 md_ctx, signature, len(signature), pkey
2749 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002750
2751 if verify_result != 1:
2752 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002753
2754
Dominic Chenf05b2122015-10-13 16:32:35 +00002755def dump_crl(type, crl):
2756 """
2757 Dump a certificate revocation list to a buffer.
2758
2759 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2760 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002761 :param CRL crl: The CRL to dump.
2762
Dominic Chenf05b2122015-10-13 16:32:35 +00002763 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002764 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002765 """
2766 bio = _new_mem_buf()
2767
2768 if type == FILETYPE_PEM:
2769 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2770 elif type == FILETYPE_ASN1:
2771 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2772 elif type == FILETYPE_TEXT:
2773 ret = _lib.X509_CRL_print(bio, crl._crl)
2774 else:
2775 raise ValueError(
2776 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2777 "FILETYPE_TEXT")
2778
2779 assert ret == 1
2780 return _bio_to_string(bio)
2781
2782
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002783def load_crl(type, buffer):
2784 """
2785 Load a certificate revocation list from a buffer
2786
2787 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2788 :param buffer: The buffer the CRL is stored in
2789
2790 :return: The PKey object
2791 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002792 if isinstance(buffer, _text_type):
2793 buffer = buffer.encode("ascii")
2794
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002795 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002796
2797 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002798 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002799 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002800 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002801 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002802 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2803
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002804 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002805 _raise_current_error()
2806
2807 result = CRL.__new__(CRL)
2808 result._crl = crl
2809 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002810
2811
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002812def load_pkcs7_data(type, buffer):
2813 """
2814 Load pkcs7 data from a buffer
2815
2816 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2817 :param buffer: The buffer with the pkcs7 data.
2818 :return: The PKCS7 object
2819 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002820 if isinstance(buffer, _text_type):
2821 buffer = buffer.encode("ascii")
2822
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002823 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002824
2825 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002826 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002827 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002828 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002829 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002830 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2831
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002832 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002833 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002834
2835 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002836 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002837 return pypkcs7
2838
2839
Stephen Holsapple38482622014-04-05 20:29:34 -07002840def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002841 """
2842 Load a PKCS12 object from a buffer
2843
2844 :param buffer: The buffer the certificate is stored in
2845 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2846 :returns: The PKCS12 object
2847 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002848 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002849
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002850 if isinstance(buffer, _text_type):
2851 buffer = buffer.encode("ascii")
2852
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002853 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002854
Stephen Holsapple38482622014-04-05 20:29:34 -07002855 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2856 # password based encryption no password and a zero length password are two
2857 # different things, but OpenSSL implementation will try both to figure out
2858 # which one works.
2859 if not passphrase:
2860 passphrase = _ffi.NULL
2861
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002862 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2863 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002864 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002865 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002866
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002867 pkey = _ffi.new("EVP_PKEY**")
2868 cert = _ffi.new("X509**")
2869 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002870
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002871 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002872 if not parse_result:
2873 _raise_current_error()
2874
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002875 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002876
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002877 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
2878 # queue for no particular reason. This error isn't interesting to anyone
2879 # outside this function. It's not even interesting to us. Get rid of it.
2880 try:
2881 _raise_current_error()
2882 except Error:
2883 pass
2884
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002885 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002886 pykey = None
2887 else:
2888 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002889 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002890
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002891 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002892 pycert = None
2893 friendlyname = None
2894 else:
2895 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002896 pycert._x509 = _ffi.gc(cert[0], _lib.X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002897
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002898 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04002899 friendlyname_buffer = _lib.X509_alias_get0(
2900 cert[0], friendlyname_length
2901 )
2902 friendlyname = _ffi.buffer(
2903 friendlyname_buffer, friendlyname_length[0]
2904 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002905 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002906 friendlyname = None
2907
2908 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002909 for i in range(_lib.sk_X509_num(cacerts)):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002910 pycacert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002911 pycacert._x509 = _lib.sk_X509_value(cacerts, i)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002912 pycacerts.append(pycacert)
2913 if not pycacerts:
2914 pycacerts = None
2915
2916 pkcs12 = PKCS12.__new__(PKCS12)
2917 pkcs12._pkey = pykey
2918 pkcs12._cert = pycert
2919 pkcs12._cacerts = pycacerts
2920 pkcs12._friendlyname = friendlyname
2921 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05002922
2923
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05002924# There are no direct unit tests for this initialization. It is tested
2925# indirectly since it is necessary for functions like dump_privatekey when
2926# using encryption.
2927#
2928# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
2929# and some other similar tests may fail without this (though they may not if
2930# the Python runtime has already done some initialization of the underlying
2931# OpenSSL library (and is linked against the same one that cryptography is
2932# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05002933_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05002934
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05002935# This is similar but exercised mainly by exception_from_error_queue. It calls
2936# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
2937_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002938
2939
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002940# Set the default string mask to match OpenSSL upstream (since 2005) and
2941# RFC5280 recommendations.
2942_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')