Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Side by Side Diff: content/child/webcrypto/openssl/hmac_openssl.cc

Issue 379383002: Refactor WebCrypto code (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase onto master Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include <openssl/hmac.h>
6
7 #include "base/logging.h"
8 #include "content/child/webcrypto/crypto_data.h"
9 #include "content/child/webcrypto/jwk.h"
10 #include "content/child/webcrypto/openssl/key_openssl.h"
11 #include "content/child/webcrypto/openssl/sym_key_openssl.h"
12 #include "content/child/webcrypto/openssl/util_openssl.h"
13 #include "content/child/webcrypto/status.h"
14 #include "content/child/webcrypto/webcrypto_util.h"
15 #include "crypto/openssl_util.h"
16 #include "crypto/secure_util.h"
17 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
18 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
19
20 namespace content {
21
22 namespace webcrypto {
23
24 namespace {
25
26 const blink::WebCryptoKeyUsageMask kAllKeyUsages =
27 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
28
29 Status SignHmac(const std::vector<uint8>& raw_key,
30 const blink::WebCryptoAlgorithm& hash,
31 const CryptoData& data,
32 std::vector<uint8>* buffer) {
33 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
34
35 const EVP_MD* digest_algorithm = GetDigest(hash.id());
36 if (!digest_algorithm)
37 return Status::ErrorUnsupported();
38 unsigned int hmac_expected_length = EVP_MD_size(digest_algorithm);
39
40 // OpenSSL wierdness here.
41 // First, HMAC() needs a void* for the key data, so make one up front as a
42 // cosmetic to avoid a cast. Second, OpenSSL does not like a NULL key,
43 // which will result if the raw_key vector is empty; an entirely valid
44 // case. Handle this specific case by pointing to an empty array.
Ryan Sleevi 2014/07/17 00:06:54 Fixed by BoringSSL?
eroman 2014/07/17 20:37:26 Not sure. Will add it as an action item to investi
45 const unsigned char null_key[] = {};
46 const void* const raw_key_voidp = raw_key.size() ? &raw_key[0] : null_key;
47
48 buffer->resize(hmac_expected_length);
49 crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result(
50 Uint8VectorStart(buffer), hmac_expected_length);
51
52 unsigned int hmac_actual_length;
53 unsigned char* const success = HMAC(digest_algorithm,
54 raw_key_voidp,
55 raw_key.size(),
56 data.bytes(),
57 data.byte_length(),
58 hmac_result.safe_buffer(),
59 &hmac_actual_length);
60 if (!success || hmac_actual_length != hmac_expected_length)
61 return Status::OperationError();
62
63 return Status::Success();
64 }
65
66 class HmacImplementation : public AlgorithmImplementation {
67 public:
68 HmacImplementation() {}
69
70 virtual Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm,
71 bool extractable,
72 blink::WebCryptoKeyUsageMask usage_mask,
73 blink::WebCryptoKey* key) const OVERRIDE {
74 const blink::WebCryptoHmacKeyGenParams* params =
75 algorithm.hmacKeyGenParams();
76
77 unsigned int keylen_bits = 0;
78 Status status = GetHmacKeyGenLength(params, &keylen_bits);
79 if (status.IsError())
80 return status;
81
82 return GenerateSecretKeyOpenSsl(blink::WebCryptoKeyAlgorithm::createHmac(
83 params->hash().id(), keylen_bits),
84 extractable,
85 usage_mask,
86 keylen_bits / 8,
87 key);
88 }
89
90 virtual Status VerifyKeyUsagesBeforeImportKey(
91 blink::WebCryptoKeyFormat format,
92 blink::WebCryptoKeyUsageMask usage_mask) const OVERRIDE {
93 switch (format) {
94 case blink::WebCryptoKeyFormatRaw:
95 case blink::WebCryptoKeyFormatJwk:
96 return CheckKeyCreationUsages(kAllKeyUsages, usage_mask);
97 default:
98 return Status::ErrorUnsupportedImportKeyFormat();
99 }
100 }
101
102 virtual Status VerifyKeyUsagesBeforeGenerateKey(
103 blink::WebCryptoKeyUsageMask usage_mask) const OVERRIDE {
104 return CheckKeyCreationUsages(kAllKeyUsages, usage_mask);
105 }
106
107 virtual Status ImportKeyRaw(const CryptoData& key_data,
108 const blink::WebCryptoAlgorithm& algorithm,
109 bool extractable,
110 blink::WebCryptoKeyUsageMask usage_mask,
111 blink::WebCryptoKey* key) const OVERRIDE {
112 const blink::WebCryptoAlgorithm& hash =
113 algorithm.hmacImportParams()->hash();
114
115 // TODO(eroman): check for overflow.
116 unsigned int keylen_bits = key_data.byte_length() * 8;
117
118 return ImportKeyRawOpenSsl(
119 key_data,
120 blink::WebCryptoKeyAlgorithm::createHmac(hash.id(), keylen_bits),
121 extractable,
122 usage_mask,
123 key);
124 }
125
126 virtual Status ImportKeyJwk(const CryptoData& key_data,
127 const blink::WebCryptoAlgorithm& algorithm,
128 bool extractable,
129 blink::WebCryptoKeyUsageMask usage_mask,
130 blink::WebCryptoKey* key) const OVERRIDE {
131 const char* algorithm_name =
132 GetJwkHmacAlgorithmName(algorithm.hmacImportParams()->hash().id());
133 if (!algorithm_name)
134 return Status::ErrorUnexpected();
135
136 std::vector<uint8> raw_data;
137 Status status = ReadSecretKeyJwk(
138 key_data, algorithm_name, extractable, usage_mask, &raw_data);
139 if (status.IsError())
140 return status;
141
142 return ImportKeyRaw(
143 CryptoData(raw_data), algorithm, extractable, usage_mask, key);
144 }
145
146 virtual Status ExportKeyRaw(const blink::WebCryptoKey& key,
147 std::vector<uint8>* buffer) const OVERRIDE {
148 *buffer = SymKeyOpenSsl::Cast(key)->raw_key_data();
149 return Status::Success();
150 }
151
152 virtual Status ExportKeyJwk(const blink::WebCryptoKey& key,
153 std::vector<uint8>* buffer) const OVERRIDE {
154 SymKeyOpenSsl* sym_key = SymKeyOpenSsl::Cast(key);
155 const std::vector<uint8>& raw_data = sym_key->raw_key_data();
156
157 const char* algorithm_name =
158 GetJwkHmacAlgorithmName(key.algorithm().hmacParams()->hash().id());
159 if (!algorithm_name)
160 return Status::ErrorUnexpected();
161
162 WriteSecretKeyJwk(CryptoData(raw_data),
163 algorithm_name,
164 key.extractable(),
165 key.usages(),
166 buffer);
167
168 return Status::Success();
169 }
170
171 virtual Status Sign(const blink::WebCryptoAlgorithm& algorithm,
172 const blink::WebCryptoKey& key,
173 const CryptoData& data,
174 std::vector<uint8>* buffer) const OVERRIDE {
175 const blink::WebCryptoAlgorithm& hash =
176 key.algorithm().hmacParams()->hash();
177
178 return SignHmac(
179 SymKeyOpenSsl::Cast(key)->raw_key_data(), hash, data, buffer);
180 }
181
182 virtual Status Verify(const blink::WebCryptoAlgorithm& algorithm,
183 const blink::WebCryptoKey& key,
184 const CryptoData& signature,
185 const CryptoData& data,
186 bool* signature_match) const OVERRIDE {
187 std::vector<uint8> result;
188 Status status = Sign(algorithm, key, data, &result);
189
190 if (status.IsError())
191 return status;
192
193 // Do not allow verification of truncated MACs.
194 *signature_match = result.size() == signature.byte_length() &&
195 crypto::SecureMemEqual(Uint8VectorStart(result),
196 signature.bytes(),
197 signature.byte_length());
198
199 return Status::Success();
200 }
201 };
202
203 } // namespace
204
205 AlgorithmImplementation* CreatePlatformHmacImplementation() {
206 return new HmacImplementation;
207 }
208
209 } // namespace webcrypto
210
211 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698