aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dev-requirements.txt1
-rw-r--r--docs/x509/reference.rst64
-rw-r--r--setup.py1
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py16
-rw-r--r--src/cryptography/hazmat/bindings/openssl/binding.py8
-rw-r--r--tests/test_x509.py41
-rw-r--r--tox.ini1
7 files changed, 99 insertions, 33 deletions
diff --git a/dev-requirements.txt b/dev-requirements.txt
index d82c13b6..f6eec132 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -5,6 +5,7 @@ invoke
iso8601
pep8-naming
pretend
+pyasn1_modules
pytest
requests
sphinx
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index e7e02de3..f056a727 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -896,7 +896,7 @@ General Name Classes
This is the generic interface that all the following classes are registered
against.
-.. class:: RFC822Name
+.. class:: RFC822Name(value)
.. versionadded:: 0.9
@@ -906,7 +906,7 @@ General Name Classes
:type: :term:`text`
-.. class:: DNSName
+.. class:: DNSName(value)
.. versionadded:: 0.9
@@ -916,7 +916,7 @@ General Name Classes
:type: :term:`text`
-.. class:: DirectoryName
+.. class:: DirectoryName(value)
.. versionadded:: 0.9
@@ -926,7 +926,7 @@ General Name Classes
:type: :class:`Name`
-.. class:: UniformResourceIdentifier
+.. class:: UniformResourceIdentifier(value)
.. versionadded:: 0.9
@@ -942,7 +942,7 @@ General Name Classes
:type: :term:`text`
-.. class:: IPAddress
+.. class:: IPAddress(value)
.. versionadded:: 0.9
@@ -954,7 +954,7 @@ General Name Classes
:class:`~ipaddress.IPv6Address`, :class:`~ipaddress.IPv4Network`,
or :class:`~ipaddress.IPv6Network`.
-.. class:: RegisteredID
+.. class:: RegisteredID(value)
.. versionadded:: 0.9
@@ -964,7 +964,7 @@ General Name Classes
:type: :class:`ObjectIdentifier`
-.. class:: OtherName
+.. class:: OtherName(type_id, value)
.. versionadded:: 1.0
@@ -1050,7 +1050,7 @@ X.509 Extensions
This is the interface against which all the following extension types are
registered.
-.. class:: KeyUsage
+.. class:: KeyUsage(digital_signature, content_commitment, key_encipherment, data_encipherment, key_agreement, key_cert_sign, crl_sign, encipher_only, decipher_only)
.. versionadded:: 0.9
@@ -1149,7 +1149,7 @@ X.509 Extensions
is false.
-.. class:: BasicConstraints
+.. class:: BasicConstraints(ca, path_length)
.. versionadded:: 0.9
@@ -1184,7 +1184,7 @@ X.509 Extensions
means the certificate can sign a subordinate CA, but the subordinate CA
is not allowed to create subordinates with ``ca`` set to true.
-.. class:: ExtendedKeyUsage
+.. class:: ExtendedKeyUsage(usages)
.. versionadded:: 0.9
@@ -1194,6 +1194,9 @@ X.509 Extensions
iterable to obtain the list of
:class:`~cryptography.x509.oid.ExtendedKeyUsageOID` OIDs present.
+ :param list usages: A list of
+ :class:`~cryptography.x509.oid.ExtendedKeyUsageOID` OIDs.
+
.. attribute:: oid
.. versionadded:: 1.0
@@ -1203,7 +1206,7 @@ X.509 Extensions
Returns :attr:`~cryptography.x509.oid.ExtensionOID.EXTENDED_KEY_USAGE`.
-.. class:: OCSPNoCheck
+.. class:: OCSPNoCheck()
.. versionadded:: 1.0
@@ -1224,7 +1227,7 @@ X.509 Extensions
Returns :attr:`~cryptography.x509.oid.ExtensionOID.OCSP_NO_CHECK`.
-.. class:: NameConstraints
+.. class:: NameConstraints(permitted_subtrees, excluded_subtrees)
.. versionadded:: 1.0
@@ -1258,7 +1261,7 @@ X.509 Extensions
``permitted_subtrees``. At least one of ``permitted_subtrees`` and
``excluded_subtrees`` will be non-None.
-.. class:: AuthorityKeyIdentifier
+.. class:: AuthorityKeyIdentifier(key_identifier, authority_cert_issuer, authority_cert_serial_number)
.. versionadded:: 0.9
@@ -1327,7 +1330,7 @@ X.509 Extensions
>>> x509.AuthorityKeyIdentifier.from_issuer_public_key(issuer_cert.public_key())
<AuthorityKeyIdentifier(key_identifier='X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9', authority_cert_issuer=None, authority_cert_serial_number=None)>
-.. class:: SubjectKeyIdentifier
+.. class:: SubjectKeyIdentifier(digest)
.. versionadded:: 0.9
@@ -1374,7 +1377,7 @@ X.509 Extensions
>>> x509.SubjectKeyIdentifier.from_public_key(csr.public_key())
<SubjectKeyIdentifier(digest='\xdb\xaa\xf0\x06\x11\xdbD\xfe\xbf\x93\x03\x8av\x88WP7\xa6\x91\xf7')>
-.. class:: SubjectAlternativeName
+.. class:: SubjectAlternativeName(general_names)
.. versionadded:: 0.9
@@ -1383,6 +1386,8 @@ X.509 Extensions
of identities for which the certificate is valid. The object is iterable to
get every element.
+ :param list general_names: A list of :class:`GeneralName` instances.
+
.. attribute:: oid
.. versionadded:: 1.0
@@ -1413,7 +1418,7 @@ X.509 Extensions
[u'www.cryptography.io', u'cryptography.io']
-.. class:: IssuerAlternativeName
+.. class:: IssuerAlternativeName(general_names)
.. versionadded:: 1.0
@@ -1422,6 +1427,8 @@ X.509 Extensions
of identities for the certificate issuer. The object is iterable to
get every element.
+ :param list general_names: A list of :class:`GeneralName` instances.
+
.. attribute:: oid
.. versionadded:: 1.0
@@ -1439,7 +1446,7 @@ X.509 Extensions
:returns: A list of values extracted from the matched general names.
-.. class:: AuthorityInformationAccess
+.. class:: AuthorityInformationAccess(descriptions)
.. versionadded:: 0.9
@@ -1450,6 +1457,8 @@ X.509 Extensions
containing one or more :class:`~cryptography.x509.AccessDescription`
instances.
+ :param list descriptions: A list of :class:`AccessDescription` objects.
+
.. attribute:: oid
.. versionadded:: 1.0
@@ -1460,7 +1469,7 @@ X.509 Extensions
:attr:`~cryptography.x509.oid.ExtensionOID.AUTHORITY_INFORMATION_ACCESS`.
-.. class:: AccessDescription
+.. class:: AccessDescription(access_method, access_location)
.. versionadded:: 0.9
@@ -1486,7 +1495,7 @@ X.509 Extensions
Where to access the information defined by the access method.
-.. class:: CRLDistributionPoints
+.. class:: CRLDistributionPoints(distribution_points)
.. versionadded:: 0.9
@@ -1494,6 +1503,9 @@ X.509 Extensions
obtained. It is an iterable, containing one or more
:class:`DistributionPoint` instances.
+ :param list distribution_points: A list of :class:`DistributionPoint`
+ instances.
+
.. attribute:: oid
.. versionadded:: 1.0
@@ -1503,7 +1515,7 @@ X.509 Extensions
Returns
:attr:`~cryptography.x509.oid.ExtensionOID.CRL_DISTRIBUTION_POINTS`.
-.. class:: DistributionPoint
+.. class:: DistributionPoint(full_name, relative_name, reasons, crl_issuer)
.. versionadded:: 0.9
@@ -1587,7 +1599,7 @@ X.509 Extensions
removed from the CRL. This reason cannot be used as a reason flag
in a :class:`DistributionPoint`.
-.. class:: InhibitAnyPolicy
+.. class:: InhibitAnyPolicy(skip_certs)
.. versionadded:: 1.0
@@ -1616,13 +1628,15 @@ X.509 Extensions
:type: int
-.. class:: CertificatePolicies
+.. class:: CertificatePolicies(policies)
.. versionadded:: 0.9
The certificate policies extension is an iterable, containing one or more
:class:`PolicyInformation` instances.
+ :param list policies: A list of :class:`PolicyInformation` instances.
+
.. attribute:: oid
.. versionadded:: 1.0
@@ -1637,7 +1651,7 @@ Certificate Policies Classes
These classes may be present within a :class:`CertificatePolicies` instance.
-.. class:: PolicyInformation
+.. class:: PolicyInformation(policy_identifier, policy_qualifiers)
.. versionadded:: 0.9
@@ -1657,7 +1671,7 @@ These classes may be present within a :class:`CertificatePolicies` instance.
meant for display to the relying party when the certificate is
used.
-.. class:: UserNotice
+.. class:: UserNotice(notice_reference, explicit_text)
.. versionadded:: 0.9
@@ -1679,7 +1693,7 @@ These classes may be present within a :class:`CertificatePolicies` instance.
:type: :term:`text`
-.. class:: NoticeReference
+.. class:: NoticeReference(organization, notice_numbers)
Notice reference can name an organization and provide information about
notices related to the certificate. For example, it might identify the
diff --git a/setup.py b/setup.py
index 9c97e1dd..19f1e663 100644
--- a/setup.py
+++ b/setup.py
@@ -63,6 +63,7 @@ test_requirements = [
"pretend",
"iso8601",
"hypothesis",
+ "pyasn1_modules",
]
# If there's no vectors locally that probably means we are in a tarball and
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index f7b5408a..8e302a99 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -52,7 +52,7 @@ from cryptography.hazmat.primitives.ciphers.algorithms import (
from cryptography.hazmat.primitives.ciphers.modes import (
CBC, CFB, CFB8, CTR, ECB, GCM, OFB
)
-from cryptography.x509.oid import ExtensionOID
+from cryptography.x509.oid import ExtensionOID, NameOID
_MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"])
@@ -133,12 +133,14 @@ def _encode_name(backend, attributes):
for attribute in attributes:
value = attribute.value.encode('utf8')
obj = _txt2obj_gc(backend, attribute.oid.dotted_string)
+ if attribute.oid == NameOID.COUNTRY_NAME:
+ # Per RFC5280 Appendix A.1 countryName should be encoded as
+ # PrintableString, not UTF8String
+ type = backend._lib.MBSTRING_ASC
+ else:
+ type = backend._lib.MBSTRING_UTF8
res = backend._lib.X509_NAME_add_entry_by_OBJ(
- subject,
- obj,
- backend._lib.MBSTRING_UTF8,
- value,
- -1, -1, 0,
+ subject, obj, type, value, -1, -1, 0,
)
backend.openssl_assert(res == 1)
return subject
@@ -614,8 +616,6 @@ class Backend(object):
res = self._lib.ASN1_STRING_set_default_mask_asc(b"utf8only")
self.openssl_assert(res == 1)
- self._binding.init_static_locks()
-
self._cipher_registry = {}
self._register_default_ciphers()
self.activate_osrandom_engine()
diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py
index 4fac11d8..a750cd6b 100644
--- a/src/cryptography/hazmat/bindings/openssl/binding.py
+++ b/src/cryptography/hazmat/bindings/openssl/binding.py
@@ -172,3 +172,11 @@ class Binding(object):
mode, n, file, line
)
)
+
+
+# OpenSSL is not thread safe until the locks are initialized. We call this
+# method in module scope so that it executes with the import lock. On
+# Pythons < 3.4 this import lock is a global lock, which can prevent a race
+# condition registering the OpenSSL locks. On Python 3.4+ the import lock
+# is per module so this approach will not work.
+Binding.init_static_locks()
diff --git a/tests/test_x509.py b/tests/test_x509.py
index a54cdc56..4072ef15 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -9,6 +9,10 @@ import datetime
import ipaddress
import os
+from pyasn1.codec.der import decoder
+
+from pyasn1_modules import rfc2459
+
import pytest
import six
@@ -1083,6 +1087,43 @@ class TestRSACertificateRequest(object):
x509.DNSName(u"cryptography.io"),
]
+ def test_build_cert_printable_string_country_name(self, backend):
+ issuer_private_key = RSA_KEY_2048.private_key(backend)
+ subject_private_key = RSA_KEY_2048.private_key(backend)
+
+ not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
+ not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
+
+ builder = x509.CertificateBuilder().serial_number(
+ 777
+ ).issuer_name(x509.Name([
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
+ ])).subject_name(x509.Name([
+ x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'),
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u'Texas'),
+ ])).public_key(
+ subject_private_key.public_key()
+ ).not_valid_before(
+ not_valid_before
+ ).not_valid_after(
+ not_valid_after
+ )
+
+ cert = builder.sign(issuer_private_key, hashes.SHA256(), backend)
+
+ parsed, _ = decoder.decode(
+ cert.public_bytes(serialization.Encoding.DER),
+ asn1Spec=rfc2459.Certificate()
+ )
+ tbs_cert = parsed.getComponentByName('tbsCertificate')
+ subject = tbs_cert.getComponentByName('subject')
+ issuer = tbs_cert.getComponentByName('issuer')
+ # \x13 is printable string. The first byte of the value of the
+ # node corresponds to the ASN.1 string type.
+ assert subject[0][0][0][1][0] == b"\x13"[0]
+ assert issuer[0][0][0][1][0] == b"\x13"[0]
+
class TestCertificateBuilder(object):
@pytest.mark.requires_backend_interface(interface=RSABackend)
diff --git a/tox.ini b/tox.ini
index 1ed03a5e..35dc5671 100644
--- a/tox.ini
+++ b/tox.ini
@@ -9,6 +9,7 @@ deps =
pretend
pytest
hypothesis>=1.11.4
+ pyasn1_modules
./vectors
passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME
commands =