OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/webcrypto/webcrypto_impl.h" | 5 #include "content/renderer/webcrypto/webcrypto_impl.h" |
6 | 6 |
7 #include <cryptohi.h> | 7 #include <cryptohi.h> |
8 #include <pk11pub.h> | 8 #include <pk11pub.h> |
9 #include <sechash.h> | 9 #include <sechash.h> |
10 | 10 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 if (new_size == buffer->byteLength()) | 77 if (new_size == buffer->byteLength()) |
78 return; | 78 return; |
79 | 79 |
80 WebKit::WebArrayBuffer new_buffer = | 80 WebKit::WebArrayBuffer new_buffer = |
81 WebKit::WebArrayBuffer::create(new_size, 1); | 81 WebKit::WebArrayBuffer::create(new_size, 1); |
82 DCHECK(!new_buffer.isNull()); | 82 DCHECK(!new_buffer.isNull()); |
83 memcpy(new_buffer.data(), buffer->data(), new_size); | 83 memcpy(new_buffer.data(), buffer->data(), new_size); |
84 *buffer = new_buffer; | 84 *buffer = new_buffer; |
85 } | 85 } |
86 | 86 |
87 bool AesCbcEncryptDecrypt( | 87 } // namespace |
88 CK_ATTRIBUTE_TYPE operation, | 88 |
| 89 void WebCryptoImpl::Init() { |
| 90 crypto::EnsureNSSInit(); |
| 91 } |
| 92 |
| 93 bool WebCryptoImpl::EncryptInternal( |
89 const WebKit::WebCryptoAlgorithm& algorithm, | 94 const WebKit::WebCryptoAlgorithm& algorithm, |
90 const WebKit::WebCryptoKey& key, | 95 const WebKit::WebCryptoKey& key, |
91 const unsigned char* data, | 96 const unsigned char* data, |
92 unsigned data_size, | 97 unsigned data_size, |
93 WebKit::WebArrayBuffer* buffer) { | 98 WebKit::WebArrayBuffer* buffer) { |
94 DCHECK_EQ(WebKit::WebCryptoAlgorithmIdAesCbc, algorithm.id()); | 99 if (algorithm.id() != WebKit::WebCryptoAlgorithmIdAesCbc) |
| 100 return false; |
| 101 |
95 DCHECK_EQ(algorithm.id(), key.algorithm().id()); | 102 DCHECK_EQ(algorithm.id(), key.algorithm().id()); |
96 DCHECK_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); | 103 DCHECK_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); |
97 DCHECK(operation == CKA_ENCRYPT || operation == CKA_DECRYPT); | |
98 | 104 |
99 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); | 105 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); |
100 | 106 |
101 const WebKit::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); | 107 const WebKit::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); |
102 if (params->iv().size() != AES_BLOCK_SIZE) | 108 if (params->iv().size() != AES_BLOCK_SIZE) |
103 return false; | 109 return false; |
104 | 110 |
105 SECItem iv_item; | 111 SECItem iv_item; |
106 iv_item.type = siBuffer; | 112 iv_item.type = siBuffer; |
107 iv_item.data = const_cast<unsigned char*>(params->iv().data()); | 113 iv_item.data = const_cast<unsigned char*>(params->iv().data()); |
108 iv_item.len = params->iv().size(); | 114 iv_item.len = params->iv().size(); |
109 | 115 |
110 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); | 116 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); |
111 if (!param) | 117 if (!param) |
112 return false; | 118 return false; |
113 | 119 |
114 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( | 120 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( |
115 CKM_AES_CBC_PAD, operation, sym_key->key(), param.get())); | 121 CKM_AES_CBC_PAD, CKA_ENCRYPT, sym_key->key(), param.get())); |
116 | 122 |
117 if (!context.get()) | 123 if (!context.get()) |
118 return false; | 124 return false; |
119 | 125 |
120 // Oddly PK11_CipherOp takes input and output lenths as "int" rather than | 126 // Oddly PK11_CipherOp takes input and output lenths as "int" rather than |
121 // "unsigned". Do some checks now to avoid integer overflowing. | 127 // "unsigned". Do some checks now to avoid integer overflowing. |
122 if (data_size >= INT_MAX - AES_BLOCK_SIZE) { | 128 if (data_size >= INT_MAX - AES_BLOCK_SIZE) { |
123 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now | 129 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now |
124 // it doesn't make much difference since the one-shot API would end up | 130 // it doesn't make much difference since the one-shot API would end up |
125 // blowing out the memory and crashing anyway. However a newer version of | 131 // blowing out the memory and crashing anyway. However a newer version of |
126 // the spec allows for a sequence<CryptoData> so this will be relevant. | 132 // the spec allows for a sequence<CryptoData> so this will be relevant. |
127 return false; | 133 return false; |
128 } | 134 } |
129 | 135 |
130 // TODO(eroman): Refine the output buffer size. It can be computed exactly for | |
131 // encryption, and can be smaller for decryption. | |
132 unsigned output_max_len = data_size + AES_BLOCK_SIZE; | 136 unsigned output_max_len = data_size + AES_BLOCK_SIZE; |
133 CHECK_GT(output_max_len, data_size); | 137 CHECK_GT(output_max_len, data_size); |
134 | 138 |
135 *buffer = WebKit::WebArrayBuffer::create(output_max_len, 1); | 139 *buffer = WebKit::WebArrayBuffer::create(output_max_len, 1); |
136 | 140 |
137 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); | 141 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); |
138 | 142 |
139 int output_len; | 143 int output_len; |
140 if (SECSuccess != PK11_CipherOp(context.get(), | 144 if (SECSuccess != PK11_CipherOp(context.get(), |
141 buffer_data, | 145 buffer_data, |
142 &output_len, | 146 &output_len, |
143 buffer->byteLength(), | 147 buffer->byteLength(), |
144 data, | 148 data, |
145 data_size)) { | 149 data_size)) { |
146 return false; | 150 return false; |
147 } | 151 } |
148 | 152 |
149 unsigned int final_output_chunk_len; | 153 unsigned int final_output_chunk_len; |
150 if (SECSuccess != PK11_DigestFinal(context.get(), | 154 if (SECSuccess != PK11_DigestFinal(context.get(), |
151 buffer_data + output_len, | 155 buffer_data + output_len, |
152 &final_output_chunk_len, | 156 &final_output_chunk_len, |
153 output_max_len - output_len)) { | 157 output_max_len - output_len)) { |
154 return false; | 158 return false; |
155 } | 159 } |
156 | 160 |
157 ShrinkBuffer(buffer, final_output_chunk_len + output_len); | 161 ShrinkBuffer(buffer, final_output_chunk_len + output_len); |
158 return true; | 162 return true; |
159 } | 163 } |
160 | 164 |
161 } // namespace | |
162 | |
163 void WebCryptoImpl::Init() { | |
164 crypto::EnsureNSSInit(); | |
165 } | |
166 | |
167 bool WebCryptoImpl::EncryptInternal( | |
168 const WebKit::WebCryptoAlgorithm& algorithm, | |
169 const WebKit::WebCryptoKey& key, | |
170 const unsigned char* data, | |
171 unsigned data_size, | |
172 WebKit::WebArrayBuffer* buffer) { | |
173 if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) { | |
174 return AesCbcEncryptDecrypt( | |
175 CKA_ENCRYPT, algorithm, key, data, data_size, buffer); | |
176 } | |
177 | |
178 return false; | |
179 } | |
180 | |
181 bool WebCryptoImpl::DecryptInternal( | |
182 const WebKit::WebCryptoAlgorithm& algorithm, | |
183 const WebKit::WebCryptoKey& key, | |
184 const unsigned char* data, | |
185 unsigned data_size, | |
186 WebKit::WebArrayBuffer* buffer) { | |
187 if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) { | |
188 return AesCbcEncryptDecrypt( | |
189 CKA_DECRYPT, algorithm, key, data, data_size, buffer); | |
190 } | |
191 | |
192 return false; | |
193 } | |
194 | |
195 bool WebCryptoImpl::DigestInternal( | 165 bool WebCryptoImpl::DigestInternal( |
196 const WebKit::WebCryptoAlgorithm& algorithm, | 166 const WebKit::WebCryptoAlgorithm& algorithm, |
197 const unsigned char* data, | 167 const unsigned char* data, |
198 unsigned data_size, | 168 unsigned data_size, |
199 WebKit::WebArrayBuffer* buffer) { | 169 WebKit::WebArrayBuffer* buffer) { |
200 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); | 170 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); |
201 if (hash_type == HASH_AlgNULL) { | 171 if (hash_type == HASH_AlgNULL) { |
202 return false; | 172 return false; |
203 } | 173 } |
204 | 174 |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 break; | 371 break; |
402 } | 372 } |
403 default: | 373 default: |
404 return false; | 374 return false; |
405 } | 375 } |
406 | 376 |
407 return true; | 377 return true; |
408 } | 378 } |
409 | 379 |
410 } // namespace content | 380 } // namespace content |
OLD | NEW |