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 FSecCrypto_KeaCore.cpp
19 * @brief This file contains implementation of Kea Key Exchange algorithms and Shared Secret Generation.
22 #include <openssl/bn.h>
23 #include <unique_ptr.h>
24 #include <FBaseResult.h>
25 #include <FBaseErrors.h>
26 #include <FBaseSysLog.h>
27 #include "FSecCrypto_KeaCore.h"
28 #include "FSecCrypto_SkipJackCore.h"
30 namespace Tizen { namespace Security { namespace Crypto
33 static const int _DATA_ARRAY_SIZE = 2;
34 static const int _KEA_KEY_LOOP_VAR_1 = 5;
35 static const int _KEA_KEY_LOOP_VAR_2 = 7;
36 static const int _ONE_BIT_RESET_VAL = 0x00;
37 static const int _KEA_LSB_VAL_1 = 2;
38 static const int _KEA_LSB_VAL_2 = 3;
39 static const int _KEA_MSB_VAL_1 = 9;
40 static const int _KEA_MSB_VAL_2 = 8;
41 static const int _TWO_BYTE_VAL = 16;
42 static const int _CRYPTO_VARIABLE_SIGNIFICANT_BITS_ = 20;
43 static const int _PUBLIC_KEY_LENGTH = 1024;
46 _KeaCore::CreateKeaN(void)
50 std::unique_ptr <Kea> pRet (new (std::nothrow) Kea());
51 SysTryReturn(NID_SEC_CRYPTO, pRet != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Allocating new Kea object failed.");
57 pRet->pPubKey1 = null;
58 pRet->pPrivKey1 = null;
59 pRet->pPubKey2 = null;
60 pRet->pPrivKey2 = null;
62 return pRet.release();
66 _KeaCore::DeleteKea(Kea* pKea)
70 BN_clear_free(pKea->pP);
75 BN_clear_free(pKea->pG);
78 if (pKea->pPubKey1 != null)
80 BN_clear_free(pKea->pPubKey1);
83 if (pKea->pPrivKey1 != null)
85 BN_clear_free(pKea->pPrivKey1);
88 if (pKea->pPubKey2 != null)
90 BN_clear_free(pKea->pPubKey2);
93 if (pKea->pPrivKey2 != null)
95 BN_clear_free(pKea->pPrivKey2);
102 _KeaCore::ComputeKeaKey(byte** ppKey, BIGNUM* pPublicKey1, BIGNUM* pPublicKey2, Kea& keaVar)
104 result r = E_SUCCESS;
106 byte secret[_PUBLIC_KEY_LENGTH] = {0, };
109 BIGNUM* pTmp1 = null;
112 SysTryReturn(NID_SEC_CRYPTO, ppKey != null && pPublicKey1 != null && pPublicKey2 != null
113 , E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Input key data and public keys should be valid.");
116 SysTryReturn(NID_SEC_CRYPTO, pCtx != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
118 // Managing 1st set of public and private key
120 pTmp = BN_CTX_get(pCtx);
121 SysTryCatch(NID_SEC_CRYPTO, pTmp != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
123 SysTryCatch(NID_SEC_CRYPTO, keaVar.pPrivKey1 != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key is not available.");
125 ret = BN_mod_exp(pTmp, pPublicKey1, keaVar.pPrivKey1, keaVar.pP, pCtx);
126 SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
128 // Managing 2nd set of public and private key
129 pTmp1 = BN_CTX_get(pCtx);
130 SysTryCatch(NID_SEC_CRYPTO, pTmp1 != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
132 SysTryCatch(NID_SEC_CRYPTO, keaVar.pPrivKey2 != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Private key is not available.");
134 ret = BN_mod_exp(pTmp1, pPublicKey2, keaVar.pPrivKey2, keaVar.pP, pCtx);
135 SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
137 // Performing operation pRem = (pTmp + pTmp1) mod p
138 pRem = BN_CTX_get(pCtx);
139 SysTryCatch(NID_SEC_CRYPTO, pRem != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
141 ret = BN_add(pRem, pTmp, pTmp1);
142 SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
144 ret = BN_mod(pTmp, pRem, keaVar.pP, pCtx);
145 SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
147 ret = BN_bn2bin(pTmp, secret);
148 SysTryCatch(NID_SEC_CRYPTO, ret > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
152 *ppKey = ComputeKeaSecret(secret, ret);
153 SysTryCatch(NID_SEC_CRYPTO, *ppKey != null, r = GetLastResult(), GetLastResult(), "[%s] Kea key secret should be valid.", GetErrorMessage(GetLastResult()));
166 _KeaCore::ComputeKeaSecret(byte* pKey, int len)
168 result r = E_SUCCESS;
171 byte pad[_SKIPJACK_KEY_LENGTH] = {0x72, 0xf1, 0xa8, 0x7e, 0x92, 0x82, 0x41, 0x98, 0xab, 0x0b};
172 byte vector3[_DATA_ARRAY_SIZE] = {0, };
173 SkipJackKey sjVar = {{0, }, };
181 std::unique_ptr <byte[]> pVector1 (new (std::nothrow) byte[_SKIPJACK_KEY_LENGTH]);
182 SysTryReturn(NID_SEC_CRYPTO, pVector1 != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Allocating new byte array failed.");
184 std::unique_ptr <byte[]> pVector2 (new (std::nothrow) byte[_SKIPJACK_KEY_LENGTH]);
185 SysTryCatch(NID_SEC_CRYPTO, pVector2 != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Allocating new byte array failed.");
188 SysTryCatch(NID_SEC_CRYPTO, pCtx != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
190 memset(&sjVar, 0, sizeof(sjVar));
192 memcpy(pVector1.get(), (pKey + len - _SKIPJACK_KEY_LENGTH), _SKIPJACK_KEY_LENGTH);
194 memcpy(pVector2.get(), (pKey + len - _CRYPTO_VARIABLE_SIGNIFICANT_BITS_), _SKIPJACK_KEY_LENGTH);
196 for (index = 0; index < _KEA_KEY_LOOP_VAR_1; index++)
198 pVector1.get()[index] = pVector1.get()[index] + pVector1.get()[_KEA_MSB_VAL_1 - index];
199 pVector1.get()[_KEA_MSB_VAL_1 - index] = pVector1.get()[index] - pVector1.get()[_KEA_MSB_VAL_1 - index];
200 pVector1.get()[index] = pVector1.get()[index] - pVector1.get()[_KEA_MSB_VAL_1 - index];
202 pVector2.get()[index] = pVector2.get()[index] + pVector2.get()[_KEA_MSB_VAL_1 - index];
203 pVector2.get()[_KEA_MSB_VAL_1 - index] = pVector2.get()[index] - pVector2.get()[_KEA_MSB_VAL_1 - index];
204 pVector2.get()[index] = pVector2.get()[index] - pVector2.get()[_KEA_MSB_VAL_1 - index];
207 //for creating key pVector1 ^ pad
208 for (index = 0; index < _SKIPJACK_KEY_LENGTH; index++)
210 pVector1.get()[index] = pVector1.get()[index] ^ pad[index];
213 //for doing (pVector2 / 2^16) mod 2 ^64
214 //1st Step: we perform left shift on pVector2 by 2 bytes to perform (pVector2 / 2^16)
215 for (index = _KEA_KEY_LOOP_VAR_2; index >= 0; index--)
217 pVector2.get()[_DATA_ARRAY_SIZE + index] = pVector2.get()[index];
220 //Setting 1st 2 bytes as 0 in continuation from the above operation
221 // no need for explicitly doing mod 2^64 opeartion since number will be the same
222 // as 2^64 -1 = 0xFFFFFFFFFFFFFFFF and that is the biggest 64 bit number
223 // and x is also a 64 bit number
224 // therefore x mod 2^64 = x
225 for (index = 0; index < _DATA_ARRAY_SIZE; index++)
227 pVector2.get()[index] = _ONE_BIT_RESET_VAL;
230 // making modified pVector1 as key for doing skipjack operation
231 for (index = 0; index < _SKIPJACK_KEY_LENGTH; index++)
233 sjVar.keyVal[index] = pVector1.get()[index];
238 pBn2 = BN_CTX_get(pCtx);
239 SysTryCatch(NID_SEC_CRYPTO, pBn2 != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
241 pBn3 = BN_CTX_get(pCtx);
242 SysTryCatch(NID_SEC_CRYPTO, pBn3 != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
244 //Peforming pVector2 mod 2exp16 and storing it in vector3
245 //pVector2 in to big number
246 pBn1 = BN_bin2bn(pVector2.get(), _SKIPJACK_KEY_LENGTH, null);
247 SysTryCatch(NID_SEC_CRYPTO, pBn1 != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
249 //2^16 into big number
250 ret = BN_lshift(pBn2, BN_value_one(), _TWO_BYTE_VAL);
251 SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
253 // performing pVector2 mod 2^16
254 ret = BN_mod(pBn3, pBn1, pBn2, pCtx);
255 SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
257 // storing it in array
258 ret = BN_bn2bin(pBn3, vector3);
259 SysTryCatch(NID_SEC_CRYPTO, ret > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
261 //Performing encryption over (pVector2/2^16) mod 2 ^ 64
262 _SkipJackCore::DoCipherEcb(static_cast< const byte* >(pVector2.get() + _DATA_ARRAY_SIZE), pVector1.get(), sjVar, static_cast< bool >(1));
264 //Performing second encryption on the output data from previous encryption
265 for (index = _KEA_KEY_LOOP_VAR_2; index >= 0; index--)
267 pVector1.get()[_DATA_ARRAY_SIZE + index] = pVector1.get()[index];
268 //printf("%c\t",pVector2[index]);
271 for (index = 0; index < _DATA_ARRAY_SIZE; index++)
273 pVector1.get()[index] = _ONE_BIT_RESET_VAL;
274 //printf("%c \t",pVector2[index]);
277 _SkipJackCore::DoCipherEcb(static_cast< const byte* >(pVector1.get() + _DATA_ARRAY_SIZE), pVector2.get(), sjVar, static_cast< bool >(1));
279 // xoring pVector1 msb with vector3
280 pVector1.get()[0] = pVector1.get()[0] ^ vector3[0];
281 pVector1.get()[1] = pVector1.get()[1] ^ vector3[1];
283 //adding the xored bits as lsb in pVector1
284 pVector2.get()[_KEA_MSB_VAL_2] = pVector1.get()[_KEA_LSB_VAL_1];
285 pVector2.get()[_KEA_MSB_VAL_1] = pVector1.get()[_KEA_LSB_VAL_2];
295 return pVector2.release();
298 } } } //Tizen::Security::Crypto