2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @file FSecKeyPairGenerator.cpp
20 * @brief This is the implementation file for KeyPairGenerator class.
22 #include <unique_ptr.h>
23 #include <openssl/bn.h>
24 #include <openssl/evp.h>
25 #include <openssl/dh.h>
26 #include <openssl/rsa.h>
27 #include <openssl/x509.h>
28 #include <FBaseResult.h>
29 #include <FBaseErrors.h>
30 #include <FSecKeyPairGenerator.h>
31 #include <FSecDhKeyParameters.h>
32 #include <FSecKeaKeyParameters.h>
33 #include <FSecPublicKey.h>
34 #include <FSecPrivateKey.h>
35 #include <FBaseSysLog.h>
36 #include "FSec_GenerateParameters.h"
38 using namespace Tizen::Base;
39 using namespace Tizen::Security;
42 namespace Tizen { namespace Security
44 static const int _BITS_IN_BYTE = 8;
45 static const int _PUBLIC_KEY_LENGTH = 1024;
46 static const char* _MAX_SECRET_E_VAL = "65537";
48 KeyPairGenerator::KeyPairGenerator(void)
50 , __pKeyPairGeneratorImpl(null)
55 KeyPairGenerator::~KeyPairGenerator(void)
60 KeyPairGenerator::Construct(int modulusBitSize)
64 SysTryReturn(NID_SEC, modulusBitSize, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The modulusBitSize should be positive.");
66 __modulusBitSize = modulusBitSize;
73 KeyPairGenerator::Construct(int modulusBitSize, Tizen::Base::String algorithm)
75 SysTryReturn(NID_SEC, modulusBitSize, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The input modulus bit size should be positive.");
76 SysTryReturn(NID_SEC, algorithm != null, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The input algorithm value should be valid.");
77 SysTryReturn(NID_SEC, (algorithm.CompareTo(L"DH") == 0) || (algorithm.CompareTo(L"KEA") == 0) || (algorithm.CompareTo(L"RSA") == 0), E_UNSUPPORTED_ALGORITHM, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] The requested algorithm is not supported.");
79 __modulusBitSize = modulusBitSize;
80 __algorithm = algorithm;
87 KeyPairGenerator::GenerateKeyParametersN(int lInBits, int nInBits) const
91 unsigned int dheSize = 0;
92 long seedLenInBytes = 0;
93 byte temp[_PUBLIC_KEY_LENGTH];
96 IKeyParameters* pKeyParams = null;
101 seedLenInBytes = (nInBits / _BITS_IN_BYTE) + 1;
103 SysTryReturn(NID_SEC, (__algorithm.CompareTo(L"DH") == 0) || (__algorithm.CompareTo(L"KEA") == 0), null, E_INVALID_ARG, "[E_INVALID_ARG] The requested algorithm is not supported.");
106 SysTryReturn(NID_SEC, pDh != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
108 r = _GenerateParameters::GenerateParametersX186(pDh, static_cast< long >(lInBits), static_cast< long >(nInBits),
110 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "Failed to do generate parameters operation for prime and generator values.");
112 SysTryCatch(NID_SEC, pDh->p != null && pDh->g != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Generated parameters prime and generator values should be valid.");
114 memset(temp, 0, _PUBLIC_KEY_LENGTH);
116 size = BN_bn2bin(pDh->p, temp);
117 SysTryCatch(NID_SEC, size > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
119 r = dhp.Construct(size);
120 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
122 r = dhp.SetArray(temp, 0, size);
123 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
127 memset(temp, 0, _PUBLIC_KEY_LENGTH);
130 size = BN_bn2bin(pDh->g, temp);
131 SysTryCatch(NID_SEC, size > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
133 r = dhg.Construct(size);
134 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
136 r = dhg.SetArray(temp, 0, size);
137 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
141 dheSize = pDh->length;
143 if (__algorithm.CompareTo(L"DH") == 0)
145 DhKeyParameters* pDHParams = new (std::nothrow) DhKeyParameters();
146 SysTryCatch(NID_SEC, pDHParams != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
148 r = pDHParams->Construct(dhp, dhg, static_cast< int >(dheSize));
152 SysLogException(NID_SEC, r, "Failed to do construct");
155 pKeyParams = pDHParams;
157 else if (__algorithm.CompareTo(L"KEA") == 0)
159 KeaKeyParameters* pKeaParams = new (std::nothrow) KeaKeyParameters();
160 SysTryCatch(NID_SEC, pKeaParams != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
162 r = pKeaParams->Construct(dhp, dhg, static_cast< int >(dheSize));
166 SysLogException(NID_SEC, r, "Failed to do construct");
169 pKeyParams = pKeaParams;
184 KeyPairGenerator::GenerateKeyPairN(Tizen::Security::IKeyParameters* pKeyParams) const
186 result r = E_SUCCESS;
190 byte* pBuffer = null;
191 byte temp[_PUBLIC_KEY_LENGTH];
194 std::unique_ptr< KeyPair > pKeyPair;
199 EVP_PKEY* pEvpKey = null;
200 std::unique_ptr< ByteBuffer > pDHp(null);
201 std::unique_ptr< ByteBuffer > pDHg(null);
202 std::unique_ptr< IPublicKey > pPubKey(null);
203 std::unique_ptr< IPrivateKey > pPriKey(null);
207 SysAssertf(__algorithm != null && __modulusBitSize > 0, "Not yet constructed. Construct() should be called before use.");
209 SysTryReturn(NID_SEC, (__algorithm.CompareTo(L"DH") == 0) || (__algorithm.CompareTo(L"KEA") == 0) || (__algorithm.CompareTo(L"RSA") == 0), null, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] The requested algorithm is not supported.");
211 if ((__algorithm.CompareTo(L"DH") == 0) || (__algorithm.CompareTo(L"KEA") == 0))
213 if (__algorithm.CompareTo(L"DH") == 0)
215 DhKeyParameters* pDHParams = dynamic_cast< DhKeyParameters* >(pKeyParams);
216 SysTryReturn(NID_SEC, pDHParams != null, null, E_INVALID_ARG, " [E_INVALID_ARG] dh parameters value is not valid.");
218 pDHp = std::unique_ptr< ByteBuffer >(pDHParams->GetParameterValueN(KEY_PARAMETER_DH_P));
219 SysTryReturn(NID_SEC, pDHp != null, null, GetLastResult(), " [%s] Dh prime value is not valid.", GetErrorMessage(GetLastResult()));
221 pDHg = std::unique_ptr< ByteBuffer >(pDHParams->GetParameterValueN(KEY_PARAMETER_DH_G));
222 SysTryCatch(NID_SEC, pDHg != null, r = GetLastResult(), GetLastResult(), " [%s] Dh generator value is not valid.", GetErrorMessage(GetLastResult()));
224 paramSize = pDHParams->GetParameterSize(KEY_PARAMETER_DH_PRIVATE_KEY_SIZE);
225 SysTryCatch(NID_SEC, paramSize > 0, r = GetLastResult(), GetLastResult(), " [%s] The dh private key size should be positive.", GetErrorMessage(GetLastResult()));
229 KeaKeyParameters* pKeaParams = dynamic_cast< KeaKeyParameters* >(pKeyParams);
230 SysTryReturn(NID_SEC, pKeaParams != null, null, E_INVALID_ARG, " [E_INVALID_ARG] kea parameters value is not valid.");
232 pDHp = std::unique_ptr< ByteBuffer >(pKeaParams->GetParameterValueN(KEY_PARAMETER_KEA_P));
233 SysTryReturn(NID_SEC, pDHp != null, null, GetLastResult(), " [%s] Kea prime value is not valid.", GetErrorMessage(GetLastResult()));
235 pDHg = std::unique_ptr< ByteBuffer >(pKeaParams->GetParameterValueN(KEY_PARAMETER_KEA_G));
236 SysTryCatch(NID_SEC, pDHg != null, r = GetLastResult(), GetLastResult(), " [%s] Kea generator value is not valid.", GetErrorMessage(GetLastResult()));
238 paramSize = pKeaParams->GetParameterSize(KEY_PARAMETER_KEA_PRIVATE_KEY_SIZE);
239 SysTryCatch(NID_SEC, paramSize > 0, r = GetLastResult(), GetLastResult(), " [%s] The kea private key size should be positive.", GetErrorMessage(GetLastResult()));
243 SysTryCatch(NID_SEC, pDh != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "The memory is insufficient.");
245 pDh->p = BN_bin2bn(pDHp->GetPointer(), pDHp->GetRemaining(), null);
246 SysTryCatch(NID_SEC, pDh->p != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
248 pDh->g = BN_bin2bn(pDHg->GetPointer(), pDHg->GetRemaining(), null);
249 SysTryCatch(NID_SEC, pDh->g != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
251 pDh->length = paramSize * _BITS_IN_BYTE;
253 ret = DH_generate_key(pDh);
254 SysTryCatch(NID_SEC, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
256 memset(temp, 0, _PUBLIC_KEY_LENGTH);
258 size = BN_bn2bin(pDh->priv_key, temp);
259 SysTryCatch(NID_SEC, size > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
261 r = privKey.Construct(size);
262 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
264 r = privKey.SetArray(temp, 0, size);
265 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
269 memset(temp, 0, _PUBLIC_KEY_LENGTH);
272 size = BN_bn2bin(pDh->pub_key, temp);
273 SysTryCatch(NID_SEC, size > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
275 r = pubKey.Construct(size);
276 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
278 r = pubKey.SetArray(temp, 0, size);
279 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
283 pPubKey = std::unique_ptr< IPublicKey >(new (std::nothrow) PublicKey());
284 SysTryCatch(NID_SEC, pPubKey != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
286 pPubKey->SetKey(pubKey);
288 pPriKey = std::unique_ptr< IPrivateKey >(new (std::nothrow) PrivateKey());
289 SysTryCatch(NID_SEC, pPriKey != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
291 pPriKey->SetKey(privKey);
294 else if (__algorithm.CompareTo(L"RSA") == 0)
297 SysTryReturn(NID_SEC, pCtx != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
302 SysTryCatch(NID_SEC, pRsa != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
304 pE = BN_CTX_get(pCtx);
305 SysTryCatch(NID_SEC, pE != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
307 ret = BN_dec2bn(&pE, _MAX_SECRET_E_VAL);
308 SysTryCatch(NID_SEC, ret != 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
310 ret = RSA_generate_key_ex(pRsa, __modulusBitSize, pE, null);
311 SysTryCatch(NID_SEC, ret != 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
313 pEvpKey = EVP_PKEY_new();
314 SysTryCatch(NID_SEC, pEvpKey != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
316 ret = EVP_PKEY_set1_RSA(pEvpKey, pRsa);
317 SysTryCatch(NID_SEC, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
319 ret = i2d_PrivateKey(pEvpKey, &pBuffer);
320 SysTryCatch(NID_SEC, ret != -1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
322 r = privKey.Construct(ret);
323 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
325 r = privKey.SetArray(pBuffer, 0, ret);
326 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
330 OPENSSL_free(pBuffer);
333 ret = i2d_PUBKEY(pEvpKey, &pBuffer);
334 SysTryCatch(NID_SEC, ret != -1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
336 r = pubKey.Construct(ret);
337 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
339 r = pubKey.SetArray(pBuffer, 0, ret);
340 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
344 pPubKey = std::unique_ptr< IPublicKey >(new (std::nothrow) PublicKey());
345 SysTryCatch(NID_SEC, pPubKey != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
347 pPubKey->SetKey(pubKey);
349 pPriKey = std::unique_ptr< IPrivateKey >(new (std::nothrow) PrivateKey());
350 SysTryCatch(NID_SEC, pPriKey != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
352 pPriKey->SetKey(privKey);
356 pKeyPair = std::unique_ptr< KeyPair >(new (std::nothrow) KeyPair());
357 SysTryCatch(NID_SEC, pKeyPair != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
359 r = pKeyPair->SetPrivateKey(privKey);
360 SysTryCatch(NID_SEC, !IsFailed(r), , r, "[%s] Failed to do set private key operation.", GetErrorMessage(r));
362 r = pKeyPair->SetPublicKey(pubKey);
363 SysTryCatch(NID_SEC, !IsFailed(r), , r, "[%s] Failed to do set public key operation.", GetErrorMessage(r));
378 EVP_PKEY_free(pEvpKey);
382 OPENSSL_free(pBuffer);
390 pKeyPair.reset(null);
393 return pKeyPair.release();
397 KeyPairGenerator::GenerateKeyPairN(void) const
399 KeyPair* pKeyPair = null;
403 SysAssertf(__algorithm != null, "Not yet constructed. Construct() should be called before use.");
405 SysTryReturn(NID_SEC, __algorithm.CompareTo(L"RSA") == 0, null, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] The requested algorithm is not supported.");
407 pKeyPair = GenerateKeyPairN(null);
408 SysTryReturn(NID_SEC, pKeyPair != null, null, GetLastResult(), "[%s] Failed to retrieve key pair for rsa", GetErrorMessage(GetLastResult()));
413 } } //Tizen::Security