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 FSecCert_CertSignature.cpp
19 // @brief This file contains implementation of X509 Certificate signature.
32 #include <openssl/objects.h>
33 #include <openssl/obj_mac.h>
34 #include <openssl/sha.h>
35 #include <openssl/md5.h>
37 #include <openssl/md2.h>
39 #include <openssl/rsa.h>
40 #include <openssl/evp.h>
41 #include <unique_ptr.h>
42 #include <FBaseByteBuffer.h>
43 #include <FBaseResult.h>
44 #include <FBaseSysLog.h>
45 #include "FSecCert_CertSignature.h"
46 #include "FSecCert_CertOidDef.h"
49 using namespace Tizen::Base;
51 namespace Tizen { namespace Security { namespace Cert
54 // _CertSignature class
56 _CertSignature::_CertSignature(void)
59 , __pSignatureAlgId(null)
63 _CertSignature::_CertSignature(const char* pSigAlgId, int len, byte* pValue)
65 SetSignature(pSigAlgId, len, pValue);
68 _CertSignature::~_CertSignature(void)
73 _CertSignature::SetSignature(const char* pSigAlgId, int len, byte* pValue)
77 if (pSigAlgId != null)
79 int algLen = strlen(pSigAlgId);
81 __pSignatureAlgId = std::unique_ptr< char[] >(new (std::nothrow) char[algLen + 1]);
82 SysTryReturn(NID_SEC_CERT, __pSignatureAlgId != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Allocating new char array failed.");
84 memcpy(__pSignatureAlgId.get(), pValue, algLen);
85 __pSignatureAlgId[algLen] = 0x00;
90 if (pValue != null && len > 0)
92 __pSignValue = std::unique_ptr< byte[] >(new (std::nothrow) byte[len + 1]);
93 SysTryReturn(NID_SEC_CERT, __pSignValue != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Allocating new byte array failed.");
95 memcpy(__pSignValue.get(), pValue, len);
96 __pSignValue[len] = 0x00;
102 _CertSignature::Verify(byte* pData, int dataLen, byte* pModulus, int keyLen, byte* pExponent, int expLen)
104 result r = E_SUCCESS;
105 std::unique_ptr< byte[] > pDataHash(null);
112 SysTryReturnResult(NID_SEC_CERT, pData != null, E_INVALID_ARG, "Invalid input data.");
113 SysTryReturnResult(NID_SEC_CERT, pExponent != null, E_INVALID_ARG, "Invalid exponent buffer.");
114 SysTryReturnResult(NID_SEC_CERT, pModulus != null, E_INVALID_ARG, "Invalid modulus buffer.");
115 SysTryReturnResult(NID_SEC_CERT, dataLen > 0, E_INVALID_ARG, "Invalid data length.");
116 SysTryReturnResult(NID_SEC_CERT, expLen > 0, E_INVALID_ARG, "Invalid exponent length.");
117 SysTryReturnResult(NID_SEC_CERT, keyLen > 0, E_INVALID_ARG, "Invalid key length.");
120 if (memcmp(__pSignatureAlgId.get(), _OID_SIG_SHA1_RSA, strlen(__pSignatureAlgId.get())) == 0)
122 rsaType = NID_sha1; // NID_sha1WithRSAEncryption; // sha1 with RSA
123 dataHashLen = SHA_DIGEST_LENGTH;
124 pDataHash = std::unique_ptr< byte[] >(new (std::nothrow) byte[SHA_DIGEST_LENGTH + 1]);
125 SysTryReturnResult(NID_SEC_CERT, pDataHash != null, E_OUT_OF_MEMORY, "Allocating new byte array failed.");
127 memset(pDataHash.get(), 0, SHA_DIGEST_LENGTH + 1);
128 //As per OpenSSL APIs, it takes input as unsigned data types
129 ret = EVP_Digest(pData, dataLen, pDataHash.get(), reinterpret_cast< unsigned int* >(&dataHashLen), EVP_sha1(), 0);
130 SysTryReturnResult(NID_SEC_CERT, ret == 1, E_SYSTEM, "Failed to create digest hash.");
132 else if (memcmp(__pSignatureAlgId.get(), _OID_SIG_MD5_RSA, strlen(__pSignatureAlgId.get())) == 0)
134 rsaType = NID_md5; // NID_md5WithRSAEncryption; //MD5 with RSA
135 dataHashLen = MD5_DIGEST_LENGTH;
136 pDataHash = std::unique_ptr< byte[] >(new (std::nothrow) byte[MD5_DIGEST_LENGTH + 1]);
137 SysTryReturnResult(NID_SEC_CERT, pDataHash != null, E_OUT_OF_MEMORY, "Allocating new byte array failed.");
139 memset(pDataHash.get(), 0, MD5_DIGEST_LENGTH + 1);
140 //As per OpenSSL APIs, it takes input as unsigned data types
141 ret = EVP_Digest(pData, dataLen, pDataHash.get(), reinterpret_cast< unsigned int* >(&dataHashLen), EVP_md5(), 0);
142 SysTryReturnResult(NID_SEC_CERT, ret == 1, E_SYSTEM, "Failed to create digest hash.");
144 else if (memcmp(__pSignatureAlgId.get(), _OID_SIG_MD2_RSA, strlen(__pSignatureAlgId.get())) == 0)
146 rsaType = NID_md2; // NID_md2WithRSAEncryption;
148 dataHashLen = MD2_DIGEST_LENGTH;
149 pDataHash = new (std::nothrow) byte[MD2_DIGEST_LENGTH + 1];
150 SysTryReturnResult(NID_SEC_CERT, pDataHash != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
152 memset(pDataHash, 0, MD2_DIGEST_LENGTH + 1);
153 //As per OpenSSL APIs, it takes input as unsigned data types
154 ret = EVP_Digest(pData, dataLen, pDataHash, &dataHashLen, EVP_md2(), 0);
155 SysTryReturnResult(NID_SEC_CERT, ret == 1, E_SYSTEM, "Failed to create digest hash.");
158 SysLogException(NID_SEC_CERT, E_FAILURE, "[E_FAILURE] Md2 with RSA algorithm not supported.");
162 else if (memcmp(__pSignatureAlgId.get(), _OID_SIG_SHA_224_RSA, strlen(__pSignatureAlgId.get())) == 0)
164 rsaType = NID_sha224; // NID_sha224WithRSAEncryption;
165 dataHashLen = SHA224_DIGEST_LENGTH;
166 pDataHash = std::unique_ptr< byte[] >(new (std::nothrow) byte[SHA224_DIGEST_LENGTH + 1]);
167 SysTryReturnResult(NID_SEC_CERT, pDataHash != null, E_OUT_OF_MEMORY, "Allocating new byte array failed.");
169 memset(pDataHash.get(), 0, SHA224_DIGEST_LENGTH + 1);
170 //As per OpenSSL APIs, it takes input as unsigned data types
171 ret = EVP_Digest(pData, dataLen, pDataHash.get(), reinterpret_cast< unsigned int* >(&dataHashLen), EVP_sha224(), 0);
172 SysTryReturnResult(NID_SEC_CERT, ret == 1, E_SYSTEM, "Failed to create digest hash.");
174 else if (memcmp(__pSignatureAlgId.get(), _OID_SIG_SHA_256_RSA, strlen(__pSignatureAlgId.get())) == 0)
176 rsaType = NID_sha256; // NID_sha256WithRSAEncryption;
177 dataHashLen = SHA256_DIGEST_LENGTH;
178 pDataHash = std::unique_ptr< byte[] >(new (std::nothrow) byte[SHA256_DIGEST_LENGTH + 1]);
179 SysTryReturnResult(NID_SEC_CERT, pDataHash != null, E_OUT_OF_MEMORY, "Allocating new byte array failed.");
181 memset(pDataHash.get(), 0, SHA256_DIGEST_LENGTH + 1);
182 //As per OpenSSL APIs, it takes input as unsigned data types
183 ret = EVP_Digest(pData, dataLen, pDataHash.get(), reinterpret_cast< unsigned int* >(&dataHashLen), EVP_sha256(), 0);
184 SysTryReturnResult(NID_SEC_CERT, ret == 1, E_SYSTEM, "Failed to create digest hash.");
186 else if (memcmp(__pSignatureAlgId.get(), _OID_SIG_SHA_384_RSA, strlen(__pSignatureAlgId.get())) == 0)
188 rsaType = NID_sha384; // NID_sha384WithRSAEncryption;
189 dataHashLen = SHA384_DIGEST_LENGTH;
190 pDataHash = std::unique_ptr< byte[] >(new (std::nothrow) byte[SHA384_DIGEST_LENGTH + 1]);
191 SysTryReturnResult(NID_SEC_CERT, pDataHash != null, E_OUT_OF_MEMORY, "Allocating new byte array failed.");
193 memset(pDataHash.get(), 0, SHA384_DIGEST_LENGTH + 1);
194 //As per OpenSSL APIs, it takes input as unsigned data types
195 ret = EVP_Digest(pData, dataLen, pDataHash.get(), reinterpret_cast< unsigned int* >(&dataHashLen), EVP_sha384(), 0);
196 SysTryReturnResult(NID_SEC_CERT, ret == 1, E_SYSTEM, "Failed to create digest hash.");
198 else if (memcmp(__pSignatureAlgId.get(), _OID_SIG_SHA_512_RSA, strlen(__pSignatureAlgId.get())) == 0)
200 rsaType = NID_sha512; // NID_sha512WithRSAEncryption;
201 dataHashLen = SHA512_DIGEST_LENGTH;
202 pDataHash = std::unique_ptr< byte[] >(new (std::nothrow) byte[SHA512_DIGEST_LENGTH + 1]);
203 SysTryReturnResult(NID_SEC_CERT, pDataHash != null, E_OUT_OF_MEMORY, "Allocating new byte array failed.");
205 memset(pDataHash.get(), 0, SHA512_DIGEST_LENGTH + 1);
206 //As per OpenSSL APIs, it takes input as unsigned data types
207 ret = EVP_Digest(pData, dataLen, pDataHash.get(), reinterpret_cast< unsigned int* >(&dataHashLen), EVP_sha512(), 0);
208 SysTryReturnResult(NID_SEC_CERT, ret == 1, E_SYSTEM, "Failed to create digest hash.");
212 SysLogException(NID_SEC_CERT, E_FAILURE, "[E_FAILURE] Signature algorithm unknown.");
216 if (pDataHash != null)
220 SysTryReturnResult(NID_SEC_CERT, pPubKey != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
222 pPubKey->n = BN_bin2bn(static_cast< const byte* >(pModulus), keyLen, pPubKey->n);
223 pPubKey->e = BN_bin2bn(static_cast< const byte* >(pExponent), expLen, pPubKey->e);
224 tempSignLen = static_cast< short >(__signLen);
225 //As per OpenSSL APIs, it takes input as unsigned data types
226 secRes = RSA_verify(rsaType, pDataHash.get(), dataHashLen, __pSignValue.get(), static_cast< unsigned int >(tempSignLen), pPubKey);
227 SysTryReturnResult(NID_SEC_CERT, secRes == 1, E_SYSTEM, "RSA verification failed.");
238 _CertSignature::GetSignatureAlgo(void)
241 return __pSignatureAlgId.release();
245 _CertSignature::GetSignatureInfo(int& sigLen)
249 return __pSignValue.get();
252 } } } //Tizen::Security::Cert