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_Pkcs08PrivateKeyInfoImpl.cpp
19 * @brief This is the implementation file for _Pkcs08PrivateKeyInfoImpl class.
21 * This header file contains the implementation of _Pkcs08PrivateKeyInfoImpl class.
27 #include <openssl/evp.h>
28 #include <openssl/crypto.h>
29 #include <openssl/x509.h>
30 #include <openssl/pkcs12.h>
31 #include <openssl/objects.h>
32 #include <unique_ptr.h>
33 #include <FBaseSysLog.h>
34 #include <FBaseByteBuffer.h>
35 #include <FBaseResult.h>
36 #include <FSecPkcsAlgorithmIdentifier.h>
37 #include <FSecPkcsTypes.h>
38 #include <FSecPkcsPkcs08PrivateKeyInfo.h>
40 #include "FSecPkcs_PkcsUtility.h"
41 #include "FSecPkcs_Pkcs08PrivateKeyInfoImpl.h"
43 using namespace Tizen::Base;
45 namespace Tizen { namespace Security { namespace Pkcs
48 _Pkcs08PrivateKeyInfoImpl::_Pkcs08PrivateKeyInfoImpl(void)
55 _Pkcs08PrivateKeyInfoImpl::~_Pkcs08PrivateKeyInfoImpl(void)
62 _Pkcs08PrivateKeyInfoImpl::Construct(const Tizen::Base::ByteBuffer& encodedData)
66 int privateKeyLen = 0;
72 Tizen::Base::String prfOid = null;
73 Tizen::Base::ByteBuffer attributeBuffer;
74 const byte* pBuffer = null;
75 byte* pPrivateKey = null;
77 X509_ALGOR* pAlgo = null;
78 Tizen::Base::ByteBuffer privateKeyBuffer;
79 PKCS8_PRIV_KEY_INFO* pPrivKeyInfo = null;
80 STACK_OF(X509_ATTRIBUTE)* pStackOfAttribute = null;
81 X509_ATTRIBUTE* pAttribute = null;
83 SysAssertf(__privateKey.GetRemaining() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
85 pBuffer = encodedData.GetPointer();
86 SysTryReturnResult(NID_SEC_CRYPTO, pBuffer != null, E_INVALID_ARG, "The specified input parameter is invalid.");
88 bufferLen = encodedData.GetRemaining();
89 SysTryReturnResult(NID_SEC_CRYPTO, bufferLen > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
91 pPrivKeyInfo = d2i_PKCS8_PRIV_KEY_INFO(null, reinterpret_cast< const unsigned char** >(&pBuffer), bufferLen);
92 SysTryReturnResult(NID_SEC_CRYPTO, pPrivKeyInfo != null, E_INVALID_ARG, "The specified input parameter is invalid.");
94 pPrivateKey = pPrivKeyInfo->pkey->value.octet_string->data;
95 SysTryCatch(NID_SEC_CRYPTO, pPrivateKey != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
97 privateKeyLen = pPrivKeyInfo->pkey->value.octet_string->length;
98 SysTryCatch(NID_SEC_CRYPTO, privateKeyLen > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
100 r = privateKeyBuffer.Construct(privateKeyLen);
101 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
103 r = privateKeyBuffer.SetArray(pPrivateKey, 0, privateKeyLen);
104 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
106 privateKeyBuffer.Flip();
107 r = __privateKey.Construct(privateKeyBuffer);
109 version = ASN1_INTEGER_get(pPrivKeyInfo->version);
111 pAlgo = pPrivKeyInfo->pkeyalg;
112 SysTryCatch(NID_SEC_CRYPTO, pPrivKeyInfo != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
114 keyAlgoNid = OBJ_obj2nid(pAlgo->algorithm);
115 prfOid = _PkcsUtility::ConvertToOid(keyAlgoNid);
118 SysTryCatch(NID_SEC_CRYPTO, r != E_UNSUPPORTED_ALGORITHM, r = E_UNSUPPORTED_ALGORITHM, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] The input algorithm is not supported.");
120 r = __algorithm.Construct(prfOid, null);
121 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
123 if (pPrivKeyInfo->attributes)
125 pStackOfAttribute = pPrivKeyInfo->attributes;
126 for (index = 0; index < sk_X509_ATTRIBUTE_num(pStackOfAttribute); index++)
128 pAttribute = sk_X509_ATTRIBUTE_value(pStackOfAttribute, index);
130 std::unique_ptr< Pkcs08Attribute > pAttributeClassObj(new (std::nothrow) Pkcs08Attribute());
131 SysTryCatch(NID_SEC_CRYPTO, pAttributeClassObj != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
133 value = i2d_X509_ATTRIBUTE(pAttribute, &pTemp);
134 SysTryCatch(NID_SEC_CRYPTO, value > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
136 size = strlen(reinterpret_cast< char* >(pTemp));
137 r = attributeBuffer.Construct(size);
138 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
140 r = attributeBuffer.SetArray(pTemp, 0, size);
141 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
143 attributeBuffer.Flip();
145 r = pAttributeClassObj->Construct(attributeBuffer);
146 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
148 r = AddAttribute(*pAttributeClassObj.release());
149 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
156 PKCS8_PRIV_KEY_INFO_free(pPrivKeyInfo);
162 _Pkcs08PrivateKeyInfoImpl::Construct(const AlgorithmIdentifier& privAlgoId, const Tizen::Base::ByteBuffer& privKey)
164 result r = E_SUCCESS;
166 SysAssertf(__privateKey.GetRemaining() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
168 SysTryReturnResult(NID_SEC_CRYPTO, privKey.GetRemaining() > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
170 r = __privateKey.Construct(privKey);
171 SysTryReturnResult(NID_SEC_CRYPTO, !IsFailed(r), E_OUT_OF_MEMORY, "The memory is insufficient.");
173 r = __algorithm.Construct(privAlgoId.GetAlgorithmObjectId(), null);
174 SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), r, r, "[%s] Failed to construct the algorithm identifier.", GetErrorMessage(r));
180 _Pkcs08PrivateKeyInfoImpl::GetVersion(void) const
186 const AlgorithmIdentifier&
187 _Pkcs08PrivateKeyInfoImpl::GetPrivateKeyAlgorithm(void) const
194 _Pkcs08PrivateKeyInfoImpl::GetPrivateKey(void) const
196 ByteBuffer privateKey;
200 SysAssertf(__privateKey.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
201 SysAssertf(__algorithm.GetAlgorithmObjectId().GetLength() > 0, "Not yet constructed. Construct () should be called before use.");
206 const Tizen::Base::Collection::ArrayList&
207 _Pkcs08PrivateKeyInfoImpl::GetAttributes(void) const
213 _Pkcs08PrivateKeyInfoImpl::AddAttribute(const Pkcs08Attribute& attribute)
215 return __attributes.Add(attribute);
219 _Pkcs08PrivateKeyInfoImpl::RemoveAttribute(const Pkcs08Attribute& attribute)
221 return __attributes.Remove(attribute);
225 _Pkcs08PrivateKeyInfoImpl::GetEncodedDataN(void) const
227 result r = E_SUCCESS;
234 const byte* pBuf = null;
235 byte* pPrivateKeyData = null;
236 std::unique_ptr< ByteBuffer > pEncPrivateKeyInfo;
237 std::unique_ptr< ByteBuffer > pAttrEncoded;
238 PKCS8_PRIV_KEY_INFO* pPrivateKeyInfo = null;
239 ASN1_OCTET_STRING* pPrivKey;
240 STACK_OF(X509_ATTRIBUTE)* pAttributes = null;
241 X509_ATTRIBUTE* pAttributeStruct = null;
243 SysAssertf(__privateKey.GetRemaining() > 0, "Not yet constructed. Construct () should be called before use.");
244 SysAssertf(__algorithm.GetAlgorithmObjectId().GetLength() > 0, "Not yet constructed. Construct () should be called before use.");
248 pPrivateKeyInfo = PKCS8_PRIV_KEY_INFO_new();
249 SysTryReturn(NID_SEC_CRYPTO, pPrivateKeyInfo != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
251 pPrivKey = M_ASN1_OCTET_STRING_new();
252 SysTryReturn(NID_SEC_CRYPTO, pPrivKey != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
254 pPrivateKeyInfo->pkey->value.octet_string = pPrivKey;
255 pPrivateKeyInfo->pkey->type = V_ASN1_OCTET_STRING;
257 privLength = __privateKey.GetRemaining();
258 SysTryCatch(NID_SEC_CRYPTO, privLength > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
260 pPrivKey->data = static_cast< unsigned char* >(OPENSSL_malloc(privLength));
261 SysTryCatch(NID_SEC_CRYPTO, pPrivKey->data != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
263 pPrivKey->length = privLength;
265 pPrivateKeyData = const_cast< byte* >(__privateKey.GetPointer());
267 memcpy(pPrivKey->data, pPrivateKeyData, privLength);
269 ASN1_INTEGER_set(pPrivateKeyInfo->version, __version);
271 prf_nid = _PkcsUtility::ConvertToNid(__algorithm.GetAlgorithmObjectId());
273 pPrivateKeyInfo->pkeyalg = X509_ALGOR_new();
274 SysTryCatch(NID_SEC_CRYPTO, pPrivateKeyInfo->pkeyalg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
276 ret = X509_ALGOR_set0(pPrivateKeyInfo->pkeyalg, OBJ_nid2obj(prf_nid), V_ASN1_NULL, NULL);
277 SysTryCatch(NID_SEC_CRYPTO, ret > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
279 count = __attributes.GetCount();
283 pAttributes = sk_X509_ATTRIBUTE_new_null();
284 SysTryCatch(NID_SEC_CRYPTO, pAttributes != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
286 pPrivateKeyInfo->attributes = pAttributes;
289 for (int i = 0; i < count; i++)
291 Pkcs08Attribute* pObj = const_cast< Pkcs08Attribute* >(static_cast< const Pkcs08Attribute* >(__attributes.GetAt(i)));
294 pAttrEncoded = std::unique_ptr< ByteBuffer >(pObj->GetEncodedDataN());
295 SysTryCatch(NID_SEC_CRYPTO, pAttrEncoded, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
297 pBuf = pAttrEncoded->GetPointer();
298 pAttributeStruct = d2i_X509_ATTRIBUTE(null, reinterpret_cast< const unsigned char** >(&pBuf), pAttrEncoded->GetRemaining());
299 SysTryCatch(NID_SEC_CRYPTO, pAttributeStruct != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
301 value = sk_X509_ATTRIBUTE_push(pAttributes, pAttributeStruct);
302 SysTryCatch(NID_SEC_CRYPTO, value > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
306 value = i2d_PKCS8_PRIV_KEY_INFO(pPrivateKeyInfo, &pTemp);
307 SysTryCatch(NID_SEC_CRYPTO, value > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
309 pEncPrivateKeyInfo = std::unique_ptr< ByteBuffer >(new (std::nothrow) ByteBuffer());
310 SysTryCatch(NID_SEC_CRYPTO, pEncPrivateKeyInfo, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
312 r = pEncPrivateKeyInfo->Construct(value);
313 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
315 r = pEncPrivateKeyInfo->SetArray(pTemp, 0, value);
316 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
318 pEncPrivateKeyInfo->Flip();
324 pEncPrivateKeyInfo.reset(null);
326 PKCS8_PRIV_KEY_INFO_free(pPrivateKeyInfo);
328 return pEncPrivateKeyInfo.release();
331 _Pkcs08PrivateKeyInfoImpl*
332 _Pkcs08PrivateKeyInfoImpl::GetInstance(Pkcs08PrivateKeyInfo& pkcs08PrivateKeyInfo)
334 return pkcs08PrivateKeyInfo.__pPkcs08PrivateKeyInfoImpl;
337 const _Pkcs08PrivateKeyInfoImpl*
338 _Pkcs08PrivateKeyInfoImpl::GetInstance(const Pkcs08PrivateKeyInfo& pkcs08PrivateKeyInfo)
340 return pkcs08PrivateKeyInfo.__pPkcs08PrivateKeyInfoImpl;