blob: 84cce76cb72c205097aacbb6b511ce19bb30fbe1 [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
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050013from OpenSSL._util import (
14 ffi as _ffi,
15 lib as _lib,
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050016 exception_from_error_queue as _exception_from_error_queue,
17 byte_string as _byte_string,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040018 native as _native,
19 UNSPECIFIED as _UNSPECIFIED,
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -040020 text_to_bytes_and_warn as _text_to_bytes_and_warn,
Alex Gaynor67903a62016-06-02 10:37:13 -070021 make_assert as _make_assert,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -040022)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080023
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050024FILETYPE_PEM = _lib.SSL_FILETYPE_PEM
25FILETYPE_ASN1 = _lib.SSL_FILETYPE_ASN1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080026
27# TODO This was an API mistake. OpenSSL has no such constant.
28FILETYPE_TEXT = 2 ** 16 - 1
29
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050030TYPE_RSA = _lib.EVP_PKEY_RSA
31TYPE_DSA = _lib.EVP_PKEY_DSA
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -080032
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080033
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050034class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050035 """
36 An error occurred in an `OpenSSL.crypto` API.
37 """
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050038
39
40_raise_current_error = partial(_exception_from_error_queue, Error)
Alex Gaynor67903a62016-06-02 10:37:13 -070041_openssl_assert = _make_assert(Error)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050042
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070043
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050044def _untested_error(where):
45 """
46 An OpenSSL API failed somehow. Additionally, the failure which was
47 encountered isn't one that's exercised by the test suite so future behavior
48 of pyOpenSSL is now somewhat less predictable.
49 """
50 raise RuntimeError("Unknown %s failure" % (where,))
51
52
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050053def _new_mem_buf(buffer=None):
54 """
55 Allocate a new OpenSSL memory BIO.
56
57 Arrange for the garbage collector to clean it up automatically.
58
59 :param buffer: None or some bytes to use to put into the BIO so that they
60 can be read out.
61 """
62 if buffer is None:
63 bio = _lib.BIO_new(_lib.BIO_s_mem())
64 free = _lib.BIO_free
65 else:
66 data = _ffi.new("char[]", buffer)
67 bio = _lib.BIO_new_mem_buf(data, len(buffer))
Alex Gaynor5945ea82015-09-05 14:59:06 -040068
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -050069 # Keep the memory alive as long as the bio is alive!
70 def free(bio, ref=data):
71 return _lib.BIO_free(bio)
72
73 if bio == _ffi.NULL:
74 # TODO: This is untested.
75 _raise_current_error()
76
77 bio = _ffi.gc(bio, free)
78 return bio
79
80
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080081def _bio_to_string(bio):
82 """
83 Copy the contents of an OpenSSL BIO object into a Python byte string.
84 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050085 result_buffer = _ffi.new('char**')
86 buffer_length = _lib.BIO_get_mem_data(bio, result_buffer)
87 return _ffi.buffer(result_buffer[0], buffer_length)[:]
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -080088
89
Jean-Paul Calderone57122982013-02-21 08:47:05 -080090def _set_asn1_time(boundary, when):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -050091 """
92 The the time value of an ASN1 time object.
93
94 @param boundary: An ASN1_GENERALIZEDTIME pointer (or an object safely
95 castable to that type) which will have its value set.
96 @param when: A string representation of the desired time value.
97
98 @raise TypeError: If C{when} is not a L{bytes} string.
99 @raise ValueError: If C{when} does not represent a time in the required
100 format.
101 @raise RuntimeError: If the time value cannot be set for some other
102 (unspecified) reason.
103 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800104 if not isinstance(when, bytes):
105 raise TypeError("when must be a byte string")
106
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500107 set_result = _lib.ASN1_GENERALIZEDTIME_set_string(
108 _ffi.cast('ASN1_GENERALIZEDTIME*', boundary), when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800109 if set_result == 0:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500110 dummy = _ffi.gc(_lib.ASN1_STRING_new(), _lib.ASN1_STRING_free)
111 _lib.ASN1_STRING_set(dummy, when, len(when))
112 check_result = _lib.ASN1_GENERALIZEDTIME_check(
113 _ffi.cast('ASN1_GENERALIZEDTIME*', dummy))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800114 if not check_result:
115 raise ValueError("Invalid string")
116 else:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500117 _untested_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800118
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800119def _get_asn1_time(timestamp):
Jean-Paul Calderonee728e872013-12-29 10:37:15 -0500120 """
121 Retrieve the time value of an ASN1 time object.
122
123 @param timestamp: An ASN1_GENERALIZEDTIME* (or an object safely castable to
124 that type) from which the time value will be retrieved.
125
126 @return: The time value from C{timestamp} as a L{bytes} string in a certain
127 format. Or C{None} if the object contains no time value.
128 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500129 string_timestamp = _ffi.cast('ASN1_STRING*', timestamp)
130 if _lib.ASN1_STRING_length(string_timestamp) == 0:
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800131 return None
Alex Gaynor5945ea82015-09-05 14:59:06 -0400132 elif (
133 _lib.ASN1_STRING_type(string_timestamp) == _lib.V_ASN1_GENERALIZEDTIME
134 ):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500135 return _ffi.string(_lib.ASN1_STRING_data(string_timestamp))
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800136 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500137 generalized_timestamp = _ffi.new("ASN1_GENERALIZEDTIME**")
138 _lib.ASN1_TIME_to_generalizedtime(timestamp, generalized_timestamp)
139 if generalized_timestamp[0] == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500140 # This may happen:
141 # - if timestamp was not an ASN1_TIME
142 # - if allocating memory for the ASN1_GENERALIZEDTIME failed
143 # - if a copy of the time data from timestamp cannot be made for
144 # the newly allocated ASN1_GENERALIZEDTIME
145 #
146 # These are difficult to test. cffi enforces the ASN1_TIME type.
147 # Memory allocation failures are a pain to trigger
148 # deterministically.
149 _untested_error("ASN1_TIME_to_generalizedtime")
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800150 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500151 string_timestamp = _ffi.cast(
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800152 "ASN1_STRING*", generalized_timestamp[0])
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500153 string_data = _lib.ASN1_STRING_data(string_timestamp)
154 string_result = _ffi.string(string_data)
155 _lib.ASN1_GENERALIZEDTIME_free(generalized_timestamp[0])
Jean-Paul Calderone57122982013-02-21 08:47:05 -0800156 return string_result
157
158
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800159class PKey(object):
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200160 """
161 A class representing an DSA or RSA public key or key pair.
162 """
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800163 _only_public = False
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800164 _initialized = True
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -0800165
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800166 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500167 pkey = _lib.EVP_PKEY_new()
168 self._pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800169 self._initialized = False
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800170
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800171 def generate_key(self, type, bits):
172 """
Laurens Van Houtven90c09142015-04-23 10:52:49 -0700173 Generate a key pair of the given type, with the given number of bits.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800174
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200175 This generates a key "into" the this object.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800176
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200177 :param type: The key type.
178 :type type: :py:data:`TYPE_RSA` or :py:data:`TYPE_DSA`
179 :param bits: The number of bits.
180 :type bits: :py:data:`int` ``>= 0``
181 :raises TypeError: If :py:data:`type` or :py:data:`bits` isn't
182 of the appropriate type.
183 :raises ValueError: If the number of bits isn't an integer of
184 the appropriate size.
Laurens Van Houtvena7904582014-06-19 12:33:04 +0200185 :return: :py:const:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800186 """
187 if not isinstance(type, int):
188 raise TypeError("type must be an integer")
189
190 if not isinstance(bits, int):
191 raise TypeError("bits must be an integer")
192
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800193 # TODO Check error return
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500194 exponent = _lib.BN_new()
195 exponent = _ffi.gc(exponent, _lib.BN_free)
196 _lib.BN_set_word(exponent, _lib.RSA_F4)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800197
198 if type == TYPE_RSA:
199 if bits <= 0:
200 raise ValueError("Invalid number of bits")
201
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500202 rsa = _lib.RSA_new()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800203
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500204 result = _lib.RSA_generate_key_ex(rsa, bits, exponent, _ffi.NULL)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500205 if result == 0:
206 # TODO: The test for this case is commented out. Different
207 # builds of OpenSSL appear to have different failure modes that
208 # make it hard to test. Visual inspection of the OpenSSL
209 # source reveals that a return value of 0 signals an error.
210 # Manual testing on a particular build of OpenSSL suggests that
211 # this is probably the appropriate way to handle those errors.
212 _raise_current_error()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800213
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500214 result = _lib.EVP_PKEY_assign_RSA(self._pkey, rsa)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800215 if not result:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500216 # TODO: It appears as though this can fail if an engine is in
217 # use which does not support RSA.
218 _raise_current_error()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800219
220 elif type == TYPE_DSA:
Paul Kehrera0860b92016-03-09 21:39:27 -0400221 dsa = _lib.DSA_new()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500222 if dsa == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500223 # TODO: This is untested.
224 _raise_current_error()
Paul Kehrerafa5a662016-03-10 10:29:28 -0400225
226 dsa = _ffi.gc(dsa, _lib.DSA_free)
Paul Kehrera0860b92016-03-09 21:39:27 -0400227 res = _lib.DSA_generate_parameters_ex(
228 dsa, bits, _ffi.NULL, 0, _ffi.NULL, _ffi.NULL, _ffi.NULL
229 )
230 if not res == 1:
231 # TODO: This is untested.
232 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500233 if not _lib.DSA_generate_key(dsa):
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500234 # TODO: This is untested.
235 _raise_current_error()
Paul Kehrerafa5a662016-03-10 10:29:28 -0400236 if not _lib.EVP_PKEY_set1_DSA(self._pkey, dsa):
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500237 # TODO: This is untested.
238 _raise_current_error()
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -0800239 else:
240 raise Error("No such key type")
241
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -0800242 self._initialized = True
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800243
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800244 def check(self):
245 """
246 Check the consistency of an RSA private key.
247
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +0200248 This is the Python equivalent of OpenSSL's ``RSA_check_key``.
249
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800250 :return: True if key is consistent.
251 :raise Error: if the key is inconsistent.
252 :raise TypeError: if the key is of a type which cannot be checked.
253 Only RSA keys can currently be checked.
254 """
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800255 if self._only_public:
256 raise TypeError("public key only")
257
Hynek Schlawack2a91ba32016-01-31 14:18:54 +0100258 if _lib.EVP_PKEY_type(self.type()) != _lib.EVP_PKEY_RSA:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800259 raise TypeError("key type unsupported")
260
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500261 rsa = _lib.EVP_PKEY_get1_RSA(self._pkey)
262 rsa = _ffi.gc(rsa, _lib.RSA_free)
263 result = _lib.RSA_check_key(rsa)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800264 if result:
265 return True
266 _raise_current_error()
267
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800268 def type(self):
269 """
270 Returns the type of the key
271
272 :return: The type of the key.
273 """
Alex Gaynorc84567b2016-03-16 07:45:09 -0400274 return _lib.Cryptography_EVP_PKEY_id(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800275
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800276 def bits(self):
277 """
278 Returns the number of bits of the key
279
280 :return: The number of bits of the key.
281 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500282 return _lib.EVP_PKEY_bits(self._pkey)
Jean-Paul Calderonec86fcaf2013-02-20 12:38:33 -0800283PKeyType = PKey
284
285
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400286class _EllipticCurve(object):
287 """
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400288 A representation of a supported elliptic curve.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400289
290 @cvar _curves: :py:obj:`None` until an attempt is made to load the curves.
291 Thereafter, a :py:type:`set` containing :py:type:`_EllipticCurve`
292 instances each of which represents one curve supported by the system.
293 @type _curves: :py:type:`NoneType` or :py:type:`set`
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400294 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400295 _curves = None
296
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400297 if _PY3:
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400298 # This only necessary on Python 3. Morever, it is broken on Python 2.
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400299 def __ne__(self, other):
Jean-Paul Calderonea5381052014-05-01 09:32:46 -0400300 """
301 Implement cooperation with the right-hand side argument of ``!=``.
302
303 Python 3 seems to have dropped this cooperation in this very narrow
304 circumstance.
305 """
Jean-Paul Calderonef22abcd2014-05-01 09:31:19 -0400306 if isinstance(other, _EllipticCurve):
307 return super(_EllipticCurve, self).__ne__(other)
308 return NotImplemented
Jean-Paul Calderone40da72d2014-05-01 09:25:17 -0400309
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400310 @classmethod
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400311 def _load_elliptic_curves(cls, lib):
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400312 """
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400313 Get the curves supported by OpenSSL.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400314
315 :param lib: The OpenSSL library binding object.
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400316
317 :return: A :py:type:`set` of ``cls`` instances giving the names of the
318 elliptic curves the underlying library supports.
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400319 """
320 if lib.Cryptography_HAS_EC:
321 num_curves = lib.EC_get_builtin_curves(_ffi.NULL, 0)
322 builtin_curves = _ffi.new('EC_builtin_curve[]', num_curves)
Alex Gaynor5945ea82015-09-05 14:59:06 -0400323 # The return value on this call should be num_curves again. We
324 # could check it to make sure but if it *isn't* then.. what could
325 # we do? Abort the whole process, I suppose...? -exarkun
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400326 lib.EC_get_builtin_curves(builtin_curves, num_curves)
327 return set(
328 cls.from_nid(lib, c.nid)
329 for c in builtin_curves)
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400330 return set()
331
Jean-Paul Calderone73945e32014-04-30 18:18:01 -0400332 @classmethod
333 def _get_elliptic_curves(cls, lib):
334 """
335 Get, cache, and return the curves supported by OpenSSL.
336
337 :param lib: The OpenSSL library binding object.
338
339 :return: A :py:type:`set` of ``cls`` instances giving the names of the
340 elliptic curves the underlying library supports.
341 """
342 if cls._curves is None:
343 cls._curves = cls._load_elliptic_curves(lib)
344 return cls._curves
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400345
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400346 @classmethod
347 def from_nid(cls, lib, nid):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400348 """
349 Instantiate a new :py:class:`_EllipticCurve` associated with the given
350 OpenSSL NID.
351
352 :param lib: The OpenSSL library binding object.
353
354 :param nid: The OpenSSL NID the resulting curve object will represent.
355 This must be a curve NID (and not, for example, a hash NID) or
356 subsequent operations will fail in unpredictable ways.
357 :type nid: :py:class:`int`
358
359 :return: The curve object.
360 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400361 return cls(lib, nid, _ffi.string(lib.OBJ_nid2sn(nid)).decode("ascii"))
362
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400363 def __init__(self, lib, nid, name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400364 """
365 :param _lib: The :py:mod:`cryptography` binding instance used to
366 interface with OpenSSL.
367
368 :param _nid: The OpenSSL NID identifying the curve this object
369 represents.
370 :type _nid: :py:class:`int`
371
372 :param name: The OpenSSL short name identifying the curve this object
373 represents.
374 :type name: :py:class:`unicode`
375 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400376 self._lib = lib
377 self._nid = nid
378 self.name = name
379
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400380 def __repr__(self):
381 return "<Curve %r>" % (self.name,)
382
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400383 def _to_EC_KEY(self):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400384 """
385 Create a new OpenSSL EC_KEY structure initialized to use this curve.
386
387 The structure is automatically garbage collected when the Python object
388 is garbage collected.
389 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400390 key = self._lib.EC_KEY_new_by_curve_name(self._nid)
391 return _ffi.gc(key, _lib.EC_KEY_free)
392
393
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400394def get_elliptic_curves():
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400395 """
396 Return a set of objects representing the elliptic curves supported in the
397 OpenSSL build in use.
398
399 The curve objects have a :py:class:`unicode` ``name`` attribute by which
400 they identify themselves.
401
402 The curve objects are useful as values for the argument accepted by
Jean-Paul Calderone3b04e352014-04-19 09:29:10 -0400403 :py:meth:`Context.set_tmp_ecdh` to specify which elliptical curve should be
404 used for ECDHE key exchange.
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400405 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400406 return _EllipticCurve._get_elliptic_curves(_lib)
407
408
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400409def get_elliptic_curve(name):
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400410 """
411 Return a single curve object selected by name.
412
413 See :py:func:`get_elliptic_curves` for information about curve objects.
414
Jean-Paul Calderoned5839e22014-04-19 09:26:44 -0400415 :param name: The OpenSSL short name identifying the curve object to
416 retrieve.
417 :type name: :py:class:`unicode`
418
Jean-Paul Calderoneaaf516d2014-04-19 09:10:45 -0400419 If the named curve is not supported then :py:class:`ValueError` is raised.
420 """
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -0400421 for curve in get_elliptic_curves():
422 if curve.name == name:
423 return curve
424 raise ValueError("unknown curve name", name)
425
426
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800427class X509Name(object):
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200428 """
429 An X.509 Distinguished Name.
430
431 :ivar countryName: The country of the entity.
432 :ivar C: Alias for :py:attr:`countryName`.
433
434 :ivar stateOrProvinceName: The state or province of the entity.
435 :ivar ST: Alias for :py:attr:`stateOrProvinceName`.
436
437 :ivar localityName: The locality of the entity.
438 :ivar L: Alias for :py:attr:`localityName`.
439
440 :ivar organizationName: The organization name of the entity.
441 :ivar O: Alias for :py:attr:`organizationName`.
442
443 :ivar organizationalUnitName: The organizational unit of the entity.
444 :ivar OU: Alias for :py:attr:`organizationalUnitName`
445
446 :ivar commonName: The common name of the entity.
447 :ivar CN: Alias for :py:attr:`commonName`.
448
449 :ivar emailAddress: The e-mail address of the entity.
450 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400451
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800452 def __init__(self, name):
453 """
454 Create a new X509Name, copying the given X509Name instance.
455
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200456 :param name: The name to copy.
457 :type name: :py:class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800458 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500459 name = _lib.X509_NAME_dup(name._name)
460 self._name = _ffi.gc(name, _lib.X509_NAME_free)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800461
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800462 def __setattr__(self, name, value):
463 if name.startswith('_'):
464 return super(X509Name, self).__setattr__(name, value)
465
Jean-Paul Calderoneff363be2013-03-03 10:21:23 -0800466 # Note: we really do not want str subclasses here, so we do not use
467 # isinstance.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800468 if type(name) is not str:
469 raise TypeError("attribute name must be string, not '%.200s'" % (
Alex Gaynora738ed52015-09-05 11:17:10 -0400470 type(value).__name__,))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800471
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500472 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500473 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800474 try:
475 _raise_current_error()
476 except Error:
477 pass
478 raise AttributeError("No such attribute")
479
480 # If there's an old entry for this NID, remove it
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500481 for i in range(_lib.X509_NAME_entry_count(self._name)):
482 ent = _lib.X509_NAME_get_entry(self._name, i)
483 ent_obj = _lib.X509_NAME_ENTRY_get_object(ent)
484 ent_nid = _lib.OBJ_obj2nid(ent_obj)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800485 if nid == ent_nid:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500486 ent = _lib.X509_NAME_delete_entry(self._name, i)
487 _lib.X509_NAME_ENTRY_free(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800488 break
489
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500490 if isinstance(value, _text_type):
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800491 value = value.encode('utf-8')
492
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500493 add_result = _lib.X509_NAME_add_entry_by_NID(
494 self._name, nid, _lib.MBSTRING_UTF8, value, -1, -1, 0)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800495 if not add_result:
Jean-Paul Calderone5300d6a2013-12-29 16:36:50 -0500496 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800497
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800498 def __getattr__(self, name):
499 """
500 Find attribute. An X509Name object has the following attributes:
501 countryName (alias C), stateOrProvince (alias ST), locality (alias L),
Alex Gaynor5945ea82015-09-05 14:59:06 -0400502 organization (alias O), organizationalUnit (alias OU), commonName
503 (alias CN) and more...
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800504 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500505 nid = _lib.OBJ_txt2nid(_byte_string(name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500506 if nid == _lib.NID_undef:
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800507 # This is a bit weird. OBJ_txt2nid indicated failure, but it seems
508 # a lower level function, a2d_ASN1_OBJECT, also feels the need to
509 # push something onto the error queue. If we don't clean that up
510 # now, someone else will bump into it later and be quite confused.
511 # See lp#314814.
512 try:
513 _raise_current_error()
514 except Error:
515 pass
516 return super(X509Name, self).__getattr__(name)
517
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500518 entry_index = _lib.X509_NAME_get_index_by_NID(self._name, nid, -1)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800519 if entry_index == -1:
520 return None
521
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500522 entry = _lib.X509_NAME_get_entry(self._name, entry_index)
523 data = _lib.X509_NAME_ENTRY_get_data(entry)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800524
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500525 result_buffer = _ffi.new("unsigned char**")
526 data_length = _lib.ASN1_STRING_to_UTF8(result_buffer, data)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800527 if data_length < 0:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500528 # TODO: This is untested.
529 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800530
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700531 try:
Alex Gaynor5945ea82015-09-05 14:59:06 -0400532 result = _ffi.buffer(
533 result_buffer[0], data_length
534 )[:].decode('utf-8')
Jean-Paul Calderoned899af02013-03-19 22:10:37 -0700535 finally:
536 # XXX untested
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500537 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800538 return result
539
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500540 def _cmp(op):
541 def f(self, other):
542 if not isinstance(other, X509Name):
543 return NotImplemented
544 result = _lib.X509_NAME_cmp(self._name, other._name)
545 return op(result, 0)
546 return f
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800547
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500548 __eq__ = _cmp(__eq__)
549 __ne__ = _cmp(__ne__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800550
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500551 __lt__ = _cmp(__lt__)
552 __le__ = _cmp(__le__)
553
554 __gt__ = _cmp(__gt__)
555 __ge__ = _cmp(__ge__)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800556
557 def __repr__(self):
558 """
559 String representation of an X509Name
560 """
Alex Gaynor962ac212015-09-04 08:06:42 -0400561 result_buffer = _ffi.new("char[]", 512)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500562 format_result = _lib.X509_NAME_oneline(
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800563 self._name, result_buffer, len(result_buffer))
564
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500565 if format_result == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500566 # TODO: This is untested.
567 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800568
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500569 return "<X509Name object '%s'>" % (
570 _native(_ffi.string(result_buffer)),)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800571
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800572 def hash(self):
573 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200574 Return an integer representation of the first four bytes of the
575 MD5 digest of the DER representation of the name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800576
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200577 This is the Python equivalent of OpenSSL's ``X509_NAME_hash``.
578
579 :return: The (integer) hash of this name.
580 :rtype: :py:class:`int`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800581 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500582 return _lib.X509_NAME_hash(self._name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800583
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800584 def der(self):
585 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200586 Return the DER encoding of this name.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800587
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200588 :return: The DER encoded form of this name.
589 :rtype: :py:class:`bytes`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800590 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500591 result_buffer = _ffi.new('unsigned char**')
592 encode_result = _lib.i2d_X509_NAME(self._name, result_buffer)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800593 if encode_result < 0:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500594 # TODO: This is untested.
595 _raise_current_error()
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800596
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500597 string_result = _ffi.buffer(result_buffer[0], encode_result)[:]
598 _lib.OPENSSL_free(result_buffer[0])
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800599 return string_result
600
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800601 def get_components(self):
602 """
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200603 Returns the components of this name, as a sequence of 2-tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800604
Laurens Van Houtven196195b2014-06-17 17:06:34 +0200605 :return: The components of this name.
606 :rtype: :py:class:`list` of ``name, value`` tuples.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800607 """
608 result = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500609 for i in range(_lib.X509_NAME_entry_count(self._name)):
610 ent = _lib.X509_NAME_get_entry(self._name, i)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800611
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500612 fname = _lib.X509_NAME_ENTRY_get_object(ent)
613 fval = _lib.X509_NAME_ENTRY_get_data(ent)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800614
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500615 nid = _lib.OBJ_obj2nid(fname)
616 name = _lib.OBJ_nid2sn(nid)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800617
618 result.append((
Alex Gaynora738ed52015-09-05 11:17:10 -0400619 _ffi.string(name),
620 _ffi.string(
621 _lib.ASN1_STRING_data(fval),
622 _lib.ASN1_STRING_length(fval))))
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800623
624 return result
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200625
626
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800627X509NameType = X509Name
628
629
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800630class X509Extension(object):
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200631 """
632 An X.509 v3 certificate extension.
633 """
Alex Gaynor5945ea82015-09-05 14:59:06 -0400634
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800635 def __init__(self, type_name, critical, value, subject=None, issuer=None):
636 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200637 Initializes an X509 extension.
638
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100639 :param type_name: The name of the type of extension_ to create.
Alex Gaynor6f719912015-09-20 09:21:29 -0400640 :type type_name: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800641
Alex Gaynor5945ea82015-09-05 14:59:06 -0400642 :param bool critical: A flag indicating whether this is a critical
643 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800644
645 :param value: The value of the extension.
Maximilian Hils0de43752015-09-18 15:26:54 +0200646 :type value: :py:data:`bytes`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800647
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200648 :param subject: Optional X509 certificate to use as subject.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800649 :type subject: :py:class:`X509`
650
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200651 :param issuer: Optional X509 certificate to use as issuer.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800652 :type issuer: :py:class:`X509`
Hynek Schlawack8d4f9762016-03-19 08:15:03 +0100653
654 .. _extension: https://openssl.org/docs/manmaster/apps/
655 x509v3_config.html#STANDARD-EXTENSIONS
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800656 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500657 ctx = _ffi.new("X509V3_CTX*")
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800658
Alex Gaynor5945ea82015-09-05 14:59:06 -0400659 # A context is necessary for any extension which uses the r2i
660 # conversion method. That is, X509V3_EXT_nconf may segfault if passed
661 # a NULL ctx. Start off by initializing most of the fields to NULL.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500662 _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800663
664 # We have no configuration database - but perhaps we should (some
665 # extensions may require it).
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500666 _lib.X509V3_set_ctx_nodb(ctx)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800667
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800668 # Initialize the subject and issuer, if appropriate. ctx is a local,
669 # and as far as I can tell none of the X509V3_* APIs invoked here steal
Alex Gaynora738ed52015-09-05 11:17:10 -0400670 # any references, so no need to mess with reference counts or
671 # duplicates.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800672 if issuer is not None:
673 if not isinstance(issuer, X509):
674 raise TypeError("issuer must be an X509 instance")
675 ctx.issuer_cert = issuer._x509
676 if subject is not None:
677 if not isinstance(subject, X509):
678 raise TypeError("subject must be an X509 instance")
679 ctx.subject_cert = subject._x509
680
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800681 if critical:
682 # There are other OpenSSL APIs which would let us pass in critical
683 # separately, but they're harder to use, and since value is already
684 # a pile of crappy junk smuggling a ton of utterly important
685 # structured data, what's the point of trying to avoid nasty stuff
Alex Gaynor5945ea82015-09-05 14:59:06 -0400686 # with strings? (However, X509V3_EXT_i2d in particular seems like
687 # it would be a better API to invoke. I do not know where to get
688 # the ext_struc it desires for its last parameter, though.)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500689 value = b"critical," + value
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800690
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500691 extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
692 if extension == _ffi.NULL:
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800693 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500694 self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800695
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400696 @property
697 def _nid(self):
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400698 return _lib.OBJ_obj2nid(
699 _lib.X509_EXTENSION_get_object(self._extension)
700 )
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400701
702 _prefixes = {
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500703 _lib.GEN_EMAIL: "email",
704 _lib.GEN_DNS: "DNS",
705 _lib.GEN_URI: "URI",
Alex Gaynora738ed52015-09-05 11:17:10 -0400706 }
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400707
708 def _subjectAltNameString(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500709 method = _lib.X509V3_EXT_get(self._extension)
710 if method == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500711 # TODO: This is untested.
712 _raise_current_error()
Paul Kehrere8f91cc2016-03-09 21:26:29 -0400713 ext_data = _lib.X509_EXTENSION_get_data(self._extension)
714 payload = ext_data.data
715 length = ext_data.length
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400716
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500717 payloadptr = _ffi.new("unsigned char**")
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400718 payloadptr[0] = payload
719
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500720 if method.it != _ffi.NULL:
721 ptr = _lib.ASN1_ITEM_ptr(method.it)
722 data = _lib.ASN1_item_d2i(_ffi.NULL, payloadptr, length, ptr)
723 names = _ffi.cast("GENERAL_NAMES*", data)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400724 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500725 names = _ffi.cast(
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400726 "GENERAL_NAMES*",
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500727 method.d2i(_ffi.NULL, payloadptr, length))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400728
Paul Kehrerb7d79502015-05-04 07:43:51 -0500729 names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400730 parts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500731 for i in range(_lib.sk_GENERAL_NAME_num(names)):
732 name = _lib.sk_GENERAL_NAME_value(names, i)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400733 try:
734 label = self._prefixes[name.type]
735 except KeyError:
736 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500737 _lib.GENERAL_NAME_print(bio, name)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500738 parts.append(_native(_bio_to_string(bio)))
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400739 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500740 value = _native(
741 _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[:])
742 parts.append(label + ":" + value)
743 return ", ".join(parts)
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400744
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800745 def __str__(self):
746 """
747 :return: a nice text representation of the extension
748 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500749 if _lib.NID_subject_alt_name == self._nid:
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400750 return self._subjectAltNameString()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800751
Jean-Paul Calderoneed0c57b2013-10-06 08:31:40 -0400752 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500753 print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800754 if not print_result:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500755 # TODO: This is untested.
756 _raise_current_error()
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800757
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500758 return _native(_bio_to_string(bio))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800759
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800760 def get_critical(self):
761 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200762 Returns the critical field of this X.509 extension.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800763
764 :return: The critical field.
765 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500766 return _lib.X509_EXTENSION_get_critical(self._extension)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800767
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800768 def get_short_name(self):
769 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200770 Returns the short type name of this X.509 extension.
771
772 The result is a byte string such as :py:const:`b"basicConstraints"`.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800773
774 :return: The short type name.
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200775 :rtype: :py:data:`bytes`
776
777 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800778 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500779 obj = _lib.X509_EXTENSION_get_object(self._extension)
780 nid = _lib.OBJ_obj2nid(obj)
781 return _ffi.string(_lib.OBJ_nid2sn(nid))
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -0800782
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800783 def get_data(self):
784 """
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200785 Returns the data of the X509 extension, encoded as ASN.1.
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800786
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200787 :return: The ASN.1 encoded data of this X509 extension.
788 :rtype: :py:data:`bytes`
789
790 .. versionadded:: 0.12
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800791 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500792 octet_result = _lib.X509_EXTENSION_get_data(self._extension)
793 string_result = _ffi.cast('ASN1_STRING*', octet_result)
794 char_result = _lib.ASN1_STRING_data(string_result)
795 result_length = _lib.ASN1_STRING_length(string_result)
796 return _ffi.buffer(char_result, result_length)[:]
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800797
Laurens Van Houtven2650de52014-06-18 13:47:47 +0200798
Jean-Paul Calderoned418a9c2013-02-20 16:24:55 -0800799X509ExtensionType = X509Extension
800
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -0800801
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800802class X509Req(object):
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200803 """
804 An X.509 certificate signing requests.
805 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400806
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800807 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500808 req = _lib.X509_REQ_new()
809 self._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800810
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800811 def set_pubkey(self, pkey):
812 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200813 Set the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800814
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200815 :param pkey: The public key to use.
816 :type pkey: :py:class:`PKey`
817
Laurens Van Houtvena7904582014-06-19 12:33:04 +0200818 :return: :py:const:`None`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800819 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500820 set_result = _lib.X509_REQ_set_pubkey(self._req, pkey._pkey)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800821 if not set_result:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500822 # TODO: This is untested.
823 _raise_current_error()
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800824
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800825 def get_pubkey(self):
826 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200827 Get the public key of the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800828
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200829 :return: The public key.
830 :rtype: :py:class:`PKey`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800831 """
832 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500833 pkey._pkey = _lib.X509_REQ_get_pubkey(self._req)
834 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500835 # TODO: This is untested.
836 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500837 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800838 pkey._only_public = True
839 return pkey
840
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800841 def set_version(self, version):
842 """
843 Set the version subfield (RFC 2459, section 4.1.2.1) of the certificate
844 request.
845
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200846 :param int version: The version number.
Laurens Van Houtvena7904582014-06-19 12:33:04 +0200847 :return: :py:const:`None`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800848 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500849 set_result = _lib.X509_REQ_set_version(self._req, version)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800850 if not set_result:
851 _raise_current_error()
852
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800853 def get_version(self):
854 """
855 Get the version subfield (RFC 2459, section 4.1.2.1) of the certificate
856 request.
857
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200858 :return: The value of the version subfield.
859 :rtype: :py:class:`int`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800860 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500861 return _lib.X509_REQ_get_version(self._req)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800862
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800863 def get_subject(self):
864 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200865 Return the subject of this certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800866
Cory Benfield881dc8d2015-12-09 08:25:14 +0000867 This creates a new :class:`X509Name` that wraps the underlying subject
868 name field on the certificate signing request. Modifying it will modify
869 the underlying signing request, and will have the effect of modifying
870 any other :class:`X509Name` that refers to this subject.
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200871
872 :return: The subject of this certificate signing request.
Cory Benfield881dc8d2015-12-09 08:25:14 +0000873 :rtype: :class:`X509Name`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800874 """
875 name = X509Name.__new__(X509Name)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500876 name._name = _lib.X509_REQ_get_subject_name(self._req)
877 if name._name == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500878 # TODO: This is untested.
879 _raise_current_error()
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800880
881 # The name is owned by the X509Req structure. As long as the X509Name
882 # Python object is alive, keep the X509Req Python object alive.
883 name._owner = self
884
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800885 return name
886
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800887 def add_extensions(self, extensions):
888 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200889 Add extensions to the certificate signing request.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800890
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200891 :param extensions: The X.509 extensions to add.
892 :type extensions: iterable of :py:class:`X509Extension`
Laurens Van Houtvena7904582014-06-19 12:33:04 +0200893 :return: :py:const:`None`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800894 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500895 stack = _lib.sk_X509_EXTENSION_new_null()
896 if stack == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500897 # TODO: This is untested.
898 _raise_current_error()
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800899
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500900 stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -0800901
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800902 for ext in extensions:
903 if not isinstance(ext, X509Extension):
Jean-Paul Calderonec2154b72013-02-20 14:29:37 -0800904 raise ValueError("One of the elements is not an X509Extension")
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800905
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -0800906 # TODO push can fail (here and elsewhere)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500907 _lib.sk_X509_EXTENSION_push(stack, ext._extension)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800908
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500909 add_result = _lib.X509_REQ_add_extensions(self._req, stack)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800910 if not add_result:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500911 # TODO: This is untested.
912 _raise_current_error()
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800913
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800914 def get_extensions(self):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800915 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200916 Get X.509 extensions in the certificate signing request.
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800917
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200918 :return: The X.509 extensions in this request.
919 :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
920
921 .. versionadded:: 0.15
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800922 """
923 exts = []
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500924 native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
Jean-Paul Calderoneb7a79b42014-03-02 08:06:47 -0500925 for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800926 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone9479d732014-03-02 08:04:54 -0500927 ext._extension = _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
Stephen Holsapple7fbdf642014-03-01 20:05:47 -0800928 exts.append(ext)
929 return exts
Stephen Holsappleadfd39d2014-01-28 17:58:31 -0800930
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800931 def sign(self, pkey, digest):
932 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -0700933 Sign the certificate signing request with this key and digest type.
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800934
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200935 :param pkey: The key pair to sign with.
936 :type pkey: :py:class:`PKey`
937 :param digest: The name of the message digest to use for the signature,
938 e.g. :py:data:`b"sha1"`.
939 :type digest: :py:class:`bytes`
Laurens Van Houtvena7904582014-06-19 12:33:04 +0200940 :return: :py:const:`None`
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800941 """
942 if pkey._only_public:
943 raise ValueError("Key has only public part")
944
945 if not pkey._initialized:
946 raise ValueError("Key is uninitialized")
947
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500948 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500949 if digest_obj == _ffi.NULL:
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800950 raise ValueError("No such digest method")
951
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500952 sign_result = _lib.X509_REQ_sign(self._req, pkey._pkey, digest_obj)
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800953 if not sign_result:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -0500954 # TODO: This is untested.
955 _raise_current_error()
Jean-Paul Calderone4328d472013-02-20 14:28:46 -0800956
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800957 def verify(self, pkey):
958 """
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200959 Verifies the signature on this certificate signing request.
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800960
Laurens Van Houtven3e83d242014-06-18 14:29:47 +0200961 :param key: A public key.
962 :type key: :py:class:`PKey`
963 :return: :py:data:`True` if the signature is correct.
964 :rtype: :py:class:`bool`
965 :raises Error: If the signature is invalid or there is a
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800966 problem verifying the signature.
967 """
968 if not isinstance(pkey, PKey):
969 raise TypeError("pkey must be a PKey instance")
970
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500971 result = _lib.X509_REQ_verify(self._req, pkey._pkey)
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800972 if result <= 0:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -0500973 _raise_current_error()
Jean-Paul Calderone5565f0f2013-03-06 11:10:20 -0800974
975 return result
976
977
Jean-Paul Calderone066f0572013-02-20 13:43:44 -0800978X509ReqType = X509Req
979
980
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800981class X509(object):
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200982 """
983 An X.509 certificate.
984 """
Alex Gaynora738ed52015-09-05 11:17:10 -0400985
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800986 def __init__(self):
987 # TODO Allocation failure? And why not __new__ instead of __init__?
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500988 x509 = _lib.X509_new()
989 self._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800990
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800991 def set_version(self, version):
992 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200993 Set the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800994
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +0200995 :param version: The version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800996 :type version: :py:class:`int`
997
Laurens Van Houtvena7904582014-06-19 12:33:04 +0200998 :return: :py:const:`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -0800999 """
1000 if not isinstance(version, int):
1001 raise TypeError("version must be an integer")
1002
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001003 _lib.X509_set_version(self._x509, version)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001004
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001005 def get_version(self):
1006 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001007 Return the version number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001008
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001009 :return: The version number of the certificate.
1010 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001011 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001012 return _lib.X509_get_version(self._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001013
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001014 def get_pubkey(self):
1015 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001016 Get the public key of the certificate.
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001017
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001018 :return: The public key.
1019 :rtype: :py:class:`PKey`
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001020 """
1021 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001022 pkey._pkey = _lib.X509_get_pubkey(self._x509)
1023 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001024 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001025 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001026 pkey._only_public = True
1027 return pkey
1028
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001029 def set_pubkey(self, pkey):
1030 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001031 Set the public key of the certificate.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001032
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001033 :param pkey: The public key.
1034 :type pkey: :py:class:`PKey`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001035
Laurens Van Houtven33fcf122015-04-23 10:50:08 -07001036 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001037 """
1038 if not isinstance(pkey, PKey):
1039 raise TypeError("pkey must be a PKey instance")
1040
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001041 set_result = _lib.X509_set_pubkey(self._x509, pkey._pkey)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001042 if not set_result:
1043 _raise_current_error()
1044
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001045 def sign(self, pkey, digest):
1046 """
Laurens Van Houtven6f2e4262015-04-23 10:48:32 -07001047 Sign the certificate with this key and digest type.
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001048
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001049 :param pkey: The key to sign with.
1050 :type pkey: :py:class:`PKey`
1051
1052 :param digest: The name of the message digest to use.
1053 :type digest: :py:class:`bytes`
1054
Laurens Van Houtvena367fe82015-04-23 10:49:12 -07001055 :return: :py:data:`None`
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001056 """
1057 if not isinstance(pkey, PKey):
1058 raise TypeError("pkey must be a PKey instance")
1059
Jean-Paul Calderoneedafced2013-02-19 11:48:38 -08001060 if pkey._only_public:
1061 raise ValueError("Key only has public part")
1062
Jean-Paul Calderone09e3bdc2013-02-19 12:15:28 -08001063 if not pkey._initialized:
1064 raise ValueError("Key is uninitialized")
1065
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001066 evp_md = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001067 if evp_md == _ffi.NULL:
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001068 raise ValueError("No such digest method")
1069
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001070 sign_result = _lib.X509_sign(self._x509, pkey._pkey, evp_md)
Jean-Paul Calderone3e29ccf2013-02-19 11:32:46 -08001071 if not sign_result:
1072 _raise_current_error()
1073
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001074 def get_signature_algorithm(self):
1075 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001076 Return the signature algorithm used in the certificate.
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001077
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001078 :return: The name of the algorithm.
1079 :rtype: :py:class:`bytes`
1080
1081 :raises ValueError: If the signature algorithm is undefined.
1082
Laurens Van Houtven0dd87402015-04-23 10:47:18 -07001083 .. versionadded:: 0.13
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001084 """
Alex Gaynor39ea5312016-06-02 09:12:10 -07001085 algor = _lib.X509_get0_tbs_sigalg(self._x509)
1086 nid = _lib.OBJ_obj2nid(algor.algorithm)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001087 if nid == _lib.NID_undef:
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001088 raise ValueError("Undefined signature algorithm")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001089 return _ffi.string(_lib.OBJ_nid2ln(nid))
Jean-Paul Calderonee4aa3fa2013-02-19 12:12:53 -08001090
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001091 def digest(self, digest_name):
1092 """
1093 Return the digest of the X509 object.
1094
1095 :param digest_name: The name of the digest algorithm to use.
1096 :type digest_name: :py:class:`bytes`
1097
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001098 :return: The digest of the object, formatted as
1099 :py:const:`b":"`-delimited hex pairs.
1100 :rtype: :py:class:`bytes`
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001101 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001102 digest = _lib.EVP_get_digestbyname(_byte_string(digest_name))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001103 if digest == _ffi.NULL:
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001104 raise ValueError("No such digest method")
1105
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001106 result_buffer = _ffi.new("char[]", _lib.EVP_MAX_MD_SIZE)
1107 result_length = _ffi.new("unsigned int[]", 1)
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001108 result_length[0] = len(result_buffer)
1109
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001110 digest_result = _lib.X509_digest(
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001111 self._x509, digest, result_buffer, result_length)
1112
1113 if not digest_result:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05001114 # TODO: This is untested.
1115 _raise_current_error()
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001116
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001117 return b":".join([
Alex Gaynora738ed52015-09-05 11:17:10 -04001118 b16encode(ch).upper() for ch
1119 in _ffi.buffer(result_buffer, result_length[0])])
Jean-Paul Calderoneb4078722013-02-19 12:01:55 -08001120
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001121 def subject_name_hash(self):
1122 """
1123 Return the hash of the X509 subject.
1124
1125 :return: The hash of the subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001126 :rtype: :py:class:`bytes`
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001127 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001128 return _lib.X509_subject_name_hash(self._x509)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001129
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001130 def set_serial_number(self, serial):
1131 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001132 Set the serial number of the certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001133
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001134 :param serial: The new serial number.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001135 :type serial: :py:class:`int`
1136
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001137 :return: :py:data`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001138 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001139 if not isinstance(serial, _integer_types):
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001140 raise TypeError("serial must be an integer")
1141
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001142 hex_serial = hex(serial)[2:]
1143 if not isinstance(hex_serial, bytes):
1144 hex_serial = hex_serial.encode('ascii')
1145
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001146 bignum_serial = _ffi.new("BIGNUM**")
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001147
1148 # BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
Alex Gaynor5945ea82015-09-05 14:59:06 -04001149 # it. If bignum is still NULL after this call, then the return value
1150 # is actually the result. I hope. -exarkun
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001151 small_serial = _lib.BN_hex2bn(bignum_serial, hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001152
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001153 if bignum_serial[0] == _ffi.NULL:
1154 set_result = _lib.ASN1_INTEGER_set(
1155 _lib.X509_get_serialNumber(self._x509), small_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001156 if set_result:
1157 # TODO Not tested
1158 _raise_current_error()
1159 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001160 asn1_serial = _lib.BN_to_ASN1_INTEGER(bignum_serial[0], _ffi.NULL)
1161 _lib.BN_free(bignum_serial[0])
1162 if asn1_serial == _ffi.NULL:
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001163 # TODO Not tested
1164 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001165 asn1_serial = _ffi.gc(asn1_serial, _lib.ASN1_INTEGER_free)
1166 set_result = _lib.X509_set_serialNumber(self._x509, asn1_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001167 if not set_result:
1168 # TODO Not tested
1169 _raise_current_error()
1170
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001171 def get_serial_number(self):
1172 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001173 Return the serial number of this certificate.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001174
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001175 :return: The serial number.
1176 :rtype: :py:class:`int`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001177 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001178 asn1_serial = _lib.X509_get_serialNumber(self._x509)
1179 bignum_serial = _lib.ASN1_INTEGER_to_BN(asn1_serial, _ffi.NULL)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001180 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001181 hex_serial = _lib.BN_bn2hex(bignum_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001182 try:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001183 hexstring_serial = _ffi.string(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001184 serial = int(hexstring_serial, 16)
1185 return serial
1186 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001187 _lib.OPENSSL_free(hex_serial)
Jean-Paul Calderone78133852013-02-19 10:41:46 -08001188 finally:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001189 _lib.BN_free(bignum_serial)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001190
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001191 def gmtime_adj_notAfter(self, amount):
1192 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001193 Adjust the time stamp on which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001194
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001195 :param amount: The number of seconds by which to adjust the timestamp.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001196 :type amount: :py:class:`int`
1197
Laurens Van Houtvena7904582014-06-19 12:33:04 +02001198 :return: :py:const:`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.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02001211 :return: :py:const:`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
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001223 :return: :py:const:`True` if the certificate has expired,
1224 :py:const:`False` otherwise.
1225 :rtype: :py:class:`bool`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001226 """
Paul Kehrer8d887e12015-10-24 09:09:55 -05001227 time_string = _native(self.get_notAfter())
Paul Kehrerfde45c92016-01-21 12:57:37 -06001228 not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ")
Paul Kehrer5d5d28d2015-10-21 18:55:22 -05001229
Paul Kehrerfde45c92016-01-21 12:57:37 -06001230 return not_after < datetime.datetime.utcnow()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001231
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001232 def _get_boundary_time(self, which):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001233 return _get_asn1_time(which(self._x509))
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001234
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001235 def get_notBefore(self):
1236 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001237 Get the timestamp at which the certificate starts being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001238
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001239 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001240
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001241 YYYYMMDDhhmmssZ
1242 YYYYMMDDhhmmss+hhmm
1243 YYYYMMDDhhmmss-hhmm
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001244
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001245 :return: A timestamp string, or :py:const:`None` if there is none.
1246 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001247 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001248 return self._get_boundary_time(_lib.X509_get_notBefore)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001249
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001250 def _set_boundary_time(self, which, when):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001251 return _set_asn1_time(which(self._x509), when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001252
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001253 def set_notBefore(self, when):
1254 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001255 Set the timestamp at which the certificate starts being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001256
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001257 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001258
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001259 YYYYMMDDhhmmssZ
1260 YYYYMMDDhhmmss+hhmm
1261 YYYYMMDDhhmmss-hhmm
1262
1263 :param when: A timestamp string.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001264 :type when: :py:class:`bytes`
1265
Laurens Van Houtvena7904582014-06-19 12:33:04 +02001266 :return: :py:const:`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001267 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001268 return self._set_boundary_time(_lib.X509_get_notBefore, when)
Jean-Paul Calderoned7d81272013-02-19 13:16:03 -08001269
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001270 def get_notAfter(self):
1271 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001272 Get the timestamp at which the certificate stops being valid.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001273
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001274 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001275
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001276 YYYYMMDDhhmmssZ
1277 YYYYMMDDhhmmss+hhmm
1278 YYYYMMDDhhmmss-hhmm
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001279
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001280 :return: A timestamp string, or :py:const:`None` if there is none.
1281 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001282 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001283 return self._get_boundary_time(_lib.X509_get_notAfter)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001284
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001285 def set_notAfter(self, when):
1286 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001287 Set the timestamp at which the certificate stops being valid.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001288
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001289 The timestamp is formatted as an ASN.1 GENERALIZEDTIME::
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001290
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001291 YYYYMMDDhhmmssZ
1292 YYYYMMDDhhmmss+hhmm
1293 YYYYMMDDhhmmss-hhmm
1294
1295 :param when: A timestamp string.
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001296 :type when: :py:class:`bytes`
1297
Laurens Van Houtvena7904582014-06-19 12:33:04 +02001298 :return: :py:const:`None`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001299 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001300 return self._set_boundary_time(_lib.X509_get_notAfter, when)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001301
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001302 def _get_name(self, which):
1303 name = X509Name.__new__(X509Name)
1304 name._name = which(self._x509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001305 if name._name == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05001306 # TODO: This is untested.
1307 _raise_current_error()
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001308
1309 # The name is owned by the X509 structure. As long as the X509Name
1310 # Python object is alive, keep the X509 Python object alive.
1311 name._owner = self
1312
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001313 return name
1314
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001315 def _set_name(self, which, name):
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001316 if not isinstance(name, X509Name):
1317 raise TypeError("name must be an X509Name")
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001318 set_result = which(self._x509, name._name)
1319 if not set_result:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05001320 # TODO: This is untested.
1321 _raise_current_error()
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001322
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001323 def get_issuer(self):
1324 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001325 Return the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001326
Cory Benfielde6bcce82015-12-09 08:40:03 +00001327 This creates a new :class:`X509Name` that wraps the underlying issuer
1328 name field on the certificate. Modifying it will modify the underlying
1329 certificate, and will have the effect of modifying any other
1330 :class:`X509Name` that refers to this issuer.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001331
1332 :return: The issuer of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001333 :rtype: :class:`X509Name`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001334 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001335 return self._get_name(_lib.X509_get_issuer_name)
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001336
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001337 def set_issuer(self, issuer):
1338 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001339 Set the issuer of this certificate.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001340
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001341 :param issuer: The issuer.
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001342 :type issuer: :py:class:`X509Name`
1343
Laurens Van Houtvena7904582014-06-19 12:33:04 +02001344 :return: :py:const:`None`
Jean-Paul Calderonec2bd4e92013-02-20 08:12:36 -08001345 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001346 return self._set_name(_lib.X509_set_issuer_name, issuer)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001347
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001348 def get_subject(self):
1349 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001350 Return the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001351
Cory Benfielde6bcce82015-12-09 08:40:03 +00001352 This creates a new :class:`X509Name` that wraps the underlying subject
1353 name field on the certificate. Modifying it will modify the underlying
1354 certificate, and will have the effect of modifying any other
1355 :class:`X509Name` that refers to this subject.
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001356
1357 :return: The subject of this certificate.
Cory Benfielde6bcce82015-12-09 08:40:03 +00001358 :rtype: :class:`X509Name`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001359 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001360 return self._get_name(_lib.X509_get_subject_name)
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001361
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001362 def set_subject(self, subject):
1363 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001364 Set the subject of this certificate.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001365
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001366 :param subject: The subject.
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001367 :type subject: :py:class:`X509Name`
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001368
Laurens Van Houtvena7904582014-06-19 12:33:04 +02001369 :return: :py:const:`None`
Jean-Paul Calderonea9de1952013-02-19 16:58:42 -08001370 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001371 return self._set_name(_lib.X509_set_subject_name, subject)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001372
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001373 def get_extension_count(self):
1374 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001375 Get the number of extensions on this certificate.
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001376
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001377 :return: The number of extensions.
1378 :rtype: :py:class:`int`
1379
1380 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001381 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001382 return _lib.X509_get_ext_count(self._x509)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001383
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001384 def add_extensions(self, extensions):
1385 """
1386 Add extensions to the certificate.
1387
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001388 :param extensions: The extensions to add.
1389 :type extensions: An iterable of :py:class:`X509Extension` objects.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02001390 :return: :py:const:`None`
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001391 """
1392 for ext in extensions:
1393 if not isinstance(ext, X509Extension):
1394 raise ValueError("One of the elements is not an X509Extension")
1395
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001396 add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001397 if not add_result:
1398 _raise_current_error()
1399
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001400 def get_extension(self, index):
1401 """
1402 Get a specific extension of the certificate by index.
1403
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02001404 Extensions on a certificate are kept in order. The index
1405 parameter selects which extension will be returned.
1406
1407 :param int index: The index of the extension to retrieve.
1408 :return: The extension at the specified index.
1409 :rtype: :py:class:`X509Extension`
1410 :raises IndexError: If the extension index was out of bounds.
1411
1412 .. versionadded:: 0.12
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001413 """
1414 ext = X509Extension.__new__(X509Extension)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001415 ext._extension = _lib.X509_get_ext(self._x509, index)
1416 if ext._extension == _ffi.NULL:
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001417 raise IndexError("extension index out of bounds")
1418
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001419 extension = _lib.X509_EXTENSION_dup(ext._extension)
1420 ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
Jean-Paul Calderone83d22eb2013-02-20 12:19:43 -08001421 return ext
1422
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001423
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001424X509Type = X509
1425
1426
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001427class X509Store(object):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001428 """
1429 An X509 certificate store.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001430 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001431
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001432 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001433 store = _lib.X509_STORE_new()
1434 self._store = _ffi.gc(store, _lib.X509_STORE_free)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001435
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001436 def add_cert(self, cert):
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001437 """
1438 Adds the certificate :py:data:`cert` to this store.
1439
Laurens Van Houtven6e7dd432014-06-17 16:10:57 +02001440 This is the Python equivalent of OpenSSL's ``X509_STORE_add_cert``.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001441
1442 :param X509 cert: The certificate to add to this store.
1443 :raises TypeError: If the certificate is not an :py:class:`X509`.
1444 :raises Error: If OpenSSL was unhappy with your certificate.
Laurens Van Houtven5ee60b32015-04-23 10:51:16 -07001445 :return: :py:data:`None` if the certificate was added successfully.
Laurens Van Houtvenef5c83d2014-06-17 15:32:27 +02001446 """
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001447 if not isinstance(cert, X509):
1448 raise TypeError()
1449
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001450 result = _lib.X509_STORE_add_cert(self._store, cert._x509)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001451 if not result:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05001452 _raise_current_error()
Jean-Paul Calderonee6f32b82013-03-06 10:27:57 -08001453
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001454
1455X509StoreType = X509Store
1456
1457
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001458class X509StoreContextError(Exception):
1459 """
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001460 An exception raised when an error occurred while verifying a certificate
1461 using `OpenSSL.X509StoreContext.verify_certificate`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001462
Jean-Paul Calderonefeb17432015-03-15 15:49:45 -04001463 :ivar certificate: The certificate which caused verificate failure.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001464 :type certificate: :class:`X509`
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001465 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001466
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001467 def __init__(self, message, certificate):
1468 super(X509StoreContextError, self).__init__(message)
1469 self.certificate = certificate
1470
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001471
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001472class X509StoreContext(object):
1473 """
1474 An X.509 store context.
1475
Jean-Paul Calderone13a81682015-01-18 15:49:15 -05001476 An :py:class:`X509StoreContext` is used to define some of the criteria for
1477 certificate verification. The information encapsulated in this object
1478 includes, but is not limited to, a set of trusted certificates,
1479 verification parameters, and revoked certificates.
1480
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001481 .. note::
1482
1483 Currently, one can only set the trusted certificates on an
1484 :py:class:`X509StoreContext`. Future versions of pyOpenSSL will expose
1485 verification parameters and certificate revocation lists.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001486
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001487 :ivar _store_ctx: The underlying X509_STORE_CTX structure used by this
1488 instance. It is dynamically allocated and automatically garbage
1489 collected.
1490
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001491 :ivar _store: See the ``store`` ``__init__`` parameter.
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001492
Jean-Paul Calderone64b6b842015-03-15 16:08:02 -04001493 :ivar _cert: See the ``certificate`` ``__init__`` parameter.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001494
1495 :param X509Store store: The certificates which will be trusted for the
1496 purposes of any verifications.
1497
1498 :param X509 certificate: The certificate to be verified.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001499 """
1500
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001501 def __init__(self, store, certificate):
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001502 store_ctx = _lib.X509_STORE_CTX_new()
1503 self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
1504 self._store = store
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001505 self._cert = certificate
Stephen Holsapple46a09252015-02-12 14:45:43 -08001506 # Make the store context available for use after instantiating this
1507 # class by initializing it now. Per testing, subsequent calls to
1508 # :py:meth:`_init` have no adverse affect.
1509 self._init()
Jean-Paul Calderoneb7b7fb92015-01-18 15:37:10 -05001510
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001511 def _init(self):
1512 """
1513 Set up the store context for a subsequent verification operation.
1514 """
Alex Gaynor5945ea82015-09-05 14:59:06 -04001515 ret = _lib.X509_STORE_CTX_init(
1516 self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
1517 )
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001518 if ret <= 0:
1519 _raise_current_error()
1520
1521 def _cleanup(self):
1522 """
1523 Internally cleans up the store context.
1524
1525 The store context can then be reused with a new call to
Stephen Holsapple46a09252015-02-12 14:45:43 -08001526 :py:meth:`_init`.
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07001527 """
1528 _lib.X509_STORE_CTX_cleanup(self._store_ctx)
1529
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001530 def _exception_from_context(self):
1531 """
1532 Convert an OpenSSL native context error failure into a Python
1533 exception.
1534
Alex Gaynor5945ea82015-09-05 14:59:06 -04001535 When a call to native OpenSSL X509_verify_cert fails, additional
1536 information about the failure can be obtained from the store context.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001537 """
1538 errors = [
1539 _lib.X509_STORE_CTX_get_error(self._store_ctx),
1540 _lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1541 _native(_ffi.string(_lib.X509_verify_cert_error_string(
Alex Gaynor5945ea82015-09-05 14:59:06 -04001542 _lib.X509_STORE_CTX_get_error(self._store_ctx)))),
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001543 ]
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001544 # A context error should always be associated with a certificate, so we
1545 # expect this call to never return :class:`None`.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001546 _x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
Stephen Holsapple1f713eb2015-02-09 19:19:44 -08001547 _cert = _lib.X509_dup(_x509)
1548 pycert = X509.__new__(X509)
1549 pycert._x509 = _ffi.gc(_cert, _lib.X509_free)
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001550 return X509StoreContextError(errors, pycert)
1551
Stephen Holsapple46a09252015-02-12 14:45:43 -08001552 def set_store(self, store):
1553 """
1554 Set the context's trust store.
1555
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001556 .. versionadded:: 0.15
1557
Stephen Holsapple46a09252015-02-12 14:45:43 -08001558 :param X509Store store: The certificates which will be trusted for the
1559 purposes of any *future* verifications.
1560 """
1561 self._store = store
1562
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001563 def verify_certificate(self):
1564 """
1565 Verify a certificate in a context.
1566
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001567 .. versionadded:: 0.15
1568
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001569 :param store_ctx: The :py:class:`X509StoreContext` to verify.
Stephen Holsapple8ad4a192015-06-09 22:51:43 -07001570
Alex Gaynorca87ff62015-09-04 23:31:03 -04001571 :raises X509StoreContextError: If an error occurred when validating a
Alex Gaynor5945ea82015-09-05 14:59:06 -04001572 certificate in the context. Sets ``certificate`` attribute to
1573 indicate which certificate caused the error.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001574 """
Stephen Holsapple46a09252015-02-12 14:45:43 -08001575 # Always re-initialize the store context in case
1576 # :py:meth:`verify_certificate` is called multiple times.
Stephen Holsapple08ffaa62015-01-30 17:18:40 -08001577 self._init()
1578 ret = _lib.X509_verify_cert(self._store_ctx)
1579 self._cleanup()
1580 if ret <= 0:
1581 raise self._exception_from_context()
1582
1583
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001584def load_certificate(type, buffer):
1585 """
1586 Load a certificate from a buffer
1587
1588 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
1589
1590 :param buffer: The buffer the certificate is stored in
1591 :type buffer: :py:class:`bytes`
1592
1593 :return: The X509 object
1594 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05001595 if isinstance(buffer, _text_type):
1596 buffer = buffer.encode("ascii")
1597
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001598 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001599
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001600 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001601 x509 = _lib.PEM_read_bio_X509(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001602 elif type == FILETYPE_ASN1:
Alex Gaynor962ac212015-09-04 08:06:42 -04001603 x509 = _lib.d2i_X509_bio(bio, _ffi.NULL)
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08001604 else:
1605 raise ValueError(
1606 "type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001607
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001608 if x509 == _ffi.NULL:
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001609 _raise_current_error()
1610
1611 cert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001612 cert._x509 = _ffi.gc(x509, _lib.X509_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001613 return cert
1614
1615
1616def dump_certificate(type, cert):
1617 """
1618 Dump a certificate to a buffer
1619
Jean-Paul Calderonea12e7d22013-04-03 08:17:34 -04001620 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1621 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001622 :param cert: The certificate to dump
1623 :return: The buffer with the dumped certificate in
1624 """
Jean-Paul Calderone0c73aff2013-03-02 07:45:12 -08001625 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001626
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001627 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001628 result_code = _lib.PEM_write_bio_X509(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001629 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001630 result_code = _lib.i2d_X509_bio(bio, cert._x509)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001631 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001632 result_code = _lib.X509_print_ex(bio, cert._x509, 0, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001633 else:
1634 raise ValueError(
1635 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1636 "FILETYPE_TEXT")
1637
Alex Gaynorc7a9eb52015-09-05 16:57:49 -04001638 assert result_code == 1
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001639 return _bio_to_string(bio)
1640
1641
Cory Benfield6492f7c2015-10-27 16:57:58 +09001642def dump_publickey(type, pkey):
1643 """
Cory Benfield11c10192015-10-27 17:23:03 +09001644 Dump a public key to a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09001645
Cory Benfield9c590b92015-10-28 14:55:05 +09001646 :param type: The file type (one of :data:`FILETYPE_PEM` or
Cory Benfielde813cec2015-10-28 08:57:08 +09001647 :data:`FILETYPE_ASN1`).
Cory Benfield2b6bb802015-10-28 22:19:31 +09001648 :param PKey pkey: The public key to dump
Cory Benfield6492f7c2015-10-27 16:57:58 +09001649 :return: The buffer with the dumped key in it.
Cory Benfield11c10192015-10-27 17:23:03 +09001650 :rtype: bytes
Cory Benfield6492f7c2015-10-27 16:57:58 +09001651 """
1652 bio = _new_mem_buf()
1653 if type == FILETYPE_PEM:
1654 write_bio = _lib.PEM_write_bio_PUBKEY
1655 elif type == FILETYPE_ASN1:
1656 write_bio = _lib.i2d_PUBKEY_bio
1657 else:
1658 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
1659
1660 result_code = write_bio(bio, pkey._pkey)
Cory Benfield1e9c7ab2015-10-28 08:58:31 +09001661 if result_code != 1: # pragma: no cover
Cory Benfield6492f7c2015-10-27 16:57:58 +09001662 _raise_current_error()
1663
1664 return _bio_to_string(bio)
1665
1666
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001667def dump_privatekey(type, pkey, cipher=None, passphrase=None):
1668 """
1669 Dump a private key to a buffer
1670
Jean-Paul Calderonee66fde22013-04-03 08:35:08 -04001671 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or
1672 FILETYPE_TEXT)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001673 :param pkey: The PKey to dump
1674 :param cipher: (optional) if encrypted PEM format, the cipher to
1675 use
1676 :param passphrase: (optional) if encrypted PEM format, this can be either
1677 the passphrase to use, or a callback for providing the
1678 passphrase.
1679 :return: The buffer with the dumped key in
Maximilian Hils0de43752015-09-18 15:26:54 +02001680 :rtype: :py:data:`bytes`
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001681 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08001682 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001683
1684 if cipher is not None:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001685 if passphrase is None:
1686 raise TypeError(
1687 "if a value is given for cipher "
1688 "one must also be given for passphrase")
1689 cipher_obj = _lib.EVP_get_cipherbyname(_byte_string(cipher))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001690 if cipher_obj == _ffi.NULL:
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08001691 raise ValueError("Invalid cipher name")
1692 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001693 cipher_obj = _ffi.NULL
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001694
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001695 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001696 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001697 result_code = _lib.PEM_write_bio_PrivateKey(
1698 bio, pkey._pkey, cipher_obj, _ffi.NULL, 0,
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08001699 helper.callback, helper.callback_args)
1700 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001701 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001702 result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001703 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001704 rsa = _lib.EVP_PKEY_get1_RSA(pkey._pkey)
1705 result_code = _lib.RSA_print(bio, rsa, 0)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08001706 # TODO RSA_free(rsa)?
1707 else:
1708 raise ValueError(
1709 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
1710 "FILETYPE_TEXT")
1711
1712 if result_code == 0:
1713 _raise_current_error()
1714
1715 return _bio_to_string(bio)
1716
1717
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001718class Revoked(object):
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001719 """
1720 A certificate revocation.
1721 """
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001722 # http://www.openssl.org/docs/apps/x509v3_config.html#CRL_distribution_points_
1723 # which differs from crl_reasons of crypto/x509v3/v3_enum.c that matches
1724 # OCSP_crl_reason_str. We use the latter, just like the command line
1725 # program.
1726 _crl_reasons = [
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001727 b"unspecified",
1728 b"keyCompromise",
1729 b"CACompromise",
1730 b"affiliationChanged",
1731 b"superseded",
1732 b"cessationOfOperation",
1733 b"certificateHold",
1734 # b"removeFromCRL",
Alex Gaynorca87ff62015-09-04 23:31:03 -04001735 ]
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001736
1737 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001738 revoked = _lib.X509_REVOKED_new()
1739 self._revoked = _ffi.gc(revoked, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001740
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001741 def set_serial(self, hex_str):
1742 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001743 Set the serial number.
1744
1745 The serial number is formatted as a hexadecimal number encoded in
1746 ASCII.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001747
1748 :param hex_str: The new serial number.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001749 :type hex_str: :py:class:`bytes`
1750
Laurens Van Houtvena7904582014-06-19 12:33:04 +02001751 :return: :py:const:`None`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001752 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001753 bignum_serial = _ffi.gc(_lib.BN_new(), _lib.BN_free)
1754 bignum_ptr = _ffi.new("BIGNUM**")
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001755 bignum_ptr[0] = bignum_serial
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001756 bn_result = _lib.BN_hex2bn(bignum_ptr, hex_str)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001757 if not bn_result:
1758 raise ValueError("bad hex string")
1759
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001760 asn1_serial = _ffi.gc(
1761 _lib.BN_to_ASN1_INTEGER(bignum_serial, _ffi.NULL),
1762 _lib.ASN1_INTEGER_free)
1763 _lib.X509_REVOKED_set_serialNumber(self._revoked, asn1_serial)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001764
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001765 def get_serial(self):
1766 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001767 Get the serial number.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001768
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001769 The serial number is formatted as a hexadecimal number encoded in
1770 ASCII.
1771
1772 :return: The serial number.
1773 :rtype: :py:class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001774 """
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001775 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001776
Alex Gaynor67903a62016-06-02 10:37:13 -07001777 asn1_int = _lib.X509_REVOKED_get0_serialNumber(self._revoked)
1778 _openssl_assert(asn1_int != _ffi.NULL)
1779 result = _lib.i2a_ASN1_INTEGER(bio, asn1_int)
1780 _openssl_assert(result >= 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001781 return _bio_to_string(bio)
1782
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001783 def _delete_reason(self):
Alex Gaynor67903a62016-06-02 10:37:13 -07001784 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1785 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001786 obj = _lib.X509_EXTENSION_get_object(ext)
1787 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001788 _lib.X509_EXTENSION_free(ext)
Alex Gaynor67903a62016-06-02 10:37:13 -07001789 _lib.X509_REVOKED_delete_ext(self._revoked, i)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001790 break
1791
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001792 def set_reason(self, reason):
1793 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001794 Set the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001795
Laurens Van Houtvena7904582014-06-19 12:33:04 +02001796 If :py:data:`reason` is :py:const:`None`, delete the reason instead.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001797
1798 :param reason: The reason string.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001799 :type reason: :py:class:`bytes` or :py:class:`NoneType`
1800
Laurens Van Houtvena7904582014-06-19 12:33:04 +02001801 :return: :py:const:`None`
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001802
1803 .. seealso::
1804
1805 :py:meth:`all_reasons`, which gives you a list of all supported
1806 reasons which you might pass to this method.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001807 """
1808 if reason is None:
1809 self._delete_reason()
1810 elif not isinstance(reason, bytes):
1811 raise TypeError("reason must be None or a byte string")
1812 else:
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001813 reason = reason.lower().replace(b' ', b'')
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001814 reason_code = [r.lower() for r in self._crl_reasons].index(reason)
1815
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001816 new_reason_ext = _lib.ASN1_ENUMERATED_new()
1817 if new_reason_ext == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05001818 # TODO: This is untested.
1819 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001820 new_reason_ext = _ffi.gc(new_reason_ext, _lib.ASN1_ENUMERATED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001821
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001822 set_result = _lib.ASN1_ENUMERATED_set(new_reason_ext, reason_code)
1823 if set_result == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05001824 # TODO: This is untested.
1825 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001826
1827 self._delete_reason()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001828 add_result = _lib.X509_REVOKED_add1_ext_i2d(
1829 self._revoked, _lib.NID_crl_reason, new_reason_ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001830
1831 if not add_result:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05001832 # TODO: This is untested.
1833 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001834
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001835 def get_reason(self):
1836 """
Alex Gaynor80262fb2016-04-22 07:53:42 -04001837 Get the reason of this revocation.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001838
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001839 :return: The reason, or :py:const:`None` if there is none.
1840 :rtype: :py:class:`bytes` or :py:class:`NoneType`
1841
1842 .. seealso::
1843
1844 :py:meth:`all_reasons`, which gives you a list of all supported
1845 reasons this method might return.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001846 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001847 for i in range(_lib.X509_REVOKED_get_ext_count(self._revoked)):
1848 ext = _lib.X509_REVOKED_get_ext(self._revoked, i)
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001849 obj = _lib.X509_EXTENSION_get_object(ext)
1850 if _lib.OBJ_obj2nid(obj) == _lib.NID_crl_reason:
Jean-Paul Calderonefd371362013-03-01 20:53:58 -08001851 bio = _new_mem_buf()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001852
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001853 print_result = _lib.X509V3_EXT_print(bio, ext, 0, 0)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001854 if not print_result:
Alex Gaynor5945ea82015-09-05 14:59:06 -04001855 print_result = _lib.M_ASN1_OCTET_STRING_print(
Paul Kehrere8f91cc2016-03-09 21:26:29 -04001856 bio, _lib.X509_EXTENSION_get_data(ext)
Alex Gaynor5945ea82015-09-05 14:59:06 -04001857 )
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001858 if print_result == 0:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05001859 # TODO: This is untested.
1860 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001861
1862 return _bio_to_string(bio)
1863
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001864 def all_reasons(self):
1865 """
1866 Return a list of all the supported reason strings.
1867
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001868 This list is a copy; modifying it does not change the supported reason
1869 strings.
1870
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001871 :return: A list of reason strings.
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001872 :rtype: :py:class:`list` of :py:class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001873 """
1874 return self._crl_reasons[:]
1875
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001876 def set_rev_date(self, when):
1877 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001878 Set the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001879
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001880 :param when: The timestamp of the revocation, as ASN.1 GENERALIZEDTIME.
1881 :type when: :py:class:`bytes`
Laurens Van Houtvena7904582014-06-19 12:33:04 +02001882 :return: :py:const:`None`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001883 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001884 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1885 return _set_asn1_time(dt, when)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001886
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001887 def get_rev_date(self):
1888 """
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001889 Get the revocation timestamp.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001890
Laurens Van Houtvend92f55c2014-06-19 17:08:41 +02001891 :return: The timestamp of the revocation, as ASN.1 GENERALIZEDTIME.
1892 :rtype: :py:class:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001893 """
Alex Gaynor67903a62016-06-02 10:37:13 -07001894 dt = _lib.X509_REVOKED_get0_revocationDate(self._revoked)
1895 return _get_asn1_time(dt)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001896
1897
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001898class CRL(object):
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001899 """
1900 A certificate revocation list.
1901 """
Alex Gaynora738ed52015-09-05 11:17:10 -04001902
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001903 def __init__(self):
1904 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001905 Create a new empty certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001906 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001907 crl = _lib.X509_CRL_new()
1908 self._crl = _ffi.gc(crl, _lib.X509_CRL_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001909
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001910 def get_revoked(self):
1911 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001912 Return the revocations in this certificate revocation list.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001913
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001914 These revocations will be provided by value, not by reference.
1915 That means it's okay to mutate them: it won't affect this CRL.
1916
1917 :return: The revocations in this CRL.
1918 :rtype: :py:class:`tuple` of :py:class:`Revocation`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001919 """
1920 results = []
Alex Gaynor67903a62016-06-02 10:37:13 -07001921 revoked_stack = _lib.X509_CRL_get_REVOKED(self._crl)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001922 for i in range(_lib.sk_X509_REVOKED_num(revoked_stack)):
1923 revoked = _lib.sk_X509_REVOKED_value(revoked_stack, i)
Paul Kehrer2fe23b02016-03-09 22:02:15 -04001924 revoked_copy = _lib.Cryptography_X509_REVOKED_dup(revoked)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001925 pyrev = Revoked.__new__(Revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001926 pyrev._revoked = _ffi.gc(revoked_copy, _lib.X509_REVOKED_free)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001927 results.append(pyrev)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08001928 if results:
1929 return tuple(results)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001930
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001931 def add_revoked(self, revoked):
1932 """
1933 Add a revoked (by value not reference) to the CRL structure
1934
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001935 This revocation will be added by value, not by reference. That
1936 means it's okay to mutate it after adding: it won't affect
1937 this CRL.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001938
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001939 :param revoked: The new revocation.
1940 :type revoked: :class:`Revoked`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001941
Laurens Van Houtvena7904582014-06-19 12:33:04 +02001942 :return: :py:const:`None`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001943 """
Paul Kehrer8dddb1a2016-03-09 21:48:04 -04001944 copy = _lib.Cryptography_X509_REVOKED_dup(revoked._revoked)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001945 if copy == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05001946 # TODO: This is untested.
1947 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001948
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001949 add_result = _lib.X509_CRL_add0_revoked(self._crl, copy)
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05001950 if add_result == 0:
1951 # TODO: This is untested.
1952 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001953
Jean-Paul Calderone60432792015-04-13 12:26:07 -04001954 def export(self, cert, key, type=FILETYPE_PEM, days=100,
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04001955 digest=_UNSPECIFIED):
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001956 """
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001957 Export a CRL as a string.
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001958
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001959 :param cert: The certificate used to sign the CRL.
1960 :type cert: :py:class:`X509`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001961
Laurens Van Houtvencb32e852014-06-19 17:36:28 +02001962 :param key: The key used to sign the CRL.
1963 :type key: :py:class:`PKey`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001964
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04001965 :param type: The export format, either :py:data:`FILETYPE_PEM`,
1966 :py:data:`FILETYPE_ASN1`, or :py:data:`FILETYPE_TEXT`.
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04001967
Jean-Paul Calderonedf514012015-04-13 21:45:18 -04001968 :param int days: The number of days until the next update of this CRL.
Bulat Gaifullin5f9eea42014-09-23 19:35:15 +04001969
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04001970 :param bytes digest: The name of the message digest to use (eg
1971 ``b"sha1"``).
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001972
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04001973 :return: :py:data:`bytes`
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001974 """
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08001975 if not isinstance(cert, X509):
1976 raise TypeError("cert must be an X509 instance")
1977 if not isinstance(key, PKey):
1978 raise TypeError("key must be a PKey instance")
1979 if not isinstance(type, int):
1980 raise TypeError("type must be an integer")
Jean-Paul Calderone57122982013-02-21 08:47:05 -08001981
Jean-Paul Calderone00f84eb2015-04-13 12:47:21 -04001982 if digest is _UNSPECIFIED:
Jean-Paul Calderone60432792015-04-13 12:26:07 -04001983 _warn(
1984 "The default message digest (md5) is deprecated. "
1985 "Pass the name of a message digest explicitly.",
1986 category=DeprecationWarning,
1987 stacklevel=2,
1988 )
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04001989 digest = b"md5"
Jean-Paul Calderone60432792015-04-13 12:26:07 -04001990
Jean-Paul Calderonecce22d02015-04-13 13:56:09 -04001991 digest_obj = _lib.EVP_get_digestbyname(digest)
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04001992 if digest_obj == _ffi.NULL:
1993 raise ValueError("No such digest method")
1994
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05001995 bio = _lib.BIO_new(_lib.BIO_s_mem())
1996 if bio == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05001997 # TODO: This is untested.
1998 _raise_current_error()
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08001999
Alex Gaynora738ed52015-09-05 11:17:10 -04002000 # A scratch time object to give different values to different CRL
2001 # fields
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002002 sometime = _lib.ASN1_TIME_new()
2003 if sometime == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05002004 # TODO: This is untested.
2005 _raise_current_error()
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002006
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002007 _lib.X509_gmtime_adj(sometime, 0)
2008 _lib.X509_CRL_set_lastUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002009
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002010 _lib.X509_gmtime_adj(sometime, days * 24 * 60 * 60)
2011 _lib.X509_CRL_set_nextUpdate(self._crl, sometime)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002012
Alex Gaynor5945ea82015-09-05 14:59:06 -04002013 _lib.X509_CRL_set_issuer_name(
2014 self._crl, _lib.X509_get_subject_name(cert._x509)
2015 )
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002016
Bulat Gaifullin2923dc02014-09-21 22:36:48 +04002017 sign_result = _lib.X509_CRL_sign(self._crl, key._pkey, digest_obj)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002018 if not sign_result:
2019 _raise_current_error()
2020
Dominic Chenf05b2122015-10-13 16:32:35 +00002021 return dump_crl(type, self)
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002022
Jean-Paul Calderone85b74eb2013-02-21 09:15:01 -08002023
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002024CRLType = CRL
2025
2026
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002027class PKCS7(object):
2028 def type_is_signed(self):
2029 """
2030 Check if this NID_pkcs7_signed object
2031
2032 :return: True if the PKCS7 is of type signed
2033 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002034 if _lib.PKCS7_type_is_signed(self._pkcs7):
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002035 return True
2036 return False
2037
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002038 def type_is_enveloped(self):
2039 """
2040 Check if this NID_pkcs7_enveloped object
2041
2042 :returns: True if the PKCS7 is of type enveloped
2043 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002044 if _lib.PKCS7_type_is_enveloped(self._pkcs7):
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002045 return True
2046 return False
2047
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002048 def type_is_signedAndEnveloped(self):
2049 """
2050 Check if this NID_pkcs7_signedAndEnveloped object
2051
2052 :returns: True if the PKCS7 is of type signedAndEnveloped
2053 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002054 if _lib.PKCS7_type_is_signedAndEnveloped(self._pkcs7):
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002055 return True
2056 return False
2057
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002058 def type_is_data(self):
2059 """
2060 Check if this NID_pkcs7_data object
2061
2062 :return: True if the PKCS7 is of type data
2063 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002064 if _lib.PKCS7_type_is_data(self._pkcs7):
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002065 return True
2066 return False
2067
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002068 def get_type_name(self):
2069 """
2070 Returns the type name of the PKCS7 structure
2071
2072 :return: A string with the typename
2073 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002074 nid = _lib.OBJ_obj2nid(self._pkcs7.type)
2075 string_type = _lib.OBJ_nid2sn(nid)
2076 return _ffi.string(string_type)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002077
2078PKCS7Type = PKCS7
2079
2080
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002081class PKCS12(object):
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002082 """
2083 A PKCS #12 archive.
2084 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002085
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002086 def __init__(self):
2087 self._pkey = None
2088 self._cert = None
2089 self._cacerts = None
2090 self._friendlyname = None
2091
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002092 def get_certificate(self):
2093 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002094 Get the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002095
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002096 :return: The certificate, or :py:const:`None` if there is none.
2097 :rtype: :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002098 """
2099 return self._cert
2100
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002101 def set_certificate(self, cert):
2102 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002103 Set the certificate in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002104
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002105 :param cert: The new certificate, or :py:const:`None` to unset it.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002106 :type cert: :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002107
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002108 :return: :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002109 """
2110 if not isinstance(cert, X509):
2111 raise TypeError("cert must be an X509 instance")
2112 self._cert = cert
2113
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002114 def get_privatekey(self):
2115 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002116 Get the private key in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002117
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002118 :return: The private key, or :py:const:`None` if there is none.
2119 :rtype: :py:class:`PKey`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002120 """
2121 return self._pkey
2122
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002123 def set_privatekey(self, pkey):
2124 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002125 Set the certificate portion of the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002126
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002127 :param pkey: The new private key, or :py:const:`None` to unset it.
2128 :type pkey: :py:class:`PKey` or :py:const:`None`
2129
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002130 :return: :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002131 """
2132 if not isinstance(pkey, PKey):
2133 raise TypeError("pkey must be a PKey instance")
2134 self._pkey = pkey
2135
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002136 def get_ca_certificates(self):
2137 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002138 Get the CA certificates in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002139
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002140 :return: A tuple with the CA certificates in the chain, or
2141 :py:const:`None` if there are none.
2142 :rtype: :py:class:`tuple` of :py:class:`X509` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002143 """
2144 if self._cacerts is not None:
2145 return tuple(self._cacerts)
2146
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002147 def set_ca_certificates(self, cacerts):
2148 """
Alex Gaynor3b0ee972014-11-15 09:17:33 -08002149 Replace or set the CA certificates within the PKCS12 object.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002150
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002151 :param cacerts: The new CA certificates, or :py:const:`None` to unset
2152 them.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002153 :type cacerts: An iterable of :py:class:`X509` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002154
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002155 :return: :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002156 """
2157 if cacerts is None:
2158 self._cacerts = None
2159 else:
2160 cacerts = list(cacerts)
2161 for cert in cacerts:
2162 if not isinstance(cert, X509):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002163 raise TypeError(
2164 "iterable must only contain X509 instances"
2165 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002166 self._cacerts = cacerts
2167
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002168 def set_friendlyname(self, name):
2169 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002170 Set the friendly name in the PKCS #12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002171
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002172 :param name: The new friendly name, or :py:const:`None` to unset.
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002173 :type name: :py:class:`bytes` or :py:const:`None`
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002174
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002175 :return: :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002176 """
2177 if name is None:
2178 self._friendlyname = None
2179 elif not isinstance(name, bytes):
Alex Gaynor5945ea82015-09-05 14:59:06 -04002180 raise TypeError(
2181 "name must be a byte string or None (not %r)" % (name,)
2182 )
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002183 self._friendlyname = name
2184
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002185 def get_friendlyname(self):
2186 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002187 Get the friendly name in the PKCS# 12 structure.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002188
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002189 :returns: The friendly name, or :py:const:`None` if there is none.
2190 :rtype: :py:class:`bytes` or :py:const:`None`
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002191 """
2192 return self._friendlyname
2193
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002194 def export(self, passphrase=None, iter=2048, maciter=1):
2195 """
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002196 Dump a PKCS12 object as a string.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002197
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002198 For more information, see the :c:func:`PKCS12_create` man page.
2199
2200 :param passphrase: The passphrase used to encrypt the structure. Unlike
2201 some other passphrase arguments, this *must* be a string, not a
2202 callback.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002203 :type passphrase: :py:data:`bytes`
2204
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002205 :param iter: Number of times to repeat the encryption step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002206 :type iter: :py:data:`int`
2207
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002208 :param maciter: Number of times to repeat the MAC step.
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002209 :type maciter: :py:data:`int`
2210
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002211 :return: The string representation of the PKCS #12 structure.
2212 :rtype:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002213 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002214 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002215
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002216 if self._cacerts is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002217 cacerts = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002218 else:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002219 cacerts = _lib.sk_X509_new_null()
2220 cacerts = _ffi.gc(cacerts, _lib.sk_X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002221 for cert in self._cacerts:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002222 _lib.sk_X509_push(cacerts, cert._x509)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002223
2224 if passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002225 passphrase = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002226
2227 friendlyname = self._friendlyname
2228 if friendlyname is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002229 friendlyname = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002230
2231 if self._pkey is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002232 pkey = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002233 else:
2234 pkey = self._pkey._pkey
2235
2236 if self._cert is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002237 cert = _ffi.NULL
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002238 else:
2239 cert = self._cert._x509
2240
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002241 pkcs12 = _lib.PKCS12_create(
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002242 passphrase, friendlyname, pkey, cert, cacerts,
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002243 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
2244 _lib.NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002245 iter, maciter, 0)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002246 if pkcs12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002247 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002248 pkcs12 = _ffi.gc(pkcs12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002249
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002250 bio = _new_mem_buf()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002251 _lib.i2d_PKCS12_bio(bio, pkcs12)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002252 return _bio_to_string(bio)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002253
Laurens Van Houtvenbb503a32014-06-19 12:28:08 +02002254
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002255PKCS12Type = PKCS12
2256
2257
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002258class NetscapeSPKI(object):
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002259 """
2260 A Netscape SPKI object.
2261 """
Alex Gaynora738ed52015-09-05 11:17:10 -04002262
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002263 def __init__(self):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002264 spki = _lib.NETSCAPE_SPKI_new()
2265 self._spki = _ffi.gc(spki, _lib.NETSCAPE_SPKI_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002266
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002267 def sign(self, pkey, digest):
2268 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002269 Sign the certificate request with this key and digest type.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002270
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002271 :param pkey: The private key to sign with.
2272 :type pkey: :py:class:`PKey`
2273
2274 :param digest: The message digest to use.
2275 :type digest: :py:class:`bytes`
2276
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002277 :return: :py:const:`None`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002278 """
2279 if pkey._only_public:
2280 raise ValueError("Key has only public part")
2281
2282 if not pkey._initialized:
2283 raise ValueError("Key is uninitialized")
2284
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002285 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002286 if digest_obj == _ffi.NULL:
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002287 raise ValueError("No such digest method")
2288
Alex Gaynor5945ea82015-09-05 14:59:06 -04002289 sign_result = _lib.NETSCAPE_SPKI_sign(
2290 self._spki, pkey._pkey, digest_obj
2291 )
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002292 if not sign_result:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05002293 # TODO: This is untested.
2294 _raise_current_error()
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002295
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002296 def verify(self, key):
2297 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002298 Verifies a signature on a certificate request.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002299
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002300 :param key: The public key that signature is supposedly from.
2301 :type pkey: :py:class:`PKey`
2302
2303 :return: :py:const:`True` if the signature is correct.
2304 :rtype: :py:class:`bool`
2305
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002306 :raises Error: If the signature is invalid, or there was a problem
2307 verifying the signature.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002308 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002309 answer = _lib.NETSCAPE_SPKI_verify(self._spki, key._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002310 if answer <= 0:
2311 _raise_current_error()
2312 return True
2313
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002314 def b64_encode(self):
2315 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002316 Generate a base64 encoded representation of this SPKI object.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002317
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002318 :return: The base64 encoded string.
2319 :rtype: :py:class:`bytes`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002320 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002321 encoded = _lib.NETSCAPE_SPKI_b64_encode(self._spki)
2322 result = _ffi.string(encoded)
Paul Kehrer0dcacf72016-03-17 19:25:39 -04002323 _lib.OPENSSL_free(encoded)
Jean-Paul Calderone2c2e21d2013-03-02 16:50:35 -08002324 return result
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002325
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002326 def get_pubkey(self):
2327 """
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002328 Get the public key of this certificate.
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002329
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002330 :return: The public key.
2331 :rtype: :py:class:`PKey`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002332 """
2333 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002334 pkey._pkey = _lib.NETSCAPE_SPKI_get_pubkey(self._spki)
2335 if pkey._pkey == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05002336 # TODO: This is untested.
2337 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002338 pkey._pkey = _ffi.gc(pkey._pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002339 pkey._only_public = True
2340 return pkey
2341
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002342 def set_pubkey(self, pkey):
2343 """
2344 Set the public key of the certificate
2345
2346 :param pkey: The public key
Laurens Van Houtvena7904582014-06-19 12:33:04 +02002347 :return: :py:const:`None`
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002348 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002349 set_result = _lib.NETSCAPE_SPKI_set_pubkey(self._spki, pkey._pkey)
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002350 if not set_result:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05002351 # TODO: This is untested.
2352 _raise_current_error()
Laurens Van Houtven59152b52014-06-19 16:42:30 +02002353
2354
Jean-Paul Calderone3b89f472013-02-21 09:32:25 -08002355NetscapeSPKIType = NetscapeSPKI
2356
2357
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002358class _PassphraseHelper(object):
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002359 def __init__(self, type, passphrase, more_args=False, truncate=False):
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002360 if type != FILETYPE_PEM and passphrase is not None:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002361 raise ValueError(
2362 "only FILETYPE_PEM key format supports encryption"
2363 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002364 self._passphrase = passphrase
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002365 self._more_args = more_args
2366 self._truncate = truncate
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002367 self._problems = []
2368
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002369 @property
2370 def callback(self):
2371 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002372 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002373 elif isinstance(self._passphrase, bytes):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002374 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002375 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002376 return _ffi.callback("pem_password_cb", self._read_passphrase)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002377 else:
2378 raise TypeError("Last argument must be string or callable")
2379
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002380 @property
2381 def callback_args(self):
2382 if self._passphrase is None:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002383 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002384 elif isinstance(self._passphrase, bytes):
2385 return self._passphrase
2386 elif callable(self._passphrase):
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002387 return _ffi.NULL
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002388 else:
2389 raise TypeError("Last argument must be string or callable")
2390
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002391 def raise_if_problem(self, exceptionType=Error):
2392 try:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05002393 _exception_from_error_queue(exceptionType)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002394 except exceptionType as e:
Jean-Paul Calderone9b4115f2014-01-10 14:06:04 -05002395 from_queue = e
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002396 if self._problems:
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002397 raise self._problems[0]
Jean-Paul Calderone9b4115f2014-01-10 14:06:04 -05002398 return from_queue
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002399
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002400 def _read_passphrase(self, buf, size, rwflag, userdata):
2401 try:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002402 if self._more_args:
2403 result = self._passphrase(size, rwflag, userdata)
2404 else:
2405 result = self._passphrase(rwflag)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002406 if not isinstance(result, bytes):
2407 raise ValueError("String expected")
2408 if len(result) > size:
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08002409 if self._truncate:
2410 result = result[:size]
2411 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002412 raise ValueError(
2413 "passphrase returned by callback is too long"
2414 )
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002415 for i in range(len(result)):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002416 buf[i] = result[i:i + 1]
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002417 return len(result)
2418 except Exception as e:
2419 self._problems.append(e)
2420 return 0
2421
2422
Cory Benfield6492f7c2015-10-27 16:57:58 +09002423def load_publickey(type, buffer):
2424 """
Cory Benfield11c10192015-10-27 17:23:03 +09002425 Load a public key from a buffer.
Cory Benfield6492f7c2015-10-27 16:57:58 +09002426
Cory Benfield9c590b92015-10-28 14:55:05 +09002427 :param type: The file type (one of :data:`FILETYPE_PEM`,
Cory Benfielde813cec2015-10-28 08:57:08 +09002428 :data:`FILETYPE_ASN1`).
Cory Benfieldc9c30a22015-10-28 17:39:20 +09002429 :param buffer: The buffer the key is stored in.
2430 :type buffer: A Python string object, either unicode or bytestring.
2431 :return: The PKey object.
2432 :rtype: :class:`PKey`
Cory Benfield6492f7c2015-10-27 16:57:58 +09002433 """
2434 if isinstance(buffer, _text_type):
2435 buffer = buffer.encode("ascii")
2436
2437 bio = _new_mem_buf(buffer)
2438
2439 if type == FILETYPE_PEM:
2440 evp_pkey = _lib.PEM_read_bio_PUBKEY(
2441 bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
2442 elif type == FILETYPE_ASN1:
2443 evp_pkey = _lib.d2i_PUBKEY_bio(bio, _ffi.NULL)
2444 else:
2445 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2446
2447 if evp_pkey == _ffi.NULL:
2448 _raise_current_error()
2449
2450 pkey = PKey.__new__(PKey)
2451 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
2452 return pkey
2453
2454
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002455def load_privatekey(type, buffer, passphrase=None):
2456 """
2457 Load a private key from a buffer
2458
2459 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2460 :param buffer: The buffer the key is stored in
2461 :param passphrase: (optional) if encrypted PEM format, this can be
2462 either the passphrase to use, or a callback for
2463 providing the passphrase.
2464
2465 :return: The PKey object
2466 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002467 if isinstance(buffer, _text_type):
2468 buffer = buffer.encode("ascii")
2469
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002470 bio = _new_mem_buf(buffer)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002471
Jean-Paul Calderone23478b32013-02-20 13:31:38 -08002472 helper = _PassphraseHelper(type, passphrase)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002473 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002474 evp_pkey = _lib.PEM_read_bio_PrivateKey(
2475 bio, _ffi.NULL, helper.callback, helper.callback_args)
Jean-Paul Calderonee41f05c2013-02-20 13:28:16 -08002476 helper.raise_if_problem()
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002477 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002478 evp_pkey = _lib.d2i_PrivateKey_bio(bio, _ffi.NULL)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002479 else:
2480 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2481
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002482 if evp_pkey == _ffi.NULL:
Jean-Paul Calderone31393aa2013-02-20 13:22:21 -08002483 _raise_current_error()
2484
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002485 pkey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002486 pkey._pkey = _ffi.gc(evp_pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002487 return pkey
2488
2489
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002490def dump_certificate_request(type, req):
2491 """
2492 Dump a certificate request to a buffer
2493
2494 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2495 :param req: The certificate request to dump
2496 :return: The buffer with the dumped certificate request in
2497 """
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002498 bio = _new_mem_buf()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002499
2500 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002501 result_code = _lib.PEM_write_bio_X509_REQ(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002502 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002503 result_code = _lib.i2d_X509_REQ_bio(bio, req._req)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002504 elif type == FILETYPE_TEXT:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002505 result_code = _lib.X509_REQ_print_ex(bio, req._req, 0, 0)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002506 else:
Alex Gaynor5945ea82015-09-05 14:59:06 -04002507 raise ValueError(
2508 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2509 "FILETYPE_TEXT"
2510 )
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002511
2512 if result_code == 0:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05002513 # TODO: This is untested.
2514 _raise_current_error()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002515
2516 return _bio_to_string(bio)
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002517
2518
Jean-Paul Calderoneabfbab62013-02-09 21:25:02 -08002519def load_certificate_request(type, buffer):
2520 """
2521 Load a certificate request from a buffer
2522
2523 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2524 :param buffer: The buffer the certificate request is stored in
2525 :return: The X509Req object
2526 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002527 if isinstance(buffer, _text_type):
2528 buffer = buffer.encode("ascii")
2529
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002530 bio = _new_mem_buf(buffer)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002531
2532 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002533 req = _lib.PEM_read_bio_X509_REQ(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002534 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002535 req = _lib.d2i_X509_REQ_bio(bio, _ffi.NULL)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002536 else:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002537 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002538
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002539 if req == _ffi.NULL:
Jean-Paul Calderone4a68b402013-12-29 16:54:58 -05002540 # TODO: This is untested.
2541 _raise_current_error()
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002542
2543 x509req = X509Req.__new__(X509Req)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002544 x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
Jean-Paul Calderone066f0572013-02-20 13:43:44 -08002545 return x509req
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002546
2547
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002548def sign(pkey, data, digest):
2549 """
2550 Sign data with a digest
2551
2552 :param pkey: Pkey to sign with
2553 :param data: data to be signed
2554 :param digest: message digest to use
2555 :return: signature
2556 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002557 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002558
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002559 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002560 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002561 raise ValueError("No such digest method")
2562
Alex Gaynor67903a62016-06-02 10:37:13 -07002563 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002564 md_ctx = _ffi.gc(md_ctx, _lib.EVP_MD_CTX_cleanup)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002565
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002566 _lib.EVP_SignInit(md_ctx, digest_obj)
2567 _lib.EVP_SignUpdate(md_ctx, data, len(data))
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002568
Colleen Murphye09399b2016-03-01 17:40:49 -08002569 pkey_length = (PKey.bits(pkey) + 7) // 8
2570 signature_buffer = _ffi.new("unsigned char[]", pkey_length)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002571 signature_length = _ffi.new("unsigned int*")
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002572 final_result = _lib.EVP_SignFinal(
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002573 md_ctx, signature_buffer, signature_length, pkey._pkey)
2574
2575 if final_result != 1:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05002576 # TODO: This is untested.
2577 _raise_current_error()
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002578
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002579 return _ffi.buffer(signature_buffer, signature_length[0])[:]
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002580
2581
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002582def verify(cert, signature, data, digest):
2583 """
Laurens Van Houtvenc3baa7b2014-06-18 22:06:56 +02002584 Verify a signature.
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002585
2586 :param cert: signing certificate (X509 object)
2587 :param signature: signature returned by sign function
2588 :param data: data to be verified
2589 :param digest: message digest to use
Alex Gaynor5945ea82015-09-05 14:59:06 -04002590 :return: :py:const:`None` if the signature is correct, raise exception
2591 otherwise
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002592 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002593 data = _text_to_bytes_and_warn("data", data)
Abraham Martine82326c2015-02-04 10:18:10 +00002594
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002595 digest_obj = _lib.EVP_get_digestbyname(_byte_string(digest))
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002596 if digest_obj == _ffi.NULL:
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002597 raise ValueError("No such digest method")
2598
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002599 pkey = _lib.X509_get_pubkey(cert._x509)
2600 if pkey == _ffi.NULL:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05002601 # TODO: This is untested.
2602 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002603 pkey = _ffi.gc(pkey, _lib.EVP_PKEY_free)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002604
Alex Gaynor67903a62016-06-02 10:37:13 -07002605 md_ctx = _lib.Cryptography_EVP_MD_CTX_new()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002606 md_ctx = _ffi.gc(md_ctx, _lib.EVP_MD_CTX_cleanup)
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002607
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002608 _lib.EVP_VerifyInit(md_ctx, digest_obj)
2609 _lib.EVP_VerifyUpdate(md_ctx, data, len(data))
Alex Gaynor5945ea82015-09-05 14:59:06 -04002610 verify_result = _lib.EVP_VerifyFinal(
2611 md_ctx, signature, len(signature), pkey
2612 )
Jean-Paul Calderone8cf4f802013-02-20 16:45:02 -08002613
2614 if verify_result != 1:
2615 _raise_current_error()
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002616
2617
Dominic Chenf05b2122015-10-13 16:32:35 +00002618def dump_crl(type, crl):
2619 """
2620 Dump a certificate revocation list to a buffer.
2621
2622 :param type: The file type (one of ``FILETYPE_PEM``, ``FILETYPE_ASN1``, or
2623 ``FILETYPE_TEXT``).
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002624 :param CRL crl: The CRL to dump.
2625
Dominic Chenf05b2122015-10-13 16:32:35 +00002626 :return: The buffer with the CRL.
Hynek Schlawack0a3cd6d2015-10-21 16:39:22 +02002627 :rtype: :data:`bytes`
Dominic Chenf05b2122015-10-13 16:32:35 +00002628 """
2629 bio = _new_mem_buf()
2630
2631 if type == FILETYPE_PEM:
2632 ret = _lib.PEM_write_bio_X509_CRL(bio, crl._crl)
2633 elif type == FILETYPE_ASN1:
2634 ret = _lib.i2d_X509_CRL_bio(bio, crl._crl)
2635 elif type == FILETYPE_TEXT:
2636 ret = _lib.X509_CRL_print(bio, crl._crl)
2637 else:
2638 raise ValueError(
2639 "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or "
2640 "FILETYPE_TEXT")
2641
2642 assert ret == 1
2643 return _bio_to_string(bio)
2644
2645
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002646def load_crl(type, buffer):
2647 """
2648 Load a certificate revocation list from a buffer
2649
2650 :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)
2651 :param buffer: The buffer the CRL is stored in
2652
2653 :return: The PKey object
2654 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002655 if isinstance(buffer, _text_type):
2656 buffer = buffer.encode("ascii")
2657
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002658 bio = _new_mem_buf(buffer)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002659
2660 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002661 crl = _lib.PEM_read_bio_X509_CRL(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002662 elif type == FILETYPE_ASN1:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002663 crl = _lib.d2i_X509_CRL_bio(bio, _ffi.NULL)
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002664 else:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002665 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2666
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002667 if crl == _ffi.NULL:
Jean-Paul Calderone57122982013-02-21 08:47:05 -08002668 _raise_current_error()
2669
2670 result = CRL.__new__(CRL)
2671 result._crl = crl
2672 return result
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002673
2674
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002675def load_pkcs7_data(type, buffer):
2676 """
2677 Load pkcs7 data from a buffer
2678
2679 :param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)
2680 :param buffer: The buffer with the pkcs7 data.
2681 :return: The PKCS7 object
2682 """
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002683 if isinstance(buffer, _text_type):
2684 buffer = buffer.encode("ascii")
2685
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002686 bio = _new_mem_buf(buffer)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002687
2688 if type == FILETYPE_PEM:
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002689 pkcs7 = _lib.PEM_read_bio_PKCS7(bio, _ffi.NULL, _ffi.NULL, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002690 elif type == FILETYPE_ASN1:
Alex Gaynor77acc362014-08-13 14:46:15 -07002691 pkcs7 = _lib.d2i_PKCS7_bio(bio, _ffi.NULL)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002692 else:
Jean-Paul Calderonedba578b2013-12-29 17:00:04 -05002693 # TODO: This is untested.
2694 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002695 raise ValueError("type argument must be FILETYPE_PEM or FILETYPE_ASN1")
2696
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002697 if pkcs7 == _ffi.NULL:
Jean-Paul Calderoneb0f64712013-03-03 10:15:39 -08002698 _raise_current_error()
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002699
2700 pypkcs7 = PKCS7.__new__(PKCS7)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002701 pypkcs7._pkcs7 = _ffi.gc(pkcs7, _lib.PKCS7_free)
Jean-Paul Calderone4e8be1c2013-02-21 18:31:12 -08002702 return pypkcs7
2703
2704
Stephen Holsapple38482622014-04-05 20:29:34 -07002705def load_pkcs12(buffer, passphrase=None):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002706 """
2707 Load a PKCS12 object from a buffer
2708
2709 :param buffer: The buffer the certificate is stored in
2710 :param passphrase: (Optional) The password to decrypt the PKCS12 lump
2711 :returns: The PKCS12 object
2712 """
Jean-Paul Calderone39a8d592015-04-13 20:49:50 -04002713 passphrase = _text_to_bytes_and_warn("passphrase", passphrase)
Abraham Martine82326c2015-02-04 10:18:10 +00002714
Jean-Paul Calderone6922a862014-01-18 10:38:28 -05002715 if isinstance(buffer, _text_type):
2716 buffer = buffer.encode("ascii")
2717
Jean-Paul Calderonef6745b32013-03-01 15:08:46 -08002718 bio = _new_mem_buf(buffer)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002719
Stephen Holsapple38482622014-04-05 20:29:34 -07002720 # Use null passphrase if passphrase is None or empty string. With PKCS#12
2721 # password based encryption no password and a zero length password are two
2722 # different things, but OpenSSL implementation will try both to figure out
2723 # which one works.
2724 if not passphrase:
2725 passphrase = _ffi.NULL
2726
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002727 p12 = _lib.d2i_PKCS12_bio(bio, _ffi.NULL)
2728 if p12 == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002729 _raise_current_error()
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002730 p12 = _ffi.gc(p12, _lib.PKCS12_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002731
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002732 pkey = _ffi.new("EVP_PKEY**")
2733 cert = _ffi.new("X509**")
2734 cacerts = _ffi.new("Cryptography_STACK_OF_X509**")
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002735
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002736 parse_result = _lib.PKCS12_parse(p12, passphrase, pkey, cert, cacerts)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002737 if not parse_result:
2738 _raise_current_error()
2739
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002740 cacerts = _ffi.gc(cacerts[0], _lib.sk_X509_free)
Jean-Paul Calderoneef9a3dc2013-03-02 16:33:32 -08002741
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002742 # openssl 1.0.0 sometimes leaves an X509_check_private_key error in the
2743 # queue for no particular reason. This error isn't interesting to anyone
2744 # outside this function. It's not even interesting to us. Get rid of it.
2745 try:
2746 _raise_current_error()
2747 except Error:
2748 pass
2749
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002750 if pkey[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002751 pykey = None
2752 else:
2753 pykey = PKey.__new__(PKey)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002754 pykey._pkey = _ffi.gc(pkey[0], _lib.EVP_PKEY_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002755
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002756 if cert[0] == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002757 pycert = None
2758 friendlyname = None
2759 else:
2760 pycert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002761 pycert._x509 = _ffi.gc(cert[0], _lib.X509_free)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002762
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002763 friendlyname_length = _ffi.new("int*")
Alex Gaynor5945ea82015-09-05 14:59:06 -04002764 friendlyname_buffer = _lib.X509_alias_get0(
2765 cert[0], friendlyname_length
2766 )
2767 friendlyname = _ffi.buffer(
2768 friendlyname_buffer, friendlyname_length[0]
2769 )[:]
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002770 if friendlyname_buffer == _ffi.NULL:
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002771 friendlyname = None
2772
2773 pycacerts = []
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002774 for i in range(_lib.sk_X509_num(cacerts)):
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002775 pycacert = X509.__new__(X509)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -05002776 pycacert._x509 = _lib.sk_X509_value(cacerts, i)
Jean-Paul Calderonee5912ce2013-02-21 10:49:35 -08002777 pycacerts.append(pycacert)
2778 if not pycacerts:
2779 pycacerts = None
2780
2781 pkcs12 = PKCS12.__new__(PKCS12)
2782 pkcs12._pkey = pykey
2783 pkcs12._cert = pycert
2784 pkcs12._cacerts = pycacerts
2785 pkcs12._friendlyname = friendlyname
2786 return pkcs12
Jean-Paul Calderone6bb40892014-01-01 12:21:34 -05002787
2788
Jean-Paul Calderoneb64e2a22014-01-11 08:06:35 -05002789# There are no direct unit tests for this initialization. It is tested
2790# indirectly since it is necessary for functions like dump_privatekey when
2791# using encryption.
2792#
2793# Thus OpenSSL.test.test_crypto.FunctionTests.test_dump_privatekey_passphrase
2794# and some other similar tests may fail without this (though they may not if
2795# the Python runtime has already done some initialization of the underlying
2796# OpenSSL library (and is linked against the same one that cryptography is
2797# using)).
Jean-Paul Calderonee324fd62014-01-11 08:00:33 -05002798_lib.OpenSSL_add_all_algorithms()
Jean-Paul Calderone11ed8e82014-01-18 10:21:50 -05002799
Jean-Paul Calderonefab157b2014-01-18 11:21:38 -05002800# This is similar but exercised mainly by exception_from_error_queue. It calls
2801# both ERR_load_crypto_strings() and ERR_load_SSL_strings().
2802_lib.SSL_load_error_strings()
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002803
2804
D.S. Ljungmark349e1362014-05-31 18:40:38 +02002805# Set the default string mask to match OpenSSL upstream (since 2005) and
2806# RFC5280 recommendations.
2807_lib.ASN1_STRING_set_default_mask_asc(b'utf8only')