7ec4869cbb9f260c506b8284fdaa8330d708489c
[platform/core/security/cert-svc.git] / vcore / src / vcore / CryptoHash.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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  * @file        wrt_crypto_hash.cpp
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of cryptographic hasing algorithms
21  */
22 #include <vcore/CryptoHash.h>
23
24 #include <openssl/bio.h>
25 #include <openssl/ssl.h>
26 #include <openssl/evp.h>
27 #include <stdexcept>
28
29 #include <vcore/Base64.h>
30
31 namespace ValidationCore
32 {
33 namespace Crypto
34 {
35 namespace Hash
36 {
37 namespace // anonymous
38 {
39 const size_t HASH_DIGEST_STREAM_FEED_SIZE = 1024;
40 } // namespace anonymous
41
42 Base::Base()
43     : m_hasFinal(false)
44 {
45 }
46
47 Base::~Base()
48 {
49 }
50
51 void Base::Append(const char *buffer)
52 {
53     if (m_hasFinal)
54         VcoreThrowMsg(Crypto::Hash::OutOfSequence,
55                       "Cannot append hash after final update!");
56
57     HashUpdate(buffer, strlen(buffer));
58 }
59
60 void Base::Append(const char *buffer, size_t bufferSize)
61 {
62     if (m_hasFinal)
63         VcoreThrowMsg(Crypto::Hash::OutOfSequence,
64                       "Cannot append hash after final update!");
65
66     HashUpdate(buffer, bufferSize);
67 }
68
69 void Base::Append(const std::string &buffer)
70 {
71     if (m_hasFinal)
72         VcoreThrowMsg(Crypto::Hash::OutOfSequence,
73                  "Cannot append hash after final update!");
74
75     HashUpdate(buffer.c_str(), buffer.size());
76 }
77
78 void Base::Append(std::istream &stream)
79 {
80     if (m_hasFinal)
81         VcoreThrowMsg(Crypto::Hash::OutOfSequence,
82                  "Cannot append hash after final update!");
83
84     char buffer[HASH_DIGEST_STREAM_FEED_SIZE];
85
86     do
87     {
88         stream.read(buffer, HASH_DIGEST_STREAM_FEED_SIZE);
89
90         if (stream.gcount() > 0)
91             Append(static_cast<void *>(buffer), static_cast<size_t>(stream.gcount()));
92
93     } while (stream.gcount() > 0);
94 }
95
96 void Base::Append(const void *data, size_t dataSize)
97 {
98     if (m_hasFinal)
99         VcoreThrowMsg(Crypto::Hash::OutOfSequence,
100                  "Cannot append hash after final update!");
101
102     HashUpdate(data, dataSize);
103 }
104
105 void Base::Finish()
106 {
107     if (m_hasFinal)
108         return;
109
110     // Finalize hashing algorithm
111     m_raw = HashFinal();
112
113     // Convert to base 64 string
114     Base64Encoder encoder;
115     encoder.reset();
116     encoder.append(std::string(m_raw.begin(), m_raw.end()));
117     encoder.finalize();
118     m_base64StringHash = encoder.get();
119
120     m_hasFinal = true;
121 }
122
123 std::string Base::ToBase64String() const
124 {
125     return m_base64StringHash;
126 }
127
128 Raw Base::GetHash() const
129 {
130     return m_raw;
131 }
132
133 OpenSSL::OpenSSL(const EVP_MD *evpMd)
134     : m_finalized(false)
135 {
136     EVP_MD_CTX_init(&m_context);
137
138     if (EVP_DigestInit(&m_context, evpMd) != 1)
139         VcoreThrowMsg(Crypto::Hash::AppendFailed,
140                       "EVP_DigestInit failed!");
141 }
142
143 OpenSSL::~OpenSSL()
144 {
145     if (!m_finalized)
146     {
147         // Just clean context
148         EVP_MD_CTX_cleanup(&m_context);
149         m_finalized = true;
150     }
151 }
152
153 void OpenSSL::HashUpdate(const void *data, size_t dataSize)
154 {
155     if (m_finalized)
156         VcoreThrowMsg(Crypto::Hash::AppendFailed,
157                       "OpenSSLHash hash already finalized!");
158
159     if (EVP_DigestUpdate(&m_context, data, dataSize) != 1)
160         VcoreThrowMsg(Crypto::Hash::AppendFailed,
161                       "EVP_DigestUpdate failed!");
162 }
163
164 Hash::Raw OpenSSL::HashFinal()
165 {
166     if (m_finalized)
167         VcoreThrowMsg(Crypto::Hash::AppendFailed,
168                  "OpenSSLHash hash already finalized!");
169
170     unsigned char hash[EVP_MAX_MD_SIZE] = {};
171     unsigned int hashLength;
172
173     // Also cleans context
174     if (EVP_DigestFinal(&m_context, hash, &hashLength) != 1)
175         VcoreThrowMsg(Crypto::Hash::AppendFailed,
176                       "EVP_DigestFinal failed!");
177
178     m_finalized = true;
179     return Raw(hash, hash + hashLength);
180 }
181
182 } // namespace Hash
183 } // namespace Crypto
184 } // namespace ValidationCore