Merge "Fixed Klocwork issues" into tizen_2.2
[platform/framework/native/appfw.git] / src / security / FSecKeyPairGenerator.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15 //
16
17 /**
18  * @file                FSecKeyPairGenerator.cpp
19  * @brief               This is the implementation file for KeyPairGenerator class.
20  */
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"
36
37 using namespace Tizen::Base;
38 using namespace Tizen::Security;
39
40
41 namespace Tizen { namespace Security
42 {
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";
46
47 KeyPairGenerator::KeyPairGenerator(void)
48         : __modulusBitSize(0)
49         , __pKeyPairGeneratorImpl(null)
50 {
51         __algorithm = L"RSA";
52 }
53
54 KeyPairGenerator::~KeyPairGenerator(void)
55 {
56 }
57
58 result
59 KeyPairGenerator::Construct(int modulusBitSize)
60 {
61         result r = E_SUCCESS;
62
63         SysTryReturn(NID_SEC, modulusBitSize, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The modulusBitSize should be positive.");
64
65         __modulusBitSize = modulusBitSize;
66
67         return r;
68
69 }
70
71 result
72 KeyPairGenerator::Construct(int modulusBitSize, Tizen::Base::String algorithm)
73 {
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.");
77
78         __modulusBitSize = modulusBitSize;
79         __algorithm = algorithm;
80
81         return E_SUCCESS;
82
83 }
84
85 IKeyParameters*
86 KeyPairGenerator::GenerateKeyParametersN(int lInBits, int nInBits) const
87 {
88         result r = E_SUCCESS;
89         int size = 0;
90         unsigned int dheSize = 0;
91         long seedLenInBytes = 0;
92         byte temp[_PUBLIC_KEY_LENGTH];
93         ByteBuffer dhp;
94         ByteBuffer dhg;
95         IKeyParameters* pKeyParams = null;
96         DH* pDh = null;
97
98         ClearLastResult();
99
100         seedLenInBytes = (nInBits / _BITS_IN_BYTE) + 1;
101
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.");
103
104         pDh = DH_new();
105         SysTryReturn(NID_SEC, pDh != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
106
107         r = _GenerateParameters::GenerateParametersX186(pDh, static_cast< long >(lInBits), static_cast< long >(nInBits),
108                                                                                                         seedLenInBytes);
109         SysTryCatch(NID_SEC, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "Failed to do generate parameters operation for prime and generator values.");
110
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.");
112
113         memset(temp, 0, _PUBLIC_KEY_LENGTH);
114
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.");
117
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.");
120
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.");
123
124         dhp.Flip();
125
126         memset(temp, 0, _PUBLIC_KEY_LENGTH);
127         size = 0;
128
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.");
131
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.");
134
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.");
137
138         dhg.Flip();
139
140         dheSize = pDh->length;
141
142         if (__algorithm.CompareTo(L"DH") == 0)
143         {
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.");
146
147                 r = pDHParams->Construct(dhp, dhg, static_cast< int >(dheSize));
148                 if (IsFailed(r))
149                 {
150                         delete pDHParams;
151                         SysLogException(NID_SEC, r, "Failed to do construct");
152                         goto CATCH;
153                 }
154                 pKeyParams = pDHParams;
155         }
156         else if (__algorithm.CompareTo(L"KEA") == 0)
157         {
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.");
160
161                 r = pKeaParams->Construct(dhp, dhg, static_cast< int >(dheSize));
162                 if (IsFailed(r))
163                 {
164                         delete pKeaParams;
165                         SysLogException(NID_SEC, r, "Failed to do construct");
166                         goto CATCH;
167                 }
168                 pKeyParams = pKeaParams;
169         }
170
171 CATCH:
172
173         if (pDh != null)
174         {
175                 DH_free(pDh);
176         }
177
178         SetLastResult(r);
179         return pKeyParams;
180 }
181
182 KeyPair*
183 KeyPairGenerator::GenerateKeyPairN(Tizen::Security::IKeyParameters* pKeyParams) const
184 {
185         result r = E_SUCCESS;
186         int ret = 0;
187         int paramSize = 0;
188         int size = 0;
189         byte* pBuffer = null;
190         byte temp[_PUBLIC_KEY_LENGTH];
191         ByteBuffer privKey;
192         ByteBuffer pubKey;
193         std::unique_ptr< KeyPair > pKeyPair;
194         BN_CTX* pCtx = null;
195         DH* pDh = null;
196         RSA* pRsa = null;
197         BIGNUM* pE = null;
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);
203
204         ClearLastResult();
205
206         SysAssertf(__algorithm != null && __modulusBitSize > 0, "Not yet constructed. Construct() should be called before use.");
207
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.");
209
210         if ((__algorithm.CompareTo(L"DH") == 0) || (__algorithm.CompareTo(L"KEA") == 0))
211         {
212                 if (__algorithm.CompareTo(L"DH") == 0)
213                 {
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.");
216
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()));
219
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()));
222
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()));
225                 }
226                 else
227                 {
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.");
230
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()));
233
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()));
236
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()));
239                 }
240
241                 pDh = DH_new();
242                 SysTryCatch(NID_SEC, pDh != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "The memory is insufficient.");
243
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.");
246
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.");
249
250                 pDh->length = paramSize * _BITS_IN_BYTE;
251
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.");
254
255                 memset(temp, 0, _PUBLIC_KEY_LENGTH);
256
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.");
259
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.");
262
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.");
265
266                 privKey.Flip();
267
268                 memset(temp, 0, _PUBLIC_KEY_LENGTH);
269                 size = 0;
270
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.");
273
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.");
276
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.");
279
280                 pubKey.Flip();
281
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.");
284
285                 pPubKey->SetKey(pubKey);
286
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.");
289
290                 pPriKey->SetKey(privKey);
291
292         }
293         else if (__algorithm.CompareTo(L"RSA") == 0)
294         {
295                 pCtx = BN_CTX_new();
296                 SysTryReturn(NID_SEC, pCtx != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
297
298                 BN_CTX_start(pCtx);
299
300                 pRsa = RSA_new();
301                 SysTryCatch(NID_SEC, pRsa != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
302
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.");
305
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.");
308
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.");
311
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.");
314
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.");
317
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.");
320
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.");
323
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.");
326
327                 privKey.Flip();
328
329                 OPENSSL_free(pBuffer);
330                 pBuffer = null;
331
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.");
334
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.");
337
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.");
340
341                 pubKey.Flip();
342
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.");
345
346                 pPubKey->SetKey(pubKey);
347
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.");
350
351                 pPriKey->SetKey(privKey);
352
353         }
354
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.");
357
358         r = pKeyPair->SetPrivateKey(privKey);
359         SysTryCatch(NID_SEC, !IsFailed(r), , r, "[%s] Failed to do set private key operation.", GetErrorMessage(r));
360
361         r = pKeyPair->SetPublicKey(pubKey);
362         SysTryCatch(NID_SEC, !IsFailed(r), , r, "[%s] Failed to do set public key operation.", GetErrorMessage(r));
363
364 CATCH:
365
366         if (pDh != null)
367         {
368                 DH_free(pDh);
369         }
370         if (pCtx != null)
371         {
372                 BN_CTX_end(pCtx);
373                 BN_CTX_free(pCtx);
374         }
375         if (pEvpKey != null)
376         {
377                 EVP_PKEY_free(pEvpKey);
378         }
379         if (pBuffer != null)
380         {
381                 OPENSSL_free(pBuffer);
382         }
383         if (pRsa != null)
384         {
385                 RSA_free(pRsa);
386         }
387         if (IsFailed(r))
388         {
389                 pKeyPair.reset(null);
390         }
391
392         return pKeyPair.release();
393 }
394
395 KeyPair*
396 KeyPairGenerator::GenerateKeyPairN(void) const
397 {
398         KeyPair* pKeyPair = null;
399
400         ClearLastResult();
401
402         SysAssertf(__algorithm != null, "Not yet constructed. Construct() should be called before use.");
403
404         SysTryReturn(NID_SEC, __algorithm.CompareTo(L"RSA") == 0, null, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] The requested algorithm is not supported.");
405
406         pKeyPair = GenerateKeyPairN(null);
407         SysTryReturn(NID_SEC, pKeyPair != null, null, GetLastResult(), "[%s] Failed to retrieve key pair for rsa", GetErrorMessage(GetLastResult()));
408
409         return pKeyPair;
410 }
411
412 } } //Tizen::Security