2 // Copyright (c) 2013 Samsung Electronics Co., Ltd.
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file FSecPkcs_Pkcs05PbKdf2ParametersImpl.cpp
19 * @brief This is the implementation file for _Pkcs05PbKdf2ParametersImpl class.
21 * This header file contains the implementation of _Pkcs05PbKdf2ParametersImpl class.
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"
46 using namespace Tizen::Base;
48 namespace Tizen { namespace Security { namespace Pkcs
51 _Pkcs05PbKdf2ParametersImpl::_Pkcs05PbKdf2ParametersImpl(void)
52 : __derivedKeyLength(0)
59 _Pkcs05PbKdf2ParametersImpl::~_Pkcs05PbKdf2ParametersImpl(void)
65 _Pkcs05PbKdf2ParametersImpl::Construct(const Tizen::Base::ByteBuffer& encodedData)
69 Tizen::Base::ByteBuffer saltBuffer;
70 Tizen::Base::String prfOid = null;
72 int derivedKeyLength = 0;
76 PBKDF2PARAM* pKdf = null;
78 SysAssertf(__saltBuffer.GetRemaining() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
80 const byte* pBuffer = encodedData.GetPointer();
81 SysTryReturnResult(NID_SEC_CRYPTO, pBuffer != null, E_INVALID_ARG, "The specified input parameter is invalid.");
83 bufferLen = encodedData.GetRemaining();
84 SysTryReturnResult(NID_SEC_CRYPTO, bufferLen > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
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.");
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.");
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.");
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.");
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.");
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.");
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.");
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.");
111 __iterationCount = iter;
113 derivedKeyLength = ASN1_INTEGER_get(pKdf->keylength);
115 __derivedKeyLength = derivedKeyLength;
119 prfNid = OBJ_obj2nid(pKdf->prf->algorithm);
120 prfOid = _PkcsUtility::ConvertToOid(prfNid);
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.");
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.");
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.");
137 PBKDF2PARAM_free(pKdf);
142 _Pkcs05PbKdf2ParametersImpl::Construct(const Tizen::Base::ByteBuffer& saltBuffer, int iterationCount, int derivedKeyLength)
144 result r = E_SUCCESS;
146 SysAssertf(__saltBuffer.GetRemaining() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
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.");
152 r = __saltBuffer.Construct(saltBuffer);
153 SysTryReturnResult(NID_SEC_CRYPTO, !IsFailed(r), E_OUT_OF_MEMORY, "The memory is insufficient.");
155 __iterationCount = iterationCount;
157 __derivedKeyLength = derivedKeyLength; // derivedKeyLength is an optional parameter so no need to check its length
159 r = __oidPrf.Construct(OID_HMAC_SHA1, null);
160 SysTryReturnResult(NID_SEC_CRYPTO, !IsFailed(r), E_OUT_OF_MEMORY, "The memory is insufficient.")
167 _Pkcs05PbKdf2ParametersImpl::Construct(const Tizen::Base::ByteBuffer& saltBuffer, int iterationCount, const AlgorithmIdentifier& prf, int derivedKeyLength)
169 result r = E_SUCCESS;
171 SysAssertf(__saltBuffer.GetRemaining() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
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.");
176 r = __saltBuffer.Construct(saltBuffer);
177 SysTryReturnResult(NID_SEC_CRYPTO, !IsFailed(r), E_OUT_OF_MEMORY, "The memory is insufficient.");
179 SysTryReturnResult(NID_SEC_CRYPTO, iterationCount > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
180 __iterationCount = iterationCount;
183 __derivedKeyLength = derivedKeyLength; // derivedKeyLength is an optional parameter
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));
192 _Pkcs05PbKdf2ParametersImpl::GetEncodedDataN(void) const
195 result r = E_SUCCESS;
196 PBKDF2PARAM* pKdf = null;
197 ASN1_OCTET_STRING* pSalt = null;
198 std::unique_ptr< ByteBuffer > pEncKdfParam;
203 byte* pSaltData = null;
207 SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
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.");
212 pKdf = PBKDF2PARAM_new();
213 SysTryReturn(NID_SEC_CRYPTO, pKdf != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
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.");
219 pKdf->salt->value.octet_string = pSalt;
220 pKdf->salt->type = V_ASN1_OCTET_STRING;
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.");
225 pSalt->length = saltLength;
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.");
230 memcpy(pSalt->data, pSaltData, saltLength);
232 ASN1_INTEGER_set(pKdf->iter, __iterationCount);
234 if (__derivedKeyLength != 0) //optional parameter
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.");
239 ASN1_INTEGER_set(pKdf->keylength, __derivedKeyLength);
242 prfNid = _PkcsUtility::ConvertToNid(__oidPrf.GetAlgorithmObjectId());
244 if (prfNid != NID_hmacWithSHA1) // default : not required
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.");
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.");
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.");
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.");
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.");
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.");
266 pEncKdfParam->Flip();
272 pEncKdfParam.reset(null);
274 PBKDF2PARAM_free(pKdf);
277 return pEncKdfParam.release();
282 _Pkcs05PbKdf2ParametersImpl::GetSaltValue(void) const
286 SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
292 _Pkcs05PbKdf2ParametersImpl::GetIterationCount(void) const
296 SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
298 return __iterationCount;
301 _Pkcs05PbKdf2ParametersImpl::GetDerivedKeyLength(void) const
305 SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
307 return __derivedKeyLength;
310 const AlgorithmIdentifier&
311 _Pkcs05PbKdf2ParametersImpl::GetPrf(void) const
315 SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
320 PkcsAlgorithmParameterType
321 _Pkcs05PbKdf2ParametersImpl::GetType(void) const
324 return PKCS_ALGO_PARAM_TYPE_PKCS05_KDF02;
329 _Pkcs05PbKdf2ParametersImpl::Equals(const Object& obj) const
332 const _Pkcs05PbKdf2ParametersImpl* pOther = dynamic_cast< const _Pkcs05PbKdf2ParametersImpl* >(&obj);
334 SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
336 SysTryReturn(NID_SEC_CRYPTO, pOther != null, false, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
343 SysTryReturn(NID_SEC_CRYPTO, pOther->GetSaltValue().GetRemaining() > 0, false, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
345 SysTryReturn(NID_SEC_CRYPTO, pOther->GetPrf().GetAlgorithmObjectId().GetLength() > 0, false, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
347 value = (__saltBuffer == pOther->GetSaltValue()) && (__oidPrf.GetAlgorithmObjectId() == pOther->GetPrf().GetAlgorithmObjectId()) && (__derivedKeyLength == pOther->GetDerivedKeyLength())
348 && (__iterationCount == pOther->GetIterationCount());
355 _Pkcs05PbKdf2ParametersImpl::GetHashCode(void) const
357 SysAssertf(__saltBuffer.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
359 if (__derivedKeyLength > 0)
361 return (__saltBuffer.GetHashCode() + __oidPrf.GetAlgorithmObjectId().GetHashCode() + Integer::GetHashCode(__derivedKeyLength) + Integer::GetHashCode(__iterationCount));
365 return (__saltBuffer.GetHashCode() + __oidPrf.GetAlgorithmObjectId().GetHashCode() + Integer::GetHashCode(__iterationCount));
369 _Pkcs05PbKdf2ParametersImpl*
370 _Pkcs05PbKdf2ParametersImpl::GetInstance(Pkcs05PbKdf2Parameters& pkcs05PbKdf2Parameters)
372 return pkcs05PbKdf2Parameters.__pPkcs05PbKdf2ParametersImpl;
375 const _Pkcs05PbKdf2ParametersImpl*
376 _Pkcs05PbKdf2ParametersImpl::GetInstance(const Pkcs05PbKdf2Parameters& pkcs05PbKdf2Parameters)
378 return pkcs05PbKdf2Parameters.__pPkcs05PbKdf2ParametersImpl;
381 } } } // end of namespace Pkcs