sync with tizen_2.0
[platform/framework/native/appfw.git] / src / security / crypto / FSecCryptoRsaCipher.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                FSecCryptoRsaCipher.cpp
20  * @brief               This file contains the implementation of Tizen::Security::Crypto::RsaCipher class.
21  *
22  */
23 #include <openssl/rsa.h>
24 #include <openssl/evp.h>
25 #include <openssl/x509.h>
26 #include <FBaseResult.h>
27 #include <FBaseErrors.h>
28 #include <FSecCryptoRsaCipher.h>
29 #include <FBaseSysLog.h>
30
31 using namespace Tizen::Base;
32
33
34 namespace Tizen { namespace Security { namespace Crypto
35 {
36 static const int _MAX_ARRAY_LENGTH = 4096;
37
38 RsaCipher::RsaCipher(void)
39         : __pRsaCipherImpl(null)
40 {
41 }
42
43 RsaCipher::~RsaCipher(void)
44 {
45 }
46
47 result
48 RsaCipher::SetPrivateKey(const Tizen::Security::IKey& key)
49 {
50         result r = E_SUCCESS;
51         ByteBuffer* pBuffer = null;
52
53         pBuffer = key.GetEncodedN();
54         SysTryReturn(NID_SEC_CRYPTO, pBuffer != null, GetLastResult(), GetLastResult(), "[%s] Failed to fill the key buffer.", GetErrorMessage(GetLastResult()));
55
56         r = __privateKey.Construct(*pBuffer);
57         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), , r, "[%s] Input key buffer should be valid.", GetErrorMessage(r));
58
59 CATCH:
60         delete pBuffer;
61         return r;
62 }
63
64 result
65 RsaCipher::SetPublicKey(const Tizen::Security::IKey& key)
66 {
67         result r = E_SUCCESS;
68         ByteBuffer* pBuffer = null;
69
70         pBuffer = key.GetEncodedN();
71         SysTryReturn(NID_SEC_CRYPTO, pBuffer != null, GetLastResult(), GetLastResult(), "[%s] Failed to fill the key buffer.", GetErrorMessage(GetLastResult()));
72
73         r = __publicKey.Construct(*pBuffer);
74         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), , r, "[%s] Input key buffer should be valid.", GetErrorMessage(r));
75
76 CATCH:
77         delete pBuffer;
78         return r;
79 }
80
81 ByteBuffer*
82 RsaCipher::EncryptN(const Tizen::Base::ByteBuffer& input)
83 {
84         result r = E_SUCCESS;
85         int dataLen = 0;
86         int keyLen = 0;
87         int outLen = 0;
88         int tempLen = 0;
89         byte* pData = null;
90         byte* pTempBuf = null;
91         byte buffer[_MAX_ARRAY_LENGTH];
92         const byte* pKey = null;
93         ByteBuffer* pOutput = null;
94         EVP_PKEY* pEvpKey = null;
95         RSA* pRsa = null;
96
97         ClearLastResult();
98
99         pData = const_cast< byte* >(input.GetPointer());
100         SysTryReturn(NID_SEC_CRYPTO, pData != null, null, E_INVALID_ARG, "[E_INVALID_ARG] Input data value should be valid.");
101
102         dataLen = input.GetRemaining();
103         SysTryReturn(NID_SEC_CRYPTO, dataLen > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] Input data length should be positive.");
104
105         pKey = __publicKey.GetPointer();
106         SysTryReturn(NID_SEC_CRYPTO, pKey != null, null, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] Key value should be valid.");
107
108         keyLen = __publicKey.GetRemaining();
109         SysTryReturn(NID_SEC_CRYPTO, keyLen > 0, null, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] Key length should be positive.");
110
111         pEvpKey = d2i_PublicKey(EVP_PKEY_RSA, null, &pKey, keyLen);
112         SysTryReturn(NID_SEC_CRYPTO, pEvpKey != null, null, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
113
114         pRsa = EVP_PKEY_get1_RSA(pEvpKey);
115         SysTryCatch(NID_SEC_CRYPTO, pRsa != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
116
117         tempLen = BN_bn2bin(pRsa->n, buffer);
118         SysTryCatch(NID_SEC_CRYPTO, tempLen > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
119
120         pTempBuf = new (std::nothrow) byte[tempLen];
121         SysTryCatch(NID_SEC_CRYPTO, pTempBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
122
123         memset(pTempBuf, 0, tempLen);
124
125         outLen = RSA_public_encrypt(dataLen, pData, pTempBuf, pRsa, RSA_PKCS1_PADDING);
126         SysTryCatch(NID_SEC_CRYPTO, outLen > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
127
128         SysTryCatch(NID_SEC_CRYPTO, outLen <= tempLen, r = E_OVERFLOW, E_OVERFLOW, "[E_OVERFLOW] Overflow as output data length > input data length.");
129
130         pOutput = new (std::nothrow) ByteBuffer();
131         SysTryCatch(NID_SEC_CRYPTO, pOutput != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
132
133         r = pOutput->Construct(outLen);
134         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
135
136         r = pOutput->SetArray(pTempBuf, 0, outLen);
137         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
138
139         pOutput->Flip();
140
141 CATCH:
142
143         if (IsFailed(r))
144         {
145                 delete pOutput;
146                 pOutput = null;
147         }
148         if (pRsa)
149         {
150                 RSA_free(pRsa);
151         }
152         EVP_PKEY_free(pEvpKey);
153
154         delete[] pTempBuf;
155         return pOutput;
156 }
157
158 ByteBuffer*
159 RsaCipher::DecryptN(const Tizen::Base::ByteBuffer& input)
160 {
161         result r = E_SUCCESS;
162         int dataLen = 0;
163         int keyLen = 0;
164         int outLen = 0;
165         int tempLen = 0;
166         byte* pData = null;
167         byte* pTempBuf = null;
168         byte buffer[_MAX_ARRAY_LENGTH];
169         const byte* pKey = null;
170         ByteBuffer* pOutput = null;
171         EVP_PKEY* pEvpKey = null;
172         RSA* pRsa = null;
173
174         ClearLastResult();
175
176         pData = const_cast< byte* >(input.GetPointer());
177         SysTryReturn(NID_SEC_CRYPTO, pData != null, null, E_INVALID_ARG, "[E_INVALID_ARG] Input data value should be valid.");
178
179         dataLen = input.GetRemaining();
180         SysTryReturn(NID_SEC_CRYPTO, dataLen > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] Input data length should be positive.");
181
182         pKey = __privateKey.GetPointer();
183         SysTryReturn(NID_SEC_CRYPTO, pKey != null, null, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] Key data should be valid.");
184
185         keyLen = __privateKey.GetRemaining();
186         SysTryReturn(NID_SEC_CRYPTO, keyLen > 0, null, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] Key length should be positive.");
187
188         //res = __SecCrDecodeRSAPrivateKey(&pPriKey, (CrUINT8 *)pKey, (CrUINT32)keyLen);
189         pEvpKey = d2i_PrivateKey(EVP_PKEY_RSA, null, &pKey, keyLen);
190         SysTryReturn(NID_SEC_CRYPTO, pEvpKey != null, null, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
191
192         pRsa = EVP_PKEY_get1_RSA(pEvpKey);
193         SysTryCatch(NID_SEC_CRYPTO, pRsa != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
194
195         tempLen = BN_bn2bin(pRsa->n, buffer);
196         SysTryCatch(NID_SEC_CRYPTO, tempLen > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
197
198         pTempBuf = new (std::nothrow) byte[tempLen];
199         SysTryCatch(NID_SEC_CRYPTO, pTempBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_SYSTEM] An unexpected system error occurred.");
200
201         memset(pTempBuf, 0, tempLen);
202
203         outLen = RSA_private_decrypt(dataLen, pData, pTempBuf, pRsa, RSA_PKCS1_PADDING);
204         SysTryCatch(NID_SEC_CRYPTO, outLen > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_SYSTEM] An unexpected system error occurred.");
205         SysTryCatch(NID_SEC_CRYPTO, outLen <= tempLen, r = E_OVERFLOW, E_OVERFLOW, "[E_OVERFLOW] Overflow as output data length > input data length.");
206
207         pOutput = new (std::nothrow) ByteBuffer();
208         SysTryCatch(NID_SEC_CRYPTO, pOutput != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
209
210         r = pOutput->Construct(outLen);
211         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
212
213         r = pOutput->SetArray(pTempBuf, 0, outLen);
214         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
215
216         pOutput->Flip();
217
218 CATCH:
219
220         if (IsFailed(r))
221         {
222                 delete pOutput;
223                 pOutput = null;
224         }
225         if (pRsa)
226         {
227                 RSA_free(pRsa);
228         }
229         EVP_PKEY_free(pEvpKey);
230
231         delete[] pTempBuf;
232         return pOutput;
233 }
234
235 } } } //Tizen::Security::Crypto