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 FSecKeyPairGenerator.cpp
19 * @brief This is the implementation file for KeyPairGenerator class.
21 #include <unique_ptr.h>
22 #include <openssl/bn.h>
23 #include <openssl/evp.h>
24 #include <openssl/dh.h>
25 #include <openssl/rsa.h>
26 #include <openssl/x509.h>
27 #include <FBaseResult.h>
28 #include <FBaseErrors.h>
29 #include <FSecKeyPairGenerator.h>
30 #include <FSecDhKeyParameters.h>
31 #include <FSecKeaKeyParameters.h>
32 #include <FSecPublicKey.h>
33 #include <FSecPrivateKey.h>
34 #include <FBaseSysLog.h>
35 #include "FSec_GenerateParameters.h"
37 using namespace Tizen::Base;
38 using namespace Tizen::Security;
41 namespace Tizen { namespace Security
43 static const int _BITS_IN_BYTE = 8;
44 static const int _PUBLIC_KEY_LENGTH = 1024;
45 static const char* _MAX_SECRET_E_VAL = "65537";
47 KeyPairGenerator::KeyPairGenerator(void)
49 , __pKeyPairGeneratorImpl(null)
54 KeyPairGenerator::~KeyPairGenerator(void)
59 KeyPairGenerator::Construct(int modulusBitSize)
63 SysTryReturn(NID_SEC, modulusBitSize, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The modulusBitSize should be positive.");
65 __modulusBitSize = modulusBitSize;
72 KeyPairGenerator::Construct(int modulusBitSize, Tizen::Base::String algorithm)
74 SysTryReturn(NID_SEC, modulusBitSize, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The input modulus bit size should be positive.");
75 SysTryReturn(NID_SEC, algorithm != null, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The input algorithm value should be valid.");
76 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.");
78 __modulusBitSize = modulusBitSize;
79 __algorithm = algorithm;
86 KeyPairGenerator::GenerateKeyParametersN(int lInBits, int nInBits) const
90 unsigned int dheSize = 0;
91 long seedLenInBytes = 0;
92 byte temp[_PUBLIC_KEY_LENGTH];
95 IKeyParameters* pKeyParams = null;
100 seedLenInBytes = (nInBits / _BITS_IN_BYTE) + 1;
102 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.");
105 SysTryReturn(NID_SEC, pDh != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
107 r = _GenerateParameters::GenerateParametersX186(pDh, static_cast< long >(lInBits), static_cast< long >(nInBits),
109 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "Failed to do generate parameters operation for prime and generator values.");
111 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.");
113 memset(temp, 0, _PUBLIC_KEY_LENGTH);
115 size = BN_bn2bin(pDh->p, temp);
116 SysTryCatch(NID_SEC, size > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
118 r = dhp.Construct(size);
119 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
121 r = dhp.SetArray(temp, 0, size);
122 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
126 memset(temp, 0, _PUBLIC_KEY_LENGTH);
129 size = BN_bn2bin(pDh->g, temp);
130 SysTryCatch(NID_SEC, size > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
132 r = dhg.Construct(size);
133 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
135 r = dhg.SetArray(temp, 0, size);
136 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
140 dheSize = pDh->length;
142 if (__algorithm.CompareTo(L"DH") == 0)
144 DhKeyParameters* pDHParams = new (std::nothrow) DhKeyParameters();
145 SysTryCatch(NID_SEC, pDHParams != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
147 r = pDHParams->Construct(dhp, dhg, static_cast< int >(dheSize));
151 SysLogException(NID_SEC, r, "Failed to do construct");
154 pKeyParams = pDHParams;
156 else if (__algorithm.CompareTo(L"KEA") == 0)
158 KeaKeyParameters* pKeaParams = new (std::nothrow) KeaKeyParameters();
159 SysTryCatch(NID_SEC, pKeaParams != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
161 r = pKeaParams->Construct(dhp, dhg, static_cast< int >(dheSize));
165 SysLogException(NID_SEC, r, "Failed to do construct");
168 pKeyParams = pKeaParams;
183 KeyPairGenerator::GenerateKeyPairN(Tizen::Security::IKeyParameters* pKeyParams) const
185 result r = E_SUCCESS;
189 byte* pBuffer = null;
190 byte temp[_PUBLIC_KEY_LENGTH];
193 std::unique_ptr< KeyPair > pKeyPair;
198 EVP_PKEY* pEvpKey = null;
199 std::unique_ptr< ByteBuffer > pDHp(null);
200 std::unique_ptr< ByteBuffer > pDHg(null);
201 std::unique_ptr< IPublicKey > pPubKey(null);
202 std::unique_ptr< IPrivateKey > pPriKey(null);
206 SysAssertf(__algorithm != null && __modulusBitSize > 0, "Not yet constructed. Construct() should be called before use.");
208 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.");
210 if ((__algorithm.CompareTo(L"DH") == 0) || (__algorithm.CompareTo(L"KEA") == 0))
212 if (__algorithm.CompareTo(L"DH") == 0)
214 DhKeyParameters* pDHParams = dynamic_cast< DhKeyParameters* >(pKeyParams);
215 SysTryReturn(NID_SEC, pDHParams != null, null, E_INVALID_ARG, " [E_INVALID_ARG] dh parameters value is not valid.");
217 pDHp = std::unique_ptr< ByteBuffer >(pDHParams->GetParameterValueN(KEY_PARAMETER_DH_P));
218 SysTryReturn(NID_SEC, pDHp != null, null, GetLastResult(), " [%s] Dh prime value is not valid.", GetErrorMessage(GetLastResult()));
220 pDHg = std::unique_ptr< ByteBuffer >(pDHParams->GetParameterValueN(KEY_PARAMETER_DH_G));
221 SysTryCatch(NID_SEC, pDHg != null, r = GetLastResult(), GetLastResult(), " [%s] Dh generator value is not valid.", GetErrorMessage(GetLastResult()));
223 paramSize = pDHParams->GetParameterSize(KEY_PARAMETER_DH_PRIVATE_KEY_SIZE);
224 SysTryCatch(NID_SEC, paramSize > 0, r = GetLastResult(), GetLastResult(), " [%s] The dh private key size should be positive.", GetErrorMessage(GetLastResult()));
228 KeaKeyParameters* pKeaParams = dynamic_cast< KeaKeyParameters* >(pKeyParams);
229 SysTryReturn(NID_SEC, pKeaParams != null, null, E_INVALID_ARG, " [E_INVALID_ARG] kea parameters value is not valid.");
231 pDHp = std::unique_ptr< ByteBuffer >(pKeaParams->GetParameterValueN(KEY_PARAMETER_KEA_P));
232 SysTryReturn(NID_SEC, pDHp != null, null, GetLastResult(), " [%s] Kea prime value is not valid.", GetErrorMessage(GetLastResult()));
234 pDHg = std::unique_ptr< ByteBuffer >(pKeaParams->GetParameterValueN(KEY_PARAMETER_KEA_G));
235 SysTryCatch(NID_SEC, pDHg != null, r = GetLastResult(), GetLastResult(), " [%s] Kea generator value is not valid.", GetErrorMessage(GetLastResult()));
237 paramSize = pKeaParams->GetParameterSize(KEY_PARAMETER_KEA_PRIVATE_KEY_SIZE);
238 SysTryCatch(NID_SEC, paramSize > 0, r = GetLastResult(), GetLastResult(), " [%s] The kea private key size should be positive.", GetErrorMessage(GetLastResult()));
242 SysTryCatch(NID_SEC, pDh != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "The memory is insufficient.");
244 pDh->p = BN_bin2bn(pDHp->GetPointer(), pDHp->GetRemaining(), null);
245 SysTryCatch(NID_SEC, pDh->p != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
247 pDh->g = BN_bin2bn(pDHg->GetPointer(), pDHg->GetRemaining(), null);
248 SysTryCatch(NID_SEC, pDh->g != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
250 pDh->length = paramSize * _BITS_IN_BYTE;
252 ret = DH_generate_key(pDh);
253 SysTryCatch(NID_SEC, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
255 memset(temp, 0, _PUBLIC_KEY_LENGTH);
257 size = BN_bn2bin(pDh->priv_key, temp);
258 SysTryCatch(NID_SEC, size > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
260 r = privKey.Construct(size);
261 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
263 r = privKey.SetArray(temp, 0, size);
264 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
268 memset(temp, 0, _PUBLIC_KEY_LENGTH);
271 size = BN_bn2bin(pDh->pub_key, temp);
272 SysTryCatch(NID_SEC, size > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
274 r = pubKey.Construct(size);
275 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
277 r = pubKey.SetArray(temp, 0, size);
278 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
282 pPubKey = std::unique_ptr< IPublicKey >(new (std::nothrow) PublicKey());
283 SysTryCatch(NID_SEC, pPubKey != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
285 pPubKey->SetKey(pubKey);
287 pPriKey = std::unique_ptr< IPrivateKey >(new (std::nothrow) PrivateKey());
288 SysTryCatch(NID_SEC, pPriKey != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
290 pPriKey->SetKey(privKey);
293 else if (__algorithm.CompareTo(L"RSA") == 0)
296 SysTryReturn(NID_SEC, pCtx != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
301 SysTryCatch(NID_SEC, pRsa != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
303 pE = BN_CTX_get(pCtx);
304 SysTryCatch(NID_SEC, pE != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
306 ret = BN_dec2bn(&pE, _MAX_SECRET_E_VAL);
307 SysTryCatch(NID_SEC, ret != 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
309 ret = RSA_generate_key_ex(pRsa, __modulusBitSize, pE, null);
310 SysTryCatch(NID_SEC, ret != 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
312 pEvpKey = EVP_PKEY_new();
313 SysTryCatch(NID_SEC, pEvpKey != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
315 ret = EVP_PKEY_set1_RSA(pEvpKey, pRsa);
316 SysTryCatch(NID_SEC, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
318 ret = i2d_PrivateKey(pEvpKey, &pBuffer);
319 SysTryCatch(NID_SEC, ret != -1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
321 r = privKey.Construct(ret);
322 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
324 r = privKey.SetArray(pBuffer, 0, ret);
325 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
329 OPENSSL_free(pBuffer);
332 ret = i2d_PUBKEY(pEvpKey, &pBuffer);
333 SysTryCatch(NID_SEC, ret != -1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
335 r = pubKey.Construct(ret);
336 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
338 r = pubKey.SetArray(pBuffer, 0, ret);
339 SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The method cannot proceed due to a severe system error.");
343 pPubKey = std::unique_ptr< IPublicKey >(new (std::nothrow) PublicKey());
344 SysTryCatch(NID_SEC, pPubKey != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
346 pPubKey->SetKey(pubKey);
348 pPriKey = std::unique_ptr< IPrivateKey >(new (std::nothrow) PrivateKey());
349 SysTryCatch(NID_SEC, pPriKey != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
351 pPriKey->SetKey(privKey);
355 pKeyPair = std::unique_ptr< KeyPair >(new (std::nothrow) KeyPair());
356 SysTryCatch(NID_SEC, pKeyPair != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
358 r = pKeyPair->SetPrivateKey(privKey);
359 SysTryCatch(NID_SEC, !IsFailed(r), , r, "[%s] Failed to do set private key operation.", GetErrorMessage(r));
361 r = pKeyPair->SetPublicKey(pubKey);
362 SysTryCatch(NID_SEC, !IsFailed(r), , r, "[%s] Failed to do set public key operation.", GetErrorMessage(r));
377 EVP_PKEY_free(pEvpKey);
381 OPENSSL_free(pBuffer);
389 pKeyPair.reset(null);
392 return pKeyPair.release();
396 KeyPairGenerator::GenerateKeyPairN(void) const
398 KeyPair* pKeyPair = null;
402 SysAssertf(__algorithm != null, "Not yet constructed. Construct() should be called before use.");
404 SysTryReturn(NID_SEC, __algorithm.CompareTo(L"RSA") == 0, null, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] The requested algorithm is not supported.");
406 pKeyPair = GenerateKeyPairN(null);
407 SysTryReturn(NID_SEC, pKeyPair != null, null, GetLastResult(), "[%s] Failed to retrieve key pair for rsa", GetErrorMessage(GetLastResult()));
412 } } //Tizen::Security