Merge pull request #2447 from reaperhulk/encode-decode-point

add support for encoding/decoding elliptic curve points
diff --git a/dev-requirements.txt b/dev-requirements.txt
index d82c13b..f6eec13 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -5,6 +5,7 @@
 iso8601
 pep8-naming
 pretend
+pyasn1_modules
 pytest
 requests
 sphinx
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index e7e02de..f056a72 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -896,7 +896,7 @@
     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 @@
 
         :type: :term:`text`
 
-.. class:: DNSName
+.. class:: DNSName(value)
 
     .. versionadded:: 0.9
 
@@ -916,7 +916,7 @@
 
         :type: :term:`text`
 
-.. class:: DirectoryName
+.. class:: DirectoryName(value)
 
     .. versionadded:: 0.9
 
@@ -926,7 +926,7 @@
 
         :type: :class:`Name`
 
-.. class:: UniformResourceIdentifier
+.. class:: UniformResourceIdentifier(value)
 
     .. versionadded:: 0.9
 
@@ -942,7 +942,7 @@
 
         :type: :term:`text`
 
-.. class:: IPAddress
+.. class:: IPAddress(value)
 
     .. versionadded:: 0.9
 
@@ -954,7 +954,7 @@
             :class:`~ipaddress.IPv6Address`,  :class:`~ipaddress.IPv4Network`,
             or :class:`~ipaddress.IPv6Network`.
 
-.. class:: RegisteredID
+.. class:: RegisteredID(value)
 
     .. versionadded:: 0.9
 
@@ -964,7 +964,7 @@
 
         :type: :class:`ObjectIdentifier`
 
-.. class:: OtherName
+.. class:: OtherName(type_id, value)
 
     .. versionadded:: 1.0
 
@@ -1050,7 +1050,7 @@
     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 @@
             is false.
 
 
-.. class:: BasicConstraints
+.. class:: BasicConstraints(ca, path_length)
 
     .. versionadded:: 0.9
 
@@ -1184,7 +1184,7 @@
         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 @@
     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 @@
         Returns :attr:`~cryptography.x509.oid.ExtensionOID.EXTENDED_KEY_USAGE`.
 
 
-.. class:: OCSPNoCheck
+.. class:: OCSPNoCheck()
 
     .. versionadded:: 1.0
 
@@ -1224,7 +1227,7 @@
 
         Returns :attr:`~cryptography.x509.oid.ExtensionOID.OCSP_NO_CHECK`.
 
-.. class:: NameConstraints
+.. class:: NameConstraints(permitted_subtrees, excluded_subtrees)
 
     .. versionadded:: 1.0
 
@@ -1258,7 +1261,7 @@
         ``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 @@
             >>> 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 @@
             >>> 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 @@
     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 @@
             [u'www.cryptography.io', u'cryptography.io']
 
 
-.. class:: IssuerAlternativeName
+.. class:: IssuerAlternativeName(general_names)
 
     .. versionadded:: 1.0
 
@@ -1422,6 +1427,8 @@
     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 @@
         :returns: A list of values extracted from the matched general names.
 
 
-.. class:: AuthorityInformationAccess
+.. class:: AuthorityInformationAccess(descriptions)
 
     .. versionadded:: 0.9
 
@@ -1450,6 +1457,8 @@
     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 @@
         :attr:`~cryptography.x509.oid.ExtensionOID.AUTHORITY_INFORMATION_ACCESS`.
 
 
-.. class:: AccessDescription
+.. class:: AccessDescription(access_method, access_location)
 
     .. versionadded:: 0.9
 
@@ -1486,7 +1495,7 @@
 
         Where to access the information defined by the access method.
 
-.. class:: CRLDistributionPoints
+.. class:: CRLDistributionPoints(distribution_points)
 
     .. versionadded:: 0.9
 
@@ -1494,6 +1503,9 @@
     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 @@
         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 @@
         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 @@
 
         :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 @@
 
 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 @@
         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 @@
 
         :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 9c97e1d..19f1e66 100644
--- a/setup.py
+++ b/setup.py
@@ -63,6 +63,7 @@
     "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 f7b5408..8e302a9 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.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 @@
     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 @@
         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 4fac11d..a750cd6 100644
--- a/src/cryptography/hazmat/bindings/openssl/binding.py
+++ b/src/cryptography/hazmat/bindings/openssl/binding.py
@@ -172,3 +172,11 @@
                     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 a54cdc5..4072ef1 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -9,6 +9,10 @@
 import ipaddress
 import os
 
+from pyasn1.codec.der import decoder
+
+from pyasn1_modules import rfc2459
+
 import pytest
 
 import six
@@ -1083,6 +1087,43 @@
             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 1ed03a5..35dc567 100644
--- a/tox.ini
+++ b/tox.ini
@@ -9,6 +9,7 @@
     pretend
     pytest
     hypothesis>=1.11.4
+    pyasn1_modules
     ./vectors
 passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME
 commands =