Change the level of datacontrol.consumer privilege from partner to public
[platform/framework/native/appfw.git] / src / security / cert / FSecCert_CertSignature.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                FSecCert_CertSignature.cpp
19 // @brief               This file contains implementation of X509 Certificate signature.
20 //
21
22 #undef USE_MD2
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <error.h>
27 #include <memory.h>
28 #include <new>
29 #include <sys/stat.h>
30 #include <assert.h>
31 #include <dirent.h>
32 #include <openssl/objects.h>
33 #include <openssl/obj_mac.h>
34 #include <openssl/sha.h>
35 #include <openssl/md5.h>
36 #ifdef USE_MD2
37 #include <openssl/md2.h>
38 #endif
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"
47
48
49 using namespace Tizen::Base;
50
51 namespace Tizen { namespace Security { namespace Cert
52 {
53
54 // _CertSignature class
55
56 _CertSignature::_CertSignature(void)
57         : __signLen(0)
58         , __pSignValue(null)
59         , __pSignatureAlgId(null)
60 {
61 }
62
63 _CertSignature::_CertSignature(const char* pSigAlgId, int len, byte* pValue)
64 {
65         SetSignature(pSigAlgId, len, pValue);
66 }
67
68 _CertSignature::~_CertSignature(void)
69 {
70 }
71
72 void
73 _CertSignature::SetSignature(const char* pSigAlgId, int len, byte* pValue)
74 {
75         ClearLastResult();
76
77         if (pSigAlgId != null)
78         {
79                 int algLen = strlen(pSigAlgId);
80
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.");
83
84                 memcpy(__pSignatureAlgId.get(), pValue, algLen);
85                 __pSignatureAlgId[algLen] = 0x00;
86         }
87
88         __signLen = 0;
89
90         if (pValue != null && len > 0)
91         {
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.");
94
95                 memcpy(__pSignValue.get(), pValue, len);
96                 __pSignValue[len] = 0x00;
97                 __signLen = len;
98         }
99 }
100
101 result
102 _CertSignature::Verify(byte* pData, int dataLen, byte* pModulus, int keyLen, byte* pExponent, int expLen)
103 {
104         result r = E_SUCCESS;
105         std::unique_ptr< byte[] > pDataHash(null);
106         int dataHashLen = 0;
107         int secRes = 0;
108         int rsaType = 0;
109         int ret = 0;
110         int tempSignLen = 0;
111
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.");
118
119
120         if (memcmp(__pSignatureAlgId.get(), _OID_SIG_SHA1_RSA, strlen(__pSignatureAlgId.get())) == 0)
121         {
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.");
126
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.");
131         }
132         else if (memcmp(__pSignatureAlgId.get(), _OID_SIG_MD5_RSA, strlen(__pSignatureAlgId.get())) == 0)
133         {
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.");
138
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.");
143         }
144         else if (memcmp(__pSignatureAlgId.get(), _OID_SIG_MD2_RSA, strlen(__pSignatureAlgId.get())) == 0)
145         {
146                 rsaType = NID_md2; // NID_md2WithRSAEncryption;
147 #ifdef _USE_MD2
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.");
151
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.");
156
157 #else
158                 SysLogException(NID_SEC_CERT, E_FAILURE, "[E_FAILURE] Md2 with RSA algorithm not supported.");
159                 return E_SYSTEM;
160 #endif
161         }
162         else if (memcmp(__pSignatureAlgId.get(), _OID_SIG_SHA_224_RSA, strlen(__pSignatureAlgId.get())) == 0)
163         {
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.");
168
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.");
173         }
174         else if (memcmp(__pSignatureAlgId.get(), _OID_SIG_SHA_256_RSA, strlen(__pSignatureAlgId.get())) == 0)
175         {
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.");
180
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.");
185         }
186         else if (memcmp(__pSignatureAlgId.get(), _OID_SIG_SHA_384_RSA, strlen(__pSignatureAlgId.get())) == 0)
187         {
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.");
192
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.");
197         }
198         else if (memcmp(__pSignatureAlgId.get(), _OID_SIG_SHA_512_RSA, strlen(__pSignatureAlgId.get())) == 0)
199         {
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.");
204
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.");
209         }
210         else
211         {
212                 SysLogException(NID_SEC_CERT, E_FAILURE, "[E_FAILURE] Signature algorithm unknown.");
213                 return E_SYSTEM;
214         }
215
216         if (pDataHash != null)
217         {
218                 RSA* pPubKey = null;
219                 pPubKey = RSA_new();
220                 SysTryReturnResult(NID_SEC_CERT, pPubKey != null, E_OUT_OF_MEMORY, "Failed to allocate memory.");
221
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.");
228
229                 r = E_SUCCESS;
230
231                 RSA_free(pPubKey);
232         }
233
234         return r;
235 }
236
237 char*
238 _CertSignature::GetSignatureAlgo(void)
239 {
240         ClearLastResult();
241         return __pSignatureAlgId.release();
242 }
243
244 byte*
245 _CertSignature::GetSignatureInfo(int& sigLen)
246 {
247         ClearLastResult();
248         sigLen = __signLen;
249         return __pSignValue.get();
250 }
251
252 } } } //Tizen::Security::Cert