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