Fix the Prevent problems
[platform/core/connectivity/smartcard-service.git] / common / ISO7816BERTLV.cpp
1 /*
2  * Copyright (c) 2012, 2013 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 /* standard library header */
18 #include <stdio.h>
19 #include <string.h>
20
21 /* SLP library header */
22
23 /* local header */
24 #include "ISO7816BERTLV.h"
25
26 namespace smartcard_service_api
27 {
28         ISO7816BERTLV::ISO7816BERTLV() : TLVHelper(), firstByte(0), tagClass(0),
29                 encoding(0)
30         {
31         }
32
33         ISO7816BERTLV::ISO7816BERTLV(TLVHelper *parent) : TLVHelper(parent),
34                 firstByte(0), tagClass(0), encoding(0)
35         {
36         }
37
38         ISO7816BERTLV::ISO7816BERTLV(const ByteArray &array) : TLVHelper(array),
39                         firstByte(0), tagClass(0), encoding(0)
40         {
41         }
42
43         ISO7816BERTLV::ISO7816BERTLV(const ByteArray &array, TLVHelper *parent) :
44                 TLVHelper(array, parent), firstByte(0), tagClass(0), encoding(0)
45         {
46         }
47
48         ISO7816BERTLV::~ISO7816BERTLV()
49         {
50                 if (childTLV != NULL)
51                 {
52                         delete childTLV;
53                         childTLV = NULL;
54                 }
55         }
56
57         int ISO7816BERTLV::decodeTag(const unsigned char *buffer)
58         {
59                 /* 0x00 is invalid tag value */
60                 if (buffer[0] == 0x00)
61                 {
62                         return -1;
63                 }
64
65                 /* first byte */
66                 tagClass = (buffer[0] & 0xC0) >> 6;
67                 encoding = (buffer[0] & 0x20) >> 5;
68
69                 currentT = buffer[0];
70
71                 if ((buffer[0] & 0x1F) < 0x1F)
72                 {
73                         return 1;
74                 }
75
76                 /* second byte */
77                 currentT = (currentT << 8) | buffer[1];
78                 if (buffer[1] & 0x80)
79                 {
80                         /* third byte */
81                         if (buffer[2] & 0x80)
82                         {
83                                 return -1;
84                         }
85
86                         currentT = (currentT << 8) | buffer[2];
87
88                         return 3;
89                 }
90
91                 return 2;
92         }
93
94         int ISO7816BERTLV::decodeLength(const unsigned char *buffer)
95         {
96                 if (buffer[0] & 0x80)
97                 {
98                         uint8_t count = (buffer[0] & 0x7F);
99                         uint8_t i;
100
101                         /* count will be less than 5 */
102                         if (count > 4)
103                                 return -1;
104
105                         count++;
106
107                         for (i = 1; i < count; i++)
108                         {
109                                 /* if big endian */
110                                 currentL = (currentL << 8) | buffer[i];
111
112                                 /* if little endian */
113                                 /* currentL = currentL | (buffer[i] << (8 * (i - 1))); */
114                         }
115
116                         return count;
117                 }
118                 else
119                 {
120                         currentL = buffer[0];
121
122                         return 1;
123                 }
124         }
125
126         int ISO7816BERTLV::decodeValue(const unsigned char *buffer)
127         {
128                 if (currentL == 0)
129                         return 0;
130
131                 currentV.assign(buffer, currentL);
132
133                 return currentL;
134         }
135
136         unsigned int ISO7816BERTLV::getClass() const
137         {
138                 return tagClass;
139         }
140
141         unsigned int ISO7816BERTLV::getEncoding() const
142         {
143                 return encoding;
144         }
145
146         const ByteArray ISO7816BERTLV::encode(unsigned int tagClass, unsigned int encoding, unsigned int tag, const ByteArray &buffer)
147         {
148                 unsigned char temp_tag[3] = { 0, };
149                 unsigned char temp_tag_len = 0;
150                 unsigned char temp_len[5] = { 0, };
151                 unsigned char temp_len_len = 0;
152                 ByteArray result;
153                 unsigned int total_len = 0;
154                 unsigned int current = 0;
155                 unsigned char *temp_buffer = NULL;
156
157                 /* add tag's length */
158                 if (tag > 0x7FFF)
159                         return result;
160
161                 temp_tag[0] = (tagClass << 6) | (encoding << 5);
162
163                 if (tag < 0x1F)
164                 {
165                         temp_tag[0] |= tag;
166                         temp_tag_len = 1;
167                 }
168                 else
169                 {
170                         temp_tag[0] |= 0x1F;
171
172                         if (tag < 0x80)
173                         {
174                                 temp_tag[1] = tag;
175
176                                 temp_tag_len = 2;
177                         }
178                         else
179                         {
180                                 temp_tag[1] = (tag & 0x000000FF);
181                                 temp_tag[2] = (tag & 0x0000FF00);
182
183                                 temp_tag_len = 3;
184                         }
185                 }
186
187                 total_len += temp_tag_len;
188
189                 /* add length's length */
190                 if (buffer.size() < 128)
191                 {
192                         temp_len[0] = buffer.size();
193
194                         temp_len_len = 1;
195                 }
196                 else
197                 {
198                         temp_len[0] = 0x80;
199                         temp_len_len = 1;
200
201                         if (buffer.size() > 0x00FFFFFF)
202                         {
203                                 temp_len[4] = (buffer.size() & 0xFF000000) >> 24;
204                                 temp_len_len++;
205                         }
206
207                         if (buffer.size() > 0x0000FFFF)
208                         {
209                                 temp_len[3] = (buffer.size() & 0x00FF0000) >> 16;
210                                 temp_len_len++;
211                         }
212
213                         if (buffer.size() > 0x000000FF)
214                         {
215                                 temp_len[2] = (buffer.size() & 0x0000FF00) >> 8;
216                                 temp_len_len++;
217                         }
218
219                         temp_len[1] = buffer.size() & 0x000000FF;
220                         temp_len_len++;
221
222                         temp_len[0] |= temp_len_len;
223                 }
224
225                 /* add buffer's length */
226                 total_len += buffer.size();
227
228                 /* alloc new buffer */
229                 temp_buffer = new unsigned char[total_len];
230                 if (temp_buffer == NULL)
231                 {
232                         return result;
233                 }
234                 memset(temp_buffer, 0, total_len);
235
236                 /* fill tag */
237                 memcpy(temp_buffer + current, temp_tag, temp_tag_len);
238                 current += temp_tag_len;
239
240                 /* fill length */
241                 memcpy(temp_buffer + current, temp_len, temp_len_len);
242                 current += temp_len_len;
243
244                 /* fill value */
245                 if (buffer.size() > 0)
246                         memcpy(temp_buffer + current, buffer.getBuffer(), buffer.size());
247
248                 result.assign(temp_buffer, total_len);
249
250                 delete []temp_buffer;
251
252                 return result;
253         }
254
255         const ByteArray ISO7816BERTLV::encode(unsigned int tagClass, unsigned int encoding, unsigned int tag, unsigned char *buffer, unsigned int length)
256         {
257                 return encode(tagClass, encoding, tag, ByteArray(buffer, length));
258         }
259
260         TLVHelper *ISO7816BERTLV::getChildTLV(const ByteArray &data)
261         {
262                 if (childTLV != NULL)
263                 {
264                         delete childTLV;
265                         childTLV = NULL;
266                 }
267                 childTLV = new ISO7816BERTLV(data, this);
268
269                 return (TLVHelper *)childTLV;
270         }
271
272 } /* namespace smartcard_service_api */