Exemple #1
0
asn1_error_code
krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val,
                            const struct atype_info *a, unsigned int *retlen)
{
    switch (a->type) {
    case atype_fn:
        assert(a->enc != NULL);
        return a->enc(buf, val, retlen);
    case atype_sequence:
        assert(a->seq != NULL);
        return just_encode_sequence(buf, val, a->seq, retlen);
    case atype_ptr:
        assert(a->basetype != NULL);
        return krb5int_asn1_encode_a_thing(buf, LOADPTR(val, a),
                                           a->basetype, retlen);
    case atype_field:
        assert(a->field != NULL);
        return encode_a_field(buf, val, a->field, retlen);
    case atype_nullterm_sequence_of:
    case atype_nonempty_nullterm_sequence_of:
        assert(a->basetype != NULL);
        return encode_nullterm_sequence_of(buf, val, a->basetype,
                                           a->type == atype_nullterm_sequence_of,
                                           retlen);
    case atype_tagged_thing:
    {
        asn1_error_code retval;
        unsigned int length, sum = 0;
        retval = krb5int_asn1_encode_a_thing(buf, val, a->basetype, &length);
        if (retval) return retval;
        sum = length;
        retval = asn1_make_etag(buf, a->tagtype, a->tagval, sum, &length);
        if (retval) return retval;
        sum += length;
        *retlen = sum;
        return 0;
    }
    case atype_int:
        assert(a->loadint != NULL);
        return asn1_encode_integer(buf, a->loadint(val), retlen);
    case atype_uint:
        assert(a->loaduint != NULL);
        return asn1_encode_unsigned_integer(buf, a->loaduint(val), retlen);
    case atype_min:
    case atype_max:
    case atype_fn_len:
    default:
        assert(a->type > atype_min);
        assert(a->type < atype_max);
        assert(a->type != atype_fn_len);
        abort();
    }
}
Exemple #2
0
/* Encode a value (contents only, no outer tag) according to a type, and return
 * its encoded tag information. */
static asn1_error_code
encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
             taginfo *tag_out, size_t *len_out)
{
    asn1_error_code ret;

    if (val == NULL)
        return ASN1_MISSING_FIELD;

    switch (a->type) {
    case atype_fn: {
        const struct fn_info *fn = a->tinfo;
        assert(fn->enc != NULL);
        return fn->enc(buf, val, tag_out, len_out);
    }
    case atype_sequence:
        assert(a->tinfo != NULL);
        ret = encode_sequence(buf, val, a->tinfo, len_out);
        if (ret)
            return ret;
        tag_out->asn1class = UNIVERSAL;
        tag_out->construction = CONSTRUCTED;
        tag_out->tagnum = ASN1_SEQUENCE;
        break;
    case atype_ptr: {
        const struct ptr_info *ptr = a->tinfo;
        assert(ptr->basetype != NULL);
        return encode_atype(buf, LOADPTR(val, ptr), ptr->basetype, tag_out,
                            len_out);
    }
    case atype_offset: {
        const struct offset_info *off = a->tinfo;
        assert(off->basetype != NULL);
        return encode_atype(buf, (const char *)val + off->dataoff,
                            off->basetype, tag_out, len_out);
    }
    case atype_optional: {
        const struct optional_info *opt = a->tinfo;
        assert(opt->is_present != NULL);
        if (opt->is_present(val))
            return encode_atype(buf, val, opt->basetype, tag_out, len_out);
        else
            return ASN1_OMITTED;
    }
    case atype_counted: {
        const struct counted_info *counted = a->tinfo;
        const void *dataptr = (const char *)val + counted->dataoff;
        size_t count;
        assert(counted->basetype != NULL);
        ret = load_count(val, counted, &count);
        if (ret)
            return ret;
        return encode_cntype(buf, dataptr, count, counted->basetype, tag_out,
                             len_out);
    }
    case atype_nullterm_sequence_of:
    case atype_nonempty_nullterm_sequence_of:
        assert(a->tinfo != NULL);
        ret = encode_nullterm_sequence_of(buf, val, a->tinfo,
                                          a->type ==
                                          atype_nullterm_sequence_of,
                                          len_out);
        if (ret)
            return ret;
        tag_out->asn1class = UNIVERSAL;
        tag_out->construction = CONSTRUCTED;
        tag_out->tagnum = ASN1_SEQUENCE;
        break;
    case atype_tagged_thing: {
        const struct tagged_info *tag = a->tinfo;
        ret = encode_atype(buf, val, tag->basetype, tag_out, len_out);
        if (ret)
            return ret;
        if (!tag->implicit) {
            size_t tlen;
            ret = make_tag(buf, tag_out, *len_out, &tlen);
            if (ret)
                return ret;
            *len_out += tlen;
            tag_out->construction = tag->construction;
        }
        tag_out->asn1class = tag->tagtype;
        tag_out->tagnum = tag->tagval;
        break;
    }
    case atype_bool:
        ret = k5_asn1_encode_bool(buf, load_int(val, a->size), len_out);
        if (ret)
            return ret;
        tag_out->asn1class = UNIVERSAL;
        tag_out->construction = PRIMITIVE;
        tag_out->tagnum = ASN1_BOOLEAN;
        break;
    case atype_int:
        ret = k5_asn1_encode_int(buf, load_int(val, a->size), len_out);
        if (ret)
            return ret;
        tag_out->asn1class = UNIVERSAL;
        tag_out->construction = PRIMITIVE;
        tag_out->tagnum = ASN1_INTEGER;
        break;
    case atype_uint:
        ret = k5_asn1_encode_uint(buf, load_uint(val, a->size), len_out);
        if (ret)
            return ret;
        tag_out->asn1class = UNIVERSAL;
        tag_out->construction = PRIMITIVE;
        tag_out->tagnum = ASN1_INTEGER;
        break;
    case atype_int_immediate: {
        const struct immediate_info *imm = a->tinfo;
        ret = k5_asn1_encode_int(buf, imm->val, len_out);
        if (ret)
            return ret;
        tag_out->asn1class = UNIVERSAL;
        tag_out->construction = PRIMITIVE;
        tag_out->tagnum = ASN1_INTEGER;
        break;
    }
    default:
        assert(a->type > atype_min);
        assert(a->type < atype_max);
        abort();
    }

    return 0;
}