[email protected] | 3b63f8f4 | 2011-03-28 01:54:15 | [diff] [blame] | 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 4b559b4d | 2011-04-14 17:37:14 | [diff] [blame] | 5 | #include "crypto/signature_verifier.h" |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 6 | |
avi | dd373b8b | 2015-12-21 21:34:43 | [diff] [blame] | 7 | #include <stdint.h> |
[email protected] | be796bb | 2010-11-18 15:43:43 | [diff] [blame] | 8 | |
thakis | d1a1847 | 2016-04-08 22:30:41 | [diff] [blame] | 9 | #include <memory> |
[email protected] | be796bb | 2010-11-18 15:43:43 | [diff] [blame] | 10 | #include <vector> |
| 11 | |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 12 | #include "base/logging.h" |
[email protected] | 4b559b4d | 2011-04-14 17:37:14 | [diff] [blame] | 13 | #include "crypto/openssl_util.h" |
tfarina | 29a3a174 | 2016-10-28 18:47:33 | [diff] [blame] | 14 | #include "third_party/boringssl/src/include/openssl/bytestring.h" |
| 15 | #include "third_party/boringssl/src/include/openssl/digest.h" |
| 16 | #include "third_party/boringssl/src/include/openssl/evp.h" |
| 17 | #include "third_party/boringssl/src/include/openssl/rsa.h" |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 18 | |
[email protected] | 4b559b4d | 2011-04-14 17:37:14 | [diff] [blame] | 19 | namespace crypto { |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 20 | |
[email protected] | be796bb | 2010-11-18 15:43:43 | [diff] [blame] | 21 | struct SignatureVerifier::VerifyContext { |
davidben | 74f6744 | 2016-10-01 01:45:22 | [diff] [blame] | 22 | bssl::ScopedEVP_MD_CTX ctx; |
[email protected] | be796bb | 2010-11-18 15:43:43 | [diff] [blame] | 23 | }; |
| 24 | |
Chris Watkins | a850a30 | 2017-11-30 03:53:49 | [diff] [blame] | 25 | SignatureVerifier::SignatureVerifier() = default; |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 26 | |
Chris Watkins | a850a30 | 2017-11-30 03:53:49 | [diff] [blame] | 27 | SignatureVerifier::~SignatureVerifier() = default; |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 28 | |
davidben | 9c97a36 | 2016-03-03 16:18:26 | [diff] [blame] | 29 | bool SignatureVerifier::VerifyInit(SignatureAlgorithm signature_algorithm, |
avi | dd373b8b | 2015-12-21 21:34:43 | [diff] [blame] | 30 | const uint8_t* signature, |
davidben | cfb6ad6 | 2017-03-23 22:14:32 | [diff] [blame] | 31 | size_t signature_len, |
avi | dd373b8b | 2015-12-21 21:34:43 | [diff] [blame] | 32 | const uint8_t* public_key_info, |
davidben | cfb6ad6 | 2017-03-23 22:14:32 | [diff] [blame] | 33 | size_t public_key_info_len) { |
David Benjamin | 8982fe4f | 2018-02-06 19:30:32 | [diff] [blame] | 34 | OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 35 | |
davidben | 9c97a36 | 2016-03-03 16:18:26 | [diff] [blame] | 36 | int pkey_type = EVP_PKEY_NONE; |
| 37 | const EVP_MD* digest = nullptr; |
| 38 | switch (signature_algorithm) { |
| 39 | case RSA_PKCS1_SHA1: |
| 40 | pkey_type = EVP_PKEY_RSA; |
| 41 | digest = EVP_sha1(); |
| 42 | break; |
| 43 | case RSA_PKCS1_SHA256: |
David Benjamin | 8982fe4f | 2018-02-06 19:30:32 | [diff] [blame] | 44 | case RSA_PSS_SHA256: |
davidben | 9c97a36 | 2016-03-03 16:18:26 | [diff] [blame] | 45 | pkey_type = EVP_PKEY_RSA; |
| 46 | digest = EVP_sha256(); |
| 47 | break; |
| 48 | case ECDSA_SHA256: |
| 49 | pkey_type = EVP_PKEY_EC; |
| 50 | digest = EVP_sha256(); |
| 51 | break; |
[email protected] | 2662ed56 | 2013-07-03 10:27:46 | [diff] [blame] | 52 | } |
davidben | 9c97a36 | 2016-03-03 16:18:26 | [diff] [blame] | 53 | DCHECK_NE(EVP_PKEY_NONE, pkey_type); |
| 54 | DCHECK(digest); |
[email protected] | 9b898661 | 2013-06-28 17:46:53 | [diff] [blame] | 55 | |
David Benjamin | 8982fe4f | 2018-02-06 19:30:32 | [diff] [blame] | 56 | if (verify_context_) |
| 57 | return false; |
[email protected] | 9b898661 | 2013-06-28 17:46:53 | [diff] [blame] | 58 | |
David Benjamin | 8982fe4f | 2018-02-06 19:30:32 | [diff] [blame] | 59 | verify_context_.reset(new VerifyContext); |
| 60 | signature_.assign(signature, signature + signature_len); |
| 61 | |
| 62 | CBS cbs; |
| 63 | CBS_init(&cbs, public_key_info, public_key_info_len); |
| 64 | bssl::UniquePtr<EVP_PKEY> public_key(EVP_parse_public_key(&cbs)); |
| 65 | if (!public_key || CBS_len(&cbs) != 0 || |
| 66 | EVP_PKEY_id(public_key.get()) != pkey_type) { |
[email protected] | edfd0f4 | 2014-07-22 18:20:37 | [diff] [blame] | 67 | return false; |
| 68 | } |
[email protected] | be796bb | 2010-11-18 15:43:43 | [diff] [blame] | 69 | |
[email protected] | 9b898661 | 2013-06-28 17:46:53 | [diff] [blame] | 70 | EVP_PKEY_CTX* pkey_ctx; |
David Benjamin | 8982fe4f | 2018-02-06 19:30:32 | [diff] [blame] | 71 | if (!EVP_DigestVerifyInit(verify_context_->ctx.get(), &pkey_ctx, digest, |
| 72 | nullptr, public_key.get())) { |
[email protected] | 9b898661 | 2013-06-28 17:46:53 | [diff] [blame] | 73 | return false; |
| 74 | } |
| 75 | |
David Benjamin | 8982fe4f | 2018-02-06 19:30:32 | [diff] [blame] | 76 | if (signature_algorithm == RSA_PSS_SHA256) { |
| 77 | if (!EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) || |
| 78 | !EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, digest) || |
| 79 | !EVP_PKEY_CTX_set_rsa_pss_saltlen( |
| 80 | pkey_ctx, -1 /* match digest and salt length */)) { |
| 81 | return false; |
| 82 | } |
[email protected] | edfd0f4 | 2014-07-22 18:20:37 | [diff] [blame] | 83 | } |
David Benjamin | 8982fe4f | 2018-02-06 19:30:32 | [diff] [blame] | 84 | |
| 85 | return true; |
[email protected] | 9b898661 | 2013-06-28 17:46:53 | [diff] [blame] | 86 | } |
| 87 | |
avi | dd373b8b | 2015-12-21 21:34:43 | [diff] [blame] | 88 | void SignatureVerifier::VerifyUpdate(const uint8_t* data_part, |
davidben | cfb6ad6 | 2017-03-23 22:14:32 | [diff] [blame] | 89 | size_t data_part_len) { |
[email protected] | 9b898661 | 2013-06-28 17:46:53 | [diff] [blame] | 90 | DCHECK(verify_context_); |
| 91 | OpenSSLErrStackTracer err_tracer(FROM_HERE); |
davidben | cfb6ad6 | 2017-03-23 22:14:32 | [diff] [blame] | 92 | int rv = EVP_DigestVerifyUpdate(verify_context_->ctx.get(), data_part, |
| 93 | data_part_len); |
[email protected] | 9b898661 | 2013-06-28 17:46:53 | [diff] [blame] | 94 | DCHECK_EQ(rv, 1); |
| 95 | } |
| 96 | |
| 97 | bool SignatureVerifier::VerifyFinal() { |
| 98 | DCHECK(verify_context_); |
| 99 | OpenSSLErrStackTracer err_tracer(FROM_HERE); |
davidben | 4507eaa | 2015-11-19 19:07:06 | [diff] [blame] | 100 | int rv = EVP_DigestVerifyFinal(verify_context_->ctx.get(), signature_.data(), |
[email protected] | 9b898661 | 2013-06-28 17:46:53 | [diff] [blame] | 101 | signature_.size()); |
davidben | 1407104c | 2014-11-11 23:55:55 | [diff] [blame] | 102 | DCHECK_EQ(static_cast<int>(!!rv), rv); |
[email protected] | 9b898661 | 2013-06-28 17:46:53 | [diff] [blame] | 103 | Reset(); |
| 104 | return rv == 1; |
| 105 | } |
| 106 | |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 107 | void SignatureVerifier::Reset() { |
davidben | 74f6744 | 2016-10-01 01:45:22 | [diff] [blame] | 108 | verify_context_.reset(); |
[email protected] | be796bb | 2010-11-18 15:43:43 | [diff] [blame] | 109 | signature_.clear(); |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 110 | } |
| 111 | |
[email protected] | 4b559b4d | 2011-04-14 17:37:14 | [diff] [blame] | 112 | } // namespace crypto |