Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / child / webcrypto / algorithm_dispatch.cc
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 "content/child/webcrypto/algorithm_dispatch.h"
6
7 #include "base/logging.h"
8 #include "content/child/webcrypto/algorithm_implementation.h"
9 #include "content/child/webcrypto/algorithm_registry.h"
10 #include "content/child/webcrypto/crypto_data.h"
11 #include "content/child/webcrypto/platform_crypto.h"
12 #include "content/child/webcrypto/status.h"
13 #include "content/child/webcrypto/webcrypto_util.h"
14 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
15
16 namespace content {
17
18 namespace webcrypto {
19
20 namespace {
21
22 Status DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm& algorithm,
23                                 const blink::WebCryptoKey& key,
24                                 const CryptoData& data,
25                                 std::vector<uint8_t>* buffer) {
26   if (algorithm.id() != key.algorithm().id())
27     return Status::ErrorUnexpected();
28
29   const AlgorithmImplementation* impl = NULL;
30   Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
31   if (status.IsError())
32     return status;
33
34   return impl->Decrypt(algorithm, key, data, buffer);
35 }
36
37 Status EncryptDontCheckUsage(const blink::WebCryptoAlgorithm& algorithm,
38                              const blink::WebCryptoKey& key,
39                              const CryptoData& data,
40                              std::vector<uint8_t>* buffer) {
41   if (algorithm.id() != key.algorithm().id())
42     return Status::ErrorUnexpected();
43
44   const AlgorithmImplementation* impl = NULL;
45   Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
46   if (status.IsError())
47     return status;
48
49   return impl->Encrypt(algorithm, key, data, buffer);
50 }
51
52 Status ExportKeyDontCheckExtractability(blink::WebCryptoKeyFormat format,
53                                         const blink::WebCryptoKey& key,
54                                         std::vector<uint8_t>* buffer) {
55   const AlgorithmImplementation* impl = NULL;
56   Status status = GetAlgorithmImplementation(key.algorithm().id(), &impl);
57   if (status.IsError())
58     return status;
59
60   switch (format) {
61     case blink::WebCryptoKeyFormatRaw:
62       return impl->ExportKeyRaw(key, buffer);
63     case blink::WebCryptoKeyFormatSpki:
64       return impl->ExportKeySpki(key, buffer);
65     case blink::WebCryptoKeyFormatPkcs8:
66       return impl->ExportKeyPkcs8(key, buffer);
67     case blink::WebCryptoKeyFormatJwk:
68       return impl->ExportKeyJwk(key, buffer);
69     default:
70       return Status::ErrorUnsupported();
71   }
72 }
73
74 }  // namespace
75
76 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
77                const blink::WebCryptoKey& key,
78                const CryptoData& data,
79                std::vector<uint8_t>* buffer) {
80   if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt))
81     return Status::ErrorUnexpected();
82   return EncryptDontCheckUsage(algorithm, key, data, buffer);
83 }
84
85 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
86                const blink::WebCryptoKey& key,
87                const CryptoData& data,
88                std::vector<uint8_t>* buffer) {
89   if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt))
90     return Status::ErrorUnexpected();
91   return DecryptDontCheckKeyUsage(algorithm, key, data, buffer);
92 }
93
94 Status Digest(const blink::WebCryptoAlgorithm& algorithm,
95               const CryptoData& data,
96               std::vector<uint8_t>* buffer) {
97   const AlgorithmImplementation* impl = NULL;
98   Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
99   if (status.IsError())
100     return status;
101
102   return impl->Digest(algorithm, data, buffer);
103 }
104
105 Status GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
106                    bool extractable,
107                    blink::WebCryptoKeyUsageMask usages,
108                    GenerateKeyResult* result) {
109   const AlgorithmImplementation* impl = NULL;
110   Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
111   if (status.IsError())
112     return status;
113
114   return impl->GenerateKey(algorithm, extractable, usages, result);
115 }
116
117 // Note that this function may be called from the target Blink thread.
118 Status ImportKey(blink::WebCryptoKeyFormat format,
119                  const CryptoData& key_data,
120                  const blink::WebCryptoAlgorithm& algorithm,
121                  bool extractable,
122                  blink::WebCryptoKeyUsageMask usages,
123                  blink::WebCryptoKey* key) {
124   const AlgorithmImplementation* impl = NULL;
125   Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
126   if (status.IsError())
127     return status;
128
129   status = impl->VerifyKeyUsagesBeforeImportKey(format, usages);
130   if (status.IsError())
131     return status;
132
133   switch (format) {
134     case blink::WebCryptoKeyFormatRaw:
135       return impl->ImportKeyRaw(key_data, algorithm, extractable, usages, key);
136     case blink::WebCryptoKeyFormatSpki:
137       return impl->ImportKeySpki(key_data, algorithm, extractable, usages, key);
138     case blink::WebCryptoKeyFormatPkcs8:
139       return impl->ImportKeyPkcs8(
140           key_data, algorithm, extractable, usages, key);
141     case blink::WebCryptoKeyFormatJwk:
142       return impl->ImportKeyJwk(key_data, algorithm, extractable, usages, key);
143     default:
144       return Status::ErrorUnsupported();
145   }
146 }
147
148 Status ExportKey(blink::WebCryptoKeyFormat format,
149                  const blink::WebCryptoKey& key,
150                  std::vector<uint8_t>* buffer) {
151   if (!key.extractable())
152     return Status::ErrorKeyNotExtractable();
153   return ExportKeyDontCheckExtractability(format, key, buffer);
154 }
155
156 Status Sign(const blink::WebCryptoAlgorithm& algorithm,
157             const blink::WebCryptoKey& key,
158             const CryptoData& data,
159             std::vector<uint8_t>* buffer) {
160   if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageSign))
161     return Status::ErrorUnexpected();
162   if (algorithm.id() != key.algorithm().id())
163     return Status::ErrorUnexpected();
164
165   const AlgorithmImplementation* impl = NULL;
166   Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
167   if (status.IsError())
168     return status;
169
170   return impl->Sign(algorithm, key, data, buffer);
171 }
172
173 Status Verify(const blink::WebCryptoAlgorithm& algorithm,
174               const blink::WebCryptoKey& key,
175               const CryptoData& signature,
176               const CryptoData& data,
177               bool* signature_match) {
178   if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageVerify))
179     return Status::ErrorUnexpected();
180   if (algorithm.id() != key.algorithm().id())
181     return Status::ErrorUnexpected();
182
183   const AlgorithmImplementation* impl = NULL;
184   Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
185   if (status.IsError())
186     return status;
187
188   return impl->Verify(algorithm, key, signature, data, signature_match);
189 }
190
191 Status WrapKey(blink::WebCryptoKeyFormat format,
192                const blink::WebCryptoKey& key_to_wrap,
193                const blink::WebCryptoKey& wrapping_key,
194                const blink::WebCryptoAlgorithm& wrapping_algorithm,
195                std::vector<uint8_t>* buffer) {
196   if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageWrapKey))
197     return Status::ErrorUnexpected();
198
199   std::vector<uint8_t> exported_data;
200   Status status = ExportKey(format, key_to_wrap, &exported_data);
201   if (status.IsError())
202     return status;
203   return EncryptDontCheckUsage(
204       wrapping_algorithm, wrapping_key, CryptoData(exported_data), buffer);
205 }
206
207 Status UnwrapKey(blink::WebCryptoKeyFormat format,
208                  const CryptoData& wrapped_key_data,
209                  const blink::WebCryptoKey& wrapping_key,
210                  const blink::WebCryptoAlgorithm& wrapping_algorithm,
211                  const blink::WebCryptoAlgorithm& algorithm,
212                  bool extractable,
213                  blink::WebCryptoKeyUsageMask usages,
214                  blink::WebCryptoKey* key) {
215   if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey))
216     return Status::ErrorUnexpected();
217   if (wrapping_algorithm.id() != wrapping_key.algorithm().id())
218     return Status::ErrorUnexpected();
219
220   // Fail fast if the import is doomed to fail.
221   const AlgorithmImplementation* import_impl = NULL;
222   Status status = GetAlgorithmImplementation(algorithm.id(), &import_impl);
223   if (status.IsError())
224     return status;
225
226   status = import_impl->VerifyKeyUsagesBeforeImportKey(format, usages);
227   if (status.IsError())
228     return status;
229
230   std::vector<uint8_t> buffer;
231   status = DecryptDontCheckKeyUsage(
232       wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer);
233   if (status.IsError())
234     return status;
235
236   // NOTE that returning the details of ImportKey() failures may leak
237   // information about the plaintext of the encrypted key (for instance the JWK
238   // key_ops). As long as the ImportKey error messages don't describe actual
239   // key bytes however this should be OK. For more discussion see
240   // http://crubg.com/372040
241   return ImportKey(
242       format, CryptoData(buffer), algorithm, extractable, usages, key);
243 }
244
245 scoped_ptr<blink::WebCryptoDigestor> CreateDigestor(
246     blink::WebCryptoAlgorithmId algorithm) {
247   PlatformInit();
248   return CreatePlatformDigestor(algorithm);
249 }
250
251 }  // namespace webcrypto
252
253 }  // namespace content