Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / content / child / webcrypto / webcrypto_util.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/webcrypto_util.h"
6
7 #include "base/base64.h"
8 #include "base/logging.h"
9 #include "base/strings/stringprintf.h"
10 #include "content/child/webcrypto/status.h"
11 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
12 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
13 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
14
15 namespace content {
16
17 namespace webcrypto {
18
19 const uint8* Uint8VectorStart(const std::vector<uint8>& data) {
20   if (data.empty())
21     return NULL;
22   return &data[0];
23 }
24
25 void ShrinkBuffer(blink::WebArrayBuffer* buffer, unsigned int new_size) {
26   DCHECK_LE(new_size, buffer->byteLength());
27
28   if (new_size == buffer->byteLength())
29     return;
30
31   blink::WebArrayBuffer new_buffer = blink::WebArrayBuffer::create(new_size, 1);
32   DCHECK(!new_buffer.isNull());
33   memcpy(new_buffer.data(), buffer->data(), new_size);
34   *buffer = new_buffer;
35 }
36
37 blink::WebArrayBuffer CreateArrayBuffer(const uint8* data,
38                                         unsigned int data_size) {
39   blink::WebArrayBuffer buffer = blink::WebArrayBuffer::create(data_size, 1);
40   DCHECK(!buffer.isNull());
41   if (data_size)  // data_size == 0 might mean the data pointer is invalid
42     memcpy(buffer.data(), data, data_size);
43   return buffer;
44 }
45
46 // This function decodes unpadded 'base64url' encoded data, as described in
47 // RFC4648 (http://www.ietf.org/rfc/rfc4648.txt) Section 5. To do this, first
48 // change the incoming data to 'base64' encoding by applying the appropriate
49 // transformation including adding padding if required, and then call a base64
50 // decoder.
51 bool Base64DecodeUrlSafe(const std::string& input, std::string* output) {
52   std::string base64EncodedText(input);
53   std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+');
54   std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/');
55   base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '=');
56   return base::Base64Decode(base64EncodedText, output);
57 }
58
59 // Returns an unpadded 'base64url' encoding of the input data, using the
60 // inverse of the process above.
61 std::string Base64EncodeUrlSafe(const base::StringPiece& input) {
62   std::string output;
63   base::Base64Encode(input, &output);
64   std::replace(output.begin(), output.end(), '+', '-');
65   std::replace(output.begin(), output.end(), '/', '_');
66   output.erase(std::remove(output.begin(), output.end(), '='), output.end());
67   return output;
68 }
69
70 std::string Base64EncodeUrlSafe(const std::vector<uint8>& input) {
71   const base::StringPiece string_piece(
72       reinterpret_cast<const char*>(Uint8VectorStart(input)), input.size());
73   return Base64EncodeUrlSafe(string_piece);
74 }
75
76 struct JwkToWebCryptoUsage {
77   const char* const jwk_key_op;
78   const blink::WebCryptoKeyUsage webcrypto_usage;
79 };
80
81 const JwkToWebCryptoUsage kJwkWebCryptoUsageMap[] = {
82     {"encrypt", blink::WebCryptoKeyUsageEncrypt},
83     {"decrypt", blink::WebCryptoKeyUsageDecrypt},
84     {"deriveKey", blink::WebCryptoKeyUsageDeriveKey},
85     // TODO(padolph): Add 'deriveBits' once supported by Blink.
86     {"sign", blink::WebCryptoKeyUsageSign},
87     {"unwrapKey", blink::WebCryptoKeyUsageUnwrapKey},
88     {"verify", blink::WebCryptoKeyUsageVerify},
89     {"wrapKey", blink::WebCryptoKeyUsageWrapKey}};
90
91 // Modifies the input usage_mask by according to the key_op value.
92 bool JwkKeyOpToWebCryptoUsage(const std::string& key_op,
93                               blink::WebCryptoKeyUsageMask* usage_mask) {
94   for (size_t i = 0; i < arraysize(kJwkWebCryptoUsageMap); ++i) {
95     if (kJwkWebCryptoUsageMap[i].jwk_key_op == key_op) {
96       *usage_mask |= kJwkWebCryptoUsageMap[i].webcrypto_usage;
97       return true;
98     }
99   }
100   return false;
101 }
102
103 // Composes a Web Crypto usage mask from an array of JWK key_ops values.
104 Status GetWebCryptoUsagesFromJwkKeyOps(
105     const base::ListValue* jwk_key_ops_value,
106     blink::WebCryptoKeyUsageMask* usage_mask) {
107   *usage_mask = 0;
108   for (size_t i = 0; i < jwk_key_ops_value->GetSize(); ++i) {
109     std::string key_op;
110     if (!jwk_key_ops_value->GetString(i, &key_op)) {
111       return Status::ErrorJwkPropertyWrongType(
112           base::StringPrintf("key_ops[%d]", static_cast<int>(i)), "string");
113     }
114     if (!JwkKeyOpToWebCryptoUsage(key_op, usage_mask))
115       return Status::ErrorJwkUnrecognizedKeyop();
116   }
117   return Status::Success();
118 }
119
120 // Composes a JWK key_ops List from a Web Crypto usage mask.
121 // Note: Caller must assume ownership of returned instance.
122 base::ListValue* CreateJwkKeyOpsFromWebCryptoUsages(
123     blink::WebCryptoKeyUsageMask usage_mask) {
124   base::ListValue* jwk_key_ops = new base::ListValue();
125   for (size_t i = 0; i < arraysize(kJwkWebCryptoUsageMap); ++i) {
126     if (usage_mask & kJwkWebCryptoUsageMap[i].webcrypto_usage)
127       jwk_key_ops->AppendString(kJwkWebCryptoUsageMap[i].jwk_key_op);
128   }
129   return jwk_key_ops;
130 }
131
132 bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) {
133   return alg_id == blink::WebCryptoAlgorithmIdSha1 ||
134          alg_id == blink::WebCryptoAlgorithmIdSha256 ||
135          alg_id == blink::WebCryptoAlgorithmIdSha384 ||
136          alg_id == blink::WebCryptoAlgorithmIdSha512;
137 }
138
139 blink::WebCryptoAlgorithm GetInnerHashAlgorithm(
140     const blink::WebCryptoAlgorithm& algorithm) {
141   DCHECK(!algorithm.isNull());
142   switch (algorithm.paramsType()) {
143     case blink::WebCryptoAlgorithmParamsTypeHmacImportParams:
144       return algorithm.hmacImportParams()->hash();
145     case blink::WebCryptoAlgorithmParamsTypeHmacKeyGenParams:
146       return algorithm.hmacKeyGenParams()->hash();
147     case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams:
148       return algorithm.rsaHashedImportParams()->hash();
149     case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams:
150       return algorithm.rsaHashedKeyGenParams()->hash();
151     default:
152       return blink::WebCryptoAlgorithm::createNull();
153   }
154 }
155
156 blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) {
157   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL);
158 }
159
160 blink::WebCryptoAlgorithm CreateHmacImportAlgorithm(
161     blink::WebCryptoAlgorithmId hash_id) {
162   DCHECK(IsHashAlgorithm(hash_id));
163   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
164       blink::WebCryptoAlgorithmIdHmac,
165       new blink::WebCryptoHmacImportParams(CreateAlgorithm(hash_id)));
166 }
167
168 blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm(
169     blink::WebCryptoAlgorithmId id,
170     blink::WebCryptoAlgorithmId hash_id) {
171   DCHECK(IsHashAlgorithm(hash_id));
172   DCHECK(id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
173          id == blink::WebCryptoAlgorithmIdRsaOaep);
174   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
175       id, new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id)));
176 }
177
178 bool CreateSecretKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm,
179                               unsigned int keylen_bytes,
180                               blink::WebCryptoKeyAlgorithm* key_algorithm) {
181   switch (algorithm.id()) {
182     case blink::WebCryptoAlgorithmIdHmac: {
183       blink::WebCryptoAlgorithm hash = GetInnerHashAlgorithm(algorithm);
184       if (hash.isNull())
185         return false;
186       if (keylen_bytes > UINT_MAX / 8)
187         return false;
188       *key_algorithm =
189           blink::WebCryptoKeyAlgorithm::createHmac(hash.id(), keylen_bytes * 8);
190       return true;
191     }
192     case blink::WebCryptoAlgorithmIdAesKw:
193     case blink::WebCryptoAlgorithmIdAesCbc:
194     case blink::WebCryptoAlgorithmIdAesCtr:
195     case blink::WebCryptoAlgorithmIdAesGcm:
196       *key_algorithm = blink::WebCryptoKeyAlgorithm::createAes(
197           algorithm.id(), keylen_bytes * 8);
198       return true;
199     default:
200       return false;
201   }
202 }
203
204 }  // namespace webcrypto
205
206 }  // namespace content