blob: 34041726ec2e6224ec36e9eca79780193bdc27b6 [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
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900106 @param boundary: An ASN1_TIME pointer (or an object safely
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500107 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
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900119 set_result = _lib.ASN1_TIME_set_string(boundary, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800120 if set_result == 0:
Moriyoshi Koizumi80b25ef2017-06-22 00:54:20 +0900121 raise ValueError("Invalid string")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800122
Alex Gaynor510293e2016-06-02 12:07:59 -0700123
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800124def _get_asn1_time(timestamp):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500125 """
126 Retrieve the time value of an ASN1 time object.
127
128 @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to
129 that type) from which the time value will be retrieved.
130
131 @return: The time value from C{timestamp} as a L{bytes} string in a certain
132 format. Or C{None} if the object contains no time value.
133 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500134 string_timestamp = _ffi.cast('ASN1_STRING*', timestamp)
135 if _lib.ASN1_STRING_length(string_timestamp) == 0:
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800136 return None
Alex Gaynor5945ea82015-09-05 14:59:06 -0400137 elif (
138 _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME
139 ):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500140 return _ffi.string(_lib.ASN1_STRING_data(string_timestamp))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800141 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500142 generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**")
143 _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp)
144 if generalized_timestamp[0] == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500145 # This may happen:
146 # - if timestamp was not an ASN1_TIME
147 # - if allocating memory for the ASN1_GENERALIZEDTIME failed
148 # - if a copy of the time data from timestamp cannot be made for
149 # the newly allocated ASN1_GENERALIZEDTIME
150 #
151 # These are difficult to test. cffi enforces the ASN1_TIME type.
152 # Memory allocation failures are a pain to trigger
153 # deterministically.
154 _untested_error("ASN1_TIME_to_generalizedtime")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800155 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500156 string_timestamp = _ffi.cast(
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800157 "ASN1_STRING*", generalized_timestamp[0])
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500158 string_data = _lib.ASN1_STRING_data(string_timestamp)
159 string_result = _ffi.string(string_data)
160 _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0])
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800161 return string_result
162
163
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800164class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200165 """
166 A class representing an DSA or RSA public key or key pair.
167 """
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800168 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800169 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800170
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800171 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500172 pkey = _lib.EVP_PKEY_new()
173 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800174 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800175
Paul Kehrer72d968b2016-07-29 15:31:04 +0800176 def to_cryptography_key(self):
177 """
178 Export as a ``cryptography`` key.
179
180 :rtype: One of ``cryptography``'s `key interfaces`_.
181
182 .. _key interfaces: https://cryptography.io/en/latest/hazmat/\
183 primitives/asymmetric/rsa/#key-interfaces
184
185 .. versionadded:: 16.1.0
186 """
Paul Kehrereb633842016-10-06 11:22:01 +0200187 backend = _get_backend()
Paul Kehrer72d968b2016-07-29 15:31:04 +0800188 if self._only_public:
189 return backend._evp_pkey_to_public_key(self._pkey)
190 else:
191 return backend._evp_pkey_to_private_key(self._pkey)
192
193 @classmethod
194 def from_cryptography_key(cls, crypto_key):
195 """
196 Construct based on a ``cryptography`` *crypto_key*.
197
198 :param crypto_key: A ``cryptography`` key.
199 :type crypto_key: One of ``cryptography``'s `key interfaces`_.
200
201 :rtype: PKey
202
203 .. versionadded:: 16.1.0
204 """
205 pkey = cls()
206 if not isinstance(crypto_key, (rsa.RSAPublicKey, rsa.RSAPrivateKey,
207 dsa.DSAPublicKey, dsa.DSAPrivateKey)):
208 raise TypeError("Unsupported key type")
209
210 pkey._pkey = crypto_key._evp_pkey
211 if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)):
212 pkey._only_public = True
213 pkey._initialized = True
214 return pkey
215
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800216 def generate_key(self, type, bits):
217 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700218 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800219
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200220 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800221
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200222 :param type: The key type.
223 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
224 :param bits: The number of bits.
225 :type bits: :py:data:`int` ``>= 0``
226 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
227 of the appropriate type.
228 :raises ValueError: If the number of bits isn't an integer of
229 the appropriate size.
Dan Sully44e767a2016-06-04 18:05:27 -0700230 :return: ``None``
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800231 """
232 if not isinstance(type, int):
233 raise TypeError("type must be an integer")
234
235 if not isinstance(bits, int):
236 raise TypeError("bits must be an integer")
237
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800238 # TODO Check error return
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500239 exponent = _lib.BN_new()
240 exponent = _ffi.gc(exponent, _lib.BN_free)
241 _lib.BN_set_word(exponent, _lib.RSA_F4)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800242
243 if type == TYPE_RSA:
244 if bits <= 0:
245 raise ValueError("Invalid number of bits")
246
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500247 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800248
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500249 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400250 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800251
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500252 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400253 _openssl_assert(result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800254
255 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400256 dsa = _lib.DSA_new()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700257 _openssl_assert(dsa != _ffi.NULL)
Paul Kehrerafa5a662016-03-10 10:29:28 -0400258
259 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400260 res = _lib.DSA_generate_parameters_ex(
261 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
262 )
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700263 _openssl_assert(res == 1)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400264
265 _openssl_assert(_lib.DSA_generate_key(dsa) == 1)
266 _openssl_assert(_lib.EVP_PKEY_set1_DSA(self._pkey, dsa) == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800267 else:
268 raise Error("No such key type")
269
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800270 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800271
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800272 def check(self):
273 """
274 Check the consistency of an RSA private key.
275
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200276 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
277
Hynek Schlawack01c31672016-12-11 15:14:09 +0100278 :return: ``True`` if key is consistent.
279
280 :raise OpenSSL.crypto.Error: if the key is inconsistent.
281
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800282 :raise TypeError: if the key is of a type which cannot be checked.
283 Only RSA keys can currently be checked.
284 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800285 if self._only_public:
286 raise TypeError("public key only")
287
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100288 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800289 raise TypeError("key type unsupported")
290
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500291 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
292 rsa = _ffi.gc(rsa, _lib.RSA_free)
293 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800294 if result:
295 return True
296 _raise_current_error()
297
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800298 def type(self):
299 """
300 Returns the type of the key
301
302 :return: The type of the key.
303 """
Alex Gaynor0d2aec52017-05-31 04:26:27 -0400304 return _lib.EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800305
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800306 def bits(self):
307 """
308 Returns the number of bits of the key
309
310 :return: The number of bits of the key.
311 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500312 return _lib.EVP_PKEY_bits(self._pkey)
Alex Chanc6077062016-11-18 13:53:39 +0000313
314
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800315PKeyType = PKey
316
317
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400318class _EllipticCurve(object):
319 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400320 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400321
322 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
323 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
324 instances each of which represents one curve supported by the system.
325 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400326 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400327 _curves = None
328
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400329 if _PY3:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400330 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400331 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400332 """
333 Implement cooperation with the right-hand side argument of ``!=``.
334
335 Python 3 seems to have dropped this cooperation in this very narrow
336 circumstance.
337 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400338 if isinstance(other, _EllipticCurve):
339 return super(_EllipticCurve, self).__ne__(other)
340 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400341
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400342 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400343 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400344 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400345 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400346
347 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400348
349 :return: A :py:type:`set` of ``cls`` instances giving the names of the
350 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400351 """
Alex Chan84902a22017-04-20 11:50:47 +0100352 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
353 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
354 # The return value on this call should be num_curves again. We
355 # could check it to make sure but if it *isn't* then.. what could
356 # we do? Abort the whole process, I suppose...? -exarkun
357 lib.EC_get_builtin_curves(builtin_curves, num_curves)
358 return set(
359 cls.from_nid(lib, c.nid)
360 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400361
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400362 @classmethod
363 def _get_elliptic_curves(cls, lib):
364 """
365 Get, cache, and return the curves supported by OpenSSL.
366
367 :param lib: The OpenSSL library binding object.
368
369 :return: A :py:type:`set` of ``cls`` instances giving the names of the
370 elliptic curves the underlying library supports.
371 """
372 if cls._curves is None:
373 cls._curves = cls._load_elliptic_curves(lib)
374 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400375
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400376 @classmethod
377 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400378 """
379 Instantiate a new :py:class:`_EllipticCurve` associated with the given
380 OpenSSL NID.
381
382 :param lib: The OpenSSL library binding object.
383
384 :param nid: The OpenSSL NID the resulting curve object will represent.
385 This must be a curve NID (and not, for example, a hash NID) or
386 subsequent operations will fail in unpredictable ways.
387 :type nid: :py:class:`int`
388
389 :return: The curve object.
390 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400391 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
392
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400393 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400394 """
395 :param _lib: The :py:mod:`cryptography` binding instance used to
396 interface with OpenSSL.
397
398 :param _nid: The OpenSSL NID identifying the curve this object
399 represents.
400 :type _nid: :py:class:`int`
401
402 :param name: The OpenSSL short name identifying the curve this object
403 represents.
404 :type name: :py:class:`unicode`
405 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400406 self._lib = lib
407 self._nid = nid
408 self.name = name
409
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400410 def __repr__(self):
411 return "<Curve %r>" % (self.name,)
412
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400413 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400414 """
415 Create a new OpenSSL EC_KEY structure initialized to use this curve.
416
417 The structure is automatically garbage collected when the Python object
418 is garbage collected.
419 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400420 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
421 return _ffi.gc(key, _lib.EC_KEY_free)
422
423
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400424def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400425 """
426 Return a set of objects representing the elliptic curves supported in the
427 OpenSSL build in use.
428
429 The curve objects have a :py:class:`unicode` ``name`` attribute by which
430 they identify themselves.
431
432 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400433 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
434 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400435 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400436 return _EllipticCurve._get_elliptic_curves(_lib)
437
438
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400439def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400440 """
441 Return a single curve object selected by name.
442
443 See :py:func:`get_elliptic_curves` for information about curve objects.
444
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400445 :param name: The OpenSSL short name identifying the curve object to
446 retrieve.
447 :type name: :py:class:`unicode`
448
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400449 If the named curve is not supported then :py:class:`ValueError` is raised.
450 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400451 for curve in get_elliptic_curves():
452 if curve.name == name:
453 return curve
454 raise ValueError("unknown curve name", name)
455
456
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800457class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200458 """
459 An X.509 Distinguished Name.
460
461 :ivar countryName: The country of the entity.
462 :ivar C: Alias for :py:attr:`countryName`.
463
464 :ivar stateOrProvinceName: The state or province of the entity.
465 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
466
467 :ivar localityName: The locality of the entity.
468 :ivar L: Alias for :py:attr:`localityName`.
469
470 :ivar organizationName: The organization name of the entity.
471 :ivar O: Alias for :py:attr:`organizationName`.
472
473 :ivar organizationalUnitName: The organizational unit of the entity.
474 :ivar OU: Alias for :py:attr:`organizationalUnitName`
475
476 :ivar commonName: The common name of the entity.
477 :ivar CN: Alias for :py:attr:`commonName`.
478
479 :ivar emailAddress: The e-mail address of the entity.
480 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400481
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800482 def __init__(self, name):
483 """
484 Create a new X509Name, copying the given X509Name instance.
485
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200486 :param name: The name to copy.
487 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800488 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500489 name = _lib.X509_NAME_dup(name._name)
490 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800491
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800492 def __setattr__(self, name, value):
493 if name.startswith('_'):
494 return super(X509Name, self).__setattr__(name, value)
495
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800496 # Note: we really do not want str subclasses here, so we do not use
497 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800498 if type(name) is not str:
499 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400500 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800501
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500502 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500503 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800504 try:
505 _raise_current_error()
506 except Error:
507 pass
508 raise AttributeError("No such attribute")
509
510 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500511 for i in range(_lib.X509_NAME_entry_count(self._name)):
512 ent = _lib.X509_NAME_get_entry(self._name, i)
513 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
514 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800515 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500516 ent = _lib.X509_NAME_delete_entry(self._name, i)
517 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800518 break
519
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500520 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800521 value = value.encode('utf-8')
522
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500523 add_result = _lib.X509_NAME_add_entry_by_NID(
524 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800525 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500526 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800527
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800528 def __getattr__(self, name):
529 """
530 Find attribute. An X509Name object has the following attributes:
531 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400532 organization (alias O), organizationalUnit (alias OU), commonName
533 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800534 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500535 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500536 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800537 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
538 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
539 # push something onto the error queue. If we don't clean that up
540 # now, someone else will bump into it later and be quite confused.
541 # See lp#314814.
542 try:
543 _raise_current_error()
544 except Error:
545 pass
546 return super(X509Name, self).__getattr__(name)
547
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500548 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800549 if entry_index == -1:
550 return None
551
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500552 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
553 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800554
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500555 result_buffer = _ffi.new("unsigned char**")
556 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400557 _openssl_assert(data_length >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800558
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700559 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400560 result = _ffi.buffer(
561 result_buffer[0], data_length
562 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700563 finally:
564 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500565 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800566 return result
567
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500568 def _cmp(op):
569 def f(self, other):
570 if not isinstance(other, X509Name):
571 return NotImplemented
572 result = _lib.X509_NAME_cmp(self._name, other._name)
573 return op(result, 0)
574 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800575
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500576 __eq__ = _cmp(__eq__)
577 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800578
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500579 __lt__ = _cmp(__lt__)
580 __le__ = _cmp(__le__)
581
582 __gt__ = _cmp(__gt__)
583 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800584
585 def __repr__(self):
586 """
587 String representation of an X509Name
588 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400589 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500590 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800591 self._name, result_buffer, len(result_buffer))
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700592 _openssl_assert(format_result != _ffi.NULL)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800593
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500594 return "<X509Name object '%s'>" % (
595 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800596
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800597 def hash(self):
598 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200599 Return an integer representation of the first four bytes of the
600 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800601
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200602 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
603
604 :return: The (integer) hash of this name.
605 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800606 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500607 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800608
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800609 def der(self):
610 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200611 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800612
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200613 :return: The DER encoded form of this name.
614 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800615 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500616 result_buffer = _ffi.new('unsigned char**')
617 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400618 _openssl_assert(encode_result >= 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800619
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500620 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
621 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800622 return string_result
623
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800624 def get_components(self):
625 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200626 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800627
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200628 :return: The components of this name.
629 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800630 """
631 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500632 for i in range(_lib.X509_NAME_entry_count(self._name)):
633 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800634
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500635 fname = _lib.X509_NAME_ENTRY_get_object(ent)
636 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800637
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500638 nid = _lib.OBJ_obj2nid(fname)
639 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800640
641 result.append((
Alex Gaynora738ed52015-09-05 11:17:10 -0400642 _ffi.string(name),
643 _ffi.string(
644 _lib.ASN1_STRING_data(fval),
645 _lib.ASN1_STRING_length(fval))))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800646
647 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200648
649
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800650X509NameType = X509Name
651
652
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800653class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200654 """
655 An X.509 v3 certificate extension.
656 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400657
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800658 def __init__(self, type_name, critical, value, subject=None, issuer=None):
659 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200660 Initializes an X509 extension.
661
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100662 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400663 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800664
Alex Gaynor5945ea82015-09-05 14:59:06 -0400665 :param bool critical: A flag indicating whether this is a critical
666 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800667
668 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200669 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800670
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200671 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800672 :type subject: :py:class:`X509`
673
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200674 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800675 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100676
Alex Chan54005ce2017-03-21 08:08:17 +0000677 .. _extension: https://www.openssl.org/docs/manmaster/man5/
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100678 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800679 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500680 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800681
Alex Gaynor5945ea82015-09-05 14:59:06 -0400682 # A context is necessary for any extension which uses the r2i
683 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
684 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500685 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800686
687 # We have no configuration database - but perhaps we should (some
688 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500689 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800690
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800691 # Initialize the subject and issuer, if appropriate. ctx is a local,
692 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400693 # any references, so no need to mess with reference counts or
694 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800695 if issuer is not None:
696 if not isinstance(issuer, X509):
697 raise TypeError("issuer must be an X509 instance")
698 ctx.issuer_cert = issuer._x509
699 if subject is not None:
700 if not isinstance(subject, X509):
701 raise TypeError("subject must be an X509 instance")
702 ctx.subject_cert = subject._x509
703
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800704 if critical:
705 # There are other OpenSSL APIs which would let us pass in critical
706 # separately, but they're harder to use, and since value is already
707 # a pile of crappy junk smuggling a ton of utterly important
708 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400709 # with strings? (However, X509V3_EXT_i2d in particular seems like
710 # it would be a better API to invoke. I do not know where to get
711 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500712 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800713
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500714 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
715 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800716 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500717 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800718
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400719 @property
720 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400721 return _lib.OBJ_obj2nid(
722 _lib.X509_EXTENSION_get_object(self._extension)
723 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400724
725 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500726 _lib.GEN_EMAIL: "email",
727 _lib.GEN_DNS: "DNS",
728 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400729 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400730
731 def _subjectAltNameString(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500732 method = _lib.X509V3_EXT_get(self._extension)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700733 _openssl_assert(method != _ffi.NULL)
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400734 ext_data = _lib.X509_EXTENSION_get_data(self._extension)
735 payload = ext_data.data
736 length = ext_data.length
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400737
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500738 payloadptr = _ffi.new("unsigned char**")
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400739 payloadptr[0] = payload
740
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500741 if method.it != _ffi.NULL:
742 ptr = _lib.ASN1_ITEM_ptr(method.it)
743 data = _lib.ASN1_item_d2i(_ffi.NULL, payloadptr, length, ptr)
744 names = _ffi.cast("GENERAL_NAMES*", data)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400745 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500746 names = _ffi.cast(
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400747 "GENERAL_NAMES*",
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500748 method.d2i(_ffi.NULL, payloadptr, length))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400749
Paul Kehrerb7d79502015-05-04 07:43:51 -0500750 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400751 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500752 for i in range(_lib.sk_GENERAL_NAME_num(names)):
753 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400754 try:
755 label = self._prefixes[name.type]
756 except KeyError:
757 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500758 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500759 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400760 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500761 value = _native(
762 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
763 parts.append(label + ":" + value)
764 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400765
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800766 def __str__(self):
767 """
768 :return: a nice text representation of the extension
769 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500770 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400771 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800772
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400773 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500774 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400775 _openssl_assert(print_result != 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800776
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500777 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800778
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800779 def get_critical(self):
780 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200781 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800782
783 :return: The critical field.
784 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500785 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800786
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800787 def get_short_name(self):
788 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200789 Returns the short type name of this X.509 extension.
790
791 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800792
793 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200794 :rtype: :py:data:`bytes`
795
796 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800797 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500798 obj = _lib.X509_EXTENSION_get_object(self._extension)
799 nid = _lib.OBJ_obj2nid(obj)
800 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800801
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800802 def get_data(self):
803 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200804 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800805
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200806 :return: The ASN.1 encoded data of this X509 extension.
807 :rtype: :py:data:`bytes`
808
809 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800810 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500811 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
812 string_result = _ffi.cast('ASN1_STRING*', octet_result)
813 char_result = _lib.ASN1_STRING_data(string_result)
814 result_length = _lib.ASN1_STRING_length(string_result)
815 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800816
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200817
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800818X509ExtensionType = X509Extension
819
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800820
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800821class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200822 """
823 An X.509 certificate signing requests.
824 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400825
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800826 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500827 req = _lib.X509_REQ_new()
828 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Alex Gaynor5af32d02016-09-24 01:52:21 -0400829 # Default to version 0.
830 self.set_version(0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800831
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800832 def set_pubkey(self, pkey):
833 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200834 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800835
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200836 :param pkey: The public key to use.
837 :type pkey: :py:class:`PKey`
838
Dan Sully44e767a2016-06-04 18:05:27 -0700839 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800840 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500841 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400842 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800843
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800844 def get_pubkey(self):
845 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200846 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800847
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200848 :return: The public key.
849 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800850 """
851 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500852 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700853 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500854 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800855 pkey._only_public = True
856 return pkey
857
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800858 def set_version(self, version):
859 """
860 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
861 request.
862
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200863 :param int version: The version number.
Dan Sully44e767a2016-06-04 18:05:27 -0700864 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800865 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500866 set_result = _lib.X509_REQ_set_version(self._req, version)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -0400867 _openssl_assert(set_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800868
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800869 def get_version(self):
870 """
871 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
872 request.
873
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200874 :return: The value of the version subfield.
875 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800876 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500877 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800878
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800879 def get_subject(self):
880 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200881 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800882
Cory Benfield881dc8d2015-12-09 08:25:14 +0000883 This creates a new :class:`X509Name` that wraps the underlying subject
884 name field on the certificate signing request. Modifying it will modify
885 the underlying signing request, and will have the effect of modifying
886 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200887
888 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000889 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800890 """
891 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500892 name._name = _lib.X509_REQ_get_subject_name(self._req)
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700893 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800894
895 # The name is owned by the X509Req structure. As long as the X509Name
896 # Python object is alive, keep the X509Req Python object alive.
897 name._owner = self
898
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800899 return name
900
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800901 def add_extensions(self, extensions):
902 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200903 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800904
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200905 :param extensions: The X.509 extensions to add.
906 :type extensions: iterable of :py:class:`X509Extension`
Dan Sully44e767a2016-06-04 18:05:27 -0700907 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800908 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500909 stack = _lib.sk_X509_EXTENSION_new_null()
Alex Gaynorfb8a2a12016-06-04 18:26:26 -0700910 _openssl_assert(stack != _ffi.NULL)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800911
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500912 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800913
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800914 for ext in extensions:
915 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -0800916 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800917
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800918 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500919 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800920
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500921 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400922 _openssl_assert(add_result == 1)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800923
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800924 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800925 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200926 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800927
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200928 :return: The X.509 extensions in this request.
929 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
930
931 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800932 """
933 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500934 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -0500935 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800936 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500937 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800938 exts.append(ext)
939 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800940
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800941 def sign(self, pkey, digest):
942 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -0700943 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800944
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200945 :param pkey: The key pair to sign with.
946 :type pkey: :py:class:`PKey`
947 :param digest: The name of the message digest to use for the signature,
Alex Gaynor239e2d32016-09-11 12:36:35 -0400948 e.g. :py:data:`b"sha256"`.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200949 :type digest: :py:class:`bytes`
Dan Sully44e767a2016-06-04 18:05:27 -0700950 :return: ``None``
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800951 """
952 if pkey._only_public:
953 raise ValueError("Key has only public part")
954
955 if not pkey._initialized:
956 raise ValueError("Key is uninitialized")
957
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500958 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500959 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800960 raise ValueError("No such digest method")
961
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500962 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Alex Gaynor09a386e2016-07-03 09:32:44 -0400963 _openssl_assert(sign_result > 0)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800964
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800965 def verify(self, pkey):
966 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200967 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800968
Hynek Schlawack01c31672016-12-11 15:14:09 +0100969 :param PKey key: A public key.
970
971 :return: ``True`` if the signature is correct.
972 :rtype: bool
973
974 :raises OpenSSL.crypto.Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800975 problem verifying the signature.
976 """
977 if not isinstance(pkey, PKey):
978 raise TypeError("pkey must be a PKey instance")
979
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500980 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800981 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500982 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800983
984 return result
985
986
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800987X509ReqType = X509Req
988
989
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800990class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200991 """
992 An X.509 certificate.
993 """
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800994 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500995 x509 = _lib.X509_new()
Hynek Schlawack8a2dd772016-07-31 13:46:20 +0200996 _openssl_assert(x509 != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500997 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800998
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800999 def set_version(self, version):
1000 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001001 Set the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001002
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001003 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001004 :type version: :py:class:`int`
1005
Dan Sully44e767a2016-06-04 18:05:27 -07001006 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001007 """
1008 if not isinstance(version, int):
1009 raise TypeError("version must be an integer")
1010
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001011 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001012
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001013 def get_version(self):
1014 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001015 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001016
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001017 :return: The version number of the certificate.
1018 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001019 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001020 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001021
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001022 def get_pubkey(self):
1023 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001024 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001025
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001026 :return: The public key.
1027 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001028 """
1029 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001030 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1031 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001032 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001033 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001034 pkey._only_public = True
1035 return pkey
1036
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001037 def set_pubkey(self, pkey):
1038 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001039 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001040
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001041 :param pkey: The public key.
1042 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001043
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001044 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001045 """
1046 if not isinstance(pkey, PKey):
1047 raise TypeError("pkey must be a PKey instance")
1048
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001049 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Alex Gaynor7778e792016-07-03 23:38:48 -04001050 _openssl_assert(set_result == 1)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001051
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001052 def sign(self, pkey, digest):
1053 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001054 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001055
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001056 :param pkey: The key to sign with.
1057 :type pkey: :py:class:`PKey`
1058
1059 :param digest: The name of the message digest to use.
1060 :type digest: :py:class:`bytes`
1061
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001062 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001063 """
1064 if not isinstance(pkey, PKey):
1065 raise TypeError("pkey must be a PKey instance")
1066
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001067 if pkey._only_public:
1068 raise ValueError("Key only has public part")
1069
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001070 if not pkey._initialized:
1071 raise ValueError("Key is uninitialized")
1072
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001073 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001074 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001075 raise ValueError("No such digest method")
1076
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001077 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Alex Gaynor5bb2bd12016-07-03 10:48:32 -04001078 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001079
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001080 def get_signature_algorithm(self):
1081 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001082 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001083
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001084 :return: The name of the algorithm.
1085 :rtype: :py:class:`bytes`
1086
1087 :raises ValueError: If the signature algorithm is undefined.
1088
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001089 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001090 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001091 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1092 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001093 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001094 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001095 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001096
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001097 def digest(self, digest_name):
1098 """
1099 Return the digest of the X509 object.
1100
1101 :param digest_name: The name of the digest algorithm to use.
1102 :type digest_name: :py:class:`bytes`
1103
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001104 :return: The digest of the object, formatted as
1105 :py:const:`b":"`-delimited hex pairs.
1106 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001107 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001108 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001109 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001110 raise ValueError("No such digest method")
1111
Paul Kehrer9f9113a2016-09-20 20:10:25 -05001112 result_buffer = _ffi.new("unsigned char[]", _lib.EVP_MAX_MD_SIZE)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001113 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001114 result_length[0] = len(result_buffer)
1115
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001116 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001117 self._x509, digest, result_buffer, result_length)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001118 _openssl_assert(digest_result == 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001119
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001120 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001121 b16encode(ch).upper() for ch
1122 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001123
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001124 def subject_name_hash(self):
1125 """
1126 Return the hash of the X509 subject.
1127
1128 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001129 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001130 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001131 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001132
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001133 def set_serial_number(self, serial):
1134 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001135 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001136
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001137 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001138 :type serial: :py:class:`int`
1139
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001140 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001141 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001142 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001143 raise TypeError("serial must be an integer")
1144
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001145 hex_serial = hex(serial)[2:]
1146 if not isinstance(hex_serial, bytes):
1147 hex_serial = hex_serial.encode('ascii')
1148
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001149 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001150
1151 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001152 # it. If bignum is still NULL after this call, then the return value
1153 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001154 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001155
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001156 if bignum_serial[0] == _ffi.NULL:
1157 set_result = _lib.ASN1_INTEGER_set(
1158 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001159 if set_result:
1160 # TODO Not tested
1161 _raise_current_error()
1162 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001163 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1164 _lib.BN_free(bignum_serial[0])
1165 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001166 # TODO Not tested
1167 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001168 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1169 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Alex Gaynor37726112016-07-04 09:51:32 -04001170 _openssl_assert(set_result == 1)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001171
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001172 def get_serial_number(self):
1173 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001174 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001175
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001176 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001177 :rtype: int
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001178 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001179 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1180 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001181 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001182 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001183 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001184 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001185 serial = int(hexstring_serial, 16)
1186 return serial
1187 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001188 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001189 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001190 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001191
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001192 def gmtime_adj_notAfter(self, amount):
1193 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001194 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001195
Dan Sully44e767a2016-06-04 18:05:27 -07001196 :param int amount: The number of seconds by which to adjust the
1197 timestamp.
1198 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001199 """
1200 if not isinstance(amount, int):
1201 raise TypeError("amount must be an integer")
1202
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001203 notAfter = _lib.X509_get_notAfter(self._x509)
1204 _lib.X509_gmtime_adj(notAfter, amount)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001205
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001206 def gmtime_adj_notBefore(self, amount):
1207 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001208 Adjust the timestamp on which the certificate starts being valid.
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001209
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001210 :param amount: The number of seconds by which to adjust the timestamp.
Dan Sully44e767a2016-06-04 18:05:27 -07001211 :return: ``None``
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001212 """
1213 if not isinstance(amount, int):
1214 raise TypeError("amount must be an integer")
1215
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001216 notBefore = _lib.X509_get_notBefore(self._x509)
1217 _lib.X509_gmtime_adj(notBefore, amount)
Jean-Paul Calderone662afe52013-02-20 08:41:11 -08001218
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001219 def has_expired(self):
1220 """
1221 Check whether the certificate has expired.
1222
Dan Sully44e767a2016-06-04 18:05:27 -07001223 :return: ``True`` if the certificate has expired, ``False`` otherwise.
1224 :rtype: bool
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001225 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001226 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001227 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001228
Paul Kehrerfde45c92016-01-21 12:57:37 -06001229 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001230
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001231 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001232 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001233
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001234 def get_notBefore(self):
1235 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001236 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001237
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001238 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001239
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001240 YYYYMMDDhhmmssZ
1241 YYYYMMDDhhmmss+hhmm
1242 YYYYMMDDhhmmss-hhmm
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001243
Dan Sully44e767a2016-06-04 18:05:27 -07001244 :return: A timestamp string, or ``None`` if there is none.
1245 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001246 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001247 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001248
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001249 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001250 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001251
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001252 def set_notBefore(self, when):
1253 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001254 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001255
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001256 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001257
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001258 YYYYMMDDhhmmssZ
1259 YYYYMMDDhhmmss+hhmm
1260 YYYYMMDDhhmmss-hhmm
1261
Dan Sully44e767a2016-06-04 18:05:27 -07001262 :param bytes when: A timestamp string.
1263 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001264 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001265 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001266
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001267 def get_notAfter(self):
1268 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001269 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001270
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001271 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001272
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001273 YYYYMMDDhhmmssZ
1274 YYYYMMDDhhmmss+hhmm
1275 YYYYMMDDhhmmss-hhmm
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001276
Dan Sully44e767a2016-06-04 18:05:27 -07001277 :return: A timestamp string, or ``None`` if there is none.
1278 :rtype: bytes or NoneType
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001279 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001280 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001281
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001282 def set_notAfter(self, when):
1283 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001284 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001285
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001286 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001287
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001288 YYYYMMDDhhmmssZ
1289 YYYYMMDDhhmmss+hhmm
1290 YYYYMMDDhhmmss-hhmm
1291
Dan Sully44e767a2016-06-04 18:05:27 -07001292 :param bytes when: A timestamp string.
1293 :return: ``None``
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001294 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001295 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001296
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001297 def _get_name(self, which):
1298 name = X509Name.__new__(X509Name)
1299 name._name = which(self._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001300 _openssl_assert(name._name != _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001301
1302 # The name is owned by the X509 structure. As long as the X509Name
1303 # Python object is alive, keep the X509 Python object alive.
1304 name._owner = self
1305
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001306 return name
1307
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001308 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001309 if not isinstance(name, X509Name):
1310 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001311 set_result = which(self._x509, name._name)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001312 _openssl_assert(set_result == 1)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001313
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001314 def get_issuer(self):
1315 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001316 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001317
Cory Benfielde6bcce82015-12-09 08:40:03 +00001318 This creates a new :class:`X509Name` that wraps the underlying issuer
1319 name field on the certificate. Modifying it will modify the underlying
1320 certificate, and will have the effect of modifying any other
1321 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001322
1323 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001324 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001325 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001326 return self._get_name(_lib.X509_get_issuer_name)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001327
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001328 def set_issuer(self, issuer):
1329 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001330 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001331
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001332 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001333 :type issuer: :py:class:`X509Name`
1334
Dan Sully44e767a2016-06-04 18:05:27 -07001335 :return: ``None``
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001336 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001337 return self._set_name(_lib.X509_set_issuer_name, issuer)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001338
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001339 def get_subject(self):
1340 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001341 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001342
Cory Benfielde6bcce82015-12-09 08:40:03 +00001343 This creates a new :class:`X509Name` that wraps the underlying subject
1344 name field on the certificate. Modifying it will modify the underlying
1345 certificate, and will have the effect of modifying any other
1346 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001347
1348 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001349 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001350 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001351 return self._get_name(_lib.X509_get_subject_name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001352
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001353 def set_subject(self, subject):
1354 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001355 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001356
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001357 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001358 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001359
Dan Sully44e767a2016-06-04 18:05:27 -07001360 :return: ``None``
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001361 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001362 return self._set_name(_lib.X509_set_subject_name, subject)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001363
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001364 def get_extension_count(self):
1365 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001366 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001367
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001368 :return: The number of extensions.
1369 :rtype: :py:class:`int`
1370
1371 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001372 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001373 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001374
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001375 def add_extensions(self, extensions):
1376 """
1377 Add extensions to the certificate.
1378
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001379 :param extensions: The extensions to add.
1380 :type extensions: An iterable of :py:class:`X509Extension` objects.
Dan Sully44e767a2016-06-04 18:05:27 -07001381 :return: ``None``
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001382 """
1383 for ext in extensions:
1384 if not isinstance(ext, X509Extension):
1385 raise ValueError("One of the elements is not an X509Extension")
1386
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001387 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001388 if not add_result:
1389 _raise_current_error()
1390
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001391 def get_extension(self, index):
1392 """
1393 Get a specific extension of the certificate by index.
1394
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001395 Extensions on a certificate are kept in order. The index
1396 parameter selects which extension will be returned.
1397
1398 :param int index: The index of the extension to retrieve.
1399 :return: The extension at the specified index.
1400 :rtype: :py:class:`X509Extension`
1401 :raises IndexError: If the extension index was out of bounds.
1402
1403 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001404 """
1405 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001406 ext._extension = _lib.X509_get_ext(self._x509, index)
1407 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001408 raise IndexError("extension index out of bounds")
1409
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001410 extension = _lib.X509_EXTENSION_dup(ext._extension)
1411 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001412 return ext
1413
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001414
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001415X509Type = X509
1416
1417
Dan Sully44e767a2016-06-04 18:05:27 -07001418class X509StoreFlags(object):
1419 """
1420 Flags for X509 verification, used to change the behavior of
1421 :class:`X509Store`.
1422
1423 See `OpenSSL Verification Flags`_ for details.
1424
1425 .. _OpenSSL Verification Flags:
Alex Chan54005ce2017-03-21 08:08:17 +00001426 https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_flags.html
Dan Sully44e767a2016-06-04 18:05:27 -07001427 """
1428 CRL_CHECK = _lib.X509_V_FLAG_CRL_CHECK
1429 CRL_CHECK_ALL = _lib.X509_V_FLAG_CRL_CHECK_ALL
1430 IGNORE_CRITICAL = _lib.X509_V_FLAG_IGNORE_CRITICAL
1431 X509_STRICT = _lib.X509_V_FLAG_X509_STRICT
1432 ALLOW_PROXY_CERTS = _lib.X509_V_FLAG_ALLOW_PROXY_CERTS
1433 POLICY_CHECK = _lib.X509_V_FLAG_POLICY_CHECK
1434 EXPLICIT_POLICY = _lib.X509_V_FLAG_EXPLICIT_POLICY
1435 INHIBIT_MAP = _lib.X509_V_FLAG_INHIBIT_MAP
1436 NOTIFY_POLICY = _lib.X509_V_FLAG_NOTIFY_POLICY
1437 CHECK_SS_SIGNATURE = _lib.X509_V_FLAG_CHECK_SS_SIGNATURE
1438 CB_ISSUER_CHECK = _lib.X509_V_FLAG_CB_ISSUER_CHECK
1439
1440
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001441class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001442 """
Dan Sully44e767a2016-06-04 18:05:27 -07001443 An X.509 store.
1444
1445 An X.509 store is used to describe a context in which to verify a
1446 certificate. A description of a context may include a set of certificates
1447 to trust, a set of certificate revocation lists, verification flags and
1448 more.
1449
1450 An X.509 store, being only a description, cannot be used by itself to
1451 verify a certificate. To carry out the actual verification process, see
1452 :class:`X509StoreContext`.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001453 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001454
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001455 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001456 store = _lib.X509_STORE_new()
1457 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001458
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001459 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001460 """
Dan Sully44e767a2016-06-04 18:05:27 -07001461 Adds a trusted certificate to this store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001462
Dan Sully44e767a2016-06-04 18:05:27 -07001463 Adding a certificate with this method adds this certificate as a
1464 *trusted* certificate.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001465
1466 :param X509 cert: The certificate to add to this store.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001467
Dan Sully44e767a2016-06-04 18:05:27 -07001468 :raises TypeError: If the certificate is not an :class:`X509`.
Hynek Schlawack01c31672016-12-11 15:14:09 +01001469
1470 :raises OpenSSL.crypto.Error: If OpenSSL was unhappy with your
1471 certificate.
1472
Dan Sully44e767a2016-06-04 18:05:27 -07001473 :return: ``None`` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001474 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001475 if not isinstance(cert, X509):
1476 raise TypeError()
1477
Dan Sully44e767a2016-06-04 18:05:27 -07001478 _openssl_assert(_lib.X509_STORE_add_cert(self._store, cert._x509) != 0)
1479
1480 def add_crl(self, crl):
1481 """
1482 Add a certificate revocation list to this store.
1483
1484 The certificate revocation lists added to a store will only be used if
1485 the associated flags are configured to check certificate revocation
1486 lists.
1487
1488 .. versionadded:: 16.1.0
1489
1490 :param CRL crl: The certificate revocation list to add to this store.
1491 :return: ``None`` if the certificate revocation list was added
1492 successfully.
1493 """
1494 _openssl_assert(_lib.X509_STORE_add_crl(self._store, crl._crl) != 0)
1495
1496 def set_flags(self, flags):
1497 """
1498 Set verification flags to this store.
1499
1500 Verification flags can be combined by oring them together.
1501
1502 .. note::
1503
1504 Setting a verification flag sometimes requires clients to add
1505 additional information to the store, otherwise a suitable error will
1506 be raised.
1507
1508 For example, in setting flags to enable CRL checking a
1509 suitable CRL must be added to the store otherwise an error will be
1510 raised.
1511
1512 .. versionadded:: 16.1.0
1513
1514 :param int flags: The verification flags to set on this store.
1515 See :class:`X509StoreFlags` for available constants.
1516 :return: ``None`` if the verification flags were successfully set.
1517 """
1518 _openssl_assert(_lib.X509_STORE_set_flags(self._store, flags) != 0)
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001519
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001520 def set_time(self, vfy_time):
1521 """
1522 Set the time against which the certificates are verified.
1523
1524 Normally the current time is used.
1525
1526 .. note::
1527
1528 For example, you can determine if a certificate was valid at a given
1529 time.
1530
Hynek Schlawackf6c96af2017-04-20 12:34:58 +02001531 .. versionadded:: 17.0.0
Thomas Sileoe15e60a2016-11-22 18:13:30 +01001532
1533 :param datetime vfy_time: The verification time to set on this store.
1534 :return: ``None`` if the verification time was successfully set.
1535 """
1536 param = _lib.X509_VERIFY_PARAM_new()
1537 param = _ffi.gc(param, _lib.X509_VERIFY_PARAM_free)
1538
1539 _lib.X509_VERIFY_PARAM_set_time(param, int(vfy_time.strftime('%s')))
1540 _openssl_assert(_lib.X509_STORE_set1_param(self._store, param) != 0)
1541
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001542
1543X509StoreType = X509Store
1544
1545
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001546class X509StoreContextError(Exception):
1547 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001548 An exception raised when an error occurred while verifying a certificate
1549 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001550
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001551 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001552 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001553 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001554
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001555 def __init__(self, message, certificate):
1556 super(X509StoreContextError, self).__init__(message)
1557 self.certificate = certificate
1558
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001559
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001560class X509StoreContext(object):
1561 """
1562 An X.509 store context.
1563
Dan Sully44e767a2016-06-04 18:05:27 -07001564 An X.509 store context is used to carry out the actual verification process
1565 of a certificate in a described context. For describing such a context, see
1566 :class:`X509Store`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001567
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001568 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1569 instance. It is dynamically allocated and automatically garbage
1570 collected.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001571 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001572 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001573 :param X509Store store: The certificates which will be trusted for the
1574 purposes of any verifications.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001575 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001576 """
1577
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001578 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001579 store_ctx = _lib.X509_STORE_CTX_new()
1580 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1581 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001582 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001583 # Make the store context available for use after instantiating this
1584 # class by initializing it now. Per testing, subsequent calls to
Dan Sully44e767a2016-06-04 18:05:27 -07001585 # :meth:`_init` have no adverse affect.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001586 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001587
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001588 def _init(self):
1589 """
1590 Set up the store context for a subsequent verification operation.
1591 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001592 ret = _lib.X509_STORE_CTX_init(
1593 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1594 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001595 if ret <= 0:
1596 _raise_current_error()
1597
1598 def _cleanup(self):
1599 """
1600 Internally cleans up the store context.
1601
Dan Sully44e767a2016-06-04 18:05:27 -07001602 The store context can then be reused with a new call to :meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001603 """
1604 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1605
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001606 def _exception_from_context(self):
1607 """
1608 Convert an OpenSSL native context error failure into a Python
1609 exception.
1610
Alex Gaynor5945ea82015-09-05 14:59:06 -04001611 When a call to native OpenSSL X509_verify_cert fails, additional
1612 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001613 """
1614 errors = [
1615 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1616 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1617 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001618 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001619 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001620 # A context error should always be associated with a certificate, so we
1621 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001622 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001623 _cert = _lib.X509_dup(_x509)
1624 pycert = X509.__new__(X509)
1625 pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001626 return X509StoreContextError(errors, pycert)
1627
Stephen Holsapple46a09252015-02-12 14:45:43 -08001628 def set_store(self, store):
1629 """
Dan Sully44e767a2016-06-04 18:05:27 -07001630 Set the context's X.509 store.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001631
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001632 .. versionadded:: 0.15
1633
Dan Sully44e767a2016-06-04 18:05:27 -07001634 :param X509Store store: The store description which will be used for
1635 the purposes of any *future* verifications.
Stephen Holsapple46a09252015-02-12 14:45:43 -08001636 """
1637 self._store = store
1638
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001639 def verify_certificate(self):
1640 """
1641 Verify a certificate in a context.
1642
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001643 .. versionadded:: 0.15
1644
Alex Gaynorca87ff62015-09-04 23:31:03 -04001645 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001646 certificate in the context. Sets ``certificate`` attribute to
1647 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001648 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001649 # Always re-initialize the store context in case
Dan Sully44e767a2016-06-04 18:05:27 -07001650 # :meth:`verify_certificate` is called multiple times.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001651 self._init()
1652 ret = _lib.X509_verify_cert(self._store_ctx)
1653 self._cleanup()
1654 if ret <= 0:
1655 raise self._exception_from_context()
1656
1657
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001658def load_certificate(type, buffer):
1659 """
1660 Load a certificate from a buffer
1661
1662 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1663
Dan Sully44e767a2016-06-04 18:05:27 -07001664 :param bytes buffer: The buffer the certificate is stored in
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001665
1666 :return: The X509 object
1667 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001668 if isinstance(buffer, _text_type):
1669 buffer = buffer.encode("ascii")
1670
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001671 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001672
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001673 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001674 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001675 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001676 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001677 else:
1678 raise ValueError(
1679 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001680
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001681 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001682 _raise_current_error()
1683
1684 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001685 cert._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001686 return cert
1687
1688
1689def dump_certificate(type, cert):
1690 """
1691 Dump a certificate to a buffer
1692
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001693 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1694 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001695 :param cert: The certificate to dump
1696 :return: The buffer with the dumped certificate in
1697 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001698 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001699
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001700 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001701 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001702 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001703 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001704 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001705 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001706 else:
1707 raise ValueError(
1708 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1709 "FILETYPE_TEXT")
1710
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001711 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001712 return _bio_to_string(bio)
1713
1714
Cory Benfield6492f7c2015-10-27 16:57:58 +09001715def dump_publickey(type, pkey):
1716 """
Cory Benfield11c10192015-10-27 17:23:03 +09001717 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001718
Cory Benfield9c590b92015-10-28 14:55:05 +09001719 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001720 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001721 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001722 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001723 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001724 """
1725 bio = _new_mem_buf()
1726 if type == FILETYPE_PEM:
1727 write_bio = _lib.PEM_write_bio_PUBKEY
1728 elif type == FILETYPE_ASN1:
1729 write_bio = _lib.i2d_PUBKEY_bio
1730 else:
1731 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1732
1733 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001734 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001735 _raise_current_error()
1736
1737 return _bio_to_string(bio)
1738
1739
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001740def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1741 """
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001742 Dump the private key *pkey* into a buffer string encoded with the type
1743 *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it
1744 using *cipher* and *passphrase*.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001745
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001746 :param type: The file type (one of :const:`FILETYPE_PEM`,
1747 :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`)
1748 :param PKey pkey: The PKey to dump
1749 :param cipher: (optional) if encrypted PEM format, the cipher to use
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001750 :param passphrase: (optional) if encrypted PEM format, this can be either
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001751 the passphrase to use, or a callback for providing the passphrase.
1752
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001753 :return: The buffer with the dumped key in
Dan Sully44e767a2016-06-04 18:05:27 -07001754 :rtype: bytes
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001755 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001756 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001757
1758 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001759 if passphrase is None:
1760 raise TypeError(
1761 "if a value is given for cipher "
1762 "one must also be given for passphrase")
1763 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001764 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001765 raise ValueError("Invalid cipher name")
1766 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001767 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001768
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001769 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001770 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001771 result_code = _lib.PEM_write_bio_PrivateKey(
1772 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001773 helper.callback, helper.callback_args)
1774 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001775 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001776 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001777 elif type == FILETYPE_TEXT:
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001778 rsa = _ffi.gc(
1779 _lib.EVP_PKEY_get1_RSA(pkey._pkey),
1780 _lib.RSA_free
1781 )
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001782 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001783 else:
1784 raise ValueError(
1785 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1786 "FILETYPE_TEXT")
1787
Hynek Schlawack11e43ad2016-07-03 14:40:20 +02001788 _openssl_assert(result_code != 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001789
1790 return _bio_to_string(bio)
1791
1792
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001793class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001794 """
1795 A certificate revocation.
1796 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001797 # http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_
1798 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1799 # OCSP_crl_reason_str. We use the latter, just like the command line
1800 # program.
1801 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001802 b"unspecified",
1803 b"keyCompromise",
1804 b"CACompromise",
1805 b"affiliationChanged",
1806 b"superseded",
1807 b"cessationOfOperation",
1808 b"certificateHold",
1809 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001810 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001811
1812 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001813 revoked = _lib.X509_REVOKED_new()
1814 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001815
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001816 def set_serial(self, hex_str):
1817 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001818 Set the serial number.
1819
1820 The serial number is formatted as a hexadecimal number encoded in
1821 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001822
Dan Sully44e767a2016-06-04 18:05:27 -07001823 :param bytes hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001824
Dan Sully44e767a2016-06-04 18:05:27 -07001825 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001826 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001827 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1828 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001829 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001830 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001831 if not bn_result:
1832 raise ValueError("bad hex string")
1833
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001834 asn1_serial = _ffi.gc(
1835 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1836 _lib.ASN1_INTEGER_free)
1837 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001838
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001839 def get_serial(self):
1840 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001841 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001842
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001843 The serial number is formatted as a hexadecimal number encoded in
1844 ASCII.
1845
1846 :return: The serial number.
Dan Sully44e767a2016-06-04 18:05:27 -07001847 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001848 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001849 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001850
Alex Gaynor67903a62016-06-02 10:37:13 -07001851 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1852 _openssl_assert(asn1_int != _ffi.NULL)
1853 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1854 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001855 return _bio_to_string(bio)
1856
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001857 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001858 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1859 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001860 obj = _lib.X509_EXTENSION_get_object(ext)
1861 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001862 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001863 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001864 break
1865
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001866 def set_reason(self, reason):
1867 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001868 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001869
Dan Sully44e767a2016-06-04 18:05:27 -07001870 If :data:`reason` is ``None``, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001871
1872 :param reason: The reason string.
Dan Sully44e767a2016-06-04 18:05:27 -07001873 :type reason: :class:`bytes` or :class:`NoneType`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001874
Dan Sully44e767a2016-06-04 18:05:27 -07001875 :return: ``None``
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001876
1877 .. seealso::
1878
Dan Sully44e767a2016-06-04 18:05:27 -07001879 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001880 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001881 """
1882 if reason is None:
1883 self._delete_reason()
1884 elif not isinstance(reason, bytes):
1885 raise TypeError("reason must be None or a byte string")
1886 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001887 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001888 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
1889
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001890 new_reason_ext = _lib.ASN1_ENUMERATED_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07001891 _openssl_assert(new_reason_ext != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001892 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001893
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001894 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
Alex Gaynoradd5b072016-06-04 21:04:00 -07001895 _openssl_assert(set_result != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001896
1897 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001898 add_result = _lib.X509_REVOKED_add1_ext_i2d(
1899 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Alex Gaynor09a386e2016-07-03 09:32:44 -04001900 _openssl_assert(add_result == 1)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001901
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001902 def get_reason(self):
1903 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04001904 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001905
Dan Sully44e767a2016-06-04 18:05:27 -07001906 :return: The reason, or ``None`` if there is none.
1907 :rtype: bytes or NoneType
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001908
1909 .. seealso::
1910
Dan Sully44e767a2016-06-04 18:05:27 -07001911 :meth:`all_reasons`, which gives you a list of all supported
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001912 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001913 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001914 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1915 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001916 obj = _lib.X509_EXTENSION_get_object(ext)
1917 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001918 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001919
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001920 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001921 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04001922 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001923 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04001924 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04001925 _openssl_assert(print_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001926
1927 return _bio_to_string(bio)
1928
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001929 def all_reasons(self):
1930 """
1931 Return a list of all the supported reason strings.
1932
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001933 This list is a copy; modifying it does not change the supported reason
1934 strings.
1935
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001936 :return: A list of reason strings.
Dan Sully44e767a2016-06-04 18:05:27 -07001937 :rtype: :class:`list` of :class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001938 """
1939 return self._crl_reasons[:]
1940
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001941 def set_rev_date(self, when):
1942 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001943 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001944
Dan Sully44e767a2016-06-04 18:05:27 -07001945 :param bytes when: The timestamp of the revocation,
1946 as ASN.1 GENERALIZEDTIME.
1947 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001948 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001949 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1950 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001951
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001952 def get_rev_date(self):
1953 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001954 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001955
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001956 :return: The timestamp of the revocation, as ASN.1 GENERALIZEDTIME.
Dan Sully44e767a2016-06-04 18:05:27 -07001957 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001958 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001959 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1960 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001961
1962
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001963class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001964 """
1965 A certificate revocation list.
1966 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001967
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001968 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001969 crl = _lib.X509_CRL_new()
1970 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001971
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001972 def get_revoked(self):
1973 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001974 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001975
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001976 These revocations will be provided by value, not by reference.
1977 That means it's okay to mutate them: it won't affect this CRL.
1978
1979 :return: The revocations in this CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07001980 :rtype: :class:`tuple` of :class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001981 """
1982 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07001983 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001984 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
1985 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04001986 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001987 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001988 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001989 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08001990 if results:
1991 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001992
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001993 def add_revoked(self, revoked):
1994 """
1995 Add a revoked (by value not reference) to the CRL structure
1996
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001997 This revocation will be added by value, not by reference. That
1998 means it's okay to mutate it after adding: it won't affect
1999 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002000
Dan Sully44e767a2016-06-04 18:05:27 -07002001 :param Revoked revoked: The new revocation.
2002 :return: ``None``
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002003 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04002004 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002005 _openssl_assert(copy != _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002006
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002007 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002008 _openssl_assert(add_result != 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002009
Dan Sully44e767a2016-06-04 18:05:27 -07002010 def get_issuer(self):
2011 """
2012 Get the CRL's issuer.
2013
2014 .. versionadded:: 16.1.0
2015
2016 :rtype: X509Name
2017 """
2018 _issuer = _lib.X509_NAME_dup(_lib.X509_CRL_get_issuer(self._crl))
2019 _openssl_assert(_issuer != _ffi.NULL)
2020 _issuer = _ffi.gc(_issuer, _lib.X509_NAME_free)
2021 issuer = X509Name.__new__(X509Name)
2022 issuer._name = _issuer
2023 return issuer
2024
2025 def set_version(self, version):
2026 """
2027 Set the CRL version.
2028
2029 .. versionadded:: 16.1.0
2030
2031 :param int version: The version of the CRL.
2032 :return: ``None``
2033 """
2034 _openssl_assert(_lib.X509_CRL_set_version(self._crl, version) != 0)
2035
2036 def _set_boundary_time(self, which, when):
2037 return _set_asn1_time(which(self._crl), when)
2038
2039 def set_lastUpdate(self, when):
2040 """
2041 Set when the CRL was last updated.
2042
2043 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
2044
2045 YYYYMMDDhhmmssZ
2046 YYYYMMDDhhmmss+hhmm
2047 YYYYMMDDhhmmss-hhmm
2048
2049 .. versionadded:: 16.1.0
2050
2051 :param bytes when: A timestamp string.
2052 :return: ``None``
2053 """
2054 return self._set_boundary_time(_lib.X509_CRL_get_lastUpdate, when)
2055
2056 def set_nextUpdate(self, when):
2057 """
2058 Set when the CRL will next be udpated.
2059
2060 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
2061
2062 YYYYMMDDhhmmssZ
2063 YYYYMMDDhhmmss+hhmm
2064 YYYYMMDDhhmmss-hhmm
2065
2066 .. versionadded:: 16.1.0
2067
2068 :param bytes when: A timestamp string.
2069 :return: ``None``
2070 """
2071 return self._set_boundary_time(_lib.X509_CRL_get_nextUpdate, when)
2072
2073 def sign(self, issuer_cert, issuer_key, digest):
2074 """
2075 Sign the CRL.
2076
2077 Signing a CRL enables clients to associate the CRL itself with an
2078 issuer. Before a CRL is meaningful to other OpenSSL functions, it must
2079 be signed by an issuer.
2080
2081 This method implicitly sets the issuer's name based on the issuer
2082 certificate and private key used to sign the CRL.
2083
2084 .. versionadded:: 16.1.0
2085
2086 :param X509 issuer_cert: The issuer's certificate.
2087 :param PKey issuer_key: The issuer's private key.
2088 :param bytes digest: The digest method to sign the CRL with.
2089 """
2090 digest_obj = _lib.EVP_get_digestbyname(digest)
2091 _openssl_assert(digest_obj != _ffi.NULL)
2092 _lib.X509_CRL_set_issuer_name(
2093 self._crl, _lib.X509_get_subject_name(issuer_cert._x509))
2094 _lib.X509_CRL_sort(self._crl)
2095 result = _lib.X509_CRL_sign(self._crl, issuer_key._pkey, digest_obj)
2096 _openssl_assert(result != 0)
2097
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002098 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002099 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002100 """
Dan Sully44e767a2016-06-04 18:05:27 -07002101 Export the CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002102
Dan Sully44e767a2016-06-04 18:05:27 -07002103 :param X509 cert: The certificate used to sign the CRL.
2104 :param PKey key: The key used to sign the CRL.
2105 :param int type: The export format, either :data:`FILETYPE_PEM`,
2106 :data:`FILETYPE_ASN1`, or :data:`FILETYPE_TEXT`.
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04002107 :param int days: The number of days until the next update of this CRL.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002108 :param bytes digest: The name of the message digest to use (eg
Alex Gaynor239e2d32016-09-11 12:36:35 -04002109 ``b"sha2566"``).
Dan Sully44e767a2016-06-04 18:05:27 -07002110 :rtype: bytes
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002111 """
Dan Sully44e767a2016-06-04 18:05:27 -07002112
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002113 if not isinstance(cert, X509):
2114 raise TypeError("cert must be an X509 instance")
2115 if not isinstance(key, PKey):
2116 raise TypeError("key must be a PKey instance")
2117 if not isinstance(type, int):
2118 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002119
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04002120 if digest is _UNSPECIFIED:
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002121 _warn(
2122 "The default message digest (md5) is deprecated. "
2123 "Pass the name of a message digest explicitly.",
2124 category=DeprecationWarning,
2125 stacklevel=2,
2126 )
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002127 digest = b"md5"
Jean-Paul Calderone60432792015-04-13 12:26:07 -04002128
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04002129 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002130 if digest_obj == _ffi.NULL:
2131 raise ValueError("No such digest method")
2132
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002133 bio = _lib.BIO_new(_lib.BIO_s_mem())
Alex Gaynoradd5b072016-06-04 21:04:00 -07002134 _openssl_assert(bio != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002135
Alex Gaynora738ed52015-09-05 11:17:10 -04002136 # A scratch time object to give different values to different CRL
2137 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002138 sometime = _lib.ASN1_TIME_new()
Alex Gaynoradd5b072016-06-04 21:04:00 -07002139 _openssl_assert(sometime != _ffi.NULL)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002140
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002141 _lib.X509_gmtime_adj(sometime, 0)
2142 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002143
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002144 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2145 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002146
Alex Gaynor5945ea82015-09-05 14:59:06 -04002147 _lib.X509_CRL_set_issuer_name(
2148 self._crl, _lib.X509_get_subject_name(cert._x509)
2149 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002150
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002151 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002152 if not sign_result:
2153 _raise_current_error()
2154
Dominic Chenf05b2122015-10-13 16:32:35 +00002155 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002156
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002157
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002158CRLType = CRL
2159
2160
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002161class PKCS7(object):
2162 def type_is_signed(self):
2163 """
2164 Check if this NID_pkcs7_signed object
2165
2166 :return: True if the PKCS7 is of type signed
2167 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002168 return bool(_lib.PKCS7_type_is_signed(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002169
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002170 def type_is_enveloped(self):
2171 """
2172 Check if this NID_pkcs7_enveloped object
2173
2174 :returns: True if the PKCS7 is of type enveloped
2175 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002176 return bool(_lib.PKCS7_type_is_enveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002177
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002178 def type_is_signedAndEnveloped(self):
2179 """
2180 Check if this NID_pkcs7_signedAndEnveloped object
2181
2182 :returns: True if the PKCS7 is of type signedAndEnveloped
2183 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002184 return bool(_lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002185
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002186 def type_is_data(self):
2187 """
2188 Check if this NID_pkcs7_data object
2189
2190 :return: True if the PKCS7 is of type data
2191 """
Alex Gaynor3aeead92016-07-31 11:31:59 -04002192 return bool(_lib.PKCS7_type_is_data(self._pkcs7))
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002193
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002194 def get_type_name(self):
2195 """
2196 Returns the type name of the PKCS7 structure
2197
2198 :return: A string with the typename
2199 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002200 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2201 string_type = _lib.OBJ_nid2sn(nid)
2202 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002203
Alex Chanc6077062016-11-18 13:53:39 +00002204
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002205PKCS7Type = PKCS7
2206
2207
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002208class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002209 """
2210 A PKCS #12 archive.
2211 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002212
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002213 def __init__(self):
2214 self._pkey = None
2215 self._cert = None
2216 self._cacerts = None
2217 self._friendlyname = None
2218
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002219 def get_certificate(self):
2220 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002221 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002222
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002223 :return: The certificate, or :py:const:`None` if there is none.
2224 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002225 """
2226 return self._cert
2227
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002228 def set_certificate(self, cert):
2229 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002230 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002231
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002232 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002233 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002234
Dan Sully44e767a2016-06-04 18:05:27 -07002235 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002236 """
2237 if not isinstance(cert, X509):
2238 raise TypeError("cert must be an X509 instance")
2239 self._cert = cert
2240
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002241 def get_privatekey(self):
2242 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002243 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002244
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002245 :return: The private key, or :py:const:`None` if there is none.
2246 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002247 """
2248 return self._pkey
2249
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002250 def set_privatekey(self, pkey):
2251 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002252 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002253
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002254 :param pkey: The new private key, or :py:const:`None` to unset it.
2255 :type pkey: :py:class:`PKey` or :py:const:`None`
2256
Dan Sully44e767a2016-06-04 18:05:27 -07002257 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002258 """
2259 if not isinstance(pkey, PKey):
2260 raise TypeError("pkey must be a PKey instance")
2261 self._pkey = pkey
2262
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002263 def get_ca_certificates(self):
2264 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002265 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002266
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002267 :return: A tuple with the CA certificates in the chain, or
2268 :py:const:`None` if there are none.
2269 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002270 """
2271 if self._cacerts is not None:
2272 return tuple(self._cacerts)
2273
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002274 def set_ca_certificates(self, cacerts):
2275 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002276 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002277
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002278 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2279 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002280 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002281
Dan Sully44e767a2016-06-04 18:05:27 -07002282 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002283 """
2284 if cacerts is None:
2285 self._cacerts = None
2286 else:
2287 cacerts = list(cacerts)
2288 for cert in cacerts:
2289 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002290 raise TypeError(
2291 "iterable must only contain X509 instances"
2292 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002293 self._cacerts = cacerts
2294
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002295 def set_friendlyname(self, name):
2296 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002297 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002298
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002299 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002300 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002301
Dan Sully44e767a2016-06-04 18:05:27 -07002302 :return: ``None``
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002303 """
2304 if name is None:
2305 self._friendlyname = None
2306 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002307 raise TypeError(
2308 "name must be a byte string or None (not %r)" % (name,)
2309 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002310 self._friendlyname = name
2311
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002312 def get_friendlyname(self):
2313 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002314 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002315
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002316 :returns: The friendly name, or :py:const:`None` if there is none.
2317 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002318 """
2319 return self._friendlyname
2320
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002321 def export(self, passphrase=None, iter=2048, maciter=1):
2322 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002323 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002324
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002325 For more information, see the :c:func:`PKCS12_create` man page.
2326
2327 :param passphrase: The passphrase used to encrypt the structure. Unlike
2328 some other passphrase arguments, this *must* be a string, not a
2329 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002330 :type passphrase: :py:data:`bytes`
2331
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002332 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002333 :type iter: :py:data:`int`
2334
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002335 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002336 :type maciter: :py:data:`int`
2337
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002338 :return: The string representation of the PKCS #12 structure.
2339 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002340 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002341 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002342
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002343 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002344 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002345 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002346 cacerts = _lib.sk_X509_new_null()
2347 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002348 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002349 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002350
2351 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002352 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002353
2354 friendlyname = self._friendlyname
2355 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002356 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002357
2358 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002359 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002360 else:
2361 pkey = self._pkey._pkey
2362
2363 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002364 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002365 else:
2366 cert = self._cert._x509
2367
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002368 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002369 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002370 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2371 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002372 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002373 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002374 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002375 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002376
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002377 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002378 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002379 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002380
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002381
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002382PKCS12Type = PKCS12
2383
2384
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002385class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002386 """
2387 A Netscape SPKI object.
2388 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002389
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002390 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002391 spki = _lib.NETSCAPE_SPKI_new()
2392 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002393
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002394 def sign(self, pkey, digest):
2395 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002396 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002397
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002398 :param pkey: The private key to sign with.
2399 :type pkey: :py:class:`PKey`
2400
2401 :param digest: The message digest to use.
2402 :type digest: :py:class:`bytes`
2403
Dan Sully44e767a2016-06-04 18:05:27 -07002404 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002405 """
2406 if pkey._only_public:
2407 raise ValueError("Key has only public part")
2408
2409 if not pkey._initialized:
2410 raise ValueError("Key is uninitialized")
2411
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002412 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002413 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002414 raise ValueError("No such digest method")
2415
Alex Gaynor5945ea82015-09-05 14:59:06 -04002416 sign_result = _lib.NETSCAPE_SPKI_sign(
2417 self._spki, pkey._pkey, digest_obj
2418 )
Alex Gaynor09a386e2016-07-03 09:32:44 -04002419 _openssl_assert(sign_result > 0)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002420
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002421 def verify(self, key):
2422 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002423 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002424
Hynek Schlawack01c31672016-12-11 15:14:09 +01002425 :param PKey key: The public key that signature is supposedly from.
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002426
Hynek Schlawack01c31672016-12-11 15:14:09 +01002427 :return: ``True`` if the signature is correct.
2428 :rtype: bool
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002429
Hynek Schlawack01c31672016-12-11 15:14:09 +01002430 :raises OpenSSL.crypto.Error: If the signature is invalid, or there was
2431 a problem verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002432 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002433 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002434 if answer <= 0:
2435 _raise_current_error()
2436 return True
2437
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002438 def b64_encode(self):
2439 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002440 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002441
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002442 :return: The base64 encoded string.
2443 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002444 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002445 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2446 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002447 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002448 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002449
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002450 def get_pubkey(self):
2451 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002452 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002453
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002454 :return: The public key.
2455 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002456 """
2457 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002458 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002459 _openssl_assert(pkey._pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002460 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002461 pkey._only_public = True
2462 return pkey
2463
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002464 def set_pubkey(self, pkey):
2465 """
2466 Set the public key of the certificate
2467
2468 :param pkey: The public key
Dan Sully44e767a2016-06-04 18:05:27 -07002469 :return: ``None``
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002470 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002471 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002472 _openssl_assert(set_result == 1)
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002473
2474
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002475NetscapeSPKIType = NetscapeSPKI
2476
2477
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002478class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002479 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002480 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002481 raise ValueError(
2482 "only FILETYPE_PEM key format supports encryption"
2483 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002484 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002485 self._more_args = more_args
2486 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002487 self._problems = []
2488
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002489 @property
2490 def callback(self):
2491 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002492 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002493 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002494 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002495 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002496 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002497 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002498 raise TypeError(
2499 "Last argument must be a byte string or a callable."
2500 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002501
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002502 @property
2503 def callback_args(self):
2504 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002505 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002506 elif isinstance(self._passphrase, bytes):
2507 return self._passphrase
2508 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002509 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002510 else:
Hynek Schlawack33675f92016-11-18 14:55:06 +01002511 raise TypeError(
2512 "Last argument must be a byte string or a callable."
2513 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002514
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002515 def raise_if_problem(self, exceptionType=Error):
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002516 if self._problems:
Greg Bowser36eb2de2017-01-24 11:38:55 -05002517
2518 # Flush the OpenSSL error queue
2519 try:
2520 _exception_from_error_queue(exceptionType)
2521 except exceptionType:
2522 pass
2523
2524 raise self._problems.pop(0)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002525
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002526 def _read_passphrase(self, buf, size, rwflag, userdata):
2527 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002528 if self._more_args:
2529 result = self._passphrase(size, rwflag, userdata)
2530 else:
2531 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002532 if not isinstance(result, bytes):
2533 raise ValueError("String expected")
2534 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002535 if self._truncate:
2536 result = result[:size]
2537 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002538 raise ValueError(
2539 "passphrase returned by callback is too long"
2540 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002541 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002542 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002543 return len(result)
2544 except Exception as e:
2545 self._problems.append(e)
2546 return 0
2547
2548
Cory Benfield6492f7c2015-10-27 16:57:58 +09002549def load_publickey(type, buffer):
2550 """
Cory Benfield11c10192015-10-27 17:23:03 +09002551 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002552
Cory Benfield9c590b92015-10-28 14:55:05 +09002553 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002554 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002555 :param buffer: The buffer the key is stored in.
2556 :type buffer: A Python string object, either unicode or bytestring.
2557 :return: The PKey object.
2558 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002559 """
2560 if isinstance(buffer, _text_type):
2561 buffer = buffer.encode("ascii")
2562
2563 bio = _new_mem_buf(buffer)
2564
2565 if type == FILETYPE_PEM:
2566 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2567 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2568 elif type == FILETYPE_ASN1:
2569 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2570 else:
2571 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2572
2573 if evp_pkey == _ffi.NULL:
2574 _raise_current_error()
2575
2576 pkey = PKey.__new__(PKey)
2577 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Paul Kehrer32fc4e62016-06-03 15:21:44 -07002578 pkey._only_public = True
Cory Benfield6492f7c2015-10-27 16:57:58 +09002579 return pkey
2580
2581
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002582def load_privatekey(type, buffer, passphrase=None):
2583 """
2584 Load a private key from a buffer
2585
2586 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2587 :param buffer: The buffer the key is stored in
2588 :param passphrase: (optional) if encrypted PEM format, this can be
2589 either the passphrase to use, or a callback for
2590 providing the passphrase.
2591
2592 :return: The PKey object
2593 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002594 if isinstance(buffer, _text_type):
2595 buffer = buffer.encode("ascii")
2596
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002597 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002598
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002599 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002600 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002601 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2602 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002603 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002604 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002605 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002606 else:
2607 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2608
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002609 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002610 _raise_current_error()
2611
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002612 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002613 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002614 return pkey
2615
2616
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002617def dump_certificate_request(type, req):
2618 """
2619 Dump a certificate request to a buffer
2620
2621 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2622 :param req: The certificate request to dump
2623 :return: The buffer with the dumped certificate request in
2624 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002625 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002626
2627 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002628 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002629 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002630 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002631 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002632 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002633 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002634 raise ValueError(
2635 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2636 "FILETYPE_TEXT"
2637 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002638
Alex Gaynor09a386e2016-07-03 09:32:44 -04002639 _openssl_assert(result_code != 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002640
2641 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002642
2643
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002644def load_certificate_request(type, buffer):
2645 """
2646 Load a certificate request from a buffer
2647
2648 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2649 :param buffer: The buffer the certificate request is stored in
2650 :return: The X509Req object
2651 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002652 if isinstance(buffer, _text_type):
2653 buffer = buffer.encode("ascii")
2654
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002655 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002656
2657 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002658 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002659 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002660 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002661 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002662 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002663
Alex Gaynoradd5b072016-06-04 21:04:00 -07002664 _openssl_assert(req != _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002665
2666 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002667 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002668 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002669
2670
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002671def sign(pkey, data, digest):
2672 """
2673 Sign data with a digest
2674
2675 :param pkey: Pkey to sign with
2676 :param data: data to be signed
2677 :param digest: message digest to use
2678 :return: signature
2679 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002680 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002681
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002682 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002683 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002684 raise ValueError("No such digest method")
2685
Alex Gaynor67903a62016-06-02 10:37:13 -07002686 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002687 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002688
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002689 _lib.EVP_SignInit(md_ctx, digest_obj)
2690 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002691
Colleen Murphye09399b2016-03-01 17:40:49 -08002692 pkey_length = (PKey.bits(pkey) + 7) // 8
2693 signature_buffer = _ffi.new("unsigned char[]", pkey_length)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002694 signature_length = _ffi.new("unsigned int*")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002695 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002696 md_ctx, signature_buffer, signature_length, pkey._pkey)
Alex Gaynor09a386e2016-07-03 09:32:44 -04002697 _openssl_assert(final_result == 1)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002698
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002699 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002700
2701
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002702def verify(cert, signature, data, digest):
2703 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002704 Verify a signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002705
2706 :param cert: signing certificate (X509 object)
2707 :param signature: signature returned by sign function
2708 :param data: data to be verified
2709 :param digest: message digest to use
Dan Sully44e767a2016-06-04 18:05:27 -07002710 :return: ``None`` if the signature is correct, raise exception otherwise.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002711 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002712 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002713
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002714 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002715 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002716 raise ValueError("No such digest method")
2717
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002718 pkey = _lib.X509_get_pubkey(cert._x509)
Alex Gaynoradd5b072016-06-04 21:04:00 -07002719 _openssl_assert(pkey != _ffi.NULL)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002720 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002721
Alex Gaynor67903a62016-06-02 10:37:13 -07002722 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Alex Gaynor1f9d4de2016-06-02 11:01:52 -07002723 md_ctx = _ffi.gc(md_ctx, _lib.Cryptography_EVP_MD_CTX_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002724
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002725 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2726 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002727 verify_result = _lib.EVP_VerifyFinal(
2728 md_ctx, signature, len(signature), pkey
2729 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002730
2731 if verify_result != 1:
2732 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002733
2734
Dominic Chenf05b2122015-10-13 16:32:35 +00002735def dump_crl(type, crl):
2736 """
2737 Dump a certificate revocation list to a buffer.
2738
2739 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2740 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002741 :param CRL crl: The CRL to dump.
2742
Dominic Chenf05b2122015-10-13 16:32:35 +00002743 :return: The buffer with the CRL.
Dan Sully44e767a2016-06-04 18:05:27 -07002744 :rtype: bytes
Dominic Chenf05b2122015-10-13 16:32:35 +00002745 """
2746 bio = _new_mem_buf()
2747
2748 if type == FILETYPE_PEM:
2749 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2750 elif type == FILETYPE_ASN1:
2751 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2752 elif type == FILETYPE_TEXT:
2753 ret = _lib.X509_CRL_print(bio, crl._crl)
2754 else:
2755 raise ValueError(
2756 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2757 "FILETYPE_TEXT")
2758
2759 assert ret == 1
2760 return _bio_to_string(bio)
2761
2762
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002763def load_crl(type, buffer):
2764 """
2765 Load a certificate revocation list from a buffer
2766
2767 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2768 :param buffer: The buffer the CRL is stored in
2769
2770 :return: The PKey object
2771 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002772 if isinstance(buffer, _text_type):
2773 buffer = buffer.encode("ascii")
2774
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002775 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002776
2777 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002778 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002779 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002780 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002781 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002782 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2783
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002784 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002785 _raise_current_error()
2786
2787 result = CRL.__new__(CRL)
2788 result._crl = crl
2789 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002790
2791
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002792def load_pkcs7_data(type, buffer):
2793 """
2794 Load pkcs7 data from a buffer
2795
2796 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2797 :param buffer: The buffer with the pkcs7 data.
2798 :return: The PKCS7 object
2799 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002800 if isinstance(buffer, _text_type):
2801 buffer = buffer.encode("ascii")
2802
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002803 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002804
2805 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002806 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002807 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002808 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002809 else:
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002810 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2811
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002812 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002813 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002814
2815 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002816 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002817 return pypkcs7
2818
2819
Stephen Holsapple38482622014-04-05 20:29:34 -07002820def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002821 """
2822 Load a PKCS12 object from a buffer
2823
2824 :param buffer: The buffer the certificate is stored in
2825 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2826 :returns: The PKCS12 object
2827 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002828 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002829
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002830 if isinstance(buffer, _text_type):
2831 buffer = buffer.encode("ascii")
2832
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002833 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002834
Stephen Holsapple38482622014-04-05 20:29:34 -07002835 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2836 # password based encryption no password and a zero length password are two
2837 # different things, but OpenSSL implementation will try both to figure out
2838 # which one works.
2839 if not passphrase:
2840 passphrase = _ffi.NULL
2841
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002842 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2843 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002844 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002845 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002846
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002847 pkey = _ffi.new("EVP_PKEY**")
2848 cert = _ffi.new("X509**")
2849 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002850
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002851 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002852 if not parse_result:
2853 _raise_current_error()
2854
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002855 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002856
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002857 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
2858 # queue for no particular reason. This error isn't interesting to anyone
2859 # outside this function. It's not even interesting to us. Get rid of it.
2860 try:
2861 _raise_current_error()
2862 except Error:
2863 pass
2864
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002865 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002866 pykey = None
2867 else:
2868 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002869 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002870
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002871 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002872 pycert = None
2873 friendlyname = None
2874 else:
2875 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002876 pycert._x509 = _ffi.gc(cert[0], _lib.X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002877
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002878 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04002879 friendlyname_buffer = _lib.X509_alias_get0(
2880 cert[0], friendlyname_length
2881 )
2882 friendlyname = _ffi.buffer(
2883 friendlyname_buffer, friendlyname_length[0]
2884 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002885 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002886 friendlyname = None
2887
2888 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002889 for i in range(_lib.sk_X509_num(cacerts)):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002890 pycacert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002891 pycacert._x509 = _lib.sk_X509_value(cacerts, i)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002892 pycacerts.append(pycacert)
2893 if not pycacerts:
2894 pycacerts = None
2895
2896 pkcs12 = PKCS12.__new__(PKCS12)
2897 pkcs12._pkey = pykey
2898 pkcs12._cert = pycert
2899 pkcs12._cacerts = pycacerts
2900 pkcs12._friendlyname = friendlyname
2901 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05002902
2903
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05002904# There are no direct unit tests for this initialization. It is tested
2905# indirectly since it is necessary for functions like dump_privatekey when
2906# using encryption.
2907#
2908# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
2909# and some other similar tests may fail without this (though they may not if
2910# the Python runtime has already done some initialization of the underlying
2911# OpenSSL library (and is linked against the same one that cryptography is
2912# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05002913_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05002914
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05002915# This is similar but exercised mainly by exception_from_error_queue. It calls
2916# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
2917_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002918
2919
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002920# Set the default string mask to match OpenSSL upstream (since 2005) and
2921# RFC5280 recommendations.
2922_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')