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 <stdlib.h>
8
9#include "base/logging.h"
10#include "crypto/cssm_init.h"
11
12namespace crypto {
13
14SignatureVerifier::SignatureVerifier() : sig_handle_(0) {
15  EnsureCSSMInit();
16}
17
18SignatureVerifier::~SignatureVerifier() {
19  Reset();
20}
21
22bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm,
23                                   int signature_algorithm_len,
24                                   const uint8* signature,
25                                   int signature_len,
26                                   const uint8* public_key_info,
27                                   int public_key_info_len) {
28  signature_.assign(signature, signature + signature_len);
29  public_key_info_.assign(public_key_info,
30                          public_key_info + public_key_info_len);
31
32  CSSM_ALGORITHMS key_alg = CSSM_ALGID_RSA;  // TODO(wtc): hardcoded.
33
34  memset(&public_key_, 0, sizeof(public_key_));
35  public_key_.KeyData.Data = const_cast<uint8*>(&public_key_info_[0]);
36  public_key_.KeyData.Length = public_key_info_.size();
37  public_key_.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
38  public_key_.KeyHeader.BlobType = CSSM_KEYBLOB_RAW;
39  public_key_.KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_X509;
40  public_key_.KeyHeader.AlgorithmId = key_alg;
41  public_key_.KeyHeader.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
42  public_key_.KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
43  public_key_.KeyHeader.KeyUsage = CSSM_KEYUSE_VERIFY;
44  CSSM_KEY_SIZE key_size;
45  CSSM_RETURN crtn;
46  crtn = CSSM_QueryKeySizeInBits(GetSharedCSPHandle(), NULL,
47                                 &public_key_, &key_size);
48  if (crtn) {
49    NOTREACHED() << "CSSM_QueryKeySizeInBits failed: " << crtn;
50    return false;
51  }
52  public_key_.KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits;
53
54  // TODO(wtc): decode signature_algorithm...
55  CSSM_ALGORITHMS sig_alg = CSSM_ALGID_SHA1WithRSA;
56
57  crtn = CSSM_CSP_CreateSignatureContext(GetSharedCSPHandle(), sig_alg, NULL,
58                                         &public_key_, &sig_handle_);
59  if (crtn) {
60    NOTREACHED();
61    return false;
62  }
63  crtn = CSSM_VerifyDataInit(sig_handle_);
64  if (crtn) {
65    NOTREACHED();
66    return false;
67  }
68  return true;
69}
70
71void SignatureVerifier::VerifyUpdate(const uint8* data_part,
72                                     int data_part_len) {
73  CSSM_DATA data;
74  data.Data = const_cast<uint8*>(data_part);
75  data.Length = data_part_len;
76  CSSM_RETURN crtn = CSSM_VerifyDataUpdate(sig_handle_, &data, 1);
77  DCHECK(crtn == CSSM_OK);
78}
79
80bool SignatureVerifier::VerifyFinal() {
81  CSSM_DATA sig;
82  sig.Data = const_cast<uint8*>(&signature_[0]);
83  sig.Length = signature_.size();
84  CSSM_RETURN crtn = CSSM_VerifyDataFinal(sig_handle_, &sig);
85  Reset();
86
87  // crtn is CSSMERR_CSP_VERIFY_FAILED if signature verification fails.
88  return (crtn == CSSM_OK);
89}
90
91void SignatureVerifier::Reset() {
92  CSSM_RETURN crtn;
93  if (sig_handle_) {
94    crtn = CSSM_DeleteContext(sig_handle_);
95    DCHECK(crtn == CSSM_OK);
96    sig_handle_ = 0;
97  }
98  signature_.clear();
99
100  // Can't call CSSM_FreeKey on public_key_ because we constructed
101  // public_key_ manually.
102}
103
104}  // namespace crypto
105
106