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 "base/logging.h" 8 9 #pragma comment(lib, "crypt32.lib") 10 11 namespace { 12 13 // Wrappers of malloc and free for CRYPT_DECODE_PARA, which requires the 14 // WINAPI calling convention. 15 void* WINAPI MyCryptAlloc(size_t size) { 16 return malloc(size); 17 } 18 19 void WINAPI MyCryptFree(void* p) { 20 free(p); 21 } 22 23 } // namespace 24 25 namespace crypto { 26 27 SignatureVerifier::SignatureVerifier() : hash_object_(0), public_key_(0) { 28 if (!CryptAcquireContext(provider_.receive(), NULL, NULL, 29 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) 30 provider_.reset(); 31 } 32 33 SignatureVerifier::~SignatureVerifier() { 34 } 35 36 bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm, 37 int signature_algorithm_len, 38 const uint8* signature, 39 int signature_len, 40 const uint8* public_key_info, 41 int public_key_info_len) { 42 signature_.reserve(signature_len); 43 // CryptoAPI uses big integers in the little-endian byte order, so we need 44 // to first swap the order of signature bytes. 45 for (int i = signature_len - 1; i >= 0; --i) 46 signature_.push_back(signature[i]); 47 48 CRYPT_DECODE_PARA decode_para; 49 decode_para.cbSize = sizeof(decode_para); 50 decode_para.pfnAlloc = MyCryptAlloc; 51 decode_para.pfnFree = MyCryptFree; 52 CERT_PUBLIC_KEY_INFO* cert_public_key_info = NULL; 53 DWORD struct_len = 0; 54 BOOL ok; 55 ok = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 56 X509_PUBLIC_KEY_INFO, 57 public_key_info, 58 public_key_info_len, 59 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, 60 &decode_para, 61 &cert_public_key_info, 62 &struct_len); 63 if (!ok) 64 return false; 65 66 ok = CryptImportPublicKeyInfo(provider_, 67 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 68 cert_public_key_info, public_key_.receive()); 69 free(cert_public_key_info); 70 if (!ok) 71 return false; 72 73 CRYPT_ALGORITHM_IDENTIFIER* signature_algorithm_id; 74 struct_len = 0; 75 ok = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 76 X509_ALGORITHM_IDENTIFIER, 77 signature_algorithm, 78 signature_algorithm_len, 79 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, 80 &decode_para, 81 &signature_algorithm_id, 82 &struct_len); 83 DCHECK(ok || GetLastError() == ERROR_FILE_NOT_FOUND); 84 ALG_ID hash_alg_id; 85 if (ok) { 86 hash_alg_id = CALG_MD4; // Initialize to a weak hash algorithm that we 87 // don't support. 88 if (!strcmp(signature_algorithm_id->pszObjId, szOID_RSA_SHA1RSA)) 89 hash_alg_id = CALG_SHA1; 90 else if (!strcmp(signature_algorithm_id->pszObjId, szOID_RSA_MD5RSA)) 91 hash_alg_id = CALG_MD5; 92 free(signature_algorithm_id); 93 DCHECK(hash_alg_id != CALG_MD4); 94 if (hash_alg_id == CALG_MD4) 95 return false; // Unsupported hash algorithm. 96 } else if (GetLastError() == ERROR_FILE_NOT_FOUND) { 97 // TODO(wtc): X509_ALGORITHM_IDENTIFIER isn't supported on XP SP2. We 98 // may be able to encapsulate signature_algorithm in a dummy SignedContent 99 // and decode it with X509_CERT into a CERT_SIGNED_CONTENT_INFO. For now, 100 // just hardcode the hash algorithm to be SHA-1. 101 hash_alg_id = CALG_SHA1; 102 } else { 103 return false; 104 } 105 106 ok = CryptCreateHash(provider_, hash_alg_id, 0, 0, hash_object_.receive()); 107 if (!ok) 108 return false; 109 return true; 110 } 111 112 void SignatureVerifier::VerifyUpdate(const uint8* data_part, 113 int data_part_len) { 114 BOOL ok = CryptHashData(hash_object_, data_part, data_part_len, 0); 115 DCHECK(ok) << "CryptHashData failed: " << GetLastError(); 116 } 117 118 bool SignatureVerifier::VerifyFinal() { 119 BOOL ok = CryptVerifySignature(hash_object_, &signature_[0], 120 signature_.size(), public_key_, NULL, 0); 121 Reset(); 122 if (!ok) 123 return false; 124 return true; 125 } 126 127 void SignatureVerifier::Reset() { 128 hash_object_.reset(); 129 public_key_.reset(); 130 signature_.clear(); 131 } 132 133 } // namespace crypto 134 135