1 /* ber-help.c - BER herlper functions
2 * Copyright (C) 2001, 2012 g10 Code GmbH
4 * This file is part of KSBA.
6 * KSBA is free software; you can redistribute it and/or modify
7 * it under the terms of either
9 * - the GNU Lesser General Public License as published by the Free
10 * Software Foundation; either version 3 of the License, or (at
11 * your option) any later version.
15 * - the GNU General Public License as published by the Free
16 * Software Foundation; either version 2 of the License, or (at
17 * your option) any later version.
19 * or both in parallel, as here.
21 * KSBA is distributed in the hope that it will be useful, but WITHOUT
22 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
24 * License for more details.
26 * You should have received a copies of the GNU General Public License
27 * and the GNU Lesser General Public License along with this program;
28 * if not, see <http://www.gnu.org/licenses/>.
38 #include "asn1-func.h" /* need some constants */
41 /* Fixme: The parser functions should check that primitive types don't
42 have the constructed bit set (which is not allowed). This saves us
43 some work when using these parsers */
46 read_byte (ksba_reader_t reader)
53 rc = ksba_reader_read (reader, &buf, 1, &nread);
54 while (!rc && !nread);
60 premature_eof (struct tag_info *ti)
62 /* Note: We do an strcmp on this string at othyer places. */
63 ti->err_string = "premature EOF";
64 return gpg_error (GPG_ERR_BAD_BER);
70 eof_or_error (ksba_reader_t reader, struct tag_info *ti, int premature)
74 err = ksba_reader_error (reader);
77 ti->err_string = "read error";
81 return premature_eof (ti);
83 return gpg_error (GPG_ERR_EOF);
89 Read the tag and the length part from the TLV triplet.
92 _ksba_ber_read_tl (ksba_reader_t reader, struct tag_info *ti)
100 ti->err_string = NULL;
104 c = read_byte (reader);
106 return eof_or_error (reader, ti, 0);
108 ti->buf[ti->nhdr++] = c;
109 ti->class = (c & 0xc0) >> 6;
110 ti->is_constructed = !!(c & 0x20);
118 /* We silently ignore an overflow in the tag value. It is
119 not worth checking for it. */
121 c = read_byte (reader);
123 return eof_or_error (reader, ti, 1);
124 if (ti->nhdr >= DIM (ti->buf))
126 ti->err_string = "tag+length header too large";
127 return gpg_error (GPG_ERR_BAD_BER);
129 ti->buf[ti->nhdr++] = c;
137 c = read_byte (reader);
139 return eof_or_error (reader, ti, 1);
140 if (ti->nhdr >= DIM (ti->buf))
142 ti->err_string = "tag+length header too large";
143 return gpg_error (GPG_ERR_BAD_BER);
145 ti->buf[ti->nhdr++] = c;
156 ti->err_string = "forbidden length value";
157 return gpg_error (GPG_ERR_BAD_BER);
161 unsigned long len = 0;
162 int count = c & 0x7f;
164 if (count > sizeof (len) || count > sizeof (size_t))
165 return gpg_error (GPG_ERR_BAD_BER);
167 for (; count; count--)
170 c = read_byte (reader);
172 return eof_or_error (reader, ti, 1);
173 if (ti->nhdr >= DIM (ti->buf))
175 ti->err_string = "tag+length header too large";
176 return gpg_error (GPG_ERR_BAD_BER);
178 ti->buf[ti->nhdr++] = c;
184 /* Without this kludge some example certs can't be parsed */
185 if (ti->class == CLASS_UNIVERSAL && !ti->tag)
192 Parse the buffer at the address BUFFER which of SIZE and return
193 the tag and the length part from the TLV triplet. Update BUFFER
194 and SIZE on success. */
196 _ksba_ber_parse_tl (unsigned char const **buffer, size_t *size,
201 const unsigned char *buf = *buffer;
202 size_t length = *size;
207 ti->err_string = NULL;
212 return premature_eof (ti);
213 c = *buf++; length--;
215 ti->buf[ti->nhdr++] = c;
216 ti->class = (c & 0xc0) >> 6;
217 ti->is_constructed = !!(c & 0x20);
225 /* We silently ignore an overflow in the tag value. It is
226 not worth checking for it. */
229 return premature_eof (ti);
230 c = *buf++; length--;
231 if (ti->nhdr >= DIM (ti->buf))
233 ti->err_string = "tag+length header too large";
234 return gpg_error (GPG_ERR_BAD_BER);
236 ti->buf[ti->nhdr++] = c;
245 return premature_eof (ti);
246 c = *buf++; length--;
247 if (ti->nhdr >= DIM (ti->buf))
249 ti->err_string = "tag+length header too large";
250 return gpg_error (GPG_ERR_BAD_BER);
252 ti->buf[ti->nhdr++] = c;
263 ti->err_string = "forbidden length value";
264 return gpg_error (GPG_ERR_BAD_BER);
268 unsigned long len = 0;
269 int count = c & 0x7f;
271 if (count > sizeof (len) || count > sizeof (size_t))
272 return gpg_error (GPG_ERR_BAD_BER);
274 for (; count; count--)
278 return premature_eof (ti);
279 c = *buf++; length--;
280 if (ti->nhdr >= DIM (ti->buf))
282 ti->err_string = "tag+length header too large";
283 return gpg_error (GPG_ERR_BAD_BER);
285 ti->buf[ti->nhdr++] = c;
288 /* Sanity check for the length: This is done so that we can take
289 * the value for malloc plus some additional bytes without
290 * risking an overflow. */
292 return gpg_error (GPG_ERR_BAD_BER);
297 /* Without this kludge some example certs can't be parsed */
298 if (ti->class == CLASS_UNIVERSAL && !ti->tag)
307 /* Write TAG of CLASS to WRITER. constructed is a flag telling
308 whether the value is a constructed one. length gives the length of
309 the value, if it is 0 undefinite length is assumed. length is
310 ignored for the NULL tag. */
312 _ksba_ber_write_tl (ksba_writer_t writer,
314 enum tag_class class,
316 unsigned long length)
318 unsigned char buf[50];
323 *buf = (class << 6) | tag;
330 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
334 buf[buflen++] = 0; /* end tag */
335 else if (tag == TYPE_NULL && !class)
336 buf[buflen++] = 0; /* NULL tag */
338 buf[buflen++] = 0x80; /* indefinite length */
339 else if (length < 128)
340 buf[buflen++] = length;
345 /* fixme: if we know the sizeof an ulong we could support larger
346 objects - however this is pretty ridiculous */
347 i = (length <= 0xff ? 1:
348 length <= 0xffff ? 2:
349 length <= 0xffffff ? 3: 4);
351 buf[buflen++] = (0x80 | i);
353 buf[buflen++] = length >> 24;
355 buf[buflen++] = length >> 16;
357 buf[buflen++] = length >> 8;
358 buf[buflen++] = length;
361 return ksba_writer_write (writer, buf, buflen);
364 /* Encode TAG of CLASS in BUFFER. CONSTRUCTED is a flag telling
365 whether the value is a constructed one. LENGTH gives the length of
366 the value, if it is 0 undefinite length is assumed. LENGTH is
367 ignored for the NULL tag. It is assumed that the provide buffer is
368 large enough for storing the result - this is usually achieved by
369 using _ksba_ber_count_tl() in advance. Returns 0 in case of an
370 error or the length of the encoding.*/
372 _ksba_ber_encode_tl (unsigned char *buffer,
374 enum tag_class class,
376 unsigned long length)
378 unsigned char *buf = buffer;
382 *buf = (class << 6) | tag;
389 return 0; /*Not implemented*/
393 *buf++ = 0; /* end tag */
394 else if (tag == TYPE_NULL && !class)
395 *buf++ = 0; /* NULL tag */
397 *buf++ = 0x80; /* indefinite length */
398 else if (length < 128)
404 /* fixme: if we know the sizeof an ulong we could support larger
405 objetcs - however this is pretty ridiculous */
406 i = (length <= 0xff ? 1:
407 length <= 0xffff ? 2:
408 length <= 0xffffff ? 3: 4);
412 *buf++ = length >> 24;
414 *buf++ = length >> 16;
416 *buf++ = length >> 8;
424 /* Calculate the length of the TL needed to encode a TAG of CLASS.
425 CONSTRUCTED is a flag telling whether the value is a constructed
426 one. LENGTH gives the length of the value; if it is 0 an
427 indefinite length is assumed. LENGTH is ignored for the NULL
430 _ksba_ber_count_tl (unsigned long tag,
431 enum tag_class class,
433 unsigned long length)
437 (void)constructed; /* Not used, but passed for uniformity of such calls. */
445 buflen++; /* assume one and let the actual write function bail out */
449 buflen++; /* end tag */
450 else if (tag == TYPE_NULL && !class)
451 buflen++; /* NULL tag */
453 buflen++; /* indefinite length */
454 else if (length < 128)
460 /* fixme: if we know the sizeof an ulong we could support larger
461 objetcs - however this is pretty ridiculous */
462 i = (length <= 0xff ? 1:
463 length <= 0xffff ? 2:
464 length <= 0xffffff ? 3: 4);