1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* Coding Buffer Implementation */
9 * The encoding buffer is filled from bottom (lowest address) to top
10 * (highest address). This makes it easier to expand the buffer,
11 * since realloc preserves the existing portion of the buffer.
13 * Note: Since ASN.1 encoding must be done in reverse, this means
14 * that you can't simply memcpy out the buffer data, since it will be
15 * backwards. You need to reverse-iterate through it, instead.
17 * ***This decision may have been a mistake. In practice, the
18 * implementation will probably be tuned such that reallocation is
19 * rarely necessary. Also, the realloc probably has recopy the
20 * buffer itself, so we don't really gain that much by avoiding an
21 * explicit copy of the buffer. --Keep this in mind for future reference.
26 * The decoding buffer is in normal order and is created by wrapping
27 * an asn1buf around a krb5_data structure.
31 * Abstraction Function
33 * Programs should use just pointers to asn1buf's (e.g. asn1buf *mybuf).
34 * These pointers must always point to a valid, allocated asn1buf
35 * structure or be NULL.
37 * The contents of the asn1buf represent an octet string. This string
38 * begins at base and continues to the octet immediately preceding next.
39 * If next == base or mybuf == NULL, then the asn1buf represents an empty
44 * Representation Invariant
46 * Pointers to asn1buf's must always point to a valid, allocated
47 * asn1buf structure or be NULL.
49 * base points to a valid, allocated octet array or is NULL
50 * bound, if non-NULL, points to the last valid octet
52 * next <= bound+2 (i.e. next should be able to step just past the bound,
53 * but no further. (The bound should move out in response
54 * to being crossed by next.))
57 #define ASN1BUF_OMIT_INLINE_FUNCS
62 #include <valgrind/memcheck.h>
64 #define VALGRIND_CHECK_READABLE(PTR,SIZE) ((void)0)
67 #if !defined(__GNUC__) || defined(CONFIG_SMALL)
69 * Declare private procedures as static if they're not used for inline
70 * expansion of other stuff elsewhere.
72 static unsigned int asn1buf_free(const asn1buf *);
73 static asn1_error_code asn1buf_ensure_space(asn1buf *, unsigned int);
74 static asn1_error_code asn1buf_expand(asn1buf *, unsigned int);
77 #define asn1_is_eoc(class, num, indef) \
78 ((class) == UNIVERSAL && !(num) && !(indef))
81 asn1buf_create(asn1buf **buf)
83 *buf = (asn1buf*)malloc(sizeof(asn1buf));
84 if (*buf == NULL) return ENOMEM;
92 asn1buf_destroy(asn1buf **buf)
101 #ifdef asn1buf_insert_octet
102 #undef asn1buf_insert_octet
105 asn1buf_insert_octet(asn1buf *buf, const int o)
107 asn1_error_code retval;
109 retval = asn1buf_ensure_space(buf,1U);
110 if (retval) return retval;
111 *(buf->next) = (char)o;
117 asn1buf_insert_bytestring(asn1buf *buf, const unsigned int len, const void *sv)
119 asn1_error_code retval;
123 retval = asn1buf_ensure_space(buf,len);
124 if (retval) return retval;
125 VALGRIND_CHECK_READABLE(sv, len);
126 for (length=1; length<=len; length++,(buf->next)++)
127 *(buf->next) = (s[len-length]);
132 asn12krb5_buf(const asn1buf *buf, krb5_data **code)
139 d = calloc(1, sizeof(krb5_data));
142 d->length = asn1buf_len(buf);
143 d->data = malloc(d->length + 1);
144 if (d->data == NULL) {
148 for (i=0; i < d->length; i++)
149 d->data[i] = buf->base[d->length - i - 1];
150 d->data[d->length] = '\0';
151 d->magic = KV5M_DATA;
156 /****************************************************************/
157 /* Private Procedures */
160 asn1buf_size(const asn1buf *buf)
162 if (buf == NULL || buf->base == NULL) return 0;
163 return buf->bound - buf->base + 1;
168 asn1buf_free(const asn1buf *buf)
170 if (buf == NULL || buf->base == NULL) return 0;
171 else return buf->bound - buf->next + 1;
174 #undef asn1buf_ensure_space
176 asn1buf_ensure_space(asn1buf *buf, const unsigned int amount)
178 unsigned int avail = asn1buf_free(buf);
181 return asn1buf_expand(buf, amount-avail);
185 asn1buf_expand(asn1buf *buf, unsigned int inc)
187 #define STANDARD_INCREMENT 200
188 int next_offset = buf->next - buf->base;
190 if (buf->base == NULL) bound_offset = -1;
191 else bound_offset = buf->bound - buf->base;
193 if (inc < STANDARD_INCREMENT)
194 inc = STANDARD_INCREMENT;
196 buf->base = realloc(buf->base,
197 (asn1buf_size(buf)+inc) * sizeof(asn1_octet));
198 if (buf->base == NULL) return ENOMEM; /* XXX leak */
199 buf->bound = (buf->base) + bound_offset + inc;
200 buf->next = (buf->base) + next_offset;
206 asn1buf_len(const asn1buf *buf)
208 return buf->next - buf->base;