sync with master
[platform/framework/native/appfw.git] / src / security / pkcs / FSecPkcs_Pkcs08PrivateKeyInfoImpl.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_Pkcs08PrivateKeyInfoImpl.cpp
20  * @brief               This is the implementation file for _Pkcs08PrivateKeyInfoImpl class.
21  *
22  * This header file contains the implementation of _Pkcs08PrivateKeyInfoImpl class.
23  *
24  */
25
26
27 #include <new>
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>
40
41 #include "FSecPkcs_PkcsUtility.h"
42 #include "FSecPkcs_Pkcs08PrivateKeyInfoImpl.h"
43
44 using namespace Tizen::Base;
45
46 namespace Tizen { namespace Security { namespace Pkcs
47 {
48
49 _Pkcs08PrivateKeyInfoImpl::_Pkcs08PrivateKeyInfoImpl(void)
50         : __version(0)
51 {
52         //do nothing
53 }
54
55 //Default Destructor
56 _Pkcs08PrivateKeyInfoImpl::~_Pkcs08PrivateKeyInfoImpl(void)
57 {
58         //do nothing
59 }
60
61
62 result
63 _Pkcs08PrivateKeyInfoImpl::Construct(const Tizen::Base::ByteBuffer& encodedData)
64 {
65         result r = E_SUCCESS;
66         int version = 0;
67         int privateKeyLen = 0;
68         int bufferLen = 0;
69         int keyAlgoNid = 0;
70         int index = 0;
71         int size = 0;
72         int value = 0;
73         Tizen::Base::String prfOid = null;
74         Tizen::Base::ByteBuffer attributeBuffer;
75         const byte* pBuffer = null;
76         byte* pPrivateKey = null;
77         byte* pTemp = {0, };
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;
84
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. ");
87
88
89         pBuffer = encodedData.GetPointer();
90         SysTryReturnResult(NID_SEC_CRYPTO, pBuffer != null, E_INVALID_ARG, "The specified input parameter is invalid.");
91
92         bufferLen = encodedData.GetRemaining();
93         SysTryReturnResult(NID_SEC_CRYPTO, bufferLen > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
94
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.");
97
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.");
100
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.");
103
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.");
106
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.");
109
110         privateKeyBuffer.Flip();
111         r = __privateKey.Construct(privateKeyBuffer);
112
113         version = ASN1_INTEGER_get(pPrivKeyInfo->version);
114
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.");
117
118         keyAlgoNid = OBJ_obj2nid(pAlgo->algorithm);
119         prfOid = _PkcsUtility::ConvertToOid(keyAlgoNid);
120
121         r = GetLastResult();
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.");
123
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.");
126
127         if (pPrivKeyInfo->attributes)
128         {
129                 pStackOfAttribute = pPrivKeyInfo->attributes;
130                 for (index = 0; index < sk_X509_ATTRIBUTE_num(pStackOfAttribute); index++)
131                 {
132                         pAttribute = sk_X509_ATTRIBUTE_value(pStackOfAttribute, index);
133
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.");
136
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.");
139
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.");
143
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.");
146
147                         attributeBuffer.Flip();
148
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.");
151
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.");
154                 }
155
156         }
157
158 CATCH:
159
160         PKCS8_PRIV_KEY_INFO_free(pPrivKeyInfo);
161         return r;
162
163 }
164
165 result
166 _Pkcs08PrivateKeyInfoImpl::Construct(const AlgorithmIdentifier& privAlgoId, const Tizen::Base::ByteBuffer& privKey)
167 {
168         result r = E_SUCCESS;
169
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. ");
172
173
174         SysTryReturnResult(NID_SEC_CRYPTO, privKey.GetRemaining() > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
175
176         r = __privateKey.Construct(privKey);
177         SysTryReturnResult(NID_SEC_CRYPTO, !IsFailed(r), E_OUT_OF_MEMORY, "The memory is insufficient.");
178
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));
181
182         return r;
183 }
184
185 int
186 _Pkcs08PrivateKeyInfoImpl::GetVersion(void) const
187 {
188         ClearLastResult();
189         return __version;
190 }
191
192 const AlgorithmIdentifier&
193 _Pkcs08PrivateKeyInfoImpl::GetPrivateKeyAlgorithm(void) const
194 {
195         ClearLastResult();
196         return __algorithm;
197 }
198
199 const ByteBuffer&
200 _Pkcs08PrivateKeyInfoImpl::GetPrivateKey(void) const
201 {
202         ByteBuffer privateKey;
203
204         ClearLastResult();
205
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.");
208
209         return __privateKey;
210 }
211
212 const Tizen::Base::Collection::ArrayList&
213 _Pkcs08PrivateKeyInfoImpl::GetAttributes(void) const
214 {
215         return __attributes;
216 }
217
218 result
219 _Pkcs08PrivateKeyInfoImpl::AddAttribute(const Pkcs08Attribute& attribute)
220 {
221         return __attributes.Add(attribute);
222 }
223
224 result
225 _Pkcs08PrivateKeyInfoImpl::RemoveAttribute(const Pkcs08Attribute& attribute)
226 {
227         return __attributes.Remove(attribute);
228 }
229
230 ByteBuffer*
231 _Pkcs08PrivateKeyInfoImpl::GetEncodedDataN(void) const
232 {
233         result r = E_SUCCESS;
234         int value = 0;
235         int privLength = 0;
236         int prf_nid = 0;
237         int ret = 0;
238         int count = 0;
239         byte* pTemp = null;
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;
248
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.");
251
252         ClearLastResult();
253
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.");
256
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.");
259
260         pPrivateKeyInfo->pkey->value.octet_string = pPrivKey;
261         pPrivateKeyInfo->pkey->type = V_ASN1_OCTET_STRING;
262
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.");
265
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.");
268
269         pPrivKey->length = privLength;
270
271         pPrivateKeyData = const_cast< byte* >(__privateKey.GetPointer());
272
273         memcpy(pPrivKey->data, pPrivateKeyData, privLength);
274
275         ASN1_INTEGER_set(pPrivateKeyInfo->version, __version);
276
277         prf_nid = _PkcsUtility::ConvertToNid(__algorithm.GetAlgorithmObjectId());
278
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.");
281
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.");
284
285         count = __attributes.GetCount();
286
287         if (count != 0)
288         {
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.");
291
292                 pPrivateKeyInfo->attributes = pAttributes;
293         }
294
295         for (int i = 0; i < count; i++)
296         {
297                 Pkcs08Attribute* pObj = const_cast< Pkcs08Attribute* >(static_cast< const Pkcs08Attribute* >(__attributes.GetAt(i)));
298                 if (pObj != null)
299                 {
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.");
302
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.");
306
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.");
309                 }
310         }
311
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.");
314
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.");
317
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.");
320
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.");
323
324         pEncPrivateKeyInfo->Flip();
325
326 CATCH:
327
328         PKCS8_PRIV_KEY_INFO_free(pPrivateKeyInfo);
329         OPENSSL_free(pTemp);
330         return pEncPrivateKeyInfo.release();
331 }
332
333 _Pkcs08PrivateKeyInfoImpl*
334 _Pkcs08PrivateKeyInfoImpl::GetInstance(Pkcs08PrivateKeyInfo& pkcs08PrivateKeyInfo)
335 {
336         return pkcs08PrivateKeyInfo.__pPkcs08PrivateKeyInfoImpl;
337 }
338
339 const _Pkcs08PrivateKeyInfoImpl*
340 _Pkcs08PrivateKeyInfoImpl::GetInstance(const Pkcs08PrivateKeyInfo& pkcs08PrivateKeyInfo)
341 {
342         return pkcs08PrivateKeyInfo.__pPkcs08PrivateKeyInfoImpl;
343 }
344
345 } } }