Use dukgenerator instead of the _DeviceKeyGenerator for the PrivateKey encryption
[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 <dukgen.h>
37 #include <FIoFile.h>
38 #include <FIoFileAttributes.h>
39 #include <FBaseByteBuffer.h>
40 #include <FBaseString.h>
41 #include <FBaseResult.h>
42 #include <FBaseSysLog.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         char certMgrInfo[16] = {0x09, 0x25, 0x19, 0x87, 0xBF, 0x02, 0x14, 0x19, 0x88, 0xDD, 0x12, 0x30, 0x19, 0x86, 0xAD, 0xED};
100         int certMgrInfoLen = 16;
101         int aesBlockLen = 16;
102         int outLength = 0;
103         int lenData = 0;
104         int err = 0;
105         EVP_CIPHER_CTX ctx;
106
107         std::unique_ptr< ISecretKey > pSecKey(reinterpret_cast< ISecretKey* >(GetDeviceUniqueKey(certMgrInfo, certMgrInfoLen, aesBlockLen)));
108         SysTryReturnResult(NID_SEC_CERT, pSecKey != null, E_SYSTEM, "Failed to generate secret key.");
109
110         std::unique_ptr< ByteBuffer > pKeyBuf(pSecKey->GetEncodedN());
111         SysAssertf(pKeyBuf != null, "Failed to get encoded secret key.");
112
113         memset(uniqueKey, 0, aesBlockLen);
114         memcpy(uniqueKey, reinterpret_cast< const char* >(pKeyBuf->GetPointer()), aesBlockLen);
115
116         *ppPrivKey = new (std::nothrow) byte[__privateKeyLen + aesBlockLen + 1];
117         SysTryReturnResult(NID_SEC_CERT, *ppPrivKey != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
118
119         memset(*ppPrivKey, 0, __privateKeyLen + aesBlockLen + 1);
120
121         if (encDecBit)
122         {
123                 EVP_CIPHER_CTX_init(&ctx);
124
125                 err = EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), null, uniqueKey, ivData, encDecBit);
126                 SysTryCatch(NID_SEC_CERT, err == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to initialized cipher.");
127
128                 err = EVP_CipherUpdate(&ctx, *ppPrivKey, &keyLen, __pPrivateKey.get(), __privateKeyLen);
129                 SysTryCatch(NID_SEC_CERT, err == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to update cipher.");
130
131                 err = EVP_CipherFinal_ex(&ctx, *ppPrivKey + keyLen, &lenData);
132                 SysTryCatch(NID_SEC_CERT, err == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to do cipher final.");
133
134                 keyLen = keyLen + lenData;
135         }
136         else
137         {
138                 //Decryption
139                 EVP_CIPHER_CTX_init(&ctx);
140
141                 std::unique_ptr< byte[] > pPlainText(new (std::nothrow) byte[__privateKeyLen + 1]);
142                 SysTryReturnResult(NID_SEC_CERT, pPlainText != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
143
144                 memset(pPlainText.get(), 0, __privateKeyLen + 1);
145                 err = EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), null, uniqueKey, ivData, encDecBit);
146                 SysTryCatch(NID_SEC_CERT, err == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to initialized cipher.");
147
148                 err = EVP_CipherUpdate(&ctx, pPlainText.get(), reinterpret_cast< int* >(&keyLen), __pPrivateKey.get(), __privateKeyLen);
149                 SysTryCatch(NID_SEC_CERT, err == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to update cipher.");
150
151                 err = EVP_CipherFinal_ex(&ctx, pPlainText.get() + keyLen, &outLength);
152                 SysTryCatch(NID_SEC_CERT, err == 1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to do cipher final.");
153
154                 *ppPrivKey = pPlainText.release();
155                 keyLen = keyLen + outLength;
156         }
157
158 CATCH:
159         EVP_CIPHER_CTX_cleanup(&ctx);
160         return r;
161 }
162
163 result
164 _CertPrivateKeyInfo::GetPkcs8EncDecKeyN(int& keyLen, byte** ppPrivKey, int encDecBit)
165 {
166         result r = E_SUCCESS;
167         byte uniqueKey[16] = {0};
168         char certMgrInfo[16] = {0x09, 0x25, 0x19, 0x87, 0xBF, 0x02, 0x14, 0x19, 0x88, 0xDD, 0x12, 0x30, 0x19, 0x86, 0xAD, 0xED};
169         int certMgrInfoLen = 16;
170         int aesBlockLen = 16;
171         const EVP_CIPHER* pCipher = null;
172         X509_SIG* pPkcs8Key = null;
173         PKCS8_PRIV_KEY_INFO* p8inf = null;
174         EVP_PKEY* pKey = null;
175         const unsigned char* pTempPriKey = null;
176         long tempkeyLen = 0;
177         byte* pPrivKey = null;
178
179         std::unique_ptr< ISecretKey > pSecKey(reinterpret_cast< ISecretKey* >(GetDeviceUniqueKey(certMgrInfo, certMgrInfoLen, aesBlockLen)));
180         SysTryReturnResult(NID_SEC_CERT, pSecKey != null, E_SYSTEM, "Failed to generate secret key.");
181
182         std::unique_ptr< ByteBuffer > pKeyBuf(pSecKey->GetEncodedN());
183         SysAssertf(pKeyBuf != null, "Failed to get encoded secret key.");
184
185         memset(uniqueKey, 0, aesBlockLen);
186         memcpy(uniqueKey, reinterpret_cast< const char* >(pKeyBuf->GetPointer()), aesBlockLen);
187
188         std::unique_ptr< const unsigned char > pTempPrivateKey(new unsigned char[__privateKeyLen + 1]);
189         SysTryReturnResult(NID_SEC_CERT, pTempPrivateKey != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
190
191         memcpy((void*) pTempPrivateKey.get(), __pPrivateKey.get(), __privateKeyLen);
192         tempkeyLen = __privateKeyLen;
193
194         if (encDecBit)
195         {
196                 pTempPriKey = pTempPrivateKey.get();
197                 pKey = d2i_PrivateKey(EVP_PKEY_RSA, null, &pTempPriKey, tempkeyLen);
198                 SysTryCatch(NID_SEC_CERT, pKey != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
199
200                 p8inf = EVP_PKEY2PKCS8(pKey);
201                 SysTryCatch(NID_SEC_CERT, p8inf != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
202
203                 //Encryption : supported PKCS#5 v2.0 algo are PBE-SHA1-RC2-64 PBE-MD2-RC2-64 PBE-MD5-RC2-64 PBE-SHA1-DES
204                 pPkcs8Key = PKCS8_encrypt(NID_pbeWithSHA1AndRC2_CBC, pCipher, reinterpret_cast< const char* >(uniqueKey), aesBlockLen, null, 0, PKCS5_DEFAULT_ITER, p8inf);
205                 SysTryCatch(NID_SEC_CERT, pPkcs8Key != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key encryption failed");
206
207                 keyLen = i2d_X509_SIG(pPkcs8Key, &pPrivKey);
208                 SysTryCatch(NID_SEC_CERT, keyLen > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
209
210         }
211         else
212         {
213                 //Decryption
214                 pTempPriKey = pTempPrivateKey.get();
215                 pPkcs8Key = d2i_X509_SIG(null, &pTempPriKey, tempkeyLen);
216                 SysTryCatch(NID_SEC_CERT, pPkcs8Key != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
217
218                 p8inf = PKCS8_decrypt(pPkcs8Key, reinterpret_cast< const char* >(uniqueKey), aesBlockLen);
219                 SysTryCatch(NID_SEC_CERT, p8inf != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key decryption failed");
220
221                 pKey = EVP_PKCS82PKEY(p8inf);
222                 SysTryCatch(NID_SEC_CERT, pKey != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
223
224                 keyLen = i2d_PrivateKey(pKey, reinterpret_cast< unsigned char** >(&pPrivKey));
225                 SysTryCatch(NID_SEC_CERT, keyLen > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
226         }
227
228         EVP_PKEY_free(pKey);
229         PKCS8_PRIV_KEY_INFO_free(p8inf);
230         X509_SIG_free(pPkcs8Key);
231
232         *ppPrivKey = pPrivKey;
233
234         return r;
235 CATCH:
236         EVP_PKEY_free(pKey);
237         PKCS8_PRIV_KEY_INFO_free(p8inf);
238         X509_SIG_free(pPkcs8Key);
239         OPENSSL_free(pPrivKey);
240
241         return r;
242 }
243
244 result
245 _CertPrivateKeyInfo::SetPrivateKey(int keyLen, byte* pPrivKey)
246 {
247         __pPrivateKey.reset(null);
248         __privateKeyLen = 0;
249
250         SysTryReturnResult(NID_SEC_CERT, pPrivKey != null, E_INVALID_ARG, "Invalid input argument.");
251
252         __pPrivateKey = std::unique_ptr< byte[] >(new (std::nothrow) byte[keyLen + 1]);
253         SysTryReturnResult(NID_SEC_CERT, __pPrivateKey != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
254
255         __privateKeyLen = keyLen;
256         memcpy(__pPrivateKey.get(), pPrivKey, keyLen);
257         __pPrivateKey[keyLen] = 0;
258
259         return E_SUCCESS;
260 }
261
262 result
263 _CertPrivateKeyInfo::SetPrivateKey(char* pFileName)
264 {
265         result r = E_SUCCESS;
266         String fileName(pFileName);
267         FileAttributes attr;
268         File file;
269         long size = 0;
270         int readCnt = 0;
271         int priKeyLen = 0;
272
273         __pPrivateKey.reset(null);
274
275         SysTryReturnResult(NID_SEC_CERT, pFileName != null, E_INVALID_ARG, "Invalid input argument.");
276
277         r = File::GetAttributes(fileName, attr);
278         SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to get file attributes.");
279
280         size = attr.GetFileSize();
281         SysTryReturn(NID_SEC_CERT, size > 0, r, r, "[%s] Failed to get file attributes.", GetErrorMessage(r));
282         SysTryReturn(NID_SEC_CERT, size < _MAX_CERT_PRIVATE_KEY_SIZE, r, r, "[%s] File size exceeds maximum specified length.", GetErrorMessage(r));
283
284         __privateKeyLen = size;
285
286         // Open file
287         r = file.Construct(fileName, L"r");
288         SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed in construct file.", GetErrorMessage(r));
289
290         __pPrivateKey = std::unique_ptr< byte[] >(new (std::nothrow) byte[size]);
291         SysTryReturnResult(NID_SEC_CERT, __pPrivateKey != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
292
293         readCnt = file.Read(__pPrivateKey.get(), size);
294         r = GetLastResult();
295
296         if ((readCnt == size && !IsFailed(r)))
297         {
298                 byte* pPrivateKey = null;
299
300                 GetPkcs8EncDecKeyN(priKeyLen, &pPrivateKey, 0);
301                 SysTryReturnResult(NID_SEC_CERT, pPrivateKey, E_SYSTEM, "Failed to get decrypted private key from file.");
302
303                 std::unique_ptr< byte[] > pPrivateKeyAuto(pPrivateKey);
304
305                 memset(__pPrivateKey.get(), 0, __privateKeyLen);
306                 memcpy(__pPrivateKey.get(), pPrivateKey, priKeyLen);
307                 __privateKeyLen = priKeyLen;
308         }
309
310         return r;
311 }
312
313 } } } //Tizen::Security::Cert