]> git.ipfire.org Git - people/ms/strongswan.git/blob - linux/lib/libfreeswan/datatot.c
- import of strongswan-2.7.0
[people/ms/strongswan.git] / linux / lib / libfreeswan / datatot.c
1 /*
2 * convert from binary data (e.g. key) to text form
3 * Copyright (C) 2000 Henry Spencer.
4 *
5 * This library is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU Library General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
9 *
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 * License for more details.
14 *
15 * RCSID $Id: datatot.c,v 1.1 2004/03/15 20:35:26 as Exp $
16 */
17 #include "internal.h"
18 #include "freeswan.h"
19
20 static void convert(const char *src, size_t nreal, int format, char *out);
21
22 /*
23 - datatot - convert data bytes to text
24 */
25 size_t /* true length (with NUL) for success */
26 datatot(src, srclen, format, dst, dstlen)
27 const char *src;
28 size_t srclen;
29 int format; /* character indicating what format */
30 char *dst; /* need not be valid if dstlen is 0 */
31 size_t dstlen;
32 {
33 size_t inblocksize; /* process this many bytes at a time */
34 size_t outblocksize; /* producing this many */
35 size_t breakevery; /* add a _ every this many (0 means don't) */
36 size_t sincebreak; /* output bytes since last _ */
37 char breakchar; /* character used to break between groups */
38 char inblock[10]; /* enough for any format */
39 char outblock[10]; /* enough for any format */
40 char fake[1]; /* fake output area for dstlen == 0 */
41 size_t needed; /* return value */
42 char *stop; /* where the terminating NUL will go */
43 size_t ntodo; /* remaining input */
44 size_t nreal;
45 char *out;
46 char *prefix;
47
48 breakevery = 0;
49 breakchar = '_';
50
51 switch (format) {
52 case 0:
53 case 'h':
54 format = 'x';
55 breakevery = 8;
56 /* FALLTHROUGH */
57 case 'x':
58 inblocksize = 1;
59 outblocksize = 2;
60 prefix = "0x";
61 break;
62 case ':':
63 format = 'x';
64 breakevery = 2;
65 breakchar = ':';
66 /* FALLTHROUGH */
67 case 16:
68 inblocksize = 1;
69 outblocksize = 2;
70 prefix = "";
71 format = 'x';
72 break;
73 case 's':
74 inblocksize = 3;
75 outblocksize = 4;
76 prefix = "0s";
77 break;
78 case 64: /* beware, equals ' ' */
79 inblocksize = 3;
80 outblocksize = 4;
81 prefix = "";
82 format = 's';
83 break;
84 default:
85 return 0;
86 break;
87 }
88 assert(inblocksize < sizeof(inblock));
89 assert(outblocksize < sizeof(outblock));
90 assert(breakevery % outblocksize == 0);
91
92 if (srclen == 0)
93 return 0;
94 ntodo = srclen;
95
96 if (dstlen == 0) { /* dispose of awkward special case */
97 dst = fake;
98 dstlen = 1;
99 }
100 stop = dst + dstlen - 1;
101
102 nreal = strlen(prefix);
103 needed = nreal; /* for starters */
104 if (dstlen <= nreal) { /* prefix won't fit */
105 strncpy(dst, prefix, dstlen - 1);
106 dst += dstlen - 1;
107 } else {
108 strcpy(dst, prefix);
109 dst += nreal;
110 }
111 assert(dst <= stop);
112 sincebreak = 0;
113
114 while (ntodo > 0) {
115 if (ntodo < inblocksize) { /* incomplete input */
116 memset(inblock, 0, sizeof(inblock));
117 memcpy(inblock, src, ntodo);
118 src = inblock;
119 nreal = ntodo;
120 ntodo = inblocksize;
121 } else
122 nreal = inblocksize;
123 out = (outblocksize > stop - dst) ? outblock : dst;
124
125 convert(src, nreal, format, out);
126 needed += outblocksize;
127 sincebreak += outblocksize;
128 if (dst < stop) {
129 if (out != dst) {
130 assert(outblocksize > stop - dst);
131 memcpy(dst, out, stop - dst);
132 dst = stop;
133 } else
134 dst += outblocksize;
135 }
136
137 src += inblocksize;
138 ntodo -= inblocksize;
139 if (breakevery != 0 && sincebreak >= breakevery && ntodo > 0) {
140 if (dst < stop)
141 *dst++ = breakchar;
142 needed++;
143 sincebreak = 0;
144 }
145 }
146
147 assert(dst <= stop);
148 *dst++ = '\0';
149 needed++;
150
151 return needed;
152 }
153
154 /*
155 - convert - convert one input block to one output block
156 */
157 static void
158 convert(src, nreal, format, out)
159 const char *src;
160 size_t nreal; /* how much of the input block is real */
161 int format;
162 char *out;
163 {
164 static char hex[] = "0123456789abcdef";
165 static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
166 "abcdefghijklmnopqrstuvwxyz"
167 "0123456789+/";
168 unsigned char c;
169 unsigned char c1, c2, c3;
170
171 assert(nreal > 0);
172 switch (format) {
173 case 'x':
174 assert(nreal == 1);
175 c = (unsigned char)*src;
176 *out++ = hex[c >> 4];
177 *out++ = hex[c & 0xf];
178 break;
179 case 's':
180 c1 = (unsigned char)*src++;
181 c2 = (unsigned char)*src++;
182 c3 = (unsigned char)*src++;
183 *out++ = base64[c1 >> 2]; /* top 6 bits of c1 */
184 c = (c1 & 0x3) << 4; /* bottom 2 of c1... */
185 c |= c2 >> 4; /* ...top 4 of c2 */
186 *out++ = base64[c];
187 if (nreal == 1)
188 *out++ = '=';
189 else {
190 c = (c2 & 0xf) << 2; /* bottom 4 of c2... */
191 c |= c3 >> 6; /* ...top 2 of c3 */
192 *out++ = base64[c];
193 }
194 if (nreal <= 2)
195 *out++ = '=';
196 else
197 *out++ = base64[c3 & 0x3f]; /* bottom 6 of c3 */
198 break;
199 default:
200 assert(nreal == 0); /* unknown format */
201 break;
202 }
203 }
204
205 /*
206 - datatoa - convert data to ASCII
207 * backward-compatibility synonym for datatot
208 */
209 size_t /* true length (with NUL) for success */
210 datatoa(src, srclen, format, dst, dstlen)
211 const char *src;
212 size_t srclen;
213 int format; /* character indicating what format */
214 char *dst; /* need not be valid if dstlen is 0 */
215 size_t dstlen;
216 {
217 return datatot(src, srclen, format, dst, dstlen);
218 }
219
220 /*
221 - bytestoa - convert data bytes to ASCII
222 * backward-compatibility synonym for datatot
223 */
224 size_t /* true length (with NUL) for success */
225 bytestoa(src, srclen, format, dst, dstlen)
226 const char *src;
227 size_t srclen;
228 int format; /* character indicating what format */
229 char *dst; /* need not be valid if dstlen is 0 */
230 size_t dstlen;
231 {
232 return datatot(src, srclen, format, dst, dstlen);
233 }