Merge "Fix memory leaks in Locales" into tizen_2.1
[platform/framework/native/appfw.git] / src / security / FSecKeyPairGenerator.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                FSecKeyPairGenerator.cpp
20  * @brief               This is the implementation file for KeyPairGenerator class.
21  */
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"
37
38 using namespace Tizen::Base;
39 using namespace Tizen::Security;
40
41
42 namespace Tizen { namespace Security
43 {
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";
47
48 KeyPairGenerator::KeyPairGenerator(void)
49         : __modulusBitSize(0)
50         , __pKeyPairGeneratorImpl(null)
51 {
52         __algorithm = L"RSA";
53 }
54
55 KeyPairGenerator::~KeyPairGenerator(void)
56 {
57 }
58
59 result
60 KeyPairGenerator::Construct(int modulusBitSize)
61 {
62         result r = E_SUCCESS;
63
64         SysTryReturn(NID_SEC, modulusBitSize, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The modulusBitSize should be positive.");
65
66         __modulusBitSize = modulusBitSize;
67
68         return r;
69
70 }
71
72 result
73 KeyPairGenerator::Construct(int modulusBitSize, Tizen::Base::String algorithm)
74 {
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.");
78
79         __modulusBitSize = modulusBitSize;
80         __algorithm = algorithm;
81
82         return E_SUCCESS;
83
84 }
85
86 IKeyParameters*
87 KeyPairGenerator::GenerateKeyParametersN(int lInBits, int nInBits) const
88 {
89         result r = E_SUCCESS;
90         int size = 0;
91         unsigned int dheSize = 0;
92         long seedLenInBytes = 0;
93         byte temp[_PUBLIC_KEY_LENGTH];
94         ByteBuffer dhp;
95         ByteBuffer dhg;
96         IKeyParameters* pKeyParams = null;
97         DH* pDh = null;
98
99         ClearLastResult();
100
101         seedLenInBytes = (nInBits / _BITS_IN_BYTE) + 1;
102
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.");
104
105         pDh = DH_new();
106         SysTryReturn(NID_SEC, pDh != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
107
108         r = _GenerateParameters::GenerateParametersX186(pDh, static_cast< long >(lInBits), static_cast< long >(nInBits),
109                                                                                                         seedLenInBytes);
110         SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "Failed to do generate parameters operation for prime and generator values.");
111
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.");
113
114         memset(temp, 0, _PUBLIC_KEY_LENGTH);
115
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.");
118
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.");
121
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.");
124
125         dhp.Flip();
126
127         memset(temp, 0, _PUBLIC_KEY_LENGTH);
128         size = 0;
129
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.");
132
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.");
135
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.");
138
139         dhg.Flip();
140
141         dheSize = pDh->length;
142
143         if (__algorithm.CompareTo(L"DH") == 0)
144         {
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.");
147
148                 r = pDHParams->Construct(dhp, dhg, static_cast< int >(dheSize));
149                 if (IsFailed(r))
150                 {
151                         delete pDHParams;
152                         SysLogException(NID_SEC, r, "Failed to do construct");
153                         goto CATCH;
154                 }
155                 pKeyParams = pDHParams;
156         }
157         else if (__algorithm.CompareTo(L"KEA") == 0)
158         {
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.");
161
162                 r = pKeaParams->Construct(dhp, dhg, static_cast< int >(dheSize));
163                 if (IsFailed(r))
164                 {
165                         delete pKeaParams;
166                         SysLogException(NID_SEC, r, "Failed to do construct");
167                         goto CATCH;
168                 }
169                 pKeyParams = pKeaParams;
170         }
171
172 CATCH:
173
174         if (pDh != null)
175         {
176                 DH_free(pDh);
177         }
178
179         SetLastResult(r);
180         return pKeyParams;
181 }
182
183 KeyPair*
184 KeyPairGenerator::GenerateKeyPairN(Tizen::Security::IKeyParameters* pKeyParams) const
185 {
186         result r = E_SUCCESS;
187         int ret = 0;
188         int paramSize = 0;
189         int size = 0;
190         byte* pBuffer = null;
191         byte temp[_PUBLIC_KEY_LENGTH];
192         ByteBuffer privKey;
193         ByteBuffer pubKey;
194         std::unique_ptr< KeyPair > pKeyPair;
195         BN_CTX* pCtx = null;
196         DH* pDh = null;
197         RSA* pRsa = null;
198         BIGNUM* pE = null;
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);
204
205         ClearLastResult();
206
207         SysAssertf(__algorithm != null && __modulusBitSize > 0, "Not yet constructed. Construct() should be called before use.");
208
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.");
210
211         if ((__algorithm.CompareTo(L"DH") == 0) || (__algorithm.CompareTo(L"KEA") == 0))
212         {
213                 if (__algorithm.CompareTo(L"DH") == 0)
214                 {
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.");
217
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()));
220
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()));
223
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()));
226                 }
227                 else
228                 {
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.");
231
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()));
234
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()));
237
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()));
240                 }
241
242                 pDh = DH_new();
243                 SysTryCatch(NID_SEC, pDh != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "The memory is insufficient.");
244
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.");
247
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.");
250
251                 pDh->length = paramSize * _BITS_IN_BYTE;
252
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.");
255
256                 memset(temp, 0, _PUBLIC_KEY_LENGTH);
257
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.");
260
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.");
263
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.");
266
267                 privKey.Flip();
268
269                 memset(temp, 0, _PUBLIC_KEY_LENGTH);
270                 size = 0;
271
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.");
274
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.");
277
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.");
280
281                 pubKey.Flip();
282
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.");
285
286                 pPubKey->SetKey(pubKey);
287
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.");
290
291                 pPriKey->SetKey(privKey);
292
293         }
294         else if (__algorithm.CompareTo(L"RSA") == 0)
295         {
296                 pCtx = BN_CTX_new();
297                 SysTryReturn(NID_SEC, pCtx != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
298
299                 BN_CTX_start(pCtx);
300
301                 pRsa = RSA_new();
302                 SysTryCatch(NID_SEC, pRsa != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
303
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.");
306
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.");
309
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.");
312
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.");
315
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.");
318
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.");
321
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.");
324
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.");
327
328                 privKey.Flip();
329
330                 OPENSSL_free(pBuffer);
331                 pBuffer = null;
332
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.");
335
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.");
338
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.");
341
342                 pubKey.Flip();
343
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.");
346
347                 pPubKey->SetKey(pubKey);
348
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.");
351
352                 pPriKey->SetKey(privKey);
353
354         }
355
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.");
358
359         r = pKeyPair->SetPrivateKey(privKey);
360         SysTryCatch(NID_SEC, !IsFailed(r), , r, "[%s] Failed to do set private key operation.", GetErrorMessage(r));
361
362         r = pKeyPair->SetPublicKey(pubKey);
363         SysTryCatch(NID_SEC, !IsFailed(r), , r, "[%s] Failed to do set public key operation.", GetErrorMessage(r));
364
365 CATCH:
366
367         if (pDh != null)
368         {
369                 DH_free(pDh);
370         }
371         if (pCtx != null)
372         {
373                 BN_CTX_end(pCtx);
374                 BN_CTX_free(pCtx);
375         }
376         if (pEvpKey != null)
377         {
378                 EVP_PKEY_free(pEvpKey);
379         }
380         if (pBuffer != null)
381         {
382                 OPENSSL_free(pBuffer);
383         }
384         if (pRsa != null)
385         {
386                 RSA_free(pRsa);
387         }
388         if (IsFailed(r))
389         {
390                 pKeyPair.reset(null);
391         }
392
393         return pKeyPair.release();
394 }
395
396 KeyPair*
397 KeyPairGenerator::GenerateKeyPairN(void) const
398 {
399         KeyPair* pKeyPair = null;
400
401         ClearLastResult();
402
403         SysAssertf(__algorithm != null, "Not yet constructed. Construct() should be called before use.");
404
405         SysTryReturn(NID_SEC, __algorithm.CompareTo(L"RSA") == 0, null, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] The requested algorithm is not supported.");
406
407         pKeyPair = GenerateKeyPairN(null);
408         SysTryReturn(NID_SEC, pKeyPair != null, null, GetLastResult(), "[%s] Failed to retrieve key pair for rsa", GetErrorMessage(GetLastResult()));
409
410         return pKeyPair;
411 }
412
413 } } //Tizen::Security