1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "crypto/signature_verifier.h" 6 7 #include <openssl/evp.h> 8 #include <openssl/x509.h> 9 10 #include <vector> 11 12 #include "base/logging.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/stl_util.h" 15 #include "crypto/openssl_util.h" 16 17 namespace crypto { 18 19 namespace { 20 21 const EVP_MD* ToOpenSSLDigest(SignatureVerifier::HashAlgorithm hash_alg) { 22 switch (hash_alg) { 23 case SignatureVerifier::SHA1: 24 return EVP_sha1(); 25 case SignatureVerifier::SHA256: 26 return EVP_sha256(); 27 } 28 return EVP_md_null(); 29 } 30 31 } // namespace 32 33 struct SignatureVerifier::VerifyContext { 34 ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> ctx; 35 }; 36 37 SignatureVerifier::SignatureVerifier() 38 : verify_context_(NULL) { 39 } 40 41 SignatureVerifier::~SignatureVerifier() { 42 Reset(); 43 } 44 45 bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, 46 int signature_algorithm_len, 47 const uint8* signature, 48 int signature_len, 49 const uint8* public_key_info, 50 int public_key_info_len) { 51 OpenSSLErrStackTracer err_tracer(FROM_HERE); 52 ScopedOpenSSL<X509_ALGOR, X509_ALGOR_free> algorithm( 53 d2i_X509_ALGOR(NULL, &signature_algorithm, signature_algorithm_len)); 54 if (!algorithm.get()) 55 return false; 56 int nid = OBJ_obj2nid(algorithm.get()->algorithm); 57 const EVP_MD* digest; 58 if (nid == NID_ecdsa_with_SHA1) { 59 digest = EVP_sha1(); 60 } else if (nid == NID_ecdsa_with_SHA256) { 61 digest = EVP_sha256(); 62 } else { 63 // This works for PKCS #1 v1.5 RSA signatures, but not for ECDSA 64 // signatures. 65 digest = EVP_get_digestbyobj(algorithm.get()->algorithm); 66 } 67 if (!digest) 68 return false; 69 70 return CommonInit(digest, signature, signature_len, public_key_info, 71 public_key_info_len, NULL); 72 } 73 74 bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, 75 HashAlgorithm mask_hash_alg, 76 int salt_len, 77 const uint8* signature, 78 int signature_len, 79 const uint8* public_key_info, 80 int public_key_info_len) { 81 OpenSSLErrStackTracer err_tracer(FROM_HERE); 82 const EVP_MD* digest = ToOpenSSLDigest(hash_alg); 83 DCHECK(digest); 84 85 EVP_PKEY_CTX* pkey_ctx; 86 if (!CommonInit(digest, signature, signature_len, public_key_info, 87 public_key_info_len, &pkey_ctx)) { 88 return false; 89 } 90 91 int rv = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING); 92 if (rv != 1) 93 return false; 94 rv = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, 95 ToOpenSSLDigest(mask_hash_alg)); 96 if (rv != 1) 97 return false; 98 rv = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len); 99 return rv == 1; 100 } 101 102 void SignatureVerifier::VerifyUpdate(const uint8* data_part, 103 int data_part_len) { 104 DCHECK(verify_context_); 105 OpenSSLErrStackTracer err_tracer(FROM_HERE); 106 int rv = EVP_DigestVerifyUpdate(verify_context_->ctx.get(), 107 data_part, data_part_len); 108 DCHECK_EQ(rv, 1); 109 } 110 111 bool SignatureVerifier::VerifyFinal() { 112 DCHECK(verify_context_); 113 OpenSSLErrStackTracer err_tracer(FROM_HERE); 114 int rv = EVP_DigestVerifyFinal(verify_context_->ctx.get(), 115 vector_as_array(&signature_), 116 signature_.size()); 117 // rv is -1 if a DER-encoded ECDSA signature cannot be decoded correctly. 118 DCHECK_GE(rv, -1); 119 Reset(); 120 return rv == 1; 121 } 122 123 bool SignatureVerifier::CommonInit(const EVP_MD* digest, 124 const uint8* signature, 125 int signature_len, 126 const uint8* public_key_info, 127 int public_key_info_len, 128 EVP_PKEY_CTX** pkey_ctx) { 129 if (verify_context_) 130 return false; 131 132 verify_context_ = new VerifyContext; 133 134 signature_.assign(signature, signature + signature_len); 135 136 // BIO_new_mem_buf is not const aware, but it does not modify the buffer. 137 char* data = reinterpret_cast<char*>(const_cast<uint8*>(public_key_info)); 138 ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new_mem_buf(data, 139 public_key_info_len)); 140 if (!bio.get()) 141 return false; 142 143 ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> public_key( 144 d2i_PUBKEY_bio(bio.get(), NULL)); 145 if (!public_key.get()) 146 return false; 147 148 verify_context_->ctx.reset(EVP_MD_CTX_create()); 149 int rv = EVP_DigestVerifyInit(verify_context_->ctx.get(), pkey_ctx, 150 digest, NULL, public_key.get()); 151 return rv == 1; 152 } 153 154 void SignatureVerifier::Reset() { 155 delete verify_context_; 156 verify_context_ = NULL; 157 signature_.clear(); 158 } 159 160 } // namespace crypto 161