Chromium Code Reviews| 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_impl.h" | 5 #include "content/renderer/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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 74 if (new_size == buffer->byteLength()) | 74 if (new_size == buffer->byteLength()) |
| 75 return; | 75 return; |
| 76 | 76 |
| 77 WebKit::WebArrayBuffer new_buffer = | 77 WebKit::WebArrayBuffer new_buffer = |
| 78 WebKit::WebArrayBuffer::create(new_size, 1); | 78 WebKit::WebArrayBuffer::create(new_size, 1); |
| 79 CHECK(!new_buffer.isNull()); | 79 CHECK(!new_buffer.isNull()); |
| 80 memcpy(new_buffer.data(), buffer->data(), new_size); | 80 memcpy(new_buffer.data(), buffer->data(), new_size); |
| 81 *buffer = new_buffer; | 81 *buffer = new_buffer; |
| 82 } | 82 } |
| 83 | 83 |
| 84 } // namespace | 84 bool AesCbcEncryptDecrypt( |
| 85 | 85 CK_ATTRIBUTE_TYPE operation, |
| 86 void WebCryptoImpl::Init() { | |
| 87 crypto::EnsureNSSInit(); | |
| 88 } | |
| 89 | |
| 90 bool WebCryptoImpl::EncryptInternal( | |
| 91 const WebKit::WebCryptoAlgorithm& algorithm, | 86 const WebKit::WebCryptoAlgorithm& algorithm, |
| 92 const WebKit::WebCryptoKey& key, | 87 const WebKit::WebCryptoKey& key, |
| 93 const unsigned char* data, | 88 const unsigned char* data, |
| 94 unsigned data_size, | 89 unsigned data_size, |
| 95 WebKit::WebArrayBuffer* buffer) { | 90 WebKit::WebArrayBuffer* buffer) { |
| 96 if (algorithm.id() != WebKit::WebCryptoAlgorithmIdAesCbc) | 91 DCHECK_EQ(WebKit::WebCryptoAlgorithmIdAesCbc, algorithm.id()); |
| 97 return false; | |
| 98 | |
| 99 CHECK_EQ(algorithm.id(), key.algorithm().id()); | 92 CHECK_EQ(algorithm.id(), key.algorithm().id()); |
| 100 CHECK_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); | 93 CHECK_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); |
| 94 CHECK(operation == CKA_ENCRYPT || operation == CKA_DECRYPT); | |
|
jamesr
2013/09/25 21:29:05
why are these hard CHECKs?
eroman
2013/09/25 22:11:59
Changed to DCHECK()
| |
| 101 | 95 |
| 102 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); | 96 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); |
| 103 | 97 |
| 104 const WebKit::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); | 98 const WebKit::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); |
| 105 if (params->iv().size() != AES_BLOCK_SIZE) | 99 if (params->iv().size() != AES_BLOCK_SIZE) |
| 106 return false; | 100 return false; |
| 107 | 101 |
| 108 SECItem iv_item; | 102 SECItem iv_item; |
| 109 iv_item.type = siBuffer; | 103 iv_item.type = siBuffer; |
| 110 iv_item.data = const_cast<unsigned char*>(params->iv().data()); | 104 iv_item.data = const_cast<unsigned char*>(params->iv().data()); |
| 111 iv_item.len = params->iv().size(); | 105 iv_item.len = params->iv().size(); |
| 112 | 106 |
| 113 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); | 107 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); |
| 114 if (!param) | 108 if (!param) |
| 115 return false; | 109 return false; |
| 116 | 110 |
| 117 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( | 111 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( |
| 118 CKM_AES_CBC_PAD, CKA_ENCRYPT, sym_key->key(), param.get())); | 112 CKM_AES_CBC_PAD, operation, sym_key->key(), param.get())); |
| 119 | 113 |
| 120 if (!context.get()) | 114 if (!context.get()) |
| 121 return false; | 115 return false; |
| 122 | 116 |
| 123 // Oddly PK11_CipherOp takes input and output lenths as "int" rather than | 117 // Oddly PK11_CipherOp takes input and output lenths as "int" rather than |
| 124 // "unsigned". Do some checks now to avoid integer overflowing. | 118 // "unsigned". Do some checks now to avoid integer overflowing. |
| 125 if (data_size >= INT_MAX - AES_BLOCK_SIZE) { | 119 if (data_size >= INT_MAX - AES_BLOCK_SIZE) { |
| 126 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now | 120 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now |
| 127 // it doesn't make much difference since the one-shot API would end up | 121 // it doesn't make much difference since the one-shot API would end up |
| 128 // blowing out the memory and crashing anyway. However a newer version of | 122 // blowing out the memory and crashing anyway. However a newer version of |
| 129 // the spec allows for a sequence<CryptoData> so this will be relevant. | 123 // the spec allows for a sequence<CryptoData> so this will be relevant. |
| 130 return false; | 124 return false; |
| 131 } | 125 } |
| 132 | 126 |
| 127 // TODO(eroman): Refine the output buffer size. It can be computed exactly for | |
| 128 // encryption, and can be smaller for decryption. | |
| 133 unsigned output_max_len = data_size + AES_BLOCK_SIZE; | 129 unsigned output_max_len = data_size + AES_BLOCK_SIZE; |
| 134 CHECK_GT(output_max_len, data_size); | 130 CHECK_GT(output_max_len, data_size); |
| 135 | 131 |
| 136 *buffer = WebKit::WebArrayBuffer::create(output_max_len, 1); | 132 *buffer = WebKit::WebArrayBuffer::create(output_max_len, 1); |
| 137 | 133 |
| 138 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); | 134 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); |
| 139 | 135 |
| 140 int output_len; | 136 int output_len; |
| 141 if (SECSuccess != PK11_CipherOp(context.get(), | 137 if (SECSuccess != PK11_CipherOp(context.get(), |
| 142 buffer_data, | 138 buffer_data, |
| 143 &output_len, | 139 &output_len, |
| 144 buffer->byteLength(), | 140 buffer->byteLength(), |
| 145 data, | 141 data, |
| 146 data_size)) { | 142 data_size)) { |
| 147 return false; | 143 return false; |
| 148 } | 144 } |
| 149 | 145 |
| 150 unsigned int final_output_chunk_len; | 146 unsigned int final_output_chunk_len; |
| 151 if (SECSuccess != PK11_DigestFinal(context.get(), | 147 if (SECSuccess != PK11_DigestFinal(context.get(), |
| 152 buffer_data + output_len, | 148 buffer_data + output_len, |
| 153 &final_output_chunk_len, | 149 &final_output_chunk_len, |
| 154 output_max_len - output_len)) { | 150 output_max_len - output_len)) { |
| 155 return false; | 151 return false; |
| 156 } | 152 } |
| 157 | 153 |
| 158 ShrinkBuffer(buffer, final_output_chunk_len + output_len); | 154 ShrinkBuffer(buffer, final_output_chunk_len + output_len); |
| 159 return true; | 155 return true; |
| 160 } | 156 } |
| 161 | 157 |
| 158 } // namespace | |
| 159 | |
| 160 void WebCryptoImpl::Init() { | |
| 161 crypto::EnsureNSSInit(); | |
| 162 } | |
| 163 | |
| 164 bool WebCryptoImpl::EncryptInternal( | |
| 165 const WebKit::WebCryptoAlgorithm& algorithm, | |
| 166 const WebKit::WebCryptoKey& key, | |
| 167 const unsigned char* data, | |
| 168 unsigned data_size, | |
| 169 WebKit::WebArrayBuffer* buffer) { | |
| 170 if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) { | |
| 171 return AesCbcEncryptDecrypt( | |
| 172 CKA_ENCRYPT, algorithm, key, data, data_size, buffer); | |
| 173 } | |
| 174 | |
| 175 return false; | |
| 176 } | |
| 177 | |
| 178 bool WebCryptoImpl::DecryptInternal( | |
| 179 const WebKit::WebCryptoAlgorithm& algorithm, | |
| 180 const WebKit::WebCryptoKey& key, | |
| 181 const unsigned char* data, | |
| 182 unsigned data_size, | |
| 183 WebKit::WebArrayBuffer* buffer) { | |
| 184 if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) { | |
| 185 return AesCbcEncryptDecrypt( | |
| 186 CKA_DECRYPT, algorithm, key, data, data_size, buffer); | |
| 187 } | |
| 188 | |
| 189 return false; | |
| 190 } | |
| 191 | |
| 162 bool WebCryptoImpl::DigestInternal( | 192 bool WebCryptoImpl::DigestInternal( |
| 163 const WebKit::WebCryptoAlgorithm& algorithm, | 193 const WebKit::WebCryptoAlgorithm& algorithm, |
| 164 const unsigned char* data, | 194 const unsigned char* data, |
| 165 unsigned data_size, | 195 unsigned data_size, |
| 166 WebKit::WebArrayBuffer* buffer) { | 196 WebKit::WebArrayBuffer* buffer) { |
| 167 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); | 197 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); |
| 168 if (hash_type == HASH_AlgNULL) { | 198 if (hash_type == HASH_AlgNULL) { |
| 169 return false; | 199 return false; |
| 170 } | 200 } |
| 171 | 201 |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 337 } | 367 } |
| 338 default: | 368 default: |
| 339 return false; | 369 return false; |
| 340 } | 370 } |
| 341 | 371 |
| 342 *buffer = result; | 372 *buffer = result; |
| 343 return true; | 373 return true; |
| 344 } | 374 } |
| 345 | 375 |
| 346 } // namespace content | 376 } // namespace content |
| OLD | NEW |