• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2008 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 "base/hmac.h"
6 
7 #include <nss.h>
8 #include <pk11pub.h>
9 
10 #include "base/logging.h"
11 #include "base/nss_util.h"
12 #include "base/scoped_ptr.h"
13 
14 namespace {
15 
16 template <typename Type, void (*Destroyer)(Type*)>
17 struct NSSDestroyer {
operator ()__anon982e36f80111::NSSDestroyer18   void operator()(Type* ptr) const {
19     if (ptr)
20       Destroyer(ptr);
21   }
22 };
23 
DestroyContext(PK11Context * context)24 void DestroyContext(PK11Context* context) {
25   PK11_DestroyContext(context, PR_TRUE);
26 }
27 
28 // Define some convenient scopers around NSS pointers.
29 typedef scoped_ptr_malloc<
30     PK11SlotInfo, NSSDestroyer<PK11SlotInfo, PK11_FreeSlot> > ScopedNSSSlot;
31 typedef scoped_ptr_malloc<
32     PK11SymKey, NSSDestroyer<PK11SymKey, PK11_FreeSymKey> > ScopedNSSSymKey;
33 typedef scoped_ptr_malloc<
34     PK11Context, NSSDestroyer<PK11Context, DestroyContext> > ScopedNSSContext;
35 
36 }  // namespace
37 
38 namespace base {
39 
40 struct HMACPlatformData {
41   ScopedNSSSlot slot_;
42   ScopedNSSSymKey sym_key_;
43 };
44 
HMAC(HashAlgorithm hash_alg)45 HMAC::HMAC(HashAlgorithm hash_alg)
46     : hash_alg_(hash_alg), plat_(new HMACPlatformData()) {
47   // Only SHA-1 digest is supported now.
48   DCHECK(hash_alg_ == SHA1);
49 }
50 
Init(const unsigned char * key,int key_length)51 bool HMAC::Init(const unsigned char *key, int key_length) {
52   base::EnsureNSSInit();
53 
54   if (hash_alg_ != SHA1) {
55     NOTREACHED();
56     return false;
57   }
58 
59   if (plat_->slot_.get()) {
60     // Init must not be called more than twice on the same HMAC object.
61     NOTREACHED();
62     return false;
63   }
64 
65   plat_->slot_.reset(PK11_GetBestSlot(CKM_SHA_1_HMAC, NULL));
66   if (!plat_->slot_.get()) {
67     NOTREACHED();
68     return false;
69   }
70 
71   SECItem key_item;
72   key_item.type = siBuffer;
73   key_item.data = const_cast<unsigned char*>(key);  // NSS API isn't const.
74   key_item.len = key_length;
75 
76   plat_->sym_key_.reset(PK11_ImportSymKey(plat_->slot_.get(),
77                                           CKM_SHA_1_HMAC,
78                                           PK11_OriginUnwrap,
79                                           CKA_SIGN,
80                                           &key_item,
81                                           NULL));
82   if (!plat_->sym_key_.get()) {
83     NOTREACHED();
84     return false;
85   }
86 
87   return true;
88 }
89 
~HMAC()90 HMAC::~HMAC() {
91 }
92 
Sign(const std::string & data,unsigned char * digest,int digest_length)93 bool HMAC::Sign(const std::string& data,
94                 unsigned char* digest,
95                 int digest_length) {
96   if (!plat_->sym_key_.get()) {
97     // Init has not been called before Sign.
98     NOTREACHED();
99     return false;
100   }
101 
102   SECItem param = { siBuffer, NULL, 0 };
103   ScopedNSSContext context(PK11_CreateContextBySymKey(CKM_SHA_1_HMAC,
104                                                       CKA_SIGN,
105                                                       plat_->sym_key_.get(),
106                                                       &param));
107   if (!context.get()) {
108     NOTREACHED();
109     return false;
110   }
111 
112   if (PK11_DigestBegin(context.get()) != SECSuccess) {
113     NOTREACHED();
114     return false;
115   }
116 
117   if (PK11_DigestOp(context.get(),
118                     reinterpret_cast<const unsigned char*>(data.data()),
119                     data.length()) != SECSuccess) {
120     NOTREACHED();
121     return false;
122   }
123 
124   unsigned int len = 0;
125   if (PK11_DigestFinal(context.get(),
126                        digest, &len, digest_length) != SECSuccess) {
127     NOTREACHED();
128     return false;
129   }
130 
131   return true;
132 }
133 
134 }  // namespace base
135