Apply coding rule
[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                 uint8_t offset = 0;
97                 uint8_t count = buffer[offset];
98
99                 offset++;
100
101                 if (count & 0x80) {
102                         uint8_t i;
103
104                         count &= ~0x80;
105
106                         /* count will be less than 5 */
107                         if (count > 4)
108                                 return -1;
109
110                         for (i = 0; i < count; i++) {
111                                 /* if big endian */
112                                 currentL = (currentL << 8) | buffer[offset + i];
113
114                                 /* if little endian */
115                                 /* currentL = currentL | (buffer[offset + i] << (8 * (i - 1))); */
116                         }
117
118                         offset += i;
119                 } else {
120                         currentL = count;
121                 }
122
123                 return offset;
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                         temp_tag[0] |= tag;
165                         temp_tag_len = 1;
166                 } else {
167                         temp_tag[0] |= 0x1F;
168
169                         if (tag < 0x80) {
170                                 temp_tag[1] = tag;
171
172                                 temp_tag_len = 2;
173                         } else {
174                                 temp_tag[1] = (tag & 0x000000FF);
175                                 temp_tag[2] = (tag & 0x0000FF00);
176
177                                 temp_tag_len = 3;
178                         }
179                 }
180
181                 total_len += temp_tag_len;
182
183                 /* add length's length */
184                 if (buffer.size() < 128) {
185                         temp_len[0] = buffer.size();
186
187                         temp_len_len = 1;
188                 } else {
189                         temp_len[0] = 0x80;
190                         temp_len_len = 1;
191
192                         if (buffer.size() > 0x00FFFFFF)
193                         {
194                                 temp_len[4] = (buffer.size() & 0xFF000000) >> 24;
195                                 temp_len_len++;
196                         }
197
198                         if (buffer.size() > 0x0000FFFF)
199                         {
200                                 temp_len[3] = (buffer.size() & 0x00FF0000) >> 16;
201                                 temp_len_len++;
202                         }
203
204                         if (buffer.size() > 0x000000FF)
205                         {
206                                 temp_len[2] = (buffer.size() & 0x0000FF00) >> 8;
207                                 temp_len_len++;
208                         }
209
210                         temp_len[1] = buffer.size() & 0x000000FF;
211                         temp_len_len++;
212
213                         temp_len[0] |= temp_len_len;
214                 }
215
216                 /* add buffer's length */
217                 total_len += buffer.size();
218
219                 /* alloc new buffer */
220                 temp_buffer = new unsigned char[total_len];
221                 if (temp_buffer == NULL)
222                 {
223                         return result;
224                 }
225                 memset(temp_buffer, 0, total_len);
226
227                 /* fill tag */
228                 memcpy(temp_buffer + current, temp_tag, temp_tag_len);
229                 current += temp_tag_len;
230
231                 /* fill length */
232                 memcpy(temp_buffer + current, temp_len, temp_len_len);
233                 current += temp_len_len;
234
235                 /* fill value */
236                 if (buffer.size() > 0)
237                         memcpy(temp_buffer + current, buffer.getBuffer(), buffer.size());
238
239                 result.assign(temp_buffer, total_len);
240
241                 delete []temp_buffer;
242
243                 return result;
244         }
245
246         const ByteArray ISO7816BERTLV::encode(unsigned int tagClass, unsigned int encoding, unsigned int tag, unsigned char *buffer, unsigned int length)
247         {
248                 return encode(tagClass, encoding, tag, ByteArray(buffer, length));
249         }
250
251         TLVHelper *ISO7816BERTLV::getChildTLV(const ByteArray &data)
252         {
253                 if (childTLV != NULL)
254                 {
255                         delete childTLV;
256                         childTLV = NULL;
257                 }
258                 childTLV = new ISO7816BERTLV(data, this);
259
260                 return (TLVHelper *)childTLV;
261         }
262
263 } /* namespace smartcard_service_api */