Removed data compression UMA from ProxyService
[chromium-blink-merge.git] / content / child / webcrypto / openssl / hmac_openssl.cc
blob5d19a451434b1175bc65aafb4e86cfabc045b314
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 <openssl/hmac.h>
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "content/child/webcrypto/algorithm_implementation.h"
10 #include "content/child/webcrypto/crypto_data.h"
11 #include "content/child/webcrypto/jwk.h"
12 #include "content/child/webcrypto/openssl/key_openssl.h"
13 #include "content/child/webcrypto/openssl/sym_key_openssl.h"
14 #include "content/child/webcrypto/openssl/util_openssl.h"
15 #include "content/child/webcrypto/status.h"
16 #include "content/child/webcrypto/webcrypto_util.h"
17 #include "crypto/openssl_util.h"
18 #include "crypto/secure_util.h"
19 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
20 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
22 namespace content {
24 namespace webcrypto {
26 namespace {
28 const blink::WebCryptoKeyUsageMask kAllKeyUsages =
29 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
31 Status SignHmac(const std::vector<uint8_t>& raw_key,
32 const blink::WebCryptoAlgorithm& hash,
33 const CryptoData& data,
34 std::vector<uint8_t>* buffer) {
35 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
37 const EVP_MD* digest_algorithm = GetDigest(hash.id());
38 if (!digest_algorithm)
39 return Status::ErrorUnsupported();
40 unsigned int hmac_expected_length = EVP_MD_size(digest_algorithm);
42 // OpenSSL wierdness here.
43 // First, HMAC() needs a void* for the key data, so make one up front as a
44 // cosmetic to avoid a cast. Second, OpenSSL does not like a NULL key,
45 // which will result if the raw_key vector is empty; an entirely valid
46 // case. Handle this specific case by pointing to an empty array.
47 const unsigned char null_key[] = {};
48 const void* const raw_key_voidp = raw_key.size() ? &raw_key[0] : null_key;
50 buffer->resize(hmac_expected_length);
51 crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result(
52 vector_as_array(buffer), hmac_expected_length);
54 unsigned int hmac_actual_length;
55 unsigned char* const success = HMAC(digest_algorithm,
56 raw_key_voidp,
57 raw_key.size(),
58 data.bytes(),
59 data.byte_length(),
60 hmac_result.safe_buffer(),
61 &hmac_actual_length);
62 if (!success || hmac_actual_length != hmac_expected_length)
63 return Status::OperationError();
65 return Status::Success();
68 class HmacImplementation : public AlgorithmImplementation {
69 public:
70 HmacImplementation() {}
72 virtual Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm,
73 bool extractable,
74 blink::WebCryptoKeyUsageMask usage_mask,
75 blink::WebCryptoKey* key) const OVERRIDE {
76 const blink::WebCryptoHmacKeyGenParams* params =
77 algorithm.hmacKeyGenParams();
79 unsigned int keylen_bits = 0;
80 Status status = GetHmacKeyGenLengthInBits(params, &keylen_bits);
81 if (status.IsError())
82 return status;
84 return GenerateSecretKeyOpenSsl(blink::WebCryptoKeyAlgorithm::createHmac(
85 params->hash().id(), keylen_bits),
86 extractable,
87 usage_mask,
88 keylen_bits / 8,
89 key);
92 virtual Status VerifyKeyUsagesBeforeImportKey(
93 blink::WebCryptoKeyFormat format,
94 blink::WebCryptoKeyUsageMask usage_mask) const OVERRIDE {
95 switch (format) {
96 case blink::WebCryptoKeyFormatRaw:
97 case blink::WebCryptoKeyFormatJwk:
98 return CheckKeyCreationUsages(kAllKeyUsages, usage_mask);
99 default:
100 return Status::ErrorUnsupportedImportKeyFormat();
104 virtual Status VerifyKeyUsagesBeforeGenerateKey(
105 blink::WebCryptoKeyUsageMask usage_mask) const OVERRIDE {
106 return CheckKeyCreationUsages(kAllKeyUsages, usage_mask);
109 virtual Status ImportKeyRaw(const CryptoData& key_data,
110 const blink::WebCryptoAlgorithm& algorithm,
111 bool extractable,
112 blink::WebCryptoKeyUsageMask usage_mask,
113 blink::WebCryptoKey* key) const OVERRIDE {
114 const blink::WebCryptoAlgorithm& hash =
115 algorithm.hmacImportParams()->hash();
117 // TODO(eroman): check for overflow.
118 unsigned int keylen_bits = key_data.byte_length() * 8;
120 return ImportKeyRawOpenSsl(
121 key_data,
122 blink::WebCryptoKeyAlgorithm::createHmac(hash.id(), keylen_bits),
123 extractable,
124 usage_mask,
125 key);
128 virtual Status ImportKeyJwk(const CryptoData& key_data,
129 const blink::WebCryptoAlgorithm& algorithm,
130 bool extractable,
131 blink::WebCryptoKeyUsageMask usage_mask,
132 blink::WebCryptoKey* key) const OVERRIDE {
133 const char* algorithm_name =
134 GetJwkHmacAlgorithmName(algorithm.hmacImportParams()->hash().id());
135 if (!algorithm_name)
136 return Status::ErrorUnexpected();
138 std::vector<uint8_t> raw_data;
139 Status status = ReadSecretKeyJwk(
140 key_data, algorithm_name, extractable, usage_mask, &raw_data);
141 if (status.IsError())
142 return status;
144 return ImportKeyRaw(
145 CryptoData(raw_data), algorithm, extractable, usage_mask, key);
148 virtual Status ExportKeyRaw(const blink::WebCryptoKey& key,
149 std::vector<uint8_t>* buffer) const OVERRIDE {
150 *buffer = SymKeyOpenSsl::Cast(key)->raw_key_data();
151 return Status::Success();
154 virtual Status ExportKeyJwk(const blink::WebCryptoKey& key,
155 std::vector<uint8_t>* buffer) const OVERRIDE {
156 SymKeyOpenSsl* sym_key = SymKeyOpenSsl::Cast(key);
157 const std::vector<uint8_t>& raw_data = sym_key->raw_key_data();
159 const char* algorithm_name =
160 GetJwkHmacAlgorithmName(key.algorithm().hmacParams()->hash().id());
161 if (!algorithm_name)
162 return Status::ErrorUnexpected();
164 WriteSecretKeyJwk(CryptoData(raw_data),
165 algorithm_name,
166 key.extractable(),
167 key.usages(),
168 buffer);
170 return Status::Success();
173 virtual Status Sign(const blink::WebCryptoAlgorithm& algorithm,
174 const blink::WebCryptoKey& key,
175 const CryptoData& data,
176 std::vector<uint8_t>* buffer) const OVERRIDE {
177 const blink::WebCryptoAlgorithm& hash =
178 key.algorithm().hmacParams()->hash();
180 return SignHmac(
181 SymKeyOpenSsl::Cast(key)->raw_key_data(), hash, data, buffer);
184 virtual Status Verify(const blink::WebCryptoAlgorithm& algorithm,
185 const blink::WebCryptoKey& key,
186 const CryptoData& signature,
187 const CryptoData& data,
188 bool* signature_match) const OVERRIDE {
189 std::vector<uint8_t> result;
190 Status status = Sign(algorithm, key, data, &result);
192 if (status.IsError())
193 return status;
195 // Do not allow verification of truncated MACs.
196 *signature_match = result.size() == signature.byte_length() &&
197 crypto::SecureMemEqual(vector_as_array(&result),
198 signature.bytes(),
199 signature.byte_length());
201 return Status::Success();
205 } // namespace
207 AlgorithmImplementation* CreatePlatformHmacImplementation() {
208 return new HmacImplementation;
211 } // namespace webcrypto
213 } // namespace content