2 // Open Service Platform
3 // Copyright (c) 2013 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @file FSecPkcs_Pkcs05SchemesImpl.cpp
20 * @brief This is the implementation file for _Pkcs05SchemesImpl class.
22 * This header file contains the implementation of _Pkcs05SchemesImpl class.
27 #include <openssl/hmac.h>
28 #include <openssl/x509.h>
29 #include <openssl/evp.h>
30 #include <openssl/objects.h>
31 #include <openssl/obj_mac.h>
32 #include <unique_ptr.h>
33 #include <FBaseSysLog.h>
34 #include <FBaseByteBuffer.h>
35 #include <FBaseResult.h>
36 #include <FSecPkcsAlgorithmIdentifier.h>
37 #include <FSecPkcsPkcs05PbKdf2Parameters.h>
38 #include <FSecPkcsPkcs05PbEs2Parameters.h>
39 #include <FSecPkcsPkcs05PbMacParameters.h>
40 #include <FSecPkcsTypes.h>
41 #include <FSecPkcsPkcs05Schemes.h>
42 #include "FSecPkcs_PkcsUtility.h"
43 #include "FSecPkcs_Pkcs05SchemesImpl.h"
45 using namespace Tizen::Base;
47 namespace Tizen { namespace Security { namespace Pkcs
50 _Pkcs05SchemesImpl::_Pkcs05SchemesImpl(void)
51 : __pMacAlgo(EVP_sha1())
52 , __derivedKeyLength(0)
57 _Pkcs05SchemesImpl::~_Pkcs05SchemesImpl(void)
63 _Pkcs05SchemesImpl::Construct(const Tizen::Base::ByteBuffer& password, int derivedKeyLength)
67 SysAssertf(__password.GetRemaining() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class.");
69 SysTryReturnResult(NID_SEC_CRYPTO, password.GetRemaining() > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
70 SysTryReturnResult(NID_SEC_CRYPTO, derivedKeyLength > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
72 __derivedKeyLength = derivedKeyLength;
74 r = __password.Construct(password);
75 SysTryReturnResult(NID_SEC_CRYPTO, !IsFailed(r), E_OUT_OF_MEMORY, "The memory is insufficient.");
82 _Pkcs05SchemesImpl::GenerateKeyKdf2N(const Pkcs05PbKdf2Parameters& params)
86 std::unique_ptr< ByteBuffer > pOut;
87 std::unique_ptr< ByteBuffer > pSaltBuffer;
88 unsigned char out[1024] = {0, };
89 const char* pPassword = null;
90 int iterationCount = 0;
92 int derivedKeyLength = 0;
95 _OidType oidValue = _OID_TYPE_UNKNOWN;
99 SysAssertf(__password.GetPointer() != null, "Not yet constructed. Construct () should be called before use.");
100 SysAssertf(__password.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
102 pPassword = reinterpret_cast< const char* >(__password.GetPointer());
103 passwordLen = __password.GetRemaining();
105 SysTryReturn(NID_SEC_CRYPTO, params.GetPrf().GetAlgorithmObjectId().GetLength() > 0, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
107 saltLen = params.GetSaltValue().GetRemaining();
108 SysTryReturn(NID_SEC_CRYPTO, saltLen > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
110 iterationCount = params.GetIterationCount();
111 SysTryReturn(NID_SEC_CRYPTO, iterationCount > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
113 derivedKeyLength = params.GetDerivedKeyLength();
115 if (derivedKeyLength <= 0)
117 derivedKeyLength = __derivedKeyLength;
119 oidValue = _PkcsUtility::ConvertOidToEnum(params.GetPrf().GetAlgorithmObjectId());
123 case _OID_TYPE_HMAC_SHA1:
124 __pMacAlgo = EVP_sha1();
127 case _OID_TYPE_HMAC_SHA2_224:
128 __pMacAlgo = EVP_sha224();
131 case _OID_TYPE_HMAC_SHA2_256:
132 __pMacAlgo = EVP_sha256();
135 case _OID_TYPE_HMAC_SHA2_384:
136 __pMacAlgo = EVP_sha384();
139 case _OID_TYPE_HMAC_SHA2_512:
140 __pMacAlgo = EVP_sha512();
144 r = E_UNSUPPORTED_ALGORITHM;
149 ret = PKCS5_PBKDF2_HMAC(pPassword, passwordLen, params.GetSaltValue().GetPointer(), saltLen, iterationCount, __pMacAlgo, derivedKeyLength, out);
150 SysTryReturn(NID_SEC_CRYPTO, ret == 1, null, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
152 pOut = std::unique_ptr< ByteBuffer >(new (std::nothrow) ByteBuffer());
153 SysTryReturn(NID_SEC_CRYPTO, pOut, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
155 r = pOut->Construct(derivedKeyLength);
156 SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
158 r = pOut->SetArray(out, 0, derivedKeyLength);
159 SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
167 return pOut.release();
172 _Pkcs05SchemesImpl::EncryptionScheme2N(const Pkcs05PbEs2Parameters& params, const Tizen::Base::ByteBuffer& message)
175 result r = E_SUCCESS;
176 std::unique_ptr< ByteBuffer > pDKey;
177 std::unique_ptr< Pkcs05PbKdf2Parameters > pKeyDerivationFuncParam;
178 std::unique_ptr< ByteBuffer > pOutBuffer;
179 Tizen::Base::String keyOid = null;
180 Tizen::Base::String tempOid = null;
185 SysTryReturn(NID_SEC_CRYPTO, params.GetKeyDerivationAlgorithm().GetAlgorithmObjectId().GetLength() > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
186 SysTryReturn(NID_SEC_CRYPTO, params.GetEncryptionScheme().GetAlgorithmObjectId().GetLength() > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
188 tempOid = params.GetEncryptionScheme().GetAlgorithmObjectId();
190 pKeyDerivationFuncParam = std::unique_ptr< Pkcs05PbKdf2Parameters >(dynamic_cast< Pkcs05PbKdf2Parameters* >(params.GetKeyDerivationAlgorithm().GetParametersN()));
191 SysTryReturn(NID_SEC_CRYPTO, pKeyDerivationFuncParam, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
193 keyOid = params.GetKeyDerivationAlgorithm().GetAlgorithmObjectId();
194 SysTryReturn(NID_SEC_CRYPTO, keyOid == OID_PBKDF2, null, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] The input algorithm is not supported.");
196 pDKey = std::unique_ptr< ByteBuffer >(GenerateKeyKdf2N(*pKeyDerivationFuncParam));
198 SysTryReturn(NID_SEC_CRYPTO, pDKey != null, null, r, "[%s] Failed to generate key.", GetErrorMessage(r));
200 pOutBuffer = std::unique_ptr< ByteBuffer >(_PkcsUtility::EncryptDecryptN(params.GetEncryptionScheme(), *pDKey, message, modeValue));
202 SysTryReturn(NID_SEC_CRYPTO, pOutBuffer != null, null, r, "[%s] Failed to encrypt message.", GetErrorMessage(r));
206 pOutBuffer.reset(null);
208 return pOutBuffer.release();
212 _Pkcs05SchemesImpl::DecryptionScheme2N(const Pkcs05PbEs2Parameters& params, const Tizen::Base::ByteBuffer& message)
214 result r = E_SUCCESS;
215 std::unique_ptr< ByteBuffer > pDKey;
216 std::unique_ptr< Pkcs05PbKdf2Parameters > pKeyDerivationFuncParam;
217 std::unique_ptr< ByteBuffer > pOutBuffer;
218 Tizen::Base::String keyOid = null;
219 Tizen::Base::String tempOid = null;
224 SysTryReturn(NID_SEC_CRYPTO, params.GetKeyDerivationAlgorithm().GetAlgorithmObjectId().GetLength() > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
225 SysTryReturn(NID_SEC_CRYPTO, params.GetEncryptionScheme().GetAlgorithmObjectId().GetLength() > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
227 tempOid = params.GetEncryptionScheme().GetAlgorithmObjectId();
229 pKeyDerivationFuncParam = std::unique_ptr< Pkcs05PbKdf2Parameters >(dynamic_cast< Pkcs05PbKdf2Parameters* >(params.GetKeyDerivationAlgorithm().GetParametersN()));
230 SysTryReturn(NID_SEC_CRYPTO, pKeyDerivationFuncParam, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
232 keyOid = params.GetKeyDerivationAlgorithm().GetAlgorithmObjectId();
233 SysTryReturn(NID_SEC_CRYPTO, keyOid == OID_PBKDF2, null, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] The input algorithm is not supported.");
235 pDKey = std::unique_ptr< ByteBuffer >(GenerateKeyKdf2N(*pKeyDerivationFuncParam));
237 SysTryReturn(NID_SEC_CRYPTO, pDKey != null, null, r, "[%s] Failed to generate key.", GetErrorMessage(r));
239 pOutBuffer = std::unique_ptr< ByteBuffer >(_PkcsUtility::EncryptDecryptN(params.GetEncryptionScheme(), *pDKey, message, modeValue));
241 SysTryReturn(NID_SEC_CRYPTO, pOutBuffer != null, null, r, "[%s] Failed to encrypt message.", GetErrorMessage(r));
245 pOutBuffer.reset(null);
248 return pOutBuffer.release();
252 _Pkcs05SchemesImpl::GetPbHMacN(const Pkcs05PbMacParameters& params, const Tizen::Base::ByteBuffer& message)
255 result r = E_SUCCESS;
256 std::unique_ptr< ByteBuffer > pDKey;
257 std::unique_ptr< Pkcs05PbKdf2Parameters > pKeyDerivationFuncParam;
258 std::unique_ptr< byte > pMd;
259 std::unique_ptr< ByteBuffer > pOutput;
260 Tizen::Base::String keyOid = null;
261 Tizen::Base::String messageAuthScheme = null;
262 unsigned int mdLen = 0;
267 _OidType oidValue = _OID_TYPE_UNKNOWN;
271 SysTryReturn(NID_SEC_CRYPTO, params.GetKeyDerivationAlgorithm().GetAlgorithmObjectId().GetLength() > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
272 SysTryReturn(NID_SEC_CRYPTO, params.GetMacAlgorithm().GetAlgorithmObjectId().GetLength() > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
274 keyOid = params.GetKeyDerivationAlgorithm().GetAlgorithmObjectId();
275 SysTryReturn(NID_SEC_CRYPTO, keyOid == OID_PBKDF2, null, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] The input algorithm is not supported.");
277 pData = const_cast< byte* >(message.GetPointer());
278 SysTryReturn(NID_SEC_CRYPTO, pData != null, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
280 dataLen = message.GetRemaining();
281 SysTryReturn(NID_SEC_CRYPTO, dataLen > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
283 pKeyDerivationFuncParam = std::unique_ptr< Pkcs05PbKdf2Parameters >(dynamic_cast< Pkcs05PbKdf2Parameters* >(params.GetKeyDerivationAlgorithm().GetParametersN()));
284 SysTryReturn(NID_SEC_CRYPTO, pKeyDerivationFuncParam, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
286 pDKey = std::unique_ptr< ByteBuffer >(GenerateKeyKdf2N(*pKeyDerivationFuncParam));
287 SysTryReturn(NID_SEC_CRYPTO, pDKey, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
289 messageAuthScheme = params.GetMacAlgorithm().GetAlgorithmObjectId();
291 oidValue = _PkcsUtility::ConvertOidToEnum(messageAuthScheme);
294 case _OID_TYPE_HMAC_SHA1:
295 __pMacAlgo = EVP_sha1();
298 case _OID_TYPE_HMAC_SHA2_224:
299 __pMacAlgo = EVP_sha224();
302 case _OID_TYPE_HMAC_SHA2_256:
303 __pMacAlgo = EVP_sha256();
306 case _OID_TYPE_HMAC_SHA2_384:
307 __pMacAlgo = EVP_sha384();
310 case _OID_TYPE_HMAC_SHA2_512:
311 __pMacAlgo = EVP_sha512();
315 r = E_UNSUPPORTED_ALGORITHM;
320 mdLen = EVP_MD_size(__pMacAlgo);
321 SysTryReturn(NID_SEC_CRYPTO, mdLen > 0, null, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
323 pMd = std::unique_ptr< byte >(new (std::nothrow) byte[mdLen]);
324 SysTryReturn(NID_SEC_CRYPTO, pMd, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
326 memset(pMd.get(), 0, mdLen);
328 pKey = const_cast< byte* >(pDKey->GetPointer());
329 SysTryReturn(NID_SEC_CRYPTO, pKey != null, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
331 keyLen = pDKey->GetRemaining();
332 SysTryReturn(NID_SEC_CRYPTO, keyLen > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
335 //gets HMAC of the input data for SEC_MAC_SHA224
336 HMAC(__pMacAlgo, pKey, keyLen, pData, dataLen, pMd.get(), &mdLen);
337 SysTryReturn(NID_SEC_CRYPTO, mdLen != 0, null, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
339 //stores the HMAC output in bytebuffer
340 pOutput = std::unique_ptr< ByteBuffer >(new (std::nothrow) ByteBuffer());
341 SysTryReturn(NID_SEC_CRYPTO, pOutput, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
343 r = pOutput->Construct(mdLen);
344 SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), null, E_OUT_OF_MEMORY, "[E_OUT_MEMORY] The memory is insufficient.");
346 r = pOutput->SetArray(pMd.get(), 0, mdLen);
347 SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
355 return pOutput.release();
360 _Pkcs05SchemesImpl::VerifyPbMac(const Pkcs05PbMacParameters& params, const Tizen::Base::ByteBuffer& message, const Tizen::Base::ByteBuffer& mac)
362 result r = E_SUCCESS;
363 std::unique_ptr< ByteBuffer > pDKey;
364 std::unique_ptr< Pkcs05PbKdf2Parameters > pKeyDerivationFuncParam;
365 std::unique_ptr< byte > pMd;
366 std::unique_ptr< ByteBuffer > pOutput;
367 Tizen::Base::String keyOid = null;
368 Tizen::Base::String messageAuthScheme = null;
369 unsigned int mdLen = 0;
374 _OidType oidValue = _OID_TYPE_UNKNOWN;
378 SysTryReturn(NID_SEC_CRYPTO, params.GetKeyDerivationAlgorithm().GetAlgorithmObjectId().GetLength() > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
379 SysTryReturn(NID_SEC_CRYPTO, params.GetMacAlgorithm().GetAlgorithmObjectId().GetLength() > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
381 keyOid = params.GetKeyDerivationAlgorithm().GetAlgorithmObjectId();
382 SysTryReturn(NID_SEC_CRYPTO, keyOid == OID_PBKDF2, null, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] The input algorithm is not supported.");
384 pData = const_cast< byte* >(message.GetPointer());
385 SysTryReturn(NID_SEC_CRYPTO, pData != null, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
387 dataLen = message.GetRemaining();
388 SysTryReturn(NID_SEC_CRYPTO, dataLen > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
390 pKeyDerivationFuncParam = std::unique_ptr< Pkcs05PbKdf2Parameters >(dynamic_cast< Pkcs05PbKdf2Parameters* >(params.GetKeyDerivationAlgorithm().GetParametersN()));
391 SysTryReturn(NID_SEC_CRYPTO, pKeyDerivationFuncParam, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
393 pDKey = std::unique_ptr< ByteBuffer >(GenerateKeyKdf2N(*pKeyDerivationFuncParam));
394 SysTryReturn(NID_SEC_CRYPTO, pDKey, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
396 messageAuthScheme = params.GetMacAlgorithm().GetAlgorithmObjectId();
398 oidValue = _PkcsUtility::ConvertOidToEnum(messageAuthScheme);
401 case _OID_TYPE_HMAC_SHA1:
402 __pMacAlgo = EVP_sha1();
405 case _OID_TYPE_HMAC_SHA2_224:
406 __pMacAlgo = EVP_sha224();
409 case _OID_TYPE_HMAC_SHA2_256:
410 __pMacAlgo = EVP_sha256();
413 case _OID_TYPE_HMAC_SHA2_384:
414 __pMacAlgo = EVP_sha384();
417 case _OID_TYPE_HMAC_SHA2_512:
418 __pMacAlgo = EVP_sha512();
422 r = E_UNSUPPORTED_ALGORITHM;
427 mdLen = EVP_MD_size(__pMacAlgo);
428 SysTryReturn(NID_SEC_CRYPTO, mdLen > 0, null, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
430 pMd = std::unique_ptr< byte >(new (std::nothrow) byte[mdLen]);
431 SysTryReturn(NID_SEC_CRYPTO, pMd, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
433 memset(pMd.get(), 0, mdLen);
435 pKey = const_cast< byte* >(pDKey->GetPointer());
436 SysTryReturn(NID_SEC_CRYPTO, pKey != null, null, E_KEY_NOT_FOUND, "[E_INVALID_ARG] The specified input parameter is invalid.");
438 keyLen = pDKey->GetRemaining();
439 SysTryReturn(NID_SEC_CRYPTO, keyLen > 0, null, E_KEY_NOT_FOUND, "[E_INVALID_ARG] The specified input parameter is invalid.");
442 //gets HMAC of the input data for SEC_MAC_SHA224
443 HMAC(__pMacAlgo, pKey, keyLen, pData, dataLen, pMd.get(), &mdLen);
444 SysTryReturn(NID_SEC_CRYPTO, mdLen != 0, null, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
446 //stores the HMAC output in bytebuffer
447 pOutput = std::unique_ptr< ByteBuffer >(new (std::nothrow) ByteBuffer());
448 SysTryReturn(NID_SEC_CRYPTO, pOutput, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
450 r = pOutput->Construct(mdLen);
451 SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), null, E_OUT_OF_MEMORY, "[E_OUT_MEMORY] The memory is insufficient.");
453 r = pOutput->SetArray(pMd.get(), 0, mdLen);
454 SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
458 if (pOutput->GetRemaining() == mac.GetRemaining())
460 SysTryReturn(NID_SEC_CRYPTO, mac == *pOutput, null, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
468 _Pkcs05SchemesImpl::GetInstance(Pkcs05Schemes& pkcs05Schemes)
470 return pkcs05Schemes.__pPkcs05SchemesImpl;
473 const _Pkcs05SchemesImpl*
474 _Pkcs05SchemesImpl::GetInstance(const Pkcs05Schemes& pkcs05Schemes)
476 return pkcs05Schemes.__pPkcs05SchemesImpl;
480 } } } // end of namespace Pkcs05