blob: 833a3dfb25dbc854e284fab1c0ea2ab5a9ba8443 [file] [log] [blame]
Avi Drissman201a9a832022-09-13 19:39:251// Copyright 2011 The Chromium Authors
[email protected]70372d42010-10-22 13:12:342// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Arthur Sonzogni125ca8e2024-07-18 17:26:555#ifdef UNSAFE_BUFFERS_BUILD
6// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
7#pragma allow_unsafe_buffers
8#endif
9
[email protected]4b559b4d2011-04-14 17:37:1410#include "crypto/signature_verifier.h"
[email protected]70372d42010-10-22 13:12:3411
Peter Boströmfb60ea02021-04-05 21:06:1212#include <memory>
13
Hans Wennborg4d0e1802020-04-24 20:19:4314#include "base/check_op.h"
[email protected]4b559b4d2011-04-14 17:37:1415#include "crypto/openssl_util.h"
tfarina29a3a1742016-10-28 18:47:3316#include "third_party/boringssl/src/include/openssl/bytestring.h"
17#include "third_party/boringssl/src/include/openssl/digest.h"
18#include "third_party/boringssl/src/include/openssl/evp.h"
19#include "third_party/boringssl/src/include/openssl/rsa.h"
[email protected]70372d42010-10-22 13:12:3420
[email protected]4b559b4d2011-04-14 17:37:1421namespace crypto {
[email protected]70372d42010-10-22 13:12:3422
[email protected]be796bb2010-11-18 15:43:4323struct SignatureVerifier::VerifyContext {
davidben74f67442016-10-01 01:45:2224 bssl::ScopedEVP_MD_CTX ctx;
[email protected]be796bb2010-11-18 15:43:4325};
26
Chris Watkinsa850a302017-11-30 03:53:4927SignatureVerifier::SignatureVerifier() = default;
[email protected]70372d42010-10-22 13:12:3428
Chris Watkinsa850a302017-11-30 03:53:4929SignatureVerifier::~SignatureVerifier() = default;
[email protected]70372d42010-10-22 13:12:3430
davidben9c97a362016-03-03 16:18:2631bool SignatureVerifier::VerifyInit(SignatureAlgorithm signature_algorithm,
David Benjamin8ed923192018-04-13 23:17:0632 base::span<const uint8_t> signature,
33 base::span<const uint8_t> public_key_info) {
David Benjamin8982fe4f2018-02-06 19:30:3234 OpenSSLErrStackTracer err_tracer(FROM_HERE);
35
davidben9c97a362016-03-03 16:18:2636 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 Benjamin8982fe4f2018-02-06 19:30:3244 case RSA_PSS_SHA256:
davidben9c97a362016-03-03 16:18:2645 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]2662ed562013-07-03 10:27:4652 }
davidben9c97a362016-03-03 16:18:2653 DCHECK_NE(EVP_PKEY_NONE, pkey_type);
54 DCHECK(digest);
[email protected]9b8986612013-06-28 17:46:5355
David Benjamin8982fe4f2018-02-06 19:30:3256 if (verify_context_)
57 return false;
[email protected]9b8986612013-06-28 17:46:5358
Peter Boströmfb60ea02021-04-05 21:06:1259 verify_context_ = std::make_unique<VerifyContext>();
David Benjamin8ed923192018-04-13 23:17:0660 signature_.assign(signature.data(), signature.data() + signature.size());
David Benjamin8982fe4f2018-02-06 19:30:3261
62 CBS cbs;
David Benjamin8ed923192018-04-13 23:17:0663 CBS_init(&cbs, public_key_info.data(), public_key_info.size());
David Benjamin8982fe4f2018-02-06 19:30:3264 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]edfd0f42014-07-22 18:20:3767 return false;
68 }
[email protected]be796bb2010-11-18 15:43:4369
[email protected]9b8986612013-06-28 17:46:5370 EVP_PKEY_CTX* pkey_ctx;
David Benjamin8982fe4f2018-02-06 19:30:3271 if (!EVP_DigestVerifyInit(verify_context_->ctx.get(), &pkey_ctx, digest,
72 nullptr, public_key.get())) {
[email protected]9b8986612013-06-28 17:46:5373 return false;
74 }
75
David Benjamin8982fe4f2018-02-06 19:30:3276 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]edfd0f42014-07-22 18:20:3783 }
David Benjamin8982fe4f2018-02-06 19:30:3284
85 return true;
[email protected]9b8986612013-06-28 17:46:5386}
87
David Benjamin8ed923192018-04-13 23:17:0688void SignatureVerifier::VerifyUpdate(base::span<const uint8_t> data_part) {
[email protected]9b8986612013-06-28 17:46:5389 DCHECK(verify_context_);
90 OpenSSLErrStackTracer err_tracer(FROM_HERE);
David Benjamin8ed923192018-04-13 23:17:0691 int rv = EVP_DigestVerifyUpdate(verify_context_->ctx.get(), data_part.data(),
92 data_part.size());
[email protected]9b8986612013-06-28 17:46:5393 DCHECK_EQ(rv, 1);
94}
95
96bool SignatureVerifier::VerifyFinal() {
97 DCHECK(verify_context_);
98 OpenSSLErrStackTracer err_tracer(FROM_HERE);
davidben4507eaa2015-11-19 19:07:0699 int rv = EVP_DigestVerifyFinal(verify_context_->ctx.get(), signature_.data(),
[email protected]9b8986612013-06-28 17:46:53100 signature_.size());
davidben1407104c2014-11-11 23:55:55101 DCHECK_EQ(static_cast<int>(!!rv), rv);
[email protected]9b8986612013-06-28 17:46:53102 Reset();
103 return rv == 1;
104}
105
[email protected]70372d42010-10-22 13:12:34106void SignatureVerifier::Reset() {
davidben74f67442016-10-01 01:45:22107 verify_context_.reset();
[email protected]be796bb2010-11-18 15:43:43108 signature_.clear();
[email protected]70372d42010-10-22 13:12:34109}
110
[email protected]4b559b4d2011-04-14 17:37:14111} // namespace crypto