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 namespace {
17
CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmId aes_alg_id,unsigned short length)18 blink::WebCryptoAlgorithm CreateAesKeyGenAlgorithm(
19 blink::WebCryptoAlgorithmId aes_alg_id,
20 unsigned short length) {
21 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
22 aes_alg_id, new blink::WebCryptoAesKeyGenParams(length));
23 }
24
IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id)25 bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) {
26 return alg_id == blink::WebCryptoAlgorithmIdSha1 ||
27 alg_id == blink::WebCryptoAlgorithmIdSha224 ||
28 alg_id == blink::WebCryptoAlgorithmIdSha256 ||
29 alg_id == blink::WebCryptoAlgorithmIdSha384 ||
30 alg_id == blink::WebCryptoAlgorithmIdSha512;
31 }
32
33 } // namespace
34
Uint8VectorStart(const std::vector<uint8> & data)35 const uint8* Uint8VectorStart(const std::vector<uint8>& data) {
36 if (data.empty())
37 return NULL;
38 return &data[0];
39 }
40
ShrinkBuffer(blink::WebArrayBuffer * buffer,unsigned new_size)41 void ShrinkBuffer(blink::WebArrayBuffer* buffer, unsigned new_size) {
42 DCHECK_LE(new_size, buffer->byteLength());
43
44 if (new_size == buffer->byteLength())
45 return;
46
47 blink::WebArrayBuffer new_buffer = blink::WebArrayBuffer::create(new_size, 1);
48 DCHECK(!new_buffer.isNull());
49 memcpy(new_buffer.data(), buffer->data(), new_size);
50 *buffer = new_buffer;
51 }
52
CreateArrayBuffer(const uint8 * data,unsigned data_size)53 blink::WebArrayBuffer CreateArrayBuffer(const uint8* data, unsigned data_size) {
54 blink::WebArrayBuffer buffer = blink::WebArrayBuffer::create(data_size, 1);
55 DCHECK(!buffer.isNull());
56 if (data_size) // data_size == 0 might mean the data pointer is invalid
57 memcpy(buffer.data(), data, data_size);
58 return buffer;
59 }
60
61 // This function decodes unpadded 'base64url' encoded data, as described in
62 // RFC4648 (http://www.ietf.org/rfc/rfc4648.txt) Section 5. To do this, first
63 // change the incoming data to 'base64' encoding by applying the appropriate
64 // transformation including adding padding if required, and then call a base64
65 // decoder.
Base64DecodeUrlSafe(const std::string & input,std::string * output)66 bool Base64DecodeUrlSafe(const std::string& input, std::string* output) {
67 std::string base64EncodedText(input);
68 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+');
69 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/');
70 base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '=');
71 return base::Base64Decode(base64EncodedText, output);
72 }
73
GetInnerHashAlgorithm(const blink::WebCryptoAlgorithm & algorithm)74 blink::WebCryptoAlgorithm GetInnerHashAlgorithm(
75 const blink::WebCryptoAlgorithm& algorithm) {
76 if (algorithm.hmacParams())
77 return algorithm.hmacParams()->hash();
78 if (algorithm.hmacKeyParams())
79 return algorithm.hmacKeyParams()->hash();
80 if (algorithm.rsaSsaParams())
81 return algorithm.rsaSsaParams()->hash();
82 if (algorithm.rsaOaepParams())
83 return algorithm.rsaOaepParams()->hash();
84 return blink::WebCryptoAlgorithm::createNull();
85 }
86
CreateAlgorithm(blink::WebCryptoAlgorithmId id)87 blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) {
88 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL);
89 }
90
CreateHmacAlgorithmByHashOutputLen(unsigned short hash_output_length_bits)91 blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashOutputLen(
92 unsigned short hash_output_length_bits) {
93 blink::WebCryptoAlgorithmId hash_id;
94 switch (hash_output_length_bits) {
95 case 160:
96 hash_id = blink::WebCryptoAlgorithmIdSha1;
97 break;
98 case 224:
99 hash_id = blink::WebCryptoAlgorithmIdSha224;
100 break;
101 case 256:
102 hash_id = blink::WebCryptoAlgorithmIdSha256;
103 break;
104 case 384:
105 hash_id = blink::WebCryptoAlgorithmIdSha384;
106 break;
107 case 512:
108 hash_id = blink::WebCryptoAlgorithmIdSha512;
109 break;
110 default:
111 NOTREACHED();
112 return blink::WebCryptoAlgorithm::createNull();
113 }
114 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
115 blink::WebCryptoAlgorithmIdHmac,
116 new blink::WebCryptoHmacParams(CreateAlgorithm(hash_id)));
117 }
118
CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmId hash_id)119 blink::WebCryptoAlgorithm CreateHmacAlgorithmByHashId(
120 blink::WebCryptoAlgorithmId hash_id) {
121 DCHECK(IsHashAlgorithm(hash_id));
122 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
123 blink::WebCryptoAlgorithmIdHmac,
124 new blink::WebCryptoHmacParams(CreateAlgorithm(hash_id)));
125 }
126
CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmId hash_id,unsigned key_length_bytes)127 blink::WebCryptoAlgorithm CreateHmacKeyGenAlgorithm(
128 blink::WebCryptoAlgorithmId hash_id,
129 unsigned key_length_bytes) {
130 DCHECK(IsHashAlgorithm(hash_id));
131 // key_length_bytes == 0 means unspecified
132 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
133 blink::WebCryptoAlgorithmIdHmac,
134 new blink::WebCryptoHmacKeyParams(
135 CreateAlgorithm(hash_id), (key_length_bytes != 0), key_length_bytes));
136 }
137
CreateRsaSsaAlgorithm(blink::WebCryptoAlgorithmId hash_id)138 blink::WebCryptoAlgorithm CreateRsaSsaAlgorithm(
139 blink::WebCryptoAlgorithmId hash_id) {
140 DCHECK(IsHashAlgorithm(hash_id));
141 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
142 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
143 new blink::WebCryptoRsaSsaParams(CreateAlgorithm(hash_id)));
144 }
145
CreateRsaOaepAlgorithm(blink::WebCryptoAlgorithmId hash_id)146 blink::WebCryptoAlgorithm CreateRsaOaepAlgorithm(
147 blink::WebCryptoAlgorithmId hash_id) {
148 DCHECK(IsHashAlgorithm(hash_id));
149 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
150 blink::WebCryptoAlgorithmIdRsaOaep,
151 new blink::WebCryptoRsaOaepParams(
152 CreateAlgorithm(hash_id), false, NULL, 0));
153 }
154
CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmId algorithm_id,unsigned modulus_length,const std::vector<uint8> & public_exponent)155 blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm(
156 blink::WebCryptoAlgorithmId algorithm_id,
157 unsigned modulus_length,
158 const std::vector<uint8>& public_exponent) {
159 DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
160 algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
161 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep);
162 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
163 algorithm_id,
164 new blink::WebCryptoRsaKeyGenParams(
165 modulus_length,
166 webcrypto::Uint8VectorStart(public_exponent),
167 public_exponent.size()));
168 }
169
CreateAesCbcAlgorithm(const std::vector<uint8> & iv)170 blink::WebCryptoAlgorithm CreateAesCbcAlgorithm(const std::vector<uint8>& iv) {
171 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
172 blink::WebCryptoAlgorithmIdAesCbc,
173 new blink::WebCryptoAesCbcParams(Uint8VectorStart(iv), iv.size()));
174 }
175
CreateAesGcmAlgorithm(const std::vector<uint8> & iv,const std::vector<uint8> & additional_data,uint8 tag_length_bytes)176 blink::WebCryptoAlgorithm CreateAesGcmAlgorithm(
177 const std::vector<uint8>& iv,
178 const std::vector<uint8>& additional_data,
179 uint8 tag_length_bytes) {
180 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
181 blink::WebCryptoAlgorithmIdAesCbc,
182 new blink::WebCryptoAesGcmParams(Uint8VectorStart(iv),
183 iv.size(),
184 additional_data.size() != 0,
185 Uint8VectorStart(additional_data),
186 additional_data.size(),
187 tag_length_bytes != 0,
188 tag_length_bytes));
189 }
190
CreateAesCbcKeyGenAlgorithm(unsigned short key_length_bits)191 blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm(
192 unsigned short key_length_bits) {
193 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc,
194 key_length_bits);
195 }
196
CreateAesGcmKeyGenAlgorithm(unsigned short key_length_bits)197 blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm(
198 unsigned short key_length_bits) {
199 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesGcm,
200 key_length_bits);
201 }
202
203 } // namespace webcrypto
204
205 } // namespace content
206