Merge "Fix accessing freed memory in X509CertificateStore::Update()" into tizen
[platform/framework/native/appfw.git] / src / security / crypto / FSecCryptoDesCipher.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                FSecCryptoDesCipher.cpp
19  * @brief               This file contains the declaration of Tizen::Security::Crypto::DesCipher.
20  */
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unique_ptr.h>
24 #include <openssl/evp.h>
25 #include <openssl/crypto.h>
26 #include <FBaseResult.h>
27 #include <FBaseErrors.h>
28 #include <FSecCryptoDesCipher.h>
29 #include <FSecSecretKey.h>
30 #include <FBaseSysLog.h>
31 #include "FSecCrypto_SymmetricCipher.h"
32
33 using namespace Tizen::Base;
34
35
36 namespace Tizen { namespace Security { namespace Crypto
37 {
38
39 static const int _TRANSFORMATION_STRING_PART_1_LENGTH = 3;
40 static const int _TRANSFORMATION_STRING_PART_2_BEGIN = 4;
41 static const int _TRANSFORMATION_STRING_PART_2_LENGTH_A = 9;
42 static const int _TRANSFORMATION_STRING_PART_2_LENGTH_B = 12;
43
44 DesCipher::DesCipher(void)
45         : __pSymmetricCipher(null)      // Default is DES/CBC/128
46         , __pCipherAlgorithm(null)
47         , __pDesCipherImpl(null)
48 {
49 }
50
51 DesCipher::~DesCipher(void)
52 {
53         delete __pSymmetricCipher;
54 }
55
56 result
57 DesCipher::Construct(const Tizen::Base::String& transformation, CipherOperation opMode)
58 {
59         result r = E_SUCCESS;
60         bool padVal = false;
61         String cipherMode = null;
62         String padding = null;
63
64         SysAssertf(__pSymmetricCipher == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class");
65
66         __pSymmetricCipher = new (std::nothrow) _SymmetricCipher();
67         SysTryReturn(NID_SEC_CRYPTO, __pSymmetricCipher != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
68
69         SysTryCatch(NID_SEC_CRYPTO, transformation.GetLength() > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The transformation string should be valid.");
70
71         // Setting the key size, cipher mode and padding for the Des Construct
72         r = transformation.SubString(0, _TRANSFORMATION_STRING_PART_1_LENGTH, cipherMode);
73         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "The transformation string should be valid.");
74
75         if (cipherMode.CompareTo(L"CBC") == E_SUCCESS)
76         {
77                 __pCipherAlgorithm = EVP_des_cbc();
78         }
79         else if (cipherMode.CompareTo(L"ECB") == E_SUCCESS)
80         {
81                 __pCipherAlgorithm = EVP_des_ecb();
82         }
83         else
84         {
85                 r = E_INVALID_ARG;
86                 SysLogException(NID_SEC_CRYPTO, r, "The cipher algorithm for requested mode is not supported.");
87                 goto CATCH;
88         }
89
90         r = transformation.SubString(_TRANSFORMATION_STRING_PART_2_BEGIN, _TRANSFORMATION_STRING_PART_2_LENGTH_A, padding);
91         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "The transformation string should be valid.");
92
93         if (padding.CompareTo(L"NOPADDING") == E_SUCCESS)
94         {
95                 padVal = false;
96         }
97         else
98         {
99                 r = transformation.SubString(_TRANSFORMATION_STRING_PART_2_BEGIN, _TRANSFORMATION_STRING_PART_2_LENGTH_B, padding);
100                 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "The transformation string should be valid.");
101
102                 if (padding.CompareTo(L"PKCS7PADDING") == E_SUCCESS)
103                 {
104                         padVal = true;
105                 }
106                 else
107                 {
108                         r = E_INVALID_ARG;
109                         SysLogException(NID_SEC_CRYPTO, r, "The cipher algorithm for requested padding is not supported.");
110                         goto CATCH;
111                 }
112         }
113
114         // sets the transformation
115         r = __pSymmetricCipher->SetTransformation(__pCipherAlgorithm, padVal);
116         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), , r, "[%s] Failed to do set transformation operation.", GetErrorMessage(r));
117
118         SysTryCatch(NID_SEC_CRYPTO, opMode == CIPHER_ENCRYPT || opMode == CIPHER_DECRYPT,
119                         r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The opMode should be valid.");
120
121         // sets the SetCipherOpearation
122         r = __pSymmetricCipher->SetCipherOperation(opMode);
123         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), , r, "[%s] The cipher operation request should be valid.", GetErrorMessage(r));
124
125 CATCH:
126         if (IsFailed(r))
127         {
128                 delete __pSymmetricCipher;
129                 __pSymmetricCipher = null;
130         }
131         return r;
132 }
133
134 result
135 DesCipher::SetKey(const Tizen::Security::ISecretKey& key)
136 {
137         result r = E_SUCCESS;
138         int keyLen = 0;
139
140         SysAssertf(__pSymmetricCipher != null, "Not yet constructed. Construct() should be called before use.");
141
142         std::unique_ptr<ByteBuffer> pKey(key.GetEncodedN());
143         SysTryReturnResult(NID_SEC_CRYPTO, pKey != null, E_INVALID_ARG, "Input key data should be valid.");
144
145         keyLen = static_cast< int >(pKey->GetRemaining());
146         SysTryReturnResult(NID_SEC_CRYPTO, keyLen == __pCipherAlgorithm->key_len, E_INVALID_ARG, "Input key length value should be equal to algorithm key length.");
147
148         r = __pSymmetricCipher->SetKey(key);
149         SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), r, r, "[%s] Failed to do set key operation.", GetErrorMessage(r));
150
151         return r;
152 }
153
154 result
155 DesCipher::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 DesCipher::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);
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 DesCipher::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);
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 DesCipher::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();
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 DesCipher::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 DesCipher::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 DesCipher::WrapN(const Tizen::Base::ByteBuffer& secretKey)
242 {
243         ClearLastResult();
244
245         SetLastResult(E_UNSUPPORTED_ALGORITHM);
246
247         return null;
248 }
249
250 ByteBuffer*
251 DesCipher::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