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