Revert "Fix prevent defect for locales"
[platform/framework/native/appfw.git] / src / security / pkcs / FSecPkcs_Pkcs08PrivateKeyInfoImpl.cpp
1 //
2 // Copyright (c) 2013 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15 //
16
17 /**
18  * @file                FSecPkcs_Pkcs08PrivateKeyInfoImpl.cpp
19  * @brief               This is the implementation file for _Pkcs08PrivateKeyInfoImpl class.
20  *
21  * This header file contains the implementation of _Pkcs08PrivateKeyInfoImpl class.
22  *
23  */
24
25
26 #include <new>
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>
39
40 #include "FSecPkcs_PkcsUtility.h"
41 #include "FSecPkcs_Pkcs08PrivateKeyInfoImpl.h"
42
43 using namespace Tizen::Base;
44
45 namespace Tizen { namespace Security { namespace Pkcs
46 {
47
48 _Pkcs08PrivateKeyInfoImpl::_Pkcs08PrivateKeyInfoImpl(void)
49         : __version(0)
50 {
51         //do nothing
52 }
53
54 //Default Destructor
55 _Pkcs08PrivateKeyInfoImpl::~_Pkcs08PrivateKeyInfoImpl(void)
56 {
57         //do nothing
58 }
59
60
61 result
62 _Pkcs08PrivateKeyInfoImpl::Construct(const Tizen::Base::ByteBuffer& encodedData)
63 {
64         result r = E_SUCCESS;
65         int version = 0;
66         int privateKeyLen = 0;
67         int bufferLen = 0;
68         int keyAlgoNid = 0;
69         int index = 0;
70         int size = 0;
71         int value = 0;
72         Tizen::Base::String prfOid = null;
73         Tizen::Base::ByteBuffer attributeBuffer;
74         const byte* pBuffer = null;
75         byte* pPrivateKey = null;
76         byte* pTemp = {0, };
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;
82
83         SysAssertf(__privateKey.GetRemaining() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
84
85         pBuffer = encodedData.GetPointer();
86         SysTryReturnResult(NID_SEC_CRYPTO, pBuffer != null, E_INVALID_ARG, "The specified input parameter is invalid.");
87
88         bufferLen = encodedData.GetRemaining();
89         SysTryReturnResult(NID_SEC_CRYPTO, bufferLen > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
90
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.");
93
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.");
96
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.");
99
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.");
102
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.");
105
106         privateKeyBuffer.Flip();
107         r = __privateKey.Construct(privateKeyBuffer);
108
109         version = ASN1_INTEGER_get(pPrivKeyInfo->version);
110
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.");
113
114         keyAlgoNid = OBJ_obj2nid(pAlgo->algorithm);
115         prfOid = _PkcsUtility::ConvertToOid(keyAlgoNid);
116
117         r = GetLastResult();
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.");
119
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.");
122
123         if (pPrivKeyInfo->attributes)
124         {
125                 pStackOfAttribute = pPrivKeyInfo->attributes;
126                 for (index = 0; index < sk_X509_ATTRIBUTE_num(pStackOfAttribute); index++)
127                 {
128                         pAttribute = sk_X509_ATTRIBUTE_value(pStackOfAttribute, index);
129
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.");
132
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.");
135
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.");
139
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.");
142
143                         attributeBuffer.Flip();
144
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.");
147
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.");
150                 }
151
152         }
153
154 CATCH:
155
156         PKCS8_PRIV_KEY_INFO_free(pPrivKeyInfo);
157         return r;
158
159 }
160
161 result
162 _Pkcs08PrivateKeyInfoImpl::Construct(const AlgorithmIdentifier& privAlgoId, const Tizen::Base::ByteBuffer& privKey)
163 {
164         result r = E_SUCCESS;
165
166         SysAssertf(__privateKey.GetRemaining() <= 0, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class. ");
167
168         SysTryReturnResult(NID_SEC_CRYPTO, privKey.GetRemaining() > 0, E_INVALID_ARG, "The specified input parameter is invalid.");
169
170         r = __privateKey.Construct(privKey);
171         SysTryReturnResult(NID_SEC_CRYPTO, !IsFailed(r), E_OUT_OF_MEMORY, "The memory is insufficient.");
172
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));
175
176         return r;
177 }
178
179 int
180 _Pkcs08PrivateKeyInfoImpl::GetVersion(void) const
181 {
182         ClearLastResult();
183         return __version;
184 }
185
186 const AlgorithmIdentifier&
187 _Pkcs08PrivateKeyInfoImpl::GetPrivateKeyAlgorithm(void) const
188 {
189         ClearLastResult();
190         return __algorithm;
191 }
192
193 const ByteBuffer&
194 _Pkcs08PrivateKeyInfoImpl::GetPrivateKey(void) const
195 {
196         ByteBuffer privateKey;
197
198         ClearLastResult();
199
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.");
202
203         return __privateKey;
204 }
205
206 const Tizen::Base::Collection::ArrayList&
207 _Pkcs08PrivateKeyInfoImpl::GetAttributes(void) const
208 {
209         return __attributes;
210 }
211
212 result
213 _Pkcs08PrivateKeyInfoImpl::AddAttribute(const Pkcs08Attribute& attribute)
214 {
215         return __attributes.Add(attribute);
216 }
217
218 result
219 _Pkcs08PrivateKeyInfoImpl::RemoveAttribute(const Pkcs08Attribute& attribute)
220 {
221         return __attributes.Remove(attribute);
222 }
223
224 ByteBuffer*
225 _Pkcs08PrivateKeyInfoImpl::GetEncodedDataN(void) const
226 {
227         result r = E_SUCCESS;
228         int value = 0;
229         int privLength = 0;
230         int prf_nid = 0;
231         int ret = 0;
232         int count = 0;
233         byte* pTemp = null;
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;
242
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.");
245
246         ClearLastResult();
247
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.");
250
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.");
253
254         pPrivateKeyInfo->pkey->value.octet_string = pPrivKey;
255         pPrivateKeyInfo->pkey->type = V_ASN1_OCTET_STRING;
256
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.");
259
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.");
262
263         pPrivKey->length = privLength;
264
265         pPrivateKeyData = const_cast< byte* >(__privateKey.GetPointer());
266
267         memcpy(pPrivKey->data, pPrivateKeyData, privLength);
268
269         ASN1_INTEGER_set(pPrivateKeyInfo->version, __version);
270
271         prf_nid = _PkcsUtility::ConvertToNid(__algorithm.GetAlgorithmObjectId());
272
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.");
275
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.");
278
279         count = __attributes.GetCount();
280
281         if (count != 0)
282         {
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.");
285
286                 pPrivateKeyInfo->attributes = pAttributes;
287         }
288
289         for (int i = 0; i < count; i++)
290         {
291                 Pkcs08Attribute* pObj = const_cast< Pkcs08Attribute* >(static_cast< const Pkcs08Attribute* >(__attributes.GetAt(i)));
292                 if (pObj != null)
293                 {
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.");
296
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.");
300
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.");
303                 }
304         }
305
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.");
308
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.");
311
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.");
314
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.");
317
318         pEncPrivateKeyInfo->Flip();
319
320 CATCH:
321
322         if (IsFailed(r))
323         {
324                 pEncPrivateKeyInfo.reset(null);
325         }
326         PKCS8_PRIV_KEY_INFO_free(pPrivateKeyInfo);
327         OPENSSL_free(pTemp);
328         return pEncPrivateKeyInfo.release();
329 }
330
331 _Pkcs08PrivateKeyInfoImpl*
332 _Pkcs08PrivateKeyInfoImpl::GetInstance(Pkcs08PrivateKeyInfo& pkcs08PrivateKeyInfo)
333 {
334         return pkcs08PrivateKeyInfo.__pPkcs08PrivateKeyInfoImpl;
335 }
336
337 const _Pkcs08PrivateKeyInfoImpl*
338 _Pkcs08PrivateKeyInfoImpl::GetInstance(const Pkcs08PrivateKeyInfo& pkcs08PrivateKeyInfo)
339 {
340         return pkcs08PrivateKeyInfo.__pPkcs08PrivateKeyInfoImpl;
341 }
342
343 } } }