common: Check option arguments for a valid range.
[gnupg.git] / common / tlv.c
1 /* tlv.c - Tag-Length-Value Utilities
2  *      Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * This file is free software; you can redistribute it and/or modify
7  * it under the terms of either
8  *
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.
12  *
13  * or
14  *
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.
18  *
19  * or both in parallel, as here.
20  *
21  * This file is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, see <http://www.gnu.org/licenses/>.
28  */
29
30 #include <config.h>
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <assert.h>
36
37 #if GNUPG_MAJOR_VERSION == 1
38 #define GPG_ERR_EOF               (-1)
39 #define GPG_ERR_BAD_BER           (1)  /*G10ERR_GENERAL*/
40 #define GPG_ERR_INV_SEXP          (45) /*G10ERR_INV_ARG*/
41 typedef int gpg_error_t;
42 #define gpg_make_err(x,n) (n)
43 #else
44 #include <gpg-error.h>
45 #endif
46
47 #include "util.h"
48 #include "tlv.h"
49
50 static const unsigned char *
51 do_find_tlv (const unsigned char *buffer, size_t length,
52              int tag, size_t *nbytes, int nestlevel)
53 {
54   const unsigned char *s = buffer;
55   size_t n = length;
56   size_t len;
57   int this_tag;
58   int composite;
59
60   for (;;)
61     {
62       buffer = s;
63       if (n < 2)
64         return NULL; /* Buffer definitely too short for tag and length. */
65       if (!*s || *s == 0xff)
66         { /* Skip optional filler between TLV objects. */
67           s++;
68           n--;
69           continue;
70         }
71       composite = !!(*s & 0x20);
72       if ((*s & 0x1f) == 0x1f)
73         { /* more tag bytes to follow */
74           s++;
75           n--;
76           if (n < 2)
77             return NULL; /* buffer definitely too short for tag and length. */
78           if ((*s & 0x1f) == 0x1f)
79             return NULL; /* We support only up to 2 bytes. */
80           this_tag = (s[-1] << 8) | (s[0] & 0x7f);
81         }
82       else
83         this_tag = s[0];
84       len = s[1];
85       s += 2; n -= 2;
86       if (len < 0x80)
87         ;
88       else if (len == 0x81)
89         { /* One byte length follows. */
90           if (!n)
91             return NULL; /* we expected 1 more bytes with the length. */
92           len = s[0];
93           s++; n--;
94         }
95       else if (len == 0x82)
96         { /* Two byte length follows. */
97           if (n < 2)
98             return NULL; /* We expected 2 more bytes with the length. */
99           len = (s[0] << 8) | s[1];
100           s += 2; n -= 2;
101         }
102       else
103         return NULL; /* APDU limit is 65535, thus it does not make
104                         sense to assume longer length fields. */
105
106       if (composite && nestlevel < 100)
107         { /* Dive into this composite DO after checking for a too deep
108              nesting. */
109           const unsigned char *tmp_s;
110           size_t tmp_len;
111
112           tmp_s = do_find_tlv (s, len, tag, &tmp_len, nestlevel+1);
113           if (tmp_s)
114             {
115               *nbytes = tmp_len;
116               return tmp_s;
117             }
118         }
119
120       if (this_tag == tag)
121         {
122           *nbytes = len;
123           return s;
124         }
125       if (len > n)
126         return NULL; /* Buffer too short to skip to the next tag. */
127       s += len; n -= len;
128     }
129 }
130
131
132 /* Locate a TLV encoded data object in BUFFER of LENGTH and
133    return a pointer to value as well as its length in NBYTES.  Return
134    NULL if it was not found or if the object does not fit into the buffer. */
135 const unsigned char *
136 find_tlv (const unsigned char *buffer, size_t length,
137           int tag, size_t *nbytes)
138 {
139   const unsigned char *p;
140
141   p = do_find_tlv (buffer, length, tag, nbytes, 0);
142   if (p && *nbytes > (length - (p-buffer)))
143     p = NULL; /* Object longer than buffer. */
144   return p;
145 }
146
147
148
149 /* Locate a TLV encoded data object in BUFFER of LENGTH and
150    return a pointer to value as well as its length in NBYTES.  Return
151    NULL if it was not found.  Note, that the function does not check
152    whether the value fits into the provided buffer. */
153 const unsigned char *
154 find_tlv_unchecked (const unsigned char *buffer, size_t length,
155                     int tag, size_t *nbytes)
156 {
157   return do_find_tlv (buffer, length, tag, nbytes, 0);
158 }
159
160
161 /* ASN.1 BER parser: Parse BUFFER of length SIZE and return the tag
162    and the length part from the TLV triplet.  Update BUFFER and SIZE
163    on success. */
164 gpg_error_t
165 parse_ber_header (unsigned char const **buffer, size_t *size,
166                   int *r_class, int *r_tag,
167                   int *r_constructed, int *r_ndef,
168                   size_t *r_length, size_t *r_nhdr)
169 {
170   int c;
171   unsigned long tag;
172   const unsigned char *buf = *buffer;
173   size_t length = *size;
174
175   *r_ndef = 0;
176   *r_length = 0;
177   *r_nhdr = 0;
178
179   /* Get the tag. */
180   if (!length)
181     return gpg_err_make (default_errsource, GPG_ERR_EOF);
182   c = *buf++; length--; ++*r_nhdr;
183
184   *r_class = (c & 0xc0) >> 6;
185   *r_constructed = !!(c & 0x20);
186   tag = c & 0x1f;
187
188   if (tag == 0x1f)
189     {
190       tag = 0;
191       do
192         {
193           tag <<= 7;
194           if (!length)
195             return gpg_err_make (default_errsource, GPG_ERR_EOF);
196           c = *buf++; length--; ++*r_nhdr;
197           tag |= c & 0x7f;
198
199         }
200       while (c & 0x80);
201     }
202   *r_tag = tag;
203
204   /* Get the length. */
205   if (!length)
206     return gpg_err_make (default_errsource, GPG_ERR_EOF);
207   c = *buf++; length--; ++*r_nhdr;
208
209   if ( !(c & 0x80) )
210     *r_length = c;
211   else if (c == 0x80)
212     *r_ndef = 1;
213   else if (c == 0xff)
214     return gpg_err_make (default_errsource, GPG_ERR_BAD_BER);
215   else
216     {
217       unsigned long len = 0;
218       int count = c & 0x7f;
219
220       if (count > sizeof (len) || count > sizeof (size_t))
221         return gpg_err_make (default_errsource, GPG_ERR_BAD_BER);
222
223       for (; count; count--)
224         {
225           len <<= 8;
226           if (!length)
227             return gpg_err_make (default_errsource, GPG_ERR_EOF);
228           c = *buf++; length--; ++*r_nhdr;
229           len |= c & 0xff;
230         }
231       *r_length = len;
232     }
233
234   /* Without this kludge some example certs can't be parsed. */
235   if (*r_class == CLASS_UNIVERSAL && !*r_tag)
236     *r_length = 0;
237
238   *buffer = buf;
239   *size = length;
240   return 0;
241 }
242
243
244 /* FIXME: The following function should not go into this file but for
245    now it is easier to keep it here. */
246
247 /* Return the next token of an canonical encoded S-expression.  BUF
248    is the pointer to the S-expression and BUFLEN is a pointer to the
249    length of this S-expression (used to validate the syntax).  Both
250    are updated to reflect the new position.  The token itself is
251    returned as a pointer into the original buffer at TOK and TOKLEN.
252    If a parentheses is the next token, TOK will be set to NULL.
253    TOKLEN is checked to be within the bounds.  On error an error code
254    is returned and no pointer is not guaranteed to point to
255    a meaningful value.  DEPTH should be initialized to 0 and will
256    reflect on return the actual depth of the tree. To detect the end
257    of the S-expression it is advisable to check DEPTH after a
258    successful return.
259
260    depth = 0;
261    while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
262           && depth)
263      process_token (tok, toklen);
264    if (err)
265      handle_error ();
266  */
267 gpg_error_t
268 parse_sexp (unsigned char const **buf, size_t *buflen,
269             int *depth, unsigned char const **tok, size_t *toklen)
270 {
271   const unsigned char *s;
272   size_t n, vlen;
273
274   s = *buf;
275   n = *buflen;
276   *tok = NULL;
277   *toklen = 0;
278   if (!n)
279     return *depth ? gpg_err_make (default_errsource, GPG_ERR_INV_SEXP) : 0;
280   if (*s == '(')
281     {
282       s++; n--;
283       (*depth)++;
284       *buf = s;
285       *buflen = n;
286       return 0;
287     }
288   if (*s == ')')
289     {
290       if (!*depth)
291         return gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
292       *toklen = 1;
293       s++; n--;
294       (*depth)--;
295       *buf = s;
296       *buflen = n;
297       return 0;
298     }
299   for (vlen=0; n && *s && *s != ':' && (*s >= '0' && *s <= '9'); s++, n--)
300     vlen = vlen*10 + (*s - '0');
301   if (!n || *s != ':')
302     return gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
303   s++; n--;
304   if (vlen > n)
305     return gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
306   *tok = s;
307   *toklen = vlen;
308   s += vlen;
309   n -= vlen;
310   *buf = s;
311   *buflen = n;
312   return 0;
313 }