File: verifier.cc

package info (click to toggle)
golang-github-google-certificate-transparency 0.0~git20160709.0.0f6e3d1~ds1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, buster
  • size: 5,676 kB
  • sloc: cpp: 35,278; python: 11,838; java: 1,911; sh: 1,885; makefile: 950; xml: 520; ansic: 225
file content (86 lines) | stat: -rw-r--r-- 2,595 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/* -*- indent-tabs-mode: nil -*- */
#include "log/verifier.h"

#include <glog/logging.h>
#include <openssl/evp.h>
#include <openssl/opensslv.h>
#include <stdint.h>

#include "merkletree/serial_hasher.h"
#include "proto/ct.pb.h"
#include "util/util.h"

#if OPENSSL_VERSION_NUMBER < 0x10000000
#error "Need OpenSSL >= 1.0.0"
#endif

using ct::DigitallySigned;

namespace cert_trans {

Verifier::Verifier(EVP_PKEY* pkey) : pkey_(CHECK_NOTNULL(pkey)) {
  switch (pkey_->type) {
    case EVP_PKEY_EC:
      hash_algo_ = DigitallySigned::SHA256;
      sig_algo_ = DigitallySigned::ECDSA;
      break;
    case EVP_PKEY_RSA:
      hash_algo_ = DigitallySigned::SHA256;
      sig_algo_ = DigitallySigned::RSA;
      break;
    default:
      LOG(FATAL) << "Unsupported key type " << pkey_->type;
  }
  key_id_ = ComputeKeyID(pkey_.get());
}

std::string Verifier::KeyID() const {
  return key_id_;
}

Verifier::Status Verifier::Verify(const std::string& input,
                                  const DigitallySigned& signature) const {
  if (signature.hash_algorithm() != hash_algo_)
    return HASH_ALGORITHM_MISMATCH;
  if (signature.sig_algorithm() != sig_algo_)
    return SIGNATURE_ALGORITHM_MISMATCH;
  if (!RawVerify(input, signature.signature()))
    return INVALID_SIGNATURE;
  return OK;
}

// static
std::string Verifier::ComputeKeyID(EVP_PKEY* pkey) {
  // i2d_PUBKEY sets the algorithm and (for ECDSA) named curve parameter and
  // encodes the key as an X509_PUBKEY (i.e., subjectPublicKeyInfo).
  int buf_len = i2d_PUBKEY(pkey, NULL);
  CHECK_GT(buf_len, 0);
  unsigned char* buf = new unsigned char[buf_len];
  unsigned char* p = buf;
  CHECK_EQ(i2d_PUBKEY(pkey, &p), buf_len);
  const std::string keystring(reinterpret_cast<char*>(buf), buf_len);
  const std::string ret(Sha256Hasher::Sha256Digest(keystring));
  delete[] buf;
  return ret;
}

Verifier::Verifier()
    : hash_algo_(DigitallySigned::NONE),
      sig_algo_(DigitallySigned::ANONYMOUS) {
}

bool Verifier::RawVerify(const std::string& data,
                         const std::string& sig_string) const {
  EVP_MD_CTX ctx;
  EVP_MD_CTX_init(&ctx);
  // NOTE: this syntax for setting the hash function requires OpenSSL >= 1.0.0.
  CHECK_EQ(1, EVP_VerifyInit(&ctx, EVP_sha256()));
  CHECK_EQ(1, EVP_VerifyUpdate(&ctx, data.data(), data.size()));
  bool ret = (EVP_VerifyFinal(&ctx, reinterpret_cast<const unsigned char*>(
                                        sig_string.data()),
                              sig_string.size(), pkey_.get()) == 1);
  EVP_MD_CTX_cleanup(&ctx);
  return ret;
}

}  // namespace cert_trans