ce7ba68c5cf4849fa4cbe69028609a3d17398fab
[platform/framework/native/appfw.git] / src / security / pkcs / FSecPkcs_Pkcs05PbKdf2ParametersImpl.cpp
1 //
2 // Copyright (c) 2013 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                FSecPkcs_Pkcs05PbKdf2ParametersImpl.cpp
19  * @brief               This is the implementation file for _Pkcs05PbKdf2ParametersImpl class.
20  *
21  * This header file contains the implementation of _Pkcs05PbKdf2ParametersImpl class.
22  *
23  */
24
25 #include <new>
26 #include <openssl/evp.h>
27 #include <openssl/crypto.h>
28 #include <openssl/x509.h>
29 #include <openssl/hmac.h>
30 #include <openssl/asn1t.h>
31 #include <openssl/asn1.h>
32 #include <openssl/objects.h>
33 #include <openssl/obj_mac.h>
34 #include <unique_ptr.h>
35 #include <FBaseSysLog.h>
36 #include <FBaseByteBuffer.h>
37 #include <FBaseResult.h>
38 #include <FBaseInteger.h>
39 #include <FSecPkcsIAlgorithmParameters.h>
40 #include <FSecPkcsAlgorithmIdentifier.h>
41 #include <FSecPkcsTypes.h>
42 #include <FSecPkcsPkcs05PbKdf2Parameters.h>
43 #include "FSecPkcs_PkcsUtility.h"
44 #include "FSecPkcs_Pkcs05PbKdf2ParametersImpl.h"
45
46 using namespace Tizen::Base;
47
48 namespace Tizen { namespace Security { namespace Pkcs
49 {
50
51 _Pkcs05PbKdf2ParametersImpl::_Pkcs05PbKdf2ParametersImpl(void)
52         : __derivedKeyLength(0)
53 {
54
55 }
56
57
58
59 _Pkcs05PbKdf2ParametersImpl::~_Pkcs05PbKdf2ParametersImpl(void)
60 {
61         //do nothing
62 }
63
64 result
65 _Pkcs05PbKdf2ParametersImpl::Construct(const Tizen::Base::ByteBuffer& encodedData)
66 {
67         result r = E_SUCCESS;
68         byte* pSalt = null;
69         Tizen::Base::ByteBuffer saltBuffer;
70         Tizen::Base::String prfOid = null;
71         int iter = 0;
72         int derivedKeyLength = 0;
73         int prfNid = 0;
74         int saltLength = 0;
75         int bufferLen = 0;
76         PBKDF2PARAM* pKdf = null;
77
78         SysAssertf(__saltBuffer.GetRemaining() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
79
80         const byte* pBuffer = encodedData.GetPointer();
81         SysTryReturnResult(NID_SEC_CRYPTO, pBuffer != null, E_INVALID_ARG, "The specified input parameter is invalid.");
82
83         bufferLen = encodedData.GetRemaining();
84         SysTryReturnResult(NID_SEC_CRYPTO, bufferLen > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
85
86         pKdf = d2i_PBKDF2PARAM(null, reinterpret_cast< const unsigned char** >(&pBuffer), bufferLen);
87         SysTryCatch(NID_SEC_CRYPTO, pKdf != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
88
89         SysTryCatch(NID_SEC_CRYPTO, pKdf->salt->type == V_ASN1_OCTET_STRING, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
90
91         pSalt = pKdf->salt->value.octet_string->data;
92         SysTryCatch(NID_SEC_CRYPTO, pSalt != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
93
94         saltLength = pKdf->salt->value.octet_string->length;
95         SysTryCatch(NID_SEC_CRYPTO, saltLength > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
96
97         r = saltBuffer.Construct(saltLength);
98         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
99
100         r = saltBuffer.SetArray(pSalt, 0, saltLength);
101         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
102
103         saltBuffer.Flip();
104
105         r = __saltBuffer.Construct(saltBuffer);
106         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
107
108         iter = ASN1_INTEGER_get(pKdf->iter);
109         SysTryCatch(NID_SEC_CRYPTO, iter > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
110
111         __iterationCount = iter;
112
113         derivedKeyLength = ASN1_INTEGER_get(pKdf->keylength);
114
115         __derivedKeyLength = derivedKeyLength;
116
117         if (pKdf->prf)
118         {
119                 prfNid = OBJ_obj2nid(pKdf->prf->algorithm);
120                 prfOid = _PkcsUtility::ConvertToOid(prfNid);
121
122                 r = GetLastResult();
123                 SysTryCatch(NID_SEC_CRYPTO, r != E_UNSUPPORTED_ALGORITHM, r = E_UNSUPPORTED_ALGORITHM, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] The input algorithm is not supported.");
124
125                 r = __oidPrf.Construct(prfOid, null);
126                 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
127
128         }
129         else
130         {
131                 r = __oidPrf.Construct(OID_HMAC_SHA1, null);
132                 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
133         }
134
135 CATCH:
136
137         PBKDF2PARAM_free(pKdf);
138         return r;
139 }
140
141 result
142 _Pkcs05PbKdf2ParametersImpl::Construct(const Tizen::Base::ByteBuffer& saltBuffer, int iterationCount, int derivedKeyLength)
143 {
144         result r = E_SUCCESS;
145
146         SysAssertf(__saltBuffer.GetRemaining() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
147
148         SysTryReturnResult(NID_SEC_CRYPTO, saltBuffer.GetRemaining() > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
149         SysTryReturnResult(NID_SEC_CRYPTO, iterationCount > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
150         SysTryReturnResult(NID_SEC_CRYPTO, derivedKeyLength >= 0, E_INVALID_ARG, "The specified input parameter is invalid.");
151
152         r = __saltBuffer.Construct(saltBuffer);
153         SysTryReturnResult(NID_SEC_CRYPTO, !IsFailed(r), E_OUT_OF_MEMORY, "The memory is insufficient.");
154
155         __iterationCount = iterationCount;
156
157         __derivedKeyLength = derivedKeyLength; // derivedKeyLength is an optional parameter so no need to check its length
158
159         r = __oidPrf.Construct(OID_HMAC_SHA1, null);
160         SysTryReturnResult(NID_SEC_CRYPTO, !IsFailed(r), E_OUT_OF_MEMORY, "The memory is insufficient.")
161
162         return r;
163 }
164
165
166 result
167 _Pkcs05PbKdf2ParametersImpl::Construct(const Tizen::Base::ByteBuffer& saltBuffer, int iterationCount, const AlgorithmIdentifier& prf, int derivedKeyLength)
168 {
169         result r = E_SUCCESS;
170
171         SysAssertf(__saltBuffer.GetRemaining() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
172
173         SysTryReturnResult(NID_SEC_CRYPTO, saltBuffer.GetRemaining() > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
174         SysTryReturnResult(NID_SEC_CRYPTO, derivedKeyLength >= 0, E_INVALID_ARG, "The specified input parameter is invalid.");
175
176         r = __saltBuffer.Construct(saltBuffer);
177         SysTryReturnResult(NID_SEC_CRYPTO, !IsFailed(r), E_OUT_OF_MEMORY, "The memory is insufficient.");
178
179         SysTryReturnResult(NID_SEC_CRYPTO, iterationCount > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
180         __iterationCount = iterationCount;
181
182
183         __derivedKeyLength = derivedKeyLength; // derivedKeyLength is an optional parameter
184
185         r = __oidPrf.Construct(prf.GetAlgorithmObjectId(), null); // prf is a default parameter.
186         SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), r, r, "[%s] Failed to construct the algorithm identifier", GetErrorMessage(r));
187
188         return r;
189 }
190
191 ByteBuffer*
192 _Pkcs05PbKdf2ParametersImpl::GetEncodedDataN(void) const
193 {
194         ClearLastResult();
195         result r = E_SUCCESS;
196         PBKDF2PARAM* pKdf = null;
197         ASN1_OCTET_STRING* pSalt = null;
198         std::unique_ptr< ByteBuffer > pEncKdfParam;
199         int saltLength = 0;
200         int prfNid = 0;
201         int value = 0;
202         int ret = 0;
203         byte* pSaltData = null;
204         byte* pTemp = {0, };
205
206
207         SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
208
209         saltLength = __saltBuffer.GetRemaining();
210         SysTryReturn(NID_SEC_CRYPTO, saltLength > 0, null, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
211
212         pKdf = PBKDF2PARAM_new();
213         SysTryReturn(NID_SEC_CRYPTO, pKdf != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
214
215         pSalt = M_ASN1_OCTET_STRING_new();
216         SysTryReturn(NID_SEC_CRYPTO, pSalt != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
217
218
219         pKdf->salt->value.octet_string = pSalt;
220         pKdf->salt->type = V_ASN1_OCTET_STRING;
221
222         pSalt->data = static_cast< unsigned char* >(OPENSSL_malloc(saltLength));
223         SysTryCatch(NID_SEC_CRYPTO, pSalt->data != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
224
225         pSalt->length = saltLength;
226
227         pSaltData = const_cast< byte* >(__saltBuffer.GetPointer());
228         SysTryCatch(NID_SEC_CRYPTO, pSaltData != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
229
230         memcpy(pSalt->data, pSaltData, saltLength);
231
232         ASN1_INTEGER_set(pKdf->iter, __iterationCount);
233
234         if (__derivedKeyLength != 0) //optional parameter
235         {
236                 pKdf->keylength = M_ASN1_INTEGER_new();
237                 SysTryCatch(NID_SEC_CRYPTO, pKdf->keylength != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
238
239                 ASN1_INTEGER_set(pKdf->keylength, __derivedKeyLength);
240         }
241
242         prfNid = _PkcsUtility::ConvertToNid(__oidPrf.GetAlgorithmObjectId());
243
244         if (prfNid != NID_hmacWithSHA1) // default : not required
245         {
246                 pKdf->prf = X509_ALGOR_new();
247                 SysTryCatch(NID_SEC_CRYPTO, (pKdf->prf != null), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
248
249                 ret = X509_ALGOR_set0(pKdf->prf, OBJ_nid2obj(prfNid), V_ASN1_NULL, NULL);
250                 SysTryCatch(NID_SEC_CRYPTO, ret > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
251         }
252
253         value = i2d_PBKDF2PARAM(pKdf, &pTemp);
254         SysTryCatch(NID_SEC_CRYPTO, value > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
255         SysTryCatch(NID_SEC_CRYPTO, pTemp != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
256
257         pEncKdfParam = std::unique_ptr< ByteBuffer >(new (std::nothrow) ByteBuffer());
258         SysTryCatch(NID_SEC_CRYPTO, pEncKdfParam, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
259
260         r = pEncKdfParam->Construct(value);
261         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
262
263         r = pEncKdfParam->SetArray(pTemp, 0, value);
264         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
265
266         pEncKdfParam->Flip();
267
268 CATCH:
269
270         if (IsFailed(r))
271         {
272                 pEncKdfParam.reset(null);
273         }
274         PBKDF2PARAM_free(pKdf);
275         OPENSSL_free(pTemp);
276         SetLastResult(r);
277         return pEncKdfParam.release();
278
279 }
280
281 const ByteBuffer&
282 _Pkcs05PbKdf2ParametersImpl::GetSaltValue(void) const
283 {
284         ClearLastResult();
285
286         SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
287
288         return __saltBuffer;
289 }
290
291 int
292 _Pkcs05PbKdf2ParametersImpl::GetIterationCount(void) const
293 {
294         ClearLastResult();
295
296         SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
297
298         return __iterationCount;
299 }
300 int
301 _Pkcs05PbKdf2ParametersImpl::GetDerivedKeyLength(void) const
302 {
303         ClearLastResult();
304
305         SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
306
307         return __derivedKeyLength;
308 }
309
310 const AlgorithmIdentifier&
311 _Pkcs05PbKdf2ParametersImpl::GetPrf(void) const
312 {
313         ClearLastResult();
314
315         SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
316
317         return __oidPrf;
318 }
319
320 PkcsAlgorithmParameterType
321 _Pkcs05PbKdf2ParametersImpl::GetType(void) const
322 {
323         ClearLastResult();
324         return PKCS_ALGO_PARAM_TYPE_PKCS05_KDF02;
325 }
326
327
328 bool
329 _Pkcs05PbKdf2ParametersImpl::Equals(const Object& obj) const
330 {
331         bool value = false;
332         const _Pkcs05PbKdf2ParametersImpl* pOther = dynamic_cast< const _Pkcs05PbKdf2ParametersImpl* >(&obj);
333
334         SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
335
336         SysTryReturn(NID_SEC_CRYPTO, pOther != null, false, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
337
338         if (pOther == this)
339         {
340                 return true;
341         }
342
343         SysTryReturn(NID_SEC_CRYPTO, pOther->GetSaltValue().GetRemaining() > 0, false, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
344
345         SysTryReturn(NID_SEC_CRYPTO, pOther->GetPrf().GetAlgorithmObjectId().GetLength() > 0, false, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
346
347         value = (__saltBuffer == pOther->GetSaltValue()) && (__oidPrf.GetAlgorithmObjectId() == pOther->GetPrf().GetAlgorithmObjectId()) && (__derivedKeyLength == pOther->GetDerivedKeyLength())
348                         && (__iterationCount == pOther->GetIterationCount());
349
350         return value;
351
352 }
353
354 int
355 _Pkcs05PbKdf2ParametersImpl::GetHashCode(void) const
356 {
357         SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
358
359         if (__derivedKeyLength > 0)
360         {
361                 return (__saltBuffer.GetHashCode() + __oidPrf.GetAlgorithmObjectId().GetHashCode() + Integer::GetHashCode(__derivedKeyLength) + Integer::GetHashCode(__iterationCount));
362         }
363         else
364         {
365                 return (__saltBuffer.GetHashCode() + __oidPrf.GetAlgorithmObjectId().GetHashCode() + Integer::GetHashCode(__iterationCount));
366         }
367 }
368
369 _Pkcs05PbKdf2ParametersImpl*
370 _Pkcs05PbKdf2ParametersImpl::GetInstance(Pkcs05PbKdf2Parameters& pkcs05PbKdf2Parameters)
371 {
372         return pkcs05PbKdf2Parameters.__pPkcs05PbKdf2ParametersImpl;
373 }
374
375 const _Pkcs05PbKdf2ParametersImpl*
376 _Pkcs05PbKdf2ParametersImpl::GetInstance(const Pkcs05PbKdf2Parameters& pkcs05PbKdf2Parameters)
377 {
378         return pkcs05PbKdf2Parameters.__pPkcs05PbKdf2ParametersImpl;
379 }
380
381 } } } // end of namespace Pkcs