Imported Upstream version 0.9.2
[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] in  octet stream, max 3 byte
32  * @param[out] out  base64 encoded stream, 4 byte
33  * @param[in] len  byte-length of in
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 /**
81  * Encode the plain message in base64.
82  *
83  * @param[in] in  Plain message
84  * @param[in] inLen  Byte length of 'in'
85  * @param[in,out] outBuf Output buffer
86  *                Base64 encoded message will be written into 'out'
87  *                NOTE : This method adds a NULL to the string configuration
88  * @param[in] outBufSize Size of output buffer
89  * @param[out] outLen  Byte length of encoded message
90  *
91  * @return  B64_OK for Success, otherwise some error value
92 */
93 B64Result b64Encode(const uint8_t* in, const size_t inLen,
94                char* outBuf, const size_t outBufSize, uint32_t* outLen)
95 {
96     uint32_t i;
97     uint32_t minBufSize;
98
99     if (NULL == in || 0 == inLen || NULL ==  outBuf || NULL == outLen )
100     {
101         return B64_INVALID_PARAM;
102     }
103
104     *outLen = ((inLen / 3) * 3 == inLen) ?
105               ((inLen / 3) * 4) :
106               (((inLen / 3) + 1) * 4);
107     minBufSize = (*outLen + 1);
108     if(outBufSize < minBufSize)
109     {
110         return B64_OUTPUT_BUFFER_TOO_SMALL;
111     }
112
113     for (i = 0; i < inLen / 3; i++)
114     {
115         if(B64_OK != b64EncodeBlk(in + i * 3, outBuf + i * 4, 3))
116         {
117             return B64_INVALID_PARAM;
118         }
119     }
120
121     if (i * 3 != inLen)
122     {
123         if(B64_OK != b64EncodeBlk(in + i * 3, outBuf + i * 4, inLen - i * 3))
124         {
125             return B64_INVALID_PARAM;
126         }
127     }
128
129     outBuf[*outLen] = '\0';
130
131     return B64_OK;
132 }
133
134 /**
135  * Get decoded value
136  *
137  * @param[in] c  Base64 encoded charactor
138  *
139  * @return decoded value, 6-bit
140  */
141 static uint32_t b64GetVal(char c)
142 {
143     if (('A' <= c) && ('Z' >= c))
144     {
145         return c - 'A';
146     }
147     else if (('a' <= c) && ('z' >= c))
148     {
149         return c - 'a' + 26;
150     }
151     else if (('0' <= c) && ('9' >= c))
152     {
153         return c - '0' + 52;
154     }
155     else if ('+' == c)
156     {
157         return 62;
158     }
159     else if ('/' == c)
160     {
161         return 63;
162     }
163     else if ('=' == c)
164     {
165         return 0;
166     }
167
168     return 0;
169 }
170
171 /**
172  * base64 block decode function
173  *
174  * @param[in] in  Base64 encoded stream, 4 bytes
175  * @param[out] out  Octet stream, 3 bytes
176  *
177  * @return  B64_OK for Success, otherwise some error value
178  */
179 static B64Result b64DecodeBlk(const char* in, uint8_t* out)
180 {
181     uint32_t val;
182
183     if(NULL == in || NULL == out)
184     {
185         return B64_INVALID_PARAM;
186     }
187
188     val = (b64GetVal(in[0]) << 18) | (b64GetVal(in[1]) << 12) |
189           (b64GetVal(in[2]) << 6) | (b64GetVal(in[3]));
190
191     out[0] = (val >> 16) & 0xff;
192
193     if ('=' != in[2])
194     {
195         out[1] = (val >> 8) & 0xff;
196     }
197     if ('=' != in[3])
198     {
199         out[2] = val & 0xff;
200     }
201
202     return B64_OK;
203 }
204
205 /**
206  * Decode the encoded message in base64.
207  *
208  * @param[in] in  Base64 encoded message
209  * @param[in] inLen  Byte lenth of 'in'
210  * @param[in, out] outBuf  Output buffer
211  *                 Base64 decoded message will be written into 'out'
212  * @param[in] outBufSize Size of output buffer
213  * @param[out] outLen  Byte length of decoded message
214  *
215  * @return  B64_OK for Success, otherwise some error value
216  */
217 B64Result b64Decode(const char* in, const size_t inLen,
218                uint8_t* outBuf, size_t outBufSize, uint32_t* outLen)
219 {
220     uint32_t i;
221     uint32_t minBufSize;
222
223     if (NULL == in || 0 == inLen || 0 != (inLen & 0x03) || NULL == outBuf || NULL == outLen)
224     {
225         return B64_INVALID_PARAM;
226     }
227
228     *outLen = (inLen / 4) * 3;
229     minBufSize = (inLen / 4) * 3;
230     if('=' == in[inLen - 1])
231     {
232         minBufSize--;
233         (*outLen)--;
234     }
235     if('=' == in[inLen - 2])
236     {
237         minBufSize--;
238         (*outLen)--;
239     }
240     if(outBufSize < minBufSize)
241     {
242         return B64_OUTPUT_BUFFER_TOO_SMALL;
243     }
244
245     for (i = 0; i < inLen / 4; i++)
246     {
247         if(B64_OK != b64DecodeBlk(in + i * 4, outBuf + i * 3))
248         {
249             return B64_INVALID_PARAM;
250         }
251     }
252
253     return B64_OK;
254 }
255