Home | History | Annotate | Download | only in crypto
      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 <cryptohi.h>
      8 #include <keyhi.h>
      9 #include <pk11pub.h>
     10 #include <secerr.h>
     11 #include <sechash.h>
     12 #include <stdint.h>
     13 #include <stdlib.h>
     14 
     15 #include "base/logging.h"
     16 #include "crypto/nss_util.h"
     17 #include "crypto/third_party/nss/chromium-nss.h"
     18 
     19 namespace crypto {
     20 
     21 namespace {
     22 
     23 HASH_HashType ToNSSHashType(SignatureVerifier::HashAlgorithm hash_alg) {
     24   switch (hash_alg) {
     25     case SignatureVerifier::SHA1:
     26       return HASH_AlgSHA1;
     27     case SignatureVerifier::SHA256:
     28       return HASH_AlgSHA256;
     29   }
     30   return HASH_AlgNULL;
     31 }
     32 
     33 SECStatus VerifyRSAPSS_End(SECKEYPublicKey* public_key,
     34                            HASHContext* hash_context,
     35                            HASH_HashType mask_hash_alg,
     36                            unsigned int salt_len,
     37                            const unsigned char* signature,
     38                            unsigned int signature_len) {
     39   unsigned int hash_len = HASH_ResultLenContext(hash_context);
     40   std::vector<unsigned char> hash(hash_len);
     41   HASH_End(hash_context, &hash[0], &hash_len, hash.size());
     42 
     43   unsigned int modulus_len = SECKEY_PublicKeyStrength(public_key);
     44   if (signature_len != modulus_len) {
     45     PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
     46     return SECFailure;
     47   }
     48   std::vector<unsigned char> enc(signature_len);
     49   SECStatus rv = PK11_PubEncryptRaw(public_key, &enc[0],
     50                                     const_cast<unsigned char*>(signature),
     51                                     signature_len, NULL);
     52   if (rv != SECSuccess) {
     53     LOG(WARNING) << "PK11_PubEncryptRaw failed";
     54     return rv;
     55   }
     56   return emsa_pss_verify(&hash[0], &enc[0], enc.size(),
     57                          HASH_GetType(hash_context), mask_hash_alg,
     58                          salt_len);
     59 }
     60 
     61 }  // namespace
     62 
     63 SignatureVerifier::SignatureVerifier()
     64     : vfy_context_(NULL),
     65       hash_alg_(SHA1),
     66       mask_hash_alg_(SHA1),
     67       salt_len_(0),
     68       public_key_(NULL),
     69       hash_context_(NULL) {
     70   EnsureNSSInit();
     71 }
     72 
     73 SignatureVerifier::~SignatureVerifier() {
     74   Reset();
     75 }
     76 
     77 bool SignatureVerifier::VerifyInit(const uint8_t* signature_algorithm,
     78                                    int signature_algorithm_len,
     79                                    const uint8_t* signature,
     80                                    int signature_len,
     81                                    const uint8_t* public_key_info,
     82                                    int public_key_info_len) {
     83   if (vfy_context_ || hash_context_)
     84     return false;
     85 
     86   signature_.assign(signature, signature + signature_len);
     87 
     88   SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info,
     89                                                     public_key_info_len);
     90   if (!public_key)
     91     return false;
     92 
     93   PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     94   if (!arena) {
     95     SECKEY_DestroyPublicKey(public_key);
     96     return false;
     97   }
     98 
     99   SECItem sig_alg_der;
    100   sig_alg_der.type = siBuffer;
    101   sig_alg_der.data = const_cast<uint8_t*>(signature_algorithm);
    102   sig_alg_der.len = signature_algorithm_len;
    103   SECAlgorithmID sig_alg_id;
    104   SECStatus rv;
    105   rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id,
    106                               SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
    107                               &sig_alg_der);
    108   if (rv != SECSuccess) {
    109     SECKEY_DestroyPublicKey(public_key);
    110     PORT_FreeArena(arena, PR_TRUE);
    111     return false;
    112   }
    113 
    114   SECItem sig;
    115   sig.type = siBuffer;
    116   sig.data = const_cast<uint8_t*>(signature);
    117   sig.len = signature_len;
    118   SECOidTag hash_alg_tag;
    119   vfy_context_ = VFY_CreateContextWithAlgorithmID(public_key, &sig,
    120                                                   &sig_alg_id, &hash_alg_tag,
    121                                                   NULL);
    122   SECKEY_DestroyPublicKey(public_key);  // Done with public_key.
    123   PORT_FreeArena(arena, PR_TRUE);  // Done with sig_alg_id.
    124   if (!vfy_context_) {
    125     // A corrupted RSA signature could be detected without the data, so
    126     // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE
    127     // (-8182).
    128     return false;
    129   }
    130 
    131   rv = VFY_Begin(vfy_context_);
    132   if (rv != SECSuccess) {
    133     NOTREACHED();
    134     return false;
    135   }
    136   return true;
    137 }
    138 
    139 bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg,
    140                                          HashAlgorithm mask_hash_alg,
    141                                          int salt_len,
    142                                          const uint8_t* signature,
    143                                          int signature_len,
    144                                          const uint8_t* public_key_info,
    145                                          int public_key_info_len) {
    146   if (vfy_context_ || hash_context_)
    147     return false;
    148 
    149   signature_.assign(signature, signature + signature_len);
    150 
    151   SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info,
    152                                                     public_key_info_len);
    153   if (!public_key)
    154     return false;
    155 
    156   public_key_ = public_key;
    157   hash_alg_ = hash_alg;
    158   mask_hash_alg_ = mask_hash_alg;
    159   salt_len_ = salt_len;
    160   hash_context_ = HASH_Create(ToNSSHashType(hash_alg_));
    161   if (!hash_context_)
    162     return false;
    163   HASH_Begin(hash_context_);
    164   return true;
    165 }
    166 
    167 void SignatureVerifier::VerifyUpdate(const uint8_t* data_part,
    168                                      int data_part_len) {
    169   if (vfy_context_) {
    170     SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len);
    171     DCHECK_EQ(SECSuccess, rv);
    172   } else {
    173     HASH_Update(hash_context_, data_part, data_part_len);
    174   }
    175 }
    176 
    177 bool SignatureVerifier::VerifyFinal() {
    178   SECStatus rv;
    179   if (vfy_context_) {
    180     rv = VFY_End(vfy_context_);
    181   } else {
    182     rv = VerifyRSAPSS_End(public_key_, hash_context_,
    183                           ToNSSHashType(mask_hash_alg_), salt_len_,
    184                           signature_.data(),
    185                           signature_.size());
    186   }
    187   Reset();
    188 
    189   // If signature verification fails, the error code is
    190   // SEC_ERROR_BAD_SIGNATURE (-8182).
    191   return (rv == SECSuccess);
    192 }
    193 
    194 // static
    195 SECKEYPublicKey* SignatureVerifier::DecodePublicKeyInfo(
    196     const uint8_t* public_key_info,
    197     int public_key_info_len) {
    198   CERTSubjectPublicKeyInfo* spki = NULL;
    199   SECItem spki_der;
    200   spki_der.type = siBuffer;
    201   spki_der.data = const_cast<uint8_t*>(public_key_info);
    202   spki_der.len = public_key_info_len;
    203   spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der);
    204   if (!spki)
    205     return NULL;
    206   SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki);
    207   SECKEY_DestroySubjectPublicKeyInfo(spki);  // Done with spki.
    208   return public_key;
    209 }
    210 
    211 void SignatureVerifier::Reset() {
    212   if (vfy_context_) {
    213     VFY_DestroyContext(vfy_context_, PR_TRUE);
    214     vfy_context_ = NULL;
    215   }
    216   if (hash_context_) {
    217     HASH_Destroy(hash_context_);
    218     hash_context_ = NULL;
    219   }
    220   if (public_key_) {
    221     SECKEY_DestroyPublicKey(public_key_);
    222     public_key_ = NULL;
    223   }
    224   signature_.clear();
    225 }
    226 
    227 }  // namespace crypto
    228