Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / renderer / webcrypto / webcrypto_util.cc
1 // Copyright 2013 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/renderer/webcrypto/webcrypto_util.h"
6
7 #include "base/base64.h"
8 #include "base/logging.h"
9 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
10 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
11
12 namespace content {
13
14 namespace webcrypto {
15
16 bool Status::IsError() const {
17   return type_ == TYPE_ERROR;
18 }
19
20 bool Status::IsSuccess() const {
21   return type_ == TYPE_SUCCESS;
22 }
23
24 bool Status::HasErrorDetails() const {
25   return !error_details_.empty();
26 }
27
28 std::string Status::ToString() const {
29   return IsSuccess() ? "Success" : error_details_;
30 }
31
32 Status Status::Success() {
33   return Status(TYPE_SUCCESS);
34 }
35
36 Status Status::Error() {
37   return Status(TYPE_ERROR);
38 }
39
40 Status Status::ErrorJwkNotDictionary() {
41   return Status("JWK input could not be parsed to a JSON dictionary");
42 }
43
44 Status Status::ErrorJwkPropertyMissing(const std::string& property) {
45   return Status("The required JWK property \"" + property + "\" was missing");
46 }
47
48 Status Status::ErrorJwkPropertyWrongType(const std::string& property,
49                                          const std::string& expected_type) {
50   return Status("The JWK property \"" + property + "\" must be a " +
51                 expected_type);
52 }
53
54 Status Status::ErrorJwkBase64Decode(const std::string& property) {
55   return Status("The JWK property \"" + property +
56                 "\" could not be base64 decoded");
57 }
58
59 Status Status::ErrorJwkExtractableInconsistent() {
60   return Status("The \"extractable\" property of the JWK dictionary is "
61                 "inconsistent what that specified by the Web Crypto call");
62 }
63
64 Status Status::ErrorJwkUnrecognizedAlgorithm() {
65   return Status("The JWK \"alg\" property was not recognized");
66 }
67
68 Status Status::ErrorJwkAlgorithmInconsistent() {
69   return Status("The JWK \"alg\" property was inconsistent with that specified "
70                 "by the Web Crypto call");
71 }
72
73 Status Status::ErrorJwkAlgorithmMissing() {
74   return Status("The JWK optional \"alg\" property is missing or not a string, "
75                 "and one wasn't specified by the Web Crypto call");
76 }
77
78 Status Status::ErrorJwkUnrecognizedUsage() {
79   return Status("The JWK \"use\" property could not be parsed");
80 }
81
82 Status Status::ErrorJwkUsageInconsistent() {
83   return Status("The JWK \"use\" property was inconsistent with that specified "
84                 "by the Web Crypto call. The JWK usage must be a superset of "
85                 "those requested");
86 }
87
88 Status Status::ErrorJwkRsaPrivateKeyUnsupported() {
89   return Status("JWK RSA key contained \"d\" property: Private key import is "
90                 "not yet supported");
91 }
92
93 Status Status::ErrorJwkUnrecognizedKty() {
94   return Status("The JWK \"kty\" property was unrecognized");
95 }
96
97 Status Status::ErrorJwkIncorrectKeyLength() {
98   return Status("The JWK \"k\" property did not include the right length "
99                 "of key data for the given algorithm.");
100 }
101
102 Status Status::ErrorImportEmptyKeyData() {
103   return Status("No key data was provided");
104 }
105
106 Status Status::ErrorUnexpectedKeyType() {
107   return Status("The key is not of the expected type");
108 }
109
110 Status Status::ErrorIncorrectSizeAesCbcIv() {
111   return Status("The \"iv\" has an unexpected length -- must be 16 bytes");
112 }
113
114 Status Status::ErrorDataTooLarge() {
115   return Status("The provided data is too large");
116 }
117
118 Status Status::ErrorUnsupported() {
119   return Status("The requested operation is unsupported");
120 }
121
122 Status Status::ErrorUnexpected() {
123   return Status("Something unexpected happened...");
124 }
125
126 Status Status::ErrorInvalidAesGcmTagLength() {
127   return Status("The tag length is invalid: either too large or not a multiple "
128                 "of 8 bits");
129 }
130
131 Status Status::ErrorGenerateKeyPublicExponent() {
132   return Status("The \"publicExponent\" is either empty, zero, or too large");
133 }
134
135 Status Status::ErrorMissingAlgorithmImportRawKey() {
136   return Status("The key's algorithm must be specified when importing "
137                 "raw-formatted key.");
138 }
139
140 Status Status::ErrorImportRsaEmptyModulus() {
141   return Status("The modulus is empty");
142 }
143
144 Status Status::ErrorGenerateRsaZeroModulus() {
145   return Status("The modulus bit length cannot be zero");
146 }
147
148 Status Status::ErrorImportRsaEmptyExponent() {
149   return Status("No bytes for the exponent were provided");
150 }
151
152 Status Status::ErrorKeyNotExtractable() {
153   return Status("They key is not extractable");
154 }
155
156 Status Status::ErrorGenerateKeyLength() {
157   return Status("Invalid key length: it is either zero or not a multiple of 8 "
158                 "bits");
159 }
160
161 Status::Status(const std::string& error_details_utf8)
162     : type_(TYPE_ERROR), error_details_(error_details_utf8) {}
163
164 Status::Status(Type type) : type_(type) {}
165
166 const uint8* Uint8VectorStart(const std::vector<uint8>& data) {
167   if (data.empty())
168     return NULL;
169   return &data[0];
170 }
171
172 void ShrinkBuffer(blink::WebArrayBuffer* buffer, unsigned int new_size) {
173   DCHECK_LE(new_size, buffer->byteLength());
174
175   if (new_size == buffer->byteLength())
176     return;
177
178   blink::WebArrayBuffer new_buffer = blink::WebArrayBuffer::create(new_size, 1);
179   DCHECK(!new_buffer.isNull());
180   memcpy(new_buffer.data(), buffer->data(), new_size);
181   *buffer = new_buffer;
182 }
183
184 blink::WebArrayBuffer CreateArrayBuffer(const uint8* data,
185                                         unsigned int data_size) {
186   blink::WebArrayBuffer buffer = blink::WebArrayBuffer::create(data_size, 1);
187   DCHECK(!buffer.isNull());
188   if (data_size)  // data_size == 0 might mean the data pointer is invalid
189     memcpy(buffer.data(), data, data_size);
190   return buffer;
191 }
192
193 // This function decodes unpadded 'base64url' encoded data, as described in
194 // RFC4648 (http://www.ietf.org/rfc/rfc4648.txt) Section 5. To do this, first
195 // change the incoming data to 'base64' encoding by applying the appropriate
196 // transformation including adding padding if required, and then call a base64
197 // decoder.
198 bool Base64DecodeUrlSafe(const std::string& input, std::string* output) {
199   std::string base64EncodedText(input);
200   std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+');
201   std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/');
202   base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '=');
203   return base::Base64Decode(base64EncodedText, output);
204 }
205
206 bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) {
207   return alg_id == blink::WebCryptoAlgorithmIdSha1 ||
208          alg_id == blink::WebCryptoAlgorithmIdSha224 ||
209          alg_id == blink::WebCryptoAlgorithmIdSha256 ||
210          alg_id == blink::WebCryptoAlgorithmIdSha384 ||
211          alg_id == blink::WebCryptoAlgorithmIdSha512;
212 }
213
214 blink::WebCryptoAlgorithm GetInnerHashAlgorithm(
215     const blink::WebCryptoAlgorithm& algorithm) {
216   DCHECK(!algorithm.isNull());
217   switch (algorithm.id()) {
218     case blink::WebCryptoAlgorithmIdHmac:
219       if (algorithm.hmacParams())
220         return algorithm.hmacParams()->hash();
221       else if (algorithm.hmacKeyParams())
222         return algorithm.hmacKeyParams()->hash();
223       break;
224     case blink::WebCryptoAlgorithmIdRsaOaep:
225       if (algorithm.rsaOaepParams())
226         return algorithm.rsaOaepParams()->hash();
227       break;
228     case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
229       if (algorithm.rsaSsaParams())
230         return algorithm.rsaSsaParams()->hash();
231       break;
232     default:
233       break;
234   }
235   return blink::WebCryptoAlgorithm::createNull();
236 }
237
238 blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) {
239   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL);
240 }
241
242 blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashId(
243     blink::WebCryptoAlgorithmId hash_id) {
244   DCHECK(IsHashAlgorithm(hash_id));
245   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
246       blink::WebCryptoAlgorithmIdHmac,
247       new blink::WebCryptoHmacParams(CreateAlgorithm(hash_id)));
248 }
249
250 blink::WebCryptoAlgorithm CreateHmacKeyGenAlgorithm(
251     blink::WebCryptoAlgorithmId hash_id,
252     unsigned int key_length_bytes) {
253   DCHECK(IsHashAlgorithm(hash_id));
254   // key_length_bytes == 0 means unspecified
255   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
256       blink::WebCryptoAlgorithmIdHmac,
257       new blink::WebCryptoHmacKeyParams(
258           CreateAlgorithm(hash_id), (key_length_bytes != 0), key_length_bytes));
259 }
260
261 blink::WebCryptoAlgorithm CreateRsaSsaAlgorithm(
262     blink::WebCryptoAlgorithmId hash_id) {
263   DCHECK(IsHashAlgorithm(hash_id));
264   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
265       blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
266       new blink::WebCryptoRsaSsaParams(CreateAlgorithm(hash_id)));
267 }
268
269 blink::WebCryptoAlgorithm CreateRsaOaepAlgorithm(
270     blink::WebCryptoAlgorithmId hash_id) {
271   DCHECK(IsHashAlgorithm(hash_id));
272   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
273       blink::WebCryptoAlgorithmIdRsaOaep,
274       new blink::WebCryptoRsaOaepParams(
275           CreateAlgorithm(hash_id), false, NULL, 0));
276 }
277
278 blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm(
279     blink::WebCryptoAlgorithmId algorithm_id,
280     unsigned int modulus_length,
281     const std::vector<uint8>& public_exponent) {
282   DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
283          algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
284          algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep);
285   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
286       algorithm_id,
287       new blink::WebCryptoRsaKeyGenParams(
288           modulus_length,
289           webcrypto::Uint8VectorStart(public_exponent),
290           public_exponent.size()));
291 }
292
293 blink::WebCryptoAlgorithm CreateAesCbcAlgorithm(const std::vector<uint8>& iv) {
294   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
295       blink::WebCryptoAlgorithmIdAesCbc,
296       new blink::WebCryptoAesCbcParams(Uint8VectorStart(iv), iv.size()));
297 }
298
299 blink::WebCryptoAlgorithm CreateAesGcmAlgorithm(
300     const std::vector<uint8>& iv,
301     const std::vector<uint8>& additional_data,
302     uint8 tag_length_bytes) {
303   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
304       blink::WebCryptoAlgorithmIdAesCbc,
305       new blink::WebCryptoAesGcmParams(Uint8VectorStart(iv),
306                                        iv.size(),
307                                        additional_data.size() != 0,
308                                        Uint8VectorStart(additional_data),
309                                        additional_data.size(),
310                                        tag_length_bytes != 0,
311                                        tag_length_bytes));
312 }
313
314 unsigned int ShaBlockSizeBytes(blink::WebCryptoAlgorithmId hash_id) {
315   switch (hash_id) {
316     case blink::WebCryptoAlgorithmIdSha1:
317     case blink::WebCryptoAlgorithmIdSha224:
318     case blink::WebCryptoAlgorithmIdSha256:
319       return 64;
320     case blink::WebCryptoAlgorithmIdSha384:
321     case blink::WebCryptoAlgorithmIdSha512:
322       return 128;
323     default:
324       NOTREACHED();
325       return 0;
326   }
327 }
328
329 }  // namespace webcrypto
330
331 }  // namespace content