replaced get_rsa_private_key() by rsa_signature() in order restrict the distribution...
[strongswan.git] / src / libstrongswan / chunk.c
1 /**
2 * @file chunk.c
3 *
4 * @brief Pointer/lenght abstraction and its functions.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <stdio.h>
25 #include <sys/stat.h>
26
27 #include "chunk.h"
28
29 #include <debug.h>
30 #include <printf_hook.h>
31 #include <utils/randomizer.h>
32
33 /**
34 * Empty chunk.
35 */
36 chunk_t chunk_empty = { NULL, 0 };
37
38 /**
39 * Described in header.
40 */
41 chunk_t chunk_create(u_char *ptr, size_t len)
42 {
43 chunk_t chunk = {ptr, len};
44 return chunk;
45 }
46
47 /**
48 * Described in header.
49 */
50 chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk)
51 {
52 chunk_t clone = chunk_empty;
53
54 if (chunk.ptr && chunk.len > 0)
55 {
56 clone.ptr = ptr;
57 clone.len = chunk.len;
58 memcpy(clone.ptr, chunk.ptr, chunk.len);
59 }
60
61 return clone;
62 }
63
64 /**
65 * Decribed in header.
66 */
67 size_t chunk_length(const char* mode, ...)
68 {
69 va_list chunks;
70 size_t length = 0;
71
72 va_start(chunks, mode);
73 while (TRUE)
74 {
75 switch (*mode++)
76 {
77 case 'm':
78 case 'c':
79 {
80 chunk_t ch = va_arg(chunks, chunk_t);
81 length += ch.len;
82 continue;
83 }
84 default:
85 break;
86 }
87 break;
88 }
89 va_end(chunks);
90 return length;
91 }
92
93 /**
94 * Decribed in header.
95 */
96 chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...)
97 {
98 va_list chunks;
99 chunk_t construct = chunk_create(ptr, 0);
100
101 va_start(chunks, mode);
102 while (TRUE)
103 {
104 bool free_chunk = FALSE;
105 switch (*mode++)
106 {
107 case 'm':
108 {
109 free_chunk = TRUE;
110 }
111 case 'c':
112 {
113 chunk_t ch = va_arg(chunks, chunk_t);
114 memcpy(ptr, ch.ptr, ch.len);
115 ptr += ch.len;
116 construct.len += ch.len;
117 if (free_chunk)
118 {
119 free(ch.ptr);
120 }
121 continue;
122 }
123 default:
124 break;
125 }
126 break;
127 }
128 va_end(chunks);
129
130 return construct;
131 }
132
133 /**
134 * Decribed in header.
135 */
136 void chunk_split(chunk_t chunk, const char *mode, ...)
137 {
138 va_list chunks;
139 size_t len;
140 chunk_t *ch;
141
142 va_start(chunks, mode);
143 while (TRUE)
144 {
145 if (*mode == '\0')
146 {
147 break;
148 }
149 len = va_arg(chunks, size_t);
150 ch = va_arg(chunks, chunk_t*);
151 /* a null chunk means skip len bytes */
152 if (ch == NULL)
153 {
154 chunk = chunk_skip(chunk, len);
155 continue;
156 }
157 switch (*mode++)
158 {
159 case 'm':
160 {
161 ch->len = min(chunk.len, len);
162 if (ch->len)
163 {
164 ch->ptr = chunk.ptr;
165 }
166 else
167 {
168 ch->ptr = NULL;
169 }
170 chunk = chunk_skip(chunk, ch->len);
171 continue;
172 }
173 case 'a':
174 {
175 ch->len = min(chunk.len, len);
176 if (ch->len)
177 {
178 ch->ptr = malloc(ch->len);
179 memcpy(ch->ptr, chunk.ptr, ch->len);
180 }
181 else
182 {
183 ch->ptr = NULL;
184 }
185 chunk = chunk_skip(chunk, ch->len);
186 continue;
187 }
188 case 'c':
189 {
190 ch->len = min(ch->len, chunk.len);
191 ch->len = min(ch->len, len);
192 if (ch->len)
193 {
194 memcpy(ch->ptr, chunk.ptr, ch->len);
195 }
196 else
197 {
198 ch->ptr = NULL;
199 }
200 chunk = chunk_skip(chunk, ch->len);
201 continue;
202 }
203 default:
204 break;
205 }
206 break;
207 }
208 va_end(chunks);
209 }
210
211 /**
212 * Described in header.
213 */
214 bool chunk_write(chunk_t chunk, const char *path, const char *label, mode_t mask, bool force)
215 {
216 mode_t oldmask;
217 FILE *fd;
218
219 if (!force)
220 {
221 fd = fopen(path, "r");
222 if (fd)
223 {
224 fclose(fd);
225 DBG1(" %s file '%s' already exists", label, path);
226 return FALSE;
227 }
228 }
229
230 /* set umask */
231 oldmask = umask(mask);
232
233 fd = fopen(path, "w");
234
235 if (fd)
236 {
237 fwrite(chunk.ptr, sizeof(u_char), chunk.len, fd);
238 fclose(fd);
239 DBG1(" written %s file '%s' (%u bytes)", label, path, chunk.len);
240 umask(oldmask);
241 return TRUE;
242 }
243 else
244 {
245 DBG1(" could not open %s file '%s' for writing", label, path);
246 umask(oldmask);
247 return FALSE;
248 }
249 }
250
251 /**
252 * Described in header.
253 */
254 void chunk_free(chunk_t *chunk)
255 {
256 free(chunk->ptr);
257 chunk->ptr = NULL;
258 chunk->len = 0;
259 }
260
261 /**
262 * Described in header.
263 */
264 void chunk_free_randomized(chunk_t *chunk)
265 {
266 if (chunk->ptr)
267 {
268 if (chunk->len > 0)
269 {
270 randomizer_t *randomizer = randomizer_create();
271
272 randomizer->get_pseudo_random_bytes(randomizer,
273 chunk->len, chunk->ptr);
274 randomizer->destroy(randomizer);
275 };
276 free(chunk->ptr);
277 chunk->ptr = NULL;
278 }
279 chunk->len = 0;
280 }
281
282 /**
283 * Described in header.
284 */
285 chunk_t chunk_skip(chunk_t chunk, size_t bytes)
286 {
287 if (chunk.len > bytes)
288 {
289 chunk.ptr += bytes;
290 chunk.len -= bytes;
291 return chunk;
292 }
293 return chunk_empty;
294 }
295
296 /**
297 * Described in header.
298 */
299 int chunk_compare(chunk_t a, chunk_t b)
300 {
301 int compare_len = a.len - b.len;
302 int len = (compare_len < 0)? a.len : b.len;
303
304 if (compare_len != 0 || len == 0)
305 {
306 return compare_len;
307 }
308 return memcmp(a.ptr, b.ptr, len);
309 };
310
311 /**
312 * Described in header.
313 */
314 bool chunk_equals(chunk_t a, chunk_t b)
315 {
316 return a.ptr != NULL && b.ptr != NULL &&
317 a.len == b.len && memeq(a.ptr, b.ptr, a.len);
318 }
319
320 /**
321 * Described in header.
322 */
323 bool chunk_equals_or_null(chunk_t a, chunk_t b)
324 {
325 if (a.ptr == NULL || b.ptr == NULL)
326 return TRUE;
327 return a.len == b.len && memeq(a.ptr, b.ptr, a.len);
328 }
329
330 /**
331 * Number of bytes per line to dump raw data
332 */
333 #define BYTES_PER_LINE 16
334
335 /**
336 * output handler in printf() for byte ranges
337 */
338 static int print_bytes(FILE *stream, const struct printf_info *info,
339 const void *const *args)
340 {
341 char *bytes = *((void**)(args[0]));
342 int len = *((size_t*)(args[1]));
343
344 char buffer[BYTES_PER_LINE * 3];
345 char ascii_buffer[BYTES_PER_LINE + 1];
346 char *buffer_pos = buffer;
347 char *bytes_pos = bytes;
348 char *bytes_roof = bytes + len;
349 int line_start = 0;
350 int i = 0;
351 int written = 0;
352
353 written += fprintf(stream, "=> %d bytes @ %p", len, bytes);
354
355 while (bytes_pos < bytes_roof)
356 {
357 static char hexdig[] = "0123456789ABCDEF";
358
359 *buffer_pos++ = hexdig[(*bytes_pos >> 4) & 0xF];
360 *buffer_pos++ = hexdig[ *bytes_pos & 0xF];
361
362 ascii_buffer[i++] =
363 (*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
364
365 if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
366 {
367 int padding = 3 * (BYTES_PER_LINE - i);
368 int written;
369
370 while (padding--)
371 {
372 *buffer_pos++ = ' ';
373 }
374 *buffer_pos++ = '\0';
375 ascii_buffer[i] = '\0';
376
377 written += fprintf(stream, "\n%4d: %s %s",
378 line_start, buffer, ascii_buffer);
379
380
381 buffer_pos = buffer;
382 line_start += BYTES_PER_LINE;
383 i = 0;
384 }
385 else
386 {
387 *buffer_pos++ = ' ';
388 }
389 }
390 return written;
391 }
392
393 /**
394 * output handler in printf() for chunks
395 */
396 static int print_chunk(FILE *stream, const struct printf_info *info,
397 const void *const *args)
398 {
399 chunk_t *chunk = *((chunk_t**)(args[0]));
400 bool first = TRUE;
401 chunk_t copy = *chunk;
402 int written = 0;
403
404 if (!info->alt)
405 {
406 const void *new_args[] = {&chunk->ptr, &chunk->len};
407 return print_bytes(stream, info, new_args);
408 }
409
410 while (copy.len > 0)
411 {
412 if (first)
413 {
414 first = FALSE;
415 }
416 else
417 {
418 written += fprintf(stream, ":");
419 }
420 written += fprintf(stream, "%02x", *copy.ptr++);
421 copy.len--;
422 }
423 return written;
424 }
425
426 /**
427 * register printf() handlers
428 */
429 static void __attribute__ ((constructor))print_register()
430 {
431 register_printf_function(PRINTF_CHUNK, print_chunk, arginfo_ptr);
432 register_printf_function(PRINTF_BYTES, print_bytes, arginfo_ptr_int);
433 }