Merge "Fix accessing freed memory in X509CertificateStore::Update()" into tizen
[platform/framework/native/appfw.git] / src / security / crypto / FSecCryptoMd5Hmac.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                FSecCryptoMd5Hmac.cpp
19  * @brief               This file contains the implementation of Md5Hmac class.
20  */
21 #include <unique_ptr.h>
22 #include <openssl/hmac.h>
23 #include <FBaseResult.h>
24 #include <FBaseErrors.h>
25 #include <FSecCryptoMd5Hmac.h>
26 #include <FSecSecretKey.h>
27 #include <FBaseSysLog.h>
28
29 using namespace Tizen::Base;
30
31
32 namespace Tizen { namespace Security { namespace Crypto
33 {
34 static const int _MD5_DIGEST_LENGTH = 16;
35
36 Md5Hmac::Md5Hmac(void)
37         : __pMd5HmacCtx(null)
38         , __pMd5HmacImpl(null)
39 {
40 }
41
42 Md5Hmac::~Md5Hmac(void)
43 {
44         delete __pMd5HmacCtx;
45 }
46
47 result
48 Md5Hmac::SetAlgorithm(const Tizen::Base::String& algorithm)
49 {
50         // Unsupported in Md5Hmac
51         return E_UNSUPPORTED_ALGORITHM;
52 }
53
54 result
55 Md5Hmac::SetKey(const Tizen::Security::ISecretKey& key)
56 {
57         result r = E_SUCCESS;
58         int dataLen = 0;
59         ByteBuffer* pBuffer = null;
60
61         // convert the ISecretKey to ByteBuffer
62         pBuffer = key.GetEncodedN();
63         SysTryReturn(NID_SEC_CRYPTO, pBuffer != null, GetLastResult(), GetLastResult(), "[%s] Failed to fill key buffer.", GetErrorMessage(GetLastResult()));
64
65         //converts into bytebuffer
66         dataLen = static_cast< int >(pBuffer->GetRemaining());
67         SysTryCatch(NID_SEC_CRYPTO, dataLen > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Key length should be positive.");
68
69         r = __keyBytes.Construct(*pBuffer);
70         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), , r, "[%s] Input key buffer should be valid.", GetErrorMessage(r));
71
72 CATCH:
73         delete pBuffer;
74         return r;
75 }
76
77 ByteBuffer*
78 Md5Hmac::GetHmacN(const ByteBuffer& input) const
79 {
80         result r = E_SUCCESS;
81         int dataLen = 0;
82         int keyLen = 0;
83         unsigned int mdLen = 0;
84         byte* pData = null;
85         byte* pKey = null;
86
87         ClearLastResult();
88
89         pData = const_cast< byte* >(input.GetPointer());
90         SysTryReturn(NID_SEC_CRYPTO, pData != null, null, E_INVALID_ARG, "[E_INVALID_ARG] Input data value should be valid.");
91
92         dataLen = input.GetRemaining();
93         SysTryReturn(NID_SEC_CRYPTO, dataLen > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] Input data length should be positive.");
94
95         std::unique_ptr<byte[]> pMd(new (std::nothrow) byte[_MD5_DIGEST_LENGTH]);
96         SysTryReturn(NID_SEC_CRYPTO, pMd != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
97
98         memset(pMd.get(), 0, _MD5_DIGEST_LENGTH);
99
100         pKey = const_cast< byte* >(__keyBytes.GetPointer());
101         SysTryReturn(NID_SEC_CRYPTO, pKey != null, null, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] Key value should be valid.");
102
103         keyLen = __keyBytes.GetRemaining();
104         SysTryReturn(NID_SEC_CRYPTO, keyLen, null, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] Key length should be positive.");
105
106         //gets HMAC of the input data
107         HMAC(EVP_md5(), pKey, keyLen, pData, dataLen, pMd.get(), &mdLen);
108         SysTryReturn(NID_SEC_CRYPTO, mdLen != 0, null, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
109
110         //stores the HMAC output in bytebuffer
111         std::unique_ptr<ByteBuffer> pOutput(new (std::nothrow) ByteBuffer());
112         SysTryReturn(NID_SEC_CRYPTO, pOutput != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to create memory.");
113
114         r = pOutput->Construct(mdLen);
115         SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), null, E_OUT_OF_MEMORY, "[E_OUT_MEMORY] Failed to allocate memory.");
116
117         r = pOutput->SetArray(pMd.get(), 0, mdLen);
118         SysTryReturn(NID_SEC_CRYPTO, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
119
120         pOutput->Flip();
121
122         return pOutput.release();
123 }
124
125 result
126 Md5Hmac::Initialize(void)
127 {
128         result r = E_SUCCESS;
129         int ret = 0;
130         int keyLen = 0;
131         byte* pKey = null;
132
133         SysAssertf(__pMd5HmacCtx == null, "Already constructed. Calling Initialize() twice or more on a same instance is not allowed for this class.");
134
135         __pMd5HmacCtx = new (std::nothrow) HMAC_CTX();
136         SysTryReturn(NID_SEC_CRYPTO, __pMd5HmacCtx != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
137
138         pKey = const_cast< byte* >(__keyBytes.GetPointer());
139         SysTryCatch(NID_SEC_CRYPTO, pKey != null, r = E_KEY_NOT_FOUND, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] The key value should be valid.");
140
141         keyLen = __keyBytes.GetRemaining();
142         SysTryCatch(NID_SEC_CRYPTO, keyLen, r = E_KEY_NOT_FOUND, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] The key length should be positive.");
143
144         //calls the HMAC_init function
145         ret = HMAC_Init(__pMd5HmacCtx, static_cast< byte* >(pKey), keyLen, EVP_md5());
146         SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
147
148 CATCH:
149
150         if (IsFailed(r))
151         {
152                 delete __pMd5HmacCtx;
153                 __pMd5HmacCtx = null;
154         }
155         return r;
156 }
157
158 result
159 Md5Hmac::Update(const Tizen::Base::ByteBuffer& input)
160 {
161         result r = E_SUCCESS;
162         int ret = 0;
163         int dataLen = 0;
164         byte* pData = null;
165
166         SysAssertf(__pMd5HmacCtx != null, "Not yet constructed. Initialize() should be called before use.");
167
168         pData = const_cast< byte* >(input.GetPointer());
169         SysTryReturn(NID_SEC_CRYPTO, pData != null, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The input data value should be valid.");
170
171         dataLen = input.GetRemaining();
172         SysTryReturn(NID_SEC_CRYPTO, dataLen > 0, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The input data length should be valid.");
173
174         //calls the HMAC_update function
175         ret = HMAC_Update(__pMd5HmacCtx, const_cast< byte* >(pData), static_cast< unsigned long >(dataLen));
176         SysTryReturn(NID_SEC_CRYPTO, ret == 1, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
177
178         return r;
179 }
180
181 Tizen::Base::ByteBuffer*
182 Md5Hmac::FinalizeN(void)
183 {
184         result r = E_SUCCESS;
185         int ret = 0;
186         unsigned int outLen = _MD5_DIGEST_LENGTH;
187         std::unique_ptr<ByteBuffer> pOutput(null);
188
189         ClearLastResult();
190
191         SysAssertf(__pMd5HmacCtx != null, "Not yet constructed. Initialize() should be called before use.");
192
193         std::unique_ptr<byte[]> pTempBuf(new (std::nothrow) byte[outLen]);
194         SysTryCatch(NID_SEC_CRYPTO, pTempBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
195
196         //call the HMAC_final function and stores output in pTempBuf
197         ret = HMAC_Final(__pMd5HmacCtx, pTempBuf.get(), &outLen);
198         SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
199
200         //write HMAC output in bytebuffer
201         pOutput = std::unique_ptr<ByteBuffer>(new (std::nothrow) ByteBuffer());
202         SysTryCatch(NID_SEC_CRYPTO, pOutput != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to create memory.");
203
204         r = pOutput->Construct(outLen);
205         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
206
207         r = pOutput->SetArray(pTempBuf.get(), 0, outLen);
208         SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
209
210         pOutput->Flip();
211
212 CATCH:
213
214         HMAC_CTX_cleanup(__pMd5HmacCtx);
215
216         if (IsFailed(r))
217         {
218                 pOutput.reset(null);
219         }
220
221         delete __pMd5HmacCtx;
222         __pMd5HmacCtx = null;
223
224         return pOutput.release();
225 }
226
227 } } } //Tizen::Security::Crypto