Fixed Klocworks issues
[platform/framework/native/appfw.git] / src / security / cert / FSecCert_CertPrivateKeyInfo.cpp
1 //
2 // Copyright (c) 2012 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                FSecCert_CertPrivateKeyInfo.cpp
19  * @brief               This file contains implementation of X509 Certificate private key.
20 */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <error.h>
26 #include <memory.h>
27 #include <new>
28 #include <unique_ptr.h>
29 #include <sys/stat.h>
30 #include <assert.h>
31 #include <dirent.h>
32 #include <openssl/evp.h>
33 #include <openssl/x509.h>
34 #include <openssl/pkcs12.h>
35 #include <dukgen.h>
36 #include <FIoFile.h>
37 #include <FIoFileAttributes.h>
38 #include <FBaseByteBuffer.h>
39 #include <FBaseString.h>
40 #include <FBaseResult.h>
41 #include <FBaseSysLog.h>
42 #include <FSecISecretKey.h>
43 #include "FSecCert_CertPrivateKeyInfo.h"
44
45 using namespace Tizen::Base;
46 using namespace Tizen::Io;
47 using namespace Tizen::Security;
48
49 struct FreeCharPtr
50 {
51         void operator ()(char* p)
52         {   
53                 if (p != null)
54                 {   
55                         free(p);
56                 }   
57         }   
58 };
59
60
61 namespace Tizen { namespace Security { namespace Cert
62 {
63
64 _CertPrivateKeyInfo::_CertPrivateKeyInfo(void)
65         : __privateKeyLen(0)
66         , __pPrivateKey(null)
67 {
68 }
69
70
71 _CertPrivateKeyInfo::_CertPrivateKeyInfo(char* pFileName)
72         : __privateKeyLen(0)
73         , __pPrivateKey(null)
74 {
75         SetPrivateKey(pFileName);
76 }
77
78 _CertPrivateKeyInfo::_CertPrivateKeyInfo(byte* pBuf, int bufSize)
79 {
80         __privateKeyLen = bufSize;
81         __pPrivateKey = std::unique_ptr< byte[] >(new (std::nothrow) byte[bufSize]);
82         SysTryReturnVoidResult(NID_SEC_CERT, __pPrivateKey != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
83
84         memcpy(__pPrivateKey.get(), pBuf, bufSize);
85 }
86
87 _CertPrivateKeyInfo::~_CertPrivateKeyInfo()
88 {
89 }
90
91 // return DER encoded form
92 void
93 _CertPrivateKeyInfo::GetPrivateKeyN(int& keyLen, byte** ppPrivKey)
94 {
95         SysTryReturnVoidResult(NID_SEC_CERT, __pPrivateKey != null, E_SYSTEM, "Private key is not set.");
96         keyLen = __privateKeyLen;
97         *ppPrivKey = new (std::nothrow) byte[keyLen + 1];
98         SysTryReturnVoidResult(NID_SEC_CERT, *ppPrivKey != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
99
100         memset(*ppPrivKey, 0, keyLen + 1);
101         memcpy(*ppPrivKey, __pPrivateKey.get(), keyLen);
102 }
103
104 result
105 _CertPrivateKeyInfo::GetEncDecPrivateKeyN(int& keyLen, byte** ppPrivKey, int encDecBit)
106 {
107         result r = E_SUCCESS;
108         byte uniqueKey[16] = {0};
109         byte ivData[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
110         char certMgrInfo[16] = {0x09, 0x25, 0x19, 0x87, 0xBF, 0x02, 0x14, 0x19, 0x88, 0xDD, 0x12, 0x30, 0x19, 0x86, 0xAD, 0xED};
111         int certMgrInfoLen = 16;
112         int aesBlockLen = 16;
113         int outLength = 0;
114         int lenData = 0;
115         int err = 0;
116         EVP_CIPHER_CTX ctx;
117
118         std::unique_ptr< char, FreeCharPtr > pUniqueKey(GetDeviceUniqueKey(certMgrInfo, certMgrInfoLen, aesBlockLen));
119         SysTryReturnResult(NID_SEC_CERT, pUniqueKey != null, E_SYSTEM, "Failed to generate unique key.");
120         
121         memset(uniqueKey, 0, aesBlockLen);
122         memcpy(uniqueKey, pUniqueKey.get(), aesBlockLen);
123
124         *ppPrivKey = new (std::nothrow) byte[__privateKeyLen + aesBlockLen + 1];
125         SysTryReturnResult(NID_SEC_CERT, *ppPrivKey != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
126
127         memset(*ppPrivKey, 0, __privateKeyLen + aesBlockLen + 1);
128
129         if (encDecBit)
130         {
131                 EVP_CIPHER_CTX_init(&ctx);
132
133                 err = EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), null, uniqueKey, ivData, encDecBit);
134                 SysTryCatch(NID_SEC_CERT, err == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to initialized cipher.");
135
136                 err = EVP_CipherUpdate(&ctx, *ppPrivKey, &keyLen, __pPrivateKey.get(), __privateKeyLen);
137                 SysTryCatch(NID_SEC_CERT, err == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to update cipher.");
138
139                 err = EVP_CipherFinal_ex(&ctx, *ppPrivKey + keyLen, &lenData);
140                 SysTryCatch(NID_SEC_CERT, err == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to do cipher final.");
141
142                 keyLen = keyLen + lenData;
143         }
144         else
145         {
146                 //Decryption
147                 EVP_CIPHER_CTX_init(&ctx);
148
149                 std::unique_ptr< byte[] > pPlainText(new (std::nothrow) byte[__privateKeyLen + 1]);
150                 SysTryReturnResult(NID_SEC_CERT, pPlainText != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
151
152                 memset(pPlainText.get(), 0, __privateKeyLen + 1);
153                 err = EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), null, uniqueKey, ivData, encDecBit);
154                 SysTryCatch(NID_SEC_CERT, err == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to initialized cipher.");
155
156                 err = EVP_CipherUpdate(&ctx, pPlainText.get(), reinterpret_cast< int* >(&keyLen), __pPrivateKey.get(), __privateKeyLen);
157                 SysTryCatch(NID_SEC_CERT, err == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to update cipher.");
158
159                 err = EVP_CipherFinal_ex(&ctx, pPlainText.get() + keyLen, &outLength);
160                 SysTryCatch(NID_SEC_CERT, err == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to do cipher final.");
161
162                 *ppPrivKey = pPlainText.release();
163                 keyLen = keyLen + outLength;
164         }
165
166 CATCH:
167         EVP_CIPHER_CTX_cleanup(&ctx);
168         return r;
169 }
170
171 result
172 _CertPrivateKeyInfo::GetPkcs8EncDecKeyN(int& keyLen, byte** ppPrivKey, int encDecBit)
173 {
174         result r = E_SUCCESS;
175         byte uniqueKey[16] = {0};
176         char certMgrInfo[16] = {0x09, 0x25, 0x19, 0x87, 0xBF, 0x02, 0x14, 0x19, 0x88, 0xDD, 0x12, 0x30, 0x19, 0x86, 0xAD, 0xED};
177         int certMgrInfoLen = 16;
178         int aesBlockLen = 16;
179         const EVP_CIPHER* pCipher = null;
180         X509_SIG* pPkcs8Key = null;
181         PKCS8_PRIV_KEY_INFO* p8inf = null;
182         EVP_PKEY* pKey = null;
183         const unsigned char* pTempPriKey = null;
184         long tempkeyLen = 0;
185         byte* pPrivKey = null;
186
187         std::unique_ptr< char, FreeCharPtr > pUniqueKey(GetDeviceUniqueKey(certMgrInfo, certMgrInfoLen, aesBlockLen));
188         SysTryReturnResult(NID_SEC_CERT, pUniqueKey != null, E_SYSTEM, "Failed to generate unique key.");
189
190         memset(uniqueKey, 0, aesBlockLen);
191         memcpy(uniqueKey, pUniqueKey.get(), aesBlockLen);
192
193         std::unique_ptr< const unsigned char > pTempPrivateKey(new unsigned char[__privateKeyLen + 1]);
194         SysTryReturnResult(NID_SEC_CERT, pTempPrivateKey != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
195
196         memcpy((void*) pTempPrivateKey.get(), __pPrivateKey.get(), __privateKeyLen);
197         tempkeyLen = __privateKeyLen;
198
199         if (encDecBit)
200         {
201                 pTempPriKey = pTempPrivateKey.get();
202                 pKey = d2i_PrivateKey(EVP_PKEY_RSA, null, &pTempPriKey, tempkeyLen);
203                 SysTryCatch(NID_SEC_CERT, pKey != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
204
205                 p8inf = EVP_PKEY2PKCS8(pKey);
206                 SysTryCatch(NID_SEC_CERT, p8inf != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
207
208                 //Encryption : supported PKCS#5 v2.0 algo are PBE-SHA1-RC2-64 PBE-MD2-RC2-64 PBE-MD5-RC2-64 PBE-SHA1-DES
209                 pPkcs8Key = PKCS8_encrypt(NID_pbeWithSHA1AndRC2_CBC, pCipher, reinterpret_cast< const char* >(uniqueKey), aesBlockLen, null, 0, PKCS5_DEFAULT_ITER, p8inf);
210                 SysTryCatch(NID_SEC_CERT, pPkcs8Key != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key encryption failed");
211
212                 keyLen = i2d_X509_SIG(pPkcs8Key, &pPrivKey);
213                 SysTryCatch(NID_SEC_CERT, keyLen > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
214
215         }
216         else
217         {
218                 //Decryption
219                 pTempPriKey = pTempPrivateKey.get();
220                 pPkcs8Key = d2i_X509_SIG(null, &pTempPriKey, tempkeyLen);
221                 SysTryCatch(NID_SEC_CERT, pPkcs8Key != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
222
223                 p8inf = PKCS8_decrypt(pPkcs8Key, reinterpret_cast< const char* >(uniqueKey), aesBlockLen);
224                 SysTryCatch(NID_SEC_CERT, p8inf != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key decryption failed");
225
226                 pKey = EVP_PKCS82PKEY(p8inf);
227                 SysTryCatch(NID_SEC_CERT, pKey != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
228
229                 keyLen = i2d_PrivateKey(pKey, reinterpret_cast< unsigned char** >(&pPrivKey));
230                 SysTryCatch(NID_SEC_CERT, keyLen > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
231         }
232
233         EVP_PKEY_free(pKey);
234         PKCS8_PRIV_KEY_INFO_free(p8inf);
235         X509_SIG_free(pPkcs8Key);
236
237         *ppPrivKey = pPrivKey;
238
239         return r;
240 CATCH:
241         EVP_PKEY_free(pKey);
242         PKCS8_PRIV_KEY_INFO_free(p8inf);
243         X509_SIG_free(pPkcs8Key);
244         OPENSSL_free(pPrivKey);
245
246         return r;
247 }
248
249 result
250 _CertPrivateKeyInfo::SetPrivateKey(int keyLen, byte* pPrivKey)
251 {
252         __pPrivateKey.reset(null);
253         __privateKeyLen = 0;
254
255         SysTryReturnResult(NID_SEC_CERT, pPrivKey != null, E_INVALID_ARG, "Invalid input argument.");
256
257         __pPrivateKey = std::unique_ptr< byte[] >(new (std::nothrow) byte[keyLen + 1]);
258         SysTryReturnResult(NID_SEC_CERT, __pPrivateKey != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
259
260         __privateKeyLen = keyLen;
261         memcpy(__pPrivateKey.get(), pPrivKey, keyLen);
262         __pPrivateKey[keyLen] = 0;
263
264         return E_SUCCESS;
265 }
266
267 result
268 _CertPrivateKeyInfo::SetPrivateKey(char* pFileName)
269 {
270         result r = E_SUCCESS;
271         String fileName(pFileName);
272         FileAttributes attr;
273         File file;
274         long size = 0;
275         int readCnt = 0;
276         int priKeyLen = 0;
277
278         __pPrivateKey.reset(null);
279
280         SysTryReturnResult(NID_SEC_CERT, pFileName != null, E_INVALID_ARG, "Invalid input argument.");
281
282         r = File::GetAttributes(fileName, attr);
283         SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to get file attributes.");
284
285         size = attr.GetFileSize();
286         SysTryReturn(NID_SEC_CERT, size > 0, r, r, "[%s] Failed to get file attributes.", GetErrorMessage(r));
287         SysTryReturn(NID_SEC_CERT, size < _MAX_CERT_PRIVATE_KEY_SIZE, r, r, "[%s] File size exceeds maximum specified length.", GetErrorMessage(r));
288
289         __privateKeyLen = size;
290
291         // Open file
292         r = file.Construct(fileName, L"r");
293         SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed in construct file.", GetErrorMessage(r));
294
295         __pPrivateKey = std::unique_ptr< byte[] >(new (std::nothrow) byte[size]);
296         SysTryReturnResult(NID_SEC_CERT, __pPrivateKey != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
297
298         readCnt = file.Read(__pPrivateKey.get(), size);
299         r = GetLastResult();
300
301         if ((readCnt == size && !IsFailed(r)))
302         {
303                 byte* pPrivateKey = null;
304
305                 GetPkcs8EncDecKeyN(priKeyLen, &pPrivateKey, 0);
306                 SysTryReturnResult(NID_SEC_CERT, pPrivateKey, E_SYSTEM, "Failed to get decrypted private key from file.");
307
308                 std::unique_ptr< byte[] > pPrivateKeyAuto(pPrivateKey);
309
310                 memset(__pPrivateKey.get(), 0, __privateKeyLen);
311                 memcpy(__pPrivateKey.get(), pPrivateKey, priKeyLen);
312                 __privateKeyLen = priKeyLen;
313         }
314
315         return r;
316 }
317
318 } } } //Tizen::Security::Cert