Merge pull request #1783 from reaperhulk/san-class

Add GeneralName and SubjectAlternativeName classes
diff --git a/.travis.yml b/.travis.yml
index b6f6f0c..251eb07 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,29 +1,125 @@
-language: c
-os:
-    - osx
-    - linux
-compiler:
-    - clang
-    - gcc
-env:
-    matrix:
-        - TOXENV=py26
-        - TOXENV=py27
-        - TOXENV=py32
-        - TOXENV=py33
-        - TOXENV=py34
-        - TOXENV=pypy
-        - TOXENV=pypy3
-        - 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=pypy3 OPENSSL=0.9.8
-        - TOXENV=docs
-        - TOXENV=pep8
-        - TOXENV=py3pep8
+sudo: false
+language: python
+cache:
+    directories:
+        - $HOME/.cache/pip
+matrix:
+    include:
+        - python: 2.6 # these are just to make travis's UI a bit prettier
+          env: TOXENV=py26
+        - python: 2.7
+          env: TOXENV=py27
+        - python: 3.2
+          env: TOXENV=py32
+        - python: 3.3
+          env: TOXENV=py33
+        - python: 3.4
+          env: TOXENV=py34
+        - python: pypy
+          env: TOXENV=pypy
+        - python: 2.6
+          env: TOXENV=py26 OPENSSL=0.9.8
+          addons:
+              apt:
+                  sources:
+                      - lucid
+                  packages:
+                      - libssl-dev/lucid
+        - python: 2.7
+          env: TOXENV=py27 OPENSSL=0.9.8
+          addons:
+              apt:
+                  sources:
+                      - lucid
+                  packages:
+                      - libssl-dev/lucid
+        - python: 3.2
+          env: TOXENV=py32 OPENSSL=0.9.8
+          addons:
+              apt:
+                  sources:
+                      - lucid
+                  packages:
+                      - libssl-dev/lucid
+        - python: 3.3
+          env: TOXENV=py33 OPENSSL=0.9.8
+          addons:
+              apt:
+                  sources:
+                      - lucid
+                  packages:
+                      - libssl-dev/lucid
+        - python: 3.4
+          env: TOXENV=py34 OPENSSL=0.9.8
+          addons:
+              apt:
+                  sources:
+                      - lucid
+                  packages:
+                      - libssl-dev/lucid
+        - python: pypy
+          env: TOXENV=pypy OPENSSL=0.9.8
+          addons:
+              apt:
+                  sources:
+                      - lucid
+                  packages:
+                      - libssl-dev/lucid
+        - python: 2.7
+          env: TOXENV=docs
+          addons:
+              apt:
+                  packages:
+                      - libenchant-dev
+        - python: 2.7
+          env: TOXENV=pep8
+        - python: 3.3
+          env: TOXENV=py3pep8
+        - language: generic
+          os: osx
+          env: TOXENV=py26
+        - language: generic
+          os: osx
+          env: TOXENV=py27
+        - language: generic
+          os: osx
+          env: TOXENV=py32
+        - language: generic
+          os: osx
+          env: TOXENV=py33
+        - language: generic
+          os: osx
+          env: TOXENV=py34
+        - language: generic
+          os: osx
+          env: TOXENV=pypy
+        - language: generic
+          os: osx
+          env: TOXENV=pypy3
+        - language: generic
+          os: osx
+          env: TOXENV=py26 OPENSSL=0.9.8
+        - language: generic
+          os: osx
+          env: TOXENV=py27 OPENSSL=0.9.8
+        - language: generic
+          os: osx
+          env: TOXENV=py32 OPENSSL=0.9.8
+        - language: generic
+          os: osx
+          env: TOXENV=py33 OPENSSL=0.9.8
+        - language: generic
+          os: osx
+          env: TOXENV=py34 OPENSSL=0.9.8
+        - language: generic
+          os: osx
+          env: TOXENV=pypy OPENSSL=0.9.8
+        - language: generic
+          os: osx
+          env: TOXENV=pypy3 OPENSSL=0.9.8
+        - language: generic
+          os: osx
+          env: TOXENV=docs
 
 install:
     - ./.travis/install.sh
@@ -40,31 +136,3 @@
             - "irc.freenode.org#cryptography-dev"
         use_notice: true
         skip_join: true
-    webhooks:
-        - https://buildtimetrend.herokuapp.com/travis
-
-matrix:
-    exclude:
-        # excluding pypy3 from linux configs until the ubuntu ppa has pypy3 available.
-        - os: linux
-          env: TOXENV=pypy3
-        - os: linux
-          env: TOXENV=pypy3 OPENSSL=0.9.8
-        - os: osx
-          compiler: gcc
-        - os: osx
-          env: TOXENV=pep8
-          compiler: clang
-        - os: osx
-          env: TOXENV=py3pep8
-          compiler: clang
-
-        - os: linux
-          env: TOXENV=docs
-          compiler: clang
-        - os: linux
-          env: TOXENV=pep8
-          compiler: clang
-        - os: linux
-          env: TOXENV=py3pep8
-          compiler: clang
diff --git a/.travis/install.sh b/.travis/install.sh
index aacfc5a..f7f3d50 100755
--- a/.travis/install.sh
+++ b/.travis/install.sh
@@ -3,7 +3,6 @@
 set -e
 set -x
 
-
 if [[ "$(uname -s)" == 'Darwin' ]]; then
     brew update
 
@@ -18,11 +17,11 @@
     case "${TOXENV}" in
         py26)
             curl -O https://bootstrap.pypa.io/get-pip.py
-            sudo python get-pip.py
+            python get-pip.py --user
             ;;
         py27)
             curl -O https://bootstrap.pypa.io/get-pip.py
-            sudo python get-pip.py
+            python get-pip.py --user
             ;;
         py32)
             brew upgrade pyenv
@@ -51,55 +50,15 @@
             ;;
         docs)
             curl -O https://bootstrap.pypa.io/get-pip.py
-            sudo python get-pip.py
+            python get-pip.py --user
             ;;
     esac
     pyenv rehash
-
+    pip install --user virtualenv
 else
-    sudo add-apt-repository -y ppa:fkrull/deadsnakes
-
-    if [[ "${TOXENV}" == "pypy" ]]; then
-        sudo add-apt-repository -y ppa:pypy/ppa
-    fi
-
-    if [[ "${OPENSSL}" == "0.9.8" ]]; then
-        sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu/ lucid main"
-    fi
-
-    # Retry `update` on failure, some of the servers aren't super reliable.
-    sudo apt-get -y update || sudo apt-get -y update || sudo apt-get -y update
-
-    if [[ "${OPENSSL}" == "0.9.8" ]]; then
-        sudo apt-get install -y --force-yes libssl-dev/lucid
-    fi
-
-    case "${TOXENV}" in
-        py26)
-            sudo apt-get install python2.6 python2.6-dev
-            ;;
-        py32)
-            sudo apt-get install python3.2 python3.2-dev
-            ;;
-        py33)
-            sudo apt-get install python3.3 python3.3-dev
-            ;;
-        py34)
-            sudo apt-get install python3.4 python3.4-dev
-            ;;
-        py3pep8)
-            sudo apt-get install python3.3 python3.3-dev
-            ;;
-        pypy)
-            sudo apt-get install --force-yes pypy pypy-dev
-            ;;
-        docs)
-            sudo apt-get install libenchant-dev
-            ;;
-    esac
+    pip install virtualenv
 fi
 
-sudo pip install virtualenv
-virtualenv ~/.venv
+python -m virtualenv ~/.venv
 source ~/.venv/bin/activate
 pip install tox coveralls
diff --git a/AUTHORS.rst b/AUTHORS.rst
index adf51af..6e92a84 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -21,3 +21,4 @@
 * Mark Adams <mark@markadams.me> (A18A 7DD3 283C CF2A B0CE FE0E C7A0 5E3F C972 098C)
 * Gregory Haynes <greg@greghaynes.net> (6FB6 44BF 9FD0 EBA2 1CE9  471F B08F 42F9 0DC6 599F)
 * Chelsea Winfree <chelsea.winfree@gmail.com>
+* Steven Buss <steven.buss@gmail.com> (1FB9 2EC1 CF93 DFD6 B47F F583 B1A5 6C22 290D A4C3)
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index fd92a56..69eea52 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -27,6 +27,10 @@
 * Add support for parsing X.509 certificate signing requests (CSRs) with
   :func:`~cryptography.x509.load_pem_x509_csr` and
   :func:`~cryptography.x509.load_der_x509_csr`.
+* Moved ``cryptography.exceptions.InvalidToken`` to
+  :class:`cryptography.hazmat.primitives.twofactor.InvalidToken` and deprecated
+  the old location. This was moved to minimize confusion between this exception
+  and :class:`cryptography.fernet.InvalidToken`.
 
 0.8.2 - 2015-04-10
 ~~~~~~~~~~~~~~~~~~
diff --git a/docs/exceptions.rst b/docs/exceptions.rst
index 28da8ec..59d7d9d 100644
--- a/docs/exceptions.rst
+++ b/docs/exceptions.rst
@@ -37,9 +37,3 @@
 
     This is raised when the verify method of a key derivation function's
     computed key does not match the expected key.
-
-
-.. class:: InvalidToken
-
-    This is raised when the verify method of a one time password function's
-    computed token does not match the expected token.
diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst
index a518774..3b5b677 100644
--- a/docs/hazmat/primitives/asymmetric/rsa.rst
+++ b/docs/hazmat/primitives/asymmetric/rsa.rst
@@ -688,4 +688,4 @@
 .. _`Chinese Remainder Theorem`: https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29#Using_the_Chinese_remainder_algorithm
 .. _`security proof`: http://eprint.iacr.org/2001/062.pdf
 .. _`recommended padding algorithm`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
-.. _`proven secure`: http://cseweb.ucsd.edu/users/mihir/papers/oae.pdf
+.. _`proven secure`: http://cseweb.ucsd.edu/~mihir/papers/oae.pdf
diff --git a/docs/hazmat/primitives/asymmetric/utils.rst b/docs/hazmat/primitives/asymmetric/utils.rst
index 6b34880..7380f0b 100644
--- a/docs/hazmat/primitives/asymmetric/utils.rst
+++ b/docs/hazmat/primitives/asymmetric/utils.rst
@@ -15,6 +15,8 @@
 
     :returns: The decoded tuple ``(r, s)``.
 
+    :raises ValueError: Raised if the signature is malformed.
+
 .. function:: encode_rfc6979_signature(r, s)
 
     Creates an :rfc:`6979` byte string from raw signature values.
diff --git a/docs/hazmat/primitives/twofactor.rst b/docs/hazmat/primitives/twofactor.rst
index 89d8122..dd3e025 100644
--- a/docs/hazmat/primitives/twofactor.rst
+++ b/docs/hazmat/primitives/twofactor.rst
@@ -11,6 +11,11 @@
 one time password values based on Hash-based message authentication
 codes (HMAC).
 
+.. class:: InvalidToken
+
+    This is raised when the verify method of a one time password function's
+    computed token does not match the expected token.
+
 .. currentmodule:: cryptography.hazmat.primitives.twofactor.hotp
 
 .. class:: HOTP(key, length, algorithm, backend)
@@ -66,8 +71,8 @@
 
         :param bytes hotp: The one time password value to validate.
         :param int counter: The counter value to validate against.
-        :raises cryptography.exceptions.InvalidToken: This is raised when the
-            supplied HOTP does not match the expected HOTP.
+        :raises cryptography.hazmat.primitives.twofactor.InvalidToken: This
+             is raised when the supplied HOTP does not match the expected HOTP.
 
 Throttling
 ~~~~~~~~~~
@@ -164,5 +169,5 @@
 
         :param bytes totp: The one time password value to validate.
         :param int time: The time value to validate against.
-        :raises cryptography.exceptions.InvalidToken: This is raised when the
-            supplied TOTP does not match the expected TOTP.
+        :raises cryptography.hazmat.primitives.twofactor.InvalidToken: This
+             is raised when the supplied TOTP does not match the expected TOTP.
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index f7b73b3..b7c4c6c 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -36,6 +36,7 @@
 Koblitz
 Lange
 metadata
+multi
 naïve
 namespace
 namespaces
diff --git a/docs/x509.rst b/docs/x509.rst
index b4ff748..e0e05b6 100644
--- a/docs/x509.rst
+++ b/docs/x509.rst
@@ -276,7 +276,7 @@
             >>> for ext in cert.extensions:
             ...     print(ext)
             <Extension(oid=<ObjectIdentifier(oid=2.5.29.14, name=subjectKeyIdentifier)>, critical=False, value=<SubjectKeyIdentifier(digest='X\x01\x84$\x1b\xbc+R\x94J=\xa5\x10r\x14Q\xf5\xaf:\xc9')>)>
-            <Extension(oid=<ObjectIdentifier(oid=2.5.29.15, name=keyUsage)>, critical=True, value=<KeyUsage(digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=N/A, decipher_only=N/A)>)>
+            <Extension(oid=<ObjectIdentifier(oid=2.5.29.15, name=keyUsage)>, critical=True, value=<KeyUsage(digital_signature=False, content_commitment=False, key_encipherment=False, data_encipherment=False, key_agreement=False, key_cert_sign=True, crl_sign=True, encipher_only=None, decipher_only=None)>)>
             <Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)>
 
 X.509 CSR (Certificate Signing Request) Object
diff --git a/setup.py b/setup.py
index 60e6b78..f66977e 100644
--- a/setup.py
+++ b/setup.py
@@ -29,15 +29,12 @@
     exec(f.read(), about)
 
 
-SETUPTOOLS_DEPENDENCY = "setuptools"
-CFFI_DEPENDENCY = "cffi>=0.8"
-SIX_DEPENDENCY = "six>=1.4.1"
 VECTORS_DEPENDENCY = "cryptography_vectors=={0}".format(about['__version__'])
 
 requirements = [
     "pyasn1",
-    SIX_DEPENDENCY,
-    SETUPTOOLS_DEPENDENCY
+    "six>=1.4.1",
+    "setuptools"
 ]
 
 if sys.version_info < (3, 4):
@@ -47,7 +44,7 @@
     requirements.append("ipaddress")
 
 if platform.python_implementation() != "PyPy":
-    requirements.append(CFFI_DEPENDENCY)
+    requirements.append("cffi>=0.8")
 
 # If you add a new dep here you probably need to add it in the tox.ini as well
 test_requirements = [
diff --git a/src/cryptography/exceptions.py b/src/cryptography/exceptions.py
index 102165c..a4292eb 100644
--- a/src/cryptography/exceptions.py
+++ b/src/cryptography/exceptions.py
@@ -6,6 +6,9 @@
 
 from enum import Enum
 
+from cryptography import utils
+from cryptography.hazmat.primitives import twofactor
+
 
 class _Reasons(Enum):
     BACKEND_MISSING_INTERFACE = 0
@@ -53,5 +56,12 @@
     pass
 
 
-class InvalidToken(Exception):
-    pass
+InvalidToken = utils.deprecated(
+    twofactor.InvalidToken,
+    __name__,
+    (
+        "The InvalidToken exception has moved to the "
+        "cryptography.hazmat.primitives.twofactor module"
+    ),
+    utils.DeprecatedIn09
+)
diff --git a/src/cryptography/hazmat/bindings/openssl/ssl.py b/src/cryptography/hazmat/bindings/openssl/ssl.py
index d680c3a..6161a9d 100644
--- a/src/cryptography/hazmat/bindings/openssl/ssl.py
+++ b/src/cryptography/hazmat/bindings/openssl/ssl.py
@@ -526,7 +526,7 @@
 #endif
 
 /* ALPN was added in OpenSSL 1.0.2. */
-#if OPENSSL_VERSION_NUMBER < 0x10002001L
+#if OPENSSL_VERSION_NUMBER < 0x10002001L && !defined(LIBRESSL_VERSION_NUMBER)
 int (*SSL_CTX_set_alpn_protos)(SSL_CTX *,
                                const unsigned char *,
                                unsigned) = NULL;
diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py
index 71f4ff8..29390e4 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/utils.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py
@@ -4,6 +4,7 @@
 
 from __future__ import absolute_import, division, print_function
 
+from pyasn1.codec.ber import eoo
 from pyasn1.codec.der import decoder, encoder
 from pyasn1.error import PyAsn1Error
 from pyasn1.type import namedtype, univ
@@ -28,6 +29,12 @@
         raise ValueError(
             "The signature contains bytes after the end of the ASN.1 sequence."
         )
+    # pyasn1 can erroneously return this from top-level DER decoding.
+    # It's intended as a sentinel in recursive BER decoding, so it's
+    # returned even though an asn1Spec is provided.
+    if eoo.endOfOctets.isSameTypeWith(data) and data == eoo.endOfOctets:
+        raise ValueError("Invalid signature data. Unable to decode ASN.1")
+
     r = int(data.getComponentByName('r'))
     s = int(data.getComponentByName('s'))
     return (r, s)
diff --git a/src/cryptography/hazmat/primitives/twofactor/__init__.py b/src/cryptography/hazmat/primitives/twofactor/__init__.py
index 4b54088..e71f9e6 100644
--- a/src/cryptography/hazmat/primitives/twofactor/__init__.py
+++ b/src/cryptography/hazmat/primitives/twofactor/__init__.py
@@ -3,3 +3,7 @@
 # for complete details.
 
 from __future__ import absolute_import, division, print_function
+
+
+class InvalidToken(Exception):
+    pass
diff --git a/src/cryptography/hazmat/primitives/twofactor/hotp.py b/src/cryptography/hazmat/primitives/twofactor/hotp.py
index 1dac920..ba228b4 100644
--- a/src/cryptography/hazmat/primitives/twofactor/hotp.py
+++ b/src/cryptography/hazmat/primitives/twofactor/hotp.py
@@ -9,11 +9,12 @@
 import six
 
 from cryptography.exceptions import (
-    InvalidToken, UnsupportedAlgorithm, _Reasons
+    UnsupportedAlgorithm, _Reasons
 )
 from cryptography.hazmat.backends.interfaces import HMACBackend
 from cryptography.hazmat.primitives import constant_time, hmac
 from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512
+from cryptography.hazmat.primitives.twofactor import InvalidToken
 
 
 class HOTP(object):
diff --git a/src/cryptography/hazmat/primitives/twofactor/totp.py b/src/cryptography/hazmat/primitives/twofactor/totp.py
index 0b04a13..03df929 100644
--- a/src/cryptography/hazmat/primitives/twofactor/totp.py
+++ b/src/cryptography/hazmat/primitives/twofactor/totp.py
@@ -5,10 +5,11 @@
 from __future__ import absolute_import, division, print_function
 
 from cryptography.exceptions import (
-    InvalidToken, UnsupportedAlgorithm, _Reasons
+    UnsupportedAlgorithm, _Reasons
 )
 from cryptography.hazmat.backends.interfaces import HMACBackend
 from cryptography.hazmat.primitives import constant_time
+from cryptography.hazmat.primitives.twofactor import InvalidToken
 from cryptography.hazmat.primitives.twofactor.hotp import HOTP
 
 
diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py
index 0f8cbb2..445554e 100644
--- a/src/cryptography/utils.py
+++ b/src/cryptography/utils.py
@@ -11,6 +11,7 @@
 
 
 DeprecatedIn08 = DeprecationWarning
+DeprecatedIn09 = PendingDeprecationWarning
 
 
 def read_only_property(name):
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index 9db333c..55b1746 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -354,8 +354,8 @@
             encipher_only = self.encipher_only
             decipher_only = self.decipher_only
         except ValueError:
-            encipher_only = "N/A"
-            decipher_only = "N/A"
+            encipher_only = None
+            decipher_only = None
 
         return ("<KeyUsage(digital_signature={0.digital_signature}, "
                 "content_commitment={0.content_commitment}, "
diff --git a/tests/hazmat/primitives/test_asym_utils.py b/tests/hazmat/primitives/test_asym_utils.py
index bf55bad..c3fbedf 100644
--- a/tests/hazmat/primitives/test_asym_utils.py
+++ b/tests/hazmat/primitives/test_asym_utils.py
@@ -63,3 +63,8 @@
         # This byte sequence has an invalid ASN.1 sequence length as well as
         # an invalid integer length for the second integer.
         decode_rfc6979_signature(b"0\x07\x02\x01\x01\x02\x02\x01")
+
+    with pytest.raises(ValueError):
+        # This is the BER "end-of-contents octets," which pyasn1 is
+        # wrongly willing to return from top-level DER decoding.
+        decode_rfc6979_signature(b"\x00\x00")
diff --git a/tests/hazmat/primitives/twofactor/test_hotp.py b/tests/hazmat/primitives/twofactor/test_hotp.py
index a76aa6e..a5d1c28 100644
--- a/tests/hazmat/primitives/twofactor/test_hotp.py
+++ b/tests/hazmat/primitives/twofactor/test_hotp.py
@@ -8,10 +8,11 @@
 
 import pytest
 
-from cryptography.exceptions import InvalidToken, _Reasons
+from cryptography.exceptions import _Reasons
 from cryptography.hazmat.backends.interfaces import HMACBackend
 from cryptography.hazmat.primitives import hashes
 from cryptography.hazmat.primitives.hashes import MD5, SHA1
+from cryptography.hazmat.primitives.twofactor import InvalidToken
 from cryptography.hazmat.primitives.twofactor.hotp import HOTP
 
 from ....utils import (
diff --git a/tests/hazmat/primitives/twofactor/test_totp.py b/tests/hazmat/primitives/twofactor/test_totp.py
index 0532108..6039983 100644
--- a/tests/hazmat/primitives/twofactor/test_totp.py
+++ b/tests/hazmat/primitives/twofactor/test_totp.py
@@ -6,9 +6,10 @@
 
 import pytest
 
-from cryptography.exceptions import InvalidToken, _Reasons
+from cryptography.exceptions import _Reasons
 from cryptography.hazmat.backends.interfaces import HMACBackend
 from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.twofactor import InvalidToken
 from cryptography.hazmat.primitives.twofactor.totp import TOTP
 
 from ....utils import (
diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py
index b6bb188..4811541 100644
--- a/tests/test_x509_ext.py
+++ b/tests/test_x509_ext.py
@@ -150,8 +150,8 @@
         assert repr(ku) == (
             "<KeyUsage(digital_signature=True, content_commitment=True, key_en"
             "cipherment=False, data_encipherment=False, key_agreement=False, k"
-            "ey_cert_sign=True, crl_sign=False, encipher_only=N/A, decipher_on"
-            "ly=N/A)>"
+            "ey_cert_sign=True, crl_sign=False, encipher_only=None, decipher_o"
+            "nly=None)>"
         )
 
     def test_repr_key_agreement_true(self):