2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file FSecCert_CertPrivateKeyInfo.cpp
19 * @brief This file contains implementation of X509 Certificate private key.
28 #include <unique_ptr.h>
32 #include <openssl/evp.h>
33 #include <openssl/x509.h>
34 #include <openssl/pkcs12.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"
45 using namespace Tizen::Base;
46 using namespace Tizen::Io;
47 using namespace Tizen::Security;
51 void operator ()(char* p)
61 namespace Tizen { namespace Security { namespace Cert
64 _CertPrivateKeyInfo::_CertPrivateKeyInfo(void)
71 _CertPrivateKeyInfo::_CertPrivateKeyInfo(char* pFileName)
75 SetPrivateKey(pFileName);
78 _CertPrivateKeyInfo::_CertPrivateKeyInfo(byte* pBuf, int bufSize)
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.");
84 memcpy(__pPrivateKey.get(), pBuf, bufSize);
87 _CertPrivateKeyInfo::~_CertPrivateKeyInfo()
91 // return DER encoded form
93 _CertPrivateKeyInfo::GetPrivateKeyN(int& keyLen, byte** ppPrivKey)
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.");
100 memset(*ppPrivKey, 0, keyLen + 1);
101 memcpy(*ppPrivKey, __pPrivateKey.get(), keyLen);
105 _CertPrivateKeyInfo::GetEncDecPrivateKeyN(int& keyLen, byte** ppPrivKey, int encDecBit)
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;
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.");
121 memset(uniqueKey, 0, aesBlockLen);
122 memcpy(uniqueKey, pUniqueKey.get(), aesBlockLen);
124 *ppPrivKey = new (std::nothrow) byte[__privateKeyLen + aesBlockLen + 1];
125 SysTryReturnResult(NID_SEC_CERT, *ppPrivKey != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
127 memset(*ppPrivKey, 0, __privateKeyLen + aesBlockLen + 1);
131 EVP_CIPHER_CTX_init(&ctx);
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.");
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.");
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.");
142 keyLen = keyLen + lenData;
147 EVP_CIPHER_CTX_init(&ctx);
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.");
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.");
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.");
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.");
162 *ppPrivKey = pPlainText.release();
163 keyLen = keyLen + outLength;
167 EVP_CIPHER_CTX_cleanup(&ctx);
172 _CertPrivateKeyInfo::GetPkcs8EncDecKeyN(int& keyLen, byte** ppPrivKey, int encDecBit)
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;
185 byte* pPrivKey = null;
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.");
190 memset(uniqueKey, 0, aesBlockLen);
191 memcpy(uniqueKey, pUniqueKey.get(), aesBlockLen);
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.");
196 memcpy((void*) pTempPrivateKey.get(), __pPrivateKey.get(), __privateKeyLen);
197 tempkeyLen = __privateKeyLen;
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");
205 p8inf = EVP_PKEY2PKCS8(pKey);
206 SysTryCatch(NID_SEC_CERT, p8inf != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
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");
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");
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");
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");
226 pKey = EVP_PKCS82PKEY(p8inf);
227 SysTryCatch(NID_SEC_CERT, pKey != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key conversion failed");
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");
234 PKCS8_PRIV_KEY_INFO_free(p8inf);
235 X509_SIG_free(pPkcs8Key);
237 *ppPrivKey = pPrivKey;
242 PKCS8_PRIV_KEY_INFO_free(p8inf);
243 X509_SIG_free(pPkcs8Key);
244 OPENSSL_free(pPrivKey);
250 _CertPrivateKeyInfo::SetPrivateKey(int keyLen, byte* pPrivKey)
252 __pPrivateKey.reset(null);
255 SysTryReturnResult(NID_SEC_CERT, pPrivKey != null, E_INVALID_ARG, "Invalid input argument.");
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.");
260 __privateKeyLen = keyLen;
261 memcpy(__pPrivateKey.get(), pPrivKey, keyLen);
262 __pPrivateKey[keyLen] = 0;
268 _CertPrivateKeyInfo::SetPrivateKey(char* pFileName)
270 result r = E_SUCCESS;
271 String fileName(pFileName);
278 __pPrivateKey.reset(null);
280 SysTryReturnResult(NID_SEC_CERT, pFileName != null, E_INVALID_ARG, "Invalid input argument.");
282 r = File::GetAttributes(fileName, attr);
283 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to get file attributes.");
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));
289 __privateKeyLen = size;
292 r = file.Construct(fileName, L"r");
293 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed in construct file.", GetErrorMessage(r));
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.");
298 readCnt = file.Read(__pPrivateKey.get(), size);
301 if ((readCnt == size && !IsFailed(r)))
303 byte* pPrivateKey = null;
305 GetPkcs8EncDecKeyN(priKeyLen, &pPrivateKey, 0);
306 SysTryReturnResult(NID_SEC_CERT, pPrivateKey, E_SYSTEM, "Failed to get decrypted private key from file.");
308 std::unique_ptr< byte[] > pPrivateKeyAuto(pPrivateKey);
310 memset(__pPrivateKey.get(), 0, __privateKeyLen);
311 memcpy(__pPrivateKey.get(), pPrivateKey, priKeyLen);
312 __privateKeyLen = priKeyLen;
318 } } } //Tizen::Security::Cert