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 FSecCryptoRsaSignature.cpp
19 * @brief This file contains the implementation for Tizen::Security::Crypto::RsaSignature class.
22 #include <openssl/rsa.h>
23 #include <openssl/evp.h>
24 #include <openssl/pem.h>
25 #include <openssl/x509.h>
26 #include <FBaseResult.h>
27 #include <FBaseErrors.h>
28 #include <FSecCryptoRsaSignature.h>
29 #include <FBaseSysLog.h>
31 using namespace Tizen::Base;
34 namespace Tizen { namespace Security { namespace Crypto
36 static const int _MAX_ARRAY_LENGTH = 4096;
38 RsaSignature::RsaSignature(void)
39 : __pRsaSignatureImpl(null)
43 RsaSignature::~RsaSignature(void)
48 RsaSignature::SetPrivateKey(const Tizen::Security::IKey& key)
51 ByteBuffer* pBuffer = null;
53 pBuffer = key.GetEncodedN();
54 SysTryReturn(NID_SEC_CRYPTO, pBuffer != null, GetLastResult(), GetLastResult(), "[%s] Failed to fill the key buffer.", GetErrorMessage(GetLastResult()));
56 r = __privateKey.Construct(*pBuffer);
57 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), , r, "[%s] Input key buffer should be valid.", GetErrorMessage(r));
65 RsaSignature::SetPublicKey(const Tizen::Security::IKey& key)
68 ByteBuffer* pBuffer = null;
70 pBuffer = key.GetEncodedN();
71 SysTryReturn(NID_SEC_CRYPTO, pBuffer != null, GetLastResult(), GetLastResult(), "[%s] Failed to fill the key buffer.", GetErrorMessage(GetLastResult()));
73 r = __publicKey.Construct(*pBuffer);
74 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), , r, "[%s] Input key buffer should be valid.", GetErrorMessage(r));
82 RsaSignature::SignN(const ByteBuffer& input)
84 return SignN(input, L"SHA1");
88 RsaSignature::SignN(const ByteBuffer& input, const Tizen::Base::String& algorithm)
93 unsigned int dataLen = 0;
94 unsigned int outLen = 0;
95 byte buffer[_MAX_ARRAY_LENGTH];
96 byte* pTempBuf = null;
97 const byte* pData = null;
98 const byte* pKey = null;
99 ByteBuffer* pOutput = null;
100 EVP_PKEY* pEvpKey = null;
103 int localNid = NID_sha1;
107 pData = input.GetPointer();
108 SysTryReturn(NID_SEC_CRYPTO, pData != null, null, E_INVALID_ARG, "[E_INVALID_ARG] Input data value should be valid.");
110 dataLen = input.GetRemaining();
111 SysTryReturn(NID_SEC_CRYPTO, dataLen > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] Input data length should be positive.");
113 pKey = __privateKey.GetPointer();
114 SysTryReturn(NID_SEC_CRYPTO, pKey != null, null, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] Key value should be valid.");
116 keyLen = __privateKey.GetRemaining();
117 SysTryReturn(NID_SEC_CRYPTO, keyLen > 0, null, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] Key length should be positive.");
119 pEvpKey = d2i_PrivateKey(EVP_PKEY_RSA, null, &pKey, keyLen);
123 PKCS8_PRIV_KEY_INFO* pPrivKeyInfo = d2i_PKCS8_PRIV_KEY_INFO(null, &pKey, keyLen);
124 if (pPrivKeyInfo != null)
126 pEvpKey = EVP_PKCS82PKEY(pPrivKeyInfo);
127 PKCS8_PRIV_KEY_INFO_free(pPrivKeyInfo);
133 pBio = BIO_new(BIO_s_mem());
134 SysTryReturn(NID_SEC_CRYPTO, pBio != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
136 int readCount = BIO_write(pBio, (const void*) pKey, keyLen);
137 SysTryCatch(NID_SEC_CRYPTO, readCount > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
139 pEvpKey = PEM_read_bio_PrivateKey(pBio, null, 0, null);
142 SysTryCatch(NID_SEC_CRYPTO, pEvpKey != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
144 pRsa = EVP_PKEY_get1_RSA(pEvpKey);
145 SysTryCatch(NID_SEC_CRYPTO, pRsa != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
147 outLen = BN_bn2bin(pRsa->n, buffer);
148 SysTryCatch(NID_SEC_CRYPTO, outLen > 0, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
150 pTempBuf = new (std::nothrow) byte[outLen];
151 SysTryCatch(NID_SEC_CRYPTO, pTempBuf != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
153 memset(pTempBuf, 0, outLen);
155 if (algorithm.CompareTo(L"MD5WITHSHA1") == 0) //for ssl padding
157 localNid = NID_md5_sha1;
159 else if (algorithm.CompareTo(L"MD5") == 0)
163 else if (algorithm.CompareTo(L"SHA1") == 0)
167 else if (algorithm.CompareTo(L"SHA2/224") == 0)
169 localNid = NID_sha224;
171 else if (algorithm.CompareTo(L"SHA2/256") == 0)
173 localNid = NID_sha256;
175 else if (algorithm.CompareTo(L"SHA2/384") == 0)
177 localNid = NID_sha384;
179 else if (algorithm.CompareTo(L"SHA2/512") == 0)
181 localNid = NID_sha512;
185 SysTryCatch(NID_SEC_CRYPTO, false, r = E_UNSUPPORTED_ALGORITHM, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] An unsupported algorithm.");
188 ret = RSA_sign(localNid, pData, dataLen, pTempBuf, &outLen, pRsa);
189 SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
190 SysTryCatch(NID_SEC_CRYPTO, outLen > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Output length should be positive.");
192 pOutput = new (std::nothrow) ByteBuffer();
193 SysTryCatch(NID_SEC_CRYPTO, pOutput != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
195 r = pOutput->Construct(outLen);
196 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allovate memory.");
198 r = pOutput->SetArray(pTempBuf, 0, outLen);
199 SysTryCatch(NID_SEC_CRYPTO, !IsFailed(r), r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
216 EVP_PKEY_free(pEvpKey);
228 RsaSignature::Verify(const Tizen::Base::ByteBuffer& data, const Tizen::Base::ByteBuffer& signedData)
230 return Verify(data, signedData, L"SHA1");
234 RsaSignature::Verify(const Tizen::Base::ByteBuffer& data, const Tizen::Base::ByteBuffer& signedData, const Tizen::Base::String& algorithm)
236 result r = E_SUCCESS;
239 unsigned int dataLen = 0;
240 unsigned int signedDataLen = 0;
241 byte* pSignedData = null;
242 const byte* pData = null;
243 const byte* pKey = null;
244 EVP_PKEY* pEvpKey = null;
247 int localNid = NID_sha1;
251 pData = data.GetPointer();
252 SysTryReturn(NID_SEC_CRYPTO, pData != null, false, E_INVALID_ARG, "[E_INVALID_ARG] Input data value should be valid.");
254 dataLen = data.GetRemaining();
255 SysTryReturn(NID_SEC_CRYPTO, dataLen > 0, false, E_INVALID_ARG, "[E_INVALID_ARG] Input data length should be positive.");
257 pSignedData = const_cast< byte* >(signedData.GetPointer());
258 SysTryReturn(NID_SEC_CRYPTO, pSignedData != null, false, E_INVALID_ARG, "[E_INVALID_ARG] Signed data value should be valid.");
260 signedDataLen = static_cast< unsigned int >(signedData.GetRemaining());
261 SysTryReturn(NID_SEC_CRYPTO, signedDataLen > 0, false, E_INVALID_ARG, "[E_INVALID_ARG] Signed data length should be positive.");
263 pKey = __publicKey.GetPointer();
264 SysTryReturn(NID_SEC_CRYPTO, pKey != null, false, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] Key value should be valid.");
266 keyLen = __publicKey.GetRemaining();
267 SysTryReturn(NID_SEC_CRYPTO, keyLen > 0, false, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] Key length should be positive.");
269 pEvpKey = d2i_PublicKey(EVP_PKEY_RSA, null, &pKey, keyLen);
273 pEvpKey = d2i_PUBKEY(null, &pKey, keyLen);
278 pBio = BIO_new(BIO_s_mem());
279 SysTryReturn(NID_SEC_CRYPTO, pBio != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
281 int readCount = BIO_write(pBio, (const void*) pKey, keyLen);
284 pEvpKey = PEM_read_bio_PUBKEY(pBio, null, 0, null);
288 SysTryCatch(NID_SEC_CRYPTO, pEvpKey != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
290 pRsa = EVP_PKEY_get1_RSA(pEvpKey);
291 SysTryCatch(NID_SEC_CRYPTO, pRsa != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
293 if (algorithm.CompareTo(L"MD5WITHSHA1") == 0) //for ssl padding
295 localNid = NID_md5_sha1;
297 else if (algorithm.CompareTo(L"MD5") == 0)
301 else if (algorithm.CompareTo(L"SHA1") == 0)
305 else if (algorithm.CompareTo(L"SHA2/224") == 0)
307 localNid = NID_sha224;
309 else if (algorithm.CompareTo(L"SHA2/256") == 0)
311 localNid = NID_sha256;
313 else if (algorithm.CompareTo(L"SHA2/384") == 0)
315 localNid = NID_sha384;
317 else if (algorithm.CompareTo(L"SHA2/512") == 0)
319 localNid = NID_sha512;
323 SysTryCatch(NID_SEC_CRYPTO, false, r = E_UNSUPPORTED_ALGORITHM, E_UNSUPPORTED_ALGORITHM, "[E_UNSUPPORTED_ALGORITHM] An unsupported algorithm.");
326 ret = RSA_verify(localNid, pData, dataLen, pSignedData, signedDataLen, pRsa);
327 SysTryCatch(NID_SEC_CRYPTO, ret == 1, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
337 EVP_PKEY_free(pEvpKey);
353 } } } //Tizen::Security::Crypto