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_Pkcs08PrivateKeyInfoImpl.cpp
20 * @brief This is the implementation file for _Pkcs08PrivateKeyInfoImpl class.
22 * This header file contains the implementation of _Pkcs08PrivateKeyInfoImpl class.
28 #include <openssl/evp.h>
29 #include <openssl/crypto.h>
30 #include <openssl/x509.h>
31 #include <openssl/pkcs12.h>
32 #include <openssl/objects.h>
33 #include <unique_ptr.h>
34 #include <FBaseSysLog.h>
35 #include <FBaseByteBuffer.h>
36 #include <FBaseResult.h>
37 #include <FSecPkcsAlgorithmIdentifier.h>
38 #include <FSecPkcsTypes.h>
39 #include <FSecPkcsPkcs08PrivateKeyInfo.h>
41 #include "FSecPkcs_PkcsUtility.h"
42 #include "FSecPkcs_Pkcs08PrivateKeyInfoImpl.h"
44 using namespace Tizen::Base;
46 namespace Tizen { namespace Security { namespace Pkcs
49 _Pkcs08PrivateKeyInfoImpl::_Pkcs08PrivateKeyInfoImpl(void)
56 _Pkcs08PrivateKeyInfoImpl::~_Pkcs08PrivateKeyInfoImpl(void)
63 _Pkcs08PrivateKeyInfoImpl::Construct(const Tizen::Base::ByteBuffer& encodedData)
67 int privateKeyLen = 0;
73 Tizen::Base::String prfOid = null;
74 Tizen::Base::ByteBuffer attributeBuffer;
75 const byte* pBuffer = null;
76 byte* pPrivateKey = null;
78 X509_ALGOR* pAlgo = null;
79 Tizen::Base::ByteBuffer privateKeyBuffer;
80 PKCS8_PRIV_KEY_INFO* pPrivKeyInfo = null;
81 STACK_OF(X509_ATTRIBUTE)* pStackOfAttribute = null;
82 X509_ATTRIBUTE* pAttribute = null;
83 Pkcs08Attribute* pAttributeClassObj = null;
85 SysAssertf(__privateKey.GetRemaining() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
86 SysAssertf(__algorithm.GetAlgorithmObjectId().GetLength() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
89 pBuffer = encodedData.GetPointer();
90 SysTryReturnResult(NID_SEC_CRYPTO, pBuffer != null, E_INVALID_ARG, "The specified input parameter is invalid.");
92 bufferLen = encodedData.GetRemaining();
93 SysTryReturnResult(NID_SEC_CRYPTO, bufferLen > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
95 pPrivKeyInfo = d2i_PKCS8_PRIV_KEY_INFO(null, reinterpret_cast< const unsigned char** >(&pBuffer), bufferLen);
96 SysTryReturnResult(NID_SEC_CRYPTO, pPrivKeyInfo != null, E_INVALID_ARG, "The specified input parameter is invalid.");
98 pPrivateKey = pPrivKeyInfo->pkey->value.octet_string->data;
99 SysTryCatch(NID_SEC_CRYPTO, pPrivateKey != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
101 privateKeyLen = pPrivKeyInfo->pkey->value.octet_string->length;
102 SysTryCatch(NID_SEC_CRYPTO, privateKeyLen > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
104 r = privateKeyBuffer.Construct(privateKeyLen);
105 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
107 r = privateKeyBuffer.SetArray(pPrivateKey, 0, privateKeyLen);
108 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
110 privateKeyBuffer.Flip();
111 r = __privateKey.Construct(privateKeyBuffer);
113 version = ASN1_INTEGER_get(pPrivKeyInfo->version);
115 pAlgo = pPrivKeyInfo->pkeyalg;
116 SysTryCatch(NID_SEC_CRYPTO, pPrivKeyInfo != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
118 keyAlgoNid = OBJ_obj2nid(pAlgo->algorithm);
119 prfOid = _PkcsUtility::ConvertToOid(keyAlgoNid);
122 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 r = __algorithm.Construct(prfOid, null);
125 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
127 if (pPrivKeyInfo->attributes)
129 pStackOfAttribute = pPrivKeyInfo->attributes;
130 for (index = 0; index < sk_X509_ATTRIBUTE_num(pStackOfAttribute); index++)
132 pAttribute = sk_X509_ATTRIBUTE_value(pStackOfAttribute, index);
134 pAttributeClassObj = new (std::nothrow) Pkcs08Attribute();
135 SysTryCatch(NID_SEC_CRYPTO, pAttributeClassObj != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
137 value = i2d_X509_ATTRIBUTE(pAttribute, &pTemp);
138 SysTryCatch(NID_SEC_CRYPTO, value > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
140 size = strlen(reinterpret_cast< char* >(pTemp));
141 r = attributeBuffer.Construct(size);
142 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
144 r = attributeBuffer.SetArray(pTemp, 0, size);
145 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
147 attributeBuffer.Flip();
149 r = pAttributeClassObj->Construct(attributeBuffer);
150 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
152 r = AddAttribute(*pAttributeClassObj);
153 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
160 PKCS8_PRIV_KEY_INFO_free(pPrivKeyInfo);
166 _Pkcs08PrivateKeyInfoImpl::Construct(const AlgorithmIdentifier& privAlgoId, const Tizen::Base::ByteBuffer& privKey)
168 result r = E_SUCCESS;
170 SysAssertf(__privateKey.GetRemaining() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
171 SysAssertf(__algorithm.GetAlgorithmObjectId().GetLength() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
174 SysTryReturnResult(NID_SEC_CRYPTO, privKey.GetRemaining() > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
176 r = __privateKey.Construct(privKey);
177 SysTryReturnResult(NID_SEC_CRYPTO, !IsFailed(r), E_OUT_OF_MEMORY, "The memory is insufficient.");
179 r = __algorithm.Construct(privAlgoId.GetAlgorithmObjectId(), null);
180 SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), r, r, "[%s] Failed to construct the algorithm identifier.", GetErrorMessage(r));
186 _Pkcs08PrivateKeyInfoImpl::GetVersion(void) const
192 const AlgorithmIdentifier&
193 _Pkcs08PrivateKeyInfoImpl::GetPrivateKeyAlgorithm(void) const
200 _Pkcs08PrivateKeyInfoImpl::GetPrivateKey(void) const
202 ByteBuffer privateKey;
206 SysAssertf(__privateKey.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
207 SysAssertf(__algorithm.GetAlgorithmObjectId().GetLength() > 0, "Not yet constructed. Construct () should be called before use.");
212 const Tizen::Base::Collection::ArrayList&
213 _Pkcs08PrivateKeyInfoImpl::GetAttributes(void) const
219 _Pkcs08PrivateKeyInfoImpl::AddAttribute(const Pkcs08Attribute& attribute)
221 return __attributes.Add(attribute);
225 _Pkcs08PrivateKeyInfoImpl::RemoveAttribute(const Pkcs08Attribute& attribute)
227 return __attributes.Remove(attribute);
231 _Pkcs08PrivateKeyInfoImpl::GetEncodedDataN(void) const
233 result r = E_SUCCESS;
240 const byte* pBuf = null;
241 byte* pPrivateKeyData = null;
242 std::unique_ptr< ByteBuffer > pEncPrivateKeyInfo;
243 std::unique_ptr< ByteBuffer > pAttrEncoded;
244 PKCS8_PRIV_KEY_INFO* pPrivateKeyInfo = null;
245 ASN1_OCTET_STRING* pPrivKey;
246 STACK_OF(X509_ATTRIBUTE)* pAttributes = null;
247 X509_ATTRIBUTE* pAttributeStruct = null;
249 SysAssertf(__privateKey.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
250 SysAssertf(__algorithm.GetAlgorithmObjectId().GetLength() > 0, "Not yet constructed. Construct () should be called before use.");
254 pPrivateKeyInfo = PKCS8_PRIV_KEY_INFO_new();
255 SysTryReturn(NID_SEC_CRYPTO, pPrivateKeyInfo != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
257 pPrivKey = M_ASN1_OCTET_STRING_new();
258 SysTryReturn(NID_SEC_CRYPTO, pPrivKey != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
260 pPrivateKeyInfo->pkey->value.octet_string = pPrivKey;
261 pPrivateKeyInfo->pkey->type = V_ASN1_OCTET_STRING;
263 privLength = __privateKey.GetRemaining();
264 SysTryCatch(NID_SEC_CRYPTO, privLength > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
266 pPrivKey->data = static_cast< unsigned char* >(OPENSSL_malloc(privLength));
267 SysTryCatch(NID_SEC_CRYPTO, pPrivKey->data != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
269 pPrivKey->length = privLength;
271 pPrivateKeyData = const_cast< byte* >(__privateKey.GetPointer());
273 memcpy(pPrivKey->data, pPrivateKeyData, privLength);
275 ASN1_INTEGER_set(pPrivateKeyInfo->version, __version);
277 prf_nid = _PkcsUtility::ConvertToNid(__algorithm.GetAlgorithmObjectId());
279 pPrivateKeyInfo->pkeyalg = X509_ALGOR_new();
280 SysTryCatch(NID_SEC_CRYPTO, pPrivateKeyInfo->pkeyalg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
282 ret = X509_ALGOR_set0(pPrivateKeyInfo->pkeyalg, OBJ_nid2obj(prf_nid), V_ASN1_NULL, NULL);
283 SysTryCatch(NID_SEC_CRYPTO, ret > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
285 count = __attributes.GetCount();
289 pAttributes = sk_X509_ATTRIBUTE_new_null();
290 SysTryCatch(NID_SEC_CRYPTO, pAttributes != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
292 pPrivateKeyInfo->attributes = pAttributes;
295 for (int i = 0; i < count; i++)
297 Pkcs08Attribute* pObj = const_cast< Pkcs08Attribute* >(static_cast< const Pkcs08Attribute* >(__attributes.GetAt(i)));
300 pAttrEncoded = std::unique_ptr< ByteBuffer >(pObj->GetEncodedDataN());
301 SysTryCatch(NID_SEC_CRYPTO, pAttrEncoded, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
303 pBuf = pAttrEncoded->GetPointer();
304 pAttributeStruct = d2i_X509_ATTRIBUTE(null, reinterpret_cast< const unsigned char** >(&pBuf), pAttrEncoded->GetRemaining());
305 SysTryCatch(NID_SEC_CRYPTO, pAttributeStruct != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
307 value = sk_X509_ATTRIBUTE_push(pAttributes, pAttributeStruct);
308 SysTryCatch(NID_SEC_CRYPTO, value > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
312 value = i2d_PKCS8_PRIV_KEY_INFO(pPrivateKeyInfo, &pTemp);
313 SysTryCatch(NID_SEC_CRYPTO, value > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
315 pEncPrivateKeyInfo = std::unique_ptr< ByteBuffer >(new (std::nothrow) ByteBuffer());
316 SysTryCatch(NID_SEC_CRYPTO, pEncPrivateKeyInfo, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
318 r = pEncPrivateKeyInfo->Construct(value);
319 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
321 r = pEncPrivateKeyInfo->SetArray(pTemp, 0, value);
322 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
324 pEncPrivateKeyInfo->Flip();
328 PKCS8_PRIV_KEY_INFO_free(pPrivateKeyInfo);
330 return pEncPrivateKeyInfo.release();
333 _Pkcs08PrivateKeyInfoImpl*
334 _Pkcs08PrivateKeyInfoImpl::GetInstance(Pkcs08PrivateKeyInfo& pkcs08PrivateKeyInfo)
336 return pkcs08PrivateKeyInfo.__pPkcs08PrivateKeyInfoImpl;
339 const _Pkcs08PrivateKeyInfoImpl*
340 _Pkcs08PrivateKeyInfoImpl::GetInstance(const Pkcs08PrivateKeyInfo& pkcs08PrivateKeyInfo)
342 return pkcs08PrivateKeyInfo.__pPkcs08PrivateKeyInfoImpl;