[email protected] | cf5d32e5 | 2014-03-07 18:00:08 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors. All rights reserved. |
[email protected] | 408699c | 2013-07-17 21:23:16 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | cf5d32e5 | 2014-03-07 18:00:08 | [diff] [blame] | 5 | #include "content/child/webcrypto/webcrypto_impl.h" |
[email protected] | 408699c | 2013-07-17 21:23:16 | [diff] [blame] | 6 | |
[email protected] | c1b944a | 2013-10-23 06:33:21 | [diff] [blame] | 7 | #include "base/logging.h" |
[email protected] | cf5d32e5 | 2014-03-07 18:00:08 | [diff] [blame] | 8 | #include "content/child/webcrypto/crypto_data.h" |
| 9 | #include "content/child/webcrypto/shared_crypto.h" |
[email protected] | 37be4cfa | 2014-03-20 05:39:37 | [diff] [blame] | 10 | #include "content/child/webcrypto/status.h" |
[email protected] | cf5d32e5 | 2014-03-07 18:00:08 | [diff] [blame] | 11 | #include "content/child/webcrypto/webcrypto_util.h" |
[email protected] | 8238bb1c | 2014-02-26 15:16:25 | [diff] [blame] | 12 | #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" |
[email protected] | cf5d32e5 | 2014-03-07 18:00:08 | [diff] [blame] | 13 | #include "third_party/WebKit/public/platform/WebString.h" |
[email protected] | 408699c | 2013-07-17 21:23:16 | [diff] [blame] | 14 | |
| 15 | namespace content { |
| 16 | |
[email protected] | cca89748 | 2014-01-30 22:40:19 | [diff] [blame] | 17 | using webcrypto::Status; |
| 18 | |
[email protected] | 043cf1d3 | 2013-11-02 13:27:30 | [diff] [blame] | 19 | namespace { |
| 20 | |
[email protected] | cca89748 | 2014-01-30 22:40:19 | [diff] [blame] | 21 | void CompleteWithError(const Status& status, blink::WebCryptoResult* result) { |
| 22 | DCHECK(status.IsError()); |
[email protected] | 116d8bb | 2014-02-07 08:08:45 | [diff] [blame] | 23 | if (status.HasErrorDetails()) |
| 24 | result->completeWithError(blink::WebString::fromUTF8(status.ToString())); |
| 25 | else |
| 26 | result->completeWithError(); |
[email protected] | cca89748 | 2014-01-30 22:40:19 | [diff] [blame] | 27 | } |
| 28 | |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 29 | bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) { |
[email protected] | 043cf1d3 | 2013-11-02 13:27:30 | [diff] [blame] | 30 | // TODO(padolph): include all other asymmetric algorithms once they are |
| 31 | // defined, e.g. EC and DH. |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 32 | return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || |
| 33 | algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || |
| 34 | algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep); |
[email protected] | 043cf1d3 | 2013-11-02 13:27:30 | [diff] [blame] | 35 | } |
| 36 | |
| 37 | } // namespace |
| 38 | |
[email protected] | a6032655 | 2014-02-19 22:58:24 | [diff] [blame] | 39 | WebCryptoImpl::WebCryptoImpl() { webcrypto::Init(); } |
[email protected] | 7e4c36f | 2013-09-12 06:10:19 | [diff] [blame] | 40 | |
[email protected] | 04166f8 | 2014-02-19 06:11:04 | [diff] [blame] | 41 | WebCryptoImpl::~WebCryptoImpl() {} |
| 42 | |
[email protected] | a6032655 | 2014-02-19 22:58:24 | [diff] [blame] | 43 | void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm, |
| 44 | const blink::WebCryptoKey& key, |
| 45 | const unsigned char* data, |
| 46 | unsigned int data_size, |
| 47 | blink::WebCryptoResult result) { |
[email protected] | 2213f25 | 2013-10-31 04:33:34 | [diff] [blame] | 48 | DCHECK(!algorithm.isNull()); |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 49 | blink::WebArrayBuffer buffer; |
[email protected] | 04166f8 | 2014-02-19 06:11:04 | [diff] [blame] | 50 | Status status = webcrypto::Encrypt( |
| 51 | algorithm, key, webcrypto::CryptoData(data, data_size), &buffer); |
[email protected] | edb692e65 | 2014-01-31 05:32:52 | [diff] [blame] | 52 | if (status.IsError()) |
[email protected] | cca89748 | 2014-01-30 22:40:19 | [diff] [blame] | 53 | CompleteWithError(status, &result); |
[email protected] | edb692e65 | 2014-01-31 05:32:52 | [diff] [blame] | 54 | else |
[email protected] | a2a06c73 | 2013-09-27 10:50:54 | [diff] [blame] | 55 | result.completeWithBuffer(buffer); |
[email protected] | a2a06c73 | 2013-09-27 10:50:54 | [diff] [blame] | 56 | } |
| 57 | |
[email protected] | a6032655 | 2014-02-19 22:58:24 | [diff] [blame] | 58 | void WebCryptoImpl::decrypt(const blink::WebCryptoAlgorithm& algorithm, |
| 59 | const blink::WebCryptoKey& key, |
| 60 | const unsigned char* data, |
| 61 | unsigned int data_size, |
| 62 | blink::WebCryptoResult result) { |
[email protected] | 2213f25 | 2013-10-31 04:33:34 | [diff] [blame] | 63 | DCHECK(!algorithm.isNull()); |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 64 | blink::WebArrayBuffer buffer; |
[email protected] | 04166f8 | 2014-02-19 06:11:04 | [diff] [blame] | 65 | Status status = webcrypto::Decrypt( |
| 66 | algorithm, key, webcrypto::CryptoData(data, data_size), &buffer); |
[email protected] | edb692e65 | 2014-01-31 05:32:52 | [diff] [blame] | 67 | if (status.IsError()) |
[email protected] | cca89748 | 2014-01-30 22:40:19 | [diff] [blame] | 68 | CompleteWithError(status, &result); |
[email protected] | edb692e65 | 2014-01-31 05:32:52 | [diff] [blame] | 69 | else |
[email protected] | 868085a9 | 2013-10-01 00:42:30 | [diff] [blame] | 70 | result.completeWithBuffer(buffer); |
[email protected] | 868085a9 | 2013-10-01 00:42:30 | [diff] [blame] | 71 | } |
| 72 | |
[email protected] | a6032655 | 2014-02-19 22:58:24 | [diff] [blame] | 73 | void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm, |
| 74 | const unsigned char* data, |
| 75 | unsigned int data_size, |
| 76 | blink::WebCryptoResult result) { |
[email protected] | 2213f25 | 2013-10-31 04:33:34 | [diff] [blame] | 77 | DCHECK(!algorithm.isNull()); |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 78 | blink::WebArrayBuffer buffer; |
[email protected] | 04166f8 | 2014-02-19 06:11:04 | [diff] [blame] | 79 | Status status = webcrypto::Digest( |
| 80 | algorithm, webcrypto::CryptoData(data, data_size), &buffer); |
[email protected] | edb692e65 | 2014-01-31 05:32:52 | [diff] [blame] | 81 | if (status.IsError()) |
[email protected] | cca89748 | 2014-01-30 22:40:19 | [diff] [blame] | 82 | CompleteWithError(status, &result); |
[email protected] | edb692e65 | 2014-01-31 05:32:52 | [diff] [blame] | 83 | else |
[email protected] | e5b794b | 2013-08-30 01:32:54 | [diff] [blame] | 84 | result.completeWithBuffer(buffer); |
[email protected] | 408699c | 2013-07-17 21:23:16 | [diff] [blame] | 85 | } |
| 86 | |
[email protected] | a6032655 | 2014-02-19 22:58:24 | [diff] [blame] | 87 | void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm, |
| 88 | bool extractable, |
| 89 | blink::WebCryptoKeyUsageMask usage_mask, |
| 90 | blink::WebCryptoResult result) { |
[email protected] | 2213f25 | 2013-10-31 04:33:34 | [diff] [blame] | 91 | DCHECK(!algorithm.isNull()); |
[email protected] | 043cf1d3 | 2013-11-02 13:27:30 | [diff] [blame] | 92 | if (IsAlgorithmAsymmetric(algorithm)) { |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 93 | blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); |
| 94 | blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); |
[email protected] | 04166f8 | 2014-02-19 06:11:04 | [diff] [blame] | 95 | Status status = webcrypto::GenerateKeyPair( |
[email protected] | cca89748 | 2014-01-30 22:40:19 | [diff] [blame] | 96 | algorithm, extractable, usage_mask, &public_key, &private_key); |
| 97 | if (status.IsError()) { |
| 98 | CompleteWithError(status, &result); |
[email protected] | 043cf1d3 | 2013-11-02 13:27:30 | [diff] [blame] | 99 | } else { |
| 100 | DCHECK(public_key.handle()); |
| 101 | DCHECK(private_key.handle()); |
| 102 | DCHECK_EQ(algorithm.id(), public_key.algorithm().id()); |
| 103 | DCHECK_EQ(algorithm.id(), private_key.algorithm().id()); |
[email protected] | 0bfa772 | 2013-12-06 02:55:47 | [diff] [blame] | 104 | DCHECK_EQ(true, public_key.extractable()); |
[email protected] | 043cf1d3 | 2013-11-02 13:27:30 | [diff] [blame] | 105 | DCHECK_EQ(extractable, private_key.extractable()); |
| 106 | DCHECK_EQ(usage_mask, public_key.usages()); |
| 107 | DCHECK_EQ(usage_mask, private_key.usages()); |
| 108 | result.completeWithKeyPair(public_key, private_key); |
| 109 | } |
[email protected] | dfae8ab | 2013-10-10 19:45:06 | [diff] [blame] | 110 | } else { |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 111 | blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); |
[email protected] | 04166f8 | 2014-02-19 06:11:04 | [diff] [blame] | 112 | Status status = |
| 113 | webcrypto::GenerateSecretKey(algorithm, extractable, usage_mask, &key); |
[email protected] | cca89748 | 2014-01-30 22:40:19 | [diff] [blame] | 114 | if (status.IsError()) { |
| 115 | CompleteWithError(status, &result); |
[email protected] | 043cf1d3 | 2013-11-02 13:27:30 | [diff] [blame] | 116 | } else { |
| 117 | DCHECK(key.handle()); |
| 118 | DCHECK_EQ(algorithm.id(), key.algorithm().id()); |
| 119 | DCHECK_EQ(extractable, key.extractable()); |
| 120 | DCHECK_EQ(usage_mask, key.usages()); |
| 121 | result.completeWithKey(key); |
| 122 | } |
[email protected] | dfae8ab | 2013-10-10 19:45:06 | [diff] [blame] | 123 | } |
| 124 | } |
| 125 | |
[email protected] | c7a9468 | 2014-03-20 22:58:40 | [diff] [blame] | 126 | void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format, |
| 127 | const unsigned char* key_data, |
| 128 | unsigned int key_data_size, |
| 129 | const blink::WebCryptoAlgorithm& algorithm, |
| 130 | bool extractable, |
| 131 | blink::WebCryptoKeyUsageMask usage_mask, |
| 132 | blink::WebCryptoResult result) { |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 133 | blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); |
[email protected] | 04166f8 | 2014-02-19 06:11:04 | [diff] [blame] | 134 | Status status = |
| 135 | webcrypto::ImportKey(format, |
| 136 | webcrypto::CryptoData(key_data, key_data_size), |
[email protected] | c7a9468 | 2014-03-20 22:58:40 | [diff] [blame] | 137 | algorithm, |
[email protected] | 04166f8 | 2014-02-19 06:11:04 | [diff] [blame] | 138 | extractable, |
| 139 | usage_mask, |
| 140 | &key); |
[email protected] | cca89748 | 2014-01-30 22:40:19 | [diff] [blame] | 141 | if (status.IsError()) { |
| 142 | CompleteWithError(status, &result); |
| 143 | } else { |
| 144 | DCHECK(key.handle()); |
| 145 | DCHECK(!key.algorithm().isNull()); |
| 146 | DCHECK_EQ(extractable, key.extractable()); |
| 147 | result.completeWithKey(key); |
| 148 | } |
[email protected] | 1c879bc9 | 2013-09-18 07:45:32 | [diff] [blame] | 149 | } |
| 150 | |
[email protected] | a6032655 | 2014-02-19 22:58:24 | [diff] [blame] | 151 | void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format, |
| 152 | const blink::WebCryptoKey& key, |
| 153 | blink::WebCryptoResult result) { |
[email protected] | e9b2c10 | 2013-11-26 04:26:33 | [diff] [blame] | 154 | blink::WebArrayBuffer buffer; |
[email protected] | 04166f8 | 2014-02-19 06:11:04 | [diff] [blame] | 155 | Status status = webcrypto::ExportKey(format, key, &buffer); |
[email protected] | edb692e65 | 2014-01-31 05:32:52 | [diff] [blame] | 156 | if (status.IsError()) |
[email protected] | cca89748 | 2014-01-30 22:40:19 | [diff] [blame] | 157 | CompleteWithError(status, &result); |
[email protected] | edb692e65 | 2014-01-31 05:32:52 | [diff] [blame] | 158 | else |
[email protected] | cca89748 | 2014-01-30 22:40:19 | [diff] [blame] | 159 | result.completeWithBuffer(buffer); |
[email protected] | e9b2c10 | 2013-11-26 04:26:33 | [diff] [blame] | 160 | } |
| 161 | |
[email protected] | a6032655 | 2014-02-19 22:58:24 | [diff] [blame] | 162 | void WebCryptoImpl::sign(const blink::WebCryptoAlgorithm& algorithm, |
| 163 | const blink::WebCryptoKey& key, |
| 164 | const unsigned char* data, |
| 165 | unsigned int data_size, |
| 166 | blink::WebCryptoResult result) { |
[email protected] | 2213f25 | 2013-10-31 04:33:34 | [diff] [blame] | 167 | DCHECK(!algorithm.isNull()); |
[email protected] | 180ef24 | 2013-11-07 06:50:46 | [diff] [blame] | 168 | blink::WebArrayBuffer buffer; |
[email protected] | 04166f8 | 2014-02-19 06:11:04 | [diff] [blame] | 169 | Status status = webcrypto::Sign( |
| 170 | algorithm, key, webcrypto::CryptoData(data, data_size), &buffer); |
[email protected] | edb692e65 | 2014-01-31 05:32:52 | [diff] [blame] | 171 | if (status.IsError()) |
[email protected] | cca89748 | 2014-01-30 22:40:19 | [diff] [blame] | 172 | CompleteWithError(status, &result); |
[email protected] | edb692e65 | 2014-01-31 05:32:52 | [diff] [blame] | 173 | else |
[email protected] | 1c879bc9 | 2013-09-18 07:45:32 | [diff] [blame] | 174 | result.completeWithBuffer(buffer); |
[email protected] | 1c879bc9 | 2013-09-18 07:45:32 | [diff] [blame] | 175 | } |
| 176 | |
[email protected] | a6032655 | 2014-02-19 22:58:24 | [diff] [blame] | 177 | void WebCryptoImpl::verifySignature(const blink::WebCryptoAlgorithm& algorithm, |
| 178 | const blink::WebCryptoKey& key, |
| 179 | const unsigned char* signature, |
| 180 | unsigned int signature_size, |
| 181 | const unsigned char* data, |
| 182 | unsigned int data_size, |
| 183 | blink::WebCryptoResult result) { |
[email protected] | 2213f25 | 2013-10-31 04:33:34 | [diff] [blame] | 184 | DCHECK(!algorithm.isNull()); |
[email protected] | 3ed0026 | 2013-09-26 22:28:10 | [diff] [blame] | 185 | bool signature_match = false; |
[email protected] | 04166f8 | 2014-02-19 06:11:04 | [diff] [blame] | 186 | Status status = webcrypto::VerifySignature( |
| 187 | algorithm, |
| 188 | key, |
| 189 | webcrypto::CryptoData(signature, signature_size), |
| 190 | webcrypto::CryptoData(data, data_size), |
| 191 | &signature_match); |
[email protected] | edb692e65 | 2014-01-31 05:32:52 | [diff] [blame] | 192 | if (status.IsError()) |
[email protected] | cca89748 | 2014-01-30 22:40:19 | [diff] [blame] | 193 | CompleteWithError(status, &result); |
[email protected] | edb692e65 | 2014-01-31 05:32:52 | [diff] [blame] | 194 | else |
[email protected] | 3ed0026 | 2013-09-26 22:28:10 | [diff] [blame] | 195 | result.completeWithBoolean(signature_match); |
[email protected] | 3ed0026 | 2013-09-26 22:28:10 | [diff] [blame] | 196 | } |
| 197 | |
[email protected] | baa9284 | 2014-03-25 01:07:38 | [diff] [blame^] | 198 | void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format, |
| 199 | const blink::WebCryptoKey& key, |
| 200 | const blink::WebCryptoKey& wrapping_key, |
| 201 | const blink::WebCryptoAlgorithm& wrap_algorithm, |
| 202 | blink::WebCryptoResult result) { |
| 203 | blink::WebArrayBuffer buffer; |
| 204 | // TODO(eroman): Use the same parameter ordering. |
| 205 | Status status = webcrypto::WrapKey( |
| 206 | format, wrapping_key, key, wrap_algorithm, &buffer); |
| 207 | if (status.IsError()) |
| 208 | CompleteWithError(status, &result); |
| 209 | else |
| 210 | result.completeWithBuffer(buffer); |
| 211 | } |
| 212 | |
| 213 | void WebCryptoImpl::unwrapKey( |
| 214 | blink::WebCryptoKeyFormat format, |
| 215 | const unsigned char* wrapped_key, |
| 216 | unsigned wrapped_key_size, |
| 217 | const blink::WebCryptoKey& wrapping_key, |
| 218 | const blink::WebCryptoAlgorithm& unwrap_algorithm, |
| 219 | const blink::WebCryptoAlgorithm& unwrapped_key_algorithm, |
| 220 | bool extractable, |
| 221 | blink::WebCryptoKeyUsageMask usages, |
| 222 | blink::WebCryptoResult result) { |
| 223 | blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); |
| 224 | Status status = |
| 225 | webcrypto::UnwrapKey(format, |
| 226 | webcrypto::CryptoData(wrapped_key, wrapped_key_size), |
| 227 | wrapping_key, |
| 228 | unwrap_algorithm, |
| 229 | unwrapped_key_algorithm, |
| 230 | extractable, |
| 231 | usages, |
| 232 | &key); |
| 233 | if (status.IsError()) |
| 234 | CompleteWithError(status, &result); |
| 235 | else |
| 236 | result.completeWithKey(key); |
| 237 | } |
| 238 | |
[email protected] | bd48e641 | 2014-02-22 08:32:53 | [diff] [blame] | 239 | bool WebCryptoImpl::digestSynchronous( |
| 240 | const blink::WebCryptoAlgorithmId algorithm_id, |
| 241 | const unsigned char* data, |
| 242 | unsigned int data_size, |
| 243 | blink::WebArrayBuffer& result) { |
| 244 | blink::WebCryptoAlgorithm algorithm = |
| 245 | blink::WebCryptoAlgorithm::adoptParamsAndCreate(algorithm_id, NULL); |
| 246 | return (webcrypto::Digest( |
| 247 | algorithm, webcrypto::CryptoData(data, data_size), &result)) |
| 248 | .IsSuccess(); |
| 249 | } |
| 250 | |
[email protected] | 5daca047 | 2014-03-18 20:27:08 | [diff] [blame] | 251 | bool WebCryptoImpl::deserializeKeyForClone( |
| 252 | const blink::WebCryptoKeyAlgorithm& algorithm, |
| 253 | blink::WebCryptoKeyType type, |
| 254 | bool extractable, |
| 255 | blink::WebCryptoKeyUsageMask usages, |
| 256 | const unsigned char* key_data, |
| 257 | unsigned key_data_size, |
| 258 | blink::WebCryptoKey& key) { |
| 259 | Status status = webcrypto::DeserializeKeyForClone( |
| 260 | algorithm, |
| 261 | type, |
| 262 | extractable, |
| 263 | usages, |
| 264 | webcrypto::CryptoData(key_data, key_data_size), |
| 265 | &key); |
| 266 | return status.IsSuccess(); |
| 267 | } |
| 268 | |
| 269 | bool WebCryptoImpl::serializeKeyForClone( |
| 270 | const blink::WebCryptoKey& key, |
| 271 | blink::WebVector<unsigned char>& key_data) { |
| 272 | Status status = webcrypto::SerializeKeyForClone(key, &key_data); |
| 273 | return status.IsSuccess(); |
| 274 | } |
| 275 | |
[email protected] | 408699c | 2013-07-17 21:23:16 | [diff] [blame] | 276 | } // namespace content |