f184505785e0882e16aa899679d7b3782dd17a16
[platform/core/security/key-manager.git] / src / manager / common / base64.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 #include <algorithm>
17 #include <memory>
18
19 #include <string.h>
20 #include <openssl/bio.h>
21 #include <openssl/evp.h>
22 #include <openssl/buffer.h>
23
24 #include <dpl/log/log.h>
25
26 #include <base64.h>
27
28 namespace CKM {
29
30 Base64Encoder::Base64Encoder() :
31     m_b64(0),
32     m_bmem(0),
33     m_finalized(false)
34 {
35 }
36
37 void Base64Encoder::append(const RawBuffer &data)
38 {
39     if (m_finalized) {
40         LogWarning("Already finalized.");
41         ThrowMsg(Exception::AlreadyFinalized, "Already finalized");
42     }
43
44     if (!m_b64) {
45         reset();
46     }
47     BIO_write(m_b64, data.data(), data.size());
48 }
49
50 void Base64Encoder::finalize()
51 {
52     if (m_finalized) {
53         LogWarning("Already finalized.");
54         ThrowMsg(Exception::AlreadyFinalized, "Already finalized.");
55     }
56     m_finalized = true;
57     (void)BIO_flush(m_b64);
58 }
59
60 RawBuffer Base64Encoder::get()
61 {
62     if (!m_finalized) {
63         LogWarning("Not finalized");
64         ThrowMsg(Exception::NotFinalized, "Not finalized");
65     }
66     BUF_MEM *bptr = 0;
67     BIO_get_mem_ptr(m_b64, &bptr);
68     if (bptr == 0) {
69         LogError("Bio internal error");
70         ThrowMsg(Exception::InternalError, "Bio internal error");
71     }
72
73     if (bptr->length > 0) {
74         return RawBuffer(bptr->data, bptr->data + bptr->length);
75     }
76     return RawBuffer();
77 }
78
79 void Base64Encoder::reset()
80 {
81     m_finalized = false;
82     BIO_free_all(m_b64);
83     m_b64 = BIO_new(BIO_f_base64());
84     m_bmem = BIO_new(BIO_s_mem());
85     if (!m_b64 || !m_bmem) {
86         LogError("Error during allocation memory in BIO");
87         ThrowMsg(Exception::InternalError,
88                  "Error during allocation memory in BIO");
89     }
90     BIO_set_flags(m_b64, BIO_FLAGS_BASE64_NO_NL);
91     m_b64 = BIO_push(m_b64, m_bmem);
92 }
93
94 Base64Encoder::~Base64Encoder()
95 {
96     BIO_free_all(m_b64);
97 }
98
99 Base64Decoder::Base64Decoder() :
100     m_finalized(false)
101 {
102 }
103
104 void Base64Decoder::append(const RawBuffer &data)
105 {
106     if (m_finalized) {
107         LogWarning("Already finalized.");
108         ThrowMsg(Exception::AlreadyFinalized, "Already finalized.");
109     }
110     std::copy(data.begin(), data.end(), std::back_inserter(m_input));
111 }
112
113 static bool whiteCharacter(char a)
114 {
115     return a == '\n';
116 }
117
118 bool Base64Decoder::finalize()
119 {
120     if (m_finalized) {
121         LogWarning("Already finalized.");
122         ThrowMsg(Exception::AlreadyFinalized, "Already finalized.");
123     }
124
125     m_finalized = true;
126
127     m_input.erase(std::remove_if(m_input.begin(),
128                                  m_input.end(),
129                                  whiteCharacter),
130                   m_input.end());
131
132     for (size_t i = 0; i<m_input.size(); ++i) {
133         if (isalnum(m_input[i])
134             || m_input[i] == '+'
135             || m_input[i] == '/'
136             || m_input[i] == '=')
137         {
138             continue;
139         }
140         LogError("Base64 input contains illegal chars: " << m_input[i]);
141         return false;
142     }
143
144     BIO *b64, *bmem;
145     size_t len = m_input.size();
146
147     RawBuffer buffer(len);
148
149     if (!buffer.data()) {
150         LogError("Error in malloc.");
151         ThrowMsg(Exception::InternalError, "Error in malloc.");
152     }
153
154     memset(buffer.data(), 0, buffer.size());
155     b64 = BIO_new(BIO_f_base64());
156     if (!b64) {
157         LogError("Couldn't create BIO object.");
158         ThrowMsg(Exception::InternalError, "Couldn't create BIO object.");
159     }
160     BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
161     RawBuffer tmp(m_input);
162     m_input.clear();
163
164     bmem = BIO_new_mem_buf(tmp.data(), len);
165
166     if (!bmem) {
167         BIO_free(b64);
168         LogError("Internal error in BIO");
169         ThrowMsg(Exception::InternalError, "Internal error in BIO");
170     }
171
172     bmem = BIO_push(b64, bmem);
173
174     if (!bmem) {
175         BIO_free(b64);
176         LogError("Internal error in BIO");
177         ThrowMsg(Exception::InternalError, "Internal error in BIO");
178     }
179
180     int readlen = BIO_read(bmem, buffer.data(), buffer.size());
181     m_output.clear();
182
183     bool status = true;
184
185     if (readlen > 0) {
186         buffer.resize(readlen);
187         m_output = std::move(buffer);
188     } else {
189         status = false;
190     }
191
192     BIO_free_all(bmem);
193     return status;
194 }
195
196 RawBuffer Base64Decoder::get() const
197 {
198     if (!m_finalized) {
199         LogWarning("Not finalized.");
200         ThrowMsg(Exception::NotFinalized, "Not finalized");
201     }
202     return m_output;
203 }
204
205 void Base64Decoder::reset()
206 {
207     m_finalized = false;
208     m_input.clear();
209     m_output.clear();
210 }
211
212 } // namespace CKM