prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  x509.CertifcateBuilder().sign() fails with "Unknown OpenSSL error' when subject has bad country code
  The x509.CertifcateBuilder().sign() function fails with an unknown OpenSSL error when the builder is provided with an invalid country code:
  
  ```
  Traceback (most recent call last):
    File "./demo.py", line 30, in <module>
      ca_crt = builder.sign(private_key=ca_key, algorithm=hashes.SHA256(), backend=default_backend())
    File "/usr/local/lib/python3.4/dist-packages/cryptography/x509/base.py", line 520, in sign
      return backend.create_x509_certificate(self, private_key, algorithm)
    File "/usr/local/lib/python3.4/dist-packages/cryptography/hazmat/backends/multibackend.py", line 381, in create_x509_certificate
      return b.create_x509_certificate(builder, private_key, algorithm)
    File "/usr/local/lib/python3.4/dist-packages/cryptography/hazmat/backends/openssl/backend.py", line 1402, in create_x509_certificate
      x509_cert, _encode_name_gc(self, list(builder._subject_name))
    File "/usr/local/lib/python3.4/dist-packages/cryptography/hazmat/backends/openssl/backend.py", line 158, in _encode_name_gc
      subject = _encode_name(backend, attributes)
    File "/usr/local/lib/python3.4/dist-packages/cryptography/hazmat/backends/openssl/backend.py", line 153, in _encode_name
      backend.openssl_assert(res == 1)
    File "/usr/local/lib/python3.4/dist-packages/cryptography/hazmat/backends/openssl/backend.py", line 719, in openssl_assert
      return binding._openssl_assert(self._lib, ok)
    File "/usr/local/lib/python3.4/dist-packages/cryptography/hazmat/bindings/openssl/binding.py", line 43, in _openssl_assert
      errors
  cryptography.exceptions.InternalError: Unknown OpenSSL error. Please file an issue at https://github.com/pyca/cryptography/issues with information on how to reproduce this. ([_OpenSSLError(code=218603671, lib=13, func=122, reason=151)])
  ```
  
  The demo code below reproduces this error. Tested on Ubuntu 14.04.3 x64 w/ Python 3.4.3, cryptography 1.2.1, and libssl-dev 1.0.1f-1ubuntu2.16.
  
  ```
  #!/usr/bin/env python3
  
  import datetime
  
  from cryptography import x509
  from cryptography.hazmat.backends import default_backend
  from cryptography.hazmat.primitives import hashes
  from cryptography.hazmat.primitives.asymmetric import rsa
  
  DUR_ONE_DAY = datetime.timedelta(1, 0, 0)
  DUR_ONE_YEAR = datetime.timedelta(366, 0, 0)
  
  ca_key = rsa.generate_private_key(65537, 4096, default_backend())
  
  sub_attr = [x509.NameAttribute(x509.NameOID.COUNTRY_NAME, "InvalidCC")]
  
  builder = x509.CertificateBuilder()
  builder = builder.issuer_name(x509.Name(sub_attr))
  builder = builder.subject_name(x509.Name(sub_attr))
  builder = builder.not_valid_before(datetime.datetime.today() - DUR_ONE_DAY)
  builder = builder.not_valid_after(datetime.datetime.today() + DUR_ONE_YEAR)
  builder = builder.serial_number(3)
  builder = builder.public_key(ca_key.public_key())
  
  extensions = []
  extensions.append(x509.BasicConstraints(ca=True, path_length=1))
  for ext in extensions:
      builder = builder.add_extension(ext, critical=True)
  
  ca_crt = builder.sign(private_key=ca_key, algorithm=hashes.SHA256(), backend=default_backend())
  
  # builder.sign() will fail with when CONTRY_NAME is invalid country code:
  #    cryptography.exceptions.InternalError: Unknown
  #    OpenSSL error. Please file an issue at
  #    https://github.com/pyca/cryptography/issues with information on
  #    how to reproduce this. ([_OpenSSLError(code=218603671, lib=13,
  #    func=122, reason=151)])
  ```
  
  Might be nice to raise a more relevant error message. Or catch this even sooner when the NameAttribute is added. 
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `src/cryptography/x509/name.py`
  Content:
  ```
  1 # This file is dual licensed under the terms of the Apache License, Version
  2 # 2.0, and the BSD License. See the LICENSE file in the root of this repository
  3 # for complete details.
  4 
  5 from __future__ import absolute_import, division, print_function
  6 
  7 import six
  8 
  9 from cryptography import utils
  10 from cryptography.x509.oid import ObjectIdentifier
  11 
  12 
  13 class NameAttribute(object):
  14     def __init__(self, oid, value):
  15         if not isinstance(oid, ObjectIdentifier):
  16             raise TypeError(
  17                 "oid argument must be an ObjectIdentifier instance."
  18             )
  19 
  20         if not isinstance(value, six.text_type):
  21             raise TypeError(
  22                 "value argument must be a text type."
  23             )
  24 
  25         self._oid = oid
  26         self._value = value
  27 
  28     oid = utils.read_only_property("_oid")
  29     value = utils.read_only_property("_value")
  30 
  31     def __eq__(self, other):
  32         if not isinstance(other, NameAttribute):
  33             return NotImplemented
  34 
  35         return (
  36             self.oid == other.oid and
  37             self.value == other.value
  38         )
  39 
  40     def __ne__(self, other):
  41         return not self == other
  42 
  43     def __hash__(self):
  44         return hash((self.oid, self.value))
  45 
  46     def __repr__(self):
  47         return "<NameAttribute(oid={0.oid}, value={0.value!r})>".format(self)
  48 
  49 
  50 class Name(object):
  51     def __init__(self, attributes):
  52         self._attributes = attributes
  53 
  54     def get_attributes_for_oid(self, oid):
  55         return [i for i in self if i.oid == oid]
  56 
  57     def __eq__(self, other):
  58         if not isinstance(other, Name):
  59             return NotImplemented
  60 
  61         return self._attributes == other._attributes
  62 
  63     def __ne__(self, other):
  64         return not self == other
  65 
  66     def __hash__(self):
  67         # TODO: this is relatively expensive, if this looks like a bottleneck
  68         # for you, consider optimizing!
  69         return hash(tuple(self._attributes))
  70 
  71     def __iter__(self):
  72         return iter(self._attributes)
  73 
  74     def __len__(self):
  75         return len(self._attributes)
  76 
  77     def __repr__(self):
  78         return "<Name({0!r})>".format(self._attributes)
  79
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py
  --- a/src/cryptography/x509/name.py
  +++ b/src/cryptography/x509/name.py
  @@ -7,7 +7,7 @@
   import six
   
   from cryptography import utils
  -from cryptography.x509.oid import ObjectIdentifier
  +from cryptography.x509.oid import NameOID, ObjectIdentifier
   
   
   class NameAttribute(object):
  @@ -22,6 +22,11 @@
                   "value argument must be a text type."
               )
   
  +        if oid == NameOID.COUNTRY_NAME and len(value.encode("utf8")) != 2:
  +            raise ValueError(
  +                "Country name must be a 2 character country code"
  +            )
  +
           self._oid = oid
           self._value = value
  
verification_info: {"golden_diff": "diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py\n--- a/src/cryptography/x509/name.py\n+++ b/src/cryptography/x509/name.py\n@@ -7,7 +7,7 @@\n import six\n \n from cryptography import utils\n-from cryptography.x509.oid import ObjectIdentifier\n+from cryptography.x509.oid import NameOID, ObjectIdentifier\n \n \n class NameAttribute(object):\n@@ -22,6 +22,11 @@\n                 \"value argument must be a text type.\"\n             )\n \n+        if oid == NameOID.COUNTRY_NAME and len(value.encode(\"utf8\")) != 2:\n+            raise ValueError(\n+                \"Country name must be a 2 character country code\"\n+            )\n+\n         self._oid = oid\n         self._value = value\n", "issue": "x509.CertifcateBuilder().sign() fails with \"Unknown OpenSSL error' when subject has bad country code\nThe x509.CertifcateBuilder().sign() function fails with an unknown OpenSSL error when the builder is provided with an invalid country code:\n\n```\nTraceback (most recent call last):\n  File \"./demo.py\", line 30, in <module>\n    ca_crt = builder.sign(private_key=ca_key, algorithm=hashes.SHA256(), backend=default_backend())\n  File \"/usr/local/lib/python3.4/dist-packages/cryptography/x509/base.py\", line 520, in sign\n    return backend.create_x509_certificate(self, private_key, algorithm)\n  File \"/usr/local/lib/python3.4/dist-packages/cryptography/hazmat/backends/multibackend.py\", line 381, in create_x509_certificate\n    return b.create_x509_certificate(builder, private_key, algorithm)\n  File \"/usr/local/lib/python3.4/dist-packages/cryptography/hazmat/backends/openssl/backend.py\", line 1402, in create_x509_certificate\n    x509_cert, _encode_name_gc(self, list(builder._subject_name))\n  File \"/usr/local/lib/python3.4/dist-packages/cryptography/hazmat/backends/openssl/backend.py\", line 158, in _encode_name_gc\n    subject = _encode_name(backend, attributes)\n  File \"/usr/local/lib/python3.4/dist-packages/cryptography/hazmat/backends/openssl/backend.py\", line 153, in _encode_name\n    backend.openssl_assert(res == 1)\n  File \"/usr/local/lib/python3.4/dist-packages/cryptography/hazmat/backends/openssl/backend.py\", line 719, in openssl_assert\n    return binding._openssl_assert(self._lib, ok)\n  File \"/usr/local/lib/python3.4/dist-packages/cryptography/hazmat/bindings/openssl/binding.py\", line 43, in _openssl_assert\n    errors\ncryptography.exceptions.InternalError: Unknown OpenSSL error. Please file an issue at https://github.com/pyca/cryptography/issues with information on how to reproduce this. ([_OpenSSLError(code=218603671, lib=13, func=122, reason=151)])\n```\n\nThe demo code below reproduces this error. Tested on Ubuntu 14.04.3 x64 w/ Python 3.4.3, cryptography 1.2.1, and libssl-dev 1.0.1f-1ubuntu2.16.\n\n```\n#!/usr/bin/env python3\n\nimport datetime\n\nfrom cryptography import x509\nfrom cryptography.hazmat.backends import default_backend\nfrom cryptography.hazmat.primitives import hashes\nfrom cryptography.hazmat.primitives.asymmetric import rsa\n\nDUR_ONE_DAY = datetime.timedelta(1, 0, 0)\nDUR_ONE_YEAR = datetime.timedelta(366, 0, 0)\n\nca_key = rsa.generate_private_key(65537, 4096, default_backend())\n\nsub_attr = [x509.NameAttribute(x509.NameOID.COUNTRY_NAME, \"InvalidCC\")]\n\nbuilder = x509.CertificateBuilder()\nbuilder = builder.issuer_name(x509.Name(sub_attr))\nbuilder = builder.subject_name(x509.Name(sub_attr))\nbuilder = builder.not_valid_before(datetime.datetime.today() - DUR_ONE_DAY)\nbuilder = builder.not_valid_after(datetime.datetime.today() + DUR_ONE_YEAR)\nbuilder = builder.serial_number(3)\nbuilder = builder.public_key(ca_key.public_key())\n\nextensions = []\nextensions.append(x509.BasicConstraints(ca=True, path_length=1))\nfor ext in extensions:\n    builder = builder.add_extension(ext, critical=True)\n\nca_crt = builder.sign(private_key=ca_key, algorithm=hashes.SHA256(), backend=default_backend())\n\n# builder.sign() will fail with when CONTRY_NAME is invalid country code:\n#    cryptography.exceptions.InternalError: Unknown\n#    OpenSSL error. Please file an issue at\n#    https://github.com/pyca/cryptography/issues with information on\n#    how to reproduce this. ([_OpenSSLError(code=218603671, lib=13,\n#    func=122, reason=151)])\n```\n\nMight be nice to raise a more relevant error message. Or catch this even sooner when the NameAttribute is added. \n\n", "before_files": [{"content": "# This file is dual licensed under the terms of the Apache License, Version\n# 2.0, and the BSD License. See the LICENSE file in the root of this repository\n# for complete details.\n\nfrom __future__ import absolute_import, division, print_function\n\nimport six\n\nfrom cryptography import utils\nfrom cryptography.x509.oid import ObjectIdentifier\n\n\nclass NameAttribute(object):\n    def __init__(self, oid, value):\n        if not isinstance(oid, ObjectIdentifier):\n            raise TypeError(\n                \"oid argument must be an ObjectIdentifier instance.\"\n            )\n\n        if not isinstance(value, six.text_type):\n            raise TypeError(\n                \"value argument must be a text type.\"\n            )\n\n        self._oid = oid\n        self._value = value\n\n    oid = utils.read_only_property(\"_oid\")\n    value = utils.read_only_property(\"_value\")\n\n    def __eq__(self, other):\n        if not isinstance(other, NameAttribute):\n            return NotImplemented\n\n        return (\n            self.oid == other.oid and\n            self.value == other.value\n        )\n\n    def __ne__(self, other):\n        return not self == other\n\n    def __hash__(self):\n        return hash((self.oid, self.value))\n\n    def __repr__(self):\n        return \"<NameAttribute(oid={0.oid}, value={0.value!r})>\".format(self)\n\n\nclass Name(object):\n    def __init__(self, attributes):\n        self._attributes = attributes\n\n    def get_attributes_for_oid(self, oid):\n        return [i for i in self if i.oid == oid]\n\n    def __eq__(self, other):\n        if not isinstance(other, Name):\n            return NotImplemented\n\n        return self._attributes == other._attributes\n\n    def __ne__(self, other):\n        return not self == other\n\n    def __hash__(self):\n        # TODO: this is relatively expensive, if this looks like a bottleneck\n        # for you, consider optimizing!\n        return hash(tuple(self._attributes))\n\n    def __iter__(self):\n        return iter(self._attributes)\n\n    def __len__(self):\n        return len(self._attributes)\n\n    def __repr__(self):\n        return \"<Name({0!r})>\".format(self._attributes)\n", "path": "src/cryptography/x509/name.py"}], "after_files": [{"content": "# This file is dual licensed under the terms of the Apache License, Version\n# 2.0, and the BSD License. See the LICENSE file in the root of this repository\n# for complete details.\n\nfrom __future__ import absolute_import, division, print_function\n\nimport six\n\nfrom cryptography import utils\nfrom cryptography.x509.oid import NameOID, ObjectIdentifier\n\n\nclass NameAttribute(object):\n    def __init__(self, oid, value):\n        if not isinstance(oid, ObjectIdentifier):\n            raise TypeError(\n                \"oid argument must be an ObjectIdentifier instance.\"\n            )\n\n        if not isinstance(value, six.text_type):\n            raise TypeError(\n                \"value argument must be a text type.\"\n            )\n\n        if oid == NameOID.COUNTRY_NAME and len(value.encode(\"utf8\")) != 2:\n            raise ValueError(\n                \"Country name must be a 2 character country code\"\n            )\n\n        self._oid = oid\n        self._value = value\n\n    oid = utils.read_only_property(\"_oid\")\n    value = utils.read_only_property(\"_value\")\n\n    def __eq__(self, other):\n        if not isinstance(other, NameAttribute):\n            return NotImplemented\n\n        return (\n            self.oid == other.oid and\n            self.value == other.value\n        )\n\n    def __ne__(self, other):\n        return not self == other\n\n    def __hash__(self):\n        return hash((self.oid, self.value))\n\n    def __repr__(self):\n        return \"<NameAttribute(oid={0.oid}, value={0.value!r})>\".format(self)\n\n\nclass Name(object):\n    def __init__(self, attributes):\n        self._attributes = attributes\n\n    def get_attributes_for_oid(self, oid):\n        return [i for i in self if i.oid == oid]\n\n    def __eq__(self, other):\n        if not isinstance(other, Name):\n            return NotImplemented\n\n        return self._attributes == other._attributes\n\n    def __ne__(self, other):\n        return not self == other\n\n    def __hash__(self):\n        # TODO: this is relatively expensive, if this looks like a bottleneck\n        # for you, consider optimizing!\n        return hash(tuple(self._attributes))\n\n    def __iter__(self):\n        return iter(self._attributes)\n\n    def __len__(self):\n        return len(self._attributes)\n\n    def __repr__(self):\n        return \"<Name({0!r})>\".format(self._attributes)\n", "path": "src/cryptography/x509/name.py"}]}