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 SECOidTag ToNSSSignatureType(SignatureVerifier::SignatureAlgorithm sig_alg) {
     34   switch (sig_alg) {
     35     case SignatureVerifier::RSA_PKCS1_SHA1:
     36       return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
     37     case SignatureVerifier::RSA_PKCS1_SHA256:
     38       return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
     39     case SignatureVerifier::ECDSA_SHA256:
     40       return SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
     41   }
     42   return SEC_OID_UNKNOWN;
     43 }
     44 
     45 SECStatus VerifyRSAPSS_End(SECKEYPublicKey* public_key,
     46                            HASHContext* hash_context,
     47                            HASH_HashType mask_hash_alg,
     48                            unsigned int salt_len,
     49                            const unsigned char* signature,
     50                            unsigned int signature_len) {
     51   unsigned int hash_len = HASH_ResultLenContext(hash_context);
     52   std::vector<unsigned char> hash(hash_len);
     53   HASH_End(hash_context, &hash[0], &hash_len, hash.size());
     54 
     55   unsigned int modulus_len = SECKEY_PublicKeyStrength(public_key);
     56   if (signature_len != modulus_len) {
     57     PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
     58     return SECFailure;
     59   }
     60   std::vector<unsigned char> enc(signature_len);
     61   SECStatus rv = PK11_PubEncryptRaw(public_key, &enc[0],
     62                                     const_cast<unsigned char*>(signature),
     63                                     signature_len, NULL);
     64   if (rv != SECSuccess) {
     65     LOG(WARNING) << "PK11_PubEncryptRaw failed";
     66     return rv;
     67   }
     68   return emsa_pss_verify(&hash[0], &enc[0], enc.size(),
     69                          HASH_GetType(hash_context), mask_hash_alg,
     70                          salt_len);
     71 }
     72 
     73 }  // namespace
     74 
     75 SignatureVerifier::SignatureVerifier()
     76     : vfy_context_(NULL),
     77       hash_alg_(SHA1),
     78       mask_hash_alg_(SHA1),
     79       salt_len_(0),
     80       public_key_(NULL),
     81       hash_context_(NULL) {
     82   EnsureNSSInit();
     83 }
     84 
     85 SignatureVerifier::~SignatureVerifier() {
     86   Reset();
     87 }
     88 
     89 bool SignatureVerifier::VerifyInit(SignatureAlgorithm signature_algorithm,
     90                                    const uint8_t* signature,
     91                                    int signature_len,
     92                                    const uint8_t* public_key_info,
     93                                    int public_key_info_len) {
     94   if (vfy_context_ || hash_context_)
     95     return false;
     96 
     97   signature_.assign(signature, signature + signature_len);
     98 
     99   SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info,
    100                                                     public_key_info_len);
    101   if (!public_key)
    102     return false;
    103 
    104   SECItem sig;
    105   sig.type = siBuffer;
    106   sig.data = const_cast<uint8_t*>(signature);
    107   sig.len = signature_len;
    108   vfy_context_ = VFY_CreateContext(
    109       public_key, &sig, ToNSSSignatureType(signature_algorithm), nullptr);
    110   SECKEY_DestroyPublicKey(public_key);  // Done with public_key.
    111   if (!vfy_context_) {
    112     // A corrupted RSA signature could be detected without the data, so
    113     // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE
    114     // (-8182).
    115     return false;
    116   }
    117 
    118   if (VFY_Begin(vfy_context_) != SECSuccess) {
    119     NOTREACHED();
    120     return false;
    121   }
    122   return true;
    123 }
    124 
    125 bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg,
    126                                          HashAlgorithm mask_hash_alg,
    127                                          int salt_len,
    128                                          const uint8_t* signature,
    129                                          int signature_len,
    130                                          const uint8_t* public_key_info,
    131                                          int public_key_info_len) {
    132   if (vfy_context_ || hash_context_)
    133     return false;
    134 
    135   signature_.assign(signature, signature + signature_len);
    136 
    137   SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info,
    138                                                     public_key_info_len);
    139   if (!public_key)
    140     return false;
    141 
    142   public_key_ = public_key;
    143   hash_alg_ = hash_alg;
    144   mask_hash_alg_ = mask_hash_alg;
    145   salt_len_ = salt_len;
    146   hash_context_ = HASH_Create(ToNSSHashType(hash_alg_));
    147   if (!hash_context_)
    148     return false;
    149   HASH_Begin(hash_context_);
    150   return true;
    151 }
    152 
    153 void SignatureVerifier::VerifyUpdate(const uint8_t* data_part,
    154                                      int data_part_len) {
    155   if (vfy_context_) {
    156     SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len);
    157     DCHECK_EQ(SECSuccess, rv);
    158   } else {
    159     HASH_Update(hash_context_, data_part, data_part_len);
    160   }
    161 }
    162 
    163 bool SignatureVerifier::VerifyFinal() {
    164   SECStatus rv;
    165   if (vfy_context_) {
    166     rv = VFY_End(vfy_context_);
    167   } else {
    168     rv = VerifyRSAPSS_End(public_key_, hash_context_,
    169                           ToNSSHashType(mask_hash_alg_), salt_len_,
    170                           signature_.data(),
    171                           signature_.size());
    172   }
    173   Reset();
    174 
    175   // If signature verification fails, the error code is
    176   // SEC_ERROR_BAD_SIGNATURE (-8182).
    177   return (rv == SECSuccess);
    178 }
    179 
    180 // static
    181 SECKEYPublicKey* SignatureVerifier::DecodePublicKeyInfo(
    182     const uint8_t* public_key_info,
    183     int public_key_info_len) {
    184   CERTSubjectPublicKeyInfo* spki = NULL;
    185   SECItem spki_der;
    186   spki_der.type = siBuffer;
    187   spki_der.data = const_cast<uint8_t*>(public_key_info);
    188   spki_der.len = public_key_info_len;
    189   spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der);
    190   if (!spki)
    191     return NULL;
    192   SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki);
    193   SECKEY_DestroySubjectPublicKeyInfo(spki);  // Done with spki.
    194   return public_key;
    195 }
    196 
    197 void SignatureVerifier::Reset() {
    198   if (vfy_context_) {
    199     VFY_DestroyContext(vfy_context_, PR_TRUE);
    200     vfy_context_ = NULL;
    201   }
    202   if (hash_context_) {
    203     HASH_Destroy(hash_context_);
    204     hash_context_ = NULL;
    205   }
    206   if (public_key_) {
    207     SECKEY_DestroyPublicKey(public_key_);
    208     public_key_ = NULL;
    209   }
    210   signature_.clear();
    211 }
    212 
    213 }  // namespace crypto
    214