Merge "Fix accessing freed memory in X509CertificateStore::Update()" into tizen
[platform/framework/native/appfw.git] / src / security / crypto / FSecCryptoRc2Cipher.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file                FSecCryptoRc2Cipher.cpp
19  * @brief               This file contains the implementation of Tizen::Security::Crypto::Rc2Cipher.
20  */
21 #include <openssl/evp.h>
22 #include <openssl/crypto.h>
23 #include <FBaseResult.h>
24 #include <FBaseErrors.h>
25 #include <FSecCryptoRc2Cipher.h>
26 #include <FSecSecretKey.h>
27 #include <FBaseSysLog.h>
28 #include "FSecCrypto_SymmetricCipher.h"
29
30 using namespace Tizen::Base;
31
32
33 namespace Tizen { namespace Security { namespace Crypto
34 {
35
36 static const int _TRANSFORMATION_STRING_PART_1_LENGTH = 3;
37 static const int _TRANSFORMATION_STRING_PART_2_BEGIN = 4;
38 static const int _TRANSFORMATION_STRING_PART_2_LENGTH_A = 9;
39 static const int _TRANSFORMATION_STRING_PART_2_LENGTH_B = 12;
40
41 Rc2Cipher::Rc2Cipher(void)
42         : __pSymmetricCipher(null)      // Default is RC2/CBC/128
43         , __pCipherAlgorithm(null)
44         , __pRc2CipherImpl(null)
45 {
46 }
47
48 Rc2Cipher::~Rc2Cipher(void)
49 {
50         delete __pSymmetricCipher;
51 }
52
53 result
54 Rc2Cipher::Construct(const Tizen::Base::String& transformation, CipherOperation opMode)
55 {
56         result r = E_SUCCESS;
57         bool padVal = false;
58         String cipherMode = null;
59         String padding = null;
60
61         SysAssertf(__pSymmetricCipher == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class");
62
63         __pSymmetricCipher = new (std::nothrow) _SymmetricCipher();
64         SysTryReturn(NID_SEC_CRYPTO, __pSymmetricCipher != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
65
66         SysTryCatch(NID_SEC_CRYPTO, transformation.GetLength() > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The transformation string should be valid.");
67
68         // Setting the key size, cipher mode and padding for the Rc2 Construct
69         r = transformation.SubString(0, _TRANSFORMATION_STRING_PART_1_LENGTH, cipherMode);
70         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "The transformation string should be valid.");
71
72         if (cipherMode.CompareTo(L"CBC") == E_SUCCESS)
73         {
74                 __pCipherAlgorithm = EVP_rc2_cbc();
75         }
76         else if (cipherMode.CompareTo(L"ECB") == E_SUCCESS)
77         {
78                 __pCipherAlgorithm = EVP_rc2_ecb();
79         }
80         else
81         {
82                 r = E_INVALID_ARG;
83                 SysLogException(NID_SEC_CRYPTO, r, "The cipher algorithm for requested mode is not supported.");
84                 goto CATCH;
85         }
86
87         r = transformation.SubString(_TRANSFORMATION_STRING_PART_2_BEGIN, _TRANSFORMATION_STRING_PART_2_LENGTH_A, padding);
88         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "The transformation string should be valid.");
89
90         if (padding.CompareTo(L"NOPADDING") == E_SUCCESS)
91         {
92                 padVal = false;
93         }
94         else
95         {
96                 r = transformation.SubString(_TRANSFORMATION_STRING_PART_2_BEGIN, _TRANSFORMATION_STRING_PART_2_LENGTH_B, padding);
97                 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "The transformation string should be valid.");
98
99                 if (padding.CompareTo(L"PKCS7PADDING") == E_SUCCESS)
100                 {
101                         padVal = true;
102                 }
103                 else
104                 {
105                         r = E_INVALID_ARG;
106                         SysLogException(NID_SEC_CRYPTO, r, "The cipher algorithm for requested padding is not supported.");
107                         goto CATCH;
108                 }
109         }
110
111         // sets the transformation
112         r = __pSymmetricCipher->SetTransformation(__pCipherAlgorithm, padVal);
113         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), , r, "[%s] Failed to do set transformation operation.", GetErrorMessage(r));
114
115         SysTryCatch(NID_SEC_CRYPTO, opMode == CIPHER_ENCRYPT || opMode == CIPHER_DECRYPT,
116                         r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The opMode should be valid.");
117
118         // sets the SetCipherOpearation
119         r = __pSymmetricCipher->SetCipherOperation(opMode);
120         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), , r, "[%s] The cipher operation request should be valid.", GetErrorMessage(r));
121
122 CATCH:
123         if (IsFailed(r))
124         {
125                 delete __pSymmetricCipher;
126                 __pSymmetricCipher = null;
127         }
128         return r;
129 }
130
131 result
132 Rc2Cipher::SetKey(const Tizen::Security::ISecretKey& key)
133 {
134         result r = E_SUCCESS;
135         int keyLen = 0;
136         ByteBuffer* pKey = null;
137
138         SysAssertf(__pSymmetricCipher != null, "Not yet constructed. Construct() should be called before use.");
139
140         pKey = key.GetEncodedN();
141         SysTryReturn(NID_SEC_CRYPTO, pKey != null, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Input key data should be valid.");
142
143         keyLen = static_cast< int >(pKey->GetRemaining());
144         SysTryCatch(NID_SEC_CRYPTO, keyLen >= 5, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Input key length should be >= algorithm key length.");
145
146         r = __pSymmetricCipher->SetKey(key);
147         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), , r, "[%s] Failed to do set key operation.", GetErrorMessage(r));
148
149 CATCH:
150         delete pKey;
151         return r;
152 }
153
154 result
155 Rc2Cipher::SetInitialVector(const Tizen::Base::ByteBuffer& initialVector)
156 {
157         result r = E_SUCCESS;
158
159         SysAssertf(__pSymmetricCipher != null, "Not yet constructed. Construct() should be called before use.");
160
161         r = __pSymmetricCipher->SetInitialVector(initialVector);
162         SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), r, r, "[%s] Failed to do set initial vector operation.", GetErrorMessage(r));
163
164         return r;
165 }
166
167 ByteBuffer*
168 Rc2Cipher::EncryptN(const Tizen::Base::ByteBuffer& input)
169 {
170         ByteBuffer* pOutput = null;
171
172         ClearLastResult();
173
174         SysAssertf(__pSymmetricCipher != null, "Not yet constructed. Construct() should be called before use.");
175
176         pOutput = __pSymmetricCipher->DoCipherN(input, true);
177         SysTryReturn(NID_SEC_CRYPTO, pOutput != null, null, GetLastResult(), "[%s]Failed to do encrypt operation", GetErrorMessage(GetLastResult()));
178
179         return pOutput;
180 }
181
182 ByteBuffer*
183 Rc2Cipher::DecryptN(const Tizen::Base::ByteBuffer& input)
184 {
185         ByteBuffer* pOutput = null;
186
187         ClearLastResult();
188
189         SysAssertf(__pSymmetricCipher != null, "Not yet constructed. Construct() should be called before use.");
190
191         pOutput = __pSymmetricCipher->DoCipherN(input, true);
192         SysTryReturn(NID_SEC_CRYPTO, pOutput != null, null, GetLastResult(), "[%s]Failed to do decrypt operation", GetErrorMessage(GetLastResult()));
193
194         return pOutput;
195 }
196
197 result
198 Rc2Cipher::Initialize(void)
199 {
200         result r = E_SUCCESS;
201
202         SysAssertf(__pSymmetricCipher != null, "Not yet constructed. Construct() should be called before use.");
203
204         r = __pSymmetricCipher->Initialize(true);
205         SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), r, r, "[%s] Failed to do initialize operation.", GetErrorMessage(r));
206
207         return r;
208 }
209
210 ByteBuffer*
211 Rc2Cipher::UpdateN(const Tizen::Base::ByteBuffer& input)
212 {
213         ByteBuffer* pOutput = null;
214
215         ClearLastResult();
216
217         SysAssertf(__pSymmetricCipher != null, "Not yet constructed. Construct() should be called before use.");
218
219         pOutput = __pSymmetricCipher->UpdateN(input);
220         SysTryReturn(NID_SEC_CRYPTO, pOutput != null, null, GetLastResult(), "[%s]Failed to do update operation", GetErrorMessage(GetLastResult()));
221
222         return pOutput;
223 }
224
225 ByteBuffer*
226 Rc2Cipher::FinalizeN(void)
227 {
228         ByteBuffer* pOutput = null;
229
230         ClearLastResult();
231
232         SysAssertf(__pSymmetricCipher != null, "Not yet constructed. Construct() should be called before use.");
233
234         pOutput = __pSymmetricCipher->FinalizeN();
235         SysTryReturn(NID_SEC_CRYPTO, pOutput != null, null, GetLastResult(), "[%s]Failed to do finalize operation", GetErrorMessage(GetLastResult()));
236
237         return pOutput;
238 }
239
240 ByteBuffer*
241 Rc2Cipher::WrapN(const Tizen::Base::ByteBuffer& secretKey)
242 {
243         ClearLastResult();
244
245         SetLastResult(E_UNSUPPORTED_ALGORITHM);
246
247         return null;
248 }
249
250 ByteBuffer*
251 Rc2Cipher::UnwrapN(const Tizen::Base::ByteBuffer& wrappedKey)
252 {
253         ClearLastResult();
254
255         SetLastResult(E_UNSUPPORTED_ALGORITHM);
256
257         return null;
258 }
259
260 } } } //Tizen::Security::Crypto