Merge pull request #356 from public/authors

Add myself to AUTHORS
diff --git a/cryptography/exceptions.py b/cryptography/exceptions.py
index e9d8819..44363c2 100644
--- a/cryptography/exceptions.py
+++ b/cryptography/exceptions.py
@@ -30,3 +30,7 @@
 
 class InvalidTag(Exception):
     pass
+
+
+class InvalidSignature(Exception):
+    pass
diff --git a/cryptography/hazmat/backends/openssl/asn1.py b/cryptography/hazmat/backends/openssl/asn1.py
index a186d59..6a309ee 100644
--- a/cryptography/hazmat/backends/openssl/asn1.py
+++ b/cryptography/hazmat/backends/openssl/asn1.py
@@ -16,7 +16,24 @@
 """
 
 TYPES = """
-typedef ... time_t;
+/*
+ * TODO: This typedef is wrong.
+ *
+ * This is due to limitations of cffi.
+ * See https://bitbucket.org/cffi/cffi/issue/69
+ *
+ * For another possible work-around (not used here because it involves more
+ * complicated use of the cffi API which falls outside the general pattern used
+ * by this package), see
+ * http://paste.pound-python.org/show/iJcTUMkKeBeS6yXpZWUU/
+ *
+ * The work-around used here is to just be sure to declare a type that is at
+ * least as large as the real type.  Maciej explains:
+ *
+ * <fijal> I think you want to declare your value too large (e.g. long)
+ * <fijal> that way you'll never pass garbage
+ */
+typedef uintptr_t time_t;
 
 typedef int ASN1_BOOLEAN;
 typedef ... ASN1_INTEGER;
@@ -118,6 +135,7 @@
 long ASN1_INTEGER_get(ASN1_INTEGER *);
 
 BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *, BIGNUM *);
+ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *, ASN1_INTEGER *);
 """
 
 CUSTOMIZATIONS = """
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index 7b67fb0..6231aad 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -85,6 +85,7 @@
         "evp",
         "hmac",
         "nid",
+        "objects",
         "opensslv",
         "pem",
         "pkcs7",
diff --git a/cryptography/hazmat/backends/openssl/bignum.py b/cryptography/hazmat/backends/openssl/bignum.py
index 68d0c3a..599eadc 100644
--- a/cryptography/hazmat/backends/openssl/bignum.py
+++ b/cryptography/hazmat/backends/openssl/bignum.py
@@ -17,7 +17,24 @@
 
 TYPES = """
 typedef ... BIGNUM;
-typedef ... BN_ULONG;
+/*
+ * TODO: This typedef is wrong.
+ *
+ * This is due to limitations of cffi.
+ * See https://bitbucket.org/cffi/cffi/issue/69
+ *
+ * For another possible work-around (not used here because it involves more
+ * complicated use of the cffi API which falls outside the general pattern used
+ * by this package), see
+ * http://paste.pound-python.org/show/iJcTUMkKeBeS6yXpZWUU/
+ *
+ * The work-around used here is to just be sure to declare a type that is at
+ * least as large as the real type.  Maciej explains:
+ *
+ * <fijal> I think you want to declare your value too large (e.g. long)
+ * <fijal> that way you'll never pass garbage
+ */
+typedef uintptr_t BN_ULONG;
 """
 
 FUNCTIONS = """
diff --git a/cryptography/hazmat/backends/openssl/evp.py b/cryptography/hazmat/backends/openssl/evp.py
index 0662b1e..1f8901b 100644
--- a/cryptography/hazmat/backends/openssl/evp.py
+++ b/cryptography/hazmat/backends/openssl/evp.py
@@ -24,7 +24,9 @@
     ...;
 } EVP_CIPHER_CTX;
 typedef ... EVP_MD;
-typedef struct env_md_ctx_st EVP_MD_CTX;
+typedef struct env_md_ctx_st {
+    ...;
+} EVP_MD_CTX;
 
 typedef struct evp_pkey_st {
     int type;
@@ -32,6 +34,7 @@
 } EVP_PKEY;
 static const int EVP_PKEY_RSA;
 static const int EVP_PKEY_DSA;
+static const int EVP_MAX_MD_SIZE;
 static const int EVP_CTRL_GCM_SET_IVLEN;
 static const int EVP_CTRL_GCM_GET_TAG;
 static const int EVP_CTRL_GCM_SET_TAG;
@@ -92,6 +95,8 @@
 int EVP_VerifyUpdate(EVP_MD_CTX *, const void *, size_t);
 int EVP_VerifyFinal(EVP_MD_CTX *, const unsigned char *, unsigned int,
                     EVP_PKEY *);
+
+const EVP_MD *EVP_md5();
 """
 
 MACROS = """
diff --git a/cryptography/hazmat/backends/openssl/nid.py b/cryptography/hazmat/backends/openssl/nid.py
index 111f82f..40aed19 100644
--- a/cryptography/hazmat/backends/openssl/nid.py
+++ b/cryptography/hazmat/backends/openssl/nid.py
@@ -37,6 +37,7 @@
 static const int NID_ecdsa_with_SHA512;
 static const int NID_crl_reason;
 static const int NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+static const int NID_subject_alt_name;
 """
 
 FUNCTIONS = """
diff --git a/cryptography/hazmat/backends/openssl/objects.py b/cryptography/hazmat/backends/openssl/objects.py
new file mode 100644
index 0000000..ad1b858
--- /dev/null
+++ b/cryptography/hazmat/backends/openssl/objects.py
@@ -0,0 +1,43 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+INCLUDES = """
+#include <openssl/objects.h>
+"""
+
+TYPES = """
+"""
+
+FUNCTIONS = """
+ASN1_OBJECT *OBJ_nid2obj(int);
+const char *OBJ_nid2ln(int);
+const char *OBJ_nid2sn(int);
+int OBJ_obj2nid(const ASN1_OBJECT *);
+int OBJ_ln2nid(const char *);
+int OBJ_sn2nid(const char *);
+int OBJ_txt2nid(const char *);
+ASN1_OBJECT *OBJ_txt2obj(const char *, int);
+int OBJ_obj2txt(char *, int, const ASN1_OBJECT *, int);
+int OBJ_cmp(const ASN1_OBJECT *, const ASN1_OBJECT *);
+ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *);
+int OBJ_create(const char *, const char *, const char *);
+void OBJ_cleanup();
+"""
+
+MACROS = """
+"""
+
+CUSTOMIZATIONS = """
+"""
+
+CONDITIONAL_NAMES = {}
diff --git a/cryptography/hazmat/backends/openssl/rsa.py b/cryptography/hazmat/backends/openssl/rsa.py
index e3a24d0..6cee569 100644
--- a/cryptography/hazmat/backends/openssl/rsa.py
+++ b/cryptography/hazmat/backends/openssl/rsa.py
@@ -33,6 +33,7 @@
 static const int RSA_NO_PADDING;
 static const int RSA_PKCS1_OAEP_PADDING;
 static const int RSA_X931_PADDING;
+static const int RSA_F4;
 """
 
 FUNCTIONS = """
@@ -50,6 +51,7 @@
                        RSA *, int);
 int RSA_private_decrypt(int, const unsigned char *, unsigned char *,
                         RSA *, int);
+int RSA_print(BIO *, const RSA *, int);
 """
 
 MACROS = """
diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py
index 618bccc..76d658a 100644
--- a/cryptography/hazmat/primitives/hmac.py
+++ b/cryptography/hazmat/primitives/hmac.py
@@ -16,8 +16,8 @@
 import six
 
 from cryptography import utils
-from cryptography.exceptions import AlreadyFinalized
-from cryptography.hazmat.primitives import interfaces
+from cryptography.exceptions import AlreadyFinalized, InvalidSignature
+from cryptography.hazmat.primitives import constant_time, interfaces
 
 
 @utils.register_interface(interfaces.HashContext)
@@ -57,3 +57,10 @@
         digest = self._ctx.finalize()
         self._ctx = None
         return digest
+
+    def verify(self, signature):
+        if isinstance(signature, six.text_type):
+            raise TypeError("Unicode-objects must be encoded before verifying")
+        digest = self.finalize()
+        if not constant_time.bytes_eq(digest, signature):
+            raise InvalidSignature("Signature did not match digest.")
diff --git a/docs/exceptions.rst b/docs/exceptions.rst
index 087066b..1fbd326 100644
--- a/docs/exceptions.rst
+++ b/docs/exceptions.rst
@@ -8,6 +8,12 @@
     This is raised when a context is used after being finalized.
 
 
+.. class:: InvalidSignature
+
+    This is raised when the verify method of a hash context does not
+    compare equal.
+
+
 .. class:: NotYetFinalized
 
     This is raised when the AEAD tag property is accessed on a context
diff --git a/docs/hazmat/primitives/hmac.rst b/docs/hazmat/primitives/hmac.rst
index 0547b7d..b8f94fd 100644
--- a/docs/hazmat/primitives/hmac.rst
+++ b/docs/hazmat/primitives/hmac.rst
@@ -71,3 +71,11 @@
 
         :return bytes: The message digest as bytes.
         :raises cryptography.exceptions.AlreadyFinalized:
+
+    .. method:: verify(signature)
+
+        Finalize the current context and securely compare digest to ``signature``.
+
+        :param bytes signature: The bytes of the HMAC signature recieved.
+        :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`
+        :raises cryptography.exceptions.InvalidSignature: If signature does not match digest
diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py
index 6d8cc27..7acb78b 100644
--- a/tests/hazmat/primitives/test_hmac.py
+++ b/tests/hazmat/primitives/test_hmac.py
@@ -20,7 +20,9 @@
 import six
 
 from cryptography import utils
-from cryptography.exceptions import AlreadyFinalized, UnsupportedAlgorithm
+from cryptography.exceptions import (
+    AlreadyFinalized, UnsupportedAlgorithm, InvalidSignature
+)
 from cryptography.hazmat.primitives import hashes, hmac, interfaces
 
 from .utils import generate_base_hmac_test
@@ -71,6 +73,29 @@
         with pytest.raises(AlreadyFinalized):
             h.finalize()
 
+    def test_verify(self, backend):
+        h = hmac.HMAC(b'', hashes.SHA1(), backend=backend)
+        digest = h.finalize()
+
+        h = hmac.HMAC(b'', hashes.SHA1(), backend=backend)
+        h.verify(digest)
+
+        with pytest.raises(AlreadyFinalized):
+            h.verify(b'')
+
+    def test_invalid_verify(self, backend):
+        h = hmac.HMAC(b'', hashes.SHA1(), backend=backend)
+        with pytest.raises(InvalidSignature):
+            h.verify(b'')
+
+        with pytest.raises(AlreadyFinalized):
+            h.verify(b'')
+
+    def test_verify_reject_unicode(self, backend):
+        h = hmac.HMAC(b'', hashes.SHA1(), backend=backend)
+        with pytest.raises(TypeError):
+            h.verify(six.u(''))
+
     def test_unsupported_hash(self, backend):
         with pytest.raises(UnsupportedAlgorithm):
             hmac.HMAC(b"key", UnsupportedDummyHash(), backend)