webcrypto_impl.cc revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
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/webcrypto_impl.h"
6
7#include "base/logging.h"
8#include "content/child/webcrypto/crypto_data.h"
9#include "content/child/webcrypto/shared_crypto.h"
10#include "content/child/webcrypto/status.h"
11#include "content/child/webcrypto/webcrypto_util.h"
12#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
13#include "third_party/WebKit/public/platform/WebString.h"
14
15namespace content {
16
17using webcrypto::Status;
18
19namespace {
20
21void CompleteWithError(const Status& status, blink::WebCryptoResult* result) {
22  DCHECK(status.IsError());
23  if (status.HasErrorDetails())
24    result->completeWithError(blink::WebString::fromUTF8(status.ToString()));
25  else
26    result->completeWithError();
27}
28
29bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) {
30  // TODO(padolph): include all other asymmetric algorithms once they are
31  // defined, e.g. EC and DH.
32  return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
33          algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
34          algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep);
35}
36
37}  // namespace
38
39WebCryptoImpl::WebCryptoImpl() { webcrypto::Init(); }
40
41WebCryptoImpl::~WebCryptoImpl() {}
42
43void 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) {
48  DCHECK(!algorithm.isNull());
49  blink::WebArrayBuffer buffer;
50  Status status = webcrypto::Encrypt(
51      algorithm, key, webcrypto::CryptoData(data, data_size), &buffer);
52  if (status.IsError())
53    CompleteWithError(status, &result);
54  else
55    result.completeWithBuffer(buffer);
56}
57
58void 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) {
63  DCHECK(!algorithm.isNull());
64  blink::WebArrayBuffer buffer;
65  Status status = webcrypto::Decrypt(
66      algorithm, key, webcrypto::CryptoData(data, data_size), &buffer);
67  if (status.IsError())
68    CompleteWithError(status, &result);
69  else
70    result.completeWithBuffer(buffer);
71}
72
73void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
74                           const unsigned char* data,
75                           unsigned int data_size,
76                           blink::WebCryptoResult result) {
77  DCHECK(!algorithm.isNull());
78  blink::WebArrayBuffer buffer;
79  Status status = webcrypto::Digest(
80      algorithm, webcrypto::CryptoData(data, data_size), &buffer);
81  if (status.IsError())
82    CompleteWithError(status, &result);
83  else
84    result.completeWithBuffer(buffer);
85}
86
87void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
88                                bool extractable,
89                                blink::WebCryptoKeyUsageMask usage_mask,
90                                blink::WebCryptoResult result) {
91  DCHECK(!algorithm.isNull());
92  if (IsAlgorithmAsymmetric(algorithm)) {
93    blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
94    blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
95    Status status = webcrypto::GenerateKeyPair(
96        algorithm, extractable, usage_mask, &public_key, &private_key);
97    if (status.IsError()) {
98      CompleteWithError(status, &result);
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());
104      DCHECK_EQ(true, public_key.extractable());
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    }
110  } else {
111    blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
112    Status status =
113        webcrypto::GenerateSecretKey(algorithm, extractable, usage_mask, &key);
114    if (status.IsError()) {
115      CompleteWithError(status, &result);
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    }
123  }
124}
125
126void 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) {
133  blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
134  Status status =
135      webcrypto::ImportKey(format,
136                           webcrypto::CryptoData(key_data, key_data_size),
137                           algorithm,
138                           extractable,
139                           usage_mask,
140                           &key);
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  }
149}
150
151void WebCryptoImpl::exportKey(blink::WebCryptoKeyFormat format,
152                              const blink::WebCryptoKey& key,
153                              blink::WebCryptoResult result) {
154  blink::WebArrayBuffer buffer;
155  Status status = webcrypto::ExportKey(format, key, &buffer);
156  if (status.IsError())
157    CompleteWithError(status, &result);
158  else
159    result.completeWithBuffer(buffer);
160}
161
162void 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) {
167  DCHECK(!algorithm.isNull());
168  blink::WebArrayBuffer buffer;
169  Status status = webcrypto::Sign(
170      algorithm, key, webcrypto::CryptoData(data, data_size), &buffer);
171  if (status.IsError())
172    CompleteWithError(status, &result);
173  else
174    result.completeWithBuffer(buffer);
175}
176
177void 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) {
184  DCHECK(!algorithm.isNull());
185  bool signature_match = false;
186  Status status = webcrypto::VerifySignature(
187      algorithm,
188      key,
189      webcrypto::CryptoData(signature, signature_size),
190      webcrypto::CryptoData(data, data_size),
191      &signature_match);
192  if (status.IsError())
193    CompleteWithError(status, &result);
194  else
195    result.completeWithBoolean(signature_match);
196}
197
198bool WebCryptoImpl::digestSynchronous(
199    const blink::WebCryptoAlgorithmId algorithm_id,
200    const unsigned char* data,
201    unsigned int data_size,
202    blink::WebArrayBuffer& result) {
203  blink::WebCryptoAlgorithm algorithm =
204      blink::WebCryptoAlgorithm::adoptParamsAndCreate(algorithm_id, NULL);
205  return (webcrypto::Digest(
206              algorithm, webcrypto::CryptoData(data, data_size), &result))
207      .IsSuccess();
208}
209
210bool WebCryptoImpl::deserializeKeyForClone(
211    const blink::WebCryptoKeyAlgorithm& algorithm,
212    blink::WebCryptoKeyType type,
213    bool extractable,
214    blink::WebCryptoKeyUsageMask usages,
215    const unsigned char* key_data,
216    unsigned key_data_size,
217    blink::WebCryptoKey& key) {
218  Status status = webcrypto::DeserializeKeyForClone(
219      algorithm,
220      type,
221      extractable,
222      usages,
223      webcrypto::CryptoData(key_data, key_data_size),
224      &key);
225  return status.IsSuccess();
226}
227
228bool WebCryptoImpl::serializeKeyForClone(
229    const blink::WebCryptoKey& key,
230    blink::WebVector<unsigned char>& key_data) {
231  Status status = webcrypto::SerializeKeyForClone(key, &key_data);
232  return status.IsSuccess();
233}
234
235}  // namespace content
236