2N/A/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2N/A/* Coding Buffer Specifications */
2N/A#ifndef __ASN1BUF_H__
2N/A#define __ASN1BUF_H__
2N/A
2N/A#include "k5-int.h"
2N/A#include "krbasn1.h"
2N/A
2N/Atypedef struct code_buffer_rep {
2N/A char *base, *bound, *next;
2N/A} asn1buf;
2N/A
2N/A
2N/A/**************** Private Procedures ****************/
2N/A
2N/A#if (__GNUC__ >= 2) && !defined(CONFIG_SMALL)
2N/Aunsigned int asn1buf_free(const asn1buf *buf);
2N/A/*
2N/A * requires *buf is allocated
2N/A * effects Returns the number of unused, allocated octets in *buf.
2N/A */
2N/A#define asn1buf_free(buf) \
2N/A (((buf) == NULL || (buf)->base == NULL) \
2N/A ? 0U \
2N/A : (unsigned int)((buf)->bound - (buf)->next + 1))
2N/A
2N/A
2N/Aasn1_error_code asn1buf_ensure_space(asn1buf *buf, const unsigned int amount);
2N/A/*
2N/A * requires *buf is allocated
2N/A * modifies *buf
2N/A * effects If buf has less than amount octets of free space, then it is
2N/A * expanded to have at least amount octets of free space.
2N/A * Returns ENOMEM memory is exhausted.
2N/A */
2N/A#define asn1buf_ensure_space(buf,amount) \
2N/A ((asn1buf_free(buf) < (amount)) \
2N/A ? (asn1buf_expand((buf), (amount)-asn1buf_free(buf))) \
2N/A : 0)
2N/A
2N/Aasn1_error_code asn1buf_expand(asn1buf *buf, unsigned int inc);
2N/A/*
2N/A * requires *buf is allocated
2N/A * modifies *buf
2N/A * effects Expands *buf by allocating space for inc more octets.
2N/A * Returns ENOMEM if memory is exhausted.
2N/A */
2N/A#endif
2N/A
2N/Aint asn1buf_len(const asn1buf *buf);
2N/A/*
2N/A * requires *buf is allocated
2N/A * effects Returns the length of the encoding in *buf.
2N/A */
2N/A#define asn1buf_len(buf) ((buf)->next - (buf)->base)
2N/A
2N/A/****** End of private procedures *****/
2N/A
2N/A/*
2N/A * Overview
2N/A *
2N/A * The coding buffer is an array of char (to match a krb5_data structure)
2N/A * with 3 reference pointers:
2N/A * 1) base - The bottom of the octet array. Used for memory management
2N/A * operations on the array (e.g. alloc, realloc, free).
2N/A * 2) next - Points to the next available octet position in the array.
2N/A * During encoding, this is the next free position, and it
2N/A * advances as octets are added to the array.
2N/A * During decoding, this is the next unread position, and it
2N/A * advances as octets are read from the array.
2N/A * 3) bound - Points to the top of the array. Used for bounds-checking.
2N/A *
2N/A * All pointers to encoding buffers should be initalized to NULL.
2N/A *
2N/A * Operations
2N/A *
2N/A * asn1buf_create
2N/A * asn1buf_wrap_data
2N/A * asn1buf_destroy
2N/A * asn1buf_insert_octet
2N/A * asn1buf_insert_charstring
2N/A * asn1buf_remove_octet
2N/A * asn1buf_remove_charstring
2N/A * asn1buf_unparse
2N/A * asn1buf_hex_unparse
2N/A * asn12krb5_buf
2N/A * asn1buf_remains
2N/A *
2N/A * (asn1buf_size)
2N/A * (asn1buf_free)
2N/A * (asn1buf_ensure_space)
2N/A * (asn1buf_expand)
2N/A * (asn1buf_len)
2N/A */
2N/A
2N/Aasn1_error_code asn1buf_create(asn1buf **buf);
2N/A/*
2N/A * effects Creates a new encoding buffer pointed to by *buf.
2N/A * Returns ENOMEM if the buffer can't be created.
2N/A */
2N/A
2N/Aasn1_error_code asn1buf_wrap_data(asn1buf *buf, const krb5_data *code);
2N/A/*
2N/A * requires *buf has already been allocated
2N/A * effects Turns *buf into a "wrapper" for *code. i.e. *buf is set up
2N/A * such that its bottom is the beginning of *code, and its top
2N/A * is the top of *code.
2N/A * Returns ASN1_MISSING_FIELD if code is empty.
2N/A */
2N/A
2N/Aasn1_error_code asn1buf_imbed(asn1buf *subbuf, const asn1buf *buf,
2N/A const unsigned int length,
2N/A const int indef);
2N/A/*
2N/A * requires *subbuf and *buf are allocated
2N/A * effects *subbuf becomes a sub-buffer of *buf. *subbuf begins
2N/A * at *buf's current position and is length octets long.
2N/A * (Unless this would exceed the bounds of *buf -- in
2N/A * that case, ASN1_OVERRUN is returned) *subbuf's current
2N/A * position starts at the beginning of *subbuf.
2N/A */
2N/A
2N/Aasn1_error_code asn1buf_sync(asn1buf *buf, asn1buf *subbuf, asn1_class Class,
2N/A asn1_tagnum lasttag,
2N/A unsigned int length, int indef,
2N/A int seqindef);
2N/A/*
2N/A * requires *subbuf is a sub-buffer of *buf, as created by asn1buf_imbed.
2N/A * lasttag is the last tagnumber read.
2N/A * effects Synchronizes *buf's current position to match that of *subbuf.
2N/A */
2N/A
2N/Aasn1_error_code asn1buf_skiptail(asn1buf *buf, const unsigned int length,
2N/A const int indef);
2N/A/*
2N/A * requires *buf is a subbuffer used in a decoding of a
2N/A * constructed indefinite sequence.
2N/A * effects skips trailing fields.
2N/A */
2N/A
2N/Avoid asn1buf_destroy(asn1buf **buf);
2N/A/* effects Deallocates **buf, sets *buf to NULL. */
2N/A
2N/Aasn1_error_code asn1buf_insert_octet(asn1buf *buf, const int o);
2N/A/*
2N/A * requires *buf is allocated
2N/A * effects Inserts o into the buffer *buf, expanding the buffer if
2N/A * necessary. Returns ENOMEM memory is exhausted.
2N/A */
2N/A#if ((__GNUC__ >= 2) && !defined(ASN1BUF_OMIT_INLINE_FUNCS)) && !defined(CONFIG_SMALL)
2N/Aextern __inline__ asn1_error_code asn1buf_insert_octet(asn1buf *buf, const int o)
2N/A{
2N/A asn1_error_code retval;
2N/A
2N/A retval = asn1buf_ensure_space(buf,1U);
2N/A if (retval) return retval;
2N/A *(buf->next) = (char)o;
2N/A (buf->next)++;
2N/A return 0;
2N/A}
2N/A#endif
2N/A
2N/Aasn1_error_code
2N/Aasn1buf_insert_bytestring(
2N/A asn1buf *buf,
2N/A const unsigned int len,
2N/A const void *s);
2N/A/*
2N/A * requires *buf is allocated
2N/A * modifies *buf
2N/A * effects Inserts the contents of s (an array of length len)
2N/A * into the buffer *buf, expanding the buffer if necessary.
2N/A * Returns ENOMEM if memory is exhausted.
2N/A */
2N/A
2N/A#define asn1buf_insert_octetstring asn1buf_insert_bytestring
2N/A#define asn1buf_insert_charstring asn1buf_insert_bytestring
2N/A
2N/Aasn1_error_code asn1buf_remove_octet(asn1buf *buf, asn1_octet *o);
2N/A/*
2N/A * requires *buf is allocated
2N/A * effects Returns *buf's current octet in *o and advances to
2N/A * the next octet.
2N/A * Returns ASN1_OVERRUN if *buf has already been exhausted.
2N/A */
2N/A#define asn1buf_remove_octet(buf,o) \
2N/A (((buf)->next > (buf)->bound) \
2N/A ? ASN1_OVERRUN \
2N/A : ((*(o) = (asn1_octet)(*(((buf)->next)++))),0))
2N/A
2N/Aasn1_error_code
2N/Aasn1buf_remove_octetstring(
2N/A asn1buf *buf,
2N/A const unsigned int len,
2N/A asn1_octet **s);
2N/A/*
2N/A * requires *buf is allocated
2N/A * effects Removes the next len octets of *buf and returns them in **s.
2N/A * Returns ASN1_OVERRUN if there are fewer than len unread octets
2N/A * left in *buf.
2N/A * Returns ENOMEM if *s could not be allocated.
2N/A */
2N/A
2N/Aasn1_error_code
2N/Aasn1buf_remove_charstring(asn1buf *buf, const unsigned int len, char **s);
2N/A/*
2N/A * requires *buf is allocated
2N/A * effects Removes the next len octets of *buf and returns them in **s.
2N/A * Returns ASN1_OVERRUN if there are fewer than len unread octets
2N/A * left in *buf.
2N/A * Returns ENOMEM if *s could not be allocated.
2N/A */
2N/A
2N/Aasn1_error_code asn1buf_unparse(const asn1buf *buf, char **s);
2N/A/*
2N/A * modifies *s
2N/A * effects Returns a human-readable representation of *buf in *s,
2N/A * where each octet in *buf is represented by a character in *s.
2N/A */
2N/A
2N/Aasn1_error_code asn1buf_hex_unparse(const asn1buf *buf, char **s);
2N/A/*
2N/A * modifies *s
2N/A * effects Returns a human-readable representation of *buf in *s,
2N/A * where each octet in *buf is represented by a 2-digit
2N/A * hexadecimal number in *s.
2N/A */
2N/A
2N/Aasn1_error_code asn12krb5_buf(const asn1buf *buf, krb5_data **code);
2N/A/*
2N/A * modifies *code
2N/A * effects Instantiates **code with the krb5_data representation of **buf.
2N/A */
2N/A
2N/Aint asn1buf_remains(asn1buf *buf, int indef);
2N/A/*
2N/A * requires *buf is a buffer containing an asn.1 structure or array
2N/A * modifies *buf
2N/A * effects Returns the number of unprocessed octets remaining in *buf.
2N/A */
2N/A
2N/A#endif