aboutsummaryrefslogtreecommitdiff
path: root/src/lib/krb5/asn.1/asn1buf.h
blob: 900b14a5aeda74ac032e158eb4aa617569786b96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/* Coding Buffer Specifications */
#ifndef __ASN1BUF_H__
#define __ASN1BUF_H__

#include "k5-int.h"
#include "krbasn1.h"

typedef struct code_buffer_rep {
    char *base, *bound, *next;
} asn1buf;


/**************** Private Procedures ****************/

#if (__GNUC__ >= 2) && !defined(CONFIG_SMALL)
unsigned int asn1buf_free(const asn1buf *buf);
/*
 * requires  *buf is allocated
 * effects   Returns the number of unused, allocated octets in *buf.
 */
#define asn1buf_free(buf)                               \
    (((buf) == NULL || (buf)->base == NULL)             \
     ? 0U                                               \
     : (unsigned int)((buf)->bound - (buf)->next + 1))


asn1_error_code asn1buf_ensure_space(asn1buf *buf, const unsigned int amount);
/*
 * requires  *buf is allocated
 * modifies  *buf
 * effects  If buf has less than amount octets of free space, then it is
 *          expanded to have at least amount octets of free space.
 *          Returns ENOMEM memory is exhausted.
 */
#define asn1buf_ensure_space(buf,amount)                        \
    ((asn1buf_free(buf) < (amount))                             \
     ? (asn1buf_expand((buf), (amount)-asn1buf_free(buf)))      \
     : 0)

asn1_error_code asn1buf_expand(asn1buf *buf, unsigned int inc);
/*
 * requires  *buf is allocated
 * modifies  *buf
 * effects   Expands *buf by allocating space for inc more octets.
 *            Returns ENOMEM if memory is exhausted.
 */
#endif

int asn1buf_len(const asn1buf *buf);
/*
 * requires  *buf is allocated
 * effects   Returns the length of the encoding in *buf.
 */
#define asn1buf_len(buf)        ((buf)->next - (buf)->base)

/****** End of private procedures *****/

/*
 * Overview
 *
 *  The coding buffer is an array of char (to match a krb5_data structure)
 *   with 3 reference pointers:
 *   1) base - The bottom of the octet array.  Used for memory management
 *             operations on the array (e.g. alloc, realloc, free).
 *   2) next - Points to the next available octet position in the array.
 *             During encoding, this is the next free position, and it
 *               advances as octets are added to the array.
 *             During decoding, this is the next unread position, and it
 *               advances as octets are read from the array.
 *   3) bound - Points to the top of the array. Used for bounds-checking.
 *
 *  All pointers to encoding buffers should be initalized to NULL.
 *
 * Operations
 *
 *  asn1buf_create
 *  asn1buf_wrap_data
 *  asn1buf_destroy
 *  asn1buf_insert_octet
 *  asn1buf_insert_charstring
 *  asn1buf_remove_octet
 *  asn1buf_remove_charstring
 *  asn1buf_unparse
 *  asn1buf_hex_unparse
 *  asn12krb5_buf
 *  asn1buf_remains
 *
 *  (asn1buf_size)
 *  (asn1buf_free)
 *  (asn1buf_ensure_space)
 *  (asn1buf_expand)
 *  (asn1buf_len)
 */

asn1_error_code asn1buf_create(asn1buf **buf);
/*
 * effects   Creates a new encoding buffer pointed to by *buf.
 *           Returns ENOMEM if the buffer can't be created.
 */

asn1_error_code asn1buf_wrap_data(asn1buf *buf, const krb5_data *code);
/*
 * requires  *buf has already been allocated
 * effects   Turns *buf into a "wrapper" for *code.  i.e. *buf is set up
 *            such that its bottom is the beginning of *code, and its top
 *            is the top of *code.
 *           Returns ASN1_MISSING_FIELD if code is empty.
 */

asn1_error_code asn1buf_imbed(asn1buf *subbuf, const asn1buf *buf,
                              const unsigned int length,
                              const int indef);
/*
 * requires  *subbuf and *buf are allocated
 * effects   *subbuf becomes a sub-buffer of *buf.  *subbuf begins
 *            at *buf's current position and is length octets long.
 *            (Unless this would exceed the bounds of *buf -- in
 *            that case, ASN1_OVERRUN is returned)  *subbuf's current
 *            position starts at the beginning of *subbuf.
 */

asn1_error_code asn1buf_sync(asn1buf *buf, asn1buf *subbuf, asn1_class Class,
                             asn1_tagnum lasttag,
                             unsigned int length, int indef,
                             int seqindef);
/*
 * requires  *subbuf is a sub-buffer of *buf, as created by asn1buf_imbed.
 *           lasttag is the last tagnumber read.
 * effects   Synchronizes *buf's current position to match that of *subbuf.
 */

asn1_error_code asn1buf_skiptail(asn1buf *buf, const unsigned int length,
                                 const int indef);
/*
 * requires  *buf is a subbuffer used in a decoding of a
 *           constructed indefinite sequence.
 * effects   skips trailing fields.
 */

void asn1buf_destroy(asn1buf **buf);
/* effects   Deallocates **buf, sets *buf to NULL. */

asn1_error_code asn1buf_insert_octet(asn1buf *buf, const int o);
/*
 * requires  *buf is allocated
 * effects   Inserts o into the buffer *buf, expanding the buffer if
 *           necessary.  Returns ENOMEM memory is exhausted.
 */
#if ((__GNUC__ >= 2) && !defined(ASN1BUF_OMIT_INLINE_FUNCS)) && !defined(CONFIG_SMALL)
extern __inline__ asn1_error_code asn1buf_insert_octet(asn1buf *buf, const int o)
{
    asn1_error_code retval;

    retval = asn1buf_ensure_space(buf,1U);
    if (retval) return retval;
    *(buf->next) = (char)o;
    (buf->next)++;
    return 0;
}
#endif

asn1_error_code
asn1buf_insert_bytestring(
    asn1buf *buf,
    const unsigned int len,
    const void *s);
/*
 * requires  *buf is allocated
 * modifies  *buf
 * effects   Inserts the contents of s (an array of length len)
 *            into the buffer *buf, expanding the buffer if necessary.
 *           Returns ENOMEM if memory is exhausted.
 */

#define asn1buf_insert_octetstring asn1buf_insert_bytestring
#define asn1buf_insert_charstring  asn1buf_insert_bytestring

asn1_error_code asn1buf_remove_octet(asn1buf *buf, asn1_octet *o);
/*
 * requires  *buf is allocated
 * effects   Returns *buf's current octet in *o and advances to
 *            the next octet.
 *           Returns ASN1_OVERRUN if *buf has already been exhausted.
 */
#define asn1buf_remove_octet(buf,o)                     \
    (((buf)->next > (buf)->bound)                       \
     ? ASN1_OVERRUN                                     \
     : ((*(o) = (asn1_octet)(*(((buf)->next)++))),0))

asn1_error_code
asn1buf_remove_octetstring(
    asn1buf *buf,
    const unsigned int len,
    asn1_octet **s);
/*
 * requires  *buf is allocated
 * effects   Removes the next len octets of *buf and returns them in **s.
 *           Returns ASN1_OVERRUN if there are fewer than len unread octets
 *            left in *buf.
 *           Returns ENOMEM if *s could not be allocated.
 */

asn1_error_code
asn1buf_remove_charstring(asn1buf *buf, const unsigned int len, char **s);
/*
 * requires  *buf is allocated
 * effects   Removes the next len octets of *buf and returns them in **s.
 *           Returns ASN1_OVERRUN if there are fewer than len unread octets
 *            left in *buf.
 *           Returns ENOMEM if *s could not be allocated.
 */

asn1_error_code asn1buf_unparse(const asn1buf *buf, char **s);
/*
 * modifies  *s
 * effects   Returns a human-readable representation of *buf in *s,
 *           where each octet in *buf is represented by a character in *s.
 */

asn1_error_code asn1buf_hex_unparse(const asn1buf *buf, char **s);
/*
 * modifies  *s
 * effects   Returns a human-readable representation of *buf in *s,
 *           where each octet in *buf is represented by a 2-digit
 *           hexadecimal number in *s.
 */

asn1_error_code asn12krb5_buf(const asn1buf *buf, krb5_data **code);
/*
 * modifies  *code
 * effects   Instantiates **code with the krb5_data representation of **buf.
 */

int asn1buf_remains(asn1buf *buf, int indef);
/*
 * requires  *buf is a buffer containing an asn.1 structure or array
 * modifies  *buf
 * effects   Returns the number of unprocessed octets remaining in *buf.
 */

#endif