Removed data compression UMA from ProxyService
[chromium-blink-merge.git] / content / child / webcrypto / nss / hmac_nss.cc
blobf02be408d7f8064b09bafd3b843e9ea02226245d
1 // Copyright 2014 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.
5 #include <cryptohi.h>
6 #include <pk11pub.h>
7 #include <secerr.h>
8 #include <sechash.h>
10 #include "base/logging.h"
11 #include "base/stl_util.h"
12 #include "content/child/webcrypto/algorithm_implementation.h"
13 #include "content/child/webcrypto/crypto_data.h"
14 #include "content/child/webcrypto/jwk.h"
15 #include "content/child/webcrypto/nss/key_nss.h"
16 #include "content/child/webcrypto/nss/sym_key_nss.h"
17 #include "content/child/webcrypto/nss/util_nss.h"
18 #include "content/child/webcrypto/status.h"
19 #include "content/child/webcrypto/webcrypto_util.h"
20 #include "crypto/secure_util.h"
21 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
22 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
24 namespace content {
26 namespace webcrypto {
28 namespace {
30 const blink::WebCryptoKeyUsageMask kAllKeyUsages =
31 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
33 bool WebCryptoHashToHMACMechanism(const blink::WebCryptoAlgorithm& algorithm,
34 CK_MECHANISM_TYPE* mechanism) {
35 switch (algorithm.id()) {
36 case blink::WebCryptoAlgorithmIdSha1:
37 *mechanism = CKM_SHA_1_HMAC;
38 return true;
39 case blink::WebCryptoAlgorithmIdSha256:
40 *mechanism = CKM_SHA256_HMAC;
41 return true;
42 case blink::WebCryptoAlgorithmIdSha384:
43 *mechanism = CKM_SHA384_HMAC;
44 return true;
45 case blink::WebCryptoAlgorithmIdSha512:
46 *mechanism = CKM_SHA512_HMAC;
47 return true;
48 default:
49 return false;
53 class HmacImplementation : public AlgorithmImplementation {
54 public:
55 HmacImplementation() {}
57 virtual Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm,
58 bool extractable,
59 blink::WebCryptoKeyUsageMask usage_mask,
60 blink::WebCryptoKey* key) const OVERRIDE {
61 const blink::WebCryptoHmacKeyGenParams* params =
62 algorithm.hmacKeyGenParams();
64 const blink::WebCryptoAlgorithm& hash = params->hash();
65 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
66 if (!WebCryptoHashToHMACMechanism(hash, &mechanism))
67 return Status::ErrorUnsupported();
69 unsigned int keylen_bits = 0;
70 Status status = GetHmacKeyGenLengthInBits(params, &keylen_bits);
71 if (status.IsError())
72 return status;
74 return GenerateSecretKeyNss(
75 blink::WebCryptoKeyAlgorithm::createHmac(hash.id(), keylen_bits),
76 extractable,
77 usage_mask,
78 keylen_bits / 8,
79 mechanism,
80 key);
83 virtual Status VerifyKeyUsagesBeforeImportKey(
84 blink::WebCryptoKeyFormat format,
85 blink::WebCryptoKeyUsageMask usage_mask) const OVERRIDE {
86 switch (format) {
87 case blink::WebCryptoKeyFormatRaw:
88 case blink::WebCryptoKeyFormatJwk:
89 return CheckKeyCreationUsages(kAllKeyUsages, usage_mask);
90 default:
91 return Status::ErrorUnsupportedImportKeyFormat();
95 virtual Status VerifyKeyUsagesBeforeGenerateKey(
96 blink::WebCryptoKeyUsageMask usage_mask) const OVERRIDE {
97 return CheckKeyCreationUsages(kAllKeyUsages, usage_mask);
100 virtual Status ImportKeyRaw(const CryptoData& key_data,
101 const blink::WebCryptoAlgorithm& algorithm,
102 bool extractable,
103 blink::WebCryptoKeyUsageMask usage_mask,
104 blink::WebCryptoKey* key) const OVERRIDE {
105 const blink::WebCryptoAlgorithm& hash =
106 algorithm.hmacImportParams()->hash();
108 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
109 if (!WebCryptoHashToHMACMechanism(hash, &mechanism))
110 return Status::ErrorUnsupported();
112 // TODO(eroman): check for overflow.
113 unsigned int keylen_bits = key_data.byte_length() * 8;
114 return ImportKeyRawNss(
115 key_data,
116 blink::WebCryptoKeyAlgorithm::createHmac(hash.id(), keylen_bits),
117 extractable,
118 usage_mask,
119 mechanism,
120 CKF_SIGN | CKF_VERIFY,
121 key);
124 virtual Status ImportKeyJwk(const CryptoData& key_data,
125 const blink::WebCryptoAlgorithm& algorithm,
126 bool extractable,
127 blink::WebCryptoKeyUsageMask usage_mask,
128 blink::WebCryptoKey* key) const OVERRIDE {
129 const char* algorithm_name =
130 GetJwkHmacAlgorithmName(algorithm.hmacImportParams()->hash().id());
131 if (!algorithm_name)
132 return Status::ErrorUnexpected();
134 std::vector<uint8_t> raw_data;
135 Status status = ReadSecretKeyJwk(
136 key_data, algorithm_name, extractable, usage_mask, &raw_data);
137 if (status.IsError())
138 return status;
140 return ImportKeyRaw(
141 CryptoData(raw_data), algorithm, extractable, usage_mask, key);
144 virtual Status ExportKeyRaw(const blink::WebCryptoKey& key,
145 std::vector<uint8_t>* buffer) const OVERRIDE {
146 *buffer = SymKeyNss::Cast(key)->raw_key_data();
147 return Status::Success();
150 virtual Status ExportKeyJwk(const blink::WebCryptoKey& key,
151 std::vector<uint8_t>* buffer) const OVERRIDE {
152 SymKeyNss* sym_key = SymKeyNss::Cast(key);
153 const std::vector<uint8_t>& raw_data = sym_key->raw_key_data();
155 const char* algorithm_name =
156 GetJwkHmacAlgorithmName(key.algorithm().hmacParams()->hash().id());
157 if (!algorithm_name)
158 return Status::ErrorUnexpected();
160 WriteSecretKeyJwk(CryptoData(raw_data),
161 algorithm_name,
162 key.extractable(),
163 key.usages(),
164 buffer);
166 return Status::Success();
169 virtual Status Sign(const blink::WebCryptoAlgorithm& algorithm,
170 const blink::WebCryptoKey& key,
171 const CryptoData& data,
172 std::vector<uint8_t>* buffer) const OVERRIDE {
173 const blink::WebCryptoAlgorithm& hash =
174 key.algorithm().hmacParams()->hash();
175 PK11SymKey* sym_key = SymKeyNss::Cast(key)->key();
177 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
178 if (!WebCryptoHashToHMACMechanism(hash, &mechanism))
179 return Status::ErrorUnexpected();
181 SECItem param_item = {siBuffer, NULL, 0};
182 SECItem data_item = MakeSECItemForBuffer(data);
183 // First call is to figure out the length.
184 SECItem signature_item = {siBuffer, NULL, 0};
186 if (PK11_SignWithSymKey(
187 sym_key, mechanism, &param_item, &signature_item, &data_item) !=
188 SECSuccess) {
189 return Status::OperationError();
192 DCHECK_NE(0u, signature_item.len);
194 buffer->resize(signature_item.len);
195 signature_item.data = vector_as_array(buffer);
197 if (PK11_SignWithSymKey(
198 sym_key, mechanism, &param_item, &signature_item, &data_item) !=
199 SECSuccess) {
200 return Status::OperationError();
203 CHECK_EQ(buffer->size(), signature_item.len);
204 return Status::Success();
207 virtual Status Verify(const blink::WebCryptoAlgorithm& algorithm,
208 const blink::WebCryptoKey& key,
209 const CryptoData& signature,
210 const CryptoData& data,
211 bool* signature_match) const OVERRIDE {
212 std::vector<uint8_t> result;
213 Status status = Sign(algorithm, key, data, &result);
215 if (status.IsError())
216 return status;
218 // Do not allow verification of truncated MACs.
219 *signature_match = result.size() == signature.byte_length() &&
220 crypto::SecureMemEqual(vector_as_array(&result),
221 signature.bytes(),
222 signature.byte_length());
224 return Status::Success();
228 } // namespace
230 AlgorithmImplementation* CreatePlatformHmacImplementation() {
231 return new HmacImplementation;
234 } // namespace webcrypto
236 } // namespace content