15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/signature_verifier.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cryptohi.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <keyhi.h>
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <pk11pub.h>
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <secerr.h>
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <sechash.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "crypto/third_party/nss/chromium-nss.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace crypto {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace {
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochHASH_HashType ToNSSHashType(SignatureVerifier::HashAlgorithm hash_alg) {
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (hash_alg) {
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SignatureVerifier::SHA1:
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return HASH_AlgSHA1;
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SignatureVerifier::SHA256:
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return HASH_AlgSHA256;
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return HASH_AlgNULL;
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSECStatus VerifyRSAPSS_End(SECKEYPublicKey* public_key,
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           HASHContext* hash_context,
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           HASH_HashType mask_hash_alg,
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           unsigned int salt_len,
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           const unsigned char* signature,
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           unsigned int signature_len) {
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  unsigned int hash_len = HASH_ResultLenContext(hash_context);
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<unsigned char> hash(hash_len);
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HASH_End(hash_context, &hash[0], &hash_len, hash.size());
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  unsigned int modulus_len = SECKEY_PublicKeyStrength(public_key);
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (signature_len != modulus_len) {
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return SECFailure;
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<unsigned char> enc(signature_len);
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SECStatus rv = PK11_PubEncryptRaw(public_key, &enc[0],
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    const_cast<unsigned char*>(signature),
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    signature_len, NULL);
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (rv != SECSuccess) {
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    LOG(WARNING) << "PK11_PubEncryptRaw failed";
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return rv;
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return emsa_pss_verify(&hash[0], &enc[0], enc.size(),
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         HASH_GetType(hash_context), mask_hash_alg,
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         salt_len);
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSignatureVerifier::SignatureVerifier()
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : vfy_context_(NULL),
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      hash_alg_(SHA1),
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      mask_hash_alg_(SHA1),
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      salt_len_(0),
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      public_key_(NULL),
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      hash_context_(NULL) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureNSSInit();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SignatureVerifier::~SignatureVerifier() {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reset();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int signature_algorithm_len,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const uint8* signature,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int signature_len,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const uint8* public_key_info,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int public_key_info_len) {
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (vfy_context_ || hash_context_)
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signature_.assign(signature, signature + signature_len);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info,
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                    public_key_info_len);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!public_key)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!arena) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEY_DestroyPublicKey(public_key);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECItem sig_alg_der;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sig_alg_der.type = siBuffer;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sig_alg_der.data = const_cast<uint8*>(signature_algorithm);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sig_alg_der.len = signature_algorithm_len;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECAlgorithmID sig_alg_id;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &sig_alg_der);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEY_DestroyPublicKey(public_key);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_FreeArena(arena, PR_TRUE);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECItem sig;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sig.type = siBuffer;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sig.data = const_cast<uint8*>(signature);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sig.len = signature_len;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECOidTag hash_alg_tag;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vfy_context_ = VFY_CreateContextWithAlgorithmID(public_key, &sig,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  &sig_alg_id, &hash_alg_tag,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  NULL);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECKEY_DestroyPublicKey(public_key);  // Done with public_key.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PORT_FreeArena(arena, PR_TRUE);  // Done with sig_alg_id.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!vfy_context_) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A corrupted RSA signature could be detected without the data, so
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (-8182).
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = VFY_Begin(vfy_context_);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg,
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                         HashAlgorithm mask_hash_alg,
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                         int salt_len,
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                         const uint8* signature,
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                         int signature_len,
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                         const uint8* public_key_info,
144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                         int public_key_info_len) {
145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (vfy_context_ || hash_context_)
146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  signature_.assign(signature, signature + signature_len);
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info,
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                    public_key_info_len);
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!public_key)
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  public_key_ = public_key;
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  hash_alg_ = hash_alg;
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  mask_hash_alg_ = mask_hash_alg;
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  salt_len_ = salt_len;
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  hash_context_ = HASH_Create(ToNSSHashType(hash_alg_));
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!hash_context_)
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HASH_Begin(hash_context_);
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return true;
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SignatureVerifier::VerifyUpdate(const uint8* data_part,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     int data_part_len) {
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (vfy_context_) {
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len);
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DCHECK_EQ(SECSuccess, rv);
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else {
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    HASH_Update(hash_context_, data_part, data_part_len);
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SignatureVerifier::VerifyFinal() {
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SECStatus rv;
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (vfy_context_) {
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    rv = VFY_End(vfy_context_);
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else {
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    rv = VerifyRSAPSS_End(public_key_, hash_context_,
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          ToNSSHashType(mask_hash_alg_), salt_len_,
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          signature_.data(),
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          signature_.size());
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reset();
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If signature verification fails, the error code is
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SEC_ERROR_BAD_SIGNATURE (-8182).
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (rv == SECSuccess);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSECKEYPublicKey* SignatureVerifier::DecodePublicKeyInfo(
195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const uint8* public_key_info,
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int public_key_info_len) {
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CERTSubjectPublicKeyInfo* spki = NULL;
198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SECItem spki_der;
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spki_der.type = siBuffer;
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spki_der.data = const_cast<uint8*>(public_key_info);
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spki_der.len = public_key_info_len;
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der);
203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!spki)
204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return NULL;
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki);
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SECKEY_DestroySubjectPublicKeyInfo(spki);  // Done with spki.
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return public_key;
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SignatureVerifier::Reset() {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (vfy_context_) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VFY_DestroyContext(vfy_context_, PR_TRUE);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vfy_context_ = NULL;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (hash_context_) {
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    HASH_Destroy(hash_context_);
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    hash_context_ = NULL;
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (public_key_) {
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SECKEY_DestroyPublicKey(public_key_);
221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public_key_ = NULL;
222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signature_.clear();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace crypto
227