d2d4ddae5d834087b12777fd626a1dab6362a3b7
[platform/framework/native/appfw.git] / src / security / crypto / FSecCrypto_KeaCore.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        FSecCrypto_KeaCore.cpp
20  * @brief       This file contains implementation of Kea Key Exchange algorithms and Shared Secret Generation.
21  */
22 #include <new>
23 #include <openssl/bn.h>
24 #include <unique_ptr.h>
25 #include <FBaseResult.h>
26 #include <FBaseErrors.h>
27 #include <FBaseSysLog.h>
28 #include "FSecCrypto_KeaCore.h"
29 #include "FSecCrypto_SkipJackCore.h"
30
31 namespace Tizen { namespace Security { namespace Crypto
32 {
33
34 static const int _DATA_ARRAY_SIZE = 2;
35 static const int _KEA_KEY_LOOP_VAR_1 = 5;
36 static const int _KEA_KEY_LOOP_VAR_2 = 7;
37 static const int _ONE_BIT_RESET_VAL = 0x00;
38 static const int _KEA_LSB_VAL_1 = 2;
39 static const int _KEA_LSB_VAL_2 = 3;
40 static const int _KEA_MSB_VAL_1 = 9;
41 static const int _KEA_MSB_VAL_2 = 8;
42 static const int _TWO_BYTE_VAL = 16;
43 static const int _CRYPTO_VARIABLE_SIGNIFICANT_BITS_ = 20;
44 static const int _PUBLIC_KEY_LENGTH = 1024;
45
46 Kea*
47 _KeaCore::CreateKeaN(void)
48 {
49         ClearLastResult();
50
51         std::unique_ptr <Kea> pRet (new (std::nothrow) Kea());
52         SysTryReturn(NID_SEC_CRYPTO, pRet != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Allocating new Kea object failed.");
53
54         pRet->version = 0;
55         pRet->pP = null;
56         pRet->pG = null;
57         pRet->length = 0;
58         pRet->pPubKey1 = null;
59         pRet->pPrivKey1 = null;
60         pRet->pPubKey2 = null;
61         pRet->pPrivKey2 = null;
62
63         return pRet.release();
64 }
65
66 void
67 _KeaCore::DeleteKea(Kea* pKea)
68 {
69         if (pKea->pP != null)
70         {
71                 BN_clear_free(pKea->pP);
72         }
73
74         if (pKea->pG != null)
75         {
76                 BN_clear_free(pKea->pG);
77         }
78
79         if (pKea->pPubKey1 != null)
80         {
81                 BN_clear_free(pKea->pPubKey1);
82         }
83
84         if (pKea->pPrivKey1 != null)
85         {
86                 BN_clear_free(pKea->pPrivKey1);
87         }
88
89         if (pKea->pPubKey2 != null)
90         {
91                 BN_clear_free(pKea->pPubKey2);
92         }
93
94         if (pKea->pPrivKey2 != null)
95         {
96                 BN_clear_free(pKea->pPrivKey2);
97         }
98 }
99
100 result
101 _KeaCore::ComputeKeaKey(byte** ppKey, BIGNUM* pPublicKey1, BIGNUM* pPublicKey2, Kea& keaVar)
102 {
103         result r = E_SUCCESS;
104         int ret = 0;
105         byte secret[_PUBLIC_KEY_LENGTH] = {0, };
106         BN_CTX* pCtx = null;
107         BIGNUM* pTmp = null;
108         BIGNUM* pTmp1 = null;
109         BIGNUM* pRem = null;
110
111         SysTryReturn(NID_SEC_CRYPTO, ppKey != null && pPublicKey1 != null && pPublicKey2 != null
112                            , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Input key data and public keys should be valid.");
113
114         pCtx = BN_CTX_new();
115         SysTryReturn(NID_SEC_CRYPTO, pCtx != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
116
117         // Managing 1st set of public and private key
118         BN_CTX_start(pCtx);
119         pTmp = BN_CTX_get(pCtx);
120         SysTryCatch(NID_SEC_CRYPTO, pTmp != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
121
122         SysTryCatch(NID_SEC_CRYPTO, keaVar.pPrivKey1 != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key is not available.");
123
124         ret = BN_mod_exp(pTmp, pPublicKey1, keaVar.pPrivKey1, keaVar.pP, pCtx);
125         SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
126
127         // Managing 2nd set of public and private key
128         pTmp1 = BN_CTX_get(pCtx);
129         SysTryCatch(NID_SEC_CRYPTO, pTmp1 != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
130
131         SysTryCatch(NID_SEC_CRYPTO, keaVar.pPrivKey2 != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key is not available.");
132
133         ret = BN_mod_exp(pTmp1, pPublicKey2, keaVar.pPrivKey2, keaVar.pP, pCtx);
134         SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
135
136         // Performing operation pRem  = (pTmp + pTmp1) mod p
137         pRem = BN_CTX_get(pCtx);
138         SysTryCatch(NID_SEC_CRYPTO, pRem != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
139
140         ret = BN_add(pRem, pTmp, pTmp1);
141         SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
142
143         ret = BN_mod(pTmp, pRem, keaVar.pP, pCtx);
144         SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
145
146         ret = BN_bn2bin(pTmp, secret);
147         SysTryCatch(NID_SEC_CRYPTO, ret > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
148
149         keaVar.length = ret;
150
151         *ppKey = ComputeKeaSecret(secret, ret);
152         SysTryCatch(NID_SEC_CRYPTO, *ppKey != null, r = GetLastResult(), GetLastResult(), "[%s] Kea key secret should be valid.", GetErrorMessage(GetLastResult()));
153
154 CATCH:
155         if (pCtx != null)
156         {
157                 BN_CTX_end(pCtx);
158                 BN_CTX_free(pCtx);
159         }
160
161         return r;
162 }
163
164 byte*
165 _KeaCore::ComputeKeaSecret(byte* pKey, int len)
166 {
167         result r = E_SUCCESS;
168         int index = 0;
169         int ret = 0;
170         byte pad[_SKIPJACK_KEY_LENGTH] = {0x72, 0xf1, 0xa8, 0x7e, 0x92, 0x82, 0x41, 0x98, 0xab, 0x0b};
171         byte vector3[_DATA_ARRAY_SIZE] = {0, };
172         SkipJackKey sjVar = {{0, }, };
173         BIGNUM* pBn1 = null;
174         BIGNUM* pBn2 = null;
175         BIGNUM* pBn3 = null;
176         BN_CTX* pCtx = null;
177
178         ClearLastResult();
179
180         std::unique_ptr <byte[]> pVector1 (new (std::nothrow) byte[_SKIPJACK_KEY_LENGTH]);
181         SysTryReturn(NID_SEC_CRYPTO, pVector1 != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Allocating new byte array failed.");
182
183         std::unique_ptr <byte[]> pVector2 (new (std::nothrow) byte[_SKIPJACK_KEY_LENGTH]);
184         SysTryCatch(NID_SEC_CRYPTO, pVector2 != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Allocating new byte array failed.");
185
186         pCtx = BN_CTX_new();
187         SysTryCatch(NID_SEC_CRYPTO, pCtx != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
188
189         memset(&sjVar, 0, sizeof(sjVar));
190
191         memcpy(pVector1.get(), (pKey + len - _SKIPJACK_KEY_LENGTH), _SKIPJACK_KEY_LENGTH);
192
193         memcpy(pVector2.get(), (pKey + len - _CRYPTO_VARIABLE_SIGNIFICANT_BITS_), _SKIPJACK_KEY_LENGTH);
194
195         for (index = 0; index < _KEA_KEY_LOOP_VAR_1; index++)
196         {
197                 pVector1.get()[index] = pVector1.get()[index] + pVector1.get()[_KEA_MSB_VAL_1 - index];
198                 pVector1.get()[_KEA_MSB_VAL_1 - index] = pVector1.get()[index] - pVector1.get()[_KEA_MSB_VAL_1 - index];
199                 pVector1.get()[index] = pVector1.get()[index] - pVector1.get()[_KEA_MSB_VAL_1 - index];
200
201                 pVector2.get()[index] = pVector2.get()[index] + pVector2.get()[_KEA_MSB_VAL_1 - index];
202                 pVector2.get()[_KEA_MSB_VAL_1 - index] = pVector2.get()[index] - pVector2.get()[_KEA_MSB_VAL_1 - index];
203                 pVector2.get()[index] = pVector2.get()[index] - pVector2.get()[_KEA_MSB_VAL_1 - index];
204         }
205
206         //for creating key pVector1 ^ pad
207         for (index = 0; index < _SKIPJACK_KEY_LENGTH; index++)
208         {
209                 pVector1.get()[index] = pVector1.get()[index] ^ pad[index];
210         }
211
212         //for doing (pVector2 / 2^16) mod 2 ^64
213         //1st Step: we perform left shift on pVector2 by 2 bytes to perform (pVector2 / 2^16)
214         for (index = _KEA_KEY_LOOP_VAR_2; index >= 0; index--)
215         {
216                 pVector2.get()[_DATA_ARRAY_SIZE + index] = pVector2.get()[index];
217         }
218
219         //Setting 1st 2 bytes as 0 in continuation from the above operation
220         // no need for explicitly doing mod 2^64 opeartion since number will be the same
221         // as 2^64 -1 = 0xFFFFFFFFFFFFFFFF and that is the biggest 64 bit number
222         // and x is also a 64 bit number
223         // therefore x mod 2^64 = x
224         for (index = 0; index < _DATA_ARRAY_SIZE; index++)
225         {
226                 pVector2.get()[index] = _ONE_BIT_RESET_VAL;
227         }
228
229         // making modified pVector1 as key for doing skipjack operation
230         for (index = 0; index < _SKIPJACK_KEY_LENGTH; index++)
231         {
232                 sjVar.keyVal[index] = pVector1.get()[index];
233         }
234
235         BN_CTX_start(pCtx);
236
237         pBn2 = BN_CTX_get(pCtx);
238         SysTryCatch(NID_SEC_CRYPTO, pBn2 != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
239
240         pBn3 = BN_CTX_get(pCtx);
241         SysTryCatch(NID_SEC_CRYPTO, pBn3 != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
242
243         //Peforming pVector2 mod 2exp16 and storing it in vector3
244         //pVector2 in to big number
245         pBn1 = BN_bin2bn(pVector2.get(), _SKIPJACK_KEY_LENGTH, null);
246         SysTryCatch(NID_SEC_CRYPTO, pBn1 != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
247
248         //2^16 into big number
249         ret = BN_lshift(pBn2, BN_value_one(), _TWO_BYTE_VAL);
250         SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
251
252         // performing pVector2 mod 2^16
253         ret = BN_mod(pBn3, pBn1, pBn2, pCtx);
254         SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
255
256         // storing it in array
257         ret = BN_bn2bin(pBn3, vector3);
258         SysTryCatch(NID_SEC_CRYPTO, ret > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
259
260         //Performing encryption over (pVector2/2^16) mod 2 ^ 64
261         _SkipJackCore::DoCipherEcb(static_cast< const byte* >(pVector2.get() + _DATA_ARRAY_SIZE), pVector1.get(), sjVar, static_cast< bool >(1));
262
263         //Performing second encryption on the output data from previous encryption
264         for (index = _KEA_KEY_LOOP_VAR_2; index >= 0; index--)
265         {
266                 pVector1.get()[_DATA_ARRAY_SIZE + index] = pVector1.get()[index];
267                 //printf("%c\t",pVector2[index]);
268         }
269
270         for (index = 0; index < _DATA_ARRAY_SIZE; index++)
271         {
272                 pVector1.get()[index] = _ONE_BIT_RESET_VAL;
273                 //printf("%c \t",pVector2[index]);
274         }
275
276         _SkipJackCore::DoCipherEcb(static_cast< const byte* >(pVector1.get() + _DATA_ARRAY_SIZE), pVector2.get(), sjVar, static_cast< bool >(1));
277
278         // xoring pVector1 msb with vector3
279         pVector1.get()[0] = pVector1.get()[0] ^ vector3[0];
280         pVector1.get()[1] = pVector1.get()[1] ^ vector3[1];
281
282         //adding the xored bits as lsb in pVector1
283         pVector2.get()[_KEA_MSB_VAL_2] = pVector1.get()[_KEA_LSB_VAL_1];
284         pVector2.get()[_KEA_MSB_VAL_1] = pVector1.get()[_KEA_LSB_VAL_2];
285
286 CATCH:
287
288         if (pCtx != null)
289         {
290                 BN_CTX_end(pCtx);
291                 BN_CTX_free(pCtx);
292         }
293
294         return pVector2.release();
295 }
296
297 } } } //Tizen::Security::Crypto