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