Merge pull request #1502 from reaperhulk/fix-1285

Support decoding RFC 6979 signatures to (r, s)
diff --git a/.travis.yml b/.travis.yml
index cacd1e2..da7ecde 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,21 +7,21 @@
     - gcc
 env:
     matrix:
-        - TOX_ENV=py26
-        - TOX_ENV=py27
-        - TOX_ENV=py32
-        - TOX_ENV=py33
-        - TOX_ENV=py34
-        - TOX_ENV=pypy
-        - TOX_ENV=py26 OPENSSL=0.9.8
-        - TOX_ENV=py27 OPENSSL=0.9.8
-        - TOX_ENV=py32 OPENSSL=0.9.8
-        - TOX_ENV=py33 OPENSSL=0.9.8
-        - TOX_ENV=py34 OPENSSL=0.9.8
-        - TOX_ENV=pypy OPENSSL=0.9.8
-        - TOX_ENV=docs
-        - TOX_ENV=pep8
-        - TOX_ENV=py3pep8
+        - TOXENV=py26
+        - TOXENV=py27
+        - TOXENV=py32
+        - TOXENV=py33
+        - TOXENV=py34
+        - TOXENV=pypy
+        - TOXENV=py26 OPENSSL=0.9.8
+        - TOXENV=py27 OPENSSL=0.9.8
+        - TOXENV=py32 OPENSSL=0.9.8
+        - TOXENV=py33 OPENSSL=0.9.8
+        - TOXENV=py34 OPENSSL=0.9.8
+        - TOXENV=pypy OPENSSL=0.9.8
+        - TOXENV=docs
+        - TOXENV=pep8
+        - TOXENV=py3pep8
 
 install:
     - ./.travis/install.sh
@@ -44,18 +44,18 @@
         - os: osx
           compiler: gcc
         - os: osx
-          env: TOX_ENV=pep8
+          env: TOXENV=pep8
           compiler: clang
         - os: osx
-          env: TOX_ENV=py3pep8
+          env: TOXENV=py3pep8
           compiler: clang
 
         - os: linux
-          env: TOX_ENV=docs
+          env: TOXENV=docs
           compiler: clang
         - os: linux
-          env: TOX_ENV=pep8
+          env: TOXENV=pep8
           compiler: clang
         - os: linux
-          env: TOX_ENV=py3pep8
+          env: TOXENV=py3pep8
           compiler: clang
diff --git a/.travis/install.sh b/.travis/install.sh
index 51d3097..6dd84f2 100755
--- a/.travis/install.sh
+++ b/.travis/install.sh
@@ -20,7 +20,7 @@
         eval "$(pyenv init -)"
     fi
 
-    case "${TOX_ENV}" in
+    case "${TOXENV}" in
         py26)
             curl -O https://bootstrap.pypa.io/get-pip.py
             sudo python get-pip.py
@@ -62,7 +62,7 @@
 else
     sudo add-apt-repository -y ppa:fkrull/deadsnakes
 
-    if [[ "${TOX_ENV}" == "pypy" ]]; then
+    if [[ "${TOXENV}" == "pypy" ]]; then
         sudo add-apt-repository -y ppa:pypy/ppa
     fi
 
@@ -76,7 +76,7 @@
         sudo apt-get install -y --force-yes libssl-dev/lucid
     fi
 
-    case "${TOX_ENV}" in
+    case "${TOXENV}" in
         py26)
             sudo apt-get install python2.6 python2.6-dev
             ;;
diff --git a/.travis/run.sh b/.travis/run.sh
index e4ff266..1efbd60 100755
--- a/.travis/run.sh
+++ b/.travis/run.sh
@@ -18,4 +18,4 @@
     fi
 fi
 source ~/.venv/bin/activate
-tox -e $TOX_ENV -- $TOX_FLAGS
+tox -- $TOX_FLAGS
diff --git a/docs/development/c-bindings.rst b/docs/development/c-bindings.rst
index 5696337..10d5fc1 100644
--- a/docs/development/c-bindings.rst
+++ b/docs/development/c-bindings.rst
@@ -7,6 +7,10 @@
 
 Bindings live in :py:mod:`cryptography.hazmat.bindings`.
 
+When modifying the bindings you will need to recompile the C extensions to
+test the changes. This can be accomplished with ``pip install -e .`` in the
+project root. If you do not do this a ``RuntimeError`` will be raised.
+
 Style guide
 -----------
 
diff --git a/src/cryptography/hazmat/bindings/openssl/asn1.py b/src/cryptography/hazmat/bindings/openssl/asn1.py
index 2681dd9..a73dc32 100644
--- a/src/cryptography/hazmat/bindings/openssl/asn1.py
+++ b/src/cryptography/hazmat/bindings/openssl/asn1.py
@@ -57,7 +57,11 @@
 
 static const int V_ASN1_GENERALIZEDTIME;
 
+static const int MBSTRING_FLAG;
+static const int MBSTRING_ASC;
+static const int MBSTRING_BMP;
 static const int MBSTRING_UTF8;
+static const int MBSTRING_UNIV;
 """
 
 FUNCTIONS = """
diff --git a/src/cryptography/hazmat/bindings/openssl/x509.py b/src/cryptography/hazmat/bindings/openssl/x509.py
index 2fdba0f..a6e1cb6 100644
--- a/src/cryptography/hazmat/bindings/openssl/x509.py
+++ b/src/cryptography/hazmat/bindings/openssl/x509.py
@@ -70,6 +70,39 @@
 } X509;
 
 typedef ... NETSCAPE_SPKI;
+
+static const int X509_FLAG_COMPAT;
+static const int X509_FLAG_NO_HEADER;
+static const int X509_FLAG_NO_VERSION;
+static const int X509_FLAG_NO_SERIAL;
+static const int X509_FLAG_NO_SIGNAME;
+static const int X509_FLAG_NO_ISSUER;
+static const int X509_FLAG_NO_VALIDITY;
+static const int X509_FLAG_NO_SUBJECT;
+static const int X509_FLAG_NO_PUBKEY;
+static const int X509_FLAG_NO_EXTENSIONS;
+static const int X509_FLAG_NO_SIGDUMP;
+static const int X509_FLAG_NO_AUX;
+static const int X509_FLAG_NO_ATTRIBUTES;
+
+static const int XN_FLAG_SEP_MASK;
+static const int XN_FLAG_COMPAT;
+static const int XN_FLAG_SEP_COMMA_PLUS;
+static const int XN_FLAG_SEP_CPLUS_SPC;
+static const int XN_FLAG_SEP_SPLUS_SPC;
+static const int XN_FLAG_SEP_MULTILINE;
+static const int XN_FLAG_DN_REV;
+static const int XN_FLAG_FN_MASK;
+static const int XN_FLAG_FN_SN;
+static const int XN_FLAG_FN_LN;
+static const int XN_FLAG_FN_OID;
+static const int XN_FLAG_FN_NONE;
+static const int XN_FLAG_SPC_EQ;
+static const int XN_FLAG_DUMP_UNKNOWN_FIELDS;
+static const int XN_FLAG_FN_ALIGN;
+static const int XN_FLAG_RFC2253;
+static const int XN_FLAG_ONELINE;
+static const int XN_FLAG_MULTILINE;
 """
 
 FUNCTIONS = """
@@ -140,6 +173,7 @@
 int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *, EVP_PKEY *);
 int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *, EVP_PKEY *, const EVP_MD *);
 char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *);
+NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *, int);
 EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *);
 int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *, EVP_PKEY *);
 NETSCAPE_SPKI *NETSCAPE_SPKI_new(void);
diff --git a/src/cryptography/hazmat/bindings/openssl/x509name.py b/src/cryptography/hazmat/bindings/openssl/x509name.py
index 59ce757..9863c19 100644
--- a/src/cryptography/hazmat/bindings/openssl/x509name.py
+++ b/src/cryptography/hazmat/bindings/openssl/x509name.py
@@ -27,6 +27,8 @@
 unsigned long X509_NAME_hash(X509_NAME *);
 
 int i2d_X509_NAME(X509_NAME *, unsigned char **);
+int X509_NAME_add_entry_by_txt(X509_NAME *, const char *, int,
+                               const unsigned char *, int, int, int);
 int X509_NAME_add_entry_by_NID(X509_NAME *, int, int, unsigned char *,
                                int, int, int);
 X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *, int);
diff --git a/src/cryptography/hazmat/bindings/openssl/x509v3.py b/src/cryptography/hazmat/bindings/openssl/x509v3.py
index 364f3fa..3b00724 100644
--- a/src/cryptography/hazmat/bindings/openssl/x509v3.py
+++ b/src/cryptography/hazmat/bindings/openssl/x509v3.py
@@ -6,6 +6,19 @@
 
 INCLUDES = """
 #include <openssl/x509v3.h>
+
+/*
+ * This is part of a work-around for the difficulty cffi has in dealing with
+ * `LHASH_OF(foo)` as the name of a type.  We invent a new, simpler name that
+ * will be an alias for this type and use the alias throughout.  This works
+ * together with another opaque typedef for the same name in the TYPES section.
+ * Note that the result is an opaque type.
+ */
+#if OPENSSL_VERSION_NUMBER >= 0x10000000
+typedef LHASH_OF(CONF_VALUE) Cryptography_LHASH_OF_CONF_VALUE;
+#else
+typedef LHASH Cryptography_LHASH_OF_CONF_VALUE;
+#endif
 """
 
 TYPES = """
@@ -67,9 +80,13 @@
 } GENERAL_NAME;
 
 typedef struct stack_st_GENERAL_NAME GENERAL_NAMES;
+
+typedef ... Cryptography_LHASH_OF_CONF_VALUE;
 """
 
+
 FUNCTIONS = """
+int X509V3_EXT_add_alias(int, int);
 void X509V3_set_ctx(X509V3_CTX *, X509 *, X509 *, X509_REQ *, X509_CRL *, int);
 X509_EXTENSION *X509V3_EXT_nconf(CONF *, X509V3_CTX *, char *, char *);
 int GENERAL_NAME_print(BIO *, GENERAL_NAME *);
@@ -83,9 +100,13 @@
 int sk_GENERAL_NAME_push(struct stack_st_GENERAL_NAME *, GENERAL_NAME *);
 GENERAL_NAME *sk_GENERAL_NAME_value(struct stack_st_GENERAL_NAME *, int);
 
+X509_EXTENSION *X509V3_EXT_conf_nid(Cryptography_LHASH_OF_CONF_VALUE *,
+                                    X509V3_CTX *, int, char *);
+
 /* These aren't macros these functions are all const X on openssl > 1.0.x */
 const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *);
 const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int);
+
 """
 
 CUSTOMIZATIONS = """
diff --git a/tox.ini b/tox.ini
index 89a4808..85a095b 100644
--- a/tox.ini
+++ b/tox.ini
@@ -62,6 +62,13 @@
 commands =
     flake8 .
 
+[testenv:randomorder]
+deps =
+    {[testenv]deps}
+    pytest-random
+commands =
+    py.test --capture=no --strict --random {posargs}
+
 [flake8]
 exclude = .tox,*.egg
 select = E,W,F,N,I