Beispiel #1
0
static asn1_error_code
encode_nullterm_sequence_of(asn1buf *buf, const void *val,
                            const struct atype_info *type,
                            int can_be_empty,
                            unsigned int *retlen)
{
    int length = get_nullterm_sequence_len(val, type);
    if (!can_be_empty && length == 0) return ASN1_MISSING_FIELD;
    return encode_sequence_of(buf, length, val, type, retlen);
}
Beispiel #2
0
static asn1_error_code
encode_nullterm_sequence_of(asn1buf *buf, const void *val,
                            const struct atype_info *type,
                            int can_be_empty, size_t *len_out)
{
    size_t len = get_nullterm_sequence_len(val, type);

    if (!can_be_empty && len == 0)
        return ASN1_MISSING_FIELD;
    return encode_sequence_of(buf, len, val, type, len_out);
}
Beispiel #3
0
/*
 * Encode an object and count according to a cntype_info structure.  val is a
 * pointer to the object being encoded, which in most cases is itself a
 * pointer (but is a union in the cntype_choice case).
 */
static asn1_error_code
encode_cntype(asn1buf *buf, const void *val, size_t count,
              const struct cntype_info *c, taginfo *tag_out, size_t *len_out)
{
    asn1_error_code ret;

    switch (c->type) {
    case cntype_string: {
        const struct string_info *string = c->tinfo;
        assert(string->enc != NULL);
        ret = string->enc(buf, val, count, len_out);
        if (ret)
            return ret;
        tag_out->asn1class = UNIVERSAL;
        tag_out->construction = PRIMITIVE;
        tag_out->tagnum = string->tagval;
        break;
    }
    case cntype_der:
        return split_der(buf, val, count, tag_out, len_out);
    case cntype_seqof: {
        const struct atype_info *a = c->tinfo;
        const struct ptr_info *ptr = a->tinfo;
        assert(a->type == atype_ptr);
        val = LOADPTR(val, ptr);
        ret = encode_sequence_of(buf, count, val, ptr->basetype, len_out);
        if (ret)
            return ret;
        tag_out->asn1class = UNIVERSAL;
        tag_out->construction = CONSTRUCTED;
        tag_out->tagnum = ASN1_SEQUENCE;
        break;
    }
    case cntype_choice: {
        const struct choice_info *choice = c->tinfo;
        if (count >= choice->n_options)
            return ASN1_MISSING_FIELD;
        return encode_atype(buf, val, choice->options[count], tag_out,
                            len_out);
    }

    default:
        assert(c->type > cntype_min);
        assert(c->type < cntype_max);
        abort();
    }

    return 0;
}
Beispiel #4
0
static asn1_error_code
encode_a_field(asn1buf *buf, const void *val,
               const struct field_info *field,
               unsigned int *retlen)
{
    asn1_error_code retval;
    unsigned int sum = 0;

    if (val == NULL) return ASN1_MISSING_FIELD;

    switch (field->ftype) {
    case field_immediate:
    {
        unsigned int length;

        retval = asn1_encode_integer(buf, (asn1_intmax) field->dataoff,
                                     &length);
        if (retval) return retval;
        sum += length;
        break;
    }
    case field_sequenceof_len:
    {
        const void *dataptr, *lenptr;
        int slen;
        unsigned int length;
        const struct atype_info *a;

        /*
         * The field holds a pointer to the array of objects.  So the
         * address we compute is a pointer-to-pointer, and that's what
         * field->atype must help us dereference.
         */
        dataptr = (const char *)val + field->dataoff;
        lenptr = (const char *)val + field->lenoff;
        assert(field->atype->type == atype_ptr);
        dataptr = LOADPTR(dataptr, field->atype);
        a = field->atype->basetype;
        assert(field->lentype != 0);
        assert(field->lentype->type == atype_int || field->lentype->type == atype_uint);
        assert(sizeof(int) <= sizeof(asn1_intmax));
        assert(sizeof(unsigned int) <= sizeof(asn1_uintmax));
        if (field->lentype->type == atype_int) {
            asn1_intmax xlen = field->lentype->loadint(lenptr);
            if (xlen < 0)
                return EINVAL;
            if ((unsigned int) xlen != (asn1_uintmax) xlen)
                return EINVAL;
            if ((unsigned int) xlen > INT_MAX)
                return EINVAL;
            slen = (int) xlen;
        } else {
            asn1_uintmax xlen = field->lentype->loaduint(lenptr);
            if ((unsigned int) xlen != xlen)
                return EINVAL;
            if (xlen > INT_MAX)
                return EINVAL;
            slen = (int) xlen;
        }
        if (slen != 0 && dataptr == NULL)
            return ASN1_MISSING_FIELD;
        retval = encode_sequence_of(buf, slen, dataptr, a, &length);
        if (retval) return retval;
        sum += length;
        break;
    }
    case field_normal:
    {
        const void *dataptr;
        const struct atype_info *a;
        unsigned int length;

        dataptr = (const char *)val + field->dataoff;

        a = field->atype;
        assert(a->type != atype_fn_len);
        retval = krb5int_asn1_encode_a_thing(buf, dataptr, a, &length);
        if (retval) {
            return retval;
        }
        sum += length;
        break;
    }
    case field_string:
    {
        const void *dataptr, *lenptr;
        const struct atype_info *a;
        size_t slen;
        unsigned int length;

        dataptr = (const char *)val + field->dataoff;
        lenptr = (const char *)val + field->lenoff;

        a = field->atype;
        assert(a->type == atype_fn_len);
        assert(field->lentype != 0);
        assert(field->lentype->type == atype_int || field->lentype->type == atype_uint);
        assert(sizeof(int) <= sizeof(asn1_intmax));
        assert(sizeof(unsigned int) <= sizeof(asn1_uintmax));
        if (field->lentype->type == atype_int) {
            asn1_intmax xlen = field->lentype->loadint(lenptr);
            if (xlen < 0)
                return EINVAL;
            if ((size_t) xlen != (asn1_uintmax) xlen)
                return EINVAL;
            slen = (size_t) xlen;
        } else {
            asn1_uintmax xlen = field->lentype->loaduint(lenptr);
            if ((size_t) xlen != xlen)
                return EINVAL;
            slen = (size_t) xlen;
        }

        dataptr = LOADPTR(dataptr, a);
        if (slen == SIZE_MAX)
            /* Error - negative or out of size_t range.  */
            return EINVAL;
        if (dataptr == NULL && slen != 0)
            return ASN1_MISSING_FIELD;
        /*
         * Currently our string encoders want "unsigned int" for
         * lengths.
         */
        if (slen != (unsigned int) slen)
            return EINVAL;
        assert(a->enclen != NULL);
        retval = a->enclen(buf, (unsigned int) slen, dataptr, &length);
        if (retval) {
            return retval;
        }
        sum += length;
        break;
    }
    default:
        assert(field->ftype > field_min);
        assert(field->ftype < field_max);
        assert(__LINE__ == 0);
        abort();
    }
    if (field->tag >= 0) {
        unsigned int length;
        retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, field->tag, sum,
                                &length);
        if (retval) {
            return retval;
        }
        sum += length;
    }
    *retlen = sum;
    return 0;
}