Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / resource / csdk / security / src / base64.c
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "base64.h"
22
23 /** base character of Base64. */
24 static const char g_b64TransTbl[] =
25                 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"\
26                 "ghijklmnopqrstuvwxyz0123456789+/";
27
28 /**
29  * base64 block encode function.
30  *
31  * @param in is the octet stream, max 3 byte.
32  * @param out is the Base64 encoded stream, 4 byte.
33  * @param len is the  byte-length of octet stream.
34  *
35  * @return ::B64_OK for Success, otherwise some error value.
36  */
37 static B64Result b64EncodeBlk(const uint8_t* in, char* out, uint32_t len)
38 {
39     if (NULL == in || NULL ==  out || 0 == len )
40     {
41         return B64_INVALID_PARAM;
42     }
43
44     out[0] = g_b64TransTbl[in[0] >> 2];
45
46     if (1 == len)
47     {
48         out[1] = g_b64TransTbl[((in[0] & 0x03) << 4)];
49     }
50     else
51     {
52         out[1] = g_b64TransTbl[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)];
53     }
54
55     if (2 == len)
56     {
57         out[2] = g_b64TransTbl[((in[1] & 0x0f) << 2)];
58     }
59     else if (1 < len)
60     {
61         out[2] = g_b64TransTbl[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)];
62     }
63     else
64     {
65         out[2] = '=';
66     }
67
68     if (2 < len)
69     {
70         out[3] = g_b64TransTbl[in[2] & 0x3f];
71     }
72     else
73     {
74         out[3] = '=';
75     }
76
77     return B64_OK;
78 }
79
80 B64Result b64Encode(const uint8_t* in, const size_t inLen,
81                char* outBuf, const size_t outBufSize, uint32_t* outLen)
82 {
83     if (NULL == in || 0 == inLen || NULL ==  outBuf || NULL == outLen )
84     {
85         return B64_INVALID_PARAM;
86     }
87
88     *outLen = ((inLen / 3) * 3 == inLen) ?
89               ((inLen / 3) * 4) :
90               (((inLen / 3) + 1) * 4);
91     uint32_t minBufSize = (*outLen + 1);
92     if (outBufSize < minBufSize)
93     {
94         return B64_OUTPUT_BUFFER_TOO_SMALL;
95     }
96
97     uint32_t i;
98     for (i = 0; i < inLen / 3; i++)
99     {
100         if(B64_OK != b64EncodeBlk(in + i * 3, outBuf + i * 4, 3))
101         {
102             return B64_INVALID_PARAM;
103         }
104     }
105
106     if (((size_t)i * 3) != inLen)
107     {
108         if (B64_OK != b64EncodeBlk(in + i * 3, outBuf + i * 4, inLen - i * 3))
109         {
110             return B64_INVALID_PARAM;
111         }
112     }
113
114     outBuf[*outLen] = '\0';
115
116     return B64_OK;
117 }
118
119 /**
120  * Get decoded value.
121  *
122  * @param c is the Base64 encoded character.
123  *
124  * @return decoded value, 6-bit.
125  */
126 static uint32_t b64GetVal(char c)
127 {
128     if (('A' <= c) && ('Z' >= c))
129     {
130         return c - 'A';
131     }
132     else if (('a' <= c) && ('z' >= c))
133     {
134         return c - 'a' + 26;
135     }
136     else if (('0' <= c) && ('9' >= c))
137     {
138         return c - '0' + 52;
139     }
140     else if ('+' == c)
141     {
142         return 62;
143     }
144     else if ('/' == c)
145     {
146         return 63;
147     }
148     else if ('=' == c)
149     {
150         return 0;
151     }
152
153     return 0;
154 }
155
156 /**
157  * Base64 block decode function.
158  *
159  * @param in is the Base64 encoded stream, 4 bytes.
160  * @param out is the Octet stream, 3 bytes.
161  *
162  * @return ::B64_OK for Success, otherwise some error value.
163  */
164 static B64Result b64DecodeBlk(const char* in, uint8_t* out)
165 {
166     if (NULL == in || NULL == out)
167     {
168         return B64_INVALID_PARAM;
169     }
170
171     uint32_t val = (b64GetVal(in[0]) << 18) | (b64GetVal(in[1]) << 12) |
172           (b64GetVal(in[2]) << 6) | (b64GetVal(in[3]));
173
174     out[0] = (val >> 16) & 0xff;
175
176     if ('=' != in[2])
177     {
178         out[1] = (val >> 8) & 0xff;
179     }
180     if ('=' != in[3])
181     {
182         out[2] = val & 0xff;
183     }
184
185     return B64_OK;
186 }
187
188 B64Result b64Decode(const char* in, const size_t inLen,
189                uint8_t* outBuf, size_t outBufSize, uint32_t* outLen)
190 {
191     if (NULL == in || 0 == inLen || 0 != (inLen & 0x03) || NULL == outBuf || NULL == outLen)
192     {
193         return B64_INVALID_PARAM;
194     }
195
196     *outLen = (inLen / 4) * 3;
197     uint32_t minBufSize = (inLen / 4) * 3;
198     if ('=' == in[inLen - 1])
199     {
200         minBufSize--;
201         (*outLen)--;
202     }
203     if ('=' == in[inLen - 2])
204     {
205         minBufSize--;
206         (*outLen)--;
207     }
208     if (outBufSize < minBufSize)
209     {
210         return B64_OUTPUT_BUFFER_TOO_SMALL;
211     }
212
213     for (uint32_t i = 0; i < inLen / 4; i++)
214     {
215         if(B64_OK != b64DecodeBlk(in + i * 4, outBuf + i * 3))
216         {
217             return B64_INVALID_PARAM;
218         }
219     }
220
221     return B64_OK;
222 }
223