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);