Merge third_party/boringssl/src from https://boringssl.googlesource.com/boringssl.git at 7ea848165b89577c6e9a1ef12a2cdff9d1beb71f

This commit was generated by merge_from_chromium.py.

Change-Id: I331e436a65b8a47efd6889d5786626b1e776d58e
diff --git a/crypto/asn1/asn1_error.c b/crypto/asn1/asn1_error.c
index 12692a0..81b9aff 100644
--- a/crypto/asn1/asn1_error.c
+++ b/crypto/asn1/asn1_error.c
@@ -193,7 +193,6 @@
   {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE), "UNKNOWN_PUBLIC_KEY_TYPE"},
   {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM), "UNKNOWN_SIGNATURE_ALGORITHM"},
   {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_TAG), "UNKNOWN_TAG"},
-  {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKOWN_FORMAT), "UNKOWN_FORMAT"},
   {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE), "UNSUPPORTED_ANY_DEFINED_BY_TYPE"},
   {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_CIPHER), "UNSUPPORTED_CIPHER"},
   {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM), "UNSUPPORTED_ENCRYPTION_ALGORITHM"},
diff --git a/crypto/engine/CMakeLists.txt b/crypto/engine/CMakeLists.txt
index 5126e2a..5458ff5 100644
--- a/crypto/engine/CMakeLists.txt
+++ b/crypto/engine/CMakeLists.txt
@@ -6,4 +6,5 @@
 	OBJECT
 
 	engine.c
+	engine_error.c
 )
diff --git a/crypto/engine/engine.c b/crypto/engine/engine.c
index c9b8823..1453e61 100644
--- a/crypto/engine/engine.c
+++ b/crypto/engine/engine.c
@@ -17,6 +17,7 @@
 #include <openssl/dh.h>
 #include <openssl/dsa.h>
 #include <openssl/ec_key.h>
+#include <openssl/err.h>
 #include <openssl/mem.h>
 #include <openssl/rsa.h>
 #include <openssl/thread.h>
@@ -131,3 +132,5 @@
     OPENSSL_free(method);
   }
 }
+
+OPENSSL_DECLARE_ERROR_REASON(ENGINE, OPERATION_NOT_SUPPORTED);
diff --git a/crypto/engine/engine_error.c b/crypto/engine/engine_error.c
new file mode 100644
index 0000000..9f65f70
--- /dev/null
+++ b/crypto/engine/engine_error.c
@@ -0,0 +1,22 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/err.h>
+
+#include <openssl/engine.h>
+
+const ERR_STRING_DATA ENGINE_error_string_data[] = {
+  {ERR_PACK(ERR_LIB_ENGINE, 0, ENGINE_R_OPERATION_NOT_SUPPORTED), "OPERATION_NOT_SUPPORTED"},
+  {0, NULL},
+};
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 7ca2842..3c5ea99 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -168,7 +168,7 @@
 }
 
 static uint32_t get_error_values(int inc, int top, const char **file, int *line,
-                                 char **data, int *flags) {
+                                 const char **data, int *flags) {
   unsigned i = 0;
   ERR_STATE *state;
   struct err_error_st *error;
@@ -211,6 +211,12 @@
       if (flags != NULL) {
         *flags = error->flags & ERR_FLAG_PUBLIC_MASK;
       }
+      if (error->flags & ERR_FLAG_MALLOCED) {
+        if (state->to_free) {
+          OPENSSL_free(state->to_free);
+        }
+        state->to_free = error->data;
+      }
       error->data = NULL;
       error->flags = 0;
     }
@@ -234,7 +240,7 @@
 }
 
 uint32_t ERR_get_error_line_data(const char **file, int *line,
-                                 char **data, int *flags) {
+                                 const char **data, int *flags) {
   return get_error_values(1, 0, file, line, data, flags);
 }
 
@@ -248,7 +254,7 @@
 
 uint32_t ERR_peek_error_line_data(const char **file, int *line,
                                   const char **data, int *flags) {
-  return get_error_values(0, 0, file, line, (char **) data, flags);
+  return get_error_values(0, 0, file, line, data, flags);
 }
 
 uint32_t ERR_peek_last_error(void) {
@@ -261,7 +267,7 @@
 
 uint32_t ERR_peek_last_error_line_data(const char **file, int *line,
                                        const char **data, int *flags) {
-  return get_error_values(0, 1, file, line, (char **) data, flags);
+  return get_error_values(0, 1, file, line, data, flags);
 }
 
 void ERR_clear_error(void) {
@@ -271,6 +277,10 @@
   for (i = 0; i < ERR_NUM_ERRORS; i++) {
     err_clear(&state->errors[i]);
   }
+  if (state->to_free) {
+    OPENSSL_free(state->to_free);
+    state->to_free = NULL;
+  }
 
   state->top = state->bottom = 0;
 }
@@ -294,7 +304,9 @@
   for (i = 0; i < ERR_NUM_ERRORS; i++) {
     err_clear(&state->errors[i]);
   }
-
+  if (state->to_free) {
+    OPENSSL_free(state->to_free);
+  }
   OPENSSL_free(state);
 }
 
@@ -433,8 +445,7 @@
   char buf[ERR_ERROR_STRING_BUF_LEN];
   char buf2[1024];
   unsigned long thread_hash;
-  const char *file;
-  char *data;
+  const char *file, *data;
   int line, flags;
   uint32_t packed_error;
 
@@ -453,9 +464,6 @@
     if (callback(buf2, strlen(buf2), ctx) <= 0) {
       break;
     }
-    if (flags & ERR_FLAG_MALLOCED) {
-      OPENSSL_free(data);
-    }
   }
 }
 
@@ -691,6 +699,7 @@
 extern const ERR_STRING_DATA ECDH_error_string_data[];
 extern const ERR_STRING_DATA ECDSA_error_string_data[];
 extern const ERR_STRING_DATA EC_error_string_data[];
+extern const ERR_STRING_DATA ENGINE_error_string_data[];
 extern const ERR_STRING_DATA EVP_error_string_data[];
 extern const ERR_STRING_DATA OBJ_error_string_data[];
 extern const ERR_STRING_DATA PEM_error_string_data[];
@@ -744,6 +753,7 @@
   ERR_load_strings(ECDH_error_string_data);
   ERR_load_strings(ECDSA_error_string_data);
   ERR_load_strings(EC_error_string_data);
+  ERR_load_strings(ENGINE_error_string_data);
   ERR_load_strings(EVP_error_string_data);
   ERR_load_strings(OBJ_error_string_data);
   ERR_load_strings(PEM_error_string_data);
diff --git a/crypto/err/err_test.c b/crypto/err/err_test.c
index 230cada..ed0156a 100644
--- a/crypto/err/err_test.c
+++ b/crypto/err/err_test.c
@@ -44,8 +44,7 @@
 static int test_put_error(void) {
   uint32_t packed_error;
   int line, flags;
-  const char *file;
-  char *data;
+  const char *file, *data;
 
   if (ERR_get_error() != 0) {
     fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
@@ -59,7 +58,6 @@
   if (strcmp(file, "test") != 0 ||
       line != 4 ||
       (flags & ERR_FLAG_STRING) == 0 ||
-      (flags & ERR_FLAG_MALLOCED) == 0 ||
       ERR_GET_LIB(packed_error) != 1 ||
       ERR_GET_FUNC(packed_error) != 2 ||
       ERR_GET_REASON(packed_error) != 3 ||
@@ -68,8 +66,6 @@
     return 0;
   }
 
-  OPENSSL_free(data);
-
   return 1;
 }
 
diff --git a/crypto/evp/CMakeLists.txt b/crypto/evp/CMakeLists.txt
index c3d8d8a..43e351a 100644
--- a/crypto/evp/CMakeLists.txt
+++ b/crypto/evp/CMakeLists.txt
@@ -5,6 +5,7 @@
 
 	OBJECT
 
+	algorithm.c
 	asn1.c
 	digestsign.c
 	evp.c
diff --git a/crypto/evp/algorithm.c b/crypto/evp/algorithm.c
new file mode 100644
index 0000000..4ec111b
--- /dev/null
+++ b/crypto/evp/algorithm.c
@@ -0,0 +1,162 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/evp.h>
+
+#include <assert.h>
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+#include "internal.h"
+
+
+/* These functions use error codes under the ASN1 and X509 namespaces for
+ * compatibility with OpenSSL. */
+
+int EVP_DigestSignAlgorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
+  const EVP_MD *digest;
+  EVP_PKEY *pkey;
+  int sign_nid, paramtype;
+
+  digest = EVP_MD_CTX_md(ctx);
+  pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+  if (!digest || !pkey) {
+    OPENSSL_PUT_ERROR(EVP, EVP_DigestSignAlgorithm,
+                      EVP_R_CONTEXT_NOT_INITIALISED);
+    return 0;
+  }
+
+  if (pkey->ameth->digest_sign_algorithm) {
+    switch (pkey->ameth->digest_sign_algorithm(ctx, algor)) {
+      case EVP_DIGEST_SIGN_ALGORITHM_ERROR:
+        return 0;
+      case EVP_DIGEST_SIGN_ALGORITHM_SUCCESS:
+        return 1;
+      case EVP_DIGEST_SIGN_ALGORITHM_DEFAULT:
+        /* Use default behavior. */
+        break;
+      default:
+        assert(0);
+    }
+  }
+
+  /* Default behavior: look up the OID for the algorithm/hash pair and encode
+   * that. */
+  if (!OBJ_find_sigid_by_algs(&sign_nid, EVP_MD_type(digest),
+                              pkey->ameth->pkey_id)) {
+    OPENSSL_PUT_ERROR(EVP, EVP_DigestSignAlgorithm,
+                      X509_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+    return 0;
+  }
+
+  if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) {
+    paramtype = V_ASN1_NULL;
+  } else {
+    paramtype = V_ASN1_UNDEF;
+  }
+
+  X509_ALGOR_set0(algor, OBJ_nid2obj(sign_nid), paramtype, NULL);
+  return 1;
+}
+
+int EVP_DigestVerifyInitFromAlgorithm(EVP_MD_CTX *ctx,
+                                      X509_ALGOR *algor,
+                                      EVP_PKEY *pkey) {
+  int digest_nid, pkey_nid;
+  const EVP_PKEY_ASN1_METHOD *ameth;
+  const EVP_MD *digest;
+
+  /* Convert signature OID into digest and public key OIDs */
+  if (!OBJ_find_sigid_algs(OBJ_obj2nid(algor->algorithm), &digest_nid,
+                           &pkey_nid)) {
+    OPENSSL_PUT_ERROR(EVP, EVP_DigestVerifyInitFromAlgorithm,
+                      ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
+    return 0;
+  }
+
+  /* Check public key OID matches public key type */
+  ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
+  if (ameth == NULL || ameth->pkey_id != pkey->ameth->pkey_id) {
+    OPENSSL_PUT_ERROR(EVP, EVP_DigestVerifyInitFromAlgorithm,
+                      ASN1_R_WRONG_PUBLIC_KEY_TYPE);
+    return 0;
+  }
+
+  /* NID_undef signals that there are custom parameters to set. */
+  if (digest_nid == NID_undef) {
+    if (!pkey->ameth || !pkey->ameth->digest_verify_init_from_algorithm) {
+      OPENSSL_PUT_ERROR(EVP, EVP_DigestVerifyInitFromAlgorithm,
+                        ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
+      return 0;
+    }
+
+    return pkey->ameth->digest_verify_init_from_algorithm(ctx, algor, pkey);
+  }
+
+  /* Otherwise, initialize with the digest from the OID. */
+  digest = EVP_get_digestbynid(digest_nid);
+  if (digest == NULL) {
+    OPENSSL_PUT_ERROR(EVP, EVP_DigestVerifyInitFromAlgorithm,
+                      ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+    return 0;
+  }
+
+  return EVP_DigestVerifyInit(ctx, NULL, digest, NULL, pkey);
+}
+
diff --git a/crypto/evp/evp_error.c b/crypto/evp/evp_error.c
index 76a802a..fae1aa7 100644
--- a/crypto/evp/evp_error.c
+++ b/crypto/evp/evp_error.c
@@ -17,6 +17,8 @@
 #include <openssl/evp.h>
 
 const ERR_STRING_DATA EVP_error_string_data[] = {
+  {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DigestSignAlgorithm, 0), "EVP_DigestSignAlgorithm"},
+  {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DigestVerifyInitFromAlgorithm, 0), "EVP_DigestVerifyInitFromAlgorithm"},
   {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_ctrl, 0), "EVP_PKEY_CTX_ctrl"},
   {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_copy_parameters, 0), "EVP_PKEY_copy_parameters"},
   {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_decrypt, 0), "EVP_PKEY_decrypt"},
@@ -74,6 +76,7 @@
   {ERR_PACK(ERR_LIB_EVP, EVP_F_rsa_pub_decode, 0), "rsa_pub_decode"},
   {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BUFFER_TOO_SMALL), "BUFFER_TOO_SMALL"},
   {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_COMMAND_NOT_SUPPORTED), "COMMAND_NOT_SUPPORTED"},
+  {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CONTEXT_NOT_INITIALISED), "CONTEXT_NOT_INITIALISED"},
   {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DECODE_ERROR), "DECODE_ERROR"},
   {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIFFERENT_KEY_TYPES), "DIFFERENT_KEY_TYPES"},
   {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIFFERENT_PARAMETERS), "DIFFERENT_PARAMETERS"},
diff --git a/crypto/evp/example_sign.c b/crypto/evp/example_sign.c
index c25ef2a..42a19ec 100644
--- a/crypto/evp/example_sign.c
+++ b/crypto/evp/example_sign.c
@@ -17,10 +17,13 @@
 #include <stdlib.h>
 
 #include <openssl/bio.h>
+#include <openssl/bytestring.h>
 #include <openssl/crypto.h>
 #include <openssl/digest.h>
+#include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/rsa.h>
+#include <openssl/x509.h>
 
 
 /* kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you
@@ -95,26 +98,104 @@
     0x55, 0xa7, 0xab, 0x45, 0x02, 0x97, 0x60, 0x42,
 };
 
+/* kExamplePSSCert is an example self-signed certificate, signed with
+ * kExampleRSAKeyDER using RSA-PSS with default hash functions. */
+static const uint8_t kExamplePSSCert[] = {
+    0x30, 0x82, 0x02, 0x62, 0x30, 0x82, 0x01, 0xc6, 0xa0, 0x03, 0x02, 0x01,
+    0x02, 0x02, 0x09, 0x00, 0x8d, 0xea, 0x53, 0x24, 0xfa, 0x48, 0x87, 0xf3,
+    0x30, 0x12, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+    0x0a, 0x30, 0x05, 0xa2, 0x03, 0x02, 0x01, 0x6a, 0x30, 0x45, 0x31, 0x0b,
+    0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31,
+    0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f,
+    0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f,
+    0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+    0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20,
+    0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+    0x34, 0x31, 0x30, 0x30, 0x39, 0x31, 0x39, 0x30, 0x39, 0x35, 0x35, 0x5a,
+    0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, 0x30, 0x39, 0x31, 0x39, 0x30, 0x39,
+    0x35, 0x35, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+    0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+    0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+    0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+    0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+    0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+    0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+    0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
+    0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xf8, 0xb8, 0x6c, 0x83, 0xb4,
+    0xbc, 0xd9, 0xa8, 0x57, 0xc0, 0xa5, 0xb4, 0x59, 0x76, 0x8c, 0x54, 0x1d,
+    0x79, 0xeb, 0x22, 0x52, 0x04, 0x7e, 0xd3, 0x37, 0xeb, 0x41, 0xfd, 0x83,
+    0xf9, 0xf0, 0xa6, 0x85, 0x15, 0x34, 0x75, 0x71, 0x5a, 0x84, 0xa8, 0x3c,
+    0xd2, 0xef, 0x5a, 0x4e, 0xd3, 0xde, 0x97, 0x8a, 0xdd, 0xff, 0xbb, 0xcf,
+    0x0a, 0xaa, 0x86, 0x92, 0xbe, 0xb8, 0x50, 0xe4, 0xcd, 0x6f, 0x80, 0x33,
+    0x30, 0x76, 0x13, 0x8f, 0xca, 0x7b, 0xdc, 0xec, 0x5a, 0xca, 0x63, 0xc7,
+    0x03, 0x25, 0xef, 0xa8, 0x8a, 0x83, 0x58, 0x76, 0x20, 0xfa, 0x16, 0x77,
+    0xd7, 0x79, 0x92, 0x63, 0x01, 0x48, 0x1a, 0xd8, 0x7b, 0x67, 0xf1, 0x52,
+    0x55, 0x49, 0x4e, 0xd6, 0x6e, 0x4a, 0x5c, 0xd7, 0x7a, 0x37, 0x36, 0x0c,
+    0xde, 0xdd, 0x8f, 0x44, 0xe8, 0xc2, 0xa7, 0x2c, 0x2b, 0xb5, 0xaf, 0x64,
+    0x4b, 0x61, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e,
+    0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xd0,
+    0x41, 0xfb, 0x89, 0x41, 0x1e, 0xa7, 0xad, 0x5a, 0xec, 0x34, 0x5d, 0x49,
+    0x11, 0xf9, 0x55, 0x81, 0x78, 0x1f, 0x13, 0x30, 0x1f, 0x06, 0x03, 0x55,
+    0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xd0, 0x41, 0xfb, 0x89,
+    0x41, 0x1e, 0xa7, 0xad, 0x5a, 0xec, 0x34, 0x5d, 0x49, 0x11, 0xf9, 0x55,
+    0x81, 0x78, 0x1f, 0x13, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
+    0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x12, 0x06, 0x09, 0x2a, 0x86,
+    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x05, 0xa2, 0x03, 0x02,
+    0x01, 0x6a, 0x03, 0x81, 0x81, 0x00, 0x49, 0x4c, 0xb6, 0x45, 0x97, 0x20,
+    0x35, 0xb3, 0x50, 0x64, 0x0d, 0x3f, 0xec, 0x5f, 0x95, 0xd5, 0x84, 0xcb,
+    0x11, 0x7c, 0x03, 0xd7, 0xa6, 0xe6, 0xfa, 0x24, 0x95, 0x9f, 0x31, 0xb0,
+    0xb5, 0xec, 0x66, 0x41, 0x51, 0x18, 0x21, 0x91, 0xbb, 0xe0, 0xaf, 0xf0,
+    0xc5, 0xb7, 0x59, 0x41, 0xd4, 0xdb, 0xa4, 0xd2, 0x64, 0xa7, 0x54, 0x0f,
+    0x8c, 0xf7, 0xe1, 0xd3, 0x3b, 0x1a, 0xb7, 0x0e, 0x9d, 0x9a, 0xde, 0x50,
+    0xa1, 0x9f, 0x0a, 0xf0, 0xda, 0x34, 0x0e, 0x34, 0x7d, 0x76, 0x07, 0xfe,
+    0x5a, 0xfb, 0xf9, 0x58, 0x9b, 0xc9, 0x50, 0x84, 0x01, 0xa0, 0x05, 0x4d,
+    0x67, 0x42, 0x0b, 0xf8, 0xe4, 0x05, 0xcf, 0xaf, 0x8b, 0x71, 0x31, 0xf1,
+    0x0f, 0x6e, 0xc9, 0x24, 0x27, 0x9b, 0xac, 0x04, 0xd7, 0x64, 0x0d, 0x30,
+    0x4e, 0x11, 0x93, 0x40, 0x39, 0xbb, 0x72, 0xb2, 0xfe, 0x6b, 0xe4, 0xae,
+    0x8c, 0x16,
+};
 
-int example_EVP_DigestSignInit(void) {
-  int ret = 0;
+static EVP_PKEY *load_example_rsa_key(void) {
+  EVP_PKEY *ret = NULL;
+  const uint8_t *derp = kExampleRSAKeyDER;
   EVP_PKEY *pkey = NULL;
   RSA *rsa = NULL;
-  const uint8_t *derp = kExampleRSAKeyDER;
-  uint8_t *sig = NULL;
-  size_t sig_len = 0;
-  EVP_MD_CTX md_ctx;
-
-  EVP_MD_CTX_init(&md_ctx);
 
   if (!d2i_RSAPrivateKey(&rsa, &derp, sizeof(kExampleRSAKeyDER))) {
-    goto out;
+    return NULL;
   }
 
   pkey = EVP_PKEY_new();
-  sig = malloc(sig_len);
+  if (pkey == NULL || !EVP_PKEY_set1_RSA(pkey, rsa)) {
+    goto out;
+  }
+
+  ret = pkey;
+  pkey = NULL;
+
+out:
+  if (pkey) {
+    EVP_PKEY_free(pkey);
+  }
+  if (rsa) {
+    RSA_free(rsa);
+  }
+
+  return ret;
+}
+
+static int example_EVP_DigestSignInit(void) {
+  int ret = 0;
+  EVP_PKEY *pkey = NULL;
+  uint8_t *sig = NULL;
+  size_t sig_len = 0;
+  EVP_MD_CTX md_ctx, md_ctx_verify;
+
+  EVP_MD_CTX_init(&md_ctx);
+  EVP_MD_CTX_init(&md_ctx_verify);
+
+  pkey = load_example_rsa_key();
   if (pkey == NULL ||
-      !EVP_PKEY_set1_RSA(pkey, rsa) ||
       EVP_DigestSignInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1 ||
       EVP_DigestSignUpdate(&md_ctx, kMsg, sizeof(kMsg)) != 1) {
     goto out;
@@ -124,17 +205,20 @@
     goto out;
   }
   /* Sanity check for testing. */
-  if (sig_len != RSA_size(rsa)) {
+  if (sig_len != EVP_PKEY_size(pkey)) {
     fprintf(stderr, "sig_len mismatch\n");
     goto out;
   }
 
   sig = malloc(sig_len);
-  if (sig == NULL) {
+  if (sig == NULL || EVP_DigestSignFinal(&md_ctx, sig, &sig_len) != 1) {
     goto out;
   }
-  if (EVP_DigestSignFinal(&md_ctx, sig, &sig_len) != 1) {
-    free(sig);
+
+  /* Ensure that the signature round-trips. */
+  if (EVP_DigestVerifyInit(&md_ctx_verify, NULL, EVP_sha256(), NULL, pkey) != 1 ||
+      EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg)) != 1 ||
+      EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len) != 1) {
     goto out;
   }
 
@@ -146,12 +230,10 @@
   }
 
   EVP_MD_CTX_cleanup(&md_ctx);
+  EVP_MD_CTX_cleanup(&md_ctx_verify);
   if (pkey) {
     EVP_PKEY_free(pkey);
   }
-  if (rsa) {
-    RSA_free(rsa);
-  }
   if (sig) {
     free(sig);
   }
@@ -159,22 +241,15 @@
   return ret;
 }
 
-int example_EVP_DigestVerifyInit(void) {
+static int example_EVP_DigestVerifyInit(void) {
   int ret = 0;
   EVP_PKEY *pkey = NULL;
-  RSA *rsa = NULL;
-  const uint8_t *derp = kExampleRSAKeyDER;
   EVP_MD_CTX md_ctx;
 
   EVP_MD_CTX_init(&md_ctx);
 
-  if (!d2i_RSAPrivateKey(&rsa, &derp, sizeof(kExampleRSAKeyDER))) {
-    goto out;
-  }
-
-  pkey = EVP_PKEY_new();
+  pkey = load_example_rsa_key();
   if (pkey == NULL ||
-      !EVP_PKEY_set1_RSA(pkey, rsa) ||
       EVP_DigestVerifyInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1 ||
       EVP_DigestVerifyUpdate(&md_ctx, kMsg, sizeof(kMsg)) != 1 ||
       EVP_DigestVerifyFinal(&md_ctx, kSignature, sizeof(kSignature)) != 1) {
@@ -191,8 +266,169 @@
   if (pkey) {
     EVP_PKEY_free(pkey);
   }
-  if (rsa) {
-    RSA_free(rsa);
+
+  return ret;
+}
+
+/* test_algorithm_roundtrip signs a message using an already-initialized
+ * |md_ctx|, sampling the AlgorithmIdentifier. It then uses |pkey| and the
+ * AlgorithmIdentifier to verify the signature. */
+static int test_algorithm_roundtrip(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
+  int ret = 0;
+  uint8_t *sig = NULL;
+  size_t sig_len = 0;
+  EVP_MD_CTX md_ctx_verify;
+  X509_ALGOR *algor = NULL;
+
+  EVP_MD_CTX_init(&md_ctx_verify);
+
+  if (EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg)) != 1) {
+    goto out;
+  }
+
+  /* Save the algorithm. */
+  algor = X509_ALGOR_new();
+  if (algor == NULL || !EVP_DigestSignAlgorithm(md_ctx, algor)) {
+    goto out;
+  }
+
+  /* Determine the size of the signature. */
+  if (EVP_DigestSignFinal(md_ctx, NULL, &sig_len) != 1) {
+    goto out;
+  }
+  /* Sanity check for testing. */
+  if (sig_len != EVP_PKEY_size(pkey)) {
+    fprintf(stderr, "sig_len mismatch\n");
+    goto out;
+  }
+
+  sig = malloc(sig_len);
+  if (sig == NULL || EVP_DigestSignFinal(md_ctx, sig, &sig_len) != 1) {
+    goto out;
+  }
+
+  /* Ensure that the signature round-trips. */
+  if (EVP_DigestVerifyInitFromAlgorithm(&md_ctx_verify, algor, pkey) != 1 ||
+      EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg)) != 1 ||
+      EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len) != 1) {
+    goto out;
+  }
+
+  ret = 1;
+
+out:
+  EVP_MD_CTX_cleanup(&md_ctx_verify);
+  if (sig) {
+    free(sig);
+  }
+  if (algor) {
+    X509_ALGOR_free(algor);
+  }
+
+  return ret;
+}
+
+static int test_EVP_DigestSignAlgorithm(void) {
+  int ret = 0;
+  EVP_PKEY *pkey = NULL;
+  EVP_MD_CTX md_ctx;
+  EVP_PKEY_CTX *pkey_ctx;
+
+  EVP_MD_CTX_init(&md_ctx);
+
+  pkey = load_example_rsa_key();
+  if (pkey == NULL) {
+    goto out;
+  }
+
+  /* Test a simple AlgorithmIdentifier. */
+  if (EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) != 1 ||
+      !test_algorithm_roundtrip(&md_ctx, pkey)) {
+    fprintf(stderr, "RSA with SHA-256 failed\n");
+    goto out;
+  }
+
+  EVP_MD_CTX_cleanup(&md_ctx);
+  EVP_MD_CTX_init(&md_ctx);
+
+  /* Test RSA-PSS with custom parameters. */
+  if (EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) != 1 ||
+      EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1 ||
+      EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) != 1 ||
+      !test_algorithm_roundtrip(&md_ctx, pkey)) {
+    fprintf(stderr, "RSA-PSS failed\n");
+    goto out;
+  }
+
+  ret = 1;
+
+out:
+  if (!ret) {
+    BIO_print_errors_fp(stderr);
+  }
+
+  EVP_MD_CTX_cleanup(&md_ctx);
+  if (pkey) {
+    EVP_PKEY_free(pkey);
+  }
+
+  return ret;
+}
+
+static int example_EVP_DigestVerifyInitFromAlgorithm(void) {
+  int ret = 0;
+  CBS cert, cert_body, tbs_cert, algorithm, signature;
+  uint8_t padding;
+  X509_ALGOR *algor = NULL;
+  const uint8_t *derp;
+  EVP_PKEY *pkey = NULL;
+  EVP_MD_CTX md_ctx;
+
+  EVP_MD_CTX_init(&md_ctx);
+
+  CBS_init(&cert, kExamplePSSCert, sizeof(kExamplePSSCert));
+  if (!CBS_get_asn1(&cert, &cert_body, CBS_ASN1_SEQUENCE) ||
+      CBS_len(&cert) != 0 ||
+      !CBS_get_any_asn1_element(&cert_body, &tbs_cert, NULL, NULL) ||
+      !CBS_get_asn1_element(&cert_body, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1(&cert_body, &signature, CBS_ASN1_BITSTRING) ||
+      CBS_len(&cert_body) != 0) {
+    fprintf(stderr, "Failed to parse certificate\n");
+    goto out;
+  }
+
+  /* Signatures are BIT STRINGs, but they have are multiple of 8 bytes, so the
+     leading phase byte is just a zero. */
+  if (!CBS_get_u8(&signature, &padding) || padding != 0) {
+    fprintf(stderr, "Invalid signature padding\n");
+    goto out;
+  }
+
+  derp = CBS_data(&algorithm);
+  if (!d2i_X509_ALGOR(&algor, &derp, CBS_len(&algorithm)) ||
+      derp != CBS_data(&algorithm) + CBS_len(&algorithm)) {
+    fprintf(stderr, "Failed to parse algorithm\n");
+  }
+
+  pkey = load_example_rsa_key();
+  if (pkey == NULL ||
+      EVP_DigestVerifyInitFromAlgorithm(&md_ctx, algor, pkey) != 1||
+      EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&tbs_cert),
+                             CBS_len(&tbs_cert)) != 1 ||
+      EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature),
+                            CBS_len(&signature)) != 1) {
+    goto out;
+  }
+  ret = 1;
+
+out:
+  if (!ret) {
+    BIO_print_errors_fp(stderr);
+  }
+
+  EVP_MD_CTX_cleanup(&md_ctx);
+  if (pkey) {
+    EVP_PKEY_free(pkey);
   }
 
   return ret;
@@ -200,6 +436,7 @@
 
 int main(void) {
   CRYPTO_library_init();
+  ERR_load_crypto_strings();
 
   if (!example_EVP_DigestSignInit()) {
     fprintf(stderr, "EVP_DigestSignInit failed\n");
@@ -211,6 +448,16 @@
     return 1;
   }
 
+  if (!test_EVP_DigestSignAlgorithm()) {
+    fprintf(stderr, "EVP_DigestSignInit failed\n");
+    return 1;
+  }
+
+  if (!example_EVP_DigestVerifyInitFromAlgorithm()) {
+    fprintf(stderr, "EVP_DigestVerifyInitFromAlgorithm failed\n");
+    return 1;
+  }
+
   printf("PASS\n");
   return 0;
 }
diff --git a/crypto/evp/internal.h b/crypto/evp/internal.h
index 36755f0..d92c9e5 100644
--- a/crypto/evp/internal.h
+++ b/crypto/evp/internal.h
@@ -67,8 +67,25 @@
 /* These values are flags for EVP_PKEY_ASN1_METHOD.flags. */
 #define ASN1_PKEY_ALIAS 0x1
 #define ASN1_PKEY_DYNAMIC 0x2
+
+/* ASN1_PKEY_SIGPARAM_NULL controls whether the default behavior of
+ * EVP_DigestSignAlgorithm writes an explicit NULL parameter in the
+ * AlgorithmIdentifier. */
 #define ASN1_PKEY_SIGPARAM_NULL 0x4
 
+/* evp_digest_sign_algorithm_result_t is the return value of the
+ * digest_sign_algorithm function in EVP_PKEY_ASN1_METHOD. */
+typedef enum {
+  /* EVP_DIGEST_SIGN_ALGORITHM_ERROR signals an error. */
+  EVP_DIGEST_SIGN_ALGORITHM_ERROR = 0,
+  /* EVP_DIGEST_SIGN_ALGORITHM_SUCCESS signals that the parameters were
+   * serialized in the AlgorithmIdentifier. */
+  EVP_DIGEST_SIGN_ALGORITHM_SUCCESS = 1,
+  /* EVP_DIGEST_SIGN_ALGORITHM_DEFAULT signals that the parameters are
+   * serialized using the default behavior. */
+  EVP_DIGEST_SIGN_ALGORITHM_DEFAULT = 2,
+} evp_digest_sign_algorithm_result_t;
+
 struct evp_pkey_asn1_method_st {
   int pkey_id;
   int pkey_base_id;
@@ -113,11 +130,14 @@
   int (*old_priv_decode)(EVP_PKEY *pkey, const unsigned char **pder,
                          int derlen);
   int (*old_priv_encode)(const EVP_PKEY *pkey, unsigned char **pder);
-  /* Custom ASN1 signature verification */
-  int (*item_verify)(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
-                     X509_ALGOR *a, ASN1_BIT_STRING *sig, EVP_PKEY *pkey);
-  int (*item_sign)(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
-                   X509_ALGOR *alg1, X509_ALGOR *alg2, ASN1_BIT_STRING *sig);
+
+  /* Converting parameters to/from AlgorithmIdentifier (X509_ALGOR). */
+  int (*digest_verify_init_from_algorithm)(EVP_MD_CTX *ctx,
+                                           X509_ALGOR *algor,
+                                           EVP_PKEY *pkey);
+  evp_digest_sign_algorithm_result_t (*digest_sign_algorithm)(
+      EVP_MD_CTX *ctx,
+      X509_ALGOR *algor);
 
 } /* EVP_PKEY_ASN1_METHOD */;
 
diff --git a/crypto/evp/p_rsa.c b/crypto/evp/p_rsa.c
index bcaca4b..1c42fbd 100644
--- a/crypto/evp/p_rsa.c
+++ b/crypto/evp/p_rsa.c
@@ -207,8 +207,8 @@
         if (!setup_tbuf(rctx, ctx) ||
             !RSA_padding_add_PKCS1_PSS_mgf1(rsa, rctx->tbuf, tbs, rctx->md,
                                             rctx->mgf1md, rctx->saltlen) ||
-            !RSA_encrypt(rsa, siglen, sig, *siglen, rctx->tbuf, key_len,
-                         RSA_NO_PADDING)) {
+            !RSA_sign_raw(rsa, siglen, sig, *siglen, rctx->tbuf, key_len,
+                          RSA_NO_PADDING)) {
           return 0;
         }
         return 1;
diff --git a/crypto/evp/p_rsa_asn1.c b/crypto/evp/p_rsa_asn1.c
index a9334ab..ab83a8e 100644
--- a/crypto/evp/p_rsa_asn1.c
+++ b/crypto/evp/p_rsa_asn1.c
@@ -583,21 +583,19 @@
   return NULL;
 }
 
-/* From PSS AlgorithmIdentifier set public key parameters. If pkey
- * isn't NULL then the EVP_MD_CTX is setup and initalised. If it
- * is NULL parameters are passed to pkctx instead. */
-static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
-                          X509_ALGOR *sigalg, EVP_PKEY *pkey) {
-  int ret = -1;
+/* From PSS AlgorithmIdentifier set public key parameters. */
+static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) {
+  int ret = 0;
   int saltlen;
   const EVP_MD *mgf1md = NULL, *md = NULL;
   RSA_PSS_PARAMS *pss;
   X509_ALGOR *maskHash;
+  EVP_PKEY_CTX *pkctx;
 
   /* Sanity check: make sure it is PSS */
   if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
     OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_UNSUPPORTED_SIGNATURE_TYPE);
-    return -1;
+    return 0;
   }
   /* Decode PSS parameters */
   pss = rsa_pss_decode(sigalg, &maskHash);
@@ -634,22 +632,8 @@
     goto err;
   }
 
-  if (pkey) {
-    if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey)) {
-      goto err;
-    }
-  } else {
-    const EVP_MD *checkmd;
-    if (EVP_PKEY_CTX_get_signature_md(pkctx, &checkmd) <= 0) {
-      goto err;
-    }
-    if (EVP_MD_type(md) != EVP_MD_type(checkmd)) {
-      OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_DIGEST_DOES_NOT_MATCH);
-      goto err;
-    }
-  }
-
-  if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0 ||
+  if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) ||
+      EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0 ||
       EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0 ||
       EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) {
     goto err;
@@ -665,54 +649,37 @@
   return ret;
 }
 
-/* Customised RSA item verification routine. This is called
- * when a signature is encountered requiring special handling. We
- * currently only handle PSS. */
-static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
-                           X509_ALGOR *sigalg, ASN1_BIT_STRING *sig,
-                           EVP_PKEY *pkey) {
+/* Customised RSA AlgorithmIdentifier handling. This is called when a signature
+ * is encountered requiring special handling. We currently only handle PSS. */
+static int rsa_digest_verify_init_from_algorithm(EVP_MD_CTX *ctx,
+                                                 X509_ALGOR *sigalg,
+                                                 EVP_PKEY *pkey) {
   /* Sanity check: make sure it is PSS */
   if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
     OPENSSL_PUT_ERROR(EVP, rsa_item_verify, EVP_R_UNSUPPORTED_SIGNATURE_TYPE);
-    return -1;
+    return 0;
   }
-  if (rsa_pss_to_ctx(ctx, NULL, sigalg, pkey)) {
-    /* Carry on */
-    return 2;
-  }
-
-  return -1;
+  return rsa_pss_to_ctx(ctx, sigalg, pkey);
 }
 
-static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
-                         X509_ALGOR *alg1, X509_ALGOR *alg2,
-                         ASN1_BIT_STRING *sig) {
+static evp_digest_sign_algorithm_result_t rsa_digest_sign_algorithm(
+    EVP_MD_CTX *ctx, X509_ALGOR *sigalg) {
   int pad_mode;
   EVP_PKEY_CTX *pkctx = ctx->pctx;
   if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0) {
-    return 0;
-  }
-  if (pad_mode == RSA_PKCS1_PADDING) {
-    return 2;
+    return EVP_DIGEST_SIGN_ALGORITHM_ERROR;
   }
   if (pad_mode == RSA_PKCS1_PSS_PADDING) {
     ASN1_STRING *os1 = rsa_ctx_to_pss(pkctx);
     if (!os1) {
-      return 0;
+      return EVP_DIGEST_SIGN_ALGORITHM_ERROR;
     }
-    /* Duplicate parameters if we have to */
-    if (alg2) {
-      ASN1_STRING *os2 = ASN1_STRING_dup(os1);
-      if (!os2) {
-        ASN1_STRING_free(os1);
-        return 0;
-      }
-      X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os2);
-    }
-    X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os1);
-    return 3;
+    X509_ALGOR_set0(sigalg, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os1);
+    return EVP_DIGEST_SIGN_ALGORITHM_SUCCESS;
   }
-  return 2;
+
+  /* Other padding schemes use the default behavior. */
+  return EVP_DIGEST_SIGN_ALGORITHM_DEFAULT;
 }
 
 const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
@@ -746,8 +713,8 @@
   old_rsa_priv_decode,
   old_rsa_priv_encode,
 
-  rsa_item_verify,
-  rsa_item_sign,
+  rsa_digest_verify_init_from_algorithm,
+  rsa_digest_sign_algorithm,
 };
 
 const EVP_PKEY_ASN1_METHOD rsa_asn1_meth_2 = {
diff --git a/crypto/x509/a_digest.c b/crypto/x509/a_digest.c
index 9411dbc..6060bbd 100644
--- a/crypto/x509/a_digest.c
+++ b/crypto/x509/a_digest.c
@@ -65,7 +65,7 @@
 int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
 		unsigned char *md, unsigned int *len)
 	{
-	int i;
+	int i, ret;
 	unsigned char *str,*p;
 
 	i=i2d(data,NULL);
@@ -77,23 +77,21 @@
 	p=str;
 	i2d(data,&p);
 
-	if (!EVP_Digest(str, i, md, len, type, NULL))
-		return 0;
+	ret = EVP_Digest(str, i, md, len, type, NULL);
 	OPENSSL_free(str);
-	return(1);
+	return ret;
 	}
 
 int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
 		unsigned char *md, unsigned int *len)
 	{
-	int i;
+	int i, ret;
 	unsigned char *str = NULL;
 
 	i=ASN1_item_i2d(asn,&str, it);
 	if (!str) return(0);
 
-	if (!EVP_Digest(str, i, md, len, type, NULL))
-		return 0;
+	ret = EVP_Digest(str, i, md, len, type, NULL);
 	OPENSSL_free(str);
-	return(1);
+	return ret;
 	}
diff --git a/crypto/x509/a_sign.c b/crypto/x509/a_sign.c
index d35efe1..f219c23 100644
--- a/crypto/x509/a_sign.c
+++ b/crypto/x509/a_sign.c
@@ -65,97 +65,6 @@
 #include "../evp/internal.h"
 
 
-/* TODO(fork): this code appears to be dead. */
-#if 0
-#ifndef NO_ASN1_OLD
-
-int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
-	      ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey,
-	      const EVP_MD *type)
-	{
-	EVP_MD_CTX ctx;
-	unsigned char *p,*buf_in=NULL,*buf_out=NULL;
-	int i,inl=0,outl=0,outll=0;
-	X509_ALGOR *a;
-
-	EVP_MD_CTX_init(&ctx);
-	for (i=0; i<2; i++)
-		{
-		if (i == 0)
-			a=algor1;
-		else
-			a=algor2;
-		if (a == NULL) continue;
-                if (type->pkey_type == NID_dsaWithSHA1)
-			{
-			/* special case: RFC 2459 tells us to omit 'parameters'
-			 * with id-dsa-with-sha1 */
-			ASN1_TYPE_free(a->parameter);
-			a->parameter = NULL;
-			}
-		else if ((a->parameter == NULL) || 
-			(a->parameter->type != V_ASN1_NULL))
-			{
-			ASN1_TYPE_free(a->parameter);
-			if ((a->parameter=ASN1_TYPE_new()) == NULL) goto err;
-			a->parameter->type=V_ASN1_NULL;
-			}
-		ASN1_OBJECT_free(a->algorithm);
-		a->algorithm=OBJ_nid2obj(type->pkey_type);
-		if (a->algorithm == NULL)
-			{
-			OPENSSL_PUT_ERROR(ASN1, XXX, ASN1_R_UNKNOWN_OBJECT_TYPE);
-			goto err;
-			}
-		if (a->algorithm->length == 0)
-			{
-			OPENSSL_PUT_ERROR(ASN1, XXX, ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
-			goto err;
-			}
-		}
-	inl=i2d(data,NULL);
-	buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl);
-	outll=outl=EVP_PKEY_size(pkey);
-	buf_out=(unsigned char *)OPENSSL_malloc((unsigned int)outl);
-	if ((buf_in == NULL) || (buf_out == NULL))
-		{
-		outl=0;
-		OPENSSL_PUT_ERROR(ASN1, XXX, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
-	p=buf_in;
-
-	i2d(data,&p);
-	if (!EVP_SignInit_ex(&ctx,type, NULL)
-		|| !EVP_SignUpdate(&ctx,(unsigned char *)buf_in,inl)
-		|| !EVP_SignFinal(&ctx,(unsigned char *)buf_out,
-			(unsigned int *)&outl,pkey))
-		{
-		outl=0;
-		OPENSSL_PUT_ERROR(ASN1, XXX, ERR_R_EVP_LIB);
-		goto err;
-		}
-	if (signature->data != NULL) OPENSSL_free(signature->data);
-	signature->data=buf_out;
-	buf_out=NULL;
-	signature->length=outl;
-	/* In the interests of compatibility, I'll make sure that
-	 * the bit string has a 'not-used bits' value of 0
-	 */
-	signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
-	signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
-err:
-	EVP_MD_CTX_cleanup(&ctx);
-	if (buf_in != NULL)
-		{ OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
-	if (buf_out != NULL)
-		{ OPENSSL_cleanse((char *)buf_out,outll); OPENSSL_free(buf_out); }
-	return(outl);
-	}
-
-#endif
-#endif
-
 int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
 	     ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey,
 	     const EVP_MD *type)
@@ -175,65 +84,20 @@
 		X509_ALGOR *algor1, X509_ALGOR *algor2,
 	     	ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
 	{
-	const EVP_MD *type;
 	EVP_PKEY *pkey;
 	unsigned char *buf_in=NULL,*buf_out=NULL;
 	size_t inl=0,outl=0,outll=0;
-	int signid, paramtype;
-	int rv;
 
-	type = EVP_MD_CTX_md(ctx);
 	pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
 
-	if (!type || !pkey)
+	/* Write out the requested copies of the AlgorithmIdentifier. */
+	if (algor1 && !EVP_DigestSignAlgorithm(ctx, algor1))
 		{
-		OPENSSL_PUT_ERROR(X509, ASN1_item_sign_ctx, X509_R_CONTEXT_NOT_INITIALISED);
-		return 0;
+		goto err;
 		}
-
-	if (pkey->ameth->item_sign)
+	if (algor2 && !EVP_DigestSignAlgorithm(ctx, algor2))
 		{
-		rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2,
-						signature);
-		if (rv == 1)
-			outl = signature->length;
-		/* Return value meanings:
-		 * <=0: error.
-		 *   1: method does everything.
-		 *   2: carry on as normal.
-		 *   3: ASN1 method sets algorithm identifiers: just sign.
-		 */
-		if (rv <= 0)
-			OPENSSL_PUT_ERROR(X509, ASN1_item_sign_ctx, ERR_R_EVP_LIB);
-		if (rv <= 1)
-			goto err;
-		}
-	else
-		rv = 2;
-
-	if (rv == 2)
-		{
-		/* TODO(fork): EVP_MD_FLAG_PKEY_METHOD_SIGNATURE seems to mean
-		 * "is SHA". */
-		if (!pkey->ameth ||
-			!OBJ_find_sigid_by_algs(&signid,
-						EVP_MD_type(type),
-						pkey->ameth->pkey_id))
-			{
-			OPENSSL_PUT_ERROR(X509, ASN1_item_sign_ctx, X509_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
-			return 0;
-			}
-
-		if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
-			paramtype = V_ASN1_NULL;
-		else
-			paramtype = V_ASN1_UNDEF;
-
-		if (algor1)
-			X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
-		if (algor2)
-			X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);
-
+		goto err;
 		}
 
 	inl=ASN1_item_i2d(asn,&buf_in, it);
diff --git a/crypto/x509/a_verify.c b/crypto/x509/a_verify.c
index 51f0b35..e728863 100644
--- a/crypto/x509/a_verify.c
+++ b/crypto/x509/a_verify.c
@@ -75,69 +75,21 @@
 		ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
 	{
 	EVP_MD_CTX ctx;
-	unsigned char *buf_in=NULL;
-	int ret= -1,inl;
-	const EVP_PKEY_ASN1_METHOD *ameth;
-
-	int mdnid, pknid;
+	uint8_t *buf_in = NULL;
+	int ret = 0, inl;
 
 	if (!pkey)
 		{
 		OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ERR_R_PASSED_NULL_PARAMETER);
-		return 1;
+		return 0;
 		}
 
 	EVP_MD_CTX_init(&ctx);
 
-	/* Convert signature OID into digest and public key OIDs */
-	if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid))
+	if (!EVP_DigestVerifyInitFromAlgorithm(&ctx, a, pkey))
 		{
-		OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
 		goto err;
 		}
-	if (mdnid == NID_undef)
-		{
-		if (!pkey->ameth || !pkey->ameth->item_verify)
-			{
-			OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
-			goto err;
-			}
-		ret = pkey->ameth->item_verify(&ctx, it, asn, a,
-							signature, pkey);
-		/* Return value of 2 means carry on, anything else means we
-		 * exit straight away: either a fatal error of the underlying
-		 * verification routine handles all verification.
-		 */
-		if (ret != 2)
-			goto err;
-		ret = -1;
-		}
-	else
-		{
-		const EVP_MD *type;
-		type=EVP_get_digestbynid(mdnid);
-		if (type == NULL)
-			{
-			OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
-			goto err;
-			}
-
-		/* Check public key OID matches public key type */
-		ameth = EVP_PKEY_asn1_find(NULL, pknid);
-		if (ameth == NULL || ameth->pkey_id != pkey->ameth->pkey_id)
-			{
-			OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
-			goto err;
-			}
-
-		if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey))
-			{
-			OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ERR_R_EVP_LIB);
-			ret=0;
-			goto err;
-			}
-
-		}
 
 	inl = ASN1_item_i2d(asn, &buf_in, it);
 	
@@ -149,8 +101,9 @@
 
 	if (!EVP_DigestVerifyUpdate(&ctx,buf_in,inl))
 		{
+		OPENSSL_cleanse(buf_in,(unsigned int)inl);
+		OPENSSL_free(buf_in);
 		OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ERR_R_EVP_LIB);
-		ret=0;
 		goto err;
 		}
 
@@ -161,15 +114,14 @@
 			(size_t)signature->length) <= 0)
 		{
 		OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ERR_R_EVP_LIB);
-		ret=0;
 		goto err;
 		}
 	/* we don't need to zero the 'ctx' because we just checked
 	 * public information */
 	/* memset(&ctx,0,sizeof(ctx)); */
-	ret=1;
+	ret = 1;
 err:
 	EVP_MD_CTX_cleanup(&ctx);
-	return(ret);
+	return ret;
 	}
 
diff --git a/crypto/x509/asn1_gen.c b/crypto/x509/asn1_gen.c
index bbdc1a3..6fcae7b 100644
--- a/crypto/x509/asn1_gen.c
+++ b/crypto/x509/asn1_gen.c
@@ -375,7 +375,7 @@
 			arg->format = ASN1_GEN_FORMAT_BITLIST;
 		else
 			{
-			OPENSSL_PUT_ERROR(X509, asn1_cb, ASN1_R_UNKOWN_FORMAT);
+			OPENSSL_PUT_ERROR(X509, asn1_cb, ASN1_R_UNKNOWN_FORMAT);
 			return -1;
 			}
 		break;
diff --git a/include/openssl/asn1.h b/include/openssl/asn1.h
index 014b059..a64572c 100644
--- a/include/openssl/asn1.h
+++ b/include/openssl/asn1.h
@@ -1160,7 +1160,7 @@
 #define ASN1_R_NOT_ASCII_FORMAT 110
 #define ASN1_R_NOT_ENOUGH_DATA 111
 #define ASN1_R_MSTRING_NOT_UNIVERSAL 112
-#define ASN1_R_UNKOWN_FORMAT 113
+#define ASN1_R_UNKNOWN_FORMAT 113
 #define ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM 114
 #define ASN1_R_BAD_PASSWORD_READ 115
 #define ASN1_R_BAD_OBJECT_HEADER 116
@@ -1247,7 +1247,6 @@
 #define ASN1_R_DECODE_ERROR 197
 #define ASN1_R_NON_HEX_CHARACTERS 198
 #define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 199
-#define ASN1_R_UNKNOWN_FORMAT 200
 #define ASN1_R_EXPECTING_AN_ASN1_SEQUENCE 201
 #define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 202
 #define ASN1_R_STRING_TOO_SHORT 203
diff --git a/include/openssl/engine.h b/include/openssl/engine.h
index 367e98e..4a4f37d 100644
--- a/include/openssl/engine.h
+++ b/include/openssl/engine.h
@@ -100,4 +100,6 @@
 }  /* extern C */
 #endif
 
+#define ENGINE_R_OPERATION_NOT_SUPPORTED 100
+
 #endif  /* OPENSSL_HEADER_ENGINE_H */
diff --git a/include/openssl/err.h b/include/openssl/err.h
index 9843045..a7f30c7 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -166,9 +166,12 @@
 
 /* ERR_get_error_line_data acts like |ERR_get_error_line|, but also returns the
  * error-specific data pointer and flags. The flags are a bitwise-OR of
- * |ERR_FLAG_*| values. */
+ * |ERR_FLAG_*| values. The error-specific data is owned by the error queue
+ * and the pointer becomes invalid after the next call that affects the same
+ * thread's error queue. If |*flags| contains |ERR_FLAG_STRING| then |*data| is
+ * human-readable. */
 OPENSSL_EXPORT uint32_t ERR_get_error_line_data(const char **file, int *line,
-                                                char **data, int *flags);
+                                                const char **data, int *flags);
 
 /* The "peek" functions act like the |ERR_get_error| functions, above, but they
  * do not remove the error from the queue. */
@@ -325,12 +328,9 @@
   uint8_t flags;
 };
 
-/* ERR_FLAG_MALLOCED means the the |data| member must be freed when no longer
- * needed. */
-#define ERR_FLAG_MALLOCED 1
 /* ERR_FLAG_STRING means that the |data| member is a NUL-terminated string that
  * can be printed. */
-#define ERR_FLAG_STRING 2
+#define ERR_FLAG_STRING 1
 /* ERR_TXT_STRING is provided for compatibility with code that assumes that
  * it's using OpenSSL. */
 #define ERR_TXT_STRING ERR_FLAG_STRING
@@ -342,9 +342,12 @@
 /* The following flag values are internal and are masked when flags are
  * returned from functions like |ERR_get_error_line_data|. */
 
+/* ERR_FLAG_MALLOCED means the the |data| member must be freed when no longer
+ * needed. */
+#define ERR_FLAG_MALLOCED 16
 /* ERR_FLAG_MARK is used to indicate a reversion point in the queue. See
  * |ERR_pop_to_mark|. */
-#define ERR_FLAG_MARK 16
+#define ERR_FLAG_MARK 32
 
 /* ERR_NUM_ERRORS is the limit of the number of errors in the queue. */
 #define ERR_NUM_ERRORS 16
@@ -362,6 +365,10 @@
   unsigned top;
   /* bottom contains the index of the last error in the queue. */
   unsigned bottom;
+
+  /* to_free, if not NULL, contains a pointer owned by this structure that was
+   * previously a |data| pointer of one of the elements of |errors|. */
+  void *to_free;
 } ERR_STATE;
 
 enum {
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 091912f..fcbb085 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -247,6 +247,15 @@
 OPENSSL_EXPORT int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
                                        size_t *out_sig_len);
 
+/* EVP_DigestSignAlgorithm encodes the signing parameters of |ctx| as an
+ * AlgorithmIdentifer and saves the result in |algor|.
+ *
+ * It returns one on success, or zero on error.
+ *
+ * TODO(davidben): This API should eventually lose the dependency on
+ * crypto/asn1/. */
+OPENSSL_EXPORT int EVP_DigestSignAlgorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor);
+
 
 /* Verifying */
 
@@ -261,6 +270,18 @@
                                         const EVP_MD *type, ENGINE *e,
                                         EVP_PKEY *pkey);
 
+/* EVP_DigestVerifyInitFromAlgorithm sets up |ctx| for a signature verification
+ * operation with public key |pkey| and parameters from |algor|. The |ctx|
+ * argument must have been initialised with |EVP_MD_CTX_init|.
+ *
+ * It returns one on success, or zero on error.
+ *
+ * TODO(davidben): This API should eventually lose the dependency on
+ * crypto/asn1/. */
+OPENSSL_EXPORT int EVP_DigestVerifyInitFromAlgorithm(EVP_MD_CTX *ctx,
+                                                     X509_ALGOR *algor,
+                                                     EVP_PKEY *pkey);
+
 /* EVP_DigestVerifyUpdate appends |len| bytes from |data| to the data which
  * will be verified by |EVP_DigestVerifyFinal|. It returns one on success and
  * zero otherwise. */
@@ -813,6 +834,8 @@
 #define EVP_F_pkey_rsa_encrypt 152
 #define EVP_F_pkey_rsa_decrypt 153
 #define EVP_F_hmac_signctx 154
+#define EVP_F_EVP_DigestVerifyInitFromAlgorithm 155
+#define EVP_F_EVP_DigestSignAlgorithm 156
 #define EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE 100
 #define EVP_R_UNSUPPORTED_SIGNATURE_TYPE 101
 #define EVP_R_INVALID_DIGEST_TYPE 102
@@ -859,5 +882,6 @@
 #define EVP_R_DECODE_ERROR 143
 #define EVP_R_INVALID_PSS_SALTLEN 144
 #define EVP_R_UNKNOWN_PUBLIC_KEY_TYPE 145
+#define EVP_R_CONTEXT_NOT_INITIALISED 146
 
 #endif  /* OPENSSL_HEADER_EVP_H */
diff --git a/include/openssl/sha.h b/include/openssl/sha.h
index bc10d38..1f321fc 100644
--- a/include/openssl/sha.h
+++ b/include/openssl/sha.h
@@ -116,15 +116,15 @@
 /* SHA224_Init initialises |sha| and returns 1. */
 OPENSSL_EXPORT int SHA224_Init(SHA256_CTX *sha);
 
-/* SHA224_Update adds |len| bytes from |data| to |sha|. */
+/* SHA224_Update adds |len| bytes from |data| to |sha| and returns 1. */
 OPENSSL_EXPORT int SHA224_Update(SHA256_CTX *sha, const void *data, size_t len);
 
 /* SHA224_Final adds the final padding to |sha| and writes the resulting digest
- * to |md|, which must have at least |SHA_DIGEST_LENGTH| bytes of space. */
+ * to |md|, which must have at least |SHA224_DIGEST_LENGTH| bytes of space. */
 OPENSSL_EXPORT int SHA224_Final(uint8_t *md, SHA256_CTX *sha);
 
 /* SHA224 writes the digest of |len| bytes from |data| to |out| and returns
- * |out|. There must be at least |SHA_DIGEST_LENGTH| bytes of space in
+ * |out|. There must be at least |SHA224_DIGEST_LENGTH| bytes of space in
  * |out|. */
 OPENSSL_EXPORT uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out);
 
@@ -140,15 +140,15 @@
 /* SHA256_Init initialises |sha| and returns 1. */
 OPENSSL_EXPORT int SHA256_Init(SHA256_CTX *sha);
 
-/* SHA256_Update adds |len| bytes from |data| to |sha|. */
+/* SHA256_Update adds |len| bytes from |data| to |sha| and returns 1. */
 OPENSSL_EXPORT int SHA256_Update(SHA256_CTX *sha, const void *data, size_t len);
 
 /* SHA256_Final adds the final padding to |sha| and writes the resulting digest
- * to |md|, which must have at least |SHA_DIGEST_LENGTH| bytes of space. */
+ * to |md|, which must have at least |SHA256_DIGEST_LENGTH| bytes of space. */
 OPENSSL_EXPORT int SHA256_Final(uint8_t *md, SHA256_CTX *sha);
 
 /* SHA256 writes the digest of |len| bytes from |data| to |out| and returns
- * |out|. There must be at least |SHA_DIGEST_LENGTH| bytes of space in
+ * |out|. There must be at least |SHA256_DIGEST_LENGTH| bytes of space in
  * |out|. */
 OPENSSL_EXPORT uint8_t *SHA256(const uint8_t *data, size_t len, uint8_t *out);
 
@@ -175,15 +175,15 @@
 /* SHA384_Init initialises |sha| and returns 1. */
 OPENSSL_EXPORT int SHA384_Init(SHA512_CTX *sha);
 
-/* SHA384_Update adds |len| bytes from |data| to |sha|. */
+/* SHA384_Update adds |len| bytes from |data| to |sha| and returns 1. */
 OPENSSL_EXPORT int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len);
 
 /* SHA384_Final adds the final padding to |sha| and writes the resulting digest
- * to |md|, which must have at least |SHA_DIGEST_LENGTH| bytes of space. */
+ * to |md|, which must have at least |SHA384_DIGEST_LENGTH| bytes of space. */
 OPENSSL_EXPORT int SHA384_Final(uint8_t *md, SHA512_CTX *sha);
 
 /* SHA384 writes the digest of |len| bytes from |data| to |out| and returns
- * |out|. There must be at least |SHA_DIGEST_LENGTH| bytes of space in
+ * |out|. There must be at least |SHA384_DIGEST_LENGTH| bytes of space in
  * |out|. */
 OPENSSL_EXPORT uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out);
 
@@ -203,15 +203,15 @@
 /* SHA512_Init initialises |sha| and returns 1. */
 OPENSSL_EXPORT int SHA512_Init(SHA512_CTX *sha);
 
-/* SHA512_Update adds |len| bytes from |data| to |sha|. */
+/* SHA512_Update adds |len| bytes from |data| to |sha| and returns 1. */
 OPENSSL_EXPORT int SHA512_Update(SHA512_CTX *sha, const void *data, size_t len);
 
 /* SHA512_Final adds the final padding to |sha| and writes the resulting digest
- * to |md|, which must have at least |SHA_DIGEST_LENGTH| bytes of space. */
+ * to |md|, which must have at least |SHA512_DIGEST_LENGTH| bytes of space. */
 OPENSSL_EXPORT int SHA512_Final(uint8_t *md, SHA512_CTX *sha);
 
 /* SHA512 writes the digest of |len| bytes from |data| to |out| and returns
- * |out|. There must be at least |SHA_DIGEST_LENGTH| bytes of space in
+ * |out|. There must be at least |SHA512_DIGEST_LENGTH| bytes of space in
  * |out|. */
 OPENSSL_EXPORT uint8_t *SHA512(const uint8_t *data, size_t len, uint8_t *out);
 
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index 1f277f3..1d67ed3 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -844,10 +844,6 @@
 OPENSSL_EXPORT int ASN1_digest(i2d_of_void *i2d,const EVP_MD *type,char *data,
 		unsigned char *md,unsigned int *len);
 
-OPENSSL_EXPORT int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1,
-	      X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
-	      char *data,EVP_PKEY *pkey, const EVP_MD *type);
-
 OPENSSL_EXPORT int ASN1_item_digest(const ASN1_ITEM *it,const EVP_MD *type,void *data,
 	unsigned char *md,unsigned int *len);