Removing uses of X11 native key events.
[chromium-blink-merge.git] / content / child / webcrypto / openssl / hmac_openssl.cc
blobc6f6536275d547f4a977eace6b351497812190ae
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/numerics/safe_math.h"
9 #include "base/stl_util.h"
10 #include "content/child/webcrypto/algorithm_implementation.h"
11 #include "content/child/webcrypto/crypto_data.h"
12 #include "content/child/webcrypto/jwk.h"
13 #include "content/child/webcrypto/openssl/key_openssl.h"
14 #include "content/child/webcrypto/openssl/sym_key_openssl.h"
15 #include "content/child/webcrypto/openssl/util_openssl.h"
16 #include "content/child/webcrypto/status.h"
17 #include "content/child/webcrypto/webcrypto_util.h"
18 #include "crypto/openssl_util.h"
19 #include "crypto/secure_util.h"
20 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
21 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
23 namespace content {
25 namespace webcrypto {
27 namespace {
29 const blink::WebCryptoKeyUsageMask kAllKeyUsages =
30 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
32 Status SignHmac(const std::vector<uint8_t>& raw_key,
33 const blink::WebCryptoAlgorithm& hash,
34 const CryptoData& data,
35 std::vector<uint8_t>* buffer) {
36 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
38 const EVP_MD* digest_algorithm = GetDigest(hash.id());
39 if (!digest_algorithm)
40 return Status::ErrorUnsupported();
41 unsigned int hmac_expected_length = EVP_MD_size(digest_algorithm);
43 // OpenSSL wierdness here.
44 // First, HMAC() needs a void* for the key data, so make one up front as a
45 // cosmetic to avoid a cast. Second, OpenSSL does not like a NULL key,
46 // which will result if the raw_key vector is empty; an entirely valid
47 // case. Handle this specific case by pointing to an empty array.
48 const unsigned char null_key[] = {};
49 const void* const raw_key_voidp = raw_key.size() ? &raw_key[0] : null_key;
51 buffer->resize(hmac_expected_length);
52 crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result(
53 vector_as_array(buffer), hmac_expected_length);
55 unsigned int hmac_actual_length;
56 unsigned char* const success = HMAC(digest_algorithm,
57 raw_key_voidp,
58 raw_key.size(),
59 data.bytes(),
60 data.byte_length(),
61 hmac_result.safe_buffer(),
62 &hmac_actual_length);
63 if (!success || hmac_actual_length != hmac_expected_length)
64 return Status::OperationError();
66 return Status::Success();
69 class HmacImplementation : public AlgorithmImplementation {
70 public:
71 HmacImplementation() {}
73 virtual Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm,
74 bool extractable,
75 blink::WebCryptoKeyUsageMask usage_mask,
76 blink::WebCryptoKey* key) const OVERRIDE {
77 const blink::WebCryptoHmacKeyGenParams* params =
78 algorithm.hmacKeyGenParams();
80 unsigned int keylen_bits = 0;
81 Status status = GetHmacKeyGenLengthInBits(params, &keylen_bits);
82 if (status.IsError())
83 return status;
85 return GenerateSecretKeyOpenSsl(blink::WebCryptoKeyAlgorithm::createHmac(
86 params->hash().id(), keylen_bits),
87 extractable,
88 usage_mask,
89 keylen_bits / 8,
90 key);
93 virtual Status VerifyKeyUsagesBeforeImportKey(
94 blink::WebCryptoKeyFormat format,
95 blink::WebCryptoKeyUsageMask usage_mask) const OVERRIDE {
96 switch (format) {
97 case blink::WebCryptoKeyFormatRaw:
98 case blink::WebCryptoKeyFormatJwk:
99 return CheckKeyCreationUsages(kAllKeyUsages, usage_mask);
100 default:
101 return Status::ErrorUnsupportedImportKeyFormat();
105 virtual Status VerifyKeyUsagesBeforeGenerateKey(
106 blink::WebCryptoKeyUsageMask usage_mask) const OVERRIDE {
107 return CheckKeyCreationUsages(kAllKeyUsages, usage_mask);
110 virtual Status ImportKeyRaw(const CryptoData& key_data,
111 const blink::WebCryptoAlgorithm& algorithm,
112 bool extractable,
113 blink::WebCryptoKeyUsageMask usage_mask,
114 blink::WebCryptoKey* key) const OVERRIDE {
115 const blink::WebCryptoAlgorithm& hash =
116 algorithm.hmacImportParams()->hash();
118 base::CheckedNumeric<unsigned int> keylen_bits(key_data.byte_length());
119 keylen_bits *= 8;
121 if (!keylen_bits.IsValid())
122 return Status::ErrorDataTooLarge();
124 return ImportKeyRawOpenSsl(key_data,
125 blink::WebCryptoKeyAlgorithm::createHmac(
126 hash.id(), keylen_bits.ValueOrDie()),
127 extractable,
128 usage_mask,
129 key);
132 virtual Status ImportKeyJwk(const CryptoData& key_data,
133 const blink::WebCryptoAlgorithm& algorithm,
134 bool extractable,
135 blink::WebCryptoKeyUsageMask usage_mask,
136 blink::WebCryptoKey* key) const OVERRIDE {
137 const char* algorithm_name =
138 GetJwkHmacAlgorithmName(algorithm.hmacImportParams()->hash().id());
139 if (!algorithm_name)
140 return Status::ErrorUnexpected();
142 std::vector<uint8_t> raw_data;
143 Status status = ReadSecretKeyJwk(
144 key_data, algorithm_name, extractable, usage_mask, &raw_data);
145 if (status.IsError())
146 return status;
148 return ImportKeyRaw(
149 CryptoData(raw_data), algorithm, extractable, usage_mask, key);
152 virtual Status ExportKeyRaw(const blink::WebCryptoKey& key,
153 std::vector<uint8_t>* buffer) const OVERRIDE {
154 *buffer = SymKeyOpenSsl::Cast(key)->raw_key_data();
155 return Status::Success();
158 virtual Status ExportKeyJwk(const blink::WebCryptoKey& key,
159 std::vector<uint8_t>* buffer) const OVERRIDE {
160 SymKeyOpenSsl* sym_key = SymKeyOpenSsl::Cast(key);
161 const std::vector<uint8_t>& raw_data = sym_key->raw_key_data();
163 const char* algorithm_name =
164 GetJwkHmacAlgorithmName(key.algorithm().hmacParams()->hash().id());
165 if (!algorithm_name)
166 return Status::ErrorUnexpected();
168 WriteSecretKeyJwk(CryptoData(raw_data),
169 algorithm_name,
170 key.extractable(),
171 key.usages(),
172 buffer);
174 return Status::Success();
177 virtual Status Sign(const blink::WebCryptoAlgorithm& algorithm,
178 const blink::WebCryptoKey& key,
179 const CryptoData& data,
180 std::vector<uint8_t>* buffer) const OVERRIDE {
181 const blink::WebCryptoAlgorithm& hash =
182 key.algorithm().hmacParams()->hash();
184 return SignHmac(
185 SymKeyOpenSsl::Cast(key)->raw_key_data(), hash, data, buffer);
188 virtual Status Verify(const blink::WebCryptoAlgorithm& algorithm,
189 const blink::WebCryptoKey& key,
190 const CryptoData& signature,
191 const CryptoData& data,
192 bool* signature_match) const OVERRIDE {
193 std::vector<uint8_t> result;
194 Status status = Sign(algorithm, key, data, &result);
196 if (status.IsError())
197 return status;
199 // Do not allow verification of truncated MACs.
200 *signature_match = result.size() == signature.byte_length() &&
201 crypto::SecureMemEqual(vector_as_array(&result),
202 signature.bytes(),
203 signature.byte_length());
205 return Status::Success();
209 } // namespace
211 AlgorithmImplementation* CreatePlatformHmacImplementation() {
212 return new HmacImplementation;
215 } // namespace webcrypto
217 } // namespace content