blob: 3c8b26b69256d7e5895a265322436b8d062a0f2c [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
Paul Kehrer72d968b2016-07-29 15:31:04 +080013from cryptography.hazmat.primitives.asymmetric import dsa, rsa
14
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050015from OpenSSL._util import (
16 ffi as _ffi,
17 lib as _lib,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050018 exception_from_error_queue as _exception_from_error_queue,
19 byte_string as _byte_string,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040020 native as _native,
21 UNSPECIFIED as _UNSPECIFIED,
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -040022 text_to_bytes_and_warn as _text_to_bytes_and_warn,
Alex Gaynor67903a62016-06-02 10:37:13 -070023 make_assert as _make_assert,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040024)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080025
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050026FILETYPE_PEM = _lib.SSL_FILETYPE_PEM
27FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080028
29# TODO This was an API mistake. OpenSSL has no such constant.
30FILETYPE_TEXT = 2 ** 16 - 1
31
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050032TYPE_RSA = _lib.EVP_PKEY_RSA
33TYPE_DSA = _lib.EVP_PKEY_DSA
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -080034
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080035
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050036class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050037 """
38 An error occurred in an `OpenSSL.crypto` API.
39 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050040
41
42_raise_current_error = partial(_exception_from_error_queue, Error)
Alex Gaynor67903a62016-06-02 10:37:13 -070043_openssl_assert = _make_assert(Error)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050044
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070045
Paul Kehrereb633842016-10-06 11:22:01 +020046def _get_backend():
47 """
48 Importing the backend from cryptography has the side effect of activating
49 the osrandom engine. This mutates the global state of OpenSSL in the
50 process and causes issues for various programs that use subinterpreters or
51 embed Python. By putting the import in this function we can avoid
52 triggering this side effect unless _get_backend is called.
53 """
54 from cryptography.hazmat.backends.openssl.backend import backend
55 return backend
56
57
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050058def _untested_error(where):
59 """
60 An OpenSSL API failed somehow. Additionally, the failure which was
61 encountered isn't one that's exercised by the test suite so future behavior
62 of pyOpenSSL is now somewhat less predictable.
63 """
64 raise RuntimeError("Unknown %s failure" % (where,))
65
66
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050067def _new_mem_buf(buffer=None):
68 """
69 Allocate a new OpenSSL memory BIO.
70
71 Arrange for the garbage collector to clean it up automatically.
72
73 :param buffer: None or some bytes to use to put into the BIO so that they
74 can be read out.
75 """
76 if buffer is None:
77 bio = _lib.BIO_new(_lib.BIO_s_mem())
78 free = _lib.BIO_free
79 else:
80 data = _ffi.new("char[]", buffer)
81 bio = _lib.BIO_new_mem_buf(data, len(buffer))
Alex Gaynor5945ea82015-09-05 14:59:06 -040082
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050083 # Keep the memory alive as long as the bio is alive!
84 def free(bio, ref=data):
85 return _lib.BIO_free(bio)
86
Alex Gaynorfb8a2a12016-06-04 18:26:26 -070087 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050088
89 bio = _ffi.gc(bio, free)
90 return bio
91
92
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080093def _bio_to_string(bio):
94 """
95 Copy the contents of an OpenSSL BIO object into a Python byte string.
96 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050097 result_buffer = _ffi.new('char**')
98 buffer_length = _lib.BIO_get_mem_data(bio, result_buffer)
99 return _ffi.buffer(result_buffer[0], buffer_length)[:]
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800100
101
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800102def _set_asn1_time(boundary, when):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500103 """
104 The the time value of an ASN1 time object.
105
106 @param boundary: An ASN1_GENERALIZEDTIME pointer (or an object safely
107 castable to that type) which will have its value set.
108 @param when: A string representation of the desired time value.
109
110 @raise TypeError: If C{when} is not a L{bytes} string.
111 @raise ValueError: If C{when} does not represent a time in the required
112 format.
113 @raise RuntimeError: If the time value cannot be set for some other
114 (unspecified) reason.
115 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800116 if not isinstance(when, bytes):
117 raise TypeError("when must be a byte string")
118
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500119 set_result = _lib.ASN1_GENERALIZEDTIME_set_string(
120 _ffi.cast('ASN1_GENERALIZEDTIME*', boundary), when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800121 if set_result == 0:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500122 dummy = _ffi.gc(_lib.ASN1_STRING_new(), _lib.ASN1_STRING_free)
123 _lib.ASN1_STRING_set(dummy, when, len(when))
124 check_result = _lib.ASN1_GENERALIZEDTIME_check(
125 _ffi.cast('ASN1_GENERALIZEDTIME*', dummy))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800126 if not check_result:
127 raise ValueError("Invalid string")
128 else:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500129 _untested_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800130
Alex Gaynor510293e2016-06-02 12:07:59 -0700131
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800132def _get_asn1_time(timestamp):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500133 """
134 Retrieve the time value of an ASN1 time object.
135
136 @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to
137 that type) from which the time value will be retrieved.
138
139 @return: The time value from C{timestamp} as a L{bytes} string in a certain
140 format. Or C{None} if the object contains no time value.
141 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500142 string_timestamp = _ffi.cast('ASN1_STRING*', timestamp)
143 if _lib.ASN1_STRING_length(string_timestamp) == 0:
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800144 return None
Alex Gaynor5945ea82015-09-05 14:59:06 -0400145 elif (
146 _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME
147 ):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500148 return _ffi.string(_lib.ASN1_STRING_data(string_timestamp))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800149 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500150 generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**")
151 _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp)
152 if generalized_timestamp[0] == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500153 # This may happen:
154 # - if timestamp was not an ASN1_TIME
155 # - if allocating memory for the ASN1_GENERALIZEDTIME failed
156 # - if a copy of the time data from timestamp cannot be made for
157 # the newly allocated ASN1_GENERALIZEDTIME
158 #
159 # These are difficult to test. cffi enforces the ASN1_TIME type.
160 # Memory allocation failures are a pain to trigger
161 # deterministically.
162 _untested_error("ASN1_TIME_to_generalizedtime")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800163 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500164 string_timestamp = _ffi.cast(
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800165 "ASN1_STRING*", generalized_timestamp[0])
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500166 string_data = _lib.ASN1_STRING_data(string_timestamp)
167 string_result = _ffi.string(string_data)
168 _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0])
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800169 return string_result
170
171
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800172class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200173 """
174 A class representing an DSA or RSA public key or key pair.
175 """
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800176 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800177 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800178
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800179 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500180 pkey = _lib.EVP_PKEY_new()
181 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800182 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800183
Paul Kehrer72d968b2016-07-29 15:31:04 +0800184 def to_cryptography_key(self):
185 """
186 Export as a ``cryptography`` key.
187
188 :rtype: One of ``cryptography``'s `key interfaces`_.
189
190 .. _key interfaces: https://cryptography.io/en/latest/hazmat/\
191 primitives/asymmetric/rsa/#key-interfaces
192
193 .. versionadded:: 16.1.0
194 """
Paul Kehrereb633842016-10-06 11:22:01 +0200195 backend = _get_backend()
Paul Kehrer72d968b2016-07-29 15:31:04 +0800196 if self._only_public:
197 return backend._evp_pkey_to_public_key(self._pkey)
198 else:
199 return backend._evp_pkey_to_private_key(self._pkey)
200
201 @classmethod
202 def from_cryptography_key(cls, crypto_key):
203 """
204 Construct based on a ``cryptography`` *crypto_key*.
205
206 :param crypto_key: A ``cryptography`` key.
207 :type crypto_key: One of ``cryptography``'s `key interfaces`_.
208
209 :rtype: PKey
210
211 .. versionadded:: 16.1.0
212 """
213 pkey = cls()
214 if not isinstance(crypto_key, (rsa.RSAPublicKey, rsa.RSAPrivateKey,
215 dsa.DSAPublicKey, dsa.DSAPrivateKey)):
216 raise TypeError("Unsupported key type")
217
218 pkey._pkey = crypto_key._evp_pkey
219 if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)):
220 pkey._only_public = True
221 pkey._initialized = True
222 return pkey
223
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800224 def generate_key(self, type, bits):
225 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700226 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800227
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200228 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800229
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200230 :param type: The key type.
231 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
232 :param bits: The number of bits.
233 :type bits: :py:data:`int` ``>= 0``
234 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
235 of the appropriate type.
236 :raises ValueError: If the number of bits isn't an integer of
237 the appropriate size.
Dan Sully44e767a2016-06-04 18:05:27 -0700238 :return: ``None``
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800239 """
240 if not isinstance(type, int):
241 raise TypeError("type must be an integer")
242
243 if not isinstance(bits, int):
244 raise TypeError("bits must be an integer")
245
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800246 # TODO Check error return
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500247 exponent = _lib.BN_new()
248 exponent = _ffi.gc(exponent, _lib.BN_free)
249 _lib.BN_set_word(exponent, _lib.RSA_F4)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800250
251 if type == TYPE_RSA:
252 if bits <= 0:
253 raise ValueError("Invalid number of bits")
254
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500255 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800256
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500257 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400258 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800259
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500260 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400261 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800262
263 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400264 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700265 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400266
267 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400268 res = _lib.DSA_generate_parameters_ex(
269 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
270 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700271 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400272
273 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
274 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800275 else:
276 raise Error("No such key type")
277
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800278 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800279
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800280 def check(self):
281 """
282 Check the consistency of an RSA private key.
283
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200284 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
285
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800286 :return: True if key is consistent.
287 :raise Error: if the key is inconsistent.
288 :raise TypeError: if the key is of a type which cannot be checked.
289 Only RSA keys can currently be checked.
290 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800291 if self._only_public:
292 raise TypeError("public key only")
293
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100294 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800295 raise TypeError("key type unsupported")
296
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500297 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
298 rsa = _ffi.gc(rsa, _lib.RSA_free)
299 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800300 if result:
301 return True
302 _raise_current_error()
303
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800304 def type(self):
305 """
306 Returns the type of the key
307
308 :return: The type of the key.
309 """
Alex Gaynorc84567b2016-03-16 07:45:09 -0400310 return _lib.Cryptography_EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800311
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800312 def bits(self):
313 """
314 Returns the number of bits of the key
315
316 :return: The number of bits of the key.
317 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500318 return _lib.EVP_PKEY_bits(self._pkey)
Alex Chanc6077062016-11-18 13:53:39 +0000319
320
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800321PKeyType = PKey
322
323
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400324class _EllipticCurve(object):
325 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400326 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400327
328 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
329 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
330 instances each of which represents one curve supported by the system.
331 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400332 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400333 _curves = None
334
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400335 if _PY3:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400336 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400337 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400338 """
339 Implement cooperation with the right-hand side argument of ``!=``.
340
341 Python 3 seems to have dropped this cooperation in this very narrow
342 circumstance.
343 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400344 if isinstance(other, _EllipticCurve):
345 return super(_EllipticCurve, self).__ne__(other)
346 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400347
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400348 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400349 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400350 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400351 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400352
353 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400354
355 :return: A :py:type:`set` of ``cls`` instances giving the names of the
356 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400357 """
358 if lib.Cryptography_HAS_EC:
359 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
360 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
Alex Gaynor5945ea82015-09-05 14:59:06 -0400361 # The return value on this call should be num_curves again. We
362 # could check it to make sure but if it *isn't* then.. what could
363 # we do? Abort the whole process, I suppose...? -exarkun
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400364 lib.EC_get_builtin_curves(builtin_curves, num_curves)
365 return set(
366 cls.from_nid(lib, c.nid)
367 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400368 return set()
369
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400370 @classmethod
371 def _get_elliptic_curves(cls, lib):
372 """
373 Get, cache, and return the curves supported by OpenSSL.
374
375 :param lib: The OpenSSL library binding object.
376
377 :return: A :py:type:`set` of ``cls`` instances giving the names of the
378 elliptic curves the underlying library supports.
379 """
380 if cls._curves is None:
381 cls._curves = cls._load_elliptic_curves(lib)
382 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400383
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400384 @classmethod
385 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400386 """
387 Instantiate a new :py:class:`_EllipticCurve` associated with the given
388 OpenSSL NID.
389
390 :param lib: The OpenSSL library binding object.
391
392 :param nid: The OpenSSL NID the resulting curve object will represent.
393 This must be a curve NID (and not, for example, a hash NID) or
394 subsequent operations will fail in unpredictable ways.
395 :type nid: :py:class:`int`
396
397 :return: The curve object.
398 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400399 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
400
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400401 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400402 """
403 :param _lib: The :py:mod:`cryptography` binding instance used to
404 interface with OpenSSL.
405
406 :param _nid: The OpenSSL NID identifying the curve this object
407 represents.
408 :type _nid: :py:class:`int`
409
410 :param name: The OpenSSL short name identifying the curve this object
411 represents.
412 :type name: :py:class:`unicode`
413 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400414 self._lib = lib
415 self._nid = nid
416 self.name = name
417
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400418 def __repr__(self):
419 return "<Curve %r>" % (self.name,)
420
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400421 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400422 """
423 Create a new OpenSSL EC_KEY structure initialized to use this curve.
424
425 The structure is automatically garbage collected when the Python object
426 is garbage collected.
427 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400428 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
429 return _ffi.gc(key, _lib.EC_KEY_free)
430
431
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400432def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400433 """
434 Return a set of objects representing the elliptic curves supported in the
435 OpenSSL build in use.
436
437 The curve objects have a :py:class:`unicode` ``name`` attribute by which
438 they identify themselves.
439
440 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400441 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
442 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400443 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400444 return _EllipticCurve._get_elliptic_curves(_lib)
445
446
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400447def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400448 """
449 Return a single curve object selected by name.
450
451 See :py:func:`get_elliptic_curves` for information about curve objects.
452
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400453 :param name: The OpenSSL short name identifying the curve object to
454 retrieve.
455 :type name: :py:class:`unicode`
456
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400457 If the named curve is not supported then :py:class:`ValueError` is raised.
458 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400459 for curve in get_elliptic_curves():
460 if curve.name == name:
461 return curve
462 raise ValueError("unknown curve name", name)
463
464
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800465class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200466 """
467 An X.509 Distinguished Name.
468
469 :ivar countryName: The country of the entity.
470 :ivar C: Alias for :py:attr:`countryName`.
471
472 :ivar stateOrProvinceName: The state or province of the entity.
473 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
474
475 :ivar localityName: The locality of the entity.
476 :ivar L: Alias for :py:attr:`localityName`.
477
478 :ivar organizationName: The organization name of the entity.
479 :ivar O: Alias for :py:attr:`organizationName`.
480
481 :ivar organizationalUnitName: The organizational unit of the entity.
482 :ivar OU: Alias for :py:attr:`organizationalUnitName`
483
484 :ivar commonName: The common name of the entity.
485 :ivar CN: Alias for :py:attr:`commonName`.
486
487 :ivar emailAddress: The e-mail address of the entity.
488 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400489
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800490 def __init__(self, name):
491 """
492 Create a new X509Name, copying the given X509Name instance.
493
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200494 :param name: The name to copy.
495 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800496 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500497 name = _lib.X509_NAME_dup(name._name)
498 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800499
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800500 def __setattr__(self, name, value):
501 if name.startswith('_'):
502 return super(X509Name, self).__setattr__(name, value)
503
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800504 # Note: we really do not want str subclasses here, so we do not use
505 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800506 if type(name) is not str:
507 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400508 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800509
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500510 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500511 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800512 try:
513 _raise_current_error()
514 except Error:
515 pass
516 raise AttributeError("No such attribute")
517
518 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500519 for i in range(_lib.X509_NAME_entry_count(self._name)):
520 ent = _lib.X509_NAME_get_entry(self._name, i)
521 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
522 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800523 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500524 ent = _lib.X509_NAME_delete_entry(self._name, i)
525 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800526 break
527
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500528 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800529 value = value.encode('utf-8')
530
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500531 add_result = _lib.X509_NAME_add_entry_by_NID(
532 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800533 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500534 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800535
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800536 def __getattr__(self, name):
537 """
538 Find attribute. An X509Name object has the following attributes:
539 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400540 organization (alias O), organizationalUnit (alias OU), commonName
541 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800542 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500543 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500544 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800545 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
546 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
547 # push something onto the error queue. If we don't clean that up
548 # now, someone else will bump into it later and be quite confused.
549 # See lp#314814.
550 try:
551 _raise_current_error()
552 except Error:
553 pass
554 return super(X509Name, self).__getattr__(name)
555
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500556 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800557 if entry_index == -1:
558 return None
559
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500560 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
561 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800562
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500563 result_buffer = _ffi.new("unsigned char**")
564 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400565 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800566
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700567 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400568 result = _ffi.buffer(
569 result_buffer[0], data_length
570 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700571 finally:
572 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500573 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800574 return result
575
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500576 def _cmp(op):
577 def f(self, other):
578 if not isinstance(other, X509Name):
579 return NotImplemented
580 result = _lib.X509_NAME_cmp(self._name, other._name)
581 return op(result, 0)
582 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800583
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500584 __eq__ = _cmp(__eq__)
585 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800586
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500587 __lt__ = _cmp(__lt__)
588 __le__ = _cmp(__le__)
589
590 __gt__ = _cmp(__gt__)
591 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800592
593 def __repr__(self):
594 """
595 String representation of an X509Name
596 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400597 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500598 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800599 self._name, result_buffer, len(result_buffer))
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700600 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800601
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500602 return "<X509Name object '%s'>" % (
603 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800604
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800605 def hash(self):
606 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200607 Return an integer representation of the first four bytes of the
608 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800609
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200610 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
611
612 :return: The (integer) hash of this name.
613 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800614 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500615 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800616
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800617 def der(self):
618 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200619 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800620
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200621 :return: The DER encoded form of this name.
622 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800623 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500624 result_buffer = _ffi.new('unsigned char**')
625 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400626 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800627
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500628 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
629 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800630 return string_result
631
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800632 def get_components(self):
633 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200634 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800635
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200636 :return: The components of this name.
637 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800638 """
639 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500640 for i in range(_lib.X509_NAME_entry_count(self._name)):
641 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800642
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500643 fname = _lib.X509_NAME_ENTRY_get_object(ent)
644 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800645
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500646 nid = _lib.OBJ_obj2nid(fname)
647 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800648
649 result.append((
Alex Gaynora738ed52015-09-05 11:17:10 -0400650 _ffi.string(name),
651 _ffi.string(
652 _lib.ASN1_STRING_data(fval),
653 _lib.ASN1_STRING_length(fval))))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800654
655 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200656
657
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800658X509NameType = X509Name
659
660
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800661class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200662 """
663 An X.509 v3 certificate extension.
664 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400665
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800666 def __init__(self, type_name, critical, value, subject=None, issuer=None):
667 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200668 Initializes an X509 extension.
669
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100670 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400671 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800672
Alex Gaynor5945ea82015-09-05 14:59:06 -0400673 :param bool critical: A flag indicating whether this is a critical
674 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800675
676 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200677 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800678
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200679 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800680 :type subject: :py:class:`X509`
681
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200682 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800683 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100684
Hynek Schlawackc3b38e52016-10-15 14:56:14 +0200685 .. _extension: https://www.openssl.org/docs/manmaster/apps/
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100686 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800687 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500688 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800689
Alex Gaynor5945ea82015-09-05 14:59:06 -0400690 # A context is necessary for any extension which uses the r2i
691 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
692 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500693 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800694
695 # We have no configuration database - but perhaps we should (some
696 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500697 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800698
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800699 # Initialize the subject and issuer, if appropriate. ctx is a local,
700 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400701 # any references, so no need to mess with reference counts or
702 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800703 if issuer is not None:
704 if not isinstance(issuer, X509):
705 raise TypeError("issuer must be an X509 instance")
706 ctx.issuer_cert = issuer._x509
707 if subject is not None:
708 if not isinstance(subject, X509):
709 raise TypeError("subject must be an X509 instance")
710 ctx.subject_cert = subject._x509
711
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800712 if critical:
713 # There are other OpenSSL APIs which would let us pass in critical
714 # separately, but they're harder to use, and since value is already
715 # a pile of crappy junk smuggling a ton of utterly important
716 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400717 # with strings? (However, X509V3_EXT_i2d in particular seems like
718 # it would be a better API to invoke. I do not know where to get
719 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500720 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800721
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500722 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
723 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800724 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500725 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800726
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400727 @property
728 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400729 return _lib.OBJ_obj2nid(
730 _lib.X509_EXTENSION_get_object(self._extension)
731 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400732
733 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500734 _lib.GEN_EMAIL: "email",
735 _lib.GEN_DNS: "DNS",
736 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400737 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400738
739 def _subjectAltNameString(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500740 method = _lib.X509V3_EXT_get(self._extension)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700741 _openssl_assert(method != _ffi.NULL)
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400742 ext_data = _lib.X509_EXTENSION_get_data(self._extension)
743 payload = ext_data.data
744 length = ext_data.length
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400745
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500746 payloadptr = _ffi.new("unsigned char**")
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400747 payloadptr[0] = payload
748
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500749 if method.it != _ffi.NULL:
750 ptr = _lib.ASN1_ITEM_ptr(method.it)
751 data = _lib.ASN1_item_d2i(_ffi.NULL, payloadptr, length, ptr)
752 names = _ffi.cast("GENERAL_NAMES*", data)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400753 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500754 names = _ffi.cast(
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400755 "GENERAL_NAMES*",
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500756 method.d2i(_ffi.NULL, payloadptr, length))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400757
Paul Kehrerb7d79502015-05-04 07:43:51 -0500758 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400759 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500760 for i in range(_lib.sk_GENERAL_NAME_num(names)):
761 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400762 try:
763 label = self._prefixes[name.type]
764 except KeyError:
765 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500766 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500767 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400768 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500769 value = _native(
770 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
771 parts.append(label + ":" + value)
772 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400773
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800774 def __str__(self):
775 """
776 :return: a nice text representation of the extension
777 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500778 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400779 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800780
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400781 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500782 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400783 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800784
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500785 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800786
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800787 def get_critical(self):
788 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200789 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800790
791 :return: The critical field.
792 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500793 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800794
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800795 def get_short_name(self):
796 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200797 Returns the short type name of this X.509 extension.
798
799 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800800
801 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200802 :rtype: :py:data:`bytes`
803
804 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800805 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500806 obj = _lib.X509_EXTENSION_get_object(self._extension)
807 nid = _lib.OBJ_obj2nid(obj)
808 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800809
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800810 def get_data(self):
811 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200812 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800813
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200814 :return: The ASN.1 encoded data of this X509 extension.
815 :rtype: :py:data:`bytes`
816
817 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800818 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500819 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
820 string_result = _ffi.cast('ASN1_STRING*', octet_result)
821 char_result = _lib.ASN1_STRING_data(string_result)
822 result_length = _lib.ASN1_STRING_length(string_result)
823 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800824
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200825
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800826X509ExtensionType = X509Extension
827
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800828
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800829class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200830 """
831 An X.509 certificate signing requests.
832 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400833
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800834 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500835 req = _lib.X509_REQ_new()
836 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Alex Gaynor5af32d02016-09-24 01:52:21 -0400837 # Default to version 0.
838 self.set_version(0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800839
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800840 def set_pubkey(self, pkey):
841 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200842 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800843
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200844 :param pkey: The public key to use.
845 :type pkey: :py:class:`PKey`
846
Dan Sully44e767a2016-06-04 18:05:27 -0700847 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800848 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500849 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400850 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800851
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800852 def get_pubkey(self):
853 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200854 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800855
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200856 :return: The public key.
857 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800858 """
859 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500860 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700861 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500862 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800863 pkey._only_public = True
864 return pkey
865
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800866 def set_version(self, version):
867 """
868 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
869 request.
870
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200871 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700872 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800873 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500874 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400875 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800876
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800877 def get_version(self):
878 """
879 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
880 request.
881
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200882 :return: The value of the version subfield.
883 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800884 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500885 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800886
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800887 def get_subject(self):
888 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200889 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800890
Cory Benfield881dc8d2015-12-09 08:25:14 +0000891 This creates a new :class:`X509Name` that wraps the underlying subject
892 name field on the certificate signing request. Modifying it will modify
893 the underlying signing request, and will have the effect of modifying
894 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200895
896 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000897 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800898 """
899 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500900 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700901 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800902
903 # The name is owned by the X509Req structure. As long as the X509Name
904 # Python object is alive, keep the X509Req Python object alive.
905 name._owner = self
906
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800907 return name
908
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800909 def add_extensions(self, extensions):
910 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200911 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800912
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200913 :param extensions: The X.509 extensions to add.
914 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700915 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800916 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500917 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700918 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800919
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500920 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800921
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800922 for ext in extensions:
923 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -0800924 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800925
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800926 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500927 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800928
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500929 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400930 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800931
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800932 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800933 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200934 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800935
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200936 :return: The X.509 extensions in this request.
937 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
938
939 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800940 """
941 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500942 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -0500943 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800944 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500945 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800946 exts.append(ext)
947 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800948
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800949 def sign(self, pkey, digest):
950 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -0700951 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800952
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200953 :param pkey: The key pair to sign with.
954 :type pkey: :py:class:`PKey`
955 :param digest: The name of the message digest to use for the signature,
Alex Gaynor239e2d32016-09-11 12:36:35 -0400956 e.g. :py:data:`b"sha256"`.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200957 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -0700958 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800959 """
960 if pkey._only_public:
961 raise ValueError("Key has only public part")
962
963 if not pkey._initialized:
964 raise ValueError("Key is uninitialized")
965
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500966 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500967 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800968 raise ValueError("No such digest method")
969
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500970 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400971 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800972
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800973 def verify(self, pkey):
974 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200975 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800976
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200977 :param key: A public key.
978 :type key: :py:class:`PKey`
979 :return: :py:data:`True` if the signature is correct.
980 :rtype: :py:class:`bool`
981 :raises Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800982 problem verifying the signature.
983 """
984 if not isinstance(pkey, PKey):
985 raise TypeError("pkey must be a PKey instance")
986
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500987 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800988 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500989 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800990
991 return result
992
993
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800994X509ReqType = X509Req
995
996
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800997class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200998 """
999 An X.509 certificate.
1000 """
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001001 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001002 x509 = _lib.X509_new()
Hynek Schlawack8a2dd772016-07-31 13:46:20 +02001003 _openssl_assert(x509 != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001004 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001005
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001006 def set_version(self, version):
1007 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001008 Set the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001009
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001010 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001011 :type version: :py:class:`int`
1012
Dan Sully44e767a2016-06-04 18:05:27 -07001013 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001014 """
1015 if not isinstance(version, int):
1016 raise TypeError("version must be an integer")
1017
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001018 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001019
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001020 def get_version(self):
1021 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001022 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001023
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001024 :return: The version number of the certificate.
1025 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001026 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001027 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001028
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001029 def get_pubkey(self):
1030 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001031 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001032
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001033 :return: The public key.
1034 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001035 """
1036 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001037 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1038 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001039 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001040 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001041 pkey._only_public = True
1042 return pkey
1043
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001044 def set_pubkey(self, pkey):
1045 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001046 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001047
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001048 :param pkey: The public key.
1049 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001050
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001051 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001052 """
1053 if not isinstance(pkey, PKey):
1054 raise TypeError("pkey must be a PKey instance")
1055
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001056 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001057 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001058
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001059 def sign(self, pkey, digest):
1060 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001061 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001062
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001063 :param pkey: The key to sign with.
1064 :type pkey: :py:class:`PKey`
1065
1066 :param digest: The name of the message digest to use.
1067 :type digest: :py:class:`bytes`
1068
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001069 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001070 """
1071 if not isinstance(pkey, PKey):
1072 raise TypeError("pkey must be a PKey instance")
1073
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001074 if pkey._only_public:
1075 raise ValueError("Key only has public part")
1076
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001077 if not pkey._initialized:
1078 raise ValueError("Key is uninitialized")
1079
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001080 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001081 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001082 raise ValueError("No such digest method")
1083
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001084 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001085 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001086
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001087 def get_signature_algorithm(self):
1088 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001089 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001090
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001091 :return: The name of the algorithm.
1092 :rtype: :py:class:`bytes`
1093
1094 :raises ValueError: If the signature algorithm is undefined.
1095
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001096 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001097 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001098 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1099 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001100 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001101 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001102 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001103
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001104 def digest(self, digest_name):
1105 """
1106 Return the digest of the X509 object.
1107
1108 :param digest_name: The name of the digest algorithm to use.
1109 :type digest_name: :py:class:`bytes`
1110
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001111 :return: The digest of the object, formatted as
1112 :py:const:`b":"`-delimited hex pairs.
1113 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001114 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001115 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001116 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001117 raise ValueError("No such digest method")
1118
Paul Kehrer9f9113a2016-09-20 20:10:25 -05001119 result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001120 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001121 result_length[0] = len(result_buffer)
1122
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001123 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001124 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001125 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001126
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001127 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001128 b16encode(ch).upper() for ch
1129 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001130
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001131 def subject_name_hash(self):
1132 """
1133 Return the hash of the X509 subject.
1134
1135 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001136 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001137 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001138 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001139
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001140 def set_serial_number(self, serial):
1141 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001142 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001143
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001144 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001145 :type serial: :py:class:`int`
1146
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001147 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001148 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001149 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001150 raise TypeError("serial must be an integer")
1151
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001152 hex_serial = hex(serial)[2:]
1153 if not isinstance(hex_serial, bytes):
1154 hex_serial = hex_serial.encode('ascii')
1155
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001156 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001157
1158 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001159 # it. If bignum is still NULL after this call, then the return value
1160 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001161 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001162
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001163 if bignum_serial[0] == _ffi.NULL:
1164 set_result = _lib.ASN1_INTEGER_set(
1165 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001166 if set_result:
1167 # TODO Not tested
1168 _raise_current_error()
1169 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001170 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1171 _lib.BN_free(bignum_serial[0])
1172 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001173 # TODO Not tested
1174 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001175 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1176 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001177 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001178
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001179 def get_serial_number(self):
1180 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001181 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001182
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001183 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001184 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001185 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001186 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1187 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001188 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001189 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001190 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001191 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001192 serial = int(hexstring_serial, 16)
1193 return serial
1194 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001195 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001196 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001197 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001198
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001199 def gmtime_adj_notAfter(self, amount):
1200 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001201 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001202
Dan Sully44e767a2016-06-04 18:05:27 -07001203 :param int amount: The number of seconds by which to adjust the
1204 timestamp.
1205 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001206 """
1207 if not isinstance(amount, int):
1208 raise TypeError("amount must be an integer")
1209
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001210 notAfter = _lib.X509_get_notAfter(self._x509)
1211 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001212
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001213 def gmtime_adj_notBefore(self, amount):
1214 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001215 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001216
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001217 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001218 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001219 """
1220 if not isinstance(amount, int):
1221 raise TypeError("amount must be an integer")
1222
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001223 notBefore = _lib.X509_get_notBefore(self._x509)
1224 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001225
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001226 def has_expired(self):
1227 """
1228 Check whether the certificate has expired.
1229
Dan Sully44e767a2016-06-04 18:05:27 -07001230 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1231 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001232 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001233 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001234 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001235
Paul Kehrerfde45c92016-01-21 12:57:37 -06001236 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001237
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001238 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001239 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001240
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001241 def get_notBefore(self):
1242 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001243 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001244
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001245 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001246
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001247 YYYYMMDDhhmmssZ
1248 YYYYMMDDhhmmss+hhmm
1249 YYYYMMDDhhmmss-hhmm
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001250
Dan Sully44e767a2016-06-04 18:05:27 -07001251 :return: A timestamp string, or ``None`` if there is none.
1252 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001253 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001254 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001255
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001256 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001257 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001258
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001259 def set_notBefore(self, when):
1260 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001261 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001262
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001263 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001264
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001265 YYYYMMDDhhmmssZ
1266 YYYYMMDDhhmmss+hhmm
1267 YYYYMMDDhhmmss-hhmm
1268
Dan Sully44e767a2016-06-04 18:05:27 -07001269 :param bytes when: A timestamp string.
1270 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001271 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001272 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001273
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001274 def get_notAfter(self):
1275 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001276 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001277
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001278 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001279
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001280 YYYYMMDDhhmmssZ
1281 YYYYMMDDhhmmss+hhmm
1282 YYYYMMDDhhmmss-hhmm
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001283
Dan Sully44e767a2016-06-04 18:05:27 -07001284 :return: A timestamp string, or ``None`` if there is none.
1285 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001286 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001287 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001288
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001289 def set_notAfter(self, when):
1290 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001291 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001292
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001293 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001294
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001295 YYYYMMDDhhmmssZ
1296 YYYYMMDDhhmmss+hhmm
1297 YYYYMMDDhhmmss-hhmm
1298
Dan Sully44e767a2016-06-04 18:05:27 -07001299 :param bytes when: A timestamp string.
1300 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001301 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001302 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001303
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001304 def _get_name(self, which):
1305 name = X509Name.__new__(X509Name)
1306 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001307 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001308
1309 # The name is owned by the X509 structure. As long as the X509Name
1310 # Python object is alive, keep the X509 Python object alive.
1311 name._owner = self
1312
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001313 return name
1314
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001315 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001316 if not isinstance(name, X509Name):
1317 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001318 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001319 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001320
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001321 def get_issuer(self):
1322 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001323 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001324
Cory Benfielde6bcce82015-12-09 08:40:03 +00001325 This creates a new :class:`X509Name` that wraps the underlying issuer
1326 name field on the certificate. Modifying it will modify the underlying
1327 certificate, and will have the effect of modifying any other
1328 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001329
1330 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001331 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001332 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001333 return self._get_name(_lib.X509_get_issuer_name)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001334
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001335 def set_issuer(self, issuer):
1336 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001337 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001338
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001339 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001340 :type issuer: :py:class:`X509Name`
1341
Dan Sully44e767a2016-06-04 18:05:27 -07001342 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001343 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001344 return self._set_name(_lib.X509_set_issuer_name, issuer)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001345
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001346 def get_subject(self):
1347 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001348 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001349
Cory Benfielde6bcce82015-12-09 08:40:03 +00001350 This creates a new :class:`X509Name` that wraps the underlying subject
1351 name field on the certificate. Modifying it will modify the underlying
1352 certificate, and will have the effect of modifying any other
1353 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001354
1355 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001356 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001357 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001358 return self._get_name(_lib.X509_get_subject_name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001359
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001360 def set_subject(self, subject):
1361 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001362 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001363
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001364 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001365 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001366
Dan Sully44e767a2016-06-04 18:05:27 -07001367 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001368 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001369 return self._set_name(_lib.X509_set_subject_name, subject)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001370
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001371 def get_extension_count(self):
1372 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001373 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001374
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001375 :return: The number of extensions.
1376 :rtype: :py:class:`int`
1377
1378 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001379 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001380 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001381
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001382 def add_extensions(self, extensions):
1383 """
1384 Add extensions to the certificate.
1385
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001386 :param extensions: The extensions to add.
1387 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001388 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001389 """
1390 for ext in extensions:
1391 if not isinstance(ext, X509Extension):
1392 raise ValueError("One of the elements is not an X509Extension")
1393
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001394 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001395 if not add_result:
1396 _raise_current_error()
1397
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001398 def get_extension(self, index):
1399 """
1400 Get a specific extension of the certificate by index.
1401
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001402 Extensions on a certificate are kept in order. The index
1403 parameter selects which extension will be returned.
1404
1405 :param int index: The index of the extension to retrieve.
1406 :return: The extension at the specified index.
1407 :rtype: :py:class:`X509Extension`
1408 :raises IndexError: If the extension index was out of bounds.
1409
1410 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001411 """
1412 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001413 ext._extension = _lib.X509_get_ext(self._x509, index)
1414 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001415 raise IndexError("extension index out of bounds")
1416
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001417 extension = _lib.X509_EXTENSION_dup(ext._extension)
1418 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001419 return ext
1420
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001421
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001422X509Type = X509
1423
1424
Dan Sully44e767a2016-06-04 18:05:27 -07001425class X509StoreFlags(object):
1426 """
1427 Flags for X509 verification, used to change the behavior of
1428 :class:`X509Store`.
1429
1430 See `OpenSSL Verification Flags`_ for details.
1431
1432 .. _OpenSSL Verification Flags:
1433 https://www.openssl.org/docs/manmaster/crypto/X509_VERIFY_PARAM_set_flags.html
1434 """
1435 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1436 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1437 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1438 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1439 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1440 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1441 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1442 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1443 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1444 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1445 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1446
1447
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001448class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001449 """
Dan Sully44e767a2016-06-04 18:05:27 -07001450 An X.509 store.
1451
1452 An X.509 store is used to describe a context in which to verify a
1453 certificate. A description of a context may include a set of certificates
1454 to trust, a set of certificate revocation lists, verification flags and
1455 more.
1456
1457 An X.509 store, being only a description, cannot be used by itself to
1458 verify a certificate. To carry out the actual verification process, see
1459 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001460 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001461
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001462 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001463 store = _lib.X509_STORE_new()
1464 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001465
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001466 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001467 """
Dan Sully44e767a2016-06-04 18:05:27 -07001468 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001469
Dan Sully44e767a2016-06-04 18:05:27 -07001470 Adding a certificate with this method adds this certificate as a
1471 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001472
1473 :param X509 cert: The certificate to add to this store.
Dan Sully44e767a2016-06-04 18:05:27 -07001474 :raises TypeError: If the certificate is not an :class:`X509`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001475 :raises Error: If OpenSSL was unhappy with your certificate.
Dan Sully44e767a2016-06-04 18:05:27 -07001476 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001477 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001478 if not isinstance(cert, X509):
1479 raise TypeError()
1480
Dan Sully44e767a2016-06-04 18:05:27 -07001481 _openssl_assert(_lib.X509_STORE_add_cert(self._store, cert._x509) != 0)
1482
1483 def add_crl(self, crl):
1484 """
1485 Add a certificate revocation list to this store.
1486
1487 The certificate revocation lists added to a store will only be used if
1488 the associated flags are configured to check certificate revocation
1489 lists.
1490
1491 .. versionadded:: 16.1.0
1492
1493 :param CRL crl: The certificate revocation list to add to this store.
1494 :return: ``None`` if the certificate revocation list was added
1495 successfully.
1496 """
1497 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1498
1499 def set_flags(self, flags):
1500 """
1501 Set verification flags to this store.
1502
1503 Verification flags can be combined by oring them together.
1504
1505 .. note::
1506
1507 Setting a verification flag sometimes requires clients to add
1508 additional information to the store, otherwise a suitable error will
1509 be raised.
1510
1511 For example, in setting flags to enable CRL checking a
1512 suitable CRL must be added to the store otherwise an error will be
1513 raised.
1514
1515 .. versionadded:: 16.1.0
1516
1517 :param int flags: The verification flags to set on this store.
1518 See :class:`X509StoreFlags` for available constants.
1519 :return: ``None`` if the verification flags were successfully set.
1520 """
1521 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001522
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001523 def set_time(self, vfy_time):
1524 """
1525 Set the time against which the certificates are verified.
1526
1527 Normally the current time is used.
1528
1529 .. note::
1530
1531 For example, you can determine if a certificate was valid at a given
1532 time.
1533
1534 .. versionadded:: 16.3.0
1535
1536 :param datetime vfy_time: The verification time to set on this store.
1537 :return: ``None`` if the verification time was successfully set.
1538 """
1539 param = _lib.X509_VERIFY_PARAM_new()
1540 param = _ffi.gc(param, _lib.X509_VERIFY_PARAM_free)
1541
1542 _lib.X509_VERIFY_PARAM_set_time(param, int(vfy_time.strftime('%s')))
1543 _openssl_assert(_lib.X509_STORE_set1_param(self._store, param) != 0)
1544
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001545
1546X509StoreType = X509Store
1547
1548
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001549class X509StoreContextError(Exception):
1550 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001551 An exception raised when an error occurred while verifying a certificate
1552 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001553
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001554 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001555 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001556 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001557
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001558 def __init__(self, message, certificate):
1559 super(X509StoreContextError, self).__init__(message)
1560 self.certificate = certificate
1561
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001562
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001563class X509StoreContext(object):
1564 """
1565 An X.509 store context.
1566
Dan Sully44e767a2016-06-04 18:05:27 -07001567 An X.509 store context is used to carry out the actual verification process
1568 of a certificate in a described context. For describing such a context, see
1569 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001570
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001571 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1572 instance. It is dynamically allocated and automatically garbage
1573 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001574 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001575 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001576 :param X509Store store: The certificates which will be trusted for the
1577 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001578 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001579 """
1580
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001581 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001582 store_ctx = _lib.X509_STORE_CTX_new()
1583 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1584 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001585 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001586 # Make the store context available for use after instantiating this
1587 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001588 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001589 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001590
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001591 def _init(self):
1592 """
1593 Set up the store context for a subsequent verification operation.
1594 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001595 ret = _lib.X509_STORE_CTX_init(
1596 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1597 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001598 if ret <= 0:
1599 _raise_current_error()
1600
1601 def _cleanup(self):
1602 """
1603 Internally cleans up the store context.
1604
Dan Sully44e767a2016-06-04 18:05:27 -07001605 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001606 """
1607 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1608
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001609 def _exception_from_context(self):
1610 """
1611 Convert an OpenSSL native context error failure into a Python
1612 exception.
1613
Alex Gaynor5945ea82015-09-05 14:59:06 -04001614 When a call to native OpenSSL X509_verify_cert fails, additional
1615 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001616 """
1617 errors = [
1618 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1619 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1620 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001621 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001622 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001623 # A context error should always be associated with a certificate, so we
1624 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001625 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001626 _cert = _lib.X509_dup(_x509)
1627 pycert = X509.__new__(X509)
1628 pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001629 return X509StoreContextError(errors, pycert)
1630
Stephen Holsapple46a09252015-02-12 14:45:43 -08001631 def set_store(self, store):
1632 """
Dan Sully44e767a2016-06-04 18:05:27 -07001633 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001634
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001635 .. versionadded:: 0.15
1636
Dan Sully44e767a2016-06-04 18:05:27 -07001637 :param X509Store store: The store description which will be used for
1638 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001639 """
1640 self._store = store
1641
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001642 def verify_certificate(self):
1643 """
1644 Verify a certificate in a context.
1645
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001646 .. versionadded:: 0.15
1647
Alex Gaynorca87ff62015-09-04 23:31:03 -04001648 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001649 certificate in the context. Sets ``certificate`` attribute to
1650 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001651 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001652 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001653 # :meth:`verify_certificate` is called multiple times.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001654 self._init()
1655 ret = _lib.X509_verify_cert(self._store_ctx)
1656 self._cleanup()
1657 if ret <= 0:
1658 raise self._exception_from_context()
1659
1660
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001661def load_certificate(type, buffer):
1662 """
1663 Load a certificate from a buffer
1664
1665 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1666
Dan Sully44e767a2016-06-04 18:05:27 -07001667 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001668
1669 :return: The X509 object
1670 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001671 if isinstance(buffer, _text_type):
1672 buffer = buffer.encode("ascii")
1673
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001674 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001675
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001676 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001677 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001678 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001679 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001680 else:
1681 raise ValueError(
1682 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001683
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001684 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001685 _raise_current_error()
1686
1687 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001688 cert._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001689 return cert
1690
1691
1692def dump_certificate(type, cert):
1693 """
1694 Dump a certificate to a buffer
1695
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001696 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1697 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001698 :param cert: The certificate to dump
1699 :return: The buffer with the dumped certificate in
1700 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001701 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001702
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001703 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001704 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001705 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001706 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001707 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001708 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001709 else:
1710 raise ValueError(
1711 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1712 "FILETYPE_TEXT")
1713
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001714 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001715 return _bio_to_string(bio)
1716
1717
Cory Benfield6492f7c2015-10-27 16:57:58 +09001718def dump_publickey(type, pkey):
1719 """
Cory Benfield11c10192015-10-27 17:23:03 +09001720 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001721
Cory Benfield9c590b92015-10-28 14:55:05 +09001722 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001723 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001724 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001725 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001726 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001727 """
1728 bio = _new_mem_buf()
1729 if type == FILETYPE_PEM:
1730 write_bio = _lib.PEM_write_bio_PUBKEY
1731 elif type == FILETYPE_ASN1:
1732 write_bio = _lib.i2d_PUBKEY_bio
1733 else:
1734 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1735
1736 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001737 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001738 _raise_current_error()
1739
1740 return _bio_to_string(bio)
1741
1742
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001743def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1744 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001745 Dump the private key *pkey* into a buffer string encoded with the type
1746 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1747 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001748
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001749 :param type: The file type (one of :const:`FILETYPE_PEM`,
1750 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1751 :param PKey pkey: The PKey to dump
1752 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001753 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001754 the passphrase to use, or a callback for providing the passphrase.
1755
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001756 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001757 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001758 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001759 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001760
1761 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001762 if passphrase is None:
1763 raise TypeError(
1764 "if a value is given for cipher "
1765 "one must also be given for passphrase")
1766 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001767 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001768 raise ValueError("Invalid cipher name")
1769 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001770 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001771
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001772 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001773 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001774 result_code = _lib.PEM_write_bio_PrivateKey(
1775 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001776 helper.callback, helper.callback_args)
1777 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001778 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001779 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001780 elif type == FILETYPE_TEXT:
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001781 rsa = _ffi.gc(
1782 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1783 _lib.RSA_free
1784 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001785 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001786 else:
1787 raise ValueError(
1788 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1789 "FILETYPE_TEXT")
1790
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001791 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001792
1793 return _bio_to_string(bio)
1794
1795
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001796class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001797 """
1798 A certificate revocation.
1799 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001800 # http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_
1801 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1802 # OCSP_crl_reason_str. We use the latter, just like the command line
1803 # program.
1804 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001805 b"unspecified",
1806 b"keyCompromise",
1807 b"CACompromise",
1808 b"affiliationChanged",
1809 b"superseded",
1810 b"cessationOfOperation",
1811 b"certificateHold",
1812 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001813 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001814
1815 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001816 revoked = _lib.X509_REVOKED_new()
1817 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001818
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001819 def set_serial(self, hex_str):
1820 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001821 Set the serial number.
1822
1823 The serial number is formatted as a hexadecimal number encoded in
1824 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001825
Dan Sully44e767a2016-06-04 18:05:27 -07001826 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001827
Dan Sully44e767a2016-06-04 18:05:27 -07001828 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001829 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001830 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1831 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001832 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001833 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001834 if not bn_result:
1835 raise ValueError("bad hex string")
1836
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001837 asn1_serial = _ffi.gc(
1838 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1839 _lib.ASN1_INTEGER_free)
1840 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001841
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001842 def get_serial(self):
1843 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001844 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001845
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001846 The serial number is formatted as a hexadecimal number encoded in
1847 ASCII.
1848
1849 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001850 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001851 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001852 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001853
Alex Gaynor67903a62016-06-02 10:37:13 -07001854 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1855 _openssl_assert(asn1_int != _ffi.NULL)
1856 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1857 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001858 return _bio_to_string(bio)
1859
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001860 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001861 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1862 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001863 obj = _lib.X509_EXTENSION_get_object(ext)
1864 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001865 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001866 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001867 break
1868
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001869 def set_reason(self, reason):
1870 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001871 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001872
Dan Sully44e767a2016-06-04 18:05:27 -07001873 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001874
1875 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07001876 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001877
Dan Sully44e767a2016-06-04 18:05:27 -07001878 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001879
1880 .. seealso::
1881
Dan Sully44e767a2016-06-04 18:05:27 -07001882 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001883 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001884 """
1885 if reason is None:
1886 self._delete_reason()
1887 elif not isinstance(reason, bytes):
1888 raise TypeError("reason must be None or a byte string")
1889 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001890 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001891 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
1892
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001893 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07001894 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001895 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001896
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001897 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001898 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001899
1900 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001901 add_result = _lib.X509_REVOKED_add1_ext_i2d(
1902 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001903 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001904
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001905 def get_reason(self):
1906 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04001907 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001908
Dan Sully44e767a2016-06-04 18:05:27 -07001909 :return: The reason, or ``None`` if there is none.
1910 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001911
1912 .. seealso::
1913
Dan Sully44e767a2016-06-04 18:05:27 -07001914 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001915 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001916 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001917 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1918 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001919 obj = _lib.X509_EXTENSION_get_object(ext)
1920 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001921 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001922
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001923 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001924 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04001925 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001926 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04001927 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04001928 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001929
1930 return _bio_to_string(bio)
1931
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001932 def all_reasons(self):
1933 """
1934 Return a list of all the supported reason strings.
1935
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001936 This list is a copy; modifying it does not change the supported reason
1937 strings.
1938
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001939 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07001940 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001941 """
1942 return self._crl_reasons[:]
1943
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001944 def set_rev_date(self, when):
1945 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001946 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001947
Dan Sully44e767a2016-06-04 18:05:27 -07001948 :param bytes when: The timestamp of the revocation,
1949 as ASN.1 GENERALIZEDTIME.
1950 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001951 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001952 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1953 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001954
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001955 def get_rev_date(self):
1956 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001957 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001958
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001959 :return: The timestamp of the revocation, as ASN.1 GENERALIZEDTIME.
Dan Sully44e767a2016-06-04 18:05:27 -07001960 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001961 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001962 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1963 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001964
1965
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001966class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001967 """
1968 A certificate revocation list.
1969 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001970
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001971 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001972 crl = _lib.X509_CRL_new()
1973 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001974
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001975 def get_revoked(self):
1976 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001977 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001978
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001979 These revocations will be provided by value, not by reference.
1980 That means it's okay to mutate them: it won't affect this CRL.
1981
1982 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07001983 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001984 """
1985 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07001986 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001987 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
1988 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04001989 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001990 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001991 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001992 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08001993 if results:
1994 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001995
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001996 def add_revoked(self, revoked):
1997 """
1998 Add a revoked (by value not reference) to the CRL structure
1999
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02002000 This revocation will be added by value, not by reference. That
2001 means it's okay to mutate it after adding: it won't affect
2002 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002003
Dan Sully44e767a2016-06-04 18:05:27 -07002004 :param Revoked revoked: The new revocation.
2005 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002006 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04002007 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002008 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002009
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002010 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002011 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002012
Dan Sully44e767a2016-06-04 18:05:27 -07002013 def get_issuer(self):
2014 """
2015 Get the CRL's issuer.
2016
2017 .. versionadded:: 16.1.0
2018
2019 :rtype: X509Name
2020 """
2021 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
2022 _openssl_assert(_issuer != _ffi.NULL)
2023 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
2024 issuer = X509Name.__new__(X509Name)
2025 issuer._name = _issuer
2026 return issuer
2027
2028 def set_version(self, version):
2029 """
2030 Set the CRL version.
2031
2032 .. versionadded:: 16.1.0
2033
2034 :param int version: The version of the CRL.
2035 :return: ``None``
2036 """
2037 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2038
2039 def _set_boundary_time(self, which, when):
2040 return _set_asn1_time(which(self._crl), when)
2041
2042 def set_lastUpdate(self, when):
2043 """
2044 Set when the CRL was last updated.
2045
2046 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
2047
2048 YYYYMMDDhhmmssZ
2049 YYYYMMDDhhmmss+hhmm
2050 YYYYMMDDhhmmss-hhmm
2051
2052 .. versionadded:: 16.1.0
2053
2054 :param bytes when: A timestamp string.
2055 :return: ``None``
2056 """
2057 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2058
2059 def set_nextUpdate(self, when):
2060 """
2061 Set when the CRL will next be udpated.
2062
2063 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
2064
2065 YYYYMMDDhhmmssZ
2066 YYYYMMDDhhmmss+hhmm
2067 YYYYMMDDhhmmss-hhmm
2068
2069 .. versionadded:: 16.1.0
2070
2071 :param bytes when: A timestamp string.
2072 :return: ``None``
2073 """
2074 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2075
2076 def sign(self, issuer_cert, issuer_key, digest):
2077 """
2078 Sign the CRL.
2079
2080 Signing a CRL enables clients to associate the CRL itself with an
2081 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2082 be signed by an issuer.
2083
2084 This method implicitly sets the issuer's name based on the issuer
2085 certificate and private key used to sign the CRL.
2086
2087 .. versionadded:: 16.1.0
2088
2089 :param X509 issuer_cert: The issuer's certificate.
2090 :param PKey issuer_key: The issuer's private key.
2091 :param bytes digest: The digest method to sign the CRL with.
2092 """
2093 digest_obj = _lib.EVP_get_digestbyname(digest)
2094 _openssl_assert(digest_obj != _ffi.NULL)
2095 _lib.X509_CRL_set_issuer_name(
2096 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2097 _lib.X509_CRL_sort(self._crl)
2098 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2099 _openssl_assert(result != 0)
2100
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002101 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002102 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002103 """
Dan Sully44e767a2016-06-04 18:05:27 -07002104 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002105
Dan Sully44e767a2016-06-04 18:05:27 -07002106 :param X509 cert: The certificate used to sign the CRL.
2107 :param PKey key: The key used to sign the CRL.
2108 :param int type: The export format, either :data:`FILETYPE_PEM`,
2109 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002110 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002111 :param bytes digest: The name of the message digest to use (eg
Alex Gaynor239e2d32016-09-11 12:36:35 -04002112 ``b"sha2566"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002113 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002114 """
Dan Sully44e767a2016-06-04 18:05:27 -07002115
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002116 if not isinstance(cert, X509):
2117 raise TypeError("cert must be an X509 instance")
2118 if not isinstance(key, PKey):
2119 raise TypeError("key must be a PKey instance")
2120 if not isinstance(type, int):
2121 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002122
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002123 if digest is _UNSPECIFIED:
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002124 _warn(
2125 "The default message digest (md5) is deprecated. "
2126 "Pass the name of a message digest explicitly.",
2127 category=DeprecationWarning,
2128 stacklevel=2,
2129 )
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002130 digest = b"md5"
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002131
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002132 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002133 if digest_obj == _ffi.NULL:
2134 raise ValueError("No such digest method")
2135
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002136 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002137 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002138
Alex Gaynora738ed52015-09-05 11:17:10 -04002139 # A scratch time object to give different values to different CRL
2140 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002141 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002142 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002143
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002144 _lib.X509_gmtime_adj(sometime, 0)
2145 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002146
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002147 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2148 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002149
Alex Gaynor5945ea82015-09-05 14:59:06 -04002150 _lib.X509_CRL_set_issuer_name(
2151 self._crl, _lib.X509_get_subject_name(cert._x509)
2152 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002153
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002154 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002155 if not sign_result:
2156 _raise_current_error()
2157
Dominic Chenf05b2122015-10-13 16:32:35 +00002158 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002159
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002160
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002161CRLType = CRL
2162
2163
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002164class PKCS7(object):
2165 def type_is_signed(self):
2166 """
2167 Check if this NID_pkcs7_signed object
2168
2169 :return: True if the PKCS7 is of type signed
2170 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002171 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002172
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002173 def type_is_enveloped(self):
2174 """
2175 Check if this NID_pkcs7_enveloped object
2176
2177 :returns: True if the PKCS7 is of type enveloped
2178 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002179 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002180
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002181 def type_is_signedAndEnveloped(self):
2182 """
2183 Check if this NID_pkcs7_signedAndEnveloped object
2184
2185 :returns: True if the PKCS7 is of type signedAndEnveloped
2186 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002187 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002188
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002189 def type_is_data(self):
2190 """
2191 Check if this NID_pkcs7_data object
2192
2193 :return: True if the PKCS7 is of type data
2194 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002195 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002196
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002197 def get_type_name(self):
2198 """
2199 Returns the type name of the PKCS7 structure
2200
2201 :return: A string with the typename
2202 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002203 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2204 string_type = _lib.OBJ_nid2sn(nid)
2205 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002206
Alex Chanc6077062016-11-18 13:53:39 +00002207
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002208PKCS7Type = PKCS7
2209
2210
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002211class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002212 """
2213 A PKCS #12 archive.
2214 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002215
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002216 def __init__(self):
2217 self._pkey = None
2218 self._cert = None
2219 self._cacerts = None
2220 self._friendlyname = None
2221
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002222 def get_certificate(self):
2223 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002224 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002225
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002226 :return: The certificate, or :py:const:`None` if there is none.
2227 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002228 """
2229 return self._cert
2230
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002231 def set_certificate(self, cert):
2232 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002233 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002234
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002235 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002236 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002237
Dan Sully44e767a2016-06-04 18:05:27 -07002238 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002239 """
2240 if not isinstance(cert, X509):
2241 raise TypeError("cert must be an X509 instance")
2242 self._cert = cert
2243
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002244 def get_privatekey(self):
2245 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002246 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002247
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002248 :return: The private key, or :py:const:`None` if there is none.
2249 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002250 """
2251 return self._pkey
2252
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002253 def set_privatekey(self, pkey):
2254 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002255 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002256
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002257 :param pkey: The new private key, or :py:const:`None` to unset it.
2258 :type pkey: :py:class:`PKey` or :py:const:`None`
2259
Dan Sully44e767a2016-06-04 18:05:27 -07002260 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002261 """
2262 if not isinstance(pkey, PKey):
2263 raise TypeError("pkey must be a PKey instance")
2264 self._pkey = pkey
2265
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002266 def get_ca_certificates(self):
2267 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002268 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002269
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002270 :return: A tuple with the CA certificates in the chain, or
2271 :py:const:`None` if there are none.
2272 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002273 """
2274 if self._cacerts is not None:
2275 return tuple(self._cacerts)
2276
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002277 def set_ca_certificates(self, cacerts):
2278 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002279 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002280
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002281 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2282 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002283 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002284
Dan Sully44e767a2016-06-04 18:05:27 -07002285 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002286 """
2287 if cacerts is None:
2288 self._cacerts = None
2289 else:
2290 cacerts = list(cacerts)
2291 for cert in cacerts:
2292 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002293 raise TypeError(
2294 "iterable must only contain X509 instances"
2295 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002296 self._cacerts = cacerts
2297
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002298 def set_friendlyname(self, name):
2299 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002300 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002301
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002302 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002303 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002304
Dan Sully44e767a2016-06-04 18:05:27 -07002305 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002306 """
2307 if name is None:
2308 self._friendlyname = None
2309 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002310 raise TypeError(
2311 "name must be a byte string or None (not %r)" % (name,)
2312 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002313 self._friendlyname = name
2314
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002315 def get_friendlyname(self):
2316 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002317 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002318
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002319 :returns: The friendly name, or :py:const:`None` if there is none.
2320 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002321 """
2322 return self._friendlyname
2323
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002324 def export(self, passphrase=None, iter=2048, maciter=1):
2325 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002326 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002327
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002328 For more information, see the :c:func:`PKCS12_create` man page.
2329
2330 :param passphrase: The passphrase used to encrypt the structure. Unlike
2331 some other passphrase arguments, this *must* be a string, not a
2332 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002333 :type passphrase: :py:data:`bytes`
2334
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002335 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002336 :type iter: :py:data:`int`
2337
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002338 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002339 :type maciter: :py:data:`int`
2340
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002341 :return: The string representation of the PKCS #12 structure.
2342 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002343 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002344 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002345
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002346 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002347 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002348 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002349 cacerts = _lib.sk_X509_new_null()
2350 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002351 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002352 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002353
2354 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002355 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002356
2357 friendlyname = self._friendlyname
2358 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002359 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002360
2361 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002362 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002363 else:
2364 pkey = self._pkey._pkey
2365
2366 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002367 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002368 else:
2369 cert = self._cert._x509
2370
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002371 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002372 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002373 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2374 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002375 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002376 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002377 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002378 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002379
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002380 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002381 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002382 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002383
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002384
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002385PKCS12Type = PKCS12
2386
2387
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002388class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002389 """
2390 A Netscape SPKI object.
2391 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002392
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002393 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002394 spki = _lib.NETSCAPE_SPKI_new()
2395 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002396
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002397 def sign(self, pkey, digest):
2398 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002399 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002400
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002401 :param pkey: The private key to sign with.
2402 :type pkey: :py:class:`PKey`
2403
2404 :param digest: The message digest to use.
2405 :type digest: :py:class:`bytes`
2406
Dan Sully44e767a2016-06-04 18:05:27 -07002407 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002408 """
2409 if pkey._only_public:
2410 raise ValueError("Key has only public part")
2411
2412 if not pkey._initialized:
2413 raise ValueError("Key is uninitialized")
2414
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002415 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002416 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002417 raise ValueError("No such digest method")
2418
Alex Gaynor5945ea82015-09-05 14:59:06 -04002419 sign_result = _lib.NETSCAPE_SPKI_sign(
2420 self._spki, pkey._pkey, digest_obj
2421 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002422 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002423
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002424 def verify(self, key):
2425 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002426 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002427
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002428 :param key: The public key that signature is supposedly from.
2429 :type pkey: :py:class:`PKey`
2430
2431 :return: :py:const:`True` if the signature is correct.
2432 :rtype: :py:class:`bool`
2433
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002434 :raises Error: If the signature is invalid, or there was a problem
2435 verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002436 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002437 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002438 if answer <= 0:
2439 _raise_current_error()
2440 return True
2441
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002442 def b64_encode(self):
2443 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002444 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002445
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002446 :return: The base64 encoded string.
2447 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002448 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002449 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2450 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002451 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002452 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002453
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002454 def get_pubkey(self):
2455 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002456 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002457
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002458 :return: The public key.
2459 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002460 """
2461 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002462 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002463 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002464 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002465 pkey._only_public = True
2466 return pkey
2467
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002468 def set_pubkey(self, pkey):
2469 """
2470 Set the public key of the certificate
2471
2472 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002473 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002474 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002475 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002476 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002477
2478
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002479NetscapeSPKIType = NetscapeSPKI
2480
2481
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002482class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002483 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002484 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002485 raise ValueError(
2486 "only FILETYPE_PEM key format supports encryption"
2487 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002488 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002489 self._more_args = more_args
2490 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002491 self._problems = []
2492
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002493 @property
2494 def callback(self):
2495 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002496 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002497 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002498 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002499 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002500 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002501 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002502 raise TypeError(
2503 "Last argument must be a byte string or a callable."
2504 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002505
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002506 @property
2507 def callback_args(self):
2508 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002509 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002510 elif isinstance(self._passphrase, bytes):
2511 return self._passphrase
2512 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002513 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002514 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002515 raise TypeError(
2516 "Last argument must be a byte string or a callable."
2517 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002518
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002519 def raise_if_problem(self, exceptionType=Error):
2520 try:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05002521 _exception_from_error_queue(exceptionType)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002522 except exceptionType as e:
Jean-Paul Calderone9b4115f2014-01-10 14:06:04 -05002523 from_queue = e
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002524 if self._problems:
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002525 raise self._problems[0]
Jean-Paul Calderone9b4115f2014-01-10 14:06:04 -05002526 return from_queue
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002527
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002528 def _read_passphrase(self, buf, size, rwflag, userdata):
2529 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002530 if self._more_args:
2531 result = self._passphrase(size, rwflag, userdata)
2532 else:
2533 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002534 if not isinstance(result, bytes):
2535 raise ValueError("String expected")
2536 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002537 if self._truncate:
2538 result = result[:size]
2539 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002540 raise ValueError(
2541 "passphrase returned by callback is too long"
2542 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002543 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002544 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002545 return len(result)
2546 except Exception as e:
2547 self._problems.append(e)
2548 return 0
2549
2550
Cory Benfield6492f7c2015-10-27 16:57:58 +09002551def load_publickey(type, buffer):
2552 """
Cory Benfield11c10192015-10-27 17:23:03 +09002553 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002554
Cory Benfield9c590b92015-10-28 14:55:05 +09002555 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002556 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002557 :param buffer: The buffer the key is stored in.
2558 :type buffer: A Python string object, either unicode or bytestring.
2559 :return: The PKey object.
2560 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002561 """
2562 if isinstance(buffer, _text_type):
2563 buffer = buffer.encode("ascii")
2564
2565 bio = _new_mem_buf(buffer)
2566
2567 if type == FILETYPE_PEM:
2568 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2569 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2570 elif type == FILETYPE_ASN1:
2571 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2572 else:
2573 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2574
2575 if evp_pkey == _ffi.NULL:
2576 _raise_current_error()
2577
2578 pkey = PKey.__new__(PKey)
2579 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002580 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002581 return pkey
2582
2583
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002584def load_privatekey(type, buffer, passphrase=None):
2585 """
2586 Load a private key from a buffer
2587
2588 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2589 :param buffer: The buffer the key is stored in
2590 :param passphrase: (optional) if encrypted PEM format, this can be
2591 either the passphrase to use, or a callback for
2592 providing the passphrase.
2593
2594 :return: The PKey object
2595 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002596 if isinstance(buffer, _text_type):
2597 buffer = buffer.encode("ascii")
2598
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002599 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002600
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002601 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002602 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002603 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2604 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002605 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002606 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002607 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002608 else:
2609 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2610
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002611 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002612 _raise_current_error()
2613
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002614 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002615 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002616 return pkey
2617
2618
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002619def dump_certificate_request(type, req):
2620 """
2621 Dump a certificate request to a buffer
2622
2623 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2624 :param req: The certificate request to dump
2625 :return: The buffer with the dumped certificate request in
2626 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002627 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002628
2629 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002630 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002631 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002632 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002633 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002634 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002635 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002636 raise ValueError(
2637 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2638 "FILETYPE_TEXT"
2639 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002640
Alex Gaynor09a386e2016-07-03 09:32:44 -04002641 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002642
2643 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002644
2645
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002646def load_certificate_request(type, buffer):
2647 """
2648 Load a certificate request from a buffer
2649
2650 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2651 :param buffer: The buffer the certificate request is stored in
2652 :return: The X509Req object
2653 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002654 if isinstance(buffer, _text_type):
2655 buffer = buffer.encode("ascii")
2656
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002657 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002658
2659 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002660 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002661 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002662 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002663 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002664 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002665
Alex Gaynoradd5b072016-06-04 21:04:00 -07002666 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002667
2668 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002669 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002670 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002671
2672
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002673def sign(pkey, data, digest):
2674 """
2675 Sign data with a digest
2676
2677 :param pkey: Pkey to sign with
2678 :param data: data to be signed
2679 :param digest: message digest to use
2680 :return: signature
2681 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002682 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002683
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002684 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002685 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002686 raise ValueError("No such digest method")
2687
Alex Gaynor67903a62016-06-02 10:37:13 -07002688 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002689 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002690
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002691 _lib.EVP_SignInit(md_ctx, digest_obj)
2692 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002693
Colleen Murphye09399b2016-03-01 17:40:49 -08002694 pkey_length = (PKey.bits(pkey) + 7) // 8
2695 signature_buffer = _ffi.new("unsigned char[]", pkey_length)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002696 signature_length = _ffi.new("unsigned int*")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002697 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002698 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002699 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002700
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002701 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002702
2703
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002704def verify(cert, signature, data, digest):
2705 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002706 Verify a signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002707
2708 :param cert: signing certificate (X509 object)
2709 :param signature: signature returned by sign function
2710 :param data: data to be verified
2711 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002712 :return: ``None`` if the signature is correct, raise exception otherwise.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002713 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002714 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002715
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002716 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002717 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002718 raise ValueError("No such digest method")
2719
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002720 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002721 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002722 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002723
Alex Gaynor67903a62016-06-02 10:37:13 -07002724 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002725 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002726
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002727 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2728 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002729 verify_result = _lib.EVP_VerifyFinal(
2730 md_ctx, signature, len(signature), pkey
2731 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002732
2733 if verify_result != 1:
2734 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002735
2736
Dominic Chenf05b2122015-10-13 16:32:35 +00002737def dump_crl(type, crl):
2738 """
2739 Dump a certificate revocation list to a buffer.
2740
2741 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2742 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002743 :param CRL crl: The CRL to dump.
2744
Dominic Chenf05b2122015-10-13 16:32:35 +00002745 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002746 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002747 """
2748 bio = _new_mem_buf()
2749
2750 if type == FILETYPE_PEM:
2751 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2752 elif type == FILETYPE_ASN1:
2753 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2754 elif type == FILETYPE_TEXT:
2755 ret = _lib.X509_CRL_print(bio, crl._crl)
2756 else:
2757 raise ValueError(
2758 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2759 "FILETYPE_TEXT")
2760
2761 assert ret == 1
2762 return _bio_to_string(bio)
2763
2764
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002765def load_crl(type, buffer):
2766 """
2767 Load a certificate revocation list from a buffer
2768
2769 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2770 :param buffer: The buffer the CRL is stored in
2771
2772 :return: The PKey object
2773 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002774 if isinstance(buffer, _text_type):
2775 buffer = buffer.encode("ascii")
2776
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002777 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002778
2779 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002780 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002781 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002782 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002783 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002784 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2785
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002786 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002787 _raise_current_error()
2788
2789 result = CRL.__new__(CRL)
2790 result._crl = crl
2791 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002792
2793
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002794def load_pkcs7_data(type, buffer):
2795 """
2796 Load pkcs7 data from a buffer
2797
2798 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2799 :param buffer: The buffer with the pkcs7 data.
2800 :return: The PKCS7 object
2801 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002802 if isinstance(buffer, _text_type):
2803 buffer = buffer.encode("ascii")
2804
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002805 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002806
2807 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002808 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002809 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002810 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002811 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002812 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2813
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002814 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002815 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002816
2817 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002818 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002819 return pypkcs7
2820
2821
Stephen Holsapple38482622014-04-05 20:29:34 -07002822def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002823 """
2824 Load a PKCS12 object from a buffer
2825
2826 :param buffer: The buffer the certificate is stored in
2827 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2828 :returns: The PKCS12 object
2829 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002830 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002831
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002832 if isinstance(buffer, _text_type):
2833 buffer = buffer.encode("ascii")
2834
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002835 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002836
Stephen Holsapple38482622014-04-05 20:29:34 -07002837 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2838 # password based encryption no password and a zero length password are two
2839 # different things, but OpenSSL implementation will try both to figure out
2840 # which one works.
2841 if not passphrase:
2842 passphrase = _ffi.NULL
2843
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002844 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2845 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002846 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002847 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002848
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002849 pkey = _ffi.new("EVP_PKEY**")
2850 cert = _ffi.new("X509**")
2851 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002852
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002853 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002854 if not parse_result:
2855 _raise_current_error()
2856
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002857 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002858
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002859 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
2860 # queue for no particular reason. This error isn't interesting to anyone
2861 # outside this function. It's not even interesting to us. Get rid of it.
2862 try:
2863 _raise_current_error()
2864 except Error:
2865 pass
2866
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002867 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002868 pykey = None
2869 else:
2870 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002871 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002872
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002873 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002874 pycert = None
2875 friendlyname = None
2876 else:
2877 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002878 pycert._x509 = _ffi.gc(cert[0], _lib.X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002879
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002880 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04002881 friendlyname_buffer = _lib.X509_alias_get0(
2882 cert[0], friendlyname_length
2883 )
2884 friendlyname = _ffi.buffer(
2885 friendlyname_buffer, friendlyname_length[0]
2886 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002887 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002888 friendlyname = None
2889
2890 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002891 for i in range(_lib.sk_X509_num(cacerts)):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002892 pycacert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002893 pycacert._x509 = _lib.sk_X509_value(cacerts, i)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002894 pycacerts.append(pycacert)
2895 if not pycacerts:
2896 pycacerts = None
2897
2898 pkcs12 = PKCS12.__new__(PKCS12)
2899 pkcs12._pkey = pykey
2900 pkcs12._cert = pycert
2901 pkcs12._cacerts = pycacerts
2902 pkcs12._friendlyname = friendlyname
2903 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05002904
2905
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05002906# There are no direct unit tests for this initialization. It is tested
2907# indirectly since it is necessary for functions like dump_privatekey when
2908# using encryption.
2909#
2910# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
2911# and some other similar tests may fail without this (though they may not if
2912# the Python runtime has already done some initialization of the underlying
2913# OpenSSL library (and is linked against the same one that cryptography is
2914# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05002915_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05002916
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05002917# This is similar but exercised mainly by exception_from_error_queue. It calls
2918# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
2919_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002920
2921
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002922# Set the default string mask to match OpenSSL upstream (since 2005) and
2923# RFC5280 recommendations.
2924_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')