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 17namespace crypto { 18 19namespace { 20 21const 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 33struct SignatureVerifier::VerifyContext { 34 ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> ctx; 35}; 36 37SignatureVerifier::SignatureVerifier() 38 : verify_context_(NULL) { 39} 40 41SignatureVerifier::~SignatureVerifier() { 42 Reset(); 43} 44 45bool 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 74bool 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 102void 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 111bool 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 123bool 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 154void SignatureVerifier::Reset() { 155 delete verify_context_; 156 verify_context_ = NULL; 157 signature_.clear(); 158} 159 160} // namespace crypto 161