OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 <cryptohi.h> | 5 #include <cryptohi.h> |
6 | 6 |
| 7 #include "base/numerics/safe_math.h" |
7 #include "content/child/webcrypto/crypto_data.h" | 8 #include "content/child/webcrypto/crypto_data.h" |
8 #include "content/child/webcrypto/nss/aes_key_nss.h" | 9 #include "content/child/webcrypto/nss/aes_key_nss.h" |
9 #include "content/child/webcrypto/nss/key_nss.h" | 10 #include "content/child/webcrypto/nss/key_nss.h" |
10 #include "content/child/webcrypto/nss/util_nss.h" | 11 #include "content/child/webcrypto/nss/util_nss.h" |
11 #include "content/child/webcrypto/status.h" | 12 #include "content/child/webcrypto/status.h" |
12 #include "content/child/webcrypto/webcrypto_util.h" | 13 #include "content/child/webcrypto/webcrypto_util.h" |
13 #include "crypto/scoped_nss_types.h" | 14 #include "crypto/scoped_nss_types.h" |
14 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 15 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
15 | 16 |
16 namespace content { | 17 namespace content { |
(...skipping 26 matching lines...) Expand all Loading... |
43 return Status::OperationError(); | 44 return Status::OperationError(); |
44 | 45 |
45 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( | 46 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( |
46 CKM_AES_CBC_PAD, operation, sym_key, param.get())); | 47 CKM_AES_CBC_PAD, operation, sym_key, param.get())); |
47 | 48 |
48 if (!context.get()) | 49 if (!context.get()) |
49 return Status::OperationError(); | 50 return Status::OperationError(); |
50 | 51 |
51 // Oddly PK11_CipherOp takes input and output lengths as "int" rather than | 52 // Oddly PK11_CipherOp takes input and output lengths as "int" rather than |
52 // "unsigned int". Do some checks now to avoid integer overflowing. | 53 // "unsigned int". Do some checks now to avoid integer overflowing. |
53 if (data.byte_length() >= INT_MAX - AES_BLOCK_SIZE) { | 54 base::CheckedNumeric<int> output_max_len = data.byte_length(); |
| 55 output_max_len += AES_BLOCK_SIZE; |
| 56 if (!output_max_len.IsValid()) { |
54 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now | 57 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now |
55 // it doesn't make much difference since the one-shot API would end up | 58 // it doesn't make much difference since the one-shot API would end up |
56 // blowing out the memory and crashing anyway. | 59 // blowing out the memory and crashing anyway. |
57 return Status::ErrorDataTooLarge(); | 60 return Status::ErrorDataTooLarge(); |
58 } | 61 } |
59 | 62 |
60 // PK11_CipherOp does an invalid memory access when given empty decryption | 63 // PK11_CipherOp does an invalid memory access when given empty decryption |
61 // input, or input which is not a multiple of the block size. See also | 64 // input, or input which is not a multiple of the block size. See also |
62 // https://bugzilla.mozilla.com/show_bug.cgi?id=921687. | 65 // https://bugzilla.mozilla.com/show_bug.cgi?id=921687. |
63 if (operation == CKA_DECRYPT && | 66 if (operation == CKA_DECRYPT && |
64 (data.byte_length() == 0 || (data.byte_length() % AES_BLOCK_SIZE != 0))) { | 67 (data.byte_length() == 0 || (data.byte_length() % AES_BLOCK_SIZE != 0))) { |
65 return Status::OperationError(); | 68 return Status::OperationError(); |
66 } | 69 } |
67 | 70 |
68 // TODO(eroman): Refine the output buffer size. It can be computed exactly for | 71 // TODO(eroman): Refine the output buffer size. It can be computed exactly for |
69 // encryption, and can be smaller for decryption. | 72 // encryption, and can be smaller for decryption. |
70 unsigned int output_max_len = data.byte_length() + AES_BLOCK_SIZE; | 73 buffer->resize(output_max_len.ValueOrDie()); |
71 CHECK_GT(output_max_len, data.byte_length()); | |
72 | |
73 buffer->resize(output_max_len); | |
74 | 74 |
75 unsigned char* buffer_data = Uint8VectorStart(buffer); | 75 unsigned char* buffer_data = Uint8VectorStart(buffer); |
76 | 76 |
77 int output_len; | 77 int output_len; |
78 if (SECSuccess != PK11_CipherOp(context.get(), | 78 if (SECSuccess != PK11_CipherOp(context.get(), |
79 buffer_data, | 79 buffer_data, |
80 &output_len, | 80 &output_len, |
81 buffer->size(), | 81 buffer->size(), |
82 data.bytes(), | 82 data.bytes(), |
83 data.byte_length())) { | 83 data.byte_length())) { |
84 return Status::OperationError(); | 84 return Status::OperationError(); |
85 } | 85 } |
86 | 86 |
87 unsigned int final_output_chunk_len; | 87 unsigned int final_output_chunk_len; |
88 if (SECSuccess != PK11_DigestFinal(context.get(), | 88 if (SECSuccess != |
89 buffer_data + output_len, | 89 PK11_DigestFinal(context.get(), |
90 &final_output_chunk_len, | 90 buffer_data + output_len, |
91 output_max_len - output_len)) { | 91 &final_output_chunk_len, |
| 92 (output_max_len - output_len).ValueOrDie())) { |
92 return Status::OperationError(); | 93 return Status::OperationError(); |
93 } | 94 } |
94 | 95 |
95 buffer->resize(final_output_chunk_len + output_len); | 96 buffer->resize(final_output_chunk_len + output_len); |
96 return Status::Success(); | 97 return Status::Success(); |
97 } | 98 } |
98 | 99 |
99 class AesCbcImplementation : public AesAlgorithm { | 100 class AesCbcImplementation : public AesAlgorithm { |
100 public: | 101 public: |
101 AesCbcImplementation() : AesAlgorithm(CKM_AES_CBC, "CBC") {} | 102 AesCbcImplementation() : AesAlgorithm(CKM_AES_CBC, "CBC") {} |
(...skipping 15 matching lines...) Expand all Loading... |
117 | 118 |
118 } // namespace | 119 } // namespace |
119 | 120 |
120 AlgorithmImplementation* CreatePlatformAesCbcImplementation() { | 121 AlgorithmImplementation* CreatePlatformAesCbcImplementation() { |
121 return new AesCbcImplementation; | 122 return new AesCbcImplementation; |
122 } | 123 } |
123 | 124 |
124 } // namespace webcrypto | 125 } // namespace webcrypto |
125 | 126 |
126 } // namespace content | 127 } // namespace content |
OLD | NEW |