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