| OLD | NEW |
| (Empty) |
| 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/hmac.h" | |
| 6 | |
| 7 #include <nss.h> | |
| 8 #include <pk11pub.h> | |
| 9 #include <stddef.h> | |
| 10 | |
| 11 #include <memory> | |
| 12 | |
| 13 #include "base/logging.h" | |
| 14 #include "crypto/nss_util.h" | |
| 15 #include "crypto/scoped_nss_types.h" | |
| 16 | |
| 17 namespace crypto { | |
| 18 | |
| 19 struct HMACPlatformData { | |
| 20 CK_MECHANISM_TYPE mechanism_; | |
| 21 ScopedPK11Slot slot_; | |
| 22 ScopedPK11SymKey sym_key_; | |
| 23 }; | |
| 24 | |
| 25 HMAC::HMAC(HashAlgorithm hash_alg) | |
| 26 : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { | |
| 27 // Only SHA-1 and SHA-256 hash algorithms are supported. | |
| 28 switch (hash_alg_) { | |
| 29 case SHA1: | |
| 30 plat_->mechanism_ = CKM_SHA_1_HMAC; | |
| 31 break; | |
| 32 case SHA256: | |
| 33 plat_->mechanism_ = CKM_SHA256_HMAC; | |
| 34 break; | |
| 35 default: | |
| 36 NOTREACHED() << "Unsupported hash algorithm"; | |
| 37 break; | |
| 38 } | |
| 39 } | |
| 40 | |
| 41 HMAC::~HMAC() { | |
| 42 } | |
| 43 | |
| 44 bool HMAC::Init(const unsigned char *key, size_t key_length) { | |
| 45 EnsureNSSInit(); | |
| 46 | |
| 47 if (plat_->slot_.get()) { | |
| 48 // Init must not be called more than twice on the same HMAC object. | |
| 49 NOTREACHED(); | |
| 50 return false; | |
| 51 } | |
| 52 | |
| 53 plat_->slot_.reset(PK11_GetInternalSlot()); | |
| 54 if (!plat_->slot_.get()) { | |
| 55 NOTREACHED(); | |
| 56 return false; | |
| 57 } | |
| 58 | |
| 59 SECItem key_item; | |
| 60 key_item.type = siBuffer; | |
| 61 key_item.data = const_cast<unsigned char*>(key); // NSS API isn't const. | |
| 62 key_item.len = key_length; | |
| 63 | |
| 64 plat_->sym_key_.reset(PK11_ImportSymKey(plat_->slot_.get(), | |
| 65 plat_->mechanism_, | |
| 66 PK11_OriginUnwrap, | |
| 67 CKA_SIGN, | |
| 68 &key_item, | |
| 69 NULL)); | |
| 70 if (!plat_->sym_key_.get()) { | |
| 71 NOTREACHED(); | |
| 72 return false; | |
| 73 } | |
| 74 | |
| 75 return true; | |
| 76 } | |
| 77 | |
| 78 bool HMAC::Sign(const base::StringPiece& data, | |
| 79 unsigned char* digest, | |
| 80 size_t digest_length) const { | |
| 81 if (!plat_->sym_key_.get()) { | |
| 82 // Init has not been called before Sign. | |
| 83 NOTREACHED(); | |
| 84 return false; | |
| 85 } | |
| 86 | |
| 87 SECItem param = { siBuffer, NULL, 0 }; | |
| 88 ScopedPK11Context context(PK11_CreateContextBySymKey(plat_->mechanism_, | |
| 89 CKA_SIGN, | |
| 90 plat_->sym_key_.get(), | |
| 91 ¶m)); | |
| 92 if (!context.get()) { | |
| 93 NOTREACHED(); | |
| 94 return false; | |
| 95 } | |
| 96 | |
| 97 if (PK11_DigestBegin(context.get()) != SECSuccess) { | |
| 98 NOTREACHED(); | |
| 99 return false; | |
| 100 } | |
| 101 | |
| 102 if (PK11_DigestOp(context.get(), | |
| 103 reinterpret_cast<const unsigned char*>(data.data()), | |
| 104 data.length()) != SECSuccess) { | |
| 105 NOTREACHED(); | |
| 106 return false; | |
| 107 } | |
| 108 | |
| 109 unsigned int len = 0; | |
| 110 if (PK11_DigestFinal(context.get(), | |
| 111 digest, &len, digest_length) != SECSuccess) { | |
| 112 NOTREACHED(); | |
| 113 return false; | |
| 114 } | |
| 115 | |
| 116 return true; | |
| 117 } | |
| 118 | |
| 119 } // namespace crypto | |
| OLD | NEW |