merging
authorVolker Birk <vb@pep-project.org>
Wed, 11 May 2016 20:06:23 +0200
changeset 6038bff69e425d3
parent 602 41fc6ea3548b
parent 601 4811189c7f9a
child 604 ba04c2bd81a1
merging
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/asn.1/BIT_STRING.c	Wed May 11 20:06:23 2016 +0200
     1.3 @@ -0,0 +1,189 @@
     1.4 +/*-
     1.5 + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
     1.6 + * Redistribution and modifications are permitted subject to BSD license.
     1.7 + */
     1.8 +#include <asn_internal.h>
     1.9 +#include <BIT_STRING.h>
    1.10 +#include <asn_internal.h>
    1.11 +
    1.12 +/*
    1.13 + * BIT STRING basic type description.
    1.14 + */
    1.15 +static ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = {
    1.16 +	(ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
    1.17 +};
    1.18 +static asn_OCTET_STRING_specifics_t asn_DEF_BIT_STRING_specs = {
    1.19 +	sizeof(BIT_STRING_t),
    1.20 +	offsetof(BIT_STRING_t, _asn_ctx),
    1.21 +	ASN_OSUBV_BIT
    1.22 +};
    1.23 +asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
    1.24 +	"BIT STRING",
    1.25 +	"BIT_STRING",
    1.26 +	OCTET_STRING_free,         /* Implemented in terms of OCTET STRING */
    1.27 +	BIT_STRING_print,
    1.28 +	BIT_STRING_constraint,
    1.29 +	OCTET_STRING_decode_ber,   /* Implemented in terms of OCTET STRING */
    1.30 +	OCTET_STRING_encode_der,   /* Implemented in terms of OCTET STRING */
    1.31 +	OCTET_STRING_decode_xer_binary,
    1.32 +	BIT_STRING_encode_xer,
    1.33 +	OCTET_STRING_decode_uper,	/* Unaligned PER decoder */
    1.34 +	OCTET_STRING_encode_uper,	/* Unaligned PER encoder */
    1.35 +	0, /* Use generic outmost tag fetcher */
    1.36 +	asn_DEF_BIT_STRING_tags,
    1.37 +	sizeof(asn_DEF_BIT_STRING_tags)
    1.38 +	  / sizeof(asn_DEF_BIT_STRING_tags[0]),
    1.39 +	asn_DEF_BIT_STRING_tags,	/* Same as above */
    1.40 +	sizeof(asn_DEF_BIT_STRING_tags)
    1.41 +	  / sizeof(asn_DEF_BIT_STRING_tags[0]),
    1.42 +	0,	/* No PER visible constraints */
    1.43 +	0, 0,	/* No members */
    1.44 +	&asn_DEF_BIT_STRING_specs
    1.45 +};
    1.46 +
    1.47 +/*
    1.48 + * BIT STRING generic constraint.
    1.49 + */
    1.50 +int
    1.51 +BIT_STRING_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
    1.52 +		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
    1.53 +	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
    1.54 +
    1.55 +	if(st && st->buf) {
    1.56 +		if((st->size == 0 && st->bits_unused)
    1.57 +		|| st->bits_unused < 0 || st->bits_unused > 7) {
    1.58 +			_ASN_CTFAIL(app_key, td, sptr,
    1.59 +				"%s: invalid padding byte (%s:%d)",
    1.60 +				td->name, __FILE__, __LINE__);
    1.61 +			return -1;
    1.62 +		}
    1.63 +	} else {
    1.64 +		_ASN_CTFAIL(app_key, td, sptr,
    1.65 +			"%s: value not given (%s:%d)",
    1.66 +			td->name, __FILE__, __LINE__);
    1.67 +		return -1;
    1.68 +	}
    1.69 +
    1.70 +	return 0;
    1.71 +}
    1.72 +
    1.73 +static char *_bit_pattern[16] = {
    1.74 +	"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
    1.75 +	"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
    1.76 +};
    1.77 +
    1.78 +asn_enc_rval_t
    1.79 +BIT_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
    1.80 +	int ilevel, enum xer_encoder_flags_e flags,
    1.81 +		asn_app_consume_bytes_f *cb, void *app_key) {
    1.82 +	asn_enc_rval_t er;
    1.83 +	char scratch[128];
    1.84 +	char *p = scratch;
    1.85 +	char *scend = scratch + (sizeof(scratch) - 10);
    1.86 +	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
    1.87 +	int xcan = (flags & XER_F_CANONICAL);
    1.88 +	uint8_t *buf;
    1.89 +	uint8_t *end;
    1.90 +
    1.91 +	if(!st || !st->buf)
    1.92 +		_ASN_ENCODE_FAILED;
    1.93 +
    1.94 +	er.encoded = 0;
    1.95 +
    1.96 +	buf = st->buf;
    1.97 +	end = buf + st->size - 1;	/* Last byte is special */
    1.98 +
    1.99 +	/*
   1.100 +	 * Binary dump
   1.101 +	 */
   1.102 +	for(; buf < end; buf++) {
   1.103 +		int v = *buf;
   1.104 +		int nline = xcan?0:(((buf - st->buf) % 8) == 0);
   1.105 +		if(p >= scend || nline) {
   1.106 +			er.encoded += p - scratch;
   1.107 +			_ASN_CALLBACK(scratch, p - scratch);
   1.108 +			p = scratch;
   1.109 +			if(nline) _i_ASN_TEXT_INDENT(1, ilevel);
   1.110 +		}
   1.111 +		memcpy(p + 0, _bit_pattern[v >> 4], 4);
   1.112 +		memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
   1.113 +		p += 8;
   1.114 +	}
   1.115 +
   1.116 +	if(!xcan && ((buf - st->buf) % 8) == 0)
   1.117 +		_i_ASN_TEXT_INDENT(1, ilevel);
   1.118 +	er.encoded += p - scratch;
   1.119 +	_ASN_CALLBACK(scratch, p - scratch);
   1.120 +	p = scratch;
   1.121 +
   1.122 +	if(buf == end) {
   1.123 +		int v = *buf;
   1.124 +		int ubits = st->bits_unused;
   1.125 +		int i;
   1.126 +		for(i = 7; i >= ubits; i--)
   1.127 +			*p++ = (v & (1 << i)) ? 0x31 : 0x30;
   1.128 +		er.encoded += p - scratch;
   1.129 +		_ASN_CALLBACK(scratch, p - scratch);
   1.130 +	}
   1.131 +
   1.132 +	if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1);
   1.133 +
   1.134 +	_ASN_ENCODED_OK(er);
   1.135 +cb_failed:
   1.136 +	_ASN_ENCODE_FAILED;
   1.137 +}
   1.138 +
   1.139 +
   1.140 +/*
   1.141 + * BIT STRING specific contents printer.
   1.142 + */
   1.143 +int
   1.144 +BIT_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
   1.145 +		asn_app_consume_bytes_f *cb, void *app_key) {
   1.146 +	static const char *h2c = "0123456789ABCDEF";
   1.147 +	char scratch[64];
   1.148 +	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
   1.149 +	uint8_t *buf;
   1.150 +	uint8_t *end;
   1.151 +	char *p = scratch;
   1.152 +
   1.153 +	(void)td;	/* Unused argument */
   1.154 +
   1.155 +	if(!st || !st->buf)
   1.156 +		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
   1.157 +
   1.158 +	ilevel++;
   1.159 +	buf = st->buf;
   1.160 +	end = buf + st->size;
   1.161 +
   1.162 +	/*
   1.163 +	 * Hexadecimal dump.
   1.164 +	 */
   1.165 +	for(; buf < end; buf++) {
   1.166 +		if((buf - st->buf) % 16 == 0 && (st->size > 16)
   1.167 +				&& buf != st->buf) {
   1.168 +			_i_INDENT(1);
   1.169 +			/* Dump the string */
   1.170 +			if(cb(scratch, p - scratch, app_key) < 0) return -1;
   1.171 +			p = scratch;
   1.172 +		}
   1.173 +		*p++ = h2c[*buf >> 4];
   1.174 +		*p++ = h2c[*buf & 0x0F];
   1.175 +		*p++ = 0x20;
   1.176 +	}
   1.177 +
   1.178 +	if(p > scratch) {
   1.179 +		p--;	/* Eat the tailing space */
   1.180 +
   1.181 +		if((st->size > 16)) {
   1.182 +			_i_INDENT(1);
   1.183 +		}
   1.184 +
   1.185 +		/* Dump the incomplete 16-bytes row */
   1.186 +		if(cb(scratch, p - scratch, app_key) < 0)
   1.187 +			return -1;
   1.188 +	}
   1.189 +
   1.190 +	return 0;
   1.191 +}
   1.192 +
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/asn.1/BIT_STRING.h	Wed May 11 20:06:23 2016 +0200
     2.3 @@ -0,0 +1,33 @@
     2.4 +/*-
     2.5 + * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
     2.6 + * Redistribution and modifications are permitted subject to BSD license.
     2.7 + */
     2.8 +#ifndef	_BIT_STRING_H_
     2.9 +#define	_BIT_STRING_H_
    2.10 +
    2.11 +#include <OCTET_STRING.h>	/* Some help from OCTET STRING */
    2.12 +
    2.13 +#ifdef __cplusplus
    2.14 +extern "C" {
    2.15 +#endif
    2.16 +
    2.17 +typedef struct BIT_STRING_s {
    2.18 +	uint8_t *buf;	/* BIT STRING body */
    2.19 +	int size;	/* Size of the above buffer */
    2.20 +
    2.21 +	int bits_unused;/* Unused trailing bits in the last octet (0..7) */
    2.22 +
    2.23 +	asn_struct_ctx_t _asn_ctx;	/* Parsing across buffer boundaries */
    2.24 +} BIT_STRING_t;
    2.25 +
    2.26 +extern asn_TYPE_descriptor_t asn_DEF_BIT_STRING;
    2.27 +
    2.28 +asn_struct_print_f BIT_STRING_print;	/* Human-readable output */
    2.29 +asn_constr_check_f BIT_STRING_constraint;
    2.30 +xer_type_encoder_f BIT_STRING_encode_xer;
    2.31 +
    2.32 +#ifdef __cplusplus
    2.33 +}
    2.34 +#endif
    2.35 +
    2.36 +#endif	/* _BIT_STRING_H_ */
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/asn.1/Header.c	Wed May 11 20:06:23 2016 +0200
     3.3 @@ -0,0 +1,139 @@
     3.4 +/*
     3.5 + * Generated by asn1c-0.9.26 (http://lionet.info/asn1c)
     3.6 + * From ASN.1 module "PEP"
     3.7 + * 	found in "pEp.asn1"
     3.8 + */
     3.9 +
    3.10 +#include "Header.h"
    3.11 +
    3.12 +static int
    3.13 +memb_protocol_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr,
    3.14 +			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
    3.15 +	long value;
    3.16 +	
    3.17 +	if(!sptr) {
    3.18 +		_ASN_CTFAIL(app_key, td, sptr,
    3.19 +			"%s: value not given (%s:%d)",
    3.20 +			td->name, __FILE__, __LINE__);
    3.21 +		return -1;
    3.22 +	}
    3.23 +	
    3.24 +	value = *(const long *)sptr;
    3.25 +	
    3.26 +	if((value >= 0 && value <= 65535)) {
    3.27 +		/* Constraint check succeeded */
    3.28 +		return 0;
    3.29 +	} else {
    3.30 +		_ASN_CTFAIL(app_key, td, sptr,
    3.31 +			"%s: constraint failed (%s:%d)",
    3.32 +			td->name, __FILE__, __LINE__);
    3.33 +		return -1;
    3.34 +	}
    3.35 +}
    3.36 +
    3.37 +static int
    3.38 +memb_message_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr,
    3.39 +			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
    3.40 +	long value;
    3.41 +	
    3.42 +	if(!sptr) {
    3.43 +		_ASN_CTFAIL(app_key, td, sptr,
    3.44 +			"%s: value not given (%s:%d)",
    3.45 +			td->name, __FILE__, __LINE__);
    3.46 +		return -1;
    3.47 +	}
    3.48 +	
    3.49 +	value = *(const long *)sptr;
    3.50 +	
    3.51 +	if((value >= 0 && value <= 65535)) {
    3.52 +		/* Constraint check succeeded */
    3.53 +		return 0;
    3.54 +	} else {
    3.55 +		_ASN_CTFAIL(app_key, td, sptr,
    3.56 +			"%s: constraint failed (%s:%d)",
    3.57 +			td->name, __FILE__, __LINE__);
    3.58 +		return -1;
    3.59 +	}
    3.60 +}
    3.61 +
    3.62 +static asn_per_constraints_t asn_PER_memb_protocol_constr_2 GCC_NOTUSED = {
    3.63 +	{ APC_CONSTRAINED,	 16,  16,  0,  65535 }	/* (0..65535) */,
    3.64 +	{ APC_UNCONSTRAINED,	-1, -1,  0,  0 },
    3.65 +	0, 0	/* No PER value map */
    3.66 +};
    3.67 +static asn_per_constraints_t asn_PER_memb_message_constr_4 GCC_NOTUSED = {
    3.68 +	{ APC_CONSTRAINED,	 16,  16,  0,  65535 }	/* (0..65535) */,
    3.69 +	{ APC_UNCONSTRAINED,	-1, -1,  0,  0 },
    3.70 +	0, 0	/* No PER value map */
    3.71 +};
    3.72 +static asn_TYPE_member_t asn_MBR_Header_1[] = {
    3.73 +	{ ATF_NOFLAGS, 0, offsetof(struct Header, protocol),
    3.74 +		(ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
    3.75 +		0,
    3.76 +		&asn_DEF_NativeInteger,
    3.77 +		memb_protocol_constraint_1,
    3.78 +		&asn_PER_memb_protocol_constr_2,
    3.79 +		0,
    3.80 +		"protocol"
    3.81 +		},
    3.82 +	{ ATF_NOFLAGS, 0, offsetof(struct Header, version),
    3.83 +		(ASN_TAG_CLASS_UNIVERSAL | (16 << 2)),
    3.84 +		0,
    3.85 +		&asn_DEF_Version,
    3.86 +		0,	/* Defer constraints checking to the member type */
    3.87 +		0,	/* No PER visible constraints */
    3.88 +		0,
    3.89 +		"version"
    3.90 +		},
    3.91 +	{ ATF_NOFLAGS, 0, offsetof(struct Header, message),
    3.92 +		(ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
    3.93 +		0,
    3.94 +		&asn_DEF_NativeInteger,
    3.95 +		memb_message_constraint_1,
    3.96 +		&asn_PER_memb_message_constr_4,
    3.97 +		0,
    3.98 +		"message"
    3.99 +		},
   3.100 +};
   3.101 +static ber_tlv_tag_t asn_DEF_Header_tags_1[] = {
   3.102 +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
   3.103 +};
   3.104 +static asn_TYPE_tag2member_t asn_MAP_Header_tag2el_1[] = {
   3.105 +    { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 1 }, /* protocol */
   3.106 +    { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 2, -1, 0 }, /* message */
   3.107 +    { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 1, 0, 0 } /* version */
   3.108 +};
   3.109 +static asn_SEQUENCE_specifics_t asn_SPC_Header_specs_1 = {
   3.110 +	sizeof(struct Header),
   3.111 +	offsetof(struct Header, _asn_ctx),
   3.112 +	asn_MAP_Header_tag2el_1,
   3.113 +	3,	/* Count of tags in the map */
   3.114 +	0, 0, 0,	/* Optional elements (not needed) */
   3.115 +	-1,	/* Start extensions */
   3.116 +	-1	/* Stop extensions */
   3.117 +};
   3.118 +asn_TYPE_descriptor_t asn_DEF_Header = {
   3.119 +	"Header",
   3.120 +	"Header",
   3.121 +	SEQUENCE_free,
   3.122 +	SEQUENCE_print,
   3.123 +	SEQUENCE_constraint,
   3.124 +	SEQUENCE_decode_ber,
   3.125 +	SEQUENCE_encode_der,
   3.126 +	SEQUENCE_decode_xer,
   3.127 +	SEQUENCE_encode_xer,
   3.128 +	SEQUENCE_decode_uper,
   3.129 +	SEQUENCE_encode_uper,
   3.130 +	0,	/* Use generic outmost tag fetcher */
   3.131 +	asn_DEF_Header_tags_1,
   3.132 +	sizeof(asn_DEF_Header_tags_1)
   3.133 +		/sizeof(asn_DEF_Header_tags_1[0]), /* 1 */
   3.134 +	asn_DEF_Header_tags_1,	/* Same as above */
   3.135 +	sizeof(asn_DEF_Header_tags_1)
   3.136 +		/sizeof(asn_DEF_Header_tags_1[0]), /* 1 */
   3.137 +	0,	/* No PER visible constraints */
   3.138 +	asn_MBR_Header_1,
   3.139 +	3,	/* Elements count */
   3.140 +	&asn_SPC_Header_specs_1	/* Additional specs */
   3.141 +};
   3.142 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/asn.1/Header.h	Wed May 11 20:06:23 2016 +0200
     4.3 @@ -0,0 +1,40 @@
     4.4 +/*
     4.5 + * Generated by asn1c-0.9.26 (http://lionet.info/asn1c)
     4.6 + * From ASN.1 module "PEP"
     4.7 + * 	found in "pEp.asn1"
     4.8 + */
     4.9 +
    4.10 +#ifndef	_Header_H_
    4.11 +#define	_Header_H_
    4.12 +
    4.13 +
    4.14 +#include <asn_application.h>
    4.15 +
    4.16 +/* Including external dependencies */
    4.17 +#include <NativeInteger.h>
    4.18 +#include "Version.h"
    4.19 +#include <constr_SEQUENCE.h>
    4.20 +
    4.21 +#ifdef __cplusplus
    4.22 +extern "C" {
    4.23 +#endif
    4.24 +
    4.25 +/* Header */
    4.26 +typedef struct Header {
    4.27 +	long	 protocol;
    4.28 +	Version_t	 version;
    4.29 +	long	 message;
    4.30 +	
    4.31 +	/* Context for parsing across buffer boundaries */
    4.32 +	asn_struct_ctx_t _asn_ctx;
    4.33 +} Header_t;
    4.34 +
    4.35 +/* Implementation */
    4.36 +extern asn_TYPE_descriptor_t asn_DEF_Header;
    4.37 +
    4.38 +#ifdef __cplusplus
    4.39 +}
    4.40 +#endif
    4.41 +
    4.42 +#endif	/* _Header_H_ */
    4.43 +#include <asn_internal.h>
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/asn.1/INTEGER.c	Wed May 11 20:06:23 2016 +0200
     5.3 @@ -0,0 +1,1023 @@
     5.4 +/*-
     5.5 + * Copyright (c) 2003-2014 Lev Walkin <vlm@lionet.info>.
     5.6 + * All rights reserved.
     5.7 + * Redistribution and modifications are permitted subject to BSD license.
     5.8 + */
     5.9 +#include <asn_internal.h>
    5.10 +#include <INTEGER.h>
    5.11 +#include <asn_codecs_prim.h>	/* Encoder and decoder of a primitive type */
    5.12 +#include <errno.h>
    5.13 +
    5.14 +/*
    5.15 + * INTEGER basic type description.
    5.16 + */
    5.17 +static ber_tlv_tag_t asn_DEF_INTEGER_tags[] = {
    5.18 +	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
    5.19 +};
    5.20 +asn_TYPE_descriptor_t asn_DEF_INTEGER = {
    5.21 +	"INTEGER",
    5.22 +	"INTEGER",
    5.23 +	ASN__PRIMITIVE_TYPE_free,
    5.24 +	INTEGER_print,
    5.25 +	asn_generic_no_constraint,
    5.26 +	ber_decode_primitive,
    5.27 +	INTEGER_encode_der,
    5.28 +	INTEGER_decode_xer,
    5.29 +	INTEGER_encode_xer,
    5.30 +#ifdef	ASN_DISABLE_PER_SUPPORT
    5.31 +	0,
    5.32 +	0,
    5.33 +#else
    5.34 +	INTEGER_decode_uper,	/* Unaligned PER decoder */
    5.35 +	INTEGER_encode_uper,	/* Unaligned PER encoder */
    5.36 +#endif	/* ASN_DISABLE_PER_SUPPORT */
    5.37 +	0, /* Use generic outmost tag fetcher */
    5.38 +	asn_DEF_INTEGER_tags,
    5.39 +	sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
    5.40 +	asn_DEF_INTEGER_tags,	/* Same as above */
    5.41 +	sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
    5.42 +	0,	/* No PER visible constraints */
    5.43 +	0, 0,	/* No members */
    5.44 +	0	/* No specifics */
    5.45 +};
    5.46 +
    5.47 +/*
    5.48 + * Encode INTEGER type using DER.
    5.49 + */
    5.50 +asn_enc_rval_t
    5.51 +INTEGER_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
    5.52 +	int tag_mode, ber_tlv_tag_t tag,
    5.53 +	asn_app_consume_bytes_f *cb, void *app_key) {
    5.54 +	INTEGER_t *st = (INTEGER_t *)sptr;
    5.55 +
    5.56 +	ASN_DEBUG("%s %s as INTEGER (tm=%d)",
    5.57 +		cb?"Encoding":"Estimating", td->name, tag_mode);
    5.58 +
    5.59 +	/*
    5.60 +	 * Canonicalize integer in the buffer.
    5.61 +	 * (Remove too long sign extension, remove some first 0x00 bytes)
    5.62 +	 */
    5.63 +	if(st->buf) {
    5.64 +		uint8_t *buf = st->buf;
    5.65 +		uint8_t *end1 = buf + st->size - 1;
    5.66 +		int shift;
    5.67 +
    5.68 +		/* Compute the number of superfluous leading bytes */
    5.69 +		for(; buf < end1; buf++) {
    5.70 +			/*
    5.71 +			 * If the contents octets of an integer value encoding
    5.72 +			 * consist of more than one octet, then the bits of the
    5.73 +			 * first octet and bit 8 of the second octet:
    5.74 +			 * a) shall not all be ones; and
    5.75 +			 * b) shall not all be zero.
    5.76 +			 */
    5.77 +			switch(*buf) {
    5.78 +			case 0x00: if((buf[1] & 0x80) == 0)
    5.79 +					continue;
    5.80 +				break;
    5.81 +			case 0xff: if((buf[1] & 0x80))
    5.82 +					continue;
    5.83 +				break;
    5.84 +			}
    5.85 +			break;
    5.86 +		}
    5.87 +
    5.88 +		/* Remove leading superfluous bytes from the integer */
    5.89 +		shift = buf - st->buf;
    5.90 +		if(shift) {
    5.91 +			uint8_t *nb = st->buf;
    5.92 +			uint8_t *end;
    5.93 +
    5.94 +			st->size -= shift;	/* New size, minus bad bytes */
    5.95 +			end = nb + st->size;
    5.96 +
    5.97 +			for(; nb < end; nb++, buf++)
    5.98 +				*nb = *buf;
    5.99 +		}
   5.100 +
   5.101 +	} /* if(1) */
   5.102 +
   5.103 +	return der_encode_primitive(td, sptr, tag_mode, tag, cb, app_key);
   5.104 +}
   5.105 +
   5.106 +static const asn_INTEGER_enum_map_t *INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop);
   5.107 +
   5.108 +/*
   5.109 + * INTEGER specific human-readable output.
   5.110 + */
   5.111 +static ssize_t
   5.112 +INTEGER__dump(asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) {
   5.113 +	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
   5.114 +	char scratch[32];	/* Enough for 64-bit integer */
   5.115 +	uint8_t *buf = st->buf;
   5.116 +	uint8_t *buf_end = st->buf + st->size;
   5.117 +	signed long value;
   5.118 +	ssize_t wrote = 0;
   5.119 +	char *p;
   5.120 +	int ret;
   5.121 +
   5.122 +	if(specs && specs->field_unsigned)
   5.123 +		ret = asn_INTEGER2ulong(st, (unsigned long *)&value);
   5.124 +	else
   5.125 +		ret = asn_INTEGER2long(st, &value);
   5.126 +
   5.127 +	/* Simple case: the integer size is small */
   5.128 +	if(ret == 0) {
   5.129 +		const asn_INTEGER_enum_map_t *el;
   5.130 +		size_t scrsize;
   5.131 +		char *scr;
   5.132 +
   5.133 +		el = (value >= 0 || !specs || !specs->field_unsigned)
   5.134 +			? INTEGER_map_value2enum(specs, value) : 0;
   5.135 +		if(el) {
   5.136 +			scrsize = el->enum_len + 32;
   5.137 +			scr = (char *)alloca(scrsize);
   5.138 +			if(plainOrXER == 0)
   5.139 +				ret = snprintf(scr, scrsize,
   5.140 +					"%ld (%s)", value, el->enum_name);
   5.141 +			else
   5.142 +				ret = snprintf(scr, scrsize,
   5.143 +					"<%s/>", el->enum_name);
   5.144 +		} else if(plainOrXER && specs && specs->strict_enumeration) {
   5.145 +			ASN_DEBUG("ASN.1 forbids dealing with "
   5.146 +				"unknown value of ENUMERATED type");
   5.147 +			errno = EPERM;
   5.148 +			return -1;
   5.149 +		} else {
   5.150 +			scrsize = sizeof(scratch);
   5.151 +			scr = scratch;
   5.152 +			ret = snprintf(scr, scrsize,
   5.153 +				(specs && specs->field_unsigned)
   5.154 +				?"%lu":"%ld", value);
   5.155 +		}
   5.156 +		assert(ret > 0 && (size_t)ret < scrsize);
   5.157 +		return (cb(scr, ret, app_key) < 0) ? -1 : ret;
   5.158 +	} else if(plainOrXER && specs && specs->strict_enumeration) {
   5.159 +		/*
   5.160 +		 * Here and earlier, we cannot encode the ENUMERATED values
   5.161 +		 * if there is no corresponding identifier.
   5.162 +		 */
   5.163 +		ASN_DEBUG("ASN.1 forbids dealing with "
   5.164 +			"unknown value of ENUMERATED type");
   5.165 +		errno = EPERM;
   5.166 +		return -1;
   5.167 +	}
   5.168 +
   5.169 +	/* Output in the long xx:yy:zz... format */
   5.170 +	/* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */
   5.171 +	for(p = scratch; buf < buf_end; buf++) {
   5.172 +		static const char *h2c = "0123456789ABCDEF";
   5.173 +		if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {
   5.174 +			/* Flush buffer */
   5.175 +			if(cb(scratch, p - scratch, app_key) < 0)
   5.176 +				return -1;
   5.177 +			wrote += p - scratch;
   5.178 +			p = scratch;
   5.179 +		}
   5.180 +		*p++ = h2c[*buf >> 4];
   5.181 +		*p++ = h2c[*buf & 0x0F];
   5.182 +		*p++ = 0x3a;	/* ":" */
   5.183 +	}
   5.184 +	if(p != scratch)
   5.185 +		p--;	/* Remove the last ":" */
   5.186 +
   5.187 +	wrote += p - scratch;
   5.188 +	return (cb(scratch, p - scratch, app_key) < 0) ? -1 : wrote;
   5.189 +}
   5.190 +
   5.191 +/*
   5.192 + * INTEGER specific human-readable output.
   5.193 + */
   5.194 +int
   5.195 +INTEGER_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
   5.196 +	asn_app_consume_bytes_f *cb, void *app_key) {
   5.197 +	const INTEGER_t *st = (const INTEGER_t *)sptr;
   5.198 +	ssize_t ret;
   5.199 +
   5.200 +	(void)td;
   5.201 +	(void)ilevel;
   5.202 +
   5.203 +	if(!st || !st->buf)
   5.204 +		ret = cb("<absent>", 8, app_key);
   5.205 +	else
   5.206 +		ret = INTEGER__dump(td, st, cb, app_key, 0);
   5.207 +
   5.208 +	return (ret < 0) ? -1 : 0;
   5.209 +}
   5.210 +
   5.211 +struct e2v_key {
   5.212 +	const char *start;
   5.213 +	const char *stop;
   5.214 +	asn_INTEGER_enum_map_t *vemap;
   5.215 +	unsigned int *evmap;
   5.216 +};
   5.217 +static int
   5.218 +INTEGER__compar_enum2value(const void *kp, const void *am) {
   5.219 +	const struct e2v_key *key = (const struct e2v_key *)kp;
   5.220 +	const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
   5.221 +	const char *ptr, *end, *name;
   5.222 +
   5.223 +	/* Remap the element (sort by different criterion) */
   5.224 +	el = key->vemap + key->evmap[el - key->vemap];
   5.225 +
   5.226 +	/* Compare strings */
   5.227 +	for(ptr = key->start, end = key->stop, name = el->enum_name;
   5.228 +			ptr < end; ptr++, name++) {
   5.229 +		if(*ptr != *name)
   5.230 +			return *(const unsigned char *)ptr
   5.231 +				- *(const unsigned char *)name;
   5.232 +	}
   5.233 +	return name[0] ? -1 : 0;
   5.234 +}
   5.235 +
   5.236 +static const asn_INTEGER_enum_map_t *
   5.237 +INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop) {
   5.238 +	asn_INTEGER_enum_map_t *el_found;
   5.239 +	int count = specs ? specs->map_count : 0;
   5.240 +	struct e2v_key key;
   5.241 +	const char *lp;
   5.242 +
   5.243 +	if(!count) return NULL;
   5.244 +
   5.245 +	/* Guaranteed: assert(lstart < lstop); */
   5.246 +	/* Figure out the tag name */
   5.247 +	for(lstart++, lp = lstart; lp < lstop; lp++) {
   5.248 +		switch(*lp) {
   5.249 +		case 9: case 10: case 11: case 12: case 13: case 32: /* WSP */
   5.250 +		case 0x2f: /* '/' */ case 0x3e: /* '>' */
   5.251 +			break;
   5.252 +		default:
   5.253 +			continue;
   5.254 +		}
   5.255 +		break;
   5.256 +	}
   5.257 +	if(lp == lstop) return NULL;	/* No tag found */
   5.258 +	lstop = lp;
   5.259 +
   5.260 +	key.start = lstart;
   5.261 +	key.stop = lstop;
   5.262 +	key.vemap = specs->value2enum;
   5.263 +	key.evmap = specs->enum2value;
   5.264 +	el_found = (asn_INTEGER_enum_map_t *)bsearch(&key,
   5.265 +		specs->value2enum, count, sizeof(specs->value2enum[0]),
   5.266 +		INTEGER__compar_enum2value);
   5.267 +	if(el_found) {
   5.268 +		/* Remap enum2value into value2enum */
   5.269 +		el_found = key.vemap + key.evmap[el_found - key.vemap];
   5.270 +	}
   5.271 +	return el_found;
   5.272 +}
   5.273 +
   5.274 +static int
   5.275 +INTEGER__compar_value2enum(const void *kp, const void *am) {
   5.276 +	long a = *(const long *)kp;
   5.277 +	const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
   5.278 +	long b = el->nat_value;
   5.279 +	if(a < b) return -1;
   5.280 +	else if(a == b) return 0;
   5.281 +	else return 1;
   5.282 +}
   5.283 +
   5.284 +const asn_INTEGER_enum_map_t *
   5.285 +INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value) {
   5.286 +	int count = specs ? specs->map_count : 0;
   5.287 +	if(!count) return 0;
   5.288 +	return (asn_INTEGER_enum_map_t *)bsearch(&value, specs->value2enum,
   5.289 +		count, sizeof(specs->value2enum[0]),
   5.290 +		INTEGER__compar_value2enum);
   5.291 +}
   5.292 +
   5.293 +static int
   5.294 +INTEGER_st_prealloc(INTEGER_t *st, int min_size) {
   5.295 +	void *p = MALLOC(min_size + 1);
   5.296 +	if(p) {
   5.297 +		void *b = st->buf;
   5.298 +		st->size = 0;
   5.299 +		st->buf = p;
   5.300 +		FREEMEM(b);
   5.301 +		return 0;
   5.302 +	} else {
   5.303 +		return -1;
   5.304 +	}
   5.305 +}
   5.306 +
   5.307 +/*
   5.308 + * Decode the chunk of XML text encoding INTEGER.
   5.309 + */
   5.310 +static enum xer_pbd_rval
   5.311 +INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
   5.312 +	INTEGER_t *st = (INTEGER_t *)sptr;
   5.313 +	long dec_value;
   5.314 +	long hex_value = 0;
   5.315 +	const char *lp;
   5.316 +	const char *lstart = (const char *)chunk_buf;
   5.317 +	const char *lstop = lstart + chunk_size;
   5.318 +	enum {
   5.319 +		ST_LEADSPACE,
   5.320 +		ST_SKIPSPHEX,
   5.321 +		ST_WAITDIGITS,
   5.322 +		ST_DIGITS,
   5.323 +		ST_DIGITS_TRAILSPACE,
   5.324 +		ST_HEXDIGIT1,
   5.325 +		ST_HEXDIGIT2,
   5.326 +		ST_HEXDIGITS_TRAILSPACE,
   5.327 +		ST_HEXCOLON,
   5.328 +		ST_END_ENUM,
   5.329 +		ST_UNEXPECTED
   5.330 +	} state = ST_LEADSPACE;
   5.331 +	const char *dec_value_start = 0; /* INVARIANT: always !0 in ST_DIGITS */
   5.332 +	const char *dec_value_end = 0;
   5.333 +
   5.334 +	if(chunk_size)
   5.335 +		ASN_DEBUG("INTEGER body %ld 0x%2x..0x%2x",
   5.336 +			(long)chunk_size, *lstart, lstop[-1]);
   5.337 +
   5.338 +	if(INTEGER_st_prealloc(st, (chunk_size/3) + 1))
   5.339 +		return XPBD_SYSTEM_FAILURE;
   5.340 +
   5.341 +	/*
   5.342 +	 * We may have received a tag here. It will be processed inline.
   5.343 +	 * Use strtoul()-like code and serialize the result.
   5.344 +	 */
   5.345 +	for(lp = lstart; lp < lstop; lp++) {
   5.346 +		int lv = *lp;
   5.347 +		switch(lv) {
   5.348 +		case 0x09: case 0x0a: case 0x0d: case 0x20:
   5.349 +			switch(state) {
   5.350 +			case ST_LEADSPACE:
   5.351 +			case ST_DIGITS_TRAILSPACE:
   5.352 +			case ST_HEXDIGITS_TRAILSPACE:
   5.353 +			case ST_SKIPSPHEX:
   5.354 +				continue;
   5.355 +			case ST_DIGITS:
   5.356 +				dec_value_end = lp;
   5.357 +				state = ST_DIGITS_TRAILSPACE;
   5.358 +				continue;
   5.359 +			case ST_HEXCOLON:
   5.360 +				state = ST_HEXDIGITS_TRAILSPACE;
   5.361 +				continue;
   5.362 +			default:
   5.363 +				break;
   5.364 +			}
   5.365 +			break;
   5.366 +		case 0x2d:	/* '-' */
   5.367 +			if(state == ST_LEADSPACE) {
   5.368 +				dec_value = 0;
   5.369 +				dec_value_start = lp;
   5.370 +				state = ST_WAITDIGITS;
   5.371 +				continue;
   5.372 +			}
   5.373 +			break;
   5.374 +		case 0x2b:	/* '+' */
   5.375 +			if(state == ST_LEADSPACE) {
   5.376 +				dec_value = 0;
   5.377 +				dec_value_start = lp;
   5.378 +				state = ST_WAITDIGITS;
   5.379 +				continue;
   5.380 +			}
   5.381 +			break;
   5.382 +		case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
   5.383 +		case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
   5.384 +			switch(state) {
   5.385 +			case ST_DIGITS: continue;
   5.386 +			case ST_SKIPSPHEX:	/* Fall through */
   5.387 +			case ST_HEXDIGIT1:
   5.388 +				hex_value = (lv - 0x30) << 4;
   5.389 +				state = ST_HEXDIGIT2;
   5.390 +				continue;
   5.391 +			case ST_HEXDIGIT2:
   5.392 +				hex_value += (lv - 0x30);
   5.393 +				state = ST_HEXCOLON;
   5.394 +				st->buf[st->size++] = (uint8_t)hex_value;
   5.395 +				continue;
   5.396 +			case ST_HEXCOLON:
   5.397 +				return XPBD_BROKEN_ENCODING;
   5.398 +			case ST_LEADSPACE:
   5.399 +				dec_value = 0;
   5.400 +				dec_value_start = lp;
   5.401 +				/* FALL THROUGH */
   5.402 +			case ST_WAITDIGITS:
   5.403 +				state = ST_DIGITS;
   5.404 +				continue;
   5.405 +			default:
   5.406 +				break;
   5.407 +			}
   5.408 +			break;
   5.409 +		case 0x3c:	/* '<', start of XML encoded enumeration */
   5.410 +			if(state == ST_LEADSPACE) {
   5.411 +				const asn_INTEGER_enum_map_t *el;
   5.412 +				el = INTEGER_map_enum2value(
   5.413 +					(asn_INTEGER_specifics_t *)
   5.414 +					td->specifics, lstart, lstop);
   5.415 +				if(el) {
   5.416 +					ASN_DEBUG("Found \"%s\" => %ld",
   5.417 +						el->enum_name, el->nat_value);
   5.418 +					dec_value = el->nat_value;
   5.419 +					state = ST_END_ENUM;
   5.420 +					lp = lstop - 1;
   5.421 +					continue;
   5.422 +				}
   5.423 +				ASN_DEBUG("Unknown identifier for INTEGER");
   5.424 +			}
   5.425 +			return XPBD_BROKEN_ENCODING;
   5.426 +		case 0x3a:	/* ':' */
   5.427 +			if(state == ST_HEXCOLON) {
   5.428 +				/* This colon is expected */
   5.429 +				state = ST_HEXDIGIT1;
   5.430 +				continue;
   5.431 +			} else if(state == ST_DIGITS) {
   5.432 +				/* The colon here means that we have
   5.433 +				 * decoded the first two hexadecimal
   5.434 +				 * places as a decimal value.
   5.435 +				 * Switch decoding mode. */
   5.436 +				ASN_DEBUG("INTEGER re-evaluate as hex form");
   5.437 +				state = ST_SKIPSPHEX;
   5.438 +				dec_value_start = 0;
   5.439 +				lp = lstart - 1;
   5.440 +				continue;
   5.441 +			} else {
   5.442 +				ASN_DEBUG("state %d at %ld", state, (long)(lp - lstart));
   5.443 +				break;
   5.444 +			}
   5.445 +		/* [A-Fa-f] */
   5.446 +		case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:
   5.447 +		case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:
   5.448 +			switch(state) {
   5.449 +			case ST_SKIPSPHEX:
   5.450 +			case ST_LEADSPACE: /* Fall through */
   5.451 +			case ST_HEXDIGIT1:
   5.452 +				hex_value = lv - ((lv < 0x61) ? 0x41 : 0x61);
   5.453 +				hex_value += 10;
   5.454 +				hex_value <<= 4;
   5.455 +				state = ST_HEXDIGIT2;
   5.456 +				continue;
   5.457 +			case ST_HEXDIGIT2:
   5.458 +				hex_value += lv - ((lv < 0x61) ? 0x41 : 0x61);
   5.459 +				hex_value += 10;
   5.460 +				st->buf[st->size++] = (uint8_t)hex_value;
   5.461 +				state = ST_HEXCOLON;
   5.462 +				continue;
   5.463 +			case ST_DIGITS:
   5.464 +				ASN_DEBUG("INTEGER re-evaluate as hex form");
   5.465 +				state = ST_SKIPSPHEX;
   5.466 +				dec_value_start = 0;
   5.467 +				lp = lstart - 1;
   5.468 +				continue;
   5.469 +			default:
   5.470 +				break;
   5.471 +			}
   5.472 +			break;
   5.473 +		}
   5.474 +
   5.475 +		/* Found extra non-numeric stuff */
   5.476 +		ASN_DEBUG("INTEGER :: Found non-numeric 0x%2x at %ld",
   5.477 +			lv, (long)(lp - lstart));
   5.478 +		state = ST_UNEXPECTED;
   5.479 +		break;
   5.480 +	}
   5.481 +
   5.482 +	switch(state) {
   5.483 +	case ST_END_ENUM:
   5.484 +		/* Got a complete and valid enumeration encoded as a tag. */
   5.485 +		break;
   5.486 +	case ST_DIGITS:
   5.487 +		dec_value_end = lstop;
   5.488 +		/* FALL THROUGH */
   5.489 +	case ST_DIGITS_TRAILSPACE:
   5.490 +		/* The last symbol encountered was a digit. */
   5.491 +		switch(asn_strtol_lim(dec_value_start, &dec_value_end, &dec_value)) {
   5.492 +		case ASN_STRTOL_OK:
   5.493 +			break;
   5.494 +		case ASN_STRTOL_ERROR_RANGE:
   5.495 +			return XPBD_DECODER_LIMIT;
   5.496 +		case ASN_STRTOL_ERROR_INVAL:
   5.497 +		case ASN_STRTOL_EXPECT_MORE:
   5.498 +		case ASN_STRTOL_EXTRA_DATA:
   5.499 +			return XPBD_BROKEN_ENCODING;
   5.500 +		}
   5.501 +		break;
   5.502 +	case ST_HEXCOLON:
   5.503 +	case ST_HEXDIGITS_TRAILSPACE:
   5.504 +		st->buf[st->size] = 0;	/* Just in case termination */
   5.505 +		return XPBD_BODY_CONSUMED;
   5.506 +	case ST_HEXDIGIT1:
   5.507 +	case ST_HEXDIGIT2:
   5.508 +	case ST_SKIPSPHEX:
   5.509 +		return XPBD_BROKEN_ENCODING;
   5.510 +	case ST_LEADSPACE:
   5.511 +		/* Content not found */
   5.512 +		return XPBD_NOT_BODY_IGNORE;
   5.513 +	case ST_WAITDIGITS:
   5.514 +	case ST_UNEXPECTED:
   5.515 +		ASN_DEBUG("INTEGER: No useful digits (state %d)", state);
   5.516 +		return XPBD_BROKEN_ENCODING;	/* No digits */
   5.517 +	}
   5.518 +
   5.519 +	/*
   5.520 +	 * Convert the result of parsing of enumeration or a straight
   5.521 +	 * decimal value into a BER representation.
   5.522 +	 */
   5.523 +	if(asn_long2INTEGER(st, dec_value))
   5.524 +		return XPBD_SYSTEM_FAILURE;
   5.525 +
   5.526 +	return XPBD_BODY_CONSUMED;
   5.527 +}
   5.528 +
   5.529 +asn_dec_rval_t
   5.530 +INTEGER_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
   5.531 +	asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
   5.532 +		const void *buf_ptr, size_t size) {
   5.533 +
   5.534 +	return xer_decode_primitive(opt_codec_ctx, td,
   5.535 +		sptr, sizeof(INTEGER_t), opt_mname,
   5.536 +		buf_ptr, size, INTEGER__xer_body_decode);
   5.537 +}
   5.538 +
   5.539 +asn_enc_rval_t
   5.540 +INTEGER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
   5.541 +	int ilevel, enum xer_encoder_flags_e flags,
   5.542 +		asn_app_consume_bytes_f *cb, void *app_key) {
   5.543 +	const INTEGER_t *st = (const INTEGER_t *)sptr;
   5.544 +	asn_enc_rval_t er;
   5.545 +
   5.546 +	(void)ilevel;
   5.547 +	(void)flags;
   5.548 +	
   5.549 +	if(!st || !st->buf)
   5.550 +		_ASN_ENCODE_FAILED;
   5.551 +
   5.552 +	er.encoded = INTEGER__dump(td, st, cb, app_key, 1);
   5.553 +	if(er.encoded < 0) _ASN_ENCODE_FAILED;
   5.554 +
   5.555 +	_ASN_ENCODED_OK(er);
   5.556 +}
   5.557 +
   5.558 +#ifndef	ASN_DISABLE_PER_SUPPORT
   5.559 +
   5.560 +asn_dec_rval_t
   5.561 +INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
   5.562 +	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
   5.563 +	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
   5.564 +	asn_dec_rval_t rval = { RC_OK, 0 };
   5.565 +	INTEGER_t *st = (INTEGER_t *)*sptr;
   5.566 +	asn_per_constraint_t *ct;
   5.567 +	int repeat;
   5.568 +
   5.569 +	(void)opt_codec_ctx;
   5.570 +
   5.571 +	if(!st) {
   5.572 +		st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
   5.573 +		if(!st) _ASN_DECODE_FAILED;
   5.574 +	}
   5.575 +
   5.576 +	if(!constraints) constraints = td->per_constraints;
   5.577 +	ct = constraints ? &constraints->value : 0;
   5.578 +
   5.579 +	if(ct && ct->flags & APC_EXTENSIBLE) {
   5.580 +		int inext = per_get_few_bits(pd, 1);
   5.581 +		if(inext < 0) _ASN_DECODE_STARVED;
   5.582 +		if(inext) ct = 0;
   5.583 +	}
   5.584 +
   5.585 +	FREEMEM(st->buf);
   5.586 +	st->buf = 0;
   5.587 +	st->size = 0;
   5.588 +	if(ct) {
   5.589 +		if(ct->flags & APC_SEMI_CONSTRAINED) {
   5.590 +			st->buf = (uint8_t *)CALLOC(1, 2);
   5.591 +			if(!st->buf) _ASN_DECODE_FAILED;
   5.592 +			st->size = 1;
   5.593 +		} else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
   5.594 +			size_t size = (ct->range_bits + 7) >> 3;
   5.595 +			st->buf = (uint8_t *)MALLOC(1 + size + 1);
   5.596 +			if(!st->buf) _ASN_DECODE_FAILED;
   5.597 +			st->size = size;
   5.598 +		}
   5.599 +	}
   5.600 +
   5.601 +	/* X.691-2008/11, #13.2.2, constrained whole number */
   5.602 +	if(ct && ct->flags != APC_UNCONSTRAINED) {
   5.603 +		/* #11.5.6 */
   5.604 +		ASN_DEBUG("Integer with range %d bits", ct->range_bits);
   5.605 +		if(ct->range_bits >= 0) {
   5.606 +			if((size_t)ct->range_bits > 8 * sizeof(unsigned long))
   5.607 +				_ASN_DECODE_FAILED;
   5.608 +
   5.609 +			if(specs && specs->field_unsigned) {
   5.610 +				unsigned long uvalue;
   5.611 +				if(uper_get_constrained_whole_number(pd,
   5.612 +					&uvalue, ct->range_bits))
   5.613 +					_ASN_DECODE_STARVED;
   5.614 +				ASN_DEBUG("Got value %lu + low %ld",
   5.615 +					uvalue, ct->lower_bound);
   5.616 +				uvalue += ct->lower_bound;
   5.617 +				if(asn_ulong2INTEGER(st, uvalue))
   5.618 +					_ASN_DECODE_FAILED;
   5.619 +			} else {
   5.620 +				unsigned long svalue;
   5.621 +				if(uper_get_constrained_whole_number(pd,
   5.622 +					&svalue, ct->range_bits))
   5.623 +					_ASN_DECODE_STARVED;
   5.624 +				ASN_DEBUG("Got value %ld + low %ld",
   5.625 +					svalue, ct->lower_bound);
   5.626 +				svalue += ct->lower_bound;
   5.627 +				if(asn_long2INTEGER(st, svalue))
   5.628 +					_ASN_DECODE_FAILED;
   5.629 +			}
   5.630 +			return rval;
   5.631 +		}
   5.632 +	} else {
   5.633 +		ASN_DEBUG("Decoding unconstrained integer %s", td->name);
   5.634 +	}
   5.635 +
   5.636 +	/* X.691, #12.2.3, #12.2.4 */
   5.637 +	do {
   5.638 +		ssize_t len;
   5.639 +		void *p;
   5.640 +		int ret;
   5.641 +
   5.642 +		/* Get the PER length */
   5.643 +		len = uper_get_length(pd, -1, &repeat);
   5.644 +		if(len < 0) _ASN_DECODE_STARVED;
   5.645 +
   5.646 +		p = REALLOC(st->buf, st->size + len + 1);
   5.647 +		if(!p) _ASN_DECODE_FAILED;
   5.648 +		st->buf = (uint8_t *)p;
   5.649 +
   5.650 +		ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
   5.651 +		if(ret < 0) _ASN_DECODE_STARVED;
   5.652 +		st->size += len;
   5.653 +	} while(repeat);
   5.654 +	st->buf[st->size] = 0;	/* JIC */
   5.655 +
   5.656 +	/* #12.2.3 */
   5.657 +	if(ct && ct->lower_bound) {
   5.658 +		/*
   5.659 +		 * TODO: replace by in-place arithmetics.
   5.660 +		 */
   5.661 +		long value;
   5.662 +		if(asn_INTEGER2long(st, &value))
   5.663 +			_ASN_DECODE_FAILED;
   5.664 +		if(asn_long2INTEGER(st, value + ct->lower_bound))
   5.665 +			_ASN_DECODE_FAILED;
   5.666 +	}
   5.667 +
   5.668 +	return rval;
   5.669 +}
   5.670 +
   5.671 +asn_enc_rval_t
   5.672 +INTEGER_encode_uper(asn_TYPE_descriptor_t *td,
   5.673 +	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
   5.674 +	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
   5.675 +	asn_enc_rval_t er;
   5.676 +	INTEGER_t *st = (INTEGER_t *)sptr;
   5.677 +	const uint8_t *buf;
   5.678 +	const uint8_t *end;
   5.679 +	asn_per_constraint_t *ct;
   5.680 +	long value = 0;
   5.681 +
   5.682 +	if(!st || st->size == 0) _ASN_ENCODE_FAILED;
   5.683 +
   5.684 +	if(!constraints) constraints = td->per_constraints;
   5.685 +	ct = constraints ? &constraints->value : 0;
   5.686 +
   5.687 +	er.encoded = 0;
   5.688 +
   5.689 +	if(ct) {
   5.690 +		int inext = 0;
   5.691 +		if(specs && specs->field_unsigned) {
   5.692 +			unsigned long uval;
   5.693 +			if(asn_INTEGER2ulong(st, &uval))
   5.694 +				_ASN_ENCODE_FAILED;
   5.695 +			/* Check proper range */
   5.696 +			if(ct->flags & APC_SEMI_CONSTRAINED) {
   5.697 +				if(uval < (unsigned long)ct->lower_bound)
   5.698 +					inext = 1;
   5.699 +			} else if(ct->range_bits >= 0) {
   5.700 +				if(uval < (unsigned long)ct->lower_bound
   5.701 +				|| uval > (unsigned long)ct->upper_bound)
   5.702 +					inext = 1;
   5.703 +			}
   5.704 +			ASN_DEBUG("Value %lu (%02x/%d) lb %lu ub %lu %s",
   5.705 +				uval, st->buf[0], st->size,
   5.706 +				ct->lower_bound, ct->upper_bound,
   5.707 +				inext ? "ext" : "fix");
   5.708 +			value = uval;
   5.709 +		} else {
   5.710 +			if(asn_INTEGER2long(st, &value))
   5.711 +				_ASN_ENCODE_FAILED;
   5.712 +			/* Check proper range */
   5.713 +			if(ct->flags & APC_SEMI_CONSTRAINED) {
   5.714 +				if(value < ct->lower_bound)
   5.715 +					inext = 1;
   5.716 +			} else if(ct->range_bits >= 0) {
   5.717 +				if(value < ct->lower_bound
   5.718 +				|| value > ct->upper_bound)
   5.719 +					inext = 1;
   5.720 +			}
   5.721 +			ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s",
   5.722 +				value, st->buf[0], st->size,
   5.723 +				ct->lower_bound, ct->upper_bound,
   5.724 +				inext ? "ext" : "fix");
   5.725 +		}
   5.726 +		if(ct->flags & APC_EXTENSIBLE) {
   5.727 +			if(per_put_few_bits(po, inext, 1))
   5.728 +				_ASN_ENCODE_FAILED;
   5.729 +			if(inext) ct = 0;
   5.730 +		} else if(inext) {
   5.731 +			_ASN_ENCODE_FAILED;
   5.732 +		}
   5.733 +	}
   5.734 +
   5.735 +
   5.736 +	/* X.691-11/2008, #13.2.2, test if constrained whole number */
   5.737 +	if(ct && ct->range_bits >= 0) {
   5.738 +		/* #11.5.6 -> #11.3 */
   5.739 +		ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits",
   5.740 +			value, value - ct->lower_bound, ct->range_bits);
   5.741 +		unsigned long v = value - ct->lower_bound;
   5.742 +		if(uper_put_constrained_whole_number_u(po, v, ct->range_bits))
   5.743 +			_ASN_ENCODE_FAILED;
   5.744 +		_ASN_ENCODED_OK(er);
   5.745 +	}
   5.746 +
   5.747 +	if(ct && ct->lower_bound) {
   5.748 +		ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
   5.749 +		/* TODO: adjust lower bound */
   5.750 +		_ASN_ENCODE_FAILED;
   5.751 +	}
   5.752 +
   5.753 +	for(buf = st->buf, end = st->buf + st->size; buf < end;) {
   5.754 +		ssize_t mayEncode = uper_put_length(po, end - buf);
   5.755 +		if(mayEncode < 0)
   5.756 +			_ASN_ENCODE_FAILED;
   5.757 +		if(per_put_many_bits(po, buf, 8 * mayEncode))
   5.758 +			_ASN_ENCODE_FAILED;
   5.759 +		buf += mayEncode;
   5.760 +	}
   5.761 +
   5.762 +	_ASN_ENCODED_OK(er);
   5.763 +}
   5.764 +
   5.765 +#endif	/* ASN_DISABLE_PER_SUPPORT */
   5.766 +
   5.767 +int
   5.768 +asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
   5.769 +	uint8_t *b, *end;
   5.770 +	size_t size;
   5.771 +	long l;
   5.772 +
   5.773 +	/* Sanity checking */
   5.774 +	if(!iptr || !iptr->buf || !lptr) {
   5.775 +		errno = EINVAL;
   5.776 +		return -1;
   5.777 +	}
   5.778 +
   5.779 +	/* Cache the begin/end of the buffer */
   5.780 +	b = iptr->buf;	/* Start of the INTEGER buffer */
   5.781 +	size = iptr->size;
   5.782 +	end = b + size;	/* Where to stop */
   5.783 +
   5.784 +	if(size > sizeof(long)) {
   5.785 +		uint8_t *end1 = end - 1;
   5.786 +		/*
   5.787 +		 * Slightly more advanced processing,
   5.788 +		 * able to >sizeof(long) bytes,
   5.789 +		 * when the actual value is small
   5.790 +		 * (0x0000000000abcdef would yield a fine 0x00abcdef)
   5.791 +		 */
   5.792 +		/* Skip out the insignificant leading bytes */
   5.793 +		for(; b < end1; b++) {
   5.794 +			switch(*b) {
   5.795 +			case 0x00: if((b[1] & 0x80) == 0) continue; break;
   5.796 +			case 0xff: if((b[1] & 0x80) != 0) continue; break;
   5.797 +			}
   5.798 +			break;
   5.799 +		}
   5.800 +
   5.801 +		size = end - b;
   5.802 +		if(size > sizeof(long)) {
   5.803 +			/* Still cannot fit the long */
   5.804 +			errno = ERANGE;
   5.805 +			return -1;
   5.806 +		}
   5.807 +	}
   5.808 +
   5.809 +	/* Shortcut processing of a corner case */
   5.810 +	if(end == b) {
   5.811 +		*lptr = 0;
   5.812 +		return 0;
   5.813 +	}
   5.814 +
   5.815 +	/* Perform the sign initialization */
   5.816 +	/* Actually l = -(*b >> 7); gains nothing, yet unreadable! */
   5.817 +	if((*b >> 7)) l = -1; else l = 0;
   5.818 +
   5.819 +	/* Conversion engine */
   5.820 +	for(; b < end; b++)
   5.821 +		l = (l << 8) | *b;
   5.822 +
   5.823 +	*lptr = l;
   5.824 +	return 0;
   5.825 +}
   5.826 +
   5.827 +int
   5.828 +asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *lptr) {
   5.829 +	uint8_t *b, *end;
   5.830 +	unsigned long l;
   5.831 +	size_t size;
   5.832 +
   5.833 +	if(!iptr || !iptr->buf || !lptr) {
   5.834 +		errno = EINVAL;
   5.835 +		return -1;
   5.836 +	}
   5.837 +
   5.838 +	b = iptr->buf;
   5.839 +	size = iptr->size;
   5.840 +	end = b + size;
   5.841 +
   5.842 +	/* If all extra leading bytes are zeroes, ignore them */
   5.843 +	for(; size > sizeof(unsigned long); b++, size--) {
   5.844 +		if(*b) {
   5.845 +			/* Value won't fit unsigned long */
   5.846 +			errno = ERANGE;
   5.847 +			return -1;
   5.848 +		}
   5.849 +	}
   5.850 +
   5.851 +	/* Conversion engine */
   5.852 +	for(l = 0; b < end; b++)
   5.853 +		l = (l << 8) | *b;
   5.854 +
   5.855 +	*lptr = l;
   5.856 +	return 0;
   5.857 +}
   5.858 +
   5.859 +int
   5.860 +asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
   5.861 +	uint8_t *buf;
   5.862 +	uint8_t *end;
   5.863 +	uint8_t *b;
   5.864 +	int shr;
   5.865 +
   5.866 +	if(value <= LONG_MAX)
   5.867 +		return asn_long2INTEGER(st, value);
   5.868 +
   5.869 +	buf = (uint8_t *)MALLOC(1 + sizeof(value));
   5.870 +	if(!buf) return -1;
   5.871 +
   5.872 +	end = buf + (sizeof(value) + 1);
   5.873 +	buf[0] = 0;
   5.874 +	for(b = buf + 1, shr = (sizeof(long)-1)*8; b < end; shr -= 8, b++)
   5.875 +		*b = (uint8_t)(value >> shr);
   5.876 +
   5.877 +	if(st->buf) FREEMEM(st->buf);
   5.878 +	st->buf = buf;
   5.879 +	st->size = 1 + sizeof(value);
   5.880 +
   5.881 +	return 0;
   5.882 +}
   5.883 +
   5.884 +int
   5.885 +asn_long2INTEGER(INTEGER_t *st, long value) {
   5.886 +	uint8_t *buf, *bp;
   5.887 +	uint8_t *p;
   5.888 +	uint8_t *pstart;
   5.889 +	uint8_t *pend1;
   5.890 +	int littleEndian = 1;	/* Run-time detection */
   5.891 +	int add;
   5.892 +
   5.893 +	if(!st) {
   5.894 +		errno = EINVAL;
   5.895 +		return -1;
   5.896 +	}
   5.897 +
   5.898 +	buf = (uint8_t *)MALLOC(sizeof(value));
   5.899 +	if(!buf) return -1;
   5.900 +
   5.901 +	if(*(char *)&littleEndian) {
   5.902 +		pstart = (uint8_t *)&value + sizeof(value) - 1;
   5.903 +		pend1 = (uint8_t *)&value;
   5.904 +		add = -1;
   5.905 +	} else {
   5.906 +		pstart = (uint8_t *)&value;
   5.907 +		pend1 = pstart + sizeof(value) - 1;
   5.908 +		add = 1;
   5.909 +	}
   5.910 +
   5.911 +	/*
   5.912 +	 * If the contents octet consists of more than one octet,
   5.913 +	 * then bits of the first octet and bit 8 of the second octet:
   5.914 +	 * a) shall not all be ones; and
   5.915 +	 * b) shall not all be zero.
   5.916 +	 */
   5.917 +	for(p = pstart; p != pend1; p += add) {
   5.918 +		switch(*p) {
   5.919 +		case 0x00: if((*(p+add) & 0x80) == 0)
   5.920 +				continue;
   5.921 +			break;
   5.922 +		case 0xff: if((*(p+add) & 0x80))
   5.923 +				continue;
   5.924 +			break;
   5.925 +		}
   5.926 +		break;
   5.927 +	}
   5.928 +	/* Copy the integer body */
   5.929 +	for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add)
   5.930 +		*bp++ = *p;
   5.931 +
   5.932 +	if(st->buf) FREEMEM(st->buf);
   5.933 +	st->buf = buf;
   5.934 +	st->size = bp - buf;
   5.935 +
   5.936 +	return 0;
   5.937 +}
   5.938 +
   5.939 +/*
   5.940 + * This function is going to be DEPRECATED soon.
   5.941 + */
   5.942 +enum asn_strtol_result_e
   5.943 +asn_strtol(const char *str, const char *end, long *lp) {
   5.944 +    const char *endp = end;
   5.945 +
   5.946 +    switch(asn_strtol_lim(str, &endp, lp)) {
   5.947 +    case ASN_STRTOL_ERROR_RANGE:
   5.948 +        return ASN_STRTOL_ERROR_RANGE;
   5.949 +    case ASN_STRTOL_ERROR_INVAL:
   5.950 +        return ASN_STRTOL_ERROR_INVAL;
   5.951 +    case ASN_STRTOL_EXPECT_MORE:
   5.952 +        return ASN_STRTOL_ERROR_INVAL;  /* Retain old behavior */
   5.953 +    case ASN_STRTOL_OK:
   5.954 +        return ASN_STRTOL_OK;
   5.955 +    case ASN_STRTOL_EXTRA_DATA:
   5.956 +        return ASN_STRTOL_ERROR_INVAL;  /* Retain old behavior */
   5.957 +    }
   5.958 +
   5.959 +    return ASN_STRTOL_ERROR_INVAL;  /* Retain old behavior */
   5.960 +}
   5.961 +
   5.962 +/*
   5.963 + * Parse the number in the given string until the given *end position,
   5.964 + * returning the position after the last parsed character back using the
   5.965 + * same (*end) pointer.
   5.966 + * WARNING: This behavior is different from the standard strtol(3).
   5.967 + */
   5.968 +enum asn_strtol_result_e
   5.969 +asn_strtol_lim(const char *str, const char **end, long *lp) {
   5.970 +	int sign = 1;
   5.971 +	long l;
   5.972 +
   5.973 +	const long upper_boundary = LONG_MAX / 10;
   5.974 +	long last_digit_max = LONG_MAX % 10;
   5.975 +
   5.976 +	if(str >= *end) return ASN_STRTOL_ERROR_INVAL;
   5.977 +
   5.978 +	switch(*str) {
   5.979 +	case '-':
   5.980 +		last_digit_max++;
   5.981 +		sign = -1;
   5.982 +	case '+':
   5.983 +		str++;
   5.984 +		if(str >= *end) {
   5.985 +			*end = str;
   5.986 +			return ASN_STRTOL_EXPECT_MORE;
   5.987 +		}
   5.988 +	}
   5.989 +
   5.990 +	for(l = 0; str < (*end); str++) {
   5.991 +		switch(*str) {
   5.992 +		case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
   5.993 +		case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: {
   5.994 +			int d = *str - '0';
   5.995 +			if(l < upper_boundary) {
   5.996 +				l = l * 10 + d;
   5.997 +			} else if(l == upper_boundary) {
   5.998 +				if(d <= last_digit_max) {
   5.999 +					if(sign > 0) {
  5.1000 +						l = l * 10 + d;
  5.1001 +					} else {
  5.1002 +						sign = 1;
  5.1003 +						l = -l * 10 - d;
  5.1004 +					}
  5.1005 +				} else {
  5.1006 +					*end = str;
  5.1007 +					return ASN_STRTOL_ERROR_RANGE;
  5.1008 +				}
  5.1009 +			} else {
  5.1010 +				*end = str;
  5.1011 +				return ASN_STRTOL_ERROR_RANGE;
  5.1012 +			}
  5.1013 +		    }
  5.1014 +		    continue;
  5.1015 +		default:
  5.1016 +		    *end = str;
  5.1017 +		    *lp = sign * l;
  5.1018 +		    return ASN_STRTOL_EXTRA_DATA;
  5.1019 +		}
  5.1020 +	}
  5.1021 +
  5.1022 +	*end = str;
  5.1023 +	*lp = sign * l;
  5.1024 +	return ASN_STRTOL_OK;
  5.1025 +}
  5.1026 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/asn.1/INTEGER.h	Wed May 11 20:06:23 2016 +0200
     6.3 @@ -0,0 +1,82 @@
     6.4 +/*-
     6.5 + * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
     6.6 + * Redistribution and modifications are permitted subject to BSD license.
     6.7 + */
     6.8 +#ifndef	_INTEGER_H_
     6.9 +#define	_INTEGER_H_
    6.10 +
    6.11 +#include <asn_application.h>
    6.12 +#include <asn_codecs_prim.h>
    6.13 +
    6.14 +#ifdef __cplusplus
    6.15 +extern "C" {
    6.16 +#endif
    6.17 +
    6.18 +typedef ASN__PRIMITIVE_TYPE_t INTEGER_t;
    6.19 +
    6.20 +extern asn_TYPE_descriptor_t asn_DEF_INTEGER;
    6.21 +
    6.22 +/* Map with <tag> to integer value association */
    6.23 +typedef struct asn_INTEGER_enum_map_s {
    6.24 +	long		 nat_value;	/* associated native integer value */
    6.25 +	size_t		 enum_len;	/* strlen("tag") */
    6.26 +	const char	*enum_name;	/* "tag" */
    6.27 +} asn_INTEGER_enum_map_t;
    6.28 +
    6.29 +/* This type describes an enumeration for INTEGER and ENUMERATED types */
    6.30 +typedef struct asn_INTEGER_specifics_s {
    6.31 +	asn_INTEGER_enum_map_t *value2enum;	/* N -> "tag"; sorted by N */
    6.32 +	unsigned int *enum2value;		/* "tag" => N; sorted by tag */
    6.33 +	int map_count;				/* Elements in either map */
    6.34 +	int extension;				/* This map is extensible */
    6.35 +	int strict_enumeration;			/* Enumeration set is fixed */
    6.36 +	int field_width;			/* Size of native integer */
    6.37 +	int field_unsigned;			/* Signed=0, unsigned=1 */
    6.38 +} asn_INTEGER_specifics_t;
    6.39 +
    6.40 +asn_struct_print_f INTEGER_print;
    6.41 +ber_type_decoder_f INTEGER_decode_ber;
    6.42 +der_type_encoder_f INTEGER_encode_der;
    6.43 +xer_type_decoder_f INTEGER_decode_xer;
    6.44 +xer_type_encoder_f INTEGER_encode_xer;
    6.45 +per_type_decoder_f INTEGER_decode_uper;
    6.46 +per_type_encoder_f INTEGER_encode_uper;
    6.47 +
    6.48 +/***********************************
    6.49 + * Some handy conversion routines. *
    6.50 + ***********************************/
    6.51 +
    6.52 +/*
    6.53 + * Returns 0 if it was possible to convert, -1 otherwise.
    6.54 + * -1/EINVAL: Mandatory argument missing
    6.55 + * -1/ERANGE: Value encoded is out of range for long representation
    6.56 + * -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()).
    6.57 + */
    6.58 +int asn_INTEGER2long(const INTEGER_t *i, long *l);
    6.59 +int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l);
    6.60 +int asn_long2INTEGER(INTEGER_t *i, long l);
    6.61 +int asn_ulong2INTEGER(INTEGER_t *i, unsigned long l);
    6.62 +
    6.63 +/* A a reified version of strtol(3) with nicer error reporting. */
    6.64 +enum asn_strtol_result_e {
    6.65 +    ASN_STRTOL_ERROR_RANGE = -3,  /* Input outside of numeric range for long type */
    6.66 +    ASN_STRTOL_ERROR_INVAL = -2,  /* Invalid data encountered (e.g., "+-") */
    6.67 +    ASN_STRTOL_EXPECT_MORE = -1,  /* More data expected (e.g. "+") */
    6.68 +    ASN_STRTOL_OK          =  0,  /* Conversion succeded, number ends at (*end) */
    6.69 +    ASN_STRTOL_EXTRA_DATA  =  1,  /* Conversion succeded, but the string has extra stuff */
    6.70 +};
    6.71 +enum asn_strtol_result_e asn_strtol_lim(const char *str, const char **end, long *l);
    6.72 +
    6.73 +/* The asn_strtol is going to be DEPRECATED soon */
    6.74 +enum asn_strtol_result_e asn_strtol(const char *str, const char *end, long *l);
    6.75 +
    6.76 +/*
    6.77 + * Convert the integer value into the corresponding enumeration map entry.
    6.78 + */
    6.79 +const asn_INTEGER_enum_map_t *INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value);
    6.80 +
    6.81 +#ifdef __cplusplus
    6.82 +}
    6.83 +#endif
    6.84 +
    6.85 +#endif	/* _INTEGER_H_ */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/asn.1/Identity.c	Wed May 11 20:06:23 2016 +0200
     7.3 @@ -0,0 +1,139 @@
     7.4 +/*
     7.5 + * Generated by asn1c-0.9.26 (http://lionet.info/asn1c)
     7.6 + * From ASN.1 module "PEP"
     7.7 + * 	found in "pEp.asn1"
     7.8 + */
     7.9 +
    7.10 +#include "Identity.h"
    7.11 +
    7.12 +static int
    7.13 +memb_comm_type_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr,
    7.14 +			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
    7.15 +	long value;
    7.16 +	
    7.17 +	if(!sptr) {
    7.18 +		_ASN_CTFAIL(app_key, td, sptr,
    7.19 +			"%s: value not given (%s:%d)",
    7.20 +			td->name, __FILE__, __LINE__);
    7.21 +		return -1;
    7.22 +	}
    7.23 +	
    7.24 +	value = *(const long *)sptr;
    7.25 +	
    7.26 +	if((value >= 0 && value <= 255)) {
    7.27 +		/* Constraint check succeeded */
    7.28 +		return 0;
    7.29 +	} else {
    7.30 +		_ASN_CTFAIL(app_key, td, sptr,
    7.31 +			"%s: constraint failed (%s:%d)",
    7.32 +			td->name, __FILE__, __LINE__);
    7.33 +		return -1;
    7.34 +	}
    7.35 +}
    7.36 +
    7.37 +static asn_per_constraints_t asn_PER_memb_comm_type_constr_6 GCC_NOTUSED = {
    7.38 +	{ APC_CONSTRAINED,	 8,  8,  0,  255 }	/* (0..255) */,
    7.39 +	{ APC_UNCONSTRAINED,	-1, -1,  0,  0 },
    7.40 +	0, 0	/* No PER value map */
    7.41 +};
    7.42 +static asn_TYPE_member_t asn_MBR_Identity_1[] = {
    7.43 +	{ ATF_NOFLAGS, 0, offsetof(struct Identity, address),
    7.44 +		(ASN_TAG_CLASS_UNIVERSAL | (12 << 2)),
    7.45 +		0,
    7.46 +		&asn_DEF_UTF8String,
    7.47 +		0,	/* Defer constraints checking to the member type */
    7.48 +		0,	/* No PER visible constraints */
    7.49 +		0,
    7.50 +		"address"
    7.51 +		},
    7.52 +	{ ATF_NOFLAGS, 0, offsetof(struct Identity, fpr),
    7.53 +		(ASN_TAG_CLASS_UNIVERSAL | (12 << 2)),
    7.54 +		0,
    7.55 +		&asn_DEF_UTF8String,
    7.56 +		0,	/* Defer constraints checking to the member type */
    7.57 +		0,	/* No PER visible constraints */
    7.58 +		0,
    7.59 +		"fpr"
    7.60 +		},
    7.61 +	{ ATF_NOFLAGS, 0, offsetof(struct Identity, user_id),
    7.62 +		(ASN_TAG_CLASS_UNIVERSAL | (12 << 2)),
    7.63 +		0,
    7.64 +		&asn_DEF_UTF8String,
    7.65 +		0,	/* Defer constraints checking to the member type */
    7.66 +		0,	/* No PER visible constraints */
    7.67 +		0,
    7.68 +		"user-id"
    7.69 +		},
    7.70 +	{ ATF_NOFLAGS, 0, offsetof(struct Identity, username),
    7.71 +		(ASN_TAG_CLASS_UNIVERSAL | (12 << 2)),
    7.72 +		0,
    7.73 +		&asn_DEF_UTF8String,
    7.74 +		0,	/* Defer constraints checking to the member type */
    7.75 +		0,	/* No PER visible constraints */
    7.76 +		0,
    7.77 +		"username"
    7.78 +		},
    7.79 +	{ ATF_NOFLAGS, 0, offsetof(struct Identity, comm_type),
    7.80 +		(ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
    7.81 +		0,
    7.82 +		&asn_DEF_NativeInteger,
    7.83 +		memb_comm_type_constraint_1,
    7.84 +		&asn_PER_memb_comm_type_constr_6,
    7.85 +		0,
    7.86 +		"comm-type"
    7.87 +		},
    7.88 +	{ ATF_NOFLAGS, 0, offsetof(struct Identity, lang),
    7.89 +		(ASN_TAG_CLASS_UNIVERSAL | (19 << 2)),
    7.90 +		0,
    7.91 +		&asn_DEF_PrintableString,
    7.92 +		0,	/* Defer constraints checking to the member type */
    7.93 +		0,	/* No PER visible constraints */
    7.94 +		0,
    7.95 +		"lang"
    7.96 +		},
    7.97 +};
    7.98 +static ber_tlv_tag_t asn_DEF_Identity_tags_1[] = {
    7.99 +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
   7.100 +};
   7.101 +static asn_TYPE_tag2member_t asn_MAP_Identity_tag2el_1[] = {
   7.102 +    { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 4, 0, 0 }, /* comm-type */
   7.103 +    { (ASN_TAG_CLASS_UNIVERSAL | (12 << 2)), 0, 0, 3 }, /* address */
   7.104 +    { (ASN_TAG_CLASS_UNIVERSAL | (12 << 2)), 1, -1, 2 }, /* fpr */
   7.105 +    { (ASN_TAG_CLASS_UNIVERSAL | (12 << 2)), 2, -2, 1 }, /* user-id */
   7.106 +    { (ASN_TAG_CLASS_UNIVERSAL | (12 << 2)), 3, -3, 0 }, /* username */
   7.107 +    { (ASN_TAG_CLASS_UNIVERSAL | (19 << 2)), 5, 0, 0 } /* lang */
   7.108 +};
   7.109 +static asn_SEQUENCE_specifics_t asn_SPC_Identity_specs_1 = {
   7.110 +	sizeof(struct Identity),
   7.111 +	offsetof(struct Identity, _asn_ctx),
   7.112 +	asn_MAP_Identity_tag2el_1,
   7.113 +	6,	/* Count of tags in the map */
   7.114 +	0, 0, 0,	/* Optional elements (not needed) */
   7.115 +	-1,	/* Start extensions */
   7.116 +	-1	/* Stop extensions */
   7.117 +};
   7.118 +asn_TYPE_descriptor_t asn_DEF_Identity = {
   7.119 +	"Identity",
   7.120 +	"Identity",
   7.121 +	SEQUENCE_free,
   7.122 +	SEQUENCE_print,
   7.123 +	SEQUENCE_constraint,
   7.124 +	SEQUENCE_decode_ber,
   7.125 +	SEQUENCE_encode_der,
   7.126 +	SEQUENCE_decode_xer,
   7.127 +	SEQUENCE_encode_xer,
   7.128 +	SEQUENCE_decode_uper,
   7.129 +	SEQUENCE_encode_uper,
   7.130 +	0,	/* Use generic outmost tag fetcher */
   7.131 +	asn_DEF_Identity_tags_1,
   7.132 +	sizeof(asn_DEF_Identity_tags_1)
   7.133 +		/sizeof(asn_DEF_Identity_tags_1[0]), /* 1 */
   7.134 +	asn_DEF_Identity_tags_1,	/* Same as above */
   7.135 +	sizeof(asn_DEF_Identity_tags_1)
   7.136 +		/sizeof(asn_DEF_Identity_tags_1[0]), /* 1 */
   7.137 +	0,	/* No PER visible constraints */
   7.138 +	asn_MBR_Identity_1,
   7.139 +	6,	/* Elements count */
   7.140 +	&asn_SPC_Identity_specs_1	/* Additional specs */
   7.141 +};
   7.142 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/asn.1/Identity.h	Wed May 11 20:06:23 2016 +0200
     8.3 @@ -0,0 +1,44 @@
     8.4 +/*
     8.5 + * Generated by asn1c-0.9.26 (http://lionet.info/asn1c)
     8.6 + * From ASN.1 module "PEP"
     8.7 + * 	found in "pEp.asn1"
     8.8 + */
     8.9 +
    8.10 +#ifndef	_Identity_H_
    8.11 +#define	_Identity_H_
    8.12 +
    8.13 +
    8.14 +#include <asn_application.h>
    8.15 +
    8.16 +/* Including external dependencies */
    8.17 +#include <UTF8String.h>
    8.18 +#include <NativeInteger.h>
    8.19 +#include <PrintableString.h>
    8.20 +#include <constr_SEQUENCE.h>
    8.21 +
    8.22 +#ifdef __cplusplus
    8.23 +extern "C" {
    8.24 +#endif
    8.25 +
    8.26 +/* Identity */
    8.27 +typedef struct Identity {
    8.28 +	UTF8String_t	 address;
    8.29 +	UTF8String_t	 fpr;
    8.30 +	UTF8String_t	 user_id;
    8.31 +	UTF8String_t	 username;
    8.32 +	long	 comm_type;
    8.33 +	PrintableString_t	 lang;
    8.34 +	
    8.35 +	/* Context for parsing across buffer boundaries */
    8.36 +	asn_struct_ctx_t _asn_ctx;
    8.37 +} Identity_t;
    8.38 +
    8.39 +/* Implementation */
    8.40 +extern asn_TYPE_descriptor_t asn_DEF_Identity;
    8.41 +
    8.42 +#ifdef __cplusplus
    8.43 +}
    8.44 +#endif
    8.45 +
    8.46 +#endif	/* _Identity_H_ */
    8.47 +#include <asn_internal.h>
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/asn.1/Makefile.am.sample	Wed May 11 20:06:23 2016 +0200
     9.3 @@ -0,0 +1,100 @@
     9.4 +ASN_MODULE_SOURCES=	\
     9.5 +	Identity.c	\
     9.6 +	Stringlist.c	\
     9.7 +	Version.c	\
     9.8 +	Header.c
     9.9 +
    9.10 +ASN_MODULE_HEADERS=	\
    9.11 +	Identity.h	\
    9.12 +	Stringlist.h	\
    9.13 +	Version.h	\
    9.14 +	Header.h
    9.15 +
    9.16 +ASN_MODULE_HEADERS+=UTF8String.h
    9.17 +ASN_MODULE_HEADERS+=INTEGER.h
    9.18 +ASN_MODULE_HEADERS+=NativeEnumerated.h
    9.19 +ASN_MODULE_SOURCES+=INTEGER.c
    9.20 +ASN_MODULE_SOURCES+=NativeEnumerated.c
    9.21 +ASN_MODULE_HEADERS+=NativeInteger.h
    9.22 +ASN_MODULE_SOURCES+=NativeInteger.c
    9.23 +ASN_MODULE_HEADERS+=PrintableString.h
    9.24 +ASN_MODULE_SOURCES+=PrintableString.c
    9.25 +ASN_MODULE_SOURCES+=UTF8String.c
    9.26 +ASN_MODULE_HEADERS+=asn_SEQUENCE_OF.h
    9.27 +ASN_MODULE_SOURCES+=asn_SEQUENCE_OF.c
    9.28 +ASN_MODULE_HEADERS+=asn_SET_OF.h
    9.29 +ASN_MODULE_SOURCES+=asn_SET_OF.c
    9.30 +ASN_MODULE_HEADERS+=constr_SEQUENCE.h
    9.31 +ASN_MODULE_SOURCES+=constr_SEQUENCE.c
    9.32 +ASN_MODULE_HEADERS+=constr_SEQUENCE_OF.h
    9.33 +ASN_MODULE_SOURCES+=constr_SEQUENCE_OF.c
    9.34 +ASN_MODULE_HEADERS+=constr_SET_OF.h
    9.35 +ASN_MODULE_SOURCES+=constr_SET_OF.c
    9.36 +ASN_MODULE_HEADERS+=asn_application.h
    9.37 +ASN_MODULE_HEADERS+=asn_system.h
    9.38 +ASN_MODULE_HEADERS+=asn_codecs.h
    9.39 +ASN_MODULE_HEADERS+=asn_internal.h
    9.40 +ASN_MODULE_HEADERS+=OCTET_STRING.h
    9.41 +ASN_MODULE_SOURCES+=OCTET_STRING.c
    9.42 +ASN_MODULE_HEADERS+=BIT_STRING.h
    9.43 +ASN_MODULE_SOURCES+=BIT_STRING.c
    9.44 +ASN_MODULE_SOURCES+=asn_codecs_prim.c
    9.45 +ASN_MODULE_HEADERS+=asn_codecs_prim.h
    9.46 +ASN_MODULE_HEADERS+=ber_tlv_length.h
    9.47 +ASN_MODULE_SOURCES+=ber_tlv_length.c
    9.48 +ASN_MODULE_HEADERS+=ber_tlv_tag.h
    9.49 +ASN_MODULE_SOURCES+=ber_tlv_tag.c
    9.50 +ASN_MODULE_HEADERS+=ber_decoder.h
    9.51 +ASN_MODULE_SOURCES+=ber_decoder.c
    9.52 +ASN_MODULE_HEADERS+=der_encoder.h
    9.53 +ASN_MODULE_SOURCES+=der_encoder.c
    9.54 +ASN_MODULE_HEADERS+=constr_TYPE.h
    9.55 +ASN_MODULE_SOURCES+=constr_TYPE.c
    9.56 +ASN_MODULE_HEADERS+=constraints.h
    9.57 +ASN_MODULE_SOURCES+=constraints.c
    9.58 +ASN_MODULE_HEADERS+=xer_support.h
    9.59 +ASN_MODULE_SOURCES+=xer_support.c
    9.60 +ASN_MODULE_HEADERS+=xer_decoder.h
    9.61 +ASN_MODULE_SOURCES+=xer_decoder.c
    9.62 +ASN_MODULE_HEADERS+=xer_encoder.h
    9.63 +ASN_MODULE_SOURCES+=xer_encoder.c
    9.64 +ASN_MODULE_HEADERS+=per_support.h
    9.65 +ASN_MODULE_SOURCES+=per_support.c
    9.66 +ASN_MODULE_HEADERS+=per_decoder.h
    9.67 +ASN_MODULE_SOURCES+=per_decoder.c
    9.68 +ASN_MODULE_HEADERS+=per_encoder.h
    9.69 +ASN_MODULE_SOURCES+=per_encoder.c
    9.70 +ASN_MODULE_HEADERS+=per_opentype.h
    9.71 +ASN_MODULE_SOURCES+=per_opentype.c
    9.72 +ASN_CONVERTER_SOURCES+=converter-sample.c
    9.73 +
    9.74 +
    9.75 +lib_LTLIBRARIES=libsomething.la
    9.76 +libsomething_la_SOURCES=$(ASN_MODULE_SOURCES) $(ASN_MODULE_HEADERS)
    9.77 +
    9.78 +# This file may be used as an input for make(3)
    9.79 +# Remove the lines below to convert it into a pure .am file
    9.80 +TARGET = progname
    9.81 +CFLAGS += -I.
    9.82 +OBJS=${ASN_MODULE_SOURCES:.c=.o} ${ASN_CONVERTER_SOURCES:.c=.o}
    9.83 +
    9.84 +all: $(TARGET)
    9.85 +
    9.86 +$(TARGET): ${OBJS}
    9.87 +	$(CC) $(CFLAGS) -o $(TARGET) ${OBJS} $(LDFLAGS) $(LIBS)
    9.88 +
    9.89 +.SUFFIXES:
    9.90 +.SUFFIXES: .c .o
    9.91 +
    9.92 +.c.o:
    9.93 +	$(CC) $(CFLAGS) -o $@ -c $<
    9.94 +
    9.95 +clean:
    9.96 +	rm -f $(TARGET)
    9.97 +	rm -f $(OBJS)
    9.98 +
    9.99 +regen: regenerate-from-asn1-source
   9.100 +
   9.101 +regenerate-from-asn1-source:
   9.102 +	asn1c -gen-PER pEp.asn1
   9.103 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/asn.1/NativeEnumerated.c	Wed May 11 20:06:23 2016 +0200
    10.3 @@ -0,0 +1,207 @@
    10.4 +/*-
    10.5 + * Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
    10.6 + * Redistribution and modifications are permitted subject to BSD license.
    10.7 + */
    10.8 +/*
    10.9 + * Read the NativeInteger.h for the explanation wrt. differences between
   10.10 + * INTEGER and NativeInteger.
   10.11 + * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
   10.12 + * implementation deals with the standard (machine-specific) representation
   10.13 + * of them instead of using the platform-independent buffer.
   10.14 + */
   10.15 +#include <asn_internal.h>
   10.16 +#include <NativeEnumerated.h>
   10.17 +
   10.18 +/*
   10.19 + * NativeEnumerated basic type description.
   10.20 + */
   10.21 +static ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
   10.22 +	(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
   10.23 +};
   10.24 +asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
   10.25 +	"ENUMERATED",			/* The ASN.1 type is still ENUMERATED */
   10.26 +	"ENUMERATED",
   10.27 +	NativeInteger_free,
   10.28 +	NativeInteger_print,
   10.29 +	asn_generic_no_constraint,
   10.30 +	NativeInteger_decode_ber,
   10.31 +	NativeInteger_encode_der,
   10.32 +	NativeInteger_decode_xer,
   10.33 +	NativeEnumerated_encode_xer,
   10.34 +	NativeEnumerated_decode_uper,
   10.35 +	NativeEnumerated_encode_uper,
   10.36 +	0, /* Use generic outmost tag fetcher */
   10.37 +	asn_DEF_NativeEnumerated_tags,
   10.38 +	sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
   10.39 +	asn_DEF_NativeEnumerated_tags,	/* Same as above */
   10.40 +	sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
   10.41 +	0,	/* No PER visible constraints */
   10.42 +	0, 0,	/* No members */
   10.43 +	0	/* No specifics */
   10.44 +};
   10.45 +
   10.46 +asn_enc_rval_t
   10.47 +NativeEnumerated_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
   10.48 +        int ilevel, enum xer_encoder_flags_e flags,
   10.49 +                asn_app_consume_bytes_f *cb, void *app_key) {
   10.50 +	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
   10.51 +        asn_enc_rval_t er;
   10.52 +        const long *native = (const long *)sptr;
   10.53 +	const asn_INTEGER_enum_map_t *el;
   10.54 +
   10.55 +        (void)ilevel;
   10.56 +        (void)flags;
   10.57 +
   10.58 +        if(!native) _ASN_ENCODE_FAILED;
   10.59 +
   10.60 +	el = INTEGER_map_value2enum(specs, *native);
   10.61 +	if(el) {
   10.62 +		size_t srcsize = el->enum_len + 5;
   10.63 +		char *src = (char *)alloca(srcsize);
   10.64 +
   10.65 +		er.encoded = snprintf(src, srcsize, "<%s/>", el->enum_name);
   10.66 +		assert(er.encoded > 0 && (size_t)er.encoded < srcsize);
   10.67 +		if(cb(src, er.encoded, app_key) < 0) _ASN_ENCODE_FAILED;
   10.68 +		_ASN_ENCODED_OK(er);
   10.69 +	} else {
   10.70 +		ASN_DEBUG("ASN.1 forbids dealing with "
   10.71 +			"unknown value of ENUMERATED type");
   10.72 +		_ASN_ENCODE_FAILED;
   10.73 +	}
   10.74 +}
   10.75 +
   10.76 +asn_dec_rval_t
   10.77 +NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
   10.78 +	asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
   10.79 +	void **sptr, asn_per_data_t *pd) {
   10.80 +	asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
   10.81 +	asn_dec_rval_t rval = { RC_OK, 0 };
   10.82 +	long *native = (long *)*sptr;
   10.83 +	asn_per_constraint_t *ct;
   10.84 +	long value;
   10.85 +
   10.86 +	(void)opt_codec_ctx;
   10.87 +
   10.88 +	if(constraints) ct = &constraints->value;
   10.89 +	else if(td->per_constraints) ct = &td->per_constraints->value;
   10.90 +	else _ASN_DECODE_FAILED;	/* Mandatory! */
   10.91 +	if(!specs) _ASN_DECODE_FAILED;
   10.92 +
   10.93 +	if(!native) {
   10.94 +		native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
   10.95 +		if(!native) _ASN_DECODE_FAILED;
   10.96 +	}
   10.97 +
   10.98 +	ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
   10.99 +
  10.100 +	if(ct->flags & APC_EXTENSIBLE) {
  10.101 +		int inext = per_get_few_bits(pd, 1);
  10.102 +		if(inext < 0) _ASN_DECODE_STARVED;
  10.103 +		if(inext) ct = 0;
  10.104 +	}
  10.105 +
  10.106 +	if(ct && ct->range_bits >= 0) {
  10.107 +		value = per_get_few_bits(pd, ct->range_bits);
  10.108 +		if(value < 0) _ASN_DECODE_STARVED;
  10.109 +		if(value >= (specs->extension
  10.110 +			? specs->extension - 1 : specs->map_count))
  10.111 +			_ASN_DECODE_FAILED;
  10.112 +	} else {
  10.113 +		if(!specs->extension)
  10.114 +			_ASN_DECODE_FAILED;
  10.115 +		/*
  10.116 +		 * X.691, #10.6: normally small non-negative whole number;
  10.117 +		 */
  10.118 +		value = uper_get_nsnnwn(pd);
  10.119 +		if(value < 0) _ASN_DECODE_STARVED;
  10.120 +		value += specs->extension - 1;
  10.121 +		if(value >= specs->map_count)
  10.122 +			_ASN_DECODE_FAILED;
  10.123 +	}
  10.124 +
  10.125 +	*native = specs->value2enum[value].nat_value;
  10.126 +	ASN_DEBUG("Decoded %s = %ld", td->name, *native);
  10.127 +
  10.128 +	return rval;
  10.129 +}
  10.130 +
  10.131 +static int
  10.132 +NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
  10.133 +	const asn_INTEGER_enum_map_t *a = ap;
  10.134 +	const asn_INTEGER_enum_map_t *b = bp;
  10.135 +	if(a->nat_value == b->nat_value)
  10.136 +		return 0;
  10.137 +	if(a->nat_value < b->nat_value)
  10.138 +		return -1;
  10.139 +	return 1;
  10.140 +}
  10.141 +
  10.142 +asn_enc_rval_t
  10.143 +NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td,
  10.144 +	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
  10.145 +	asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics;
  10.146 +	asn_enc_rval_t er;
  10.147 +	long native, value;
  10.148 +	asn_per_constraint_t *ct;
  10.149 +	int inext = 0;
  10.150 +	asn_INTEGER_enum_map_t key;
  10.151 +	asn_INTEGER_enum_map_t *kf;
  10.152 +
  10.153 +	if(!sptr) _ASN_ENCODE_FAILED;
  10.154 +	if(!specs) _ASN_ENCODE_FAILED;
  10.155 +
  10.156 +	if(constraints) ct = &constraints->value;
  10.157 +	else if(td->per_constraints) ct = &td->per_constraints->value;
  10.158 +	else _ASN_ENCODE_FAILED;	/* Mandatory! */
  10.159 +
  10.160 +	ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
  10.161 +
  10.162 +	er.encoded = 0;
  10.163 +
  10.164 +	native = *(long *)sptr;
  10.165 +	if(native < 0) _ASN_ENCODE_FAILED;
  10.166 +
  10.167 +	key.nat_value = native;
  10.168 +	kf = bsearch(&key, specs->value2enum, specs->map_count,
  10.169 +		sizeof(key), NativeEnumerated__compar_value2enum);
  10.170 +	if(!kf) {
  10.171 +		ASN_DEBUG("No element corresponds to %ld", native);
  10.172 +		_ASN_ENCODE_FAILED;
  10.173 +	}
  10.174 +	value = kf - specs->value2enum;
  10.175 +
  10.176 +	if(ct->range_bits >= 0) {
  10.177 +		int cmpWith = specs->extension
  10.178 +				? specs->extension - 1 : specs->map_count;
  10.179 +		if(value >= cmpWith)
  10.180 +			inext = 1;
  10.181 +	}
  10.182 +	if(ct->flags & APC_EXTENSIBLE) {
  10.183 +		if(per_put_few_bits(po, inext, 1))
  10.184 +			_ASN_ENCODE_FAILED;
  10.185 +		if(inext) ct = 0;
  10.186 +	} else if(inext) {
  10.187 +		_ASN_ENCODE_FAILED;
  10.188 +	}
  10.189 +
  10.190 +	if(ct && ct->range_bits >= 0) {
  10.191 +		if(per_put_few_bits(po, value, ct->range_bits))
  10.192 +			_ASN_ENCODE_FAILED;
  10.193 +		_ASN_ENCODED_OK(er);
  10.194 +	}
  10.195 +
  10.196 +	if(!specs->extension)
  10.197 +		_ASN_ENCODE_FAILED;
  10.198 +
  10.199 +	/*
  10.200 +	 * X.691, #10.6: normally small non-negative whole number;
  10.201 +	 */
  10.202 +	ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
  10.203 +		value, specs->extension, inext,
  10.204 +		value - (inext ? (specs->extension - 1) : 0));
  10.205 +	if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
  10.206 +		_ASN_ENCODE_FAILED;
  10.207 +
  10.208 +	_ASN_ENCODED_OK(er);
  10.209 +}
  10.210 +
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/asn.1/NativeEnumerated.h	Wed May 11 20:06:23 2016 +0200
    11.3 @@ -0,0 +1,32 @@
    11.4 +/*-
    11.5 + * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
    11.6 + * All rights reserved.
    11.7 + * Redistribution and modifications are permitted subject to BSD license.
    11.8 + */
    11.9 +/*
   11.10 + * This type differs from the standard ENUMERATED in that it is modelled using
   11.11 + * the fixed machine type (long, int, short), so it can hold only values of
   11.12 + * limited length. There is no type (i.e., NativeEnumerated_t, any integer type
   11.13 + * will do).
   11.14 + * This type may be used when integer range is limited by subtype constraints.
   11.15 + */
   11.16 +#ifndef	_NativeEnumerated_H_
   11.17 +#define	_NativeEnumerated_H_
   11.18 +
   11.19 +#include <NativeInteger.h>
   11.20 +
   11.21 +#ifdef __cplusplus
   11.22 +extern "C" {
   11.23 +#endif
   11.24 +
   11.25 +extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
   11.26 +
   11.27 +xer_type_encoder_f NativeEnumerated_encode_xer;
   11.28 +per_type_decoder_f NativeEnumerated_decode_uper;
   11.29 +per_type_encoder_f NativeEnumerated_encode_uper;
   11.30 +
   11.31 +#ifdef __cplusplus
   11.32 +}
   11.33 +#endif
   11.34 +
   11.35 +#endif	/* _NativeEnumerated_H_ */
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/asn.1/NativeInteger.c	Wed May 11 20:06:23 2016 +0200
    12.3 @@ -0,0 +1,332 @@
    12.4 +/*-
    12.5 + * Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
    12.6 + * All rights reserved.
    12.7 + * Redistribution and modifications are permitted subject to BSD license.
    12.8 + */
    12.9 +/*
   12.10 + * Read the NativeInteger.h for the explanation wrt. differences between
   12.11 + * INTEGER and NativeInteger.
   12.12 + * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
   12.13 + * implementation deals with the standard (machine-specific) representation
   12.14 + * of them instead of using the platform-independent buffer.
   12.15 + */
   12.16 +#include <asn_internal.h>
   12.17 +#include <NativeInteger.h>
   12.18 +
   12.19 +/*
   12.20 + * NativeInteger basic type description.
   12.21 + */
   12.22 +static ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = {
   12.23 +	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
   12.24 +};
   12.25 +asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
   12.26 +	"INTEGER",			/* The ASN.1 type is still INTEGER */
   12.27 +	"INTEGER",
   12.28 +	NativeInteger_free,
   12.29 +	NativeInteger_print,
   12.30 +	asn_generic_no_constraint,
   12.31 +	NativeInteger_decode_ber,
   12.32 +	NativeInteger_encode_der,
   12.33 +	NativeInteger_decode_xer,
   12.34 +	NativeInteger_encode_xer,
   12.35 +	NativeInteger_decode_uper,	/* Unaligned PER decoder */
   12.36 +	NativeInteger_encode_uper,	/* Unaligned PER encoder */
   12.37 +	0, /* Use generic outmost tag fetcher */
   12.38 +	asn_DEF_NativeInteger_tags,
   12.39 +	sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
   12.40 +	asn_DEF_NativeInteger_tags,	/* Same as above */
   12.41 +	sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
   12.42 +	0,	/* No PER visible constraints */
   12.43 +	0, 0,	/* No members */
   12.44 +	0	/* No specifics */
   12.45 +};
   12.46 +
   12.47 +/*
   12.48 + * Decode INTEGER type.
   12.49 + */
   12.50 +asn_dec_rval_t
   12.51 +NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
   12.52 +	asn_TYPE_descriptor_t *td,
   12.53 +	void **nint_ptr, const void *buf_ptr, size_t size, int tag_mode) {
   12.54 +	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
   12.55 +	long *native = (long *)*nint_ptr;
   12.56 +	asn_dec_rval_t rval;
   12.57 +	ber_tlv_len_t length;
   12.58 +
   12.59 +	/*
   12.60 +	 * If the structure is not there, allocate it.
   12.61 +	 */
   12.62 +	if(native == NULL) {
   12.63 +		native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
   12.64 +		if(native == NULL) {
   12.65 +			rval.code = RC_FAIL;
   12.66 +			rval.consumed = 0;
   12.67 +			return rval;
   12.68 +		}
   12.69 +	}
   12.70 +
   12.71 +	ASN_DEBUG("Decoding %s as INTEGER (tm=%d)",
   12.72 +		td->name, tag_mode);
   12.73 +
   12.74 +	/*
   12.75 +	 * Check tags.
   12.76 +	 */
   12.77 +	rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
   12.78 +			tag_mode, 0, &length, 0);
   12.79 +	if(rval.code != RC_OK)
   12.80 +		return rval;
   12.81 +
   12.82 +	ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
   12.83 +
   12.84 +	/*
   12.85 +	 * Make sure we have this length.
   12.86 +	 */
   12.87 +	buf_ptr = ((const char *)buf_ptr) + rval.consumed;
   12.88 +	size -= rval.consumed;
   12.89 +	if(length > (ber_tlv_len_t)size) {
   12.90 +		rval.code = RC_WMORE;
   12.91 +		rval.consumed = 0;
   12.92 +		return rval;
   12.93 +	}
   12.94 +
   12.95 +	/*
   12.96 +	 * ASN.1 encoded INTEGER: buf_ptr, length
   12.97 +	 * Fill the native, at the same time checking for overflow.
   12.98 +	 * If overflow occured, return with RC_FAIL.
   12.99 +	 */
  12.100 +	{
  12.101 +		INTEGER_t tmp;
  12.102 +		union {
  12.103 +			const void *constbuf;
  12.104 +			void *nonconstbuf;
  12.105 +		} unconst_buf;
  12.106 +		long l;
  12.107 +
  12.108 +		unconst_buf.constbuf = buf_ptr;
  12.109 +		tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
  12.110 +		tmp.size = length;
  12.111 +
  12.112 +		if((specs&&specs->field_unsigned)
  12.113 +			? asn_INTEGER2ulong(&tmp, (unsigned long *)&l) /* sic */
  12.114 +			: asn_INTEGER2long(&tmp, &l)) {
  12.115 +			rval.code = RC_FAIL;
  12.116 +			rval.consumed = 0;
  12.117 +			return rval;
  12.118 +		}
  12.119 +
  12.120 +		*native = l;
  12.121 +	}
  12.122 +
  12.123 +	rval.code = RC_OK;
  12.124 +	rval.consumed += length;
  12.125 +
  12.126 +	ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)",
  12.127 +		(long)rval.consumed, (long)length, td->name, (long)*native);
  12.128 +
  12.129 +	return rval;
  12.130 +}
  12.131 +
  12.132 +/*
  12.133 + * Encode the NativeInteger using the standard INTEGER type DER encoder.
  12.134 + */
  12.135 +asn_enc_rval_t
  12.136 +NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr,
  12.137 +	int tag_mode, ber_tlv_tag_t tag,
  12.138 +	asn_app_consume_bytes_f *cb, void *app_key) {
  12.139 +	unsigned long native = *(unsigned long *)ptr;	/* Disable sign ext. */
  12.140 +	asn_enc_rval_t erval;
  12.141 +	INTEGER_t tmp;
  12.142 +
  12.143 +#ifdef	WORDS_BIGENDIAN		/* Opportunistic optimization */
  12.144 +
  12.145 +	tmp.buf = (uint8_t *)&native;
  12.146 +	tmp.size = sizeof(native);
  12.147 +
  12.148 +#else	/* Works even if WORDS_BIGENDIAN is not set where should've been */
  12.149 +	uint8_t buf[sizeof(native)];
  12.150 +	uint8_t *p;
  12.151 +
  12.152 +	/* Prepare a fake INTEGER */
  12.153 +	for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8)
  12.154 +		*p = (uint8_t)native;
  12.155 +
  12.156 +	tmp.buf = buf;
  12.157 +	tmp.size = sizeof(buf);
  12.158 +#endif	/* WORDS_BIGENDIAN */
  12.159 +	
  12.160 +	/* Encode fake INTEGER */
  12.161 +	erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key);
  12.162 +	if(erval.encoded == -1) {
  12.163 +		assert(erval.structure_ptr == &tmp);
  12.164 +		erval.structure_ptr = ptr;
  12.165 +	}
  12.166 +	return erval;
  12.167 +}
  12.168 +
  12.169 +/*
  12.170 + * Decode the chunk of XML text encoding INTEGER.
  12.171 + */
  12.172 +asn_dec_rval_t
  12.173 +NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
  12.174 +	asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
  12.175 +		const void *buf_ptr, size_t size) {
  12.176 +	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
  12.177 +	asn_dec_rval_t rval;
  12.178 +	INTEGER_t st;
  12.179 +	void *st_ptr = (void *)&st;
  12.180 +	long *native = (long *)*sptr;
  12.181 +
  12.182 +	if(!native) {
  12.183 +		native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
  12.184 +		if(!native) _ASN_DECODE_FAILED;
  12.185 +	}
  12.186 +
  12.187 +	memset(&st, 0, sizeof(st));
  12.188 +	rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr, 
  12.189 +		opt_mname, buf_ptr, size);
  12.190 +	if(rval.code == RC_OK) {
  12.191 +		long l;
  12.192 +		if((specs&&specs->field_unsigned)
  12.193 +			? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */
  12.194 +			: asn_INTEGER2long(&st, &l)) {
  12.195 +			rval.code = RC_FAIL;
  12.196 +			rval.consumed = 0;
  12.197 +		} else {
  12.198 +			*native = l;
  12.199 +		}
  12.200 +	} else {
  12.201 +		/*
  12.202 +		 * Cannot restart from the middle;
  12.203 +		 * there is no place to save state in the native type.
  12.204 +		 * Request a continuation from the very beginning.
  12.205 +		 */
  12.206 +		rval.consumed = 0;
  12.207 +	}
  12.208 +	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
  12.209 +	return rval;
  12.210 +}
  12.211 +
  12.212 +
  12.213 +asn_enc_rval_t
  12.214 +NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
  12.215 +	int ilevel, enum xer_encoder_flags_e flags,
  12.216 +		asn_app_consume_bytes_f *cb, void *app_key) {
  12.217 +	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
  12.218 +	char scratch[32];	/* Enough for 64-bit int */
  12.219 +	asn_enc_rval_t er;
  12.220 +	const long *native = (const long *)sptr;
  12.221 +
  12.222 +	(void)ilevel;
  12.223 +	(void)flags;
  12.224 +
  12.225 +	if(!native) _ASN_ENCODE_FAILED;
  12.226 +
  12.227 +	er.encoded = snprintf(scratch, sizeof(scratch),
  12.228 +			(specs && specs->field_unsigned)
  12.229 +			? "%lu" : "%ld", *native);
  12.230 +	if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
  12.231 +		|| cb(scratch, er.encoded, app_key) < 0)
  12.232 +		_ASN_ENCODE_FAILED;
  12.233 +
  12.234 +	_ASN_ENCODED_OK(er);
  12.235 +}
  12.236 +
  12.237 +asn_dec_rval_t
  12.238 +NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
  12.239 +	asn_TYPE_descriptor_t *td,
  12.240 +	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
  12.241 +
  12.242 +	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
  12.243 +	asn_dec_rval_t rval;
  12.244 +	long *native = (long *)*sptr;
  12.245 +	INTEGER_t tmpint;
  12.246 +	void *tmpintptr = &tmpint;
  12.247 +
  12.248 +	(void)opt_codec_ctx;
  12.249 +	ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name);
  12.250 +
  12.251 +	if(!native) {
  12.252 +		native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
  12.253 +		if(!native) _ASN_DECODE_FAILED;
  12.254 +	}
  12.255 +
  12.256 +	memset(&tmpint, 0, sizeof tmpint);
  12.257 +	rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints,
  12.258 +				   &tmpintptr, pd);
  12.259 +	if(rval.code == RC_OK) {
  12.260 +		if((specs&&specs->field_unsigned)
  12.261 +			? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
  12.262 +			: asn_INTEGER2long(&tmpint, native))
  12.263 +			rval.code = RC_FAIL;
  12.264 +		else
  12.265 +			ASN_DEBUG("NativeInteger %s got value %ld",
  12.266 +				td->name, *native);
  12.267 +	}
  12.268 +	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
  12.269 +
  12.270 +	return rval;
  12.271 +}
  12.272 +
  12.273 +asn_enc_rval_t
  12.274 +NativeInteger_encode_uper(asn_TYPE_descriptor_t *td,
  12.275 +	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
  12.276 +	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
  12.277 +	asn_enc_rval_t er;
  12.278 +	long native;
  12.279 +	INTEGER_t tmpint;
  12.280 +
  12.281 +	if(!sptr) _ASN_ENCODE_FAILED;
  12.282 +
  12.283 +	native = *(long *)sptr;
  12.284 +
  12.285 +	ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native);
  12.286 +
  12.287 +	memset(&tmpint, 0, sizeof(tmpint));
  12.288 +	if((specs&&specs->field_unsigned)
  12.289 +		? asn_ulong2INTEGER(&tmpint, native)
  12.290 +		: asn_long2INTEGER(&tmpint, native))
  12.291 +		_ASN_ENCODE_FAILED;
  12.292 +	er = INTEGER_encode_uper(td, constraints, &tmpint, po);
  12.293 +	ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
  12.294 +	return er;
  12.295 +}
  12.296 +
  12.297 +/*
  12.298 + * INTEGER specific human-readable output.
  12.299 + */
  12.300 +int
  12.301 +NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
  12.302 +	asn_app_consume_bytes_f *cb, void *app_key) {
  12.303 +	asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
  12.304 +	const long *native = (const long *)sptr;
  12.305 +	char scratch[32];	/* Enough for 64-bit int */
  12.306 +	int ret;
  12.307 +
  12.308 +	(void)td;	/* Unused argument */
  12.309 +	(void)ilevel;	/* Unused argument */
  12.310 +
  12.311 +	if(native) {
  12.312 +		ret = snprintf(scratch, sizeof(scratch),
  12.313 +			(specs && specs->field_unsigned)
  12.314 +			? "%lu" : "%ld", *native);
  12.315 +		assert(ret > 0 && (size_t)ret < sizeof(scratch));
  12.316 +		return (cb(scratch, ret, app_key) < 0) ? -1 : 0;
  12.317 +	} else {
  12.318 +		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
  12.319 +	}
  12.320 +}
  12.321 +
  12.322 +void
  12.323 +NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
  12.324 +
  12.325 +	if(!td || !ptr)
  12.326 +		return;
  12.327 +
  12.328 +	ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)",
  12.329 +		td->name, contents_only, ptr);
  12.330 +
  12.331 +	if(!contents_only) {
  12.332 +		FREEMEM(ptr);
  12.333 +	}
  12.334 +}
  12.335 +
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/asn.1/NativeInteger.h	Wed May 11 20:06:23 2016 +0200
    13.3 @@ -0,0 +1,37 @@
    13.4 +/*-
    13.5 + * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    13.6 + * Redistribution and modifications are permitted subject to BSD license.
    13.7 + */
    13.8 +/*
    13.9 + * This type differs from the standard INTEGER in that it is modelled using
   13.10 + * the fixed machine type (long, int, short), so it can hold only values of
   13.11 + * limited length. There is no type (i.e., NativeInteger_t, any integer type
   13.12 + * will do).
   13.13 + * This type may be used when integer range is limited by subtype constraints.
   13.14 + */
   13.15 +#ifndef	_NativeInteger_H_
   13.16 +#define	_NativeInteger_H_
   13.17 +
   13.18 +#include <asn_application.h>
   13.19 +#include <INTEGER.h>
   13.20 +
   13.21 +#ifdef __cplusplus
   13.22 +extern "C" {
   13.23 +#endif
   13.24 +
   13.25 +extern asn_TYPE_descriptor_t asn_DEF_NativeInteger;
   13.26 +
   13.27 +asn_struct_free_f  NativeInteger_free;
   13.28 +asn_struct_print_f NativeInteger_print;
   13.29 +ber_type_decoder_f NativeInteger_decode_ber;
   13.30 +der_type_encoder_f NativeInteger_encode_der;
   13.31 +xer_type_decoder_f NativeInteger_decode_xer;
   13.32 +xer_type_encoder_f NativeInteger_encode_xer;
   13.33 +per_type_decoder_f NativeInteger_decode_uper;
   13.34 +per_type_encoder_f NativeInteger_encode_uper;
   13.35 +
   13.36 +#ifdef __cplusplus
   13.37 +}
   13.38 +#endif
   13.39 +
   13.40 +#endif	/* _NativeInteger_H_ */
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/asn.1/OCTET_STRING.c	Wed May 11 20:06:23 2016 +0200
    14.3 @@ -0,0 +1,1805 @@
    14.4 +/*-
    14.5 + * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
    14.6 + * All rights reserved.
    14.7 + * Redistribution and modifications are permitted subject to BSD license.
    14.8 + */
    14.9 +#include <asn_internal.h>
   14.10 +#include <OCTET_STRING.h>
   14.11 +#include <BIT_STRING.h>	/* for .bits_unused member */
   14.12 +#include <errno.h>
   14.13 +
   14.14 +/*
   14.15 + * OCTET STRING basic type description.
   14.16 + */
   14.17 +static ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = {
   14.18 +	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
   14.19 +};
   14.20 +static asn_OCTET_STRING_specifics_t asn_DEF_OCTET_STRING_specs = {
   14.21 +	sizeof(OCTET_STRING_t),
   14.22 +	offsetof(OCTET_STRING_t, _asn_ctx),
   14.23 +	ASN_OSUBV_STR
   14.24 +};
   14.25 +static asn_per_constraints_t asn_DEF_OCTET_STRING_constraints = {
   14.26 +	{ APC_CONSTRAINED, 8, 8, 0, 255 },
   14.27 +	{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
   14.28 +	0, 0
   14.29 +};
   14.30 +asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
   14.31 +	"OCTET STRING",		/* Canonical name */
   14.32 +	"OCTET_STRING",		/* XML tag name */
   14.33 +	OCTET_STRING_free,
   14.34 +	OCTET_STRING_print,	/* non-ascii stuff, generally */
   14.35 +	asn_generic_no_constraint,
   14.36 +	OCTET_STRING_decode_ber,
   14.37 +	OCTET_STRING_encode_der,
   14.38 +	OCTET_STRING_decode_xer_hex,
   14.39 +	OCTET_STRING_encode_xer,
   14.40 +	OCTET_STRING_decode_uper,	/* Unaligned PER decoder */
   14.41 +	OCTET_STRING_encode_uper,	/* Unaligned PER encoder */
   14.42 +	0, /* Use generic outmost tag fetcher */
   14.43 +	asn_DEF_OCTET_STRING_tags,
   14.44 +	sizeof(asn_DEF_OCTET_STRING_tags)
   14.45 +	  / sizeof(asn_DEF_OCTET_STRING_tags[0]),
   14.46 +	asn_DEF_OCTET_STRING_tags,	/* Same as above */
   14.47 +	sizeof(asn_DEF_OCTET_STRING_tags)
   14.48 +	  / sizeof(asn_DEF_OCTET_STRING_tags[0]),
   14.49 +	0,	/* No PER visible constraints */
   14.50 +	0, 0,	/* No members */
   14.51 +	&asn_DEF_OCTET_STRING_specs
   14.52 +};
   14.53 +
   14.54 +#undef	_CH_PHASE
   14.55 +#undef	NEXT_PHASE
   14.56 +#undef	PREV_PHASE
   14.57 +#define	_CH_PHASE(ctx, inc) do {					\
   14.58 +		if(ctx->phase == 0)					\
   14.59 +			ctx->context = 0;				\
   14.60 +		ctx->phase += inc;					\
   14.61 +	} while(0)
   14.62 +#define	NEXT_PHASE(ctx)	_CH_PHASE(ctx, +1)
   14.63 +#define	PREV_PHASE(ctx)	_CH_PHASE(ctx, -1)
   14.64 +
   14.65 +#undef	ADVANCE
   14.66 +#define	ADVANCE(num_bytes)	do {					\
   14.67 +		size_t num = (num_bytes);				\
   14.68 +		buf_ptr = ((const char *)buf_ptr) + num;		\
   14.69 +		size -= num;						\
   14.70 +		consumed_myself += num;					\
   14.71 +	} while(0)
   14.72 +
   14.73 +#undef	RETURN
   14.74 +#define	RETURN(_code)	do {						\
   14.75 +		asn_dec_rval_t tmprval;					\
   14.76 +		tmprval.code = _code;					\
   14.77 +		tmprval.consumed = consumed_myself;			\
   14.78 +		return tmprval;						\
   14.79 +	} while(0)
   14.80 +
   14.81 +#undef	APPEND
   14.82 +#define	APPEND(bufptr, bufsize)	do {					\
   14.83 +		size_t _bs = (bufsize);		/* Append size */	\
   14.84 +		size_t _ns = ctx->context;	/* Allocated now */	\
   14.85 +		size_t _es = st->size + _bs;	/* Expected size */	\
   14.86 +		/* int is really a typeof(st->size): */			\
   14.87 +		if((int)_es < 0) RETURN(RC_FAIL);			\
   14.88 +		if(_ns <= _es) {					\
   14.89 +			void *ptr;					\
   14.90 +			/* Be nice and round to the memory allocator */	\
   14.91 +			do { _ns = _ns ? _ns << 1 : 16; }		\
   14.92 +			    while(_ns <= _es);				\
   14.93 +			/* int is really a typeof(st->size): */		\
   14.94 +			if((int)_ns < 0) RETURN(RC_FAIL);		\
   14.95 +			ptr = REALLOC(st->buf, _ns);			\
   14.96 +			if(ptr) {					\
   14.97 +				st->buf = (uint8_t *)ptr;		\
   14.98 +				ctx->context = _ns;			\
   14.99 +			} else {					\
  14.100 +				RETURN(RC_FAIL);			\
  14.101 +			}						\
  14.102 +			ASN_DEBUG("Reallocating into %ld", (long)_ns);	\
  14.103 +		}							\
  14.104 +		memcpy(st->buf + st->size, bufptr, _bs);		\
  14.105 +		/* Convenient nul-termination */			\
  14.106 +		st->buf[_es] = '\0';					\
  14.107 +		st->size = _es;						\
  14.108 +	} while(0)
  14.109 +
  14.110 +/*
  14.111 + * The main reason why ASN.1 is still alive is that too much time and effort
  14.112 + * is necessary for learning it more or less adequately, thus creating a gut
  14.113 + * necessity to demonstrate that aquired skill everywhere afterwards.
  14.114 + * No, I am not going to explain what the following stuff is.
  14.115 + */
  14.116 +struct _stack_el {
  14.117 +	ber_tlv_len_t	left;	/* What's left to read (or -1) */
  14.118 +	ber_tlv_len_t	got;	/* What was actually processed */
  14.119 +	int	cont_level;	/* Depth of subcontainment */
  14.120 +	int	want_nulls;	/* Want null "end of content" octets? */
  14.121 +	int	bits_chopped;	/* Flag in BIT STRING mode */
  14.122 +	ber_tlv_tag_t	tag;	/* For debugging purposes */
  14.123 +	struct _stack_el *prev;
  14.124 +	struct _stack_el *next;
  14.125 +};
  14.126 +struct _stack {
  14.127 +	struct _stack_el *tail;
  14.128 +	struct _stack_el *cur_ptr;
  14.129 +};
  14.130 +
  14.131 +static struct _stack_el *
  14.132 +OS__add_stack_el(struct _stack *st) {
  14.133 +	struct _stack_el *nel;
  14.134 +
  14.135 +	/*
  14.136 +	 * Reuse the old stack frame or allocate a new one.
  14.137 +	 */
  14.138 +	if(st->cur_ptr && st->cur_ptr->next) {
  14.139 +		nel = st->cur_ptr->next;
  14.140 +		nel->bits_chopped = 0;
  14.141 +		nel->got = 0;
  14.142 +		/* Retain the nel->cont_level, it's correct. */
  14.143 +	} else {
  14.144 +		nel = (struct _stack_el *)CALLOC(1, sizeof(struct _stack_el));
  14.145 +		if(nel == NULL)
  14.146 +			return NULL;
  14.147 +	
  14.148 +		if(st->tail) {
  14.149 +			/* Increase a subcontainment depth */
  14.150 +			nel->cont_level = st->tail->cont_level + 1;
  14.151 +			st->tail->next = nel;
  14.152 +		}
  14.153 +		nel->prev = st->tail;
  14.154 +		st->tail = nel;
  14.155 +	}
  14.156 +
  14.157 +	st->cur_ptr = nel;
  14.158 +
  14.159 +	return nel;
  14.160 +}
  14.161 +
  14.162 +static struct _stack *
  14.163 +_new_stack() {
  14.164 +	return (struct _stack *)CALLOC(1, sizeof(struct _stack));
  14.165 +}
  14.166 +
  14.167 +/*
  14.168 + * Decode OCTET STRING type.
  14.169 + */
  14.170 +asn_dec_rval_t
  14.171 +OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
  14.172 +	asn_TYPE_descriptor_t *td,
  14.173 +	void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
  14.174 +	asn_OCTET_STRING_specifics_t *specs = td->specifics
  14.175 +				? (asn_OCTET_STRING_specifics_t *)td->specifics
  14.176 +				: &asn_DEF_OCTET_STRING_specs;
  14.177 +	BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
  14.178 +	asn_dec_rval_t rval;
  14.179 +	asn_struct_ctx_t *ctx;
  14.180 +	ssize_t consumed_myself = 0;
  14.181 +	struct _stack *stck;		/* Expectations stack structure */
  14.182 +	struct _stack_el *sel = 0;	/* Stack element */
  14.183 +	int tlv_constr;
  14.184 +	enum asn_OS_Subvariant type_variant = specs->subvariant;
  14.185 +
  14.186 +	ASN_DEBUG("Decoding %s as %s (frame %ld)",
  14.187 +		td->name,
  14.188 +		(type_variant == ASN_OSUBV_STR) ?
  14.189 +			"OCTET STRING" : "OS-SpecialCase",
  14.190 +		(long)size);
  14.191 +
  14.192 +	/*
  14.193 +	 * Create the string if does not exist.
  14.194 +	 */
  14.195 +	if(st == NULL) {
  14.196 +		st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
  14.197 +		if(st == NULL) RETURN(RC_FAIL);
  14.198 +	}
  14.199 +
  14.200 +	/* Restore parsing context */
  14.201 +	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
  14.202 +
  14.203 +	switch(ctx->phase) {
  14.204 +	case 0:
  14.205 +		/*
  14.206 +		 * Check tags.
  14.207 +		 */
  14.208 +		rval = ber_check_tags(opt_codec_ctx, td, ctx,
  14.209 +			buf_ptr, size, tag_mode, -1,
  14.210 +			&ctx->left, &tlv_constr);
  14.211 +		if(rval.code != RC_OK)
  14.212 +			return rval;
  14.213 +
  14.214 +		if(tlv_constr) {
  14.215 +			/*
  14.216 +			 * Complex operation, requires stack of expectations.
  14.217 +			 */
  14.218 +			ctx->ptr = _new_stack();
  14.219 +			if(ctx->ptr) {
  14.220 +				stck = (struct _stack *)ctx->ptr;
  14.221 +			} else {
  14.222 +				RETURN(RC_FAIL);
  14.223 +			}
  14.224 +		} else {
  14.225 +			/*
  14.226 +			 * Jump into stackless primitive decoding.
  14.227 +			 */
  14.228 +			_CH_PHASE(ctx, 3);
  14.229 +			if(type_variant == ASN_OSUBV_ANY && tag_mode != 1)
  14.230 +				APPEND(buf_ptr, rval.consumed);
  14.231 +			ADVANCE(rval.consumed);
  14.232 +			goto phase3;
  14.233 +		}
  14.234 +
  14.235 +		NEXT_PHASE(ctx);
  14.236 +		/* Fall through */
  14.237 +	case 1:
  14.238 +	phase1:
  14.239 +		/*
  14.240 +		 * Fill the stack with expectations.
  14.241 +		 */
  14.242 +		stck = (struct _stack *)ctx->ptr;
  14.243 +		sel = stck->cur_ptr;
  14.244 +	  do {
  14.245 +		ber_tlv_tag_t tlv_tag;
  14.246 +		ber_tlv_len_t tlv_len;
  14.247 +		ber_tlv_tag_t expected_tag;
  14.248 +		ssize_t tl, ll, tlvl;
  14.249 +				/* This one works even if (sel->left == -1) */
  14.250 +		ssize_t Left = ((!sel||(size_t)sel->left >= size)
  14.251 +					?(ssize_t)size:sel->left);
  14.252 +
  14.253 +
  14.254 +		ASN_DEBUG("%p, s->l=%ld, s->wn=%ld, s->g=%ld\n", sel,
  14.255 +			(long)(sel?sel->left:0),
  14.256 +			(long)(sel?sel->want_nulls:0),
  14.257 +			(long)(sel?sel->got:0)
  14.258 +		);
  14.259 +		if(sel && sel->left <= 0 && sel->want_nulls == 0) {
  14.260 +			if(sel->prev) {
  14.261 +				struct _stack_el *prev = sel->prev;
  14.262 +				if(prev->left != -1) {
  14.263 +					if(prev->left < sel->got)
  14.264 +						RETURN(RC_FAIL);
  14.265 +					prev->left -= sel->got;
  14.266 +				}
  14.267 +				prev->got += sel->got;
  14.268 +				sel = stck->cur_ptr = prev;
  14.269 +				if(!sel) break;
  14.270 +				tlv_constr = 1;
  14.271 +				continue;
  14.272 +			} else {
  14.273 +				sel = stck->cur_ptr = 0;
  14.274 +				break;	/* Nothing to wait */
  14.275 +			}
  14.276 +		}
  14.277 +
  14.278 +		tl = ber_fetch_tag(buf_ptr, Left, &tlv_tag);
  14.279 +		ASN_DEBUG("fetch tag(size=%ld,L=%ld), %sstack, left=%ld, wn=%ld, tl=%ld",
  14.280 +			(long)size, (long)Left, sel?"":"!",
  14.281 +			(long)(sel?sel->left:0),
  14.282 +			(long)(sel?sel->want_nulls:0),
  14.283 +			(long)tl);
  14.284 +		switch(tl) {
  14.285 +		case -1: RETURN(RC_FAIL);
  14.286 +		case 0: RETURN(RC_WMORE);
  14.287 +		}
  14.288 +
  14.289 +		tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr);
  14.290 +
  14.291 +		ll = ber_fetch_length(tlv_constr,
  14.292 +				(const char *)buf_ptr + tl,Left - tl,&tlv_len);
  14.293 +		ASN_DEBUG("Got tag=%s, tc=%d, left=%ld, tl=%ld, len=%ld, ll=%ld",
  14.294 +			ber_tlv_tag_string(tlv_tag), tlv_constr,
  14.295 +				(long)Left, (long)tl, (long)tlv_len, (long)ll);
  14.296 +		switch(ll) {
  14.297 +		case -1: RETURN(RC_FAIL);
  14.298 +		case 0: RETURN(RC_WMORE);
  14.299 +		}
  14.300 +
  14.301 +		if(sel && sel->want_nulls
  14.302 +			&& ((const uint8_t *)buf_ptr)[0] == 0
  14.303 +			&& ((const uint8_t *)buf_ptr)[1] == 0)
  14.304 +		{
  14.305 +
  14.306 +			ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
  14.307 +
  14.308 +			if(type_variant == ASN_OSUBV_ANY
  14.309 +			&& (tag_mode != 1 || sel->cont_level))
  14.310 +				APPEND("\0\0", 2);
  14.311 +
  14.312 +			ADVANCE(2);
  14.313 +			sel->got += 2;
  14.314 +			if(sel->left != -1) {
  14.315 +				sel->left -= 2;	/* assert(sel->left >= 2) */
  14.316 +			}
  14.317 +
  14.318 +			sel->want_nulls--;
  14.319 +			if(sel->want_nulls == 0) {
  14.320 +				/* Move to the next expectation */
  14.321 +				sel->left = 0;
  14.322 +				tlv_constr = 1;
  14.323 +			}
  14.324 +
  14.325 +			continue;
  14.326 +		}
  14.327 +
  14.328 +		/*
  14.329 +		 * Set up expected tags,
  14.330 +		 * depending on ASN.1 type being decoded.
  14.331 +		 */
  14.332 +		switch(type_variant) {
  14.333 +		case ASN_OSUBV_BIT:
  14.334 +			/* X.690: 8.6.4.1, NOTE 2 */
  14.335 +			/* Fall through */
  14.336 +		case ASN_OSUBV_STR:
  14.337 +		default:
  14.338 +			if(sel) {
  14.339 +				int level = sel->cont_level;
  14.340 +				if(level < td->all_tags_count) {
  14.341 +					expected_tag = td->all_tags[level];
  14.342 +					break;
  14.343 +				} else if(td->all_tags_count) {
  14.344 +					expected_tag = td->all_tags
  14.345 +						[td->all_tags_count - 1];
  14.346 +					break;
  14.347 +				}
  14.348 +				/* else, Fall through */
  14.349 +			}
  14.350 +			/* Fall through */
  14.351 +		case ASN_OSUBV_ANY:
  14.352 +			expected_tag = tlv_tag;
  14.353 +			break;
  14.354 +		}
  14.355 +
  14.356 +
  14.357 +		if(tlv_tag != expected_tag) {
  14.358 +			char buf[2][32];
  14.359 +			ber_tlv_tag_snprint(tlv_tag,
  14.360 +				buf[0], sizeof(buf[0]));
  14.361 +			ber_tlv_tag_snprint(td->tags[td->tags_count-1],
  14.362 +				buf[1], sizeof(buf[1]));
  14.363 +			ASN_DEBUG("Tag does not match expectation: %s != %s",
  14.364 +				buf[0], buf[1]);
  14.365 +			RETURN(RC_FAIL);
  14.366 +		}
  14.367 +
  14.368 +		tlvl = tl + ll;	/* Combined length of T and L encoding */
  14.369 +		if((tlv_len + tlvl) < 0) {
  14.370 +			/* tlv_len value is too big */
  14.371 +			ASN_DEBUG("TLV encoding + length (%ld) is too big",
  14.372 +				(long)tlv_len);
  14.373 +			RETURN(RC_FAIL);
  14.374 +		}
  14.375 +
  14.376 +		/*
  14.377 +		 * Append a new expectation.
  14.378 +		 */
  14.379 +		sel = OS__add_stack_el(stck);
  14.380 +		if(!sel) RETURN(RC_FAIL);
  14.381 +
  14.382 +		sel->tag = tlv_tag;
  14.383 +
  14.384 +		sel->want_nulls = (tlv_len==-1);
  14.385 +		if(sel->prev && sel->prev->left != -1) {
  14.386 +			/* Check that the parent frame is big enough */
  14.387 +			if(sel->prev->left < tlvl + (tlv_len==-1?0:tlv_len))
  14.388 +				RETURN(RC_FAIL);
  14.389 +			if(tlv_len == -1)
  14.390 +				sel->left = sel->prev->left - tlvl;
  14.391 +			else
  14.392 +				sel->left = tlv_len;
  14.393 +		} else {
  14.394 +			sel->left = tlv_len;
  14.395 +		}
  14.396 +		if(type_variant == ASN_OSUBV_ANY
  14.397 +		&& (tag_mode != 1 || sel->cont_level))
  14.398 +			APPEND(buf_ptr, tlvl);
  14.399 +		sel->got += tlvl;
  14.400 +		ADVANCE(tlvl);
  14.401 +
  14.402 +		ASN_DEBUG("+EXPECT2 got=%ld left=%ld, wn=%d, clvl=%d",
  14.403 +			(long)sel->got, (long)sel->left,
  14.404 +			sel->want_nulls, sel->cont_level);
  14.405 +
  14.406 +	  } while(tlv_constr);
  14.407 +		if(sel == NULL) {
  14.408 +			/* Finished operation, "phase out" */
  14.409 +			ASN_DEBUG("Phase out");
  14.410 +			_CH_PHASE(ctx, +3);
  14.411 +			break;
  14.412 +		}
  14.413 +
  14.414 +		NEXT_PHASE(ctx);
  14.415 +		/* Fall through */
  14.416 +	case 2:
  14.417 +		stck = (struct _stack *)ctx->ptr;
  14.418 +		sel = stck->cur_ptr;
  14.419 +		ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld, alrg=%ld, wn=%d",
  14.420 +			(long)sel->left, (long)size, (long)sel->got,
  14.421 +				sel->want_nulls);
  14.422 +	    {
  14.423 +		ber_tlv_len_t len;
  14.424 +
  14.425 +		assert(sel->left >= 0);
  14.426 +
  14.427 +		len = ((ber_tlv_len_t)size < sel->left)
  14.428 +				? (ber_tlv_len_t)size : sel->left;
  14.429 +		if(len > 0) {
  14.430 +			if(type_variant == ASN_OSUBV_BIT
  14.431 +			&& sel->bits_chopped == 0) {
  14.432 +				/* Put the unused-bits-octet away */
  14.433 +				st->bits_unused = *(const uint8_t *)buf_ptr;
  14.434 +				APPEND(((const char *)buf_ptr+1), (len - 1));
  14.435 +				sel->bits_chopped = 1;
  14.436 +			} else {
  14.437 +				APPEND(buf_ptr, len);
  14.438 +			}
  14.439 +			ADVANCE(len);
  14.440 +			sel->left -= len;
  14.441 +			sel->got += len;
  14.442 +		}
  14.443 +
  14.444 +		if(sel->left) {
  14.445 +			ASN_DEBUG("OS left %ld, size = %ld, wn=%d\n",
  14.446 +				(long)sel->left, (long)size, sel->want_nulls);
  14.447 +			RETURN(RC_WMORE);
  14.448 +		}
  14.449 +
  14.450 +		PREV_PHASE(ctx);
  14.451 +		goto phase1;
  14.452 +	    }
  14.453 +		break;
  14.454 +	case 3:
  14.455 +	phase3:
  14.456 +		/*
  14.457 +		 * Primitive form, no stack required.
  14.458 +		 */
  14.459 +		assert(ctx->left >= 0);
  14.460 +
  14.461 +		if(size < (size_t)ctx->left) {
  14.462 +			if(!size) RETURN(RC_WMORE);
  14.463 +			if(type_variant == ASN_OSUBV_BIT && !ctx->context) {
  14.464 +				st->bits_unused = *(const uint8_t *)buf_ptr;
  14.465 +				ctx->left--;
  14.466 +				ADVANCE(1);
  14.467 +			}
  14.468 +			APPEND(buf_ptr, size);
  14.469 +			assert(ctx->context > 0);
  14.470 +			ctx->left -= size;
  14.471 +			ADVANCE(size);
  14.472 +			RETURN(RC_WMORE);
  14.473 +		} else {
  14.474 +			if(type_variant == ASN_OSUBV_BIT
  14.475 +			&& !ctx->context && ctx->left) {
  14.476 +				st->bits_unused = *(const uint8_t *)buf_ptr;
  14.477 +				ctx->left--;
  14.478 +				ADVANCE(1);
  14.479 +			}
  14.480 +			APPEND(buf_ptr, ctx->left);
  14.481 +			ADVANCE(ctx->left);
  14.482 +			ctx->left = 0;
  14.483 +
  14.484 +			NEXT_PHASE(ctx);
  14.485 +		}
  14.486 +		break;
  14.487 +	}
  14.488 +
  14.489 +	if(sel) {
  14.490 +		ASN_DEBUG("3sel p=%p, wn=%d, l=%ld, g=%ld, size=%ld",
  14.491 +			sel->prev, sel->want_nulls,
  14.492 +			(long)sel->left, (long)sel->got, (long)size);
  14.493 +		if(sel->prev || sel->want_nulls > 1 || sel->left > 0) {
  14.494 +			RETURN(RC_WMORE);
  14.495 +		}
  14.496 +	}
  14.497 +
  14.498 +	/*
  14.499 +	 * BIT STRING-specific processing.
  14.500 +	 */
  14.501 +	if(type_variant == ASN_OSUBV_BIT && st->size) {
  14.502 +		/* Finalize BIT STRING: zero out unused bits. */
  14.503 +		st->buf[st->size-1] &= 0xff << st->bits_unused;
  14.504 +	}
  14.505 +
  14.506 +	ASN_DEBUG("Took %ld bytes to encode %s: [%s]:%ld",
  14.507 +		(long)consumed_myself, td->name,
  14.508 +		(type_variant == ASN_OSUBV_STR) ? (char *)st->buf : "<data>",
  14.509 +		(long)st->size);
  14.510 +
  14.511 +
  14.512 +	RETURN(RC_OK);
  14.513 +}
  14.514 +
  14.515 +/*
  14.516 + * Encode OCTET STRING type using DER.
  14.517 + */
  14.518 +asn_enc_rval_t
  14.519 +OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
  14.520 +	int tag_mode, ber_tlv_tag_t tag,
  14.521 +	asn_app_consume_bytes_f *cb, void *app_key) {
  14.522 +	asn_enc_rval_t er;
  14.523 +	asn_OCTET_STRING_specifics_t *specs = td->specifics
  14.524 +				? (asn_OCTET_STRING_specifics_t *)td->specifics
  14.525 +				: &asn_DEF_OCTET_STRING_specs;
  14.526 +	BIT_STRING_t *st = (BIT_STRING_t *)sptr;
  14.527 +	enum asn_OS_Subvariant type_variant = specs->subvariant;
  14.528 +	int fix_last_byte = 0;
  14.529 +
  14.530 +	ASN_DEBUG("%s %s as OCTET STRING",
  14.531 +		cb?"Estimating":"Encoding", td->name);
  14.532 +
  14.533 +	/*
  14.534 +	 * Write tags.
  14.535 +	 */
  14.536 +	if(type_variant != ASN_OSUBV_ANY || tag_mode == 1) {
  14.537 +		er.encoded = der_write_tags(td,
  14.538 +				(type_variant == ASN_OSUBV_BIT) + st->size,
  14.539 +			tag_mode, type_variant == ASN_OSUBV_ANY, tag,
  14.540 +			cb, app_key);
  14.541 +		if(er.encoded == -1) {
  14.542 +			er.failed_type = td;
  14.543 +			er.structure_ptr = sptr;
  14.544 +			return er;
  14.545 +		}
  14.546 +	} else {
  14.547 +		/* Disallow: [<tag>] IMPLICIT ANY */
  14.548 +		assert(type_variant != ASN_OSUBV_ANY || tag_mode != -1);
  14.549 +		er.encoded = 0;
  14.550 +	}
  14.551 +
  14.552 +	if(!cb) {
  14.553 +		er.encoded += (type_variant == ASN_OSUBV_BIT) + st->size;
  14.554 +		_ASN_ENCODED_OK(er);
  14.555 +	}
  14.556 +
  14.557 +	/*
  14.558 +	 * Prepare to deal with the last octet of BIT STRING.
  14.559 +	 */
  14.560 +	if(type_variant == ASN_OSUBV_BIT) {
  14.561 +		uint8_t b = st->bits_unused & 0x07;
  14.562 +		if(b && st->size) fix_last_byte = 1;
  14.563 +		_ASN_CALLBACK(&b, 1);
  14.564 +		er.encoded++;
  14.565 +	}
  14.566 +
  14.567 +	/* Invoke callback for the main part of the buffer */
  14.568 +	_ASN_CALLBACK(st->buf, st->size - fix_last_byte);
  14.569 +
  14.570 +	/* The last octet should be stripped off the unused bits */
  14.571 +	if(fix_last_byte) {
  14.572 +		uint8_t b = st->buf[st->size-1] & (0xff << st->bits_unused);
  14.573 +		_ASN_CALLBACK(&b, 1);
  14.574 +	}
  14.575 +
  14.576 +	er.encoded += st->size;
  14.577 +	_ASN_ENCODED_OK(er);
  14.578 +cb_failed:
  14.579 +	_ASN_ENCODE_FAILED;
  14.580 +}
  14.581 +
  14.582 +asn_enc_rval_t
  14.583 +OCTET_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
  14.584 +	int ilevel, enum xer_encoder_flags_e flags,
  14.585 +		asn_app_consume_bytes_f *cb, void *app_key) {
  14.586 +	static const char *h2c = "0123456789ABCDEF";
  14.587 +	const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
  14.588 +	asn_enc_rval_t er;
  14.589 +	char scratch[16 * 3 + 4];
  14.590 +	char *p = scratch;
  14.591 +	uint8_t *buf;
  14.592 +	uint8_t *end;
  14.593 +	size_t i;
  14.594 +
  14.595 +	if(!st || (!st->buf && st->size))
  14.596 +		_ASN_ENCODE_FAILED;
  14.597 +
  14.598 +	er.encoded = 0;
  14.599 +
  14.600 +	/*
  14.601 +	 * Dump the contents of the buffer in hexadecimal.
  14.602 +	 */
  14.603 +	buf = st->buf;
  14.604 +	end = buf + st->size;
  14.605 +	if(flags & XER_F_CANONICAL) {
  14.606 +		char *scend = scratch + (sizeof(scratch) - 2);
  14.607 +		for(; buf < end; buf++) {
  14.608 +			if(p >= scend) {
  14.609 +				_ASN_CALLBACK(scratch, p - scratch);
  14.610 +				er.encoded += p - scratch;
  14.611 +				p = scratch;
  14.612 +			}
  14.613 +			*p++ = h2c[(*buf >> 4) & 0x0F];
  14.614 +			*p++ = h2c[*buf & 0x0F];
  14.615 +		}
  14.616 +
  14.617 +		_ASN_CALLBACK(scratch, p-scratch);	/* Dump the rest */
  14.618 +		er.encoded += p - scratch;
  14.619 +	} else {
  14.620 +		for(i = 0; buf < end; buf++, i++) {
  14.621 +			if(!(i % 16) && (i || st->size > 16)) {
  14.622 +				_ASN_CALLBACK(scratch, p-scratch);
  14.623 +				er.encoded += (p-scratch);
  14.624 +				p = scratch;
  14.625 +				_i_ASN_TEXT_INDENT(1, ilevel);
  14.626 +			}
  14.627 +			*p++ = h2c[(*buf >> 4) & 0x0F];
  14.628 +			*p++ = h2c[*buf & 0x0F];
  14.629 +			*p++ = 0x20;
  14.630 +		}
  14.631 +		if(p - scratch) {
  14.632 +			p--;	/* Remove the tail space */
  14.633 +			_ASN_CALLBACK(scratch, p-scratch); /* Dump the rest */
  14.634 +			er.encoded += p - scratch;
  14.635 +			if(st->size > 16)
  14.636 +				_i_ASN_TEXT_INDENT(1, ilevel-1);
  14.637 +		}
  14.638 +	}
  14.639 +
  14.640 +	_ASN_ENCODED_OK(er);
  14.641 +cb_failed:
  14.642 +	_ASN_ENCODE_FAILED;
  14.643 +}
  14.644 +
  14.645 +static struct OCTET_STRING__xer_escape_table_s {
  14.646 +	char *string;
  14.647 +	int size;
  14.648 +} OCTET_STRING__xer_escape_table[] = {
  14.649 +#define	OSXET(s)	{ s, sizeof(s) - 1 }
  14.650 +	OSXET("\074\156\165\154\057\076"),	/* <nul/> */
  14.651 +	OSXET("\074\163\157\150\057\076"),	/* <soh/> */
  14.652 +	OSXET("\074\163\164\170\057\076"),	/* <stx/> */
  14.653 +	OSXET("\074\145\164\170\057\076"),	/* <etx/> */
  14.654 +	OSXET("\074\145\157\164\057\076"),	/* <eot/> */
  14.655 +	OSXET("\074\145\156\161\057\076"),	/* <enq/> */
  14.656 +	OSXET("\074\141\143\153\057\076"),	/* <ack/> */
  14.657 +	OSXET("\074\142\145\154\057\076"),	/* <bel/> */
  14.658 +	OSXET("\074\142\163\057\076"),		/* <bs/> */
  14.659 +	OSXET("\011"),				/* \t */
  14.660 +	OSXET("\012"),				/* \n */
  14.661 +	OSXET("\074\166\164\057\076"),		/* <vt/> */
  14.662 +	OSXET("\074\146\146\057\076"),		/* <ff/> */
  14.663 +	OSXET("\015"),				/* \r */
  14.664 +	OSXET("\074\163\157\057\076"),		/* <so/> */
  14.665 +	OSXET("\074\163\151\057\076"),		/* <si/> */
  14.666 +	OSXET("\074\144\154\145\057\076"),	/* <dle/> */
  14.667 +	OSXET("\074\144\143\061\057\076"),	/* <de1/> */
  14.668 +	OSXET("\074\144\143\062\057\076"),	/* <de2/> */
  14.669 +	OSXET("\074\144\143\063\057\076"),	/* <de3/> */
  14.670 +	OSXET("\074\144\143\064\057\076"),	/* <de4/> */
  14.671 +	OSXET("\074\156\141\153\057\076"),	/* <nak/> */
  14.672 +	OSXET("\074\163\171\156\057\076"),	/* <syn/> */
  14.673 +	OSXET("\074\145\164\142\057\076"),	/* <etb/> */
  14.674 +	OSXET("\074\143\141\156\057\076"),	/* <can/> */
  14.675 +	OSXET("\074\145\155\057\076"),		/* <em/> */
  14.676 +	OSXET("\074\163\165\142\057\076"),	/* <sub/> */
  14.677 +	OSXET("\074\145\163\143\057\076"),	/* <esc/> */
  14.678 +	OSXET("\074\151\163\064\057\076"),	/* <is4/> */
  14.679 +	OSXET("\074\151\163\063\057\076"),	/* <is3/> */
  14.680 +	OSXET("\074\151\163\062\057\076"),	/* <is2/> */
  14.681 +	OSXET("\074\151\163\061\057\076"),	/* <is1/> */
  14.682 +	{ 0, 0 },	/* " " */
  14.683 +	{ 0, 0 },	/* ! */
  14.684 +	{ 0, 0 },	/* \" */
  14.685 +	{ 0, 0 },	/* # */
  14.686 +	{ 0, 0 },	/* $ */
  14.687 +	{ 0, 0 },	/* % */
  14.688 +	OSXET("\046\141\155\160\073"),	/* &amp; */
  14.689 +	{ 0, 0 },	/* ' */
  14.690 +	{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* ()*+,-./ */
  14.691 +	{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* 01234567 */
  14.692 +	{0,0},{0,0},{0,0},{0,0},			 /* 89:; */
  14.693 +	OSXET("\046\154\164\073"),	/* &lt; */
  14.694 +	{ 0, 0 },	/* = */
  14.695 +	OSXET("\046\147\164\073"),	/* &gt; */
  14.696 +};
  14.697 +
  14.698 +static int
  14.699 +OS__check_escaped_control_char(const void *buf, int size) {
  14.700 +	size_t i;
  14.701 +	/*
  14.702 +	 * Inefficient algorithm which translates the escape sequences
  14.703 +	 * defined above into characters. Returns -1 if not found.
  14.704 +	 * TODO: replace by a faster algorithm (bsearch(), hash or
  14.705 +	 * nested table lookups).
  14.706 +	 */
  14.707 +	for(i = 0; i < 32 /* Don't spend time on the bottom half */; i++) {
  14.708 +		struct OCTET_STRING__xer_escape_table_s *el;
  14.709 +		el = &OCTET_STRING__xer_escape_table[i];
  14.710 +		if(el->size == size && memcmp(buf, el->string, size) == 0)
  14.711 +			return i;
  14.712 +	}
  14.713 +	return -1;
  14.714 +}
  14.715 +
  14.716 +static int
  14.717 +OCTET_STRING__handle_control_chars(void *struct_ptr, const void *chunk_buf, size_t chunk_size) {
  14.718 +	/*
  14.719 +	 * This might be one of the escape sequences
  14.720 +	 * for control characters. Check it out.
  14.721 +	 * #11.15.5
  14.722 +	 */
  14.723 +	int control_char = OS__check_escaped_control_char(chunk_buf,chunk_size);
  14.724 +	if(control_char >= 0) {
  14.725 +		OCTET_STRING_t *st = (OCTET_STRING_t *)struct_ptr;
  14.726 +		void *p = REALLOC(st->buf, st->size + 2);
  14.727 +		if(p) {
  14.728 +			st->buf = (uint8_t *)p;
  14.729 +			st->buf[st->size++] = control_char;
  14.730 +			st->buf[st->size] = '\0';	/* nul-termination */
  14.731 +			return 0;
  14.732 +		}
  14.733 +	}
  14.734 +	
  14.735 +	return -1;	/* No, it's not */
  14.736 +}
  14.737 +
  14.738 +asn_enc_rval_t
  14.739 +OCTET_STRING_encode_xer_utf8(asn_TYPE_descriptor_t *td, void *sptr,
  14.740 +	int ilevel, enum xer_encoder_flags_e flags,
  14.741 +		asn_app_consume_bytes_f *cb, void *app_key) {
  14.742 +	const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
  14.743 +	asn_enc_rval_t er;
  14.744 +	uint8_t *buf, *end;
  14.745 +	uint8_t *ss;	/* Sequence start */
  14.746 +	ssize_t encoded_len = 0;
  14.747 +
  14.748 +	(void)ilevel;	/* Unused argument */
  14.749 +	(void)flags;	/* Unused argument */
  14.750 +
  14.751 +	if(!st || (!st->buf && st->size))
  14.752 +		_ASN_ENCODE_FAILED;
  14.753 +
  14.754 +	buf = st->buf;
  14.755 +	end = buf + st->size;
  14.756 +	for(ss = buf; buf < end; buf++) {
  14.757 +		unsigned int ch = *buf;
  14.758 +		int s_len;	/* Special encoding sequence length */
  14.759 +
  14.760 +		/*
  14.761 +		 * Escape certain characters: X.680/11.15
  14.762 +		 */
  14.763 +		if(ch < sizeof(OCTET_STRING__xer_escape_table)
  14.764 +			/sizeof(OCTET_STRING__xer_escape_table[0])
  14.765 +		&& (s_len = OCTET_STRING__xer_escape_table[ch].size)) {
  14.766 +			if(((buf - ss) && cb(ss, buf - ss, app_key) < 0)
  14.767 +			|| cb(OCTET_STRING__xer_escape_table[ch].string, s_len,
  14.768 +					app_key) < 0)
  14.769 +				_ASN_ENCODE_FAILED;
  14.770 +			encoded_len += (buf - ss) + s_len;
  14.771 +			ss = buf + 1;
  14.772 +		}
  14.773 +	}
  14.774 +
  14.775 +	encoded_len += (buf - ss);
  14.776 +	if((buf - ss) && cb(ss, buf - ss, app_key) < 0)
  14.777 +		_ASN_ENCODE_FAILED;
  14.778 +
  14.779 +	er.encoded = encoded_len;
  14.780 +	_ASN_ENCODED_OK(er);
  14.781 +}
  14.782 +
  14.783 +/*
  14.784 + * Convert from hexadecimal format (cstring): "AB CD EF"
  14.785 + */
  14.786 +static ssize_t OCTET_STRING__convert_hexadecimal(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
  14.787 +	OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
  14.788 +	const char *chunk_stop = (const char *)chunk_buf;
  14.789 +	const char *p = chunk_stop;
  14.790 +	const char *pend = p + chunk_size;
  14.791 +	unsigned int clv = 0;
  14.792 +	int half = 0;	/* Half bit */
  14.793 +	uint8_t *buf;
  14.794 +
  14.795 +	/* Reallocate buffer according to high cap estimation */
  14.796 +	ssize_t _ns = st->size + (chunk_size + 1) / 2;
  14.797 +	void *nptr = REALLOC(st->buf, _ns + 1);
  14.798 +	if(!nptr) return -1;
  14.799 +	st->buf = (uint8_t *)nptr;
  14.800 +	buf = st->buf + st->size;
  14.801 +
  14.802 +	/*
  14.803 +	 * If something like " a b c " appears here, the " a b":3 will be
  14.804 +	 * converted, and the rest skipped. That is, unless buf_size is greater
  14.805 +	 * than chunk_size, then it'll be equivalent to "ABC0".
  14.806 +	 */
  14.807 +	for(; p < pend; p++) {
  14.808 +		int ch = *(const unsigned char *)p;
  14.809 +		switch(ch) {
  14.810 +		case 0x09: case 0x0a: case 0x0c: case 0x0d:
  14.811 +		case 0x20:
  14.812 +			/* Ignore whitespace */
  14.813 +			continue;
  14.814 +		case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
  14.815 +		case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
  14.816 +			clv = (clv << 4) + (ch - 0x30);
  14.817 +			break;
  14.818 +		case 0x41: case 0x42: case 0x43:	/* ABC */
  14.819 +		case 0x44: case 0x45: case 0x46:	/* DEF */
  14.820 +			clv = (clv << 4) + (ch - 0x41 + 10);
  14.821 +			break;
  14.822 +		case 0x61: case 0x62: case 0x63:	/* abc */
  14.823 +		case 0x64: case 0x65: case 0x66:	/* def */
  14.824 +			clv = (clv << 4) + (ch - 0x61 + 10);
  14.825 +			break;
  14.826 +		default:
  14.827 +			*buf = 0;	/* JIC */
  14.828 +			return -1;
  14.829 +		}
  14.830 +		if(half++) {
  14.831 +			half = 0;
  14.832 +			*buf++ = clv;
  14.833 +			chunk_stop = p + 1;
  14.834 +		}
  14.835 +	}
  14.836 +
  14.837 +	/*
  14.838 +	 * Check partial decoding.
  14.839 +	 */
  14.840 +	if(half) {
  14.841 +		if(have_more) {
  14.842 +			/*
  14.843 +			 * Partial specification is fine,
  14.844 +			 * because no more more PXER_TEXT data is available.
  14.845 +			 */
  14.846 +			*buf++ = clv << 4;
  14.847 +			chunk_stop = p;
  14.848 +		}
  14.849 +	} else {
  14.850 +		chunk_stop = p;
  14.851 +	}
  14.852 +
  14.853 +	st->size = buf - st->buf;	/* Adjust the buffer size */
  14.854 +	assert(st->size <= _ns);
  14.855 +	st->buf[st->size] = 0;		/* Courtesy termination */
  14.856 +
  14.857 +	return (chunk_stop - (const char *)chunk_buf);	/* Converted size */
  14.858 +}
  14.859 +
  14.860 +/*
  14.861 + * Convert from binary format: "00101011101"
  14.862 + */
  14.863 +static ssize_t OCTET_STRING__convert_binary(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
  14.864 +	BIT_STRING_t *st = (BIT_STRING_t *)sptr;
  14.865 +	const char *p = (const char *)chunk_buf;
  14.866 +	const char *pend = p + chunk_size;
  14.867 +	int bits_unused = st->bits_unused & 0x7;
  14.868 +	uint8_t *buf;
  14.869 +
  14.870 +	/* Reallocate buffer according to high cap estimation */
  14.871 +	ssize_t _ns = st->size + (chunk_size + 7) / 8;
  14.872 +	void *nptr = REALLOC(st->buf, _ns + 1);
  14.873 +	if(!nptr) return -1;
  14.874 +	st->buf = (uint8_t *)nptr;
  14.875 +	buf = st->buf + st->size;
  14.876 +
  14.877 +	(void)have_more;
  14.878 +
  14.879 +	if(bits_unused == 0)
  14.880 +		bits_unused = 8;
  14.881 +	else if(st->size)
  14.882 +		buf--;
  14.883 +
  14.884 +	/*
  14.885 +	 * Convert series of 0 and 1 into the octet string.
  14.886 +	 */
  14.887 +	for(; p < pend; p++) {
  14.888 +		int ch = *(const unsigned char *)p;
  14.889 +		switch(ch) {
  14.890 +		case 0x09: case 0x0a: case 0x0c: case 0x0d:
  14.891 +		case 0x20:
  14.892 +			/* Ignore whitespace */
  14.893 +			break;
  14.894 +		case 0x30:
  14.895 +		case 0x31:
  14.896 +			if(bits_unused-- <= 0) {
  14.897 +				*++buf = 0;	/* Clean the cell */
  14.898 +				bits_unused = 7;
  14.899 +			}
  14.900 +			*buf |= (ch&1) << bits_unused;
  14.901 +			break;
  14.902 +		default:
  14.903 +			st->bits_unused = bits_unused;
  14.904 +			return -1;
  14.905 +		}
  14.906 +	}
  14.907 +
  14.908 +	if(bits_unused == 8) {
  14.909 +		st->size = buf - st->buf;
  14.910 +		st->bits_unused = 0;
  14.911 +	} else {
  14.912 +		st->size = buf - st->buf + 1;
  14.913 +		st->bits_unused = bits_unused;
  14.914 +	}
  14.915 +
  14.916 +	assert(st->size <= _ns);
  14.917 +	st->buf[st->size] = 0;		/* Courtesy termination */
  14.918 +
  14.919 +	return chunk_size;	/* Converted in full */
  14.920 +}
  14.921 +
  14.922 +/*
  14.923 + * Something like strtod(), but with stricter rules.
  14.924 + */
  14.925 +static int
  14.926 +OS__strtoent(int base, const char *buf, const char *end, int32_t *ret_value) {
  14.927 +	int32_t val = 0;
  14.928 +	const char *p;
  14.929 +
  14.930 +	for(p = buf; p < end; p++) {
  14.931 +		int ch = *p;
  14.932 +
  14.933 +		/* Strange huge value */
  14.934 +		if((val * base + base) < 0)
  14.935 +			return -1;
  14.936 +
  14.937 +		switch(ch) {
  14.938 +		case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
  14.939 +		case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
  14.940 +			val = val * base + (ch - 0x30);
  14.941 +			break;
  14.942 +		case 0x41: case 0x42: case 0x43:	/* ABC */
  14.943 +		case 0x44: case 0x45: case 0x46:	/* DEF */
  14.944 +			val = val * base + (ch - 0x41 + 10);
  14.945 +			break;
  14.946 +		case 0x61: case 0x62: case 0x63:	/* abc */
  14.947 +		case 0x64: case 0x65: case 0x66:	/* def */
  14.948 +			val = val * base + (ch - 0x61 + 10);
  14.949 +			break;
  14.950 +		case 0x3b:	/* ';' */
  14.951 +			*ret_value = val;
  14.952 +			return (p - buf) + 1;
  14.953 +		default:
  14.954 +			return -1;	/* Character set error */
  14.955 +		}
  14.956 +	}
  14.957 +
  14.958 +	*ret_value = -1;
  14.959 +	return (p - buf);
  14.960 +}
  14.961 +
  14.962 +/*
  14.963 + * Convert from the plain UTF-8 format, expanding entity references: "2 &lt; 3"
  14.964 + */
  14.965 +static ssize_t OCTET_STRING__convert_entrefs(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
  14.966 +	OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
  14.967 +	const char *p = (const char *)chunk_buf;
  14.968 +	const char *pend = p + chunk_size;
  14.969 +	uint8_t *buf;
  14.970 +
  14.971 +	/* Reallocate buffer */
  14.972 +	ssize_t _ns = st->size + chunk_size;
  14.973 +	void *nptr = REALLOC(st->buf, _ns + 1);
  14.974 +	if(!nptr) return -1;
  14.975 +	st->buf = (uint8_t *)nptr;
  14.976 +	buf = st->buf + st->size;
  14.977 +
  14.978 +	/*
  14.979 +	 * Convert series of 0 and 1 into the octet string.
  14.980 +	 */
  14.981 +	for(; p < pend; p++) {
  14.982 +		int ch = *(const unsigned char *)p;
  14.983 +		int len;	/* Length of the rest of the chunk */
  14.984 +
  14.985 +		if(ch != 0x26 /* '&' */) {
  14.986 +			*buf++ = ch;
  14.987 +			continue;	/* That was easy... */
  14.988 +		}
  14.989 +
  14.990 +		/*
  14.991 +		 * Process entity reference.
  14.992 +		 */
  14.993 +		len = chunk_size - (p - (const char *)chunk_buf);
  14.994 +		if(len == 1 /* "&" */) goto want_more;
  14.995 +		if(p[1] == 0x23 /* '#' */) {
  14.996 +			const char *pval;	/* Pointer to start of digits */
  14.997 +			int32_t val = 0;	/* Entity reference value */
  14.998 +			int base;
  14.999 +
 14.1000 +			if(len == 2 /* "&#" */) goto want_more;
 14.1001 +			if(p[2] == 0x78 /* 'x' */)
 14.1002 +				pval = p + 3, base = 16;
 14.1003 +			else
 14.1004 +				pval = p + 2, base = 10;
 14.1005 +			len = OS__strtoent(base, pval, p + len, &val);
 14.1006 +			if(len == -1) {
 14.1007 +				/* Invalid charset. Just copy verbatim. */
 14.1008 +				*buf++ = ch;
 14.1009 +				continue;
 14.1010 +			}
 14.1011 +			if(!len || pval[len-1] != 0x3b) goto want_more;
 14.1012 +			assert(val > 0);
 14.1013 +			p += (pval - p) + len - 1; /* Advance past entref */
 14.1014 +
 14.1015 +			if(val < 0x80) {
 14.1016 +				*buf++ = (char)val;
 14.1017 +			} else if(val < 0x800) {
 14.1018 +				*buf++ = 0xc0 | ((val >> 6));
 14.1019 +				*buf++ = 0x80 | ((val & 0x3f));
 14.1020 +			} else if(val < 0x10000) {
 14.1021 +				*buf++ = 0xe0 | ((val >> 12));
 14.1022 +				*buf++ = 0x80 | ((val >> 6) & 0x3f);
 14.1023 +				*buf++ = 0x80 | ((val & 0x3f));
 14.1024 +			} else if(val < 0x200000) {
 14.1025 +				*buf++ = 0xf0 | ((val >> 18));
 14.1026 +				*buf++ = 0x80 | ((val >> 12) & 0x3f);
 14.1027 +				*buf++ = 0x80 | ((val >> 6) & 0x3f);
 14.1028 +				*buf++ = 0x80 | ((val & 0x3f));
 14.1029 +			} else if(val < 0x4000000) {
 14.1030 +				*buf++ = 0xf8 | ((val >> 24));
 14.1031 +				*buf++ = 0x80 | ((val >> 18) & 0x3f);
 14.1032 +				*buf++ = 0x80 | ((val >> 12) & 0x3f);
 14.1033 +				*buf++ = 0x80 | ((val >> 6) & 0x3f);
 14.1034 +				*buf++ = 0x80 | ((val & 0x3f));
 14.1035 +			} else {
 14.1036 +				*buf++ = 0xfc | ((val >> 30) & 0x1);
 14.1037 +				*buf++ = 0x80 | ((val >> 24) & 0x3f);
 14.1038 +				*buf++ = 0x80 | ((val >> 18) & 0x3f);
 14.1039 +				*buf++ = 0x80 | ((val >> 12) & 0x3f);
 14.1040 +				*buf++ = 0x80 | ((val >> 6) & 0x3f);
 14.1041 +				*buf++ = 0x80 | ((val & 0x3f));
 14.1042 +			}
 14.1043 +		} else {
 14.1044 +			/*
 14.1045 +			 * Ugly, limited parsing of &amp; &gt; &lt;
 14.1046 +			 */
 14.1047 +			char *sc = (char *)memchr(p, 0x3b, len > 5 ? 5 : len);
 14.1048 +			if(!sc) goto want_more;
 14.1049 +			if((sc - p) == 4
 14.1050 +				&& p[1] == 0x61	/* 'a' */
 14.1051 +				&& p[2] == 0x6d	/* 'm' */
 14.1052 +				&& p[3] == 0x70	/* 'p' */) {
 14.1053 +				*buf++ = 0x26;
 14.1054 +				p = sc;
 14.1055 +				continue;
 14.1056 +			}
 14.1057 +			if((sc - p) == 3) {
 14.1058 +				if(p[1] == 0x6c) {
 14.1059 +					*buf = 0x3c;	/* '<' */
 14.1060 +				} else if(p[1] == 0x67) {
 14.1061 +					*buf = 0x3e;	/* '>' */
 14.1062 +				} else {
 14.1063 +					/* Unsupported entity reference */
 14.1064 +					*buf++ = ch;
 14.1065 +					continue;
 14.1066 +				}
 14.1067 +				if(p[2] != 0x74) {
 14.1068 +					/* Unsupported entity reference */
 14.1069 +					*buf++ = ch;
 14.1070 +					continue;
 14.1071 +				}
 14.1072 +				buf++;
 14.1073 +				p = sc;
 14.1074 +				continue;
 14.1075 +			}
 14.1076 +			/* Unsupported entity reference */
 14.1077 +			*buf++ = ch;
 14.1078 +		}
 14.1079 +
 14.1080 +		continue;
 14.1081 +	want_more:
 14.1082 +		if(have_more) {
 14.1083 +			/*
 14.1084 +			 * We know that no more data (of the same type)
 14.1085 +			 * is coming. Copy the rest verbatim.
 14.1086 +			 */
 14.1087 +			*buf++ = ch;
 14.1088 +			continue;
 14.1089 +		}
 14.1090 +		chunk_size = (p - (const char *)chunk_buf);
 14.1091 +		/* Processing stalled: need more data */
 14.1092 +		break;
 14.1093 +	}
 14.1094 +
 14.1095 +	st->size = buf - st->buf;
 14.1096 +	assert(st->size <= _ns);
 14.1097 +	st->buf[st->size] = 0;		/* Courtesy termination */
 14.1098 +
 14.1099 +	return chunk_size;	/* Converted in full */
 14.1100 +}
 14.1101 +
 14.1102 +/*
 14.1103 + * Decode OCTET STRING from the XML element's body.
 14.1104 + */
 14.1105 +static asn_dec_rval_t
 14.1106 +OCTET_STRING__decode_xer(asn_codec_ctx_t *opt_codec_ctx,
 14.1107 +	asn_TYPE_descriptor_t *td, void **sptr,
 14.1108 +	const char *opt_mname, const void *buf_ptr, size_t size,
 14.1109 +	int (*opt_unexpected_tag_decoder)
 14.1110 +		(void *struct_ptr, const void *chunk_buf, size_t chunk_size),
 14.1111 +	ssize_t (*body_receiver)
 14.1112 +		(void *struct_ptr, const void *chunk_buf, size_t chunk_size,
 14.1113 +			int have_more)
 14.1114 +) {
 14.1115 +	OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr;
 14.1116 +	asn_OCTET_STRING_specifics_t *specs = td->specifics
 14.1117 +				? (asn_OCTET_STRING_specifics_t *)td->specifics
 14.1118 +				: &asn_DEF_OCTET_STRING_specs;
 14.1119 +	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
 14.1120 +	asn_struct_ctx_t *ctx;		/* Per-structure parser context */
 14.1121 +	asn_dec_rval_t rval;		/* Return value from the decoder */
 14.1122 +	int st_allocated;
 14.1123 +
 14.1124 +	/*
 14.1125 +	 * Create the string if does not exist.
 14.1126 +	 */
 14.1127 +	if(!st) {
 14.1128 +		st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
 14.1129 +		*sptr = (void *)st;
 14.1130 +		if(!st) goto sta_failed;
 14.1131 +		st_allocated = 1;
 14.1132 +	} else {
 14.1133 +		st_allocated = 0;
 14.1134 +	}
 14.1135 +	if(!st->buf) {
 14.1136 +		/* This is separate from above section */
 14.1137 +		st->buf = (uint8_t *)CALLOC(1, 1);
 14.1138 +		if(!st->buf) {
 14.1139 +			if(st_allocated) {
 14.1140 +				*sptr = 0;
 14.1141 +				goto stb_failed;
 14.1142 +			} else {
 14.1143 +				goto sta_failed;
 14.1144 +			}
 14.1145 +		}
 14.1146 +	}
 14.1147 +
 14.1148 +	/* Restore parsing context */
 14.1149 +	ctx = (asn_struct_ctx_t *)(((char *)*sptr) + specs->ctx_offset);
 14.1150 +
 14.1151 +	return xer_decode_general(opt_codec_ctx, ctx, *sptr, xml_tag,
 14.1152 +		buf_ptr, size, opt_unexpected_tag_decoder, body_receiver);
 14.1153 +
 14.1154 +stb_failed:
 14.1155 +	FREEMEM(st);
 14.1156 +sta_failed:
 14.1157 +	rval.code = RC_FAIL;
 14.1158 +	rval.consumed = 0;
 14.1159 +	return rval;
 14.1160 +}
 14.1161 +
 14.1162 +/*
 14.1163 + * Decode OCTET STRING from the hexadecimal data.
 14.1164 + */
 14.1165 +asn_dec_rval_t
 14.1166 +OCTET_STRING_decode_xer_hex(asn_codec_ctx_t *opt_codec_ctx,
 14.1167 +	asn_TYPE_descriptor_t *td, void **sptr,
 14.1168 +		const char *opt_mname, const void *buf_ptr, size_t size) {
 14.1169 +	return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
 14.1170 +		buf_ptr, size, 0, OCTET_STRING__convert_hexadecimal);
 14.1171 +}
 14.1172 +
 14.1173 +/*
 14.1174 + * Decode OCTET STRING from the binary (0/1) data.
 14.1175 + */
 14.1176 +asn_dec_rval_t
 14.1177 +OCTET_STRING_decode_xer_binary(asn_codec_ctx_t *opt_codec_ctx,
 14.1178 +	asn_TYPE_descriptor_t *td, void **sptr,
 14.1179 +		const char *opt_mname, const void *buf_ptr, size_t size) {
 14.1180 +	return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
 14.1181 +		buf_ptr, size, 0, OCTET_STRING__convert_binary);
 14.1182 +}
 14.1183 +
 14.1184 +/*
 14.1185 + * Decode OCTET STRING from the string (ASCII/UTF-8) data.
 14.1186 + */
 14.1187 +asn_dec_rval_t
 14.1188 +OCTET_STRING_decode_xer_utf8(asn_codec_ctx_t *opt_codec_ctx,
 14.1189 +	asn_TYPE_descriptor_t *td, void **sptr,
 14.1190 +		const char *opt_mname, const void *buf_ptr, size_t size) {
 14.1191 +	return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
 14.1192 +		buf_ptr, size,
 14.1193 +		OCTET_STRING__handle_control_chars,
 14.1194 +		OCTET_STRING__convert_entrefs);
 14.1195 +}
 14.1196 +
 14.1197 +static int
 14.1198 +OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
 14.1199 +		size_t units, unsigned int bpc, unsigned int unit_bits,
 14.1200 +		long lb, long ub, asn_per_constraints_t *pc) {
 14.1201 +	uint8_t *end = buf + units * bpc;
 14.1202 +
 14.1203 +	ASN_DEBUG("Expanding %d characters into (%ld..%ld):%d",
 14.1204 +		(int)units, lb, ub, unit_bits);
 14.1205 +
 14.1206 +	/* X.691: 27.5.4 */
 14.1207 +	if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
 14.1208 +		/* Decode without translation */
 14.1209 +		lb = 0;
 14.1210 +	} else if(pc && pc->code2value) {
 14.1211 +		if(unit_bits > 16)
 14.1212 +			return 1;	/* FATAL: can't have constrained
 14.1213 +					 * UniversalString with more than
 14.1214 +					 * 16 million code points */
 14.1215 +		for(; buf < end; buf += bpc) {
 14.1216 +			int value;
 14.1217 +			int code = per_get_few_bits(po, unit_bits);
 14.1218 +			if(code < 0) return -1;	/* WMORE */
 14.1219 +			value = pc->code2value(code);
 14.1220 +			if(value < 0) {
 14.1221 +				ASN_DEBUG("Code %d (0x%02x) is"
 14.1222 +					" not in map (%ld..%ld)",
 14.1223 +					code, code, lb, ub);
 14.1224 +				return 1;	/* FATAL */
 14.1225 +			}
 14.1226 +			switch(bpc) {
 14.1227 +			case 1: *buf = value; break;
 14.1228 +			case 2: buf[0] = value >> 8; buf[1] = value; break;
 14.1229 +			case 4: buf[0] = value >> 24; buf[1] = value >> 16;
 14.1230 +				buf[2] = value >> 8; buf[3] = value; break;
 14.1231 +			}
 14.1232 +		}
 14.1233 +		return 0;
 14.1234 +	}
 14.1235 +
 14.1236 +	/* Shortcut the no-op copying to the aligned structure */
 14.1237 +	if(lb == 0 && (unit_bits == 8 * bpc)) {
 14.1238 +		return per_get_many_bits(po, buf, 0, unit_bits * units);
 14.1239 +	}
 14.1240 +
 14.1241 +	for(; buf < end; buf += bpc) {
 14.1242 +		int code = per_get_few_bits(po, unit_bits);
 14.1243 +		int ch = code + lb;
 14.1244 +		if(code < 0) return -1;	/* WMORE */
 14.1245 +		if(ch > ub) {
 14.1246 +			ASN_DEBUG("Code %d is out of range (%ld..%ld)",
 14.1247 +				ch, lb, ub);
 14.1248 +			return 1;	/* FATAL */
 14.1249 +		}
 14.1250 +		switch(bpc) {
 14.1251 +		case 1: *buf = ch; break;
 14.1252 +		case 2: buf[0] = ch >> 8; buf[1] = ch; break;
 14.1253 +		case 4: buf[0] = ch >> 24; buf[1] = ch >> 16;
 14.1254 +			buf[2] = ch >> 8; buf[3] = ch; break;
 14.1255 +		}
 14.1256 +	}
 14.1257 +
 14.1258 +	return 0;
 14.1259 +}
 14.1260 +
 14.1261 +static int
 14.1262 +OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf,
 14.1263 +		size_t units, unsigned int bpc, unsigned int unit_bits,
 14.1264 +		long lb, long ub, asn_per_constraints_t *pc) {
 14.1265 +	const uint8_t *end = buf + units * bpc;
 14.1266 +
 14.1267 +	ASN_DEBUG("Squeezing %d characters into (%ld..%ld):%d (%d bpc)",
 14.1268 +		(int)units, lb, ub, unit_bits, bpc);
 14.1269 +
 14.1270 +	/* X.691: 27.5.4 */
 14.1271 +	if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) {
 14.1272 +		/* Encode as is */
 14.1273 +		lb = 0;
 14.1274 +	} else if(pc && pc->value2code) {
 14.1275 +		for(; buf < end; buf += bpc) {
 14.1276 +			int code;
 14.1277 +			uint32_t value;
 14.1278 +			switch(bpc) {
 14.1279 +			case 1: value = *(const uint8_t *)buf; break;
 14.1280 +			case 2: value = (buf[0] << 8) | buf[1]; break;
 14.1281 +			case 4: value = (buf[0] << 24) | (buf[1] << 16)
 14.1282 +					| (buf[2] << 8) | buf[3]; break;
 14.1283 +			default: return -1;
 14.1284 +			}
 14.1285 +			code = pc->value2code(value);
 14.1286 +			if(code < 0) {
 14.1287 +				ASN_DEBUG("Character %d (0x%02x) is"
 14.1288 +					" not in map (%ld..%ld)",
 14.1289 +					*buf, *buf, lb, ub);
 14.1290 +				return -1;
 14.1291 +			}
 14.1292 +			if(per_put_few_bits(po, code, unit_bits))
 14.1293 +				return -1;
 14.1294 +		}
 14.1295 +	}
 14.1296 +
 14.1297 +	/* Shortcut the no-op copying to the aligned structure */
 14.1298 +	if(lb == 0 && (unit_bits == 8 * bpc)) {
 14.1299 +		return per_put_many_bits(po, buf, unit_bits * units);
 14.1300 +	}
 14.1301 +
 14.1302 +	for(ub -= lb; buf < end; buf += bpc) {
 14.1303 +		int ch;
 14.1304 +		uint32_t value;
 14.1305 +		switch(bpc) {
 14.1306 +		case 1: value = *(const uint8_t *)buf; break;
 14.1307 +		case 2: value = (buf[0] << 8) | buf[1]; break;
 14.1308 +		case 4: value = (buf[0] << 24) | (buf[1] << 16)
 14.1309 +				| (buf[2] << 8) | buf[3]; break;
 14.1310 +		default: return -1;
 14.1311 +		}
 14.1312 +		ch = value - lb;
 14.1313 +		if(ch < 0 || ch > ub) {
 14.1314 +			ASN_DEBUG("Character %d (0x%02x)"
 14.1315 +			" is out of range (%ld..%ld)",
 14.1316 +				*buf, *buf, lb, ub + lb);
 14.1317 +			return -1;
 14.1318 +		}
 14.1319 +		if(per_put_few_bits(po, ch, unit_bits))
 14.1320 +			return -1;
 14.1321 +	}
 14.1322 +
 14.1323 +	return 0;
 14.1324 +}
 14.1325 +
 14.1326 +asn_dec_rval_t
 14.1327 +OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
 14.1328 +	asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
 14.1329 +	void **sptr, asn_per_data_t *pd) {
 14.1330 +
 14.1331 +	asn_OCTET_STRING_specifics_t *specs = td->specifics
 14.1332 +		? (asn_OCTET_STRING_specifics_t *)td->specifics
 14.1333 +		: &asn_DEF_OCTET_STRING_specs;
 14.1334 +	asn_per_constraints_t *pc = constraints ? constraints
 14.1335 +				: td->per_constraints;
 14.1336 +	asn_per_constraint_t *cval;
 14.1337 +	asn_per_constraint_t *csiz;
 14.1338 +	asn_dec_rval_t rval = { RC_OK, 0 };
 14.1339 +	BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
 14.1340 +	ssize_t consumed_myself = 0;
 14.1341 +	int repeat;
 14.1342 +	enum {
 14.1343 +		OS__BPC_BIT	= 0,
 14.1344 +		OS__BPC_CHAR	= 1,
 14.1345 +		OS__BPC_U16	= 2,
 14.1346 +		OS__BPC_U32	= 4
 14.1347 +	} bpc;	/* Bytes per character */
 14.1348 +	unsigned int unit_bits;
 14.1349 +	unsigned int canonical_unit_bits;
 14.1350 +
 14.1351 +	(void)opt_codec_ctx;
 14.1352 +
 14.1353 +	if(pc) {
 14.1354 +		cval = &pc->value;
 14.1355 +		csiz = &pc->size;
 14.1356 +	} else {
 14.1357 +		cval = &asn_DEF_OCTET_STRING_constraints.value;
 14.1358 +		csiz = &asn_DEF_OCTET_STRING_constraints.size;
 14.1359 +	}
 14.1360 +
 14.1361 +	switch(specs->subvariant) {
 14.1362 +	default:
 14.1363 +	case ASN_OSUBV_ANY:
 14.1364 +		ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant);
 14.1365 +		RETURN(RC_FAIL);
 14.1366 +	case ASN_OSUBV_BIT:
 14.1367 +		canonical_unit_bits = unit_bits = 1;
 14.1368 +		bpc = OS__BPC_BIT;
 14.1369 +		break;
 14.1370 +	case ASN_OSUBV_STR:
 14.1371 +		canonical_unit_bits = unit_bits = 8;
 14.1372 +		if(cval->flags & APC_CONSTRAINED)
 14.1373 +			unit_bits = cval->range_bits;
 14.1374 +		bpc = OS__BPC_CHAR;
 14.1375 +		break;
 14.1376 +	case ASN_OSUBV_U16:
 14.1377 +		canonical_unit_bits = unit_bits = 16;
 14.1378 +		if(cval->flags & APC_CONSTRAINED)
 14.1379 +			unit_bits = cval->range_bits;
 14.1380 +		bpc = OS__BPC_U16;
 14.1381 +		break;
 14.1382 +	case ASN_OSUBV_U32:
 14.1383 +		canonical_unit_bits = unit_bits = 32;
 14.1384 +		if(cval->flags & APC_CONSTRAINED)
 14.1385 +			unit_bits = cval->range_bits;
 14.1386 +		bpc = OS__BPC_U32;
 14.1387 +		break;
 14.1388 +	}
 14.1389 +
 14.1390 +	/*
 14.1391 +	 * Allocate the string.
 14.1392 +	 */
 14.1393 +	if(!st) {
 14.1394 +		st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
 14.1395 +		if(!st) RETURN(RC_FAIL);
 14.1396 +	}
 14.1397 +
 14.1398 +	ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d",
 14.1399 +		csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
 14.1400 +		csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
 14.1401 +
 14.1402 +	if(csiz->flags & APC_EXTENSIBLE) {
 14.1403 +		int inext = per_get_few_bits(pd, 1);
 14.1404 +		if(inext < 0) RETURN(RC_WMORE);
 14.1405 +		if(inext) {
 14.1406 +			csiz = &asn_DEF_OCTET_STRING_constraints.size;
 14.1407 +			cval = &asn_DEF_OCTET_STRING_constraints.value;
 14.1408 +			unit_bits = canonical_unit_bits;
 14.1409 +		}
 14.1410 +	}
 14.1411 +
 14.1412 +	if(csiz->effective_bits >= 0) {
 14.1413 +		FREEMEM(st->buf);
 14.1414 +		if(bpc) {
 14.1415 +			st->size = csiz->upper_bound * bpc;
 14.1416 +		} else {
 14.1417 +			st->size = (csiz->upper_bound + 7) >> 3;
 14.1418 +		}
 14.1419 +		st->buf = (uint8_t *)MALLOC(st->size + 1);
 14.1420 +		if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
 14.1421 +	}
 14.1422 +
 14.1423 +	/* X.691, #16.5: zero-length encoding */
 14.1424 +	/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
 14.1425 +	/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
 14.1426 +	if(csiz->effective_bits == 0) {
 14.1427 +		int ret;
 14.1428 +		if(bpc) {
 14.1429 +			ASN_DEBUG("Encoding OCTET STRING size %ld",
 14.1430 +				csiz->upper_bound);
 14.1431 +			ret = OCTET_STRING_per_get_characters(pd, st->buf,
 14.1432 +				csiz->upper_bound, bpc, unit_bits,
 14.1433 +				cval->lower_bound, cval->upper_bound, pc);
 14.1434 +			if(ret > 0) RETURN(RC_FAIL);
 14.1435 +		} else {
 14.1436 +			ASN_DEBUG("Encoding BIT STRING size %ld",
 14.1437 +				csiz->upper_bound);
 14.1438 +			ret = per_get_many_bits(pd, st->buf, 0,
 14.1439 +					    unit_bits * csiz->upper_bound);
 14.1440 +		}
 14.1441 +		if(ret < 0) RETURN(RC_WMORE);
 14.1442 +		consumed_myself += unit_bits * csiz->upper_bound;
 14.1443 +		st->buf[st->size] = 0;
 14.1444 +		if(bpc == 0) {
 14.1445 +			int ubs = (csiz->upper_bound & 0x7);
 14.1446 +			st->bits_unused = ubs ? 8 - ubs : 0;
 14.1447 +		}
 14.1448 +		RETURN(RC_OK);
 14.1449 +	}
 14.1450 +
 14.1451 +	st->size = 0;
 14.1452 +	do {
 14.1453 +		ssize_t raw_len;
 14.1454 +		ssize_t len_bytes;
 14.1455 +		ssize_t len_bits;
 14.1456 +		void *p;
 14.1457 +		int ret;
 14.1458 +
 14.1459 +		/* Get the PER length */
 14.1460 +		raw_len = uper_get_length(pd, csiz->effective_bits, &repeat);
 14.1461 +		if(raw_len < 0) RETURN(RC_WMORE);
 14.1462 +		raw_len += csiz->lower_bound;
 14.1463 +
 14.1464 +		ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
 14.1465 +			(long)csiz->effective_bits, (long)raw_len,
 14.1466 +			repeat ? "repeat" : "once", td->name);
 14.1467 +		if(bpc) {
 14.1468 +			len_bytes = raw_len * bpc;
 14.1469 +			len_bits = len_bytes * unit_bits;
 14.1470 +		} else {
 14.1471 +			len_bits = raw_len;
 14.1472 +			len_bytes = (len_bits + 7) >> 3;
 14.1473 +			if(len_bits & 0x7)
 14.1474 +				st->bits_unused = 8 - (len_bits & 0x7);
 14.1475 +			/* len_bits be multiple of 16K if repeat is set */
 14.1476 +		}
 14.1477 +		p = REALLOC(st->buf, st->size + len_bytes + 1);
 14.1478 +		if(!p) RETURN(RC_FAIL);
 14.1479 +		st->buf = (uint8_t *)p;
 14.1480 +
 14.1481 +		if(bpc) {
 14.1482 +			ret = OCTET_STRING_per_get_characters(pd,
 14.1483 +				&st->buf[st->size], raw_len, bpc, unit_bits,
 14.1484 +				cval->lower_bound, cval->upper_bound, pc);
 14.1485 +			if(ret > 0) RETURN(RC_FAIL);
 14.1486 +		} else {
 14.1487 +			ret = per_get_many_bits(pd, &st->buf[st->size],
 14.1488 +				0, len_bits);
 14.1489 +		}
 14.1490 +		if(ret < 0) RETURN(RC_WMORE);
 14.1491 +		st->size += len_bytes;
 14.1492 +	} while(repeat);
 14.1493 +	st->buf[st->size] = 0;	/* nul-terminate */
 14.1494 +
 14.1495 +	return rval;
 14.1496 +}
 14.1497 +
 14.1498 +asn_enc_rval_t
 14.1499 +OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
 14.1500 +        asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
 14.1501 +
 14.1502 +	asn_OCTET_STRING_specifics_t *specs = td->specifics
 14.1503 +		? (asn_OCTET_STRING_specifics_t *)td->specifics
 14.1504 +		: &asn_DEF_OCTET_STRING_specs;
 14.1505 +	asn_per_constraints_t *pc = constraints ? constraints
 14.1506 +				: td->per_constraints;
 14.1507 +	asn_per_constraint_t *cval;
 14.1508 +	asn_per_constraint_t *csiz;
 14.1509 +	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
 14.1510 +	asn_enc_rval_t er = { 0, 0, 0 };
 14.1511 +	int inext = 0;		/* Lies not within extension root */
 14.1512 +	unsigned int unit_bits;
 14.1513 +	unsigned int canonical_unit_bits;
 14.1514 +	unsigned int sizeinunits;
 14.1515 +	const uint8_t *buf;
 14.1516 +	int ret;
 14.1517 +	enum {
 14.1518 +		OS__BPC_BIT	= 0,
 14.1519 +		OS__BPC_CHAR	= 1,
 14.1520 +		OS__BPC_U16	= 2,
 14.1521 +		OS__BPC_U32	= 4
 14.1522 +	} bpc;	/* Bytes per character */
 14.1523 +	int ct_extensible;
 14.1524 +
 14.1525 +	if(!st || (!st->buf && st->size))
 14.1526 +		_ASN_ENCODE_FAILED;
 14.1527 +
 14.1528 +	if(pc) {
 14.1529 +		cval = &pc->value;
 14.1530 +		csiz = &pc->size;
 14.1531 +	} else {
 14.1532 +		cval = &asn_DEF_OCTET_STRING_constraints.value;
 14.1533 +		csiz = &asn_DEF_OCTET_STRING_constraints.size;
 14.1534 +	}
 14.1535 +	ct_extensible = csiz->flags & APC_EXTENSIBLE;
 14.1536 +
 14.1537 +	switch(specs->subvariant) {
 14.1538 +	default:
 14.1539 +	case ASN_OSUBV_ANY:
 14.1540 +		_ASN_ENCODE_FAILED;
 14.1541 +	case ASN_OSUBV_BIT:
 14.1542 +		canonical_unit_bits = unit_bits = 1;
 14.1543 +		bpc = OS__BPC_BIT;
 14.1544 +		sizeinunits = st->size * 8 - (st->bits_unused & 0x07);
 14.1545 +		ASN_DEBUG("BIT STRING of %d bytes, %d bits unused",
 14.1546 +				sizeinunits, st->bits_unused);
 14.1547 +		break;
 14.1548 +	case ASN_OSUBV_STR:
 14.1549 +		canonical_unit_bits = unit_bits = 8;
 14.1550 +		if(cval->flags & APC_CONSTRAINED)
 14.1551 +			unit_bits = cval->range_bits;
 14.1552 +		bpc = OS__BPC_CHAR;
 14.1553 +		sizeinunits = st->size;
 14.1554 +		break;
 14.1555 +	case ASN_OSUBV_U16:
 14.1556 +		canonical_unit_bits = unit_bits = 16;
 14.1557 +		if(cval->flags & APC_CONSTRAINED)
 14.1558 +			unit_bits = cval->range_bits;
 14.1559 +		bpc = OS__BPC_U16;
 14.1560 +		sizeinunits = st->size / 2;
 14.1561 +		break;
 14.1562 +	case ASN_OSUBV_U32:
 14.1563 +		canonical_unit_bits = unit_bits = 32;
 14.1564 +		if(cval->flags & APC_CONSTRAINED)
 14.1565 +			unit_bits = cval->range_bits;
 14.1566 +		bpc = OS__BPC_U32;
 14.1567 +		sizeinunits = st->size / 4;
 14.1568 +		break;
 14.1569 +	}
 14.1570 +
 14.1571 +	ASN_DEBUG("Encoding %s into %d units of %d bits"
 14.1572 +		" (%ld..%ld, effective %d)%s",
 14.1573 +		td->name, sizeinunits, unit_bits,
 14.1574 +		csiz->lower_bound, csiz->upper_bound,
 14.1575 +		csiz->effective_bits, ct_extensible ? " EXT" : "");
 14.1576 +
 14.1577 +	/* Figure out whether size lies within PER visible constraint */
 14.1578 +
 14.1579 +	if(csiz->effective_bits >= 0) {
 14.1580 +		if((int)sizeinunits < csiz->lower_bound
 14.1581 +		|| (int)sizeinunits > csiz->upper_bound) {
 14.1582 +			if(ct_extensible) {
 14.1583 +				cval = &asn_DEF_OCTET_STRING_constraints.value;
 14.1584 +				csiz = &asn_DEF_OCTET_STRING_constraints.size;
 14.1585 +				unit_bits = canonical_unit_bits;
 14.1586 +				inext = 1;
 14.1587 +			} else
 14.1588 +				_ASN_ENCODE_FAILED;
 14.1589 +		}
 14.1590 +	} else {
 14.1591 +		inext = 0;
 14.1592 +	}
 14.1593 +
 14.1594 +	if(ct_extensible) {
 14.1595 +		/* Declare whether length is [not] within extension root */
 14.1596 +		if(per_put_few_bits(po, inext, 1))
 14.1597 +			_ASN_ENCODE_FAILED;
 14.1598 +	}
 14.1599 +
 14.1600 +	/* X.691, #16.5: zero-length encoding */
 14.1601 +	/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
 14.1602 +	/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
 14.1603 +	if(csiz->effective_bits >= 0) {
 14.1604 +		ASN_DEBUG("Encoding %d bytes (%ld), length in %d bits",
 14.1605 +				st->size, sizeinunits - csiz->lower_bound,
 14.1606 +				csiz->effective_bits);
 14.1607 +		ret = per_put_few_bits(po, sizeinunits - csiz->lower_bound,
 14.1608 +				csiz->effective_bits);
 14.1609 +		if(ret) _ASN_ENCODE_FAILED;
 14.1610 +		if(bpc) {
 14.1611 +			ret = OCTET_STRING_per_put_characters(po, st->buf,
 14.1612 +				sizeinunits, bpc, unit_bits,
 14.1613 +				cval->lower_bound, cval->upper_bound, pc);
 14.1614 +		} else {
 14.1615 +			ret = per_put_many_bits(po, st->buf,
 14.1616 +				sizeinunits * unit_bits);
 14.1617 +		}
 14.1618 +		if(ret) _ASN_ENCODE_FAILED;
 14.1619 +		_ASN_ENCODED_OK(er);
 14.1620 +	}
 14.1621 +
 14.1622 +	ASN_DEBUG("Encoding %d bytes", st->size);
 14.1623 +
 14.1624 +	if(sizeinunits == 0) {
 14.1625 +		if(uper_put_length(po, 0))
 14.1626 +			_ASN_ENCODE_FAILED;
 14.1627 +		_ASN_ENCODED_OK(er);
 14.1628 +	}
 14.1629 +
 14.1630 +	buf = st->buf;
 14.1631 +	while(sizeinunits) {
 14.1632 +		ssize_t maySave = uper_put_length(po, sizeinunits);
 14.1633 +		if(maySave < 0) _ASN_ENCODE_FAILED;
 14.1634 +
 14.1635 +		ASN_DEBUG("Encoding %ld of %ld",
 14.1636 +			(long)maySave, (long)sizeinunits);
 14.1637 +
 14.1638 +		if(bpc) {
 14.1639 +			ret = OCTET_STRING_per_put_characters(po, buf,
 14.1640 +				maySave, bpc, unit_bits,
 14.1641 +				cval->lower_bound, cval->upper_bound, pc);
 14.1642 +		} else {
 14.1643 +			ret = per_put_many_bits(po, buf, maySave * unit_bits);
 14.1644 +		}
 14.1645 +		if(ret) _ASN_ENCODE_FAILED;
 14.1646 +
 14.1647 +		if(bpc)
 14.1648 +			buf += maySave * bpc;
 14.1649 +		else
 14.1650 +			buf += maySave >> 3;
 14.1651 +		sizeinunits -= maySave;
 14.1652 +		assert(!(maySave & 0x07) || !sizeinunits);
 14.1653 +	}
 14.1654 +
 14.1655 +	_ASN_ENCODED_OK(er);
 14.1656 +}
 14.1657 +
 14.1658 +int
 14.1659 +OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 14.1660 +	asn_app_consume_bytes_f *cb, void *app_key) {
 14.1661 +	static const char *h2c = "0123456789ABCDEF";
 14.1662 +	const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
 14.1663 +	char scratch[16 * 3 + 4];
 14.1664 +	char *p = scratch;
 14.1665 +	uint8_t *buf;
 14.1666 +	uint8_t *end;
 14.1667 +	size_t i;
 14.1668 +
 14.1669 +	(void)td;	/* Unused argument */
 14.1670 +
 14.1671 +	if(!st || (!st->buf && st->size))
 14.1672 +		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 14.1673 +
 14.1674 +	/*
 14.1675 +	 * Dump the contents of the buffer in hexadecimal.
 14.1676 +	 */
 14.1677 +	buf = st->buf;
 14.1678 +	end = buf + st->size;
 14.1679 +	for(i = 0; buf < end; buf++, i++) {
 14.1680 +		if(!(i % 16) && (i || st->size > 16)) {
 14.1681 +			if(cb(scratch, p - scratch, app_key) < 0)
 14.1682 +				return -1;
 14.1683 +			_i_INDENT(1);
 14.1684 +			p = scratch;
 14.1685 +		}
 14.1686 +		*p++ = h2c[(*buf >> 4) & 0x0F];
 14.1687 +		*p++ = h2c[*buf & 0x0F];
 14.1688 +		*p++ = 0x20;
 14.1689 +	}
 14.1690 +
 14.1691 +	if(p > scratch) {
 14.1692 +		p--;	/* Remove the tail space */
 14.1693 +		if(cb(scratch, p - scratch, app_key) < 0)
 14.1694 +			return -1;
 14.1695 +	}
 14.1696 +
 14.1697 +	return 0;
 14.1698 +}
 14.1699 +
 14.1700 +int
 14.1701 +OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr,
 14.1702 +		int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
 14.1703 +	const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
 14.1704 +
 14.1705 +	(void)td;	/* Unused argument */
 14.1706 +	(void)ilevel;	/* Unused argument */
 14.1707 +
 14.1708 +	if(st && (st->buf || !st->size)) {
 14.1709 +		return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
 14.1710 +	} else {
 14.1711 +		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 14.1712 +	}
 14.1713 +}
 14.1714 +
 14.1715 +void
 14.1716 +OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
 14.1717 +	OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
 14.1718 +	asn_OCTET_STRING_specifics_t *specs = td->specifics
 14.1719 +				? (asn_OCTET_STRING_specifics_t *)td->specifics
 14.1720 +				: &asn_DEF_OCTET_STRING_specs;
 14.1721 +	asn_struct_ctx_t *ctx = (asn_struct_ctx_t *)
 14.1722 +					((char *)st + specs->ctx_offset);
 14.1723 +	struct _stack *stck;
 14.1724 +
 14.1725 +	if(!td || !st)
 14.1726 +		return;
 14.1727 +
 14.1728 +	ASN_DEBUG("Freeing %s as OCTET STRING", td->name);
 14.1729 +
 14.1730 +	if(st->buf) {
 14.1731 +		FREEMEM(st->buf);
 14.1732 +		st->buf = 0;
 14.1733 +	}
 14.1734 +
 14.1735 +	/*
 14.1736 +	 * Remove decode-time stack.
 14.1737 +	 */
 14.1738 +	stck = (struct _stack *)ctx->ptr;
 14.1739 +	if(stck) {
 14.1740 +		while(stck->tail) {
 14.1741 +			struct _stack_el *sel = stck->tail;
 14.1742 +			stck->tail = sel->prev;
 14.1743 +			FREEMEM(sel);
 14.1744 +		}
 14.1745 +		FREEMEM(stck);
 14.1746 +	}
 14.1747 +
 14.1748 +	if(!contents_only) {
 14.1749 +		FREEMEM(st);
 14.1750 +	}
 14.1751 +}
 14.1752 +
 14.1753 +/*
 14.1754 + * Conversion routines.
 14.1755 + */
 14.1756 +int
 14.1757 +OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) {
 14.1758 +	void *buf;
 14.1759 +
 14.1760 +	if(st == 0 || (str == 0 && len)) {
 14.1761 +		errno = EINVAL;
 14.1762 +		return -1;
 14.1763 +	}
 14.1764 +
 14.1765 +	/*
 14.1766 +	 * Clear the OCTET STRING.
 14.1767 +	 */
 14.1768 +	if(str == NULL) {
 14.1769 +		FREEMEM(st->buf);
 14.1770 +		st->buf = 0;
 14.1771 +		st->size = 0;
 14.1772 +		return 0;
 14.1773 +	}
 14.1774 +
 14.1775 +	/* Determine the original string size, if not explicitly given */
 14.1776 +	if(len < 0)
 14.1777 +		len = strlen(str);
 14.1778 +
 14.1779 +	/* Allocate and fill the memory */
 14.1780 +	buf = MALLOC(len + 1);
 14.1781 +	if(buf == NULL)
 14.1782 +		return -1;
 14.1783 +
 14.1784 +	memcpy(buf, str, len);
 14.1785 +	((uint8_t *)buf)[len] = '\0';	/* Couldn't use memcpy(len+1)! */
 14.1786 +	FREEMEM(st->buf);
 14.1787 +	st->buf = (uint8_t *)buf;
 14.1788 +	st->size = len;
 14.1789 +
 14.1790 +	return 0;
 14.1791 +}
 14.1792 +
 14.1793 +OCTET_STRING_t *
 14.1794 +OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td, const char *str, int len) {
 14.1795 +	asn_OCTET_STRING_specifics_t *specs = td->specifics
 14.1796 +				? (asn_OCTET_STRING_specifics_t *)td->specifics
 14.1797 +				: &asn_DEF_OCTET_STRING_specs;
 14.1798 +	OCTET_STRING_t *st;
 14.1799 +
 14.1800 +	st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
 14.1801 +	if(st && str && OCTET_STRING_fromBuf(st, str, len)) {
 14.1802 +		FREEMEM(st);
 14.1803 +		st = NULL;
 14.1804 +	}
 14.1805 +
 14.1806 +	return st;
 14.1807 +}
 14.1808 +
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/asn.1/OCTET_STRING.h	Wed May 11 20:06:23 2016 +0200
    15.3 @@ -0,0 +1,86 @@
    15.4 +/*-
    15.5 + * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
    15.6 + * Redistribution and modifications are permitted subject to BSD license.
    15.7 + */
    15.8 +#ifndef	_OCTET_STRING_H_
    15.9 +#define	_OCTET_STRING_H_
   15.10 +
   15.11 +#include <asn_application.h>
   15.12 +
   15.13 +#ifdef __cplusplus
   15.14 +extern "C" {
   15.15 +#endif
   15.16 +
   15.17 +typedef struct OCTET_STRING {
   15.18 +	uint8_t *buf;	/* Buffer with consecutive OCTET_STRING bits */
   15.19 +	int size;	/* Size of the buffer */
   15.20 +
   15.21 +	asn_struct_ctx_t _asn_ctx;	/* Parsing across buffer boundaries */
   15.22 +} OCTET_STRING_t;
   15.23 +
   15.24 +extern asn_TYPE_descriptor_t asn_DEF_OCTET_STRING;
   15.25 +
   15.26 +asn_struct_free_f OCTET_STRING_free;
   15.27 +asn_struct_print_f OCTET_STRING_print;
   15.28 +asn_struct_print_f OCTET_STRING_print_utf8;
   15.29 +ber_type_decoder_f OCTET_STRING_decode_ber;
   15.30 +der_type_encoder_f OCTET_STRING_encode_der;
   15.31 +xer_type_decoder_f OCTET_STRING_decode_xer_hex;		/* Hexadecimal */
   15.32 +xer_type_decoder_f OCTET_STRING_decode_xer_binary;	/* 01010111010 */
   15.33 +xer_type_decoder_f OCTET_STRING_decode_xer_utf8;	/* ASCII/UTF-8 */
   15.34 +xer_type_encoder_f OCTET_STRING_encode_xer;
   15.35 +xer_type_encoder_f OCTET_STRING_encode_xer_utf8;
   15.36 +per_type_decoder_f OCTET_STRING_decode_uper;
   15.37 +per_type_encoder_f OCTET_STRING_encode_uper;
   15.38 +
   15.39 +/******************************
   15.40 + * Handy conversion routines. *
   15.41 + ******************************/
   15.42 +
   15.43 +/*
   15.44 + * This function clears the previous value of the OCTET STRING (if any)
   15.45 + * and then allocates a new memory with the specified content (str/size).
   15.46 + * If size = -1, the size of the original string will be determined
   15.47 + * using strlen(str).
   15.48 + * If str equals to NULL, the function will silently clear the
   15.49 + * current contents of the OCTET STRING.
   15.50 + * Returns 0 if it was possible to perform operation, -1 otherwise.
   15.51 + */
   15.52 +int OCTET_STRING_fromBuf(OCTET_STRING_t *s, const char *str, int size);
   15.53 +
   15.54 +/* Handy conversion from the C string into the OCTET STRING. */
   15.55 +#define	OCTET_STRING_fromString(s, str)	OCTET_STRING_fromBuf(s, str, -1)
   15.56 +
   15.57 +/*
   15.58 + * Allocate and fill the new OCTET STRING and return a pointer to the newly
   15.59 + * allocated object. NULL is permitted in str: the function will just allocate
   15.60 + * empty OCTET STRING.
   15.61 + */
   15.62 +OCTET_STRING_t *OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td,
   15.63 +	const char *str, int size);
   15.64 +
   15.65 +/****************************
   15.66 + * Internally useful stuff. *
   15.67 + ****************************/
   15.68 +
   15.69 +typedef struct asn_OCTET_STRING_specifics_s {
   15.70 +	/*
   15.71 +	 * Target structure description.
   15.72 +	 */
   15.73 +	int struct_size;	/* Size of the structure */
   15.74 +	int ctx_offset;		/* Offset of the asn_struct_ctx_t member */
   15.75 +
   15.76 +	enum asn_OS_Subvariant {
   15.77 +		ASN_OSUBV_ANY,	/* The open type (ANY) */
   15.78 +		ASN_OSUBV_BIT,	/* BIT STRING */
   15.79 +		ASN_OSUBV_STR,	/* String types, not {BMP,Universal}String  */
   15.80 +		ASN_OSUBV_U16,	/* 16-bit character (BMPString) */
   15.81 +		ASN_OSUBV_U32	/* 32-bit character (UniversalString) */
   15.82 +	} subvariant;
   15.83 +} asn_OCTET_STRING_specifics_t;
   15.84 +
   15.85 +#ifdef __cplusplus
   15.86 +}
   15.87 +#endif
   15.88 +
   15.89 +#endif	/* _OCTET_STRING_H_ */
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/asn.1/PrintableString.c	Wed May 11 20:06:23 2016 +0200
    16.3 @@ -0,0 +1,109 @@
    16.4 +/*-
    16.5 + * Copyright (c) 2003, 2004, 2006 Lev Walkin <vlm@lionet.info>.
    16.6 + * All rights reserved.
    16.7 + * Redistribution and modifications are permitted subject to BSD license.
    16.8 + */
    16.9 +#include <asn_internal.h>
   16.10 +#include <PrintableString.h>
   16.11 +
   16.12 +/*
   16.13 + * ASN.1:1984 (X.409)
   16.14 + */
   16.15 +static int _PrintableString_alphabet[256] = {
   16.16 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/*                  */
   16.17 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/*                  */
   16.18 + 1, 0, 0, 0, 0, 0, 0, 2, 3, 4, 0, 5, 6, 7, 8, 9,	/* .      '() +,-./ */
   16.19 +10,11,12,13,14,15,16,17,18,19,20, 0, 0,21, 0,22,	/* 0123456789:  = ? */
   16.20 + 0,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,	/*  ABCDEFGHIJKLMNO */
   16.21 +38,39,40,41,42,43,44,45,46,47,48, 0, 0, 0, 0, 0,	/* PQRSTUVWXYZ      */
   16.22 + 0,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,	/*  abcdefghijklmno */
   16.23 +64,65,66,67,68,69,70,71,72,73,74, 0, 0, 0, 0, 0,	/* pqrstuvwxyz      */
   16.24 +};
   16.25 +static int _PrintableString_code2value[74] = { 
   16.26 +32,39,40,41,43,44,45,46,47,48,49,50,51,52,53,54,
   16.27 +55,56,57,58,61,63,65,66,67,68,69,70,71,72,73,74,
   16.28 +75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,
   16.29 +97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,
   16.30 +113,114,115,116,117,118,119,120,121,122};
   16.31 +
   16.32 +/*
   16.33 + * PrintableString basic type description.
   16.34 + */
   16.35 +static ber_tlv_tag_t asn_DEF_PrintableString_tags[] = {
   16.36 +	(ASN_TAG_CLASS_UNIVERSAL | (19 << 2)),	/* [UNIVERSAL 19] IMPLICIT ...*/
   16.37 +	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))	/* ... OCTET STRING */
   16.38 +};
   16.39 +static int asn_DEF_PrintableString_v2c(unsigned int value) {
   16.40 +	return _PrintableString_alphabet[value > 255 ? 0 : value] - 1;
   16.41 +}
   16.42 +static int asn_DEF_PrintableString_c2v(unsigned int code) {
   16.43 +	if(code < 74)
   16.44 +		return _PrintableString_code2value[code];
   16.45 +	return -1;
   16.46 +}
   16.47 +static asn_per_constraints_t asn_DEF_PrintableString_constraints = {
   16.48 +	{ APC_CONSTRAINED, 4, 4, 0x20, 0x39 },	/* Value */
   16.49 +	{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },	/* Size */
   16.50 +	asn_DEF_PrintableString_v2c,
   16.51 +	asn_DEF_PrintableString_c2v
   16.52 +};
   16.53 +asn_TYPE_descriptor_t asn_DEF_PrintableString = {
   16.54 +	"PrintableString",
   16.55 +	"PrintableString",
   16.56 +	OCTET_STRING_free,
   16.57 +	OCTET_STRING_print_utf8,	/* ASCII subset */
   16.58 +	PrintableString_constraint,
   16.59 +	OCTET_STRING_decode_ber,      /* Implemented in terms of OCTET STRING */
   16.60 +	OCTET_STRING_encode_der,
   16.61 +	OCTET_STRING_decode_xer_utf8,
   16.62 +	OCTET_STRING_encode_xer_utf8,
   16.63 +	OCTET_STRING_decode_uper,
   16.64 +	OCTET_STRING_encode_uper,
   16.65 +	0, /* Use generic outmost tag fetcher */
   16.66 +	asn_DEF_PrintableString_tags,
   16.67 +	sizeof(asn_DEF_PrintableString_tags)
   16.68 +	  / sizeof(asn_DEF_PrintableString_tags[0]) - 1,
   16.69 +	asn_DEF_PrintableString_tags,
   16.70 +	sizeof(asn_DEF_PrintableString_tags)
   16.71 +	  / sizeof(asn_DEF_PrintableString_tags[0]),
   16.72 +	&asn_DEF_PrintableString_constraints,
   16.73 +	0, 0,	/* No members */
   16.74 +	0	/* No specifics */
   16.75 +};
   16.76 +
   16.77 +
   16.78 +int
   16.79 +PrintableString_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
   16.80 +		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
   16.81 +	const PrintableString_t *st = (const PrintableString_t *)sptr;
   16.82 +
   16.83 +	if(st && st->buf) {
   16.84 +		uint8_t *buf = st->buf;
   16.85 +		uint8_t *end = buf + st->size;
   16.86 +
   16.87 +		/*
   16.88 +		 * Check the alphabet of the PrintableString.
   16.89 +		 * ASN.1:1984 (X.409)
   16.90 +		 */
   16.91 +		for(; buf < end; buf++) {
   16.92 +			if(!_PrintableString_alphabet[*buf]) {
   16.93 +				_ASN_CTFAIL(app_key, td, sptr,
   16.94 +					"%s: value byte %ld (%d) "
   16.95 +					"not in PrintableString alphabet "
   16.96 +					"(%s:%d)",
   16.97 +					td->name,
   16.98 +					(long)((buf - st->buf) + 1),
   16.99 +					*buf,
  16.100 +					__FILE__, __LINE__);
  16.101 +				return -1;
  16.102 +			}
  16.103 +		}
  16.104 +	} else {
  16.105 +		_ASN_CTFAIL(app_key, td, sptr,
  16.106 +			"%s: value not given (%s:%d)",
  16.107 +			td->name, __FILE__, __LINE__);
  16.108 +		return -1;
  16.109 +	}
  16.110 +
  16.111 +	return 0;
  16.112 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/asn.1/PrintableString.h	Wed May 11 20:06:23 2016 +0200
    17.3 @@ -0,0 +1,24 @@
    17.4 +/*-
    17.5 + * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
    17.6 + * Redistribution and modifications are permitted subject to BSD license.
    17.7 + */
    17.8 +#ifndef	_PrintableString_H_
    17.9 +#define	_PrintableString_H_
   17.10 +
   17.11 +#include <OCTET_STRING.h>
   17.12 +
   17.13 +#ifdef __cplusplus
   17.14 +extern "C" {
   17.15 +#endif
   17.16 +
   17.17 +typedef OCTET_STRING_t PrintableString_t;  /* Implemented via OCTET STRING */
   17.18 +
   17.19 +extern asn_TYPE_descriptor_t asn_DEF_PrintableString;
   17.20 +
   17.21 +asn_constr_check_f PrintableString_constraint;
   17.22 +
   17.23 +#ifdef __cplusplus
   17.24 +}
   17.25 +#endif
   17.26 +
   17.27 +#endif	/* _PrintableString_H_ */
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/asn.1/Stringlist.c	Wed May 11 20:06:23 2016 +0200
    18.3 @@ -0,0 +1,52 @@
    18.4 +/*
    18.5 + * Generated by asn1c-0.9.26 (http://lionet.info/asn1c)
    18.6 + * From ASN.1 module "PEP"
    18.7 + * 	found in "pEp.asn1"
    18.8 + */
    18.9 +
   18.10 +#include "Stringlist.h"
   18.11 +
   18.12 +static asn_TYPE_member_t asn_MBR_Stringlist_1[] = {
   18.13 +	{ ATF_POINTER, 0, 0,
   18.14 +		(ASN_TAG_CLASS_UNIVERSAL | (12 << 2)),
   18.15 +		0,
   18.16 +		&asn_DEF_UTF8String,
   18.17 +		0,	/* Defer constraints checking to the member type */
   18.18 +		0,	/* No PER visible constraints */
   18.19 +		0,
   18.20 +		""
   18.21 +		},
   18.22 +};
   18.23 +static ber_tlv_tag_t asn_DEF_Stringlist_tags_1[] = {
   18.24 +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
   18.25 +};
   18.26 +static asn_SET_OF_specifics_t asn_SPC_Stringlist_specs_1 = {
   18.27 +	sizeof(struct Stringlist),
   18.28 +	offsetof(struct Stringlist, _asn_ctx),
   18.29 +	0,	/* XER encoding is XMLDelimitedItemList */
   18.30 +};
   18.31 +asn_TYPE_descriptor_t asn_DEF_Stringlist = {
   18.32 +	"Stringlist",
   18.33 +	"Stringlist",
   18.34 +	SEQUENCE_OF_free,
   18.35 +	SEQUENCE_OF_print,
   18.36 +	SEQUENCE_OF_constraint,
   18.37 +	SEQUENCE_OF_decode_ber,
   18.38 +	SEQUENCE_OF_encode_der,
   18.39 +	SEQUENCE_OF_decode_xer,
   18.40 +	SEQUENCE_OF_encode_xer,
   18.41 +	SEQUENCE_OF_decode_uper,
   18.42 +	SEQUENCE_OF_encode_uper,
   18.43 +	0,	/* Use generic outmost tag fetcher */
   18.44 +	asn_DEF_Stringlist_tags_1,
   18.45 +	sizeof(asn_DEF_Stringlist_tags_1)
   18.46 +		/sizeof(asn_DEF_Stringlist_tags_1[0]), /* 1 */
   18.47 +	asn_DEF_Stringlist_tags_1,	/* Same as above */
   18.48 +	sizeof(asn_DEF_Stringlist_tags_1)
   18.49 +		/sizeof(asn_DEF_Stringlist_tags_1[0]), /* 1 */
   18.50 +	0,	/* No PER visible constraints */
   18.51 +	asn_MBR_Stringlist_1,
   18.52 +	1,	/* Single element */
   18.53 +	&asn_SPC_Stringlist_specs_1	/* Additional specs */
   18.54 +};
   18.55 +
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/asn.1/Stringlist.h	Wed May 11 20:06:23 2016 +0200
    19.3 @@ -0,0 +1,38 @@
    19.4 +/*
    19.5 + * Generated by asn1c-0.9.26 (http://lionet.info/asn1c)
    19.6 + * From ASN.1 module "PEP"
    19.7 + * 	found in "pEp.asn1"
    19.8 + */
    19.9 +
   19.10 +#ifndef	_Stringlist_H_
   19.11 +#define	_Stringlist_H_
   19.12 +
   19.13 +
   19.14 +#include <asn_application.h>
   19.15 +
   19.16 +/* Including external dependencies */
   19.17 +#include <UTF8String.h>
   19.18 +#include <asn_SEQUENCE_OF.h>
   19.19 +#include <constr_SEQUENCE_OF.h>
   19.20 +
   19.21 +#ifdef __cplusplus
   19.22 +extern "C" {
   19.23 +#endif
   19.24 +
   19.25 +/* Stringlist */
   19.26 +typedef struct Stringlist {
   19.27 +	A_SEQUENCE_OF(UTF8String_t) list;
   19.28 +	
   19.29 +	/* Context for parsing across buffer boundaries */
   19.30 +	asn_struct_ctx_t _asn_ctx;
   19.31 +} Stringlist_t;
   19.32 +
   19.33 +/* Implementation */
   19.34 +extern asn_TYPE_descriptor_t asn_DEF_Stringlist;
   19.35 +
   19.36 +#ifdef __cplusplus
   19.37 +}
   19.38 +#endif
   19.39 +
   19.40 +#endif	/* _Stringlist_H_ */
   19.41 +#include <asn_internal.h>
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/asn.1/UTF8String.c	Wed May 11 20:06:23 2016 +0200
    20.3 @@ -0,0 +1,184 @@
    20.4 +/*-
    20.5 + * Copyright (c) 2003, 2004, 2006 Lev Walkin <vlm@lionet.info>.
    20.6 + * All rights reserved.
    20.7 + * Redistribution and modifications are permitted subject to BSD license.
    20.8 + */
    20.9 +#include <asn_internal.h>
   20.10 +#include <UTF8String.h>
   20.11 +
   20.12 +/*
   20.13 + * UTF8String basic type description.
   20.14 + */
   20.15 +static ber_tlv_tag_t asn_DEF_UTF8String_tags[] = {
   20.16 +	(ASN_TAG_CLASS_UNIVERSAL | (12 << 2)),	/* [UNIVERSAL 12] IMPLICIT ...*/
   20.17 +	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)),	/* ... OCTET STRING */
   20.18 +};
   20.19 +asn_TYPE_descriptor_t asn_DEF_UTF8String = {
   20.20 +	"UTF8String",
   20.21 +	"UTF8String",
   20.22 +	OCTET_STRING_free,
   20.23 +	UTF8String_print,
   20.24 +	UTF8String_constraint,      /* Check for invalid codes, etc. */
   20.25 +	OCTET_STRING_decode_ber,    /* Implemented in terms of OCTET STRING */
   20.26 +	OCTET_STRING_encode_der,
   20.27 +	OCTET_STRING_decode_xer_utf8,
   20.28 +	OCTET_STRING_encode_xer_utf8,
   20.29 +	OCTET_STRING_decode_uper,
   20.30 +	OCTET_STRING_encode_uper,
   20.31 +	0, /* Use generic outmost tag fetcher */
   20.32 +	asn_DEF_UTF8String_tags,
   20.33 +	sizeof(asn_DEF_UTF8String_tags)
   20.34 +	  / sizeof(asn_DEF_UTF8String_tags[0]) - 1,
   20.35 +	asn_DEF_UTF8String_tags,
   20.36 +	sizeof(asn_DEF_UTF8String_tags)
   20.37 +	  / sizeof(asn_DEF_UTF8String_tags[0]),
   20.38 +	0,	/* No PER visible constraints */
   20.39 +	0, 0,	/* No members */
   20.40 +	0	/* No specifics */
   20.41 +};
   20.42 +
   20.43 +/*
   20.44 + * This is the table of length expectations.
   20.45 + * The second half of this table is only applicable to the long sequences.
   20.46 + */
   20.47 +static int UTF8String_ht[2][16] = {
   20.48 +	{ /* 0x0 ... 0x7 */
   20.49 +	  /* 0000..0111 */
   20.50 +	  1, 1, 1, 1, 1, 1, 1, 1,
   20.51 +	  /* 1000..1011(0), 1100..1101(2), 1110(3), 1111(-1) */
   20.52 +	  0, 0, 0, 0, 2, 2, 3, -1 },
   20.53 +	{ /* 0xF0 .. 0xF7 */
   20.54 +	  /* 11110000..11110111 */
   20.55 +	  4, 4, 4, 4, 4, 4, 4, 4,
   20.56 +	  5, 5, 5, 5, 6, 6, -1, -1 }
   20.57 +};
   20.58 +static int32_t UTF8String_mv[7] = { 0, 0,
   20.59 +	0x00000080,
   20.60 +	0x00000800,
   20.61 +	0x00010000,
   20.62 +	0x00200000,
   20.63 +	0x04000000
   20.64 +};
   20.65 +
   20.66 +/* Internal aliases for return codes */
   20.67 +#define	U8E_TRUNC	-1	/* UTF-8 sequence truncated */
   20.68 +#define	U8E_ILLSTART	-2	/* Illegal UTF-8 sequence start */
   20.69 +#define	U8E_NOTCONT	-3	/* Continuation expectation failed */
   20.70 +#define	U8E_NOTMIN	-4	/* Not minimal length encoding */
   20.71 +#define	U8E_EINVAL	-5	/* Invalid arguments */
   20.72 +
   20.73 +int
   20.74 +UTF8String_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
   20.75 +		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
   20.76 +	ssize_t len = UTF8String_length((const UTF8String_t *)sptr);
   20.77 +	switch(len) {
   20.78 +	case U8E_EINVAL:
   20.79 +		_ASN_CTFAIL(app_key, td, sptr,
   20.80 +			"%s: value not given", td->name);
   20.81 +		break;
   20.82 +	case U8E_TRUNC:
   20.83 +		_ASN_CTFAIL(app_key, td, sptr,
   20.84 +			"%s: truncated UTF-8 sequence (%s:%d)",
   20.85 +			td->name, __FILE__, __LINE__);
   20.86 +		break;
   20.87 +	case U8E_ILLSTART:
   20.88 +		_ASN_CTFAIL(app_key, td, sptr,
   20.89 +			"%s: UTF-8 illegal start of encoding (%s:%d)",
   20.90 +			td->name, __FILE__, __LINE__);
   20.91 +		break;
   20.92 +	case U8E_NOTCONT:
   20.93 +		_ASN_CTFAIL(app_key, td, sptr,
   20.94 +			"%s: UTF-8 not continuation (%s:%d)",
   20.95 +			td->name, __FILE__, __LINE__);
   20.96 +		break;
   20.97 +	case U8E_NOTMIN:
   20.98 +		_ASN_CTFAIL(app_key, td, sptr,
   20.99 +			"%s: UTF-8 not minimal sequence (%s:%d)",
  20.100 +			td->name, __FILE__, __LINE__);
  20.101 +		break;
  20.102 +	}
  20.103 +	return (len < 0) ? -1 : 0;
  20.104 +}
  20.105 +
  20.106 +static ssize_t
  20.107 +UTF8String__process(const UTF8String_t *st, uint32_t *dst, size_t dstlen) {
  20.108 +	size_t length;
  20.109 +	uint8_t *buf = st->buf;
  20.110 +	uint8_t *end = buf + st->size;
  20.111 +	uint32_t *dstend = dst + dstlen;
  20.112 +
  20.113 +	for(length = 0; buf < end; length++) {
  20.114 +		int ch = *buf;
  20.115 +		uint8_t *cend;
  20.116 +		int32_t value;
  20.117 +		int want;
  20.118 +
  20.119 +		/* Compute the sequence length */
  20.120 +		want = UTF8String_ht[0][ch >> 4];
  20.121 +		switch(want) {
  20.122 +		case -1:
  20.123 +			/* Second half of the table, long sequence */
  20.124 +			want = UTF8String_ht[1][ch & 0x0F];
  20.125 +			if(want != -1) break;
  20.126 +			/* Fall through */
  20.127 +		case 0:
  20.128 +			return U8E_ILLSTART;
  20.129 +		}
  20.130 +
  20.131 +		/* assert(want >= 1 && want <= 6) */
  20.132 +
  20.133 +		/* Check character sequence length */
  20.134 +		if(buf + want > end) return U8E_TRUNC;
  20.135 +
  20.136 +		value = ch & (0xff >> want);
  20.137 +		cend = buf + want;
  20.138 +		for(buf++; buf < cend; buf++) {
  20.139 +			ch = *buf;
  20.140 +			if(ch < 0x80 || ch > 0xbf) return U8E_NOTCONT;
  20.141 +			value = (value << 6) | (ch & 0x3F);
  20.142 +		}
  20.143 +		if(value < UTF8String_mv[want])
  20.144 +			return U8E_NOTMIN;
  20.145 +		if(dst < dstend)
  20.146 +			*dst++ = value;	/* Record value */
  20.147 +	}
  20.148 +
  20.149 +	if(dst < dstend) *dst = 0;	/* zero-terminate */
  20.150 +
  20.151 +	return length;
  20.152 +}
  20.153 +
  20.154 +
  20.155 +ssize_t
  20.156 +UTF8String_length(const UTF8String_t *st) {
  20.157 +	if(st && st->buf) {
  20.158 +		return UTF8String__process(st, 0, 0);
  20.159 +	} else {
  20.160 +		return U8E_EINVAL;
  20.161 +	}
  20.162 +}
  20.163 +
  20.164 +size_t
  20.165 +UTF8String_to_wcs(const UTF8String_t *st, uint32_t *dst, size_t dstlen) {
  20.166 +	if(st && st->buf) {
  20.167 +		ssize_t ret = UTF8String__process(st, dst, dstlen);
  20.168 +		return (ret < 0) ? 0 : ret;
  20.169 +	} else {
  20.170 +		return 0;
  20.171 +	}
  20.172 +}
  20.173 +
  20.174 +int
  20.175 +UTF8String_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
  20.176 +	asn_app_consume_bytes_f *cb, void *app_key) {
  20.177 +	const UTF8String_t *st = (const UTF8String_t *)sptr;
  20.178 +
  20.179 +	(void)td;	/* Unused argument */
  20.180 +	(void)ilevel;	/* Unused argument */
  20.181 +
  20.182 +	if(st && st->buf) {
  20.183 +		return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
  20.184 +	} else {
  20.185 +		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
  20.186 +	}
  20.187 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/asn.1/UTF8String.h	Wed May 11 20:06:23 2016 +0200
    21.3 @@ -0,0 +1,49 @@
    21.4 +/*-
    21.5 + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    21.6 + * Redistribution and modifications are permitted subject to BSD license.
    21.7 + */
    21.8 +#ifndef	_UTF8String_H_
    21.9 +#define	_UTF8String_H_
   21.10 +
   21.11 +#include <OCTET_STRING.h>
   21.12 +
   21.13 +#ifdef __cplusplus
   21.14 +extern "C" {
   21.15 +#endif
   21.16 +
   21.17 +typedef OCTET_STRING_t UTF8String_t;	/* Implemented via OCTET STRING */
   21.18 +
   21.19 +extern asn_TYPE_descriptor_t asn_DEF_UTF8String;
   21.20 +
   21.21 +asn_struct_print_f UTF8String_print;
   21.22 +asn_constr_check_f UTF8String_constraint;
   21.23 +
   21.24 +/*
   21.25 + * Returns length of the given UTF-8 string in characters,
   21.26 + * or a negative error code:
   21.27 + * -1:	UTF-8 sequence truncated 
   21.28 + * -2:	Illegal UTF-8 sequence start
   21.29 + * -3:	Continuation expectation failed
   21.30 + * -4:	Not minimal length encoding
   21.31 + * -5:	Invalid arguments
   21.32 + */
   21.33 +ssize_t UTF8String_length(const UTF8String_t *st);
   21.34 +
   21.35 +/*
   21.36 + * Convert the UTF-8 string into a sequence of wide characters.
   21.37 + * Returns the number of characters necessary.
   21.38 + * Returned value might be greater than dstlen.
   21.39 + * In case of conversion error, 0 is returned.
   21.40 + * 
   21.41 + * If st points to a valid UTF-8 string, calling
   21.42 + * 	UTF8String_to_wcs(st, 0, 0);
   21.43 + * is equivalent to
   21.44 + * 	UTF8String_length(const UTF8String_t *st);
   21.45 + */
   21.46 +size_t UTF8String_to_wcs(const UTF8String_t *st, uint32_t *dst, size_t dstlen);
   21.47 +
   21.48 +#ifdef __cplusplus
   21.49 +}
   21.50 +#endif
   21.51 +
   21.52 +#endif	/* _UTF8String_H_ */
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/asn.1/Version.c	Wed May 11 20:06:23 2016 +0200
    22.3 @@ -0,0 +1,129 @@
    22.4 +/*
    22.5 + * Generated by asn1c-0.9.26 (http://lionet.info/asn1c)
    22.6 + * From ASN.1 module "PEP"
    22.7 + * 	found in "pEp.asn1"
    22.8 + */
    22.9 +
   22.10 +#include "Version.h"
   22.11 +
   22.12 +static int
   22.13 +memb_major_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr,
   22.14 +			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
   22.15 +	long value;
   22.16 +	
   22.17 +	if(!sptr) {
   22.18 +		_ASN_CTFAIL(app_key, td, sptr,
   22.19 +			"%s: value not given (%s:%d)",
   22.20 +			td->name, __FILE__, __LINE__);
   22.21 +		return -1;
   22.22 +	}
   22.23 +	
   22.24 +	value = *(const long *)sptr;
   22.25 +	
   22.26 +	if((value >= 0 && value <= 255)) {
   22.27 +		/* Constraint check succeeded */
   22.28 +		return 0;
   22.29 +	} else {
   22.30 +		_ASN_CTFAIL(app_key, td, sptr,
   22.31 +			"%s: constraint failed (%s:%d)",
   22.32 +			td->name, __FILE__, __LINE__);
   22.33 +		return -1;
   22.34 +	}
   22.35 +}
   22.36 +
   22.37 +static int
   22.38 +memb_minor_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr,
   22.39 +			asn_app_constraint_failed_f *ctfailcb, void *app_key) {
   22.40 +	long value;
   22.41 +	
   22.42 +	if(!sptr) {
   22.43 +		_ASN_CTFAIL(app_key, td, sptr,
   22.44 +			"%s: value not given (%s:%d)",
   22.45 +			td->name, __FILE__, __LINE__);
   22.46 +		return -1;
   22.47 +	}
   22.48 +	
   22.49 +	value = *(const long *)sptr;
   22.50 +	
   22.51 +	if((value >= 0 && value <= 255)) {
   22.52 +		/* Constraint check succeeded */
   22.53 +		return 0;
   22.54 +	} else {
   22.55 +		_ASN_CTFAIL(app_key, td, sptr,
   22.56 +			"%s: constraint failed (%s:%d)",
   22.57 +			td->name, __FILE__, __LINE__);
   22.58 +		return -1;
   22.59 +	}
   22.60 +}
   22.61 +
   22.62 +static asn_per_constraints_t asn_PER_memb_major_constr_2 GCC_NOTUSED = {
   22.63 +	{ APC_CONSTRAINED,	 8,  8,  0,  255 }	/* (0..255) */,
   22.64 +	{ APC_UNCONSTRAINED,	-1, -1,  0,  0 },
   22.65 +	0, 0	/* No PER value map */
   22.66 +};
   22.67 +static asn_per_constraints_t asn_PER_memb_minor_constr_3 GCC_NOTUSED = {
   22.68 +	{ APC_CONSTRAINED,	 8,  8,  0,  255 }	/* (0..255) */,
   22.69 +	{ APC_UNCONSTRAINED,	-1, -1,  0,  0 },
   22.70 +	0, 0	/* No PER value map */
   22.71 +};
   22.72 +static asn_TYPE_member_t asn_MBR_Version_1[] = {
   22.73 +	{ ATF_NOFLAGS, 0, offsetof(struct Version, major),
   22.74 +		(ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
   22.75 +		0,
   22.76 +		&asn_DEF_NativeInteger,
   22.77 +		memb_major_constraint_1,
   22.78 +		&asn_PER_memb_major_constr_2,
   22.79 +		0,
   22.80 +		"major"
   22.81 +		},
   22.82 +	{ ATF_NOFLAGS, 0, offsetof(struct Version, minor),
   22.83 +		(ASN_TAG_CLASS_UNIVERSAL | (2 << 2)),
   22.84 +		0,
   22.85 +		&asn_DEF_NativeInteger,
   22.86 +		memb_minor_constraint_1,
   22.87 +		&asn_PER_memb_minor_constr_3,
   22.88 +		0,
   22.89 +		"minor"
   22.90 +		},
   22.91 +};
   22.92 +static ber_tlv_tag_t asn_DEF_Version_tags_1[] = {
   22.93 +	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
   22.94 +};
   22.95 +static asn_TYPE_tag2member_t asn_MAP_Version_tag2el_1[] = {
   22.96 +    { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 1 }, /* major */
   22.97 +    { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 1, -1, 0 } /* minor */
   22.98 +};
   22.99 +static asn_SEQUENCE_specifics_t asn_SPC_Version_specs_1 = {
  22.100 +	sizeof(struct Version),
  22.101 +	offsetof(struct Version, _asn_ctx),
  22.102 +	asn_MAP_Version_tag2el_1,
  22.103 +	2,	/* Count of tags in the map */
  22.104 +	0, 0, 0,	/* Optional elements (not needed) */
  22.105 +	-1,	/* Start extensions */
  22.106 +	-1	/* Stop extensions */
  22.107 +};
  22.108 +asn_TYPE_descriptor_t asn_DEF_Version = {
  22.109 +	"Version",
  22.110 +	"Version",
  22.111 +	SEQUENCE_free,
  22.112 +	SEQUENCE_print,
  22.113 +	SEQUENCE_constraint,
  22.114 +	SEQUENCE_decode_ber,
  22.115 +	SEQUENCE_encode_der,
  22.116 +	SEQUENCE_decode_xer,
  22.117 +	SEQUENCE_encode_xer,
  22.118 +	SEQUENCE_decode_uper,
  22.119 +	SEQUENCE_encode_uper,
  22.120 +	0,	/* Use generic outmost tag fetcher */
  22.121 +	asn_DEF_Version_tags_1,
  22.122 +	sizeof(asn_DEF_Version_tags_1)
  22.123 +		/sizeof(asn_DEF_Version_tags_1[0]), /* 1 */
  22.124 +	asn_DEF_Version_tags_1,	/* Same as above */
  22.125 +	sizeof(asn_DEF_Version_tags_1)
  22.126 +		/sizeof(asn_DEF_Version_tags_1[0]), /* 1 */
  22.127 +	0,	/* No PER visible constraints */
  22.128 +	asn_MBR_Version_1,
  22.129 +	2,	/* Elements count */
  22.130 +	&asn_SPC_Version_specs_1	/* Additional specs */
  22.131 +};
  22.132 +
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/asn.1/Version.h	Wed May 11 20:06:23 2016 +0200
    23.3 @@ -0,0 +1,38 @@
    23.4 +/*
    23.5 + * Generated by asn1c-0.9.26 (http://lionet.info/asn1c)
    23.6 + * From ASN.1 module "PEP"
    23.7 + * 	found in "pEp.asn1"
    23.8 + */
    23.9 +
   23.10 +#ifndef	_Version_H_
   23.11 +#define	_Version_H_
   23.12 +
   23.13 +
   23.14 +#include <asn_application.h>
   23.15 +
   23.16 +/* Including external dependencies */
   23.17 +#include <NativeInteger.h>
   23.18 +#include <constr_SEQUENCE.h>
   23.19 +
   23.20 +#ifdef __cplusplus
   23.21 +extern "C" {
   23.22 +#endif
   23.23 +
   23.24 +/* Version */
   23.25 +typedef struct Version {
   23.26 +	long	 major;
   23.27 +	long	 minor;
   23.28 +	
   23.29 +	/* Context for parsing across buffer boundaries */
   23.30 +	asn_struct_ctx_t _asn_ctx;
   23.31 +} Version_t;
   23.32 +
   23.33 +/* Implementation */
   23.34 +extern asn_TYPE_descriptor_t asn_DEF_Version;
   23.35 +
   23.36 +#ifdef __cplusplus
   23.37 +}
   23.38 +#endif
   23.39 +
   23.40 +#endif	/* _Version_H_ */
   23.41 +#include <asn_internal.h>
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/asn.1/asn_SEQUENCE_OF.c	Wed May 11 20:06:23 2016 +0200
    24.3 @@ -0,0 +1,41 @@
    24.4 +/*-
    24.5 + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    24.6 + * Redistribution and modifications are permitted subject to BSD license.
    24.7 + */
    24.8 +#include <asn_internal.h>
    24.9 +#include <asn_SEQUENCE_OF.h>
   24.10 +
   24.11 +typedef A_SEQUENCE_OF(void) asn_sequence;
   24.12 +
   24.13 +void
   24.14 +asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free) {
   24.15 +	asn_sequence *as = (asn_sequence *)asn_sequence_of_x;
   24.16 +
   24.17 +	if(as) {
   24.18 +		void *ptr;
   24.19 +		int n;
   24.20 +
   24.21 +		if(number < 0 || number >= as->count)
   24.22 +			return;	/* Nothing to delete */
   24.23 +
   24.24 +		if(_do_free && as->free) {
   24.25 +			ptr = as->array[number];
   24.26 +		} else {
   24.27 +			ptr = 0;
   24.28 +		}
   24.29 +
   24.30 +		/*
   24.31 +		 * Shift all elements to the left to hide the gap.
   24.32 +		 */
   24.33 +		--as->count;
   24.34 +		for(n = number; n < as->count; n++)
   24.35 +			as->array[n] = as->array[n+1];
   24.36 +
   24.37 +		/*
   24.38 +		 * Invoke the third-party function only when the state
   24.39 +		 * of the parent structure is consistent.
   24.40 +		 */
   24.41 +		if(ptr) as->free(ptr);
   24.42 +	}
   24.43 +}
   24.44 +
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/asn.1/asn_SEQUENCE_OF.h	Wed May 11 20:06:23 2016 +0200
    25.3 @@ -0,0 +1,52 @@
    25.4 +/*-
    25.5 + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    25.6 + * Redistribution and modifications are permitted subject to BSD license.
    25.7 + */
    25.8 +#ifndef	ASN_SEQUENCE_OF_H
    25.9 +#define	ASN_SEQUENCE_OF_H
   25.10 +
   25.11 +#include <asn_SET_OF.h>
   25.12 +
   25.13 +#ifdef __cplusplus
   25.14 +extern "C" {
   25.15 +#endif
   25.16 +
   25.17 +/*
   25.18 + * SEQUENCE OF is the same as SET OF with a tiny difference:
   25.19 + * the delete operation preserves the initial order of elements
   25.20 + * and thus MAY operate in non-constant time.
   25.21 + */
   25.22 +#define	A_SEQUENCE_OF(type)	A_SET_OF(type)
   25.23 +
   25.24 +#define	ASN_SEQUENCE_ADD(headptr, ptr)		\
   25.25 +	asn_sequence_add((headptr), (ptr))
   25.26 +
   25.27 +/***********************************************
   25.28 + * Implementation of the SEQUENCE OF structure.
   25.29 + */
   25.30 +
   25.31 +#define	asn_sequence_add	asn_set_add
   25.32 +#define	asn_sequence_empty	asn_set_empty
   25.33 +
   25.34 +/*
   25.35 + * Delete the element from the set by its number (base 0).
   25.36 + * This is NOT a constant-time operation.
   25.37 + * The order of elements is preserved.
   25.38 + * If _do_free is given AND the (*free) is initialized, the element
   25.39 + * will be freed using the custom (*free) function as well.
   25.40 + */
   25.41 +void asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free);
   25.42 +
   25.43 +/*
   25.44 + * Cope with different conversions requirements to/from void in C and C++.
   25.45 + * This is mostly useful for support library.
   25.46 + */
   25.47 +typedef A_SEQUENCE_OF(void) asn_anonymous_sequence_;
   25.48 +#define _A_SEQUENCE_FROM_VOID(ptr)	((asn_anonymous_sequence_ *)(ptr))
   25.49 +#define _A_CSEQUENCE_FROM_VOID(ptr) 	((const asn_anonymous_sequence_ *)(ptr))
   25.50 +
   25.51 +#ifdef __cplusplus
   25.52 +}
   25.53 +#endif
   25.54 +
   25.55 +#endif	/* ASN_SEQUENCE_OF_H */
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/asn.1/asn_SET_OF.c	Wed May 11 20:06:23 2016 +0200
    26.3 @@ -0,0 +1,88 @@
    26.4 +/*-
    26.5 + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    26.6 + * Redistribution and modifications are permitted subject to BSD license.
    26.7 + */
    26.8 +#include <asn_internal.h>
    26.9 +#include <asn_SET_OF.h>
   26.10 +#include <errno.h>
   26.11 +
   26.12 +/*
   26.13 + * Add another element into the set.
   26.14 + */
   26.15 +int
   26.16 +asn_set_add(void *asn_set_of_x, void *ptr) {
   26.17 +	asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x);
   26.18 +
   26.19 +	if(as == 0 || ptr == 0) {
   26.20 +		errno = EINVAL;		/* Invalid arguments */
   26.21 +		return -1;
   26.22 +	}
   26.23 +
   26.24 +	/*
   26.25 +	 * Make sure there's enough space to insert an element.
   26.26 +	 */
   26.27 +	if(as->count == as->size) {
   26.28 +		int _newsize = as->size ? (as->size << 1) : 4;
   26.29 +		void *_new_arr;
   26.30 +		_new_arr = REALLOC(as->array, _newsize * sizeof(as->array[0]));
   26.31 +		if(_new_arr) {
   26.32 +			as->array = (void **)_new_arr;
   26.33 +			as->size = _newsize;
   26.34 +		} else {
   26.35 +			/* ENOMEM */
   26.36 +			return -1;
   26.37 +		}
   26.38 +	}
   26.39 +
   26.40 +	as->array[as->count++] = ptr;
   26.41 +
   26.42 +	return 0;
   26.43 +}
   26.44 +
   26.45 +void
   26.46 +asn_set_del(void *asn_set_of_x, int number, int _do_free) {
   26.47 +	asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x);
   26.48 +
   26.49 +	if(as) {
   26.50 +		void *ptr;
   26.51 +		if(number < 0 || number >= as->count)
   26.52 +			return;
   26.53 +
   26.54 +		if(_do_free && as->free) {
   26.55 +			ptr = as->array[number];
   26.56 +		} else {
   26.57 +			ptr = 0;
   26.58 +		}
   26.59 +
   26.60 +		as->array[number] = as->array[--as->count];
   26.61 +
   26.62 +		/*
   26.63 +		 * Invoke the third-party function only when the state
   26.64 +		 * of the parent structure is consistent.
   26.65 +		 */
   26.66 +		if(ptr) as->free(ptr);
   26.67 +	}
   26.68 +}
   26.69 +
   26.70 +/*
   26.71 + * Free the contents of the set, do not free the set itself.
   26.72 + */
   26.73 +void
   26.74 +asn_set_empty(void *asn_set_of_x) {
   26.75 +	asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x);
   26.76 +
   26.77 +	if(as) {
   26.78 +		if(as->array) {
   26.79 +			if(as->free) {
   26.80 +				while(as->count--)
   26.81 +					as->free(as->array[as->count]);
   26.82 +			}
   26.83 +			FREEMEM(as->array);
   26.84 +			as->array = 0;
   26.85 +		}
   26.86 +		as->count = 0;
   26.87 +		as->size = 0;
   26.88 +	}
   26.89 +
   26.90 +}
   26.91 +
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/asn.1/asn_SET_OF.h	Wed May 11 20:06:23 2016 +0200
    27.3 @@ -0,0 +1,62 @@
    27.4 +/*-
    27.5 + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    27.6 + * Redistribution and modifications are permitted subject to BSD license.
    27.7 + */
    27.8 +#ifndef	ASN_SET_OF_H
    27.9 +#define	ASN_SET_OF_H
   27.10 +
   27.11 +#ifdef __cplusplus
   27.12 +extern "C" {
   27.13 +#endif
   27.14 +
   27.15 +#define	A_SET_OF(type)					\
   27.16 +	struct {					\
   27.17 +		type **array;				\
   27.18 +		int count;	/* Meaningful size */	\
   27.19 +		int size;	/* Allocated size */	\
   27.20 +		void (*free)(type *);			\
   27.21 +	}
   27.22 +
   27.23 +#define	ASN_SET_ADD(headptr, ptr)		\
   27.24 +	asn_set_add((headptr), (ptr))
   27.25 +
   27.26 +/*******************************************
   27.27 + * Implementation of the SET OF structure.
   27.28 + */
   27.29 +
   27.30 +/*
   27.31 + * Add another structure into the set by its pointer.
   27.32 + * RETURN VALUES:
   27.33 + * 0 for success and -1/errno for failure.
   27.34 + */
   27.35 +int  asn_set_add(void *asn_set_of_x, void *ptr);
   27.36 +
   27.37 +/*
   27.38 + * Delete the element from the set by its number (base 0).
   27.39 + * This is a constant-time operation. The order of elements before the
   27.40 + * deleted ones is guaranteed, the order of elements after the deleted
   27.41 + * one is NOT guaranteed.
   27.42 + * If _do_free is given AND the (*free) is initialized, the element
   27.43 + * will be freed using the custom (*free) function as well.
   27.44 + */
   27.45 +void asn_set_del(void *asn_set_of_x, int number, int _do_free);
   27.46 +
   27.47 +/*
   27.48 + * Empty the contents of the set. Will free the elements, if (*free) is given.
   27.49 + * Will NOT free the set itself.
   27.50 + */
   27.51 +void asn_set_empty(void *asn_set_of_x);
   27.52 +
   27.53 +/*
   27.54 + * Cope with different conversions requirements to/from void in C and C++.
   27.55 + * This is mostly useful for support library.
   27.56 + */
   27.57 +typedef A_SET_OF(void) asn_anonymous_set_;
   27.58 +#define _A_SET_FROM_VOID(ptr)		((asn_anonymous_set_ *)(ptr))
   27.59 +#define _A_CSET_FROM_VOID(ptr)		((const asn_anonymous_set_ *)(ptr))
   27.60 +
   27.61 +#ifdef __cplusplus
   27.62 +}
   27.63 +#endif
   27.64 +
   27.65 +#endif	/* ASN_SET_OF_H */
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/asn.1/asn_application.h	Wed May 11 20:06:23 2016 +0200
    28.3 @@ -0,0 +1,47 @@
    28.4 +/*-
    28.5 + * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
    28.6 + * Redistribution and modifications are permitted subject to BSD license.
    28.7 + */
    28.8 +/*
    28.9 + * Application-level ASN.1 callbacks.
   28.10 + */
   28.11 +#ifndef	_ASN_APPLICATION_H_
   28.12 +#define	_ASN_APPLICATION_H_
   28.13 +
   28.14 +#include "asn_system.h"		/* for platform-dependent types */
   28.15 +#include "asn_codecs.h"		/* for ASN.1 codecs specifics */
   28.16 +
   28.17 +#ifdef __cplusplus
   28.18 +extern "C" {
   28.19 +#endif
   28.20 +
   28.21 +/*
   28.22 + * Generic type of an application-defined callback to return various
   28.23 + * types of data to the application.
   28.24 + * EXPECTED RETURN VALUES:
   28.25 + *  -1: Failed to consume bytes. Abort the mission.
   28.26 + * Non-negative return values indicate success, and ignored.
   28.27 + */
   28.28 +typedef int (asn_app_consume_bytes_f)(const void *buffer, size_t size,
   28.29 +	void *application_specific_key);
   28.30 +
   28.31 +/*
   28.32 + * A callback of this type is called whenever constraint validation fails
   28.33 + * on some ASN.1 type. See "constraints.h" for more details on constraint
   28.34 + * validation.
   28.35 + * This callback specifies a descriptor of the ASN.1 type which failed
   28.36 + * the constraint check, as well as human readable message on what
   28.37 + * particular constraint has failed.
   28.38 + */
   28.39 +typedef void (asn_app_constraint_failed_f)(void *application_specific_key,
   28.40 +	struct asn_TYPE_descriptor_s *type_descriptor_which_failed,
   28.41 +	const void *structure_which_failed_ptr,
   28.42 +	const char *error_message_format, ...) GCC_PRINTFLIKE(4, 5);
   28.43 +
   28.44 +#ifdef __cplusplus
   28.45 +}
   28.46 +#endif
   28.47 +
   28.48 +#include "constr_TYPE.h"	/* for asn_TYPE_descriptor_t */
   28.49 +
   28.50 +#endif	/* _ASN_APPLICATION_H_ */
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/asn.1/asn_codecs.h	Wed May 11 20:06:23 2016 +0200
    29.3 @@ -0,0 +1,109 @@
    29.4 +/*-
    29.5 + * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
    29.6 + * All rights reserved.
    29.7 + * Redistribution and modifications are permitted subject to BSD license.
    29.8 + */
    29.9 +#ifndef	_ASN_CODECS_H_
   29.10 +#define	_ASN_CODECS_H_
   29.11 +
   29.12 +#ifdef __cplusplus
   29.13 +extern "C" {
   29.14 +#endif
   29.15 +
   29.16 +struct asn_TYPE_descriptor_s;	/* Forward declaration */
   29.17 +
   29.18 +/*
   29.19 + * This structure defines a set of parameters that may be passed
   29.20 + * to every ASN.1 encoder or decoder function.
   29.21 + * WARNING: if max_stack_size member is set, and you are calling the
   29.22 + *   function pointers of the asn_TYPE_descriptor_t directly,
   29.23 + *   this structure must be ALLOCATED ON THE STACK!
   29.24 + *   If you can't always satisfy this requirement, use ber_decode(),
   29.25 + *   xer_decode() and uper_decode() functions instead.
   29.26 + */
   29.27 +typedef struct asn_codec_ctx_s {
   29.28 +	/*
   29.29 +	 * Limit the decoder routines to use no (much) more stack than a given
   29.30 +	 * number of bytes. Most of decoders are stack-based, and this
   29.31 +	 * would protect against stack overflows if the number of nested
   29.32 +	 * encodings is high.
   29.33 +	 * The OCTET STRING, BIT STRING and ANY BER decoders are heap-based,
   29.34 +	 * and are safe from this kind of overflow.
   29.35 +	 * A value from getrlimit(RLIMIT_STACK) may be used to initialize
   29.36 +	 * this variable. Be careful in multithreaded environments, as the
   29.37 +	 * stack size is rather limited.
   29.38 +	 */
   29.39 +	size_t  max_stack_size; /* 0 disables stack bounds checking */
   29.40 +} asn_codec_ctx_t;
   29.41 +
   29.42 +/*
   29.43 + * Type of the return value of the encoding functions (der_encode, xer_encode).
   29.44 + */
   29.45 +typedef struct asn_enc_rval_s {
   29.46 +	/*
   29.47 +	 * Number of bytes encoded.
   29.48 +	 * -1 indicates failure to encode the structure.
   29.49 +	 * In this case, the members below this one are meaningful.
   29.50 +	 */
   29.51 +	ssize_t encoded;
   29.52 +
   29.53 +	/*
   29.54 +	 * Members meaningful when (encoded == -1), for post mortem analysis.
   29.55 +	 */
   29.56 +
   29.57 +	/* Type which cannot be encoded */
   29.58 +	struct asn_TYPE_descriptor_s *failed_type;
   29.59 +
   29.60 +	/* Pointer to the structure of that type */
   29.61 +	void *structure_ptr;
   29.62 +} asn_enc_rval_t;
   29.63 +#define	_ASN_ENCODE_FAILED do {					\
   29.64 +	asn_enc_rval_t tmp_error;				\
   29.65 +	tmp_error.encoded = -1;					\
   29.66 +	tmp_error.failed_type = td;				\
   29.67 +	tmp_error.structure_ptr = sptr;				\
   29.68 +	ASN_DEBUG("Failed to encode element %s", td ? td->name : "");	\
   29.69 +	return tmp_error;					\
   29.70 +} while(0)
   29.71 +#define	_ASN_ENCODED_OK(rval) do {				\
   29.72 +	rval.structure_ptr = 0;					\
   29.73 +	rval.failed_type = 0;					\
   29.74 +	return rval;						\
   29.75 +} while(0)
   29.76 +
   29.77 +/*
   29.78 + * Type of the return value of the decoding functions (ber_decode, xer_decode)
   29.79 + * 
   29.80 + * Please note that the number of consumed bytes is ALWAYS meaningful,
   29.81 + * even if code==RC_FAIL. This is to indicate the number of successfully
   29.82 + * decoded bytes, hence providing a possibility to fail with more diagnostics
   29.83 + * (i.e., print the offending remainder of the buffer).
   29.84 + */
   29.85 +enum asn_dec_rval_code_e {
   29.86 +	RC_OK,		/* Decoded successfully */
   29.87 +	RC_WMORE,	/* More data expected, call again */
   29.88 +	RC_FAIL		/* Failure to decode data */
   29.89 +};
   29.90 +typedef struct asn_dec_rval_s {
   29.91 +	enum asn_dec_rval_code_e code;	/* Result code */
   29.92 +	size_t consumed;		/* Number of bytes consumed */
   29.93 +} asn_dec_rval_t;
   29.94 +#define	_ASN_DECODE_FAILED do {					\
   29.95 +	asn_dec_rval_t tmp_error;				\
   29.96 +	tmp_error.code = RC_FAIL;				\
   29.97 +	tmp_error.consumed = 0;					\
   29.98 +	ASN_DEBUG("Failed to decode element %s", td ? td->name : "");	\
   29.99 +	return tmp_error;					\
  29.100 +} while(0)
  29.101 +#define	_ASN_DECODE_STARVED do {				\
  29.102 +	asn_dec_rval_t tmp_error;				\
  29.103 +	tmp_error.code = RC_WMORE;				\
  29.104 +	tmp_error.consumed = 0;					\
  29.105 +	return tmp_error;					\
  29.106 +} while(0)
  29.107 +
  29.108 +#ifdef __cplusplus
  29.109 +}
  29.110 +#endif
  29.111 +
  29.112 +#endif	/* _ASN_CODECS_H_ */
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/asn.1/asn_codecs_prim.c	Wed May 11 20:06:23 2016 +0200
    30.3 @@ -0,0 +1,312 @@
    30.4 +/*-
    30.5 + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    30.6 + * Redistribution and modifications are permitted subject to BSD license.
    30.7 + */
    30.8 +#include <asn_internal.h>
    30.9 +#include <asn_codecs_prim.h>
   30.10 +#include <errno.h>
   30.11 +
   30.12 +/*
   30.13 + * Decode an always-primitive type.
   30.14 + */
   30.15 +asn_dec_rval_t
   30.16 +ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
   30.17 +	asn_TYPE_descriptor_t *td,
   30.18 +	void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
   30.19 +	ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
   30.20 +	asn_dec_rval_t rval;
   30.21 +	ber_tlv_len_t length = 0; // =0 to avoid [incorrect] warning.
   30.22 +
   30.23 +	/*
   30.24 +	 * If the structure is not there, allocate it.
   30.25 +	 */
   30.26 +	if(st == NULL) {
   30.27 +		st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
   30.28 +		if(st == NULL) _ASN_DECODE_FAILED;
   30.29 +		*sptr = (void *)st;
   30.30 +	}
   30.31 +
   30.32 +	ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
   30.33 +		td->name, tag_mode);
   30.34 +
   30.35 +	/*
   30.36 +	 * Check tags and extract value length.
   30.37 +	 */
   30.38 +	rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
   30.39 +			tag_mode, 0, &length, 0);
   30.40 +	if(rval.code != RC_OK)
   30.41 +		return rval;
   30.42 +
   30.43 +	ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
   30.44 +
   30.45 +	/*
   30.46 +	 * Make sure we have this length.
   30.47 +	 */
   30.48 +	buf_ptr = ((const char *)buf_ptr) + rval.consumed;
   30.49 +	size -= rval.consumed;
   30.50 +	if(length > (ber_tlv_len_t)size) {
   30.51 +		rval.code = RC_WMORE;
   30.52 +		rval.consumed = 0;
   30.53 +		return rval;
   30.54 +	}
   30.55 +
   30.56 +	st->size = (int)length;
   30.57 +	/* The following better be optimized away. */
   30.58 +	if(sizeof(st->size) != sizeof(length)
   30.59 +			&& (ber_tlv_len_t)st->size != length) {
   30.60 +		st->size = 0;
   30.61 +		_ASN_DECODE_FAILED;
   30.62 +	}
   30.63 +
   30.64 +	st->buf = (uint8_t *)MALLOC(length + 1);
   30.65 +	if(!st->buf) {
   30.66 +		st->size = 0;
   30.67 +		_ASN_DECODE_FAILED;
   30.68 +	}
   30.69 +
   30.70 +	memcpy(st->buf, buf_ptr, length);
   30.71 +	st->buf[length] = '\0';		/* Just in case */
   30.72 +
   30.73 +	rval.code = RC_OK;
   30.74 +	rval.consumed += length;
   30.75 +
   30.76 +	ASN_DEBUG("Took %ld/%ld bytes to encode %s",
   30.77 +		(long)rval.consumed,
   30.78 +		(long)length, td->name);
   30.79 +
   30.80 +	return rval;
   30.81 +}
   30.82 +
   30.83 +/*
   30.84 + * Encode an always-primitive type using DER.
   30.85 + */
   30.86 +asn_enc_rval_t
   30.87 +der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr,
   30.88 +	int tag_mode, ber_tlv_tag_t tag,
   30.89 +	asn_app_consume_bytes_f *cb, void *app_key) {
   30.90 +	asn_enc_rval_t erval;
   30.91 +	ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
   30.92 +
   30.93 +	ASN_DEBUG("%s %s as a primitive type (tm=%d)",
   30.94 +		cb?"Encoding":"Estimating", td->name, tag_mode);
   30.95 +
   30.96 +	erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
   30.97 +		cb, app_key);
   30.98 +	ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
   30.99 +	if(erval.encoded == -1) {
  30.100 +		erval.failed_type = td;
  30.101 +		erval.structure_ptr = sptr;
  30.102 +		return erval;
  30.103 +	}
  30.104 +
  30.105 +	if(cb && st->buf) {
  30.106 +		if(cb(st->buf, st->size, app_key) < 0) {
  30.107 +			erval.encoded = -1;
  30.108 +			erval.failed_type = td;
  30.109 +			erval.structure_ptr = sptr;
  30.110 +			return erval;
  30.111 +		}
  30.112 +	} else {
  30.113 +		assert(st->buf || st->size == 0);
  30.114 +	}
  30.115 +
  30.116 +	erval.encoded += st->size;
  30.117 +	_ASN_ENCODED_OK(erval);
  30.118 +}
  30.119 +
  30.120 +void
  30.121 +ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
  30.122 +		int contents_only) {
  30.123 +	ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
  30.124 +
  30.125 +	if(!td || !sptr)
  30.126 +		return;
  30.127 +
  30.128 +	ASN_DEBUG("Freeing %s as a primitive type", td->name);
  30.129 +
  30.130 +	if(st->buf)
  30.131 +		FREEMEM(st->buf);
  30.132 +
  30.133 +	if(!contents_only)
  30.134 +		FREEMEM(st);
  30.135 +}
  30.136 +
  30.137 +
  30.138 +/*
  30.139 + * Local internal type passed around as an argument.
  30.140 + */
  30.141 +struct xdp_arg_s {
  30.142 +	asn_TYPE_descriptor_t *type_descriptor;
  30.143 +	void *struct_key;
  30.144 +	xer_primitive_body_decoder_f *prim_body_decoder;
  30.145 +	int decoded_something;
  30.146 +	int want_more;
  30.147 +};
  30.148 +
  30.149 +/*
  30.150 + * Since some kinds of primitive values can be encoded using value-specific
  30.151 + * tags (<MINUS-INFINITY>, <enum-element>, etc), the primitive decoder must
  30.152 + * be supplied with such tags to parse them as needed.
  30.153 + */
  30.154 +static int
  30.155 +xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
  30.156 +	struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
  30.157 +	enum xer_pbd_rval bret;
  30.158 +
  30.159 +	/*
  30.160 +	 * The chunk_buf is guaranteed to start at '<'.
  30.161 +	 */
  30.162 +	assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
  30.163 +
  30.164 +	/*
  30.165 +	 * Decoding was performed once already. Prohibit doing it again.
  30.166 +	 */
  30.167 +	if(arg->decoded_something)
  30.168 +		return -1;
  30.169 +
  30.170 +	bret = arg->prim_body_decoder(arg->type_descriptor,
  30.171 +		arg->struct_key, chunk_buf, chunk_size);
  30.172 +	switch(bret) {
  30.173 +	case XPBD_SYSTEM_FAILURE:
  30.174 +	case XPBD_DECODER_LIMIT:
  30.175 +	case XPBD_BROKEN_ENCODING:
  30.176 +		break;
  30.177 +	case XPBD_BODY_CONSUMED:
  30.178 +		/* Tag decoded successfully */
  30.179 +		arg->decoded_something = 1;
  30.180 +		/* Fall through */
  30.181 +	case XPBD_NOT_BODY_IGNORE:	/* Safe to proceed further */
  30.182 +		return 0;
  30.183 +	}
  30.184 +
  30.185 +	return -1;
  30.186 +}
  30.187 +
  30.188 +static ssize_t
  30.189 +xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
  30.190 +	struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
  30.191 +	enum xer_pbd_rval bret;
  30.192 +	size_t lead_wsp_size;
  30.193 +
  30.194 +	if(arg->decoded_something) {
  30.195 +		if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
  30.196 +			/*
  30.197 +			 * Example:
  30.198 +			 * "<INTEGER>123<!--/--> </INTEGER>"
  30.199 +			 *                      ^- chunk_buf position.
  30.200 +			 */
  30.201 +			return chunk_size;
  30.202 +		}
  30.203 +		/*
  30.204 +		 * Decoding was done once already. Prohibit doing it again.
  30.205 +		 */
  30.206 +		return -1;
  30.207 +	}
  30.208 +
  30.209 +	if(!have_more) {
  30.210 +		/*
  30.211 +		 * If we've received something like "1", we can't really
  30.212 +		 * tell whether it is really `1` or `123`, until we know
  30.213 +		 * that there is no more data coming.
  30.214 +		 * The have_more argument will be set to 1 once something
  30.215 +		 * like this is available to the caller of this callback:
  30.216 +		 * "1<tag_start..."
  30.217 +		 */
  30.218 +		arg->want_more = 1;
  30.219 +		return -1;
  30.220 +	}
  30.221 +
  30.222 +	lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size);
  30.223 +	chunk_buf = (const char *)chunk_buf + lead_wsp_size;
  30.224 +	chunk_size -= lead_wsp_size;
  30.225 +
  30.226 +	bret = arg->prim_body_decoder(arg->type_descriptor,
  30.227 +		arg->struct_key, chunk_buf, chunk_size);
  30.228 +	switch(bret) {
  30.229 +	case XPBD_SYSTEM_FAILURE:
  30.230 +	case XPBD_DECODER_LIMIT:
  30.231 +	case XPBD_BROKEN_ENCODING:
  30.232 +		break;
  30.233 +	case XPBD_BODY_CONSUMED:
  30.234 +		/* Tag decoded successfully */
  30.235 +		arg->decoded_something = 1;
  30.236 +		/* Fall through */
  30.237 +	case XPBD_NOT_BODY_IGNORE:	/* Safe to proceed further */
  30.238 +		return lead_wsp_size + chunk_size;
  30.239 +	}
  30.240 +
  30.241 +	return -1;
  30.242 +}
  30.243 +
  30.244 +
  30.245 +asn_dec_rval_t
  30.246 +xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
  30.247 +	asn_TYPE_descriptor_t *td,
  30.248 +	void **sptr,
  30.249 +	size_t struct_size,
  30.250 +	const char *opt_mname,
  30.251 +	const void *buf_ptr, size_t size,
  30.252 +	xer_primitive_body_decoder_f *prim_body_decoder
  30.253 +) {
  30.254 +	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
  30.255 +	asn_struct_ctx_t s_ctx;
  30.256 +	struct xdp_arg_s s_arg;
  30.257 +	asn_dec_rval_t rc;
  30.258 +
  30.259 +	/*
  30.260 +	 * Create the structure if does not exist.
  30.261 +	 */
  30.262 +	if(!*sptr) {
  30.263 +		*sptr = CALLOC(1, struct_size);
  30.264 +		if(!*sptr) _ASN_DECODE_FAILED;
  30.265 +	}
  30.266 +
  30.267 +	memset(&s_ctx, 0, sizeof(s_ctx));
  30.268 +	s_arg.type_descriptor = td;
  30.269 +	s_arg.struct_key = *sptr;
  30.270 +	s_arg.prim_body_decoder = prim_body_decoder;
  30.271 +	s_arg.decoded_something = 0;
  30.272 +	s_arg.want_more = 0;
  30.273 +
  30.274 +	rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
  30.275 +		xml_tag, buf_ptr, size,
  30.276 +		xer_decode__unexpected_tag, xer_decode__primitive_body);
  30.277 +	switch(rc.code) {
  30.278 +	case RC_OK:
  30.279 +		if(!s_arg.decoded_something) {
  30.280 +			char ch;
  30.281 +			ASN_DEBUG("Primitive body is not recognized, "
  30.282 +				"supplying empty one");
  30.283 +			/*
  30.284 +			 * Decoding opportunity has come and gone.
  30.285 +			 * Where's the result?
  30.286 +			 * Try to feed with empty body, see if it eats it.
  30.287 +			 */
  30.288 +			if(prim_body_decoder(s_arg.type_descriptor,
  30.289 +				s_arg.struct_key, &ch, 0)
  30.290 +					!= XPBD_BODY_CONSUMED) {
  30.291 +				/*
  30.292 +				 * This decoder does not like empty stuff.
  30.293 +				 */
  30.294 +				_ASN_DECODE_FAILED;
  30.295 +			}
  30.296 +		}
  30.297 +		break;
  30.298 +	case RC_WMORE:
  30.299 +		/*
  30.300 +		 * Redo the whole thing later.
  30.301 +		 * We don't have a context to save intermediate parsing state.
  30.302 +		 */
  30.303 +		rc.consumed = 0;
  30.304 +		break;
  30.305 +	case RC_FAIL:
  30.306 +		rc.consumed = 0;
  30.307 +		if(s_arg.want_more)
  30.308 +			rc.code = RC_WMORE;
  30.309 +		else
  30.310 +			_ASN_DECODE_FAILED;
  30.311 +		break;
  30.312 +	}
  30.313 +	return rc;
  30.314 +}
  30.315 +
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/asn.1/asn_codecs_prim.h	Wed May 11 20:06:23 2016 +0200
    31.3 @@ -0,0 +1,53 @@
    31.4 +/*-
    31.5 + * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    31.6 + * Redistribution and modifications are permitted subject to BSD license.
    31.7 + */
    31.8 +#ifndef	ASN_CODECS_PRIM_H
    31.9 +#define	ASN_CODECS_PRIM_H
   31.10 +
   31.11 +#include <asn_application.h>
   31.12 +
   31.13 +#ifdef __cplusplus
   31.14 +extern "C" {
   31.15 +#endif
   31.16 +
   31.17 +typedef struct ASN__PRIMITIVE_TYPE_s {
   31.18 +	uint8_t *buf;	/* Buffer with consecutive primitive encoding bytes */
   31.19 +	int size;	/* Size of the buffer */
   31.20 +} ASN__PRIMITIVE_TYPE_t;	/* Do not use this type directly! */
   31.21 +
   31.22 +asn_struct_free_f ASN__PRIMITIVE_TYPE_free;
   31.23 +ber_type_decoder_f ber_decode_primitive;
   31.24 +der_type_encoder_f der_encode_primitive;
   31.25 +
   31.26 +/*
   31.27 + * A callback specification for the xer_decode_primitive() function below.
   31.28 + */
   31.29 +enum xer_pbd_rval {
   31.30 +	XPBD_SYSTEM_FAILURE,	/* System failure (memory shortage, etc) */
   31.31 +	XPBD_DECODER_LIMIT,	/* Hit some decoder limitation or deficiency */
   31.32 +	XPBD_BROKEN_ENCODING,	/* Encoding of a primitive body is broken */
   31.33 +	XPBD_NOT_BODY_IGNORE,	/* Not a body format, but safe to ignore */
   31.34 +	XPBD_BODY_CONSUMED	/* Body is recognized and consumed */
   31.35 +};
   31.36 +typedef enum xer_pbd_rval (xer_primitive_body_decoder_f)
   31.37 +	(asn_TYPE_descriptor_t *td, void *struct_ptr,
   31.38 +		const void *chunk_buf, size_t chunk_size);
   31.39 +
   31.40 +/*
   31.41 + * Specific function to decode simple primitive types.
   31.42 + * Also see xer_decode_general() in xer_decoder.h
   31.43 + */
   31.44 +asn_dec_rval_t xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
   31.45 +	asn_TYPE_descriptor_t *type_descriptor,
   31.46 +	void **struct_ptr, size_t struct_size,
   31.47 +	const char *opt_mname,
   31.48 +	const void *buf_ptr, size_t size,
   31.49 +	xer_primitive_body_decoder_f *prim_body_decoder
   31.50 +);
   31.51 +
   31.52 +#ifdef __cplusplus
   31.53 +}
   31.54 +#endif
   31.55 +
   31.56 +#endif	/* ASN_CODECS_PRIM_H */
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/asn.1/asn_internal.h	Wed May 11 20:06:23 2016 +0200
    32.3 @@ -0,0 +1,126 @@
    32.4 +/*-
    32.5 + * Copyright (c) 2003, 2004, 2005, 2007 Lev Walkin <vlm@lionet.info>.
    32.6 + * All rights reserved.
    32.7 + * Redistribution and modifications are permitted subject to BSD license.
    32.8 + */
    32.9 +/*
   32.10 + * Declarations internally useful for the ASN.1 support code.
   32.11 + */
   32.12 +#ifndef	_ASN_INTERNAL_H_
   32.13 +#define	_ASN_INTERNAL_H_
   32.14 +
   32.15 +#include "asn_application.h"	/* Application-visible API */
   32.16 +
   32.17 +#ifndef	__NO_ASSERT_H__		/* Include assert.h only for internal use. */
   32.18 +#include <assert.h>		/* for assert() macro */
   32.19 +#endif
   32.20 +
   32.21 +#ifdef	__cplusplus
   32.22 +extern "C" {
   32.23 +#endif
   32.24 +
   32.25 +/* Environment version might be used to avoid running with the old library */
   32.26 +#define	ASN1C_ENVIRONMENT_VERSION	923	/* Compile-time version */
   32.27 +int get_asn1c_environment_version(void);	/* Run-time version */
   32.28 +
   32.29 +#define	CALLOC(nmemb, size)	calloc(nmemb, size)
   32.30 +#define	MALLOC(size)		malloc(size)
   32.31 +#define	REALLOC(oldptr, size)	realloc(oldptr, size)
   32.32 +#define	FREEMEM(ptr)		free(ptr)
   32.33 +
   32.34 +#define	asn_debug_indent	0
   32.35 +#define ASN_DEBUG_INDENT_ADD(i) do{}while(0)
   32.36 +
   32.37 +/*
   32.38 + * A macro for debugging the ASN.1 internals.
   32.39 + * You may enable or override it.
   32.40 + */
   32.41 +#ifndef	ASN_DEBUG	/* If debugging code is not defined elsewhere... */
   32.42 +#if	EMIT_ASN_DEBUG == 1	/* And it was asked to emit this code... */
   32.43 +#ifdef	__GNUC__
   32.44 +#ifdef	ASN_THREAD_SAFE
   32.45 +/* Thread safety requires sacrifice in output indentation:
   32.46 + * Retain empty definition of ASN_DEBUG_INDENT_ADD. */
   32.47 +#else	/* !ASN_THREAD_SAFE */
   32.48 +#undef  ASN_DEBUG_INDENT_ADD
   32.49 +#undef  asn_debug_indent
   32.50 +int asn_debug_indent;
   32.51 +#define ASN_DEBUG_INDENT_ADD(i) do { asn_debug_indent += i; } while(0)
   32.52 +#endif	/* ASN_THREAD_SAFE */
   32.53 +#define	ASN_DEBUG(fmt, args...)	do {			\
   32.54 +		int adi = asn_debug_indent;		\
   32.55 +		while(adi--) fprintf(stderr, " ");	\
   32.56 +		fprintf(stderr, fmt, ##args);		\
   32.57 +		fprintf(stderr, " (%s:%d)\n",		\
   32.58 +			__FILE__, __LINE__);		\
   32.59 +	} while(0)
   32.60 +#else	/* !__GNUC__ */
   32.61 +void ASN_DEBUG_f(const char *fmt, ...);
   32.62 +#define	ASN_DEBUG	ASN_DEBUG_f
   32.63 +#endif	/* __GNUC__ */
   32.64 +#else	/* EMIT_ASN_DEBUG != 1 */
   32.65 +static inline void ASN_DEBUG(const char *fmt, ...) { (void)fmt; }
   32.66 +#endif	/* EMIT_ASN_DEBUG */
   32.67 +#endif	/* ASN_DEBUG */
   32.68 +
   32.69 +/*
   32.70 + * Invoke the application-supplied callback and fail, if something is wrong.
   32.71 + */
   32.72 +#define	__ASN_E_cbc(buf, size)	(cb((buf), (size), app_key) < 0)
   32.73 +#define	_ASN_E_CALLBACK(foo)	do {					\
   32.74 +		if(foo)	goto cb_failed;					\
   32.75 +	} while(0)
   32.76 +#define	_ASN_CALLBACK(buf, size)					\
   32.77 +	_ASN_E_CALLBACK(__ASN_E_cbc(buf, size))
   32.78 +#define	_ASN_CALLBACK2(buf1, size1, buf2, size2)			\
   32.79 +	_ASN_E_CALLBACK(__ASN_E_cbc(buf1, size1) || __ASN_E_cbc(buf2, size2))
   32.80 +#define	_ASN_CALLBACK3(buf1, size1, buf2, size2, buf3, size3)		\
   32.81 +	_ASN_E_CALLBACK(__ASN_E_cbc(buf1, size1)			\
   32.82 +		|| __ASN_E_cbc(buf2, size2)				\
   32.83 +		|| __ASN_E_cbc(buf3, size3))
   32.84 +
   32.85 +#define	_i_ASN_TEXT_INDENT(nl, level) do {				\
   32.86 +	int __level = (level);						\
   32.87 +	int __nl = ((nl) != 0);						\
   32.88 +	int __i;							\
   32.89 +	if(__nl) _ASN_CALLBACK("\n", 1);				\
   32.90 +	if(__level < 0) __level = 0;					\
   32.91 +	for(__i = 0; __i < __level; __i++)				\
   32.92 +		_ASN_CALLBACK("    ", 4);				\
   32.93 +	er.encoded += __nl + 4 * __level;				\
   32.94 +} while(0)
   32.95 +
   32.96 +#define	_i_INDENT(nl)	do {						\
   32.97 +	int __i;							\
   32.98 +	if((nl) && cb("\n", 1, app_key) < 0) return -1;			\
   32.99 +	for(__i = 0; __i < ilevel; __i++)				\
  32.100 +		if(cb("    ", 4, app_key) < 0) return -1;		\
  32.101 +} while(0)
  32.102 +
  32.103 +/*
  32.104 + * Check stack against overflow, if limit is set.
  32.105 + */
  32.106 +#define	_ASN_DEFAULT_STACK_MAX	(30000)
  32.107 +static inline int
  32.108 +_ASN_STACK_OVERFLOW_CHECK(asn_codec_ctx_t *ctx) {
  32.109 +	if(ctx && ctx->max_stack_size) {
  32.110 +
  32.111 +		/* ctx MUST be allocated on the stack */
  32.112 +		ptrdiff_t usedstack = ((char *)ctx - (char *)&ctx);
  32.113 +		if(usedstack > 0) usedstack = -usedstack; /* grows up! */
  32.114 +
  32.115 +		/* double negative required to avoid int wrap-around */
  32.116 +		if(usedstack < -(ptrdiff_t)ctx->max_stack_size) {
  32.117 +			ASN_DEBUG("Stack limit %ld reached",
  32.118 +				(long)ctx->max_stack_size);
  32.119 +			return -1;
  32.120 +		}
  32.121 +	}
  32.122 +	return 0;
  32.123 +}
  32.124 +
  32.125 +#ifdef	__cplusplus
  32.126 +}
  32.127 +#endif
  32.128 +
  32.129 +#endif	/* _ASN_INTERNAL_H_ */
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/asn.1/asn_system.h	Wed May 11 20:06:23 2016 +0200
    33.3 @@ -0,0 +1,129 @@
    33.4 +/*-
    33.5 + * Copyright (c) 2003, 2004, 2007 Lev Walkin <vlm@lionet.info>.
    33.6 + * All rights reserved.
    33.7 + * Redistribution and modifications are permitted subject to BSD license.
    33.8 + */
    33.9 +/*
   33.10 + * Miscellaneous system-dependent types.
   33.11 + */
   33.12 +#ifndef	_ASN_SYSTEM_H_
   33.13 +#define	_ASN_SYSTEM_H_
   33.14 +
   33.15 +#ifdef	HAVE_CONFIG_H
   33.16 +#include "config.h"
   33.17 +#endif
   33.18 +
   33.19 +#include <stdio.h>	/* For snprintf(3) */
   33.20 +#include <stdlib.h>	/* For *alloc(3) */
   33.21 +#include <string.h>	/* For memcpy(3) */
   33.22 +#include <sys/types.h>	/* For size_t */
   33.23 +#include <limits.h>	/* For LONG_MAX */
   33.24 +#include <stdarg.h>	/* For va_start */
   33.25 +#include <stddef.h>	/* for offsetof and ptrdiff_t */
   33.26 +
   33.27 +#ifdef	_WIN32
   33.28 +
   33.29 +#include <malloc.h>
   33.30 +#define	 snprintf	_snprintf
   33.31 +#define	 vsnprintf	_vsnprintf
   33.32 +
   33.33 +/* To avoid linking with ws2_32.lib, here's the definition of ntohl() */
   33.34 +#define sys_ntohl(l)	((((l) << 24)  & 0xff000000)	\
   33.35 +			| (((l) << 8) & 0xff0000)	\
   33.36 +			| (((l) >> 8)  & 0xff00)	\
   33.37 +			| ((l >> 24) & 0xff))
   33.38 +
   33.39 +#ifdef _MSC_VER			/* MSVS.Net */
   33.40 +#ifndef __cplusplus
   33.41 +#define inline __inline
   33.42 +#endif
   33.43 +#ifndef	ASSUMESTDTYPES	/* Standard types have been defined elsewhere */
   33.44 +#define	ssize_t		SSIZE_T
   33.45 +typedef	char		int8_t;
   33.46 +typedef	short		int16_t;
   33.47 +typedef	int		int32_t;
   33.48 +typedef	unsigned char	uint8_t;
   33.49 +typedef	unsigned short	uint16_t;
   33.50 +typedef	unsigned int	uint32_t;
   33.51 +#endif	/* ASSUMESTDTYPES */
   33.52 +#define WIN32_LEAN_AND_MEAN
   33.53 +#include <windows.h>
   33.54 +#include <float.h>
   33.55 +#define isnan _isnan
   33.56 +#define finite _finite
   33.57 +#define copysign _copysign
   33.58 +#define	ilogb	_logb
   33.59 +#else	/* !_MSC_VER */
   33.60 +#include <stdint.h>
   33.61 +#endif	/* _MSC_VER */
   33.62 +
   33.63 +#else	/* !_WIN32 */
   33.64 +
   33.65 +#if defined(__vxworks)
   33.66 +#include <types/vxTypes.h>
   33.67 +#else	/* !defined(__vxworks) */
   33.68 +
   33.69 +#include <inttypes.h>	/* C99 specifies this file */
   33.70 +/*
   33.71 + * 1. Earlier FreeBSD version didn't have <stdint.h>,
   33.72 + * but <inttypes.h> was present.
   33.73 + * 2. Sun Solaris requires <alloca.h> for alloca(3),
   33.74 + * but does not have <stdint.h>.
   33.75 + */
   33.76 +#if	(!defined(__FreeBSD__) || !defined(_SYS_INTTYPES_H_))
   33.77 +#if	defined(sun)
   33.78 +#include <alloca.h>	/* For alloca(3) */
   33.79 +#include <ieeefp.h>	/* for finite(3) */
   33.80 +#elif	defined(__hpux)
   33.81 +#ifdef	__GNUC__
   33.82 +#include <alloca.h>	/* For alloca(3) */
   33.83 +#else	/* !__GNUC__ */
   33.84 +#define inline
   33.85 +#endif	/* __GNUC__ */
   33.86 +#else
   33.87 +#include <stdint.h>	/* SUSv2+ and C99 specify this file, for uintXX_t */
   33.88 +#endif	/* defined(sun) */
   33.89 +#endif
   33.90 +
   33.91 +#include <netinet/in.h> /* for ntohl() */
   33.92 +#define	sys_ntohl(foo)	ntohl(foo)
   33.93 +
   33.94 +#endif	/* defined(__vxworks) */
   33.95 +
   33.96 +#endif	/* _WIN32 */
   33.97 +
   33.98 +#if	__GNUC__ >= 3
   33.99 +#ifndef	GCC_PRINTFLIKE
  33.100 +#define	GCC_PRINTFLIKE(fmt,var)	__attribute__((format(printf,fmt,var)))
  33.101 +#endif
  33.102 +#ifndef	GCC_NOTUSED
  33.103 +#define	GCC_NOTUSED		__attribute__((unused))
  33.104 +#endif
  33.105 +#else
  33.106 +#ifndef	GCC_PRINTFLIKE
  33.107 +#define	GCC_PRINTFLIKE(fmt,var)	/* nothing */
  33.108 +#endif
  33.109 +#ifndef	GCC_NOTUSED
  33.110 +#define	GCC_NOTUSED
  33.111 +#endif
  33.112 +#endif
  33.113 +
  33.114 +/* Figure out if thread safety is requested */
  33.115 +#if !defined(ASN_THREAD_SAFE) && (defined(THREAD_SAFE) || defined(_REENTRANT))
  33.116 +#define	ASN_THREAD_SAFE
  33.117 +#endif	/* Thread safety */
  33.118 +
  33.119 +#ifndef	offsetof	/* If not defined by <stddef.h> */
  33.120 +#define	offsetof(s, m)	((ptrdiff_t)&(((s *)0)->m) - (ptrdiff_t)((s *)0))
  33.121 +#endif	/* offsetof */
  33.122 +
  33.123 +#ifndef	MIN		/* Suitable for comparing primitive types (integers) */
  33.124 +#if defined(__GNUC__)
  33.125 +#define	MIN(a,b)	({ __typeof a _a = a; __typeof b _b = b;	\
  33.126 +	((_a)<(_b)?(_a):(_b)); })
  33.127 +#else	/* !__GNUC__ */
  33.128 +#define	MIN(a,b)	((a)<(b)?(a):(b))	/* Unsafe variant */
  33.129 +#endif /* __GNUC__ */
  33.130 +#endif	/* MIN */
  33.131 +
  33.132 +#endif	/* _ASN_SYSTEM_H_ */
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/asn.1/ber_decoder.c	Wed May 11 20:06:23 2016 +0200
    34.3 @@ -0,0 +1,283 @@
    34.4 +/*-
    34.5 + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    34.6 + * Redistribution and modifications are permitted subject to BSD license.
    34.7 + */
    34.8 +#include <asn_internal.h>
    34.9 +
   34.10 +#undef	ADVANCE
   34.11 +#define	ADVANCE(num_bytes)	do {					\
   34.12 +		size_t num = num_bytes;					\
   34.13 +		ptr = ((const char *)ptr) + num;			\
   34.14 +		size -= num;						\
   34.15 +		consumed_myself += num;					\
   34.16 +	} while(0)
   34.17 +#undef	RETURN
   34.18 +#define	RETURN(_code)	do {						\
   34.19 +		asn_dec_rval_t rval;					\
   34.20 +		rval.code = _code;					\
   34.21 +		if(opt_ctx) opt_ctx->step = step; /* Save context */	\
   34.22 +		if(_code == RC_OK || opt_ctx)				\
   34.23 +			rval.consumed = consumed_myself;		\
   34.24 +		else							\
   34.25 +			rval.consumed = 0;	/* Context-free */	\
   34.26 +		return rval;						\
   34.27 +	} while(0)
   34.28 +
   34.29 +/*
   34.30 + * The BER decoder of any type.
   34.31 + */
   34.32 +asn_dec_rval_t
   34.33 +ber_decode(asn_codec_ctx_t *opt_codec_ctx,
   34.34 +	asn_TYPE_descriptor_t *type_descriptor,
   34.35 +	void **struct_ptr, const void *ptr, size_t size) {
   34.36 +	asn_codec_ctx_t s_codec_ctx;
   34.37 +
   34.38 +	/*
   34.39 +	 * Stack checker requires that the codec context
   34.40 +	 * must be allocated on the stack.
   34.41 +	 */
   34.42 +	if(opt_codec_ctx) {
   34.43 +		if(opt_codec_ctx->max_stack_size) {
   34.44 +			s_codec_ctx = *opt_codec_ctx;
   34.45 +			opt_codec_ctx = &s_codec_ctx;
   34.46 +		}
   34.47 +	} else {
   34.48 +		/* If context is not given, be security-conscious anyway */
   34.49 +		memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
   34.50 +		s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX;
   34.51 +		opt_codec_ctx = &s_codec_ctx;
   34.52 +	}
   34.53 +
   34.54 +	/*
   34.55 +	 * Invoke type-specific decoder.
   34.56 +	 */
   34.57 +	return type_descriptor->ber_decoder(opt_codec_ctx, type_descriptor,
   34.58 +		struct_ptr,	/* Pointer to the destination structure */
   34.59 +		ptr, size,	/* Buffer and its size */
   34.60 +		0		/* Default tag mode is 0 */
   34.61 +		);
   34.62 +}
   34.63 +
   34.64 +/*
   34.65 + * Check the set of <TL<TL<TL...>>> tags matches the definition.
   34.66 + */
   34.67 +asn_dec_rval_t
   34.68 +ber_check_tags(asn_codec_ctx_t *opt_codec_ctx,
   34.69 +		asn_TYPE_descriptor_t *td, asn_struct_ctx_t *opt_ctx,
   34.70 +		const void *ptr, size_t size, int tag_mode, int last_tag_form,
   34.71 +		ber_tlv_len_t *last_length, int *opt_tlv_form) {
   34.72 +	ssize_t consumed_myself = 0;
   34.73 +	ssize_t tag_len;
   34.74 +	ssize_t len_len;
   34.75 +	ber_tlv_tag_t tlv_tag;
   34.76 +	ber_tlv_len_t tlv_len;
   34.77 +	ber_tlv_len_t limit_len = -1;
   34.78 +	int expect_00_terminators = 0;
   34.79 +	int tlv_constr = -1;	/* If CHOICE, opt_tlv_form is not given */
   34.80 +	int step = opt_ctx ? opt_ctx->step : 0;	/* Where we left previously */
   34.81 +	int tagno;
   34.82 +
   34.83 +	/*
   34.84 +	 * Make sure we didn't exceed the maximum stack size.
   34.85 +	 */
   34.86 +	if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
   34.87 +		RETURN(RC_FAIL);
   34.88 +
   34.89 +	/*
   34.90 +	 * So what does all this implicit skip stuff mean?
   34.91 +	 * Imagine two types,
   34.92 +	 * 	A ::= [5] IMPLICIT	T
   34.93 +	 * 	B ::= [2] EXPLICIT	T
   34.94 +	 * Where T is defined as
   34.95 +	 *	T ::= [4] IMPLICIT SEQUENCE { ... }
   34.96 +	 * 
   34.97 +	 * Let's say, we are starting to decode type A, given the
   34.98 +	 * following TLV stream: <5> <0>. What does this mean?
   34.99 +	 * It means that the type A contains type T which is,
  34.100 +	 * in turn, empty.
  34.101 +	 * Remember though, that we are still in A. We cannot
  34.102 +	 * just pass control to the type T decoder. Why? Because
  34.103 +	 * the type T decoder expects <4> <0>, not <5> <0>.
  34.104 +	 * So, we must make sure we are going to receive <5> while
  34.105 +	 * still in A, then pass control to the T decoder, indicating
  34.106 +	 * that the tag <4> was implicitly skipped. The decoder of T
  34.107 +	 * hence will be prepared to treat <4> as valid tag, and decode
  34.108 +	 * it appropriately.
  34.109 +	 */
  34.110 +
  34.111 +	tagno = step	/* Continuing where left previously */
  34.112 +		+ (tag_mode==1?-1:0)
  34.113 +		;
  34.114 +	ASN_DEBUG("ber_check_tags(%s, size=%ld, tm=%d, step=%d, tagno=%d)",
  34.115 +		td->name, (long)size, tag_mode, step, tagno);
  34.116 +	/* assert(td->tags_count >= 1) May not be the case for CHOICE or ANY */
  34.117 +
  34.118 +	if(tag_mode == 0 && tagno == td->tags_count) {
  34.119 +		/*
  34.120 +		 * This must be the _untagged_ ANY type,
  34.121 +		 * which outermost tag isn't known in advance.
  34.122 +		 * Fetch the tag and length separately.
  34.123 +		 */
  34.124 +		tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
  34.125 +		switch(tag_len) {
  34.126 +		case -1: RETURN(RC_FAIL);
  34.127 +		case 0: RETURN(RC_WMORE);
  34.128 +		}
  34.129 +		tlv_constr = BER_TLV_CONSTRUCTED(ptr);
  34.130 +		len_len = ber_fetch_length(tlv_constr,
  34.131 +			(const char *)ptr + tag_len, size - tag_len, &tlv_len);
  34.132 +		switch(len_len) {
  34.133 +		case -1: RETURN(RC_FAIL);
  34.134 +		case 0: RETURN(RC_WMORE);
  34.135 +		}
  34.136 +		ASN_DEBUG("Advancing %ld in ANY case",
  34.137 +			(long)(tag_len + len_len));
  34.138 +		ADVANCE(tag_len + len_len);
  34.139 +	} else {
  34.140 +		assert(tagno < td->tags_count);	/* At least one loop */
  34.141 +	}
  34.142 +	for((void)tagno; tagno < td->tags_count; tagno++, step++) {
  34.143 +
  34.144 +		/*
  34.145 +		 * Fetch and process T from TLV.
  34.146 +		 */
  34.147 +		tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
  34.148 +			ASN_DEBUG("Fetching tag from {%p,%ld}: "
  34.149 +				"len %ld, step %d, tagno %d got %s",
  34.150 +				ptr, (long)size,
  34.151 +				(long)tag_len, step, tagno,
  34.152 +				ber_tlv_tag_string(tlv_tag));
  34.153 +		switch(tag_len) {
  34.154 +		case -1: RETURN(RC_FAIL);
  34.155 +		case 0: RETURN(RC_WMORE);
  34.156 +		}
  34.157 +
  34.158 +		tlv_constr = BER_TLV_CONSTRUCTED(ptr);
  34.159 +
  34.160 +		/*
  34.161 +		 * If {I}, don't check anything.
  34.162 +		 * If {I,B,C}, check B and C unless we're at I.
  34.163 +		 */
  34.164 +		if(tag_mode != 0 && step == 0) {
  34.165 +			/*
  34.166 +			 * We don't expect tag to match here.
  34.167 +			 * It's just because we don't know how the tag
  34.168 +			 * is supposed to look like.
  34.169 +			 */
  34.170 +		} else {
  34.171 +		    assert(tagno >= 0);	/* Guaranteed by the code above */
  34.172 +		    if(tlv_tag != td->tags[tagno]) {
  34.173 +			/*
  34.174 +			 * Unexpected tag. Too bad.
  34.175 +			 */
  34.176 +		    	ASN_DEBUG("Expected: %s, "
  34.177 +				"expectation failed (tn=%d, tm=%d)",
  34.178 +				ber_tlv_tag_string(td->tags[tagno]),
  34.179 +				tagno, tag_mode
  34.180 +			);
  34.181 +			RETURN(RC_FAIL);
  34.182 +		    }
  34.183 +		}
  34.184 +
  34.185 +		/*
  34.186 +		 * Attention: if there are more tags expected,
  34.187 +		 * ensure that the current tag is presented
  34.188 +		 * in constructed form (it contains other tags!).
  34.189 +		 * If this one is the last one, check that the tag form
  34.190 +		 * matches the one given in descriptor.
  34.191 +		 */
  34.192 +		if(tagno < (td->tags_count - 1)) {
  34.193 +			if(tlv_constr == 0) {
  34.194 +				ASN_DEBUG("tlv_constr = %d, expfail",
  34.195 +					tlv_constr);
  34.196 +				RETURN(RC_FAIL);
  34.197 +			}
  34.198 +		} else {
  34.199 +			if(last_tag_form != tlv_constr
  34.200 +			&& last_tag_form != -1) {
  34.201 +				ASN_DEBUG("last_tag_form %d != %d",
  34.202 +					last_tag_form, tlv_constr);
  34.203 +				RETURN(RC_FAIL);
  34.204 +			}
  34.205 +		}
  34.206 +
  34.207 +		/*
  34.208 +		 * Fetch and process L from TLV.
  34.209 +		 */
  34.210 +		len_len = ber_fetch_length(tlv_constr,
  34.211 +			(const char *)ptr + tag_len, size - tag_len, &tlv_len);
  34.212 +		ASN_DEBUG("Fetching len = %ld", (long)len_len);
  34.213 +		switch(len_len) {
  34.214 +		case -1: RETURN(RC_FAIL);
  34.215 +		case 0: RETURN(RC_WMORE);
  34.216 +		}
  34.217 +
  34.218 +		/*
  34.219 +		 * FIXME
  34.220 +		 * As of today, the chain of tags
  34.221 +		 * must either contain several indefinite length TLVs,
  34.222 +		 * or several definite length ones.
  34.223 +		 * No mixing is allowed.
  34.224 +		 */
  34.225 +		if(tlv_len == -1) {
  34.226 +			/*
  34.227 +			 * Indefinite length.
  34.228 +			 */
  34.229 +			if(limit_len == -1) {
  34.230 +				expect_00_terminators++;
  34.231 +			} else {
  34.232 +				ASN_DEBUG("Unexpected indefinite length "
  34.233 +					"in a chain of definite lengths");
  34.234 +				RETURN(RC_FAIL);
  34.235 +			}
  34.236 +			ADVANCE(tag_len + len_len);
  34.237 +			continue;
  34.238 +		} else {
  34.239 +			if(expect_00_terminators) {
  34.240 +				ASN_DEBUG("Unexpected definite length "
  34.241 +					"in a chain of indefinite lengths");
  34.242 +				RETURN(RC_FAIL);
  34.243 +			}
  34.244 +		}
  34.245 +
  34.246 +		/*
  34.247 +		 * Check that multiple TLVs specify ever decreasing length,
  34.248 +		 * which is consistent.
  34.249 +		 */
  34.250 +		if(limit_len == -1) {
  34.251 +			limit_len    = tlv_len + tag_len + len_len;
  34.252 +			if(limit_len < 0) {
  34.253 +				/* Too great tlv_len value? */
  34.254 +				RETURN(RC_FAIL);
  34.255 +			}
  34.256 +		} else if(limit_len != tlv_len + tag_len + len_len) {
  34.257 +			/*
  34.258 +			 * Inner TLV specifies length which is inconsistent
  34.259 +			 * with the outer TLV's length value.
  34.260 +			 */
  34.261 +			ASN_DEBUG("Outer TLV is %ld and inner is %ld",
  34.262 +				(long)limit_len, (long)tlv_len);
  34.263 +			RETURN(RC_FAIL);
  34.264 +		}
  34.265 +
  34.266 +		ADVANCE(tag_len + len_len);
  34.267 +
  34.268 +		limit_len -= (tag_len + len_len);
  34.269 +		if((ssize_t)size > limit_len) {
  34.270 +			/*
  34.271 +			 * Make sure that we won't consume more bytes
  34.272 +			 * from the parent frame than the inferred limit.
  34.273 +			 */
  34.274 +			size = limit_len;
  34.275 +		}
  34.276 +	}
  34.277 +
  34.278 +	if(opt_tlv_form)
  34.279 +		*opt_tlv_form = tlv_constr;
  34.280 +	if(expect_00_terminators)
  34.281 +		*last_length = -expect_00_terminators;
  34.282 +	else
  34.283 +		*last_length = tlv_len;
  34.284 +
  34.285 +	RETURN(RC_OK);
  34.286 +}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/asn.1/ber_decoder.h	Wed May 11 20:06:23 2016 +0200
    35.3 @@ -0,0 +1,64 @@
    35.4 +/*-
    35.5 + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    35.6 + * Redistribution and modifications are permitted subject to BSD license.
    35.7 + */
    35.8 +#ifndef	_BER_DECODER_H_
    35.9 +#define	_BER_DECODER_H_
   35.10 +
   35.11 +#include <asn_application.h>
   35.12 +
   35.13 +#ifdef __cplusplus
   35.14 +extern "C" {
   35.15 +#endif
   35.16 +
   35.17 +struct asn_TYPE_descriptor_s;	/* Forward declaration */
   35.18 +struct asn_codec_ctx_s;		/* Forward declaration */
   35.19 +
   35.20 +/*
   35.21 + * The BER decoder of any type.
   35.22 + * This function may be invoked directly from the application.
   35.23 + * The der_encode() function (der_encoder.h) is an opposite to ber_decode().
   35.24 + */
   35.25 +asn_dec_rval_t ber_decode(struct asn_codec_ctx_s *opt_codec_ctx,
   35.26 +	struct asn_TYPE_descriptor_s *type_descriptor,
   35.27 +	void **struct_ptr,	/* Pointer to a target structure's pointer */
   35.28 +	const void *buffer,	/* Data to be decoded */
   35.29 +	size_t size		/* Size of that buffer */
   35.30 +	);
   35.31 +
   35.32 +/*
   35.33 + * Type of generic function which decodes the byte stream into the structure.
   35.34 + */
   35.35 +typedef asn_dec_rval_t (ber_type_decoder_f)(
   35.36 +		struct asn_codec_ctx_s *opt_codec_ctx,
   35.37 +		struct asn_TYPE_descriptor_s *type_descriptor,
   35.38 +		void **struct_ptr, const void *buf_ptr, size_t size,
   35.39 +		int tag_mode);
   35.40 +
   35.41 +/*******************************
   35.42 + * INTERNALLY USEFUL FUNCTIONS *
   35.43 + *******************************/
   35.44 +
   35.45 +/*
   35.46 + * Check that all tags correspond to the type definition (as given in head).
   35.47 + * On return, last_length would contain either a non-negative length of the
   35.48 + * value part of the last TLV, or the negative number of expected
   35.49 + * "end of content" sequences. The number may only be negative if the
   35.50 + * head->last_tag_form is non-zero.
   35.51 + */
   35.52 +asn_dec_rval_t ber_check_tags(
   35.53 +		struct asn_codec_ctx_s *opt_codec_ctx,	/* codec options */
   35.54 +		struct asn_TYPE_descriptor_s *type_descriptor,
   35.55 +		asn_struct_ctx_t *opt_ctx,	/* saved decoding context */
   35.56 +		const void *ptr, size_t size,
   35.57 +		int tag_mode,		/* {-1,0,1}: IMPLICIT, no, EXPLICIT */
   35.58 +		int last_tag_form,	/* {-1,0:1}: any, primitive, constr */
   35.59 +		ber_tlv_len_t *last_length,
   35.60 +		int *opt_tlv_form	/* optional tag form */
   35.61 +	);
   35.62 +
   35.63 +#ifdef __cplusplus
   35.64 +}
   35.65 +#endif
   35.66 +
   35.67 +#endif	/* _BER_DECODER_H_ */
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/asn.1/ber_tlv_length.c	Wed May 11 20:06:23 2016 +0200
    36.3 @@ -0,0 +1,178 @@
    36.4 +/*-
    36.5 + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    36.6 + * Redistribution and modifications are permitted subject to BSD license.
    36.7 + */
    36.8 +#include <asn_internal.h>
    36.9 +#include <ber_tlv_length.h>
   36.10 +#include <ber_tlv_tag.h>
   36.11 +
   36.12 +ssize_t
   36.13 +ber_fetch_length(int _is_constructed, const void *bufptr, size_t size,
   36.14 +		ber_tlv_len_t *len_r) {
   36.15 +	const uint8_t *buf = (const uint8_t *)bufptr;
   36.16 +	unsigned oct;
   36.17 +
   36.18 +	if(size == 0)
   36.19 +		return 0;	/* Want more */
   36.20 +
   36.21 +	oct = *(const uint8_t *)buf;
   36.22 +	if((oct & 0x80) == 0) {
   36.23 +		/*
   36.24 +		 * Short definite length.
   36.25 +		 */
   36.26 +		*len_r = oct;	/* & 0x7F */
   36.27 +		return 1;
   36.28 +	} else {
   36.29 +		ber_tlv_len_t len;
   36.30 +		size_t skipped;
   36.31 +
   36.32 +		if(_is_constructed && oct == 0x80) {
   36.33 +			*len_r = -1;	/* Indefinite length */
   36.34 +			return 1;
   36.35 +		}
   36.36 +
   36.37 +		if(oct == 0xff) {
   36.38 +			/* Reserved in standard for future use. */
   36.39 +			return -1;
   36.40 +		}
   36.41 +
   36.42 +		oct &= 0x7F;	/* Leave only the 7 LS bits */
   36.43 +		for(len = 0, buf++, skipped = 1;
   36.44 +			oct && (++skipped <= size); buf++, oct--) {
   36.45 +
   36.46 +			len = (len << 8) | *buf;
   36.47 +			if(len < 0
   36.48 +			|| (len >> ((8 * sizeof(len)) - 8) && oct > 1)) {
   36.49 +				/*
   36.50 +				 * Too large length value.
   36.51 +				 */
   36.52 +				return -1;
   36.53 +			}
   36.54 +		}
   36.55 +
   36.56 +		if(oct == 0) {
   36.57 +			ber_tlv_len_t lenplusepsilon = (size_t)len + 1024;
   36.58 +			/*
   36.59 +			 * Here length may be very close or equal to 2G.
   36.60 +			 * However, the arithmetics used in some decoders
   36.61 +			 * may add some (small) quantities to the length,
   36.62 +			 * to check the resulting value against some limits.
   36.63 +			 * This may result in integer wrap-around, which
   36.64 +			 * we try to avoid by checking it earlier here.
   36.65 +			 */
   36.66 +			if(lenplusepsilon < 0) {
   36.67 +				/* Too large length value */
   36.68 +				return -1;
   36.69 +			}
   36.70 +
   36.71 +			*len_r = len;
   36.72 +			return skipped;
   36.73 +		}
   36.74 +
   36.75 +		return 0;	/* Want more */
   36.76 +	}
   36.77 +
   36.78 +}
   36.79 +
   36.80 +ssize_t
   36.81 +ber_skip_length(asn_codec_ctx_t *opt_codec_ctx,
   36.82 +		int _is_constructed, const void *ptr, size_t size) {
   36.83 +	ber_tlv_len_t vlen;	/* Length of V in TLV */
   36.84 +	ssize_t tl;		/* Length of L in TLV */
   36.85 +	ssize_t ll;		/* Length of L in TLV */
   36.86 +	size_t skip;
   36.87 +
   36.88 +	/*
   36.89 +	 * Make sure we didn't exceed the maximum stack size.
   36.90 +	 */
   36.91 +	if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
   36.92 +		return -1;
   36.93 +
   36.94 +	/*
   36.95 +	 * Determine the size of L in TLV.
   36.96 +	 */
   36.97 +	ll = ber_fetch_length(_is_constructed, ptr, size, &vlen);
   36.98 +	if(ll <= 0) return ll;
   36.99 +
  36.100 +	/*
  36.101 +	 * Definite length.
  36.102 +	 */
  36.103 +	if(vlen >= 0) {
  36.104 +		skip = ll + vlen;
  36.105 +		if(skip > size)
  36.106 +			return 0;	/* Want more */
  36.107 +		return skip;
  36.108 +	}
  36.109 +
  36.110 +	/*
  36.111 +	 * Indefinite length!
  36.112 +	 */
  36.113 +	ASN_DEBUG("Skipping indefinite length");
  36.114 +	for(skip = ll, ptr = ((const char *)ptr) + ll, size -= ll;;) {
  36.115 +		ber_tlv_tag_t tag;
  36.116 +
  36.117 +		/* Fetch the tag */
  36.118 +		tl = ber_fetch_tag(ptr, size, &tag);
  36.119 +		if(tl <= 0) return tl;
  36.120 +
  36.121 +		ll = ber_skip_length(opt_codec_ctx,
  36.122 +			BER_TLV_CONSTRUCTED(ptr),
  36.123 +			((const char *)ptr) + tl, size - tl);
  36.124 +		if(ll <= 0) return ll;
  36.125 +
  36.126 +		skip += tl + ll;
  36.127 +
  36.128 +		/*
  36.129 +		 * This may be the end of the indefinite length structure,
  36.130 +		 * two consecutive 0 octets.
  36.131 +		 * Check if it is true.
  36.132 +		 */
  36.133 +		if(((const uint8_t *)ptr)[0] == 0
  36.134 +		&& ((const uint8_t *)ptr)[1] == 0)
  36.135 +			return skip;
  36.136 +
  36.137 +		ptr = ((const char *)ptr) + tl + ll;
  36.138 +		size -= tl + ll;
  36.139 + 	}
  36.140 +
  36.141 +	/* UNREACHABLE */
  36.142 +}
  36.143 +
  36.144 +size_t
  36.145 +der_tlv_length_serialize(ber_tlv_len_t len, void *bufp, size_t size) {
  36.146 +	size_t required_size;	/* Size of len encoding */
  36.147 +	uint8_t *buf = (uint8_t *)bufp;
  36.148 +	uint8_t *end;
  36.149 +	size_t i;
  36.150 +
  36.151 +	if(len <= 127) {
  36.152 +		/* Encoded in 1 octet */
  36.153 +		if(size) *buf = (uint8_t)len;
  36.154 +		return 1;
  36.155 +	}
  36.156 +
  36.157 +	/*
  36.158 +	 * Compute the size of the subsequent bytes.
  36.159 +	 */
  36.160 +	for(required_size = 1, i = 8; i < 8 * sizeof(len); i += 8) {
  36.161 +		if(len >> i)
  36.162 +			required_size++;
  36.163 +		else
  36.164 +			break;
  36.165 +	}
  36.166 +
  36.167 +	if(size <= required_size)
  36.168 +		return required_size + 1;
  36.169 +
  36.170 +	*buf++ = (uint8_t)(0x80 | required_size);  /* Length of the encoding */
  36.171 +
  36.172 +	/*
  36.173 +	 * Produce the len encoding, space permitting.
  36.174 +	 */
  36.175 +	end = buf + required_size;
  36.176 +	for(i -= 8; buf < end; i -= 8, buf++)
  36.177 +		*buf = (uint8_t)(len >> i);
  36.178 +
  36.179 +	return required_size + 1;
  36.180 +}
  36.181 +
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/asn.1/ber_tlv_length.h	Wed May 11 20:06:23 2016 +0200
    37.3 @@ -0,0 +1,50 @@
    37.4 +/*-
    37.5 + * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
    37.6 + * Redistribution and modifications are permitted subject to BSD license.
    37.7 + */
    37.8 +#ifndef	_BER_TLV_LENGTH_H_
    37.9 +#define	_BER_TLV_LENGTH_H_
   37.10 +
   37.11 +#ifdef __cplusplus
   37.12 +extern "C" {
   37.13 +#endif
   37.14 +
   37.15 +typedef ssize_t ber_tlv_len_t;
   37.16 +
   37.17 +/*
   37.18 + * This function tries to fetch the length of the BER TLV value and place it
   37.19 + * in *len_r.
   37.20 + * RETURN VALUES:
   37.21 + *	 0:	More data expected than bufptr contains.
   37.22 + *	-1:	Fatal error deciphering length.
   37.23 + *	>0:	Number of bytes used from bufptr.
   37.24 + * On return with >0, len_r is constrained as -1..MAX, where -1 mean
   37.25 + * that the value is of indefinite length.
   37.26 + */
   37.27 +ssize_t ber_fetch_length(int _is_constructed, const void *bufptr, size_t size,
   37.28 +	ber_tlv_len_t *len_r);
   37.29 +
   37.30 +/*
   37.31 + * This function expects bufptr to be positioned over L in TLV.
   37.32 + * It returns number of bytes occupied by L and V together, suitable
   37.33 + * for skipping. The function properly handles indefinite length.
   37.34 + * RETURN VALUES:
   37.35 + * 	Standard {-1,0,>0} convention.
   37.36 + */
   37.37 +ssize_t ber_skip_length(
   37.38 +	struct asn_codec_ctx_s *opt_codec_ctx,	/* optional context */
   37.39 +	int _is_constructed, const void *bufptr, size_t size);
   37.40 +
   37.41 +/*
   37.42 + * This function serializes the length (L from TLV) in DER format.
   37.43 + * It always returns number of bytes necessary to represent the length,
   37.44 + * it is a caller's responsibility to check the return value
   37.45 + * against the supplied buffer's size.
   37.46 + */
   37.47 +size_t der_tlv_length_serialize(ber_tlv_len_t len, void *bufptr, size_t size);
   37.48 +
   37.49 +#ifdef __cplusplus
   37.50 +}
   37.51 +#endif
   37.52 +
   37.53 +#endif	/* _BER_TLV_LENGTH_H_ */
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/asn.1/ber_tlv_tag.c	Wed May 11 20:06:23 2016 +0200
    38.3 @@ -0,0 +1,144 @@
    38.4 +/*-
    38.5 + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    38.6 + * Redistribution and modifications are permitted subject to BSD license.
    38.7 + */
    38.8 +#include <asn_internal.h>
    38.9 +#include <ber_tlv_tag.h>
   38.10 +#include <errno.h>
   38.11 +
   38.12 +ssize_t
   38.13 +ber_fetch_tag(const void *ptr, size_t size, ber_tlv_tag_t *tag_r) {
   38.14 +	ber_tlv_tag_t val;
   38.15 +	ber_tlv_tag_t tclass;
   38.16 +	size_t skipped;
   38.17 +
   38.18 +	if(size == 0)
   38.19 +		return 0;
   38.20 +
   38.21 +	val = *(const uint8_t *)ptr;
   38.22 +	tclass = (val >> 6);
   38.23 +	if((val &= 0x1F) != 0x1F) {
   38.24 +		/*
   38.25 +		 * Simple form: everything encoded in a single octet.
   38.26 +		 * Tag Class is encoded using two least significant bits.
   38.27 +		 */
   38.28 +		*tag_r = (val << 2) | tclass;
   38.29 +		return 1;
   38.30 +	}
   38.31 +
   38.32 +	/*
   38.33 +	 * Each octet contains 7 bits of useful information.
   38.34 +	 * The MSB is 0 if it is the last octet of the tag.
   38.35 +	 */
   38.36 +	for(val = 0, ptr = ((const char *)ptr) + 1, skipped = 2;
   38.37 +			skipped <= size;
   38.38 +				ptr = ((const char *)ptr) + 1, skipped++) {
   38.39 +		unsigned int oct = *(const uint8_t *)ptr;
   38.40 +		if(oct & 0x80) {
   38.41 +			val = (val << 7) | (oct & 0x7F);
   38.42 +			/*
   38.43 +			 * Make sure there are at least 9 bits spare
   38.44 +			 * at the MS side of a value.
   38.45 +			 */
   38.46 +			if(val >> ((8 * sizeof(val)) - 9)) {
   38.47 +				/*
   38.48 +				 * We would not be able to accomodate
   38.49 +				 * any more tag bits.
   38.50 +				 */
   38.51 +				return -1;
   38.52 +			}
   38.53 +		} else {
   38.54 +			val = (val << 7) | oct;
   38.55 +			*tag_r = (val << 2) | tclass;
   38.56 +			return skipped;
   38.57 +		}
   38.58 +	}
   38.59 +
   38.60 +	return 0;	/* Want more */
   38.61 +}
   38.62 +
   38.63 +
   38.64 +ssize_t
   38.65 +ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *f) {
   38.66 +	char buf[sizeof("[APPLICATION ]") + 32];
   38.67 +	ssize_t ret;
   38.68 +
   38.69 +	ret = ber_tlv_tag_snprint(tag, buf, sizeof(buf));
   38.70 +	if(ret >= (ssize_t)sizeof(buf) || ret < 2) {
   38.71 +		errno = EPERM;
   38.72 +		return -1;
   38.73 +	}
   38.74 +
   38.75 +	return fwrite(buf, 1, ret, f);
   38.76 +}
   38.77 +
   38.78 +ssize_t
   38.79 +ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t size) {
   38.80 +	char *type = 0;
   38.81 +	int ret;
   38.82 +
   38.83 +	switch(tag & 0x3) {
   38.84 +	case ASN_TAG_CLASS_UNIVERSAL:	type = "UNIVERSAL ";	break;
   38.85 +	case ASN_TAG_CLASS_APPLICATION:	type = "APPLICATION ";	break;
   38.86 +	case ASN_TAG_CLASS_CONTEXT:	type = "";		break;
   38.87 +	case ASN_TAG_CLASS_PRIVATE:	type = "PRIVATE ";	break;
   38.88 +	}
   38.89 +
   38.90 +	ret = snprintf(buf, size, "[%s%u]", type, ((unsigned)tag) >> 2);
   38.91 +	if(ret <= 0 && size) buf[0] = '\0';	/* against broken libc's */
   38.92 +
   38.93 +	return ret;
   38.94 +}
   38.95 +
   38.96 +char *
   38.97 +ber_tlv_tag_string(ber_tlv_tag_t tag) {
   38.98 +	static char buf[sizeof("[APPLICATION ]") + 32];
   38.99 +
  38.100 +	(void)ber_tlv_tag_snprint(tag, buf, sizeof(buf));
  38.101 +
  38.102 +	return buf;
  38.103 +}
  38.104 +
  38.105 +
  38.106 +size_t
  38.107 +ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufp, size_t size) {
  38.108 +	int tclass = BER_TAG_CLASS(tag);
  38.109 +	ber_tlv_tag_t tval = BER_TAG_VALUE(tag);
  38.110 +	uint8_t *buf = (uint8_t *)bufp;
  38.111 +	uint8_t *end;
  38.112 +	size_t required_size;
  38.113 +	size_t i;
  38.114 +
  38.115 +	if(tval <= 30) {
  38.116 +		/* Encoded in 1 octet */
  38.117 +		if(size) buf[0] = (tclass << 6) | tval;
  38.118 +		return 1;
  38.119 +	} else if(size) {
  38.120 +		*buf++ = (tclass << 6) | 0x1F;
  38.121 +		size--;
  38.122 +	}
  38.123 +
  38.124 +	/*
  38.125 +	 * Compute the size of the subsequent bytes.
  38.126 +	 */
  38.127 +	for(required_size = 1, i = 7; i < 8 * sizeof(tval); i += 7) {
  38.128 +		if(tval >> i)
  38.129 +			required_size++;
  38.130 +		else
  38.131 +			break;
  38.132 +	}
  38.133 +
  38.134 +	if(size < required_size)
  38.135 +		return required_size + 1;
  38.136 +
  38.137 +	/*
  38.138 +	 * Fill in the buffer, space permitting.
  38.139 +	 */
  38.140 +	end = buf + required_size - 1;
  38.141 +	for(i -= 7; buf < end; i -= 7, buf++)
  38.142 +		*buf = 0x80 | ((tval >> i) & 0x7F);
  38.143 +	*buf = (tval & 0x7F);	/* Last octet without high bit */
  38.144 +
  38.145 +	return required_size + 1;
  38.146 +}
  38.147 +
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/asn.1/ber_tlv_tag.h	Wed May 11 20:06:23 2016 +0200
    39.3 @@ -0,0 +1,60 @@
    39.4 +/*-
    39.5 + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    39.6 + * Redistribution and modifications are permitted subject to BSD license.
    39.7 + */
    39.8 +#ifndef	_BER_TLV_TAG_H_
    39.9 +#define	_BER_TLV_TAG_H_
   39.10 +
   39.11 +#ifdef __cplusplus
   39.12 +extern "C" {
   39.13 +#endif
   39.14 +
   39.15 +enum asn_tag_class {
   39.16 +	ASN_TAG_CLASS_UNIVERSAL		= 0,	/* 0b00 */
   39.17 +	ASN_TAG_CLASS_APPLICATION	= 1,	/* 0b01 */
   39.18 +	ASN_TAG_CLASS_CONTEXT		= 2,	/* 0b10 */
   39.19 +	ASN_TAG_CLASS_PRIVATE		= 3	/* 0b11 */
   39.20 +};
   39.21 +typedef unsigned ber_tlv_tag_t;	/* BER TAG from Tag-Length-Value */
   39.22 +
   39.23 +/*
   39.24 + * Tag class is encoded together with tag value for optimization purposes.
   39.25 + */
   39.26 +#define	BER_TAG_CLASS(tag)	((tag) & 0x3)
   39.27 +#define	BER_TAG_VALUE(tag)	((tag) >> 2)
   39.28 +#define	BER_TLV_CONSTRUCTED(tagptr)	(((*(const uint8_t *)tagptr)&0x20)?1:0)
   39.29 +
   39.30 +#define	BER_TAGS_EQUAL(tag1, tag2)	((tag1) == (tag2))
   39.31 +
   39.32 +/*
   39.33 + * Several functions for printing the TAG in the canonical form
   39.34 + * (i.e. "[PRIVATE 0]").
   39.35 + * Return values correspond to their libc counterparts (if any).
   39.36 + */
   39.37 +ssize_t ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t buflen);
   39.38 +ssize_t ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *);
   39.39 +char *ber_tlv_tag_string(ber_tlv_tag_t tag);
   39.40 +
   39.41 +
   39.42 +/*
   39.43 + * This function tries to fetch the tag from the input stream.
   39.44 + * RETURN VALUES:
   39.45 + * 	 0:	More data expected than bufptr contains.
   39.46 + * 	-1:	Fatal error deciphering tag.
   39.47 + *	>0:	Number of bytes used from bufptr. tag_r will contain the tag.
   39.48 + */
   39.49 +ssize_t ber_fetch_tag(const void *bufptr, size_t size, ber_tlv_tag_t *tag_r);
   39.50 +
   39.51 +/*
   39.52 + * This function serializes the tag (T from TLV) in BER format.
   39.53 + * It always returns number of bytes necessary to represent the tag,
   39.54 + * it is a caller's responsibility to check the return value
   39.55 + * against the supplied buffer's size.
   39.56 + */
   39.57 +size_t ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufptr, size_t size);
   39.58 +
   39.59 +#ifdef __cplusplus
   39.60 +}
   39.61 +#endif
   39.62 +
   39.63 +#endif	/* _BER_TLV_TAG_H_ */
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/asn.1/constr_SEQUENCE.c	Wed May 11 20:06:23 2016 +0200
    40.3 @@ -0,0 +1,1422 @@
    40.4 +/*-
    40.5 + * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
    40.6 + * All rights reserved.
    40.7 + * Redistribution and modifications are permitted subject to BSD license.
    40.8 + */
    40.9 +#include <asn_internal.h>
   40.10 +#include <constr_SEQUENCE.h>
   40.11 +#include <per_opentype.h>
   40.12 +
   40.13 +/*
   40.14 + * Number of bytes left for this structure.
   40.15 + * (ctx->left) indicates the number of bytes _transferred_ for the structure.
   40.16 + * (size) contains the number of bytes in the buffer passed.
   40.17 + */
   40.18 +#define	LEFT	((size<(size_t)ctx->left)?size:(size_t)ctx->left)
   40.19 +
   40.20 +/*
   40.21 + * If the subprocessor function returns with an indication that it wants
   40.22 + * more data, it may well be a fatal decoding problem, because the
   40.23 + * size is constrained by the <TLV>'s L, even if the buffer size allows
   40.24 + * reading more data.
   40.25 + * For example, consider the buffer containing the following TLVs:
   40.26 + * <T:5><L:1><V> <T:6>...
   40.27 + * The TLV length clearly indicates that one byte is expected in V, but
   40.28 + * if the V processor returns with "want more data" even if the buffer
   40.29 + * contains way more data than the V processor have seen.
   40.30 + */
   40.31 +#define	SIZE_VIOLATION	(ctx->left >= 0 && (size_t)ctx->left <= size)
   40.32 +
   40.33 +/*
   40.34 + * This macro "eats" the part of the buffer which is definitely "consumed",
   40.35 + * i.e. was correctly converted into local representation or rightfully skipped.
   40.36 + */
   40.37 +#undef	ADVANCE
   40.38 +#define	ADVANCE(num_bytes)	do {		\
   40.39 +		size_t num = num_bytes;		\
   40.40 +		ptr = ((const char *)ptr) + num; \
   40.41 +		size -= num;			\
   40.42 +		if(ctx->left >= 0)		\
   40.43 +			ctx->left -= num;	\
   40.44 +		consumed_myself += num;		\
   40.45 +	} while(0)
   40.46 +
   40.47 +/*
   40.48 + * Switch to the next phase of parsing.
   40.49 + */
   40.50 +#undef	NEXT_PHASE
   40.51 +#undef	PHASE_OUT
   40.52 +#define	NEXT_PHASE(ctx)	do {			\
   40.53 +		ctx->phase++;			\
   40.54 +		ctx->step = 0;			\
   40.55 +	} while(0)
   40.56 +#define	PHASE_OUT(ctx)	do { ctx->phase = 10; } while(0)
   40.57 +
   40.58 +/*
   40.59 + * Return a standardized complex structure.
   40.60 + */
   40.61 +#undef	RETURN
   40.62 +#define	RETURN(_code)	do {			\
   40.63 +		rval.code = _code;		\
   40.64 +		rval.consumed = consumed_myself;\
   40.65 +		return rval;			\
   40.66 +	} while(0)
   40.67 +
   40.68 +/*
   40.69 + * Check whether we are inside the extensions group.
   40.70 + */
   40.71 +#define	IN_EXTENSION_GROUP(specs, memb_idx)	\
   40.72 +	( ((memb_idx) > (specs)->ext_after)	\
   40.73 +	&&((memb_idx) < (specs)->ext_before))
   40.74 +
   40.75 +
   40.76 +/*
   40.77 + * Tags are canonically sorted in the tag2element map.
   40.78 + */
   40.79 +static int
   40.80 +_t2e_cmp(const void *ap, const void *bp) {
   40.81 +	const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap;
   40.82 +	const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp;
   40.83 +
   40.84 +	int a_class = BER_TAG_CLASS(a->el_tag);
   40.85 +	int b_class = BER_TAG_CLASS(b->el_tag);
   40.86 +
   40.87 +	if(a_class == b_class) {
   40.88 +		ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag);
   40.89 +		ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag);
   40.90 +
   40.91 +		if(a_value == b_value) {
   40.92 +			if(a->el_no > b->el_no)
   40.93 +				return 1;
   40.94 +			/*
   40.95 +			 * Important: we do not check
   40.96 +			 * for a->el_no <= b->el_no!
   40.97 +			 */
   40.98 +			return 0;
   40.99 +		} else if(a_value < b_value)
  40.100 +			return -1;
  40.101 +		else
  40.102 +			return 1;
  40.103 +	} else if(a_class < b_class) {
  40.104 +		return -1;
  40.105 +	} else {
  40.106 +		return 1;
  40.107 +	}
  40.108 +}
  40.109 +
  40.110 +
  40.111 +/*
  40.112 + * The decoder of the SEQUENCE type.
  40.113 + */
  40.114 +asn_dec_rval_t
  40.115 +SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
  40.116 +	void **struct_ptr, const void *ptr, size_t size, int tag_mode) {
  40.117 +	/*
  40.118 +	 * Bring closer parts of structure description.
  40.119 +	 */
  40.120 +	asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
  40.121 +	asn_TYPE_member_t *elements = td->elements;
  40.122 +
  40.123 +	/*
  40.124 +	 * Parts of the structure being constructed.
  40.125 +	 */
  40.126 +	void *st = *struct_ptr;	/* Target structure. */
  40.127 +	asn_struct_ctx_t *ctx;	/* Decoder context */
  40.128 +
  40.129 +	ber_tlv_tag_t tlv_tag;	/* T from TLV */
  40.130 +	asn_dec_rval_t rval;	/* Return code from subparsers */
  40.131 +
  40.132 +	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
  40.133 +	int edx;			/* SEQUENCE element's index */
  40.134 +
  40.135 +	ASN_DEBUG("Decoding %s as SEQUENCE", td->name);
  40.136 +	
  40.137 +	/*
  40.138 +	 * Create the target structure if it is not present already.
  40.139 +	 */
  40.140 +	if(st == 0) {
  40.141 +		st = *struct_ptr = CALLOC(1, specs->struct_size);
  40.142 +		if(st == 0) {
  40.143 +			RETURN(RC_FAIL);
  40.144 +		}
  40.145 +	}
  40.146 +
  40.147 +	/*
  40.148 +	 * Restore parsing context.
  40.149 +	 */
  40.150 +	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
  40.151 +	
  40.152 +	/*
  40.153 +	 * Start to parse where left previously
  40.154 +	 */
  40.155 +	switch(ctx->phase) {
  40.156 +	case 0:
  40.157 +		/*
  40.158 +		 * PHASE 0.
  40.159 +		 * Check that the set of tags associated with given structure
  40.160 +		 * perfectly fits our expectations.
  40.161 +		 */
  40.162 +
  40.163 +		rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size,
  40.164 +			tag_mode, 1, &ctx->left, 0);
  40.165 +		if(rval.code != RC_OK) {
  40.166 +			ASN_DEBUG("%s tagging check failed: %d",
  40.167 +				td->name, rval.code);
  40.168 +			return rval;
  40.169 +		}
  40.170 +
  40.171 +		if(ctx->left >= 0)
  40.172 +			ctx->left += rval.consumed; /* ?Substracted below! */
  40.173 +		ADVANCE(rval.consumed);
  40.174 +
  40.175 +		NEXT_PHASE(ctx);
  40.176 +
  40.177 +		ASN_DEBUG("Structure consumes %ld bytes, buffer %ld",
  40.178 +			(long)ctx->left, (long)size);
  40.179 +
  40.180 +		/* Fall through */
  40.181 +	case 1:
  40.182 +		/*
  40.183 +		 * PHASE 1.
  40.184 +		 * From the place where we've left it previously,
  40.185 +		 * try to decode the next member from the list of
  40.186 +		 * this structure's elements.
  40.187 +		 * (ctx->step) stores the member being processed
  40.188 +		 * between invocations and the microphase {0,1} of parsing
  40.189 +		 * that member:
  40.190 +		 * 	step = (<member_number> * 2 + <microphase>).
  40.191 +		 */
  40.192 +	  for(edx = (ctx->step >> 1); edx < td->elements_count;
  40.193 +			edx++, ctx->step = (ctx->step & ~1) + 2) {
  40.194 +		void *memb_ptr;		/* Pointer to the member */
  40.195 +		void **memb_ptr2;	/* Pointer to that pointer */
  40.196 +		ssize_t tag_len;	/* Length of TLV's T */
  40.197 +		int opt_edx_end;	/* Next non-optional element */
  40.198 +		int use_bsearch;
  40.199 +		int n;
  40.200 +
  40.201 +		if(ctx->step & 1)
  40.202 +			goto microphase2;
  40.203 +
  40.204 +		/*
  40.205 +		 * MICROPHASE 1: Synchronize decoding.
  40.206 +		 */
  40.207 +		ASN_DEBUG("In %s SEQUENCE left %d, edx=%d flags=%d"
  40.208 +				" opt=%d ec=%d",
  40.209 +			td->name, (int)ctx->left, edx,
  40.210 +			elements[edx].flags, elements[edx].optional,
  40.211 +			td->elements_count);
  40.212 +
  40.213 +		if(ctx->left == 0	/* No more stuff is expected */
  40.214 +		&& (
  40.215 +			/* Explicit OPTIONAL specification reaches the end */
  40.216 +			(edx + elements[edx].optional
  40.217 +					== td->elements_count)
  40.218 +			||
  40.219 +			/* All extensions are optional */
  40.220 +			(IN_EXTENSION_GROUP(specs, edx)
  40.221 +				&& specs->ext_before > td->elements_count)
  40.222 +		   )
  40.223 +		) {
  40.224 +			ASN_DEBUG("End of SEQUENCE %s", td->name);
  40.225 +			/*
  40.226 +			 * Found the legitimate end of the structure.
  40.227 +			 */
  40.228 +			PHASE_OUT(ctx);
  40.229 +			RETURN(RC_OK);
  40.230 +		}
  40.231 +
  40.232 +		/*
  40.233 +		 * Fetch the T from TLV.
  40.234 +		 */
  40.235 +		tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
  40.236 +		ASN_DEBUG("Current tag in %s SEQUENCE for element %d "
  40.237 +			"(%s) is %s encoded in %d bytes, of frame %ld",
  40.238 +			td->name, edx, elements[edx].name,
  40.239 +			ber_tlv_tag_string(tlv_tag), (int)tag_len, (long)LEFT);
  40.240 +		switch(tag_len) {
  40.241 +		case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
  40.242 +			/* Fall through */
  40.243 +		case -1: RETURN(RC_FAIL);
  40.244 +		}
  40.245 +
  40.246 +		if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
  40.247 +			if(LEFT < 2) {
  40.248 +				if(SIZE_VIOLATION)
  40.249 +					RETURN(RC_FAIL);
  40.250 +				else
  40.251 +					RETURN(RC_WMORE);
  40.252 +			} else if(((const uint8_t *)ptr)[1] == 0) {
  40.253 +			ASN_DEBUG("edx = %d, opt = %d, ec=%d",
  40.254 +				edx, elements[edx].optional,
  40.255 +				td->elements_count);
  40.256 +				if((edx + elements[edx].optional
  40.257 +					== td->elements_count)
  40.258 +				|| (IN_EXTENSION_GROUP(specs, edx)
  40.259 +					&& specs->ext_before
  40.260 +						> td->elements_count)) {
  40.261 +					/*
  40.262 +					 * Yeah, baby! Found the terminator
  40.263 +					 * of the indefinite length structure.
  40.264 +					 */
  40.265 +					/*
  40.266 +					 * Proceed to the canonical
  40.267 +					 * finalization function.
  40.268 +					 * No advancing is necessary.
  40.269 +					 */
  40.270 +					goto phase3;
  40.271 +				}
  40.272 +			}
  40.273 +		}
  40.274 +
  40.275 +		/*
  40.276 +		 * Find the next available type with this tag.
  40.277 +		 */
  40.278 +		use_bsearch = 0;
  40.279 +		opt_edx_end = edx + elements[edx].optional + 1;
  40.280 +		if(opt_edx_end > td->elements_count)
  40.281 +			opt_edx_end = td->elements_count;	/* Cap */
  40.282 +		else if(opt_edx_end - edx > 8) {
  40.283 +			/* Limit the scope of linear search... */
  40.284 +			opt_edx_end = edx + 8;
  40.285 +			use_bsearch = 1;
  40.286 +			/* ... and resort to bsearch() */
  40.287 +		}
  40.288 +		for(n = edx; n < opt_edx_end; n++) {
  40.289 +			if(BER_TAGS_EQUAL(tlv_tag, elements[n].tag)) {
  40.290 +				/*
  40.291 +				 * Found element corresponding to the tag
  40.292 +				 * being looked at.
  40.293 +				 * Reposition over the right element.
  40.294 +				 */
  40.295 +				edx = n;
  40.296 +				ctx->step = 1 + 2 * edx;	/* Remember! */
  40.297 +				goto microphase2;
  40.298 +			} else if(elements[n].flags & ATF_OPEN_TYPE) {
  40.299 +				/*
  40.300 +				 * This is the ANY type, which may bear
  40.301 +				 * any flag whatsoever.
  40.302 +				 */
  40.303 +				edx = n;
  40.304 +				ctx->step = 1 + 2 * edx;	/* Remember! */
  40.305 +				goto microphase2;
  40.306 +			} else if(elements[n].tag == (ber_tlv_tag_t)-1) {
  40.307 +				use_bsearch = 1;
  40.308 +				break;
  40.309 +			}
  40.310 +		}
  40.311 +		if(use_bsearch) {
  40.312 +			/*
  40.313 +			 * Resort to a binary search over
  40.314 +			 * sorted array of tags.
  40.315 +			 */
  40.316 +			asn_TYPE_tag2member_t *t2m;
  40.317 +			asn_TYPE_tag2member_t key;
  40.318 +			key.el_tag = tlv_tag;
  40.319 +			key.el_no = edx;
  40.320 +			t2m = (asn_TYPE_tag2member_t *)bsearch(&key,
  40.321 +				specs->tag2el, specs->tag2el_count,
  40.322 +				sizeof(specs->tag2el[0]), _t2e_cmp);
  40.323 +			if(t2m) {
  40.324 +				asn_TYPE_tag2member_t *best = 0;
  40.325 +				asn_TYPE_tag2member_t *t2m_f, *t2m_l;
  40.326 +				int edx_max = edx + elements[edx].optional;
  40.327 +				/*
  40.328 +				 * Rewind to the first element with that tag,
  40.329 +				 * `cause bsearch() does not guarantee order.
  40.330 +				 */
  40.331 +				t2m_f = t2m + t2m->toff_first;
  40.332 +				t2m_l = t2m + t2m->toff_last;
  40.333 +				for(t2m = t2m_f; t2m <= t2m_l; t2m++) {
  40.334 +					if(t2m->el_no > edx_max) break;
  40.335 +					if(t2m->el_no < edx) continue;
  40.336 +					best = t2m;
  40.337 +				}
  40.338 +				if(best) {
  40.339 +					edx = best->el_no;
  40.340 +					ctx->step = 1 + 2 * edx;
  40.341 +					goto microphase2;
  40.342 +				}
  40.343 +			}
  40.344 +			n = opt_edx_end;
  40.345 +		}
  40.346 +		if(n == opt_edx_end) {
  40.347 +			/*
  40.348 +			 * If tag is unknown, it may be either
  40.349 +			 * an unknown (thus, incorrect) tag,
  40.350 +			 * or an extension (...),
  40.351 +			 * or an end of the indefinite-length structure.
  40.352 +			 */
  40.353 +			if(!IN_EXTENSION_GROUP(specs,
  40.354 +				edx + elements[edx].optional)) {
  40.355 +				ASN_DEBUG("Unexpected tag %s (at %d)",
  40.356 +					ber_tlv_tag_string(tlv_tag), edx);
  40.357 +				ASN_DEBUG("Expected tag %s (%s)%s",
  40.358 +					ber_tlv_tag_string(elements[edx].tag),
  40.359 +					elements[edx].name,
  40.360 +					elements[edx].optional
  40.361 +						?" or alternatives":"");
  40.362 +				RETURN(RC_FAIL);
  40.363 +			} else {
  40.364 +				/* Skip this tag */
  40.365 +				ssize_t skip;
  40.366 +				edx += elements[edx].optional;
  40.367 +
  40.368 +				ASN_DEBUG("Skipping unexpected %s (at %d)",
  40.369 +					ber_tlv_tag_string(tlv_tag), edx);
  40.370 +				skip = ber_skip_length(opt_codec_ctx,
  40.371 +					BER_TLV_CONSTRUCTED(ptr),
  40.372 +					(const char *)ptr + tag_len,
  40.373 +					LEFT - tag_len);
  40.374 +				ASN_DEBUG("Skip length %d in %s",
  40.375 +					(int)skip, td->name);
  40.376 +				switch(skip) {
  40.377 +				case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
  40.378 +					/* Fall through */
  40.379 +				case -1: RETURN(RC_FAIL);
  40.380 +				}
  40.381 +
  40.382 +				ADVANCE(skip + tag_len);
  40.383 +				ctx->step -= 2;
  40.384 +				edx--;
  40.385 +				continue;  /* Try again with the next tag */
  40.386 +			}
  40.387 +		}
  40.388 +
  40.389 +		/*
  40.390 +		 * MICROPHASE 2: Invoke the member-specific decoder.
  40.391 +		 */
  40.392 +		ctx->step |= 1;		/* Confirm entering next microphase */
  40.393 +	microphase2:
  40.394 +		ASN_DEBUG("Inside SEQUENCE %s MF2", td->name);
  40.395 +		
  40.396 +		/*
  40.397 +		 * Compute the position of the member inside a structure,
  40.398 +		 * and also a type of containment (it may be contained
  40.399 +		 * as pointer or using inline inclusion).
  40.400 +		 */
  40.401 +		if(elements[edx].flags & ATF_POINTER) {
  40.402 +			/* Member is a pointer to another structure */
  40.403 +			memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset);
  40.404 +		} else {
  40.405 +			/*
  40.406 +			 * A pointer to a pointer
  40.407 +			 * holding the start of the structure
  40.408 +			 */
  40.409 +			memb_ptr = (char *)st + elements[edx].memb_offset;
  40.410 +			memb_ptr2 = &memb_ptr;
  40.411 +		}
  40.412 +		/*
  40.413 +		 * Invoke the member fetch routine according to member's type
  40.414 +		 */
  40.415 +		rval = elements[edx].type->ber_decoder(opt_codec_ctx,
  40.416 +				elements[edx].type,
  40.417 +				memb_ptr2, ptr, LEFT,
  40.418 +				elements[edx].tag_mode);
  40.419 +		ASN_DEBUG("In %s SEQUENCE decoded %d %s of %d "
  40.420 +			"in %d bytes rval.code %d, size=%d",
  40.421 +			td->name, edx, elements[edx].type->name,
  40.422 +			(int)LEFT, (int)rval.consumed, rval.code, (int)size);
  40.423 +		switch(rval.code) {
  40.424 +		case RC_OK:
  40.425 +			break;
  40.426 +		case RC_WMORE: /* More data expected */
  40.427 +			if(!SIZE_VIOLATION) {
  40.428 +				ADVANCE(rval.consumed);
  40.429 +				RETURN(RC_WMORE);
  40.430 +			}
  40.431 +			ASN_DEBUG("Size violation (c->l=%ld <= s=%ld)",
  40.432 +				(long)ctx->left, (long)size);
  40.433 +			/* Fall through */
  40.434 +		case RC_FAIL: /* Fatal error */
  40.435 +			RETURN(RC_FAIL);
  40.436 +		} /* switch(rval) */
  40.437 +		
  40.438 +		ADVANCE(rval.consumed);
  40.439 +	  }	/* for(all structure members) */
  40.440 +
  40.441 +	phase3:
  40.442 +		ctx->phase = 3;
  40.443 +	case 3:	/* 00 and other tags expected */
  40.444 +	case 4:	/* only 00's expected */
  40.445 +
  40.446 +		ASN_DEBUG("SEQUENCE %s Leftover: %ld, size = %ld",
  40.447 +			td->name, (long)ctx->left, (long)size);
  40.448 +
  40.449 +		/*
  40.450 +		 * Skip everything until the end of the SEQUENCE.
  40.451 +		 */
  40.452 +		while(ctx->left) {
  40.453 +			ssize_t tl, ll;
  40.454 +
  40.455 +			tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
  40.456 +			switch(tl) {
  40.457 +			case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
  40.458 +				/* Fall through */
  40.459 +			case -1: RETURN(RC_FAIL);
  40.460 +			}
  40.461 +
  40.462 +			/*
  40.463 +			 * If expected <0><0>...
  40.464 +			 */
  40.465 +			if(ctx->left < 0
  40.466 +				&& ((const uint8_t *)ptr)[0] == 0) {
  40.467 +				if(LEFT < 2) {
  40.468 +					if(SIZE_VIOLATION)
  40.469 +						RETURN(RC_FAIL);
  40.470 +					else
  40.471 +						RETURN(RC_WMORE);
  40.472 +				} else if(((const uint8_t *)ptr)[1] == 0) {
  40.473 +					/*
  40.474 +					 * Correctly finished with <0><0>.
  40.475 +					 */
  40.476 +					ADVANCE(2);
  40.477 +					ctx->left++;
  40.478 +					ctx->phase = 4;
  40.479 +					continue;
  40.480 +				}
  40.481 +			}
  40.482 +
  40.483 +			if(!IN_EXTENSION_GROUP(specs, td->elements_count)
  40.484 +			|| ctx->phase == 4) {
  40.485 +				ASN_DEBUG("Unexpected continuation "
  40.486 +					"of a non-extensible type "
  40.487 +					"%s (SEQUENCE): %s",
  40.488 +					td->name,
  40.489 +					ber_tlv_tag_string(tlv_tag));
  40.490 +				RETURN(RC_FAIL);
  40.491 +			}
  40.492 +
  40.493 +			ll = ber_skip_length(opt_codec_ctx,
  40.494 +				BER_TLV_CONSTRUCTED(ptr),
  40.495 +				(const char *)ptr + tl, LEFT - tl);
  40.496 +			switch(ll) {
  40.497 +			case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
  40.498 +				/* Fall through */
  40.499 +			case -1: RETURN(RC_FAIL);
  40.500 +			}
  40.501 +
  40.502 +			ADVANCE(tl + ll);
  40.503 +		}
  40.504 +
  40.505 +		PHASE_OUT(ctx);
  40.506 +	}
  40.507 +	
  40.508 +	RETURN(RC_OK);
  40.509 +}
  40.510 +
  40.511 +
  40.512 +/*
  40.513 + * The DER encoder of the SEQUENCE type.
  40.514 + */
  40.515 +asn_enc_rval_t
  40.516 +SEQUENCE_encode_der(asn_TYPE_descriptor_t *td,
  40.517 +	void *sptr, int tag_mode, ber_tlv_tag_t tag,
  40.518 +	asn_app_consume_bytes_f *cb, void *app_key) {
  40.519 +	size_t computed_size = 0;
  40.520 +	asn_enc_rval_t erval;
  40.521 +	ssize_t ret;
  40.522 +	int edx;
  40.523 +
  40.524 +	ASN_DEBUG("%s %s as SEQUENCE",
  40.525 +		cb?"Encoding":"Estimating", td->name);
  40.526 +
  40.527 +	/*
  40.528 +	 * Gather the length of the underlying members sequence.
  40.529 +	 */
  40.530 +	for(edx = 0; edx < td->elements_count; edx++) {
  40.531 +		asn_TYPE_member_t *elm = &td->elements[edx];
  40.532 +		void *memb_ptr;
  40.533 +		if(elm->flags & ATF_POINTER) {
  40.534 +			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
  40.535 +			if(!memb_ptr) {
  40.536 +				if(elm->optional) continue;
  40.537 +				/* Mandatory element is missing */
  40.538 +				_ASN_ENCODE_FAILED;
  40.539 +			}
  40.540 +		} else {
  40.541 +			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
  40.542 +		}
  40.543 +		erval = elm->type->der_encoder(elm->type, memb_ptr,
  40.544 +			elm->tag_mode, elm->tag,
  40.545 +			0, 0);
  40.546 +		if(erval.encoded == -1)
  40.547 +			return erval;
  40.548 +		computed_size += erval.encoded;
  40.549 +		ASN_DEBUG("Member %d %s estimated %ld bytes",
  40.550 +			edx, elm->name, (long)erval.encoded);
  40.551 +	}
  40.552 +
  40.553 +	/*
  40.554 +	 * Encode the TLV for the sequence itself.
  40.555 +	 */
  40.556 +	ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
  40.557 +	ASN_DEBUG("Wrote tags: %ld (+%ld)", (long)ret, (long)computed_size);
  40.558 +	if(ret == -1)
  40.559 +		_ASN_ENCODE_FAILED;
  40.560 +	erval.encoded = computed_size + ret;
  40.561 +
  40.562 +	if(!cb) _ASN_ENCODED_OK(erval);
  40.563 +
  40.564 +	/*
  40.565 +	 * Encode all members.
  40.566 +	 */
  40.567 +	for(edx = 0; edx < td->elements_count; edx++) {
  40.568 +		asn_TYPE_member_t *elm = &td->elements[edx];
  40.569 +		asn_enc_rval_t tmperval;
  40.570 +		void *memb_ptr;
  40.571 +
  40.572 +		if(elm->flags & ATF_POINTER) {
  40.573 +			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
  40.574 +			if(!memb_ptr) continue;
  40.575 +		} else {
  40.576 +			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
  40.577 +		}
  40.578 +		tmperval = elm->type->der_encoder(elm->type, memb_ptr,
  40.579 +			elm->tag_mode, elm->tag,
  40.580 +			cb, app_key);
  40.581 +		if(tmperval.encoded == -1)
  40.582 +			return tmperval;
  40.583 +		computed_size -= tmperval.encoded;
  40.584 +		ASN_DEBUG("Member %d %s of SEQUENCE %s encoded in %ld bytes",
  40.585 +			edx, elm->name, td->name, (long)tmperval.encoded);
  40.586 +	}
  40.587 +
  40.588 +	if(computed_size != 0)
  40.589 +		/*
  40.590 +		 * Encoded size is not equal to the computed size.
  40.591 +		 */
  40.592 +		_ASN_ENCODE_FAILED;
  40.593 +
  40.594 +	_ASN_ENCODED_OK(erval);
  40.595 +}
  40.596 +
  40.597 +
  40.598 +#undef	XER_ADVANCE
  40.599 +#define	XER_ADVANCE(num_bytes)	do {			\
  40.600 +		size_t num = num_bytes;			\
  40.601 +		buf_ptr = ((const char *)buf_ptr) + num;\
  40.602 +		size -= num;				\
  40.603 +		consumed_myself += num;			\
  40.604 +	} while(0)
  40.605 +
  40.606 +/*
  40.607 + * Decode the XER (XML) data.
  40.608 + */
  40.609 +asn_dec_rval_t
  40.610 +SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
  40.611 +	void **struct_ptr, const char *opt_mname,
  40.612 +		const void *buf_ptr, size_t size) {
  40.613 +	/*
  40.614 +	 * Bring closer parts of structure description.
  40.615 +	 */
  40.616 +	asn_SEQUENCE_specifics_t *specs
  40.617 +		= (asn_SEQUENCE_specifics_t *)td->specifics;
  40.618 +	asn_TYPE_member_t *elements = td->elements;
  40.619 +	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
  40.620 +
  40.621 +	/*
  40.622 +	 * ... and parts of the structure being constructed.
  40.623 +	 */
  40.624 +	void *st = *struct_ptr;	/* Target structure. */
  40.625 +	asn_struct_ctx_t *ctx;	/* Decoder context */
  40.626 +
  40.627 +	asn_dec_rval_t rval;		/* Return value from a decoder */
  40.628 +	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
  40.629 +	int edx;			/* Element index */
  40.630 +	int edx_end;
  40.631 +
  40.632 +	/*
  40.633 +	 * Create the target structure if it is not present already.
  40.634 +	 */
  40.635 +	if(st == 0) {
  40.636 +		st = *struct_ptr = CALLOC(1, specs->struct_size);
  40.637 +		if(st == 0) RETURN(RC_FAIL);
  40.638 +	}
  40.639 +
  40.640 +	/*
  40.641 +	 * Restore parsing context.
  40.642 +	 */
  40.643 +	ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
  40.644 +
  40.645 +
  40.646 +	/*
  40.647 +	 * Phases of XER/XML processing:
  40.648 +	 * Phase 0: Check that the opening tag matches our expectations.
  40.649 +	 * Phase 1: Processing body and reacting on closing tag.
  40.650 +	 * Phase 2: Processing inner type.
  40.651 +	 * Phase 3: Skipping unknown extensions.
  40.652 +	 * Phase 4: PHASED OUT
  40.653 +	 */
  40.654 +	for(edx = ctx->step; ctx->phase <= 3;) {
  40.655 +		pxer_chunk_type_e ch_type;	/* XER chunk type */
  40.656 +		ssize_t ch_size;		/* Chunk size */
  40.657 +		xer_check_tag_e tcv;		/* Tag check value */
  40.658 +		asn_TYPE_member_t *elm;
  40.659 +		int n;
  40.660 +
  40.661 +		/*
  40.662 +		 * Go inside the inner member of a sequence.
  40.663 +		 */
  40.664 +		if(ctx->phase == 2) {
  40.665 +			asn_dec_rval_t tmprval;
  40.666 +			void *memb_ptr;		/* Pointer to the member */
  40.667 +			void **memb_ptr2;	/* Pointer to that pointer */
  40.668 +
  40.669 +			elm = &td->elements[edx];
  40.670 +
  40.671 +			if(elm->flags & ATF_POINTER) {
  40.672 +				/* Member is a pointer to another structure */
  40.673 +				memb_ptr2 = (void **)((char *)st + elm->memb_offset);
  40.674 +			} else {
  40.675 +				memb_ptr = (char *)st + elm->memb_offset;
  40.676 +				memb_ptr2 = &memb_ptr;
  40.677 +			}
  40.678 +
  40.679 +			/* Invoke the inner type decoder, m.b. multiple times */
  40.680 +			tmprval = elm->type->xer_decoder(opt_codec_ctx,
  40.681 +					elm->type, memb_ptr2, elm->name,
  40.682 +					buf_ptr, size);
  40.683 +			XER_ADVANCE(tmprval.consumed);
  40.684 +			if(tmprval.code != RC_OK)
  40.685 +				RETURN(tmprval.code);
  40.686 +			ctx->phase = 1;	/* Back to body processing */
  40.687 +			ctx->step = ++edx;
  40.688 +			ASN_DEBUG("XER/SEQUENCE phase => %d, step => %d",
  40.689 +				ctx->phase, ctx->step);
  40.690 +			/* Fall through */
  40.691 +		}
  40.692 +
  40.693 +		/*
  40.694 +		 * Get the next part of the XML stream.
  40.695 +		 */
  40.696 +		ch_size = xer_next_token(&ctx->context, buf_ptr, size,
  40.697 +			&ch_type);
  40.698 +		switch(ch_size) {
  40.699 +		case -1: RETURN(RC_FAIL);
  40.700 +		case 0:  RETURN(RC_WMORE);
  40.701 +		default:
  40.702 +			switch(ch_type) {
  40.703 +			case PXER_COMMENT:	/* Got XML comment */
  40.704 +			case PXER_TEXT:		/* Ignore free-standing text */
  40.705 +				XER_ADVANCE(ch_size);	/* Skip silently */
  40.706 +				continue;
  40.707 +			case PXER_TAG:
  40.708 +				break;	/* Check the rest down there */
  40.709 +			}
  40.710 +		}
  40.711 +
  40.712 +		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
  40.713 +		ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d [%s]",
  40.714 +			tcv, ctx->phase, xml_tag);
  40.715 +
  40.716 +		/* Skip the extensions section */
  40.717 +		if(ctx->phase == 3) {
  40.718 +			switch(xer_skip_unknown(tcv, &ctx->left)) {
  40.719 +			case -1:
  40.720 +				ctx->phase = 4;
  40.721 +				RETURN(RC_FAIL);
  40.722 +			case 0:
  40.723 +				XER_ADVANCE(ch_size);
  40.724 +				continue;
  40.725 +			case 1:
  40.726 +				XER_ADVANCE(ch_size);
  40.727 +				ctx->phase = 1;
  40.728 +				continue;
  40.729 +			case 2:
  40.730 +				ctx->phase = 1;
  40.731 +				break;
  40.732 +			}
  40.733 +		}
  40.734 +
  40.735 +		switch(tcv) {
  40.736 +		case XCT_CLOSING:
  40.737 +			if(ctx->phase == 0) break;
  40.738 +			ctx->phase = 0;
  40.739 +			/* Fall through */
  40.740 +		case XCT_BOTH:
  40.741 +			if(ctx->phase == 0) {
  40.742 +				if(edx >= td->elements_count
  40.743 +				   ||
  40.744 +				   /* Explicit OPTIONAL specs reaches the end */
  40.745 +				    (edx + elements[edx].optional
  40.746 +					== td->elements_count)
  40.747 +				   ||
  40.748 +				   /* All extensions are optional */
  40.749 +				   (IN_EXTENSION_GROUP(specs, edx)
  40.750 +					&& specs->ext_before
  40.751 +						> td->elements_count)
  40.752 +				) {
  40.753 +					XER_ADVANCE(ch_size);
  40.754 +					ctx->phase = 4;	/* Phase out */
  40.755 +					RETURN(RC_OK);
  40.756 +				} else {
  40.757 +					ASN_DEBUG("Premature end of XER SEQUENCE");
  40.758 +					RETURN(RC_FAIL);
  40.759 +				}
  40.760 +			}
  40.761 +			/* Fall through */
  40.762 +		case XCT_OPENING:
  40.763 +			if(ctx->phase == 0) {
  40.764 +				XER_ADVANCE(ch_size);
  40.765 +				ctx->phase = 1;	/* Processing body phase */
  40.766 +				continue;
  40.767 +			}
  40.768 +			/* Fall through */
  40.769 +		case XCT_UNKNOWN_OP:
  40.770 +		case XCT_UNKNOWN_BO:
  40.771 +
  40.772 +			ASN_DEBUG("XER/SEQUENCE: tcv=%d, ph=%d, edx=%d",
  40.773 +				tcv, ctx->phase, edx);
  40.774 +			if(ctx->phase != 1) {
  40.775 +				break;	/* Really unexpected */
  40.776 +			}
  40.777 +
  40.778 +			if(edx < td->elements_count) {
  40.779 +				/*
  40.780 +				 * Search which member corresponds to this tag.
  40.781 +				 */
  40.782 +				edx_end = edx + elements[edx].optional + 1;
  40.783 +				if(edx_end > td->elements_count)
  40.784 +					edx_end = td->elements_count;
  40.785 +				for(n = edx; n < edx_end; n++) {
  40.786 +					elm = &td->elements[n];
  40.787 +					tcv = xer_check_tag(buf_ptr,
  40.788 +						ch_size, elm->name);
  40.789 +					switch(tcv) {
  40.790 +					case XCT_BOTH:
  40.791 +					case XCT_OPENING:
  40.792 +						/*
  40.793 +						 * Process this member.
  40.794 +						 */
  40.795 +						ctx->step = edx = n;
  40.796 +						ctx->phase = 2;
  40.797 +						break;
  40.798 +					case XCT_UNKNOWN_OP:
  40.799 +					case XCT_UNKNOWN_BO:
  40.800 +						continue;
  40.801 +					default:
  40.802 +						n = edx_end;
  40.803 +						break;	/* Phase out */
  40.804 +					}
  40.805 +					break;
  40.806 +				}
  40.807 +				if(n != edx_end)
  40.808 +					continue;
  40.809 +			} else {
  40.810 +				ASN_DEBUG("Out of defined members: %d/%d",
  40.811 +					edx, td->elements_count);
  40.812 +			}
  40.813 +
  40.814 +			/* It is expected extension */
  40.815 +			if(IN_EXTENSION_GROUP(specs,
  40.816 +				edx + (edx < td->elements_count
  40.817 +					? elements[edx].optional : 0))) {
  40.818 +				ASN_DEBUG("Got anticipated extension at %d",
  40.819 +					edx);
  40.820 +				/*
  40.821 +				 * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
  40.822 +				 * By using a mask. Only record a pure
  40.823 +				 * <opening> tags.
  40.824 +				 */
  40.825 +				if(tcv & XCT_CLOSING) {
  40.826 +					/* Found </extension> without body */
  40.827 +				} else {
  40.828 +					ctx->left = 1;
  40.829 +					ctx->phase = 3;	/* Skip ...'s */
  40.830 +				}
  40.831 +				XER_ADVANCE(ch_size);
  40.832 +				continue;
  40.833 +			}
  40.834 +
  40.835 +			/* Fall through */
  40.836 +		default:
  40.837 +			break;
  40.838 +		}
  40.839 +
  40.840 +		ASN_DEBUG("Unexpected XML tag in SEQUENCE [%c%c%c%c%c%c]",
  40.841 +			size>0?((const char *)buf_ptr)[0]:'.',
  40.842 +			size>1?((const char *)buf_ptr)[1]:'.',
  40.843 +			size>2?((const char *)buf_ptr)[2]:'.',
  40.844 +			size>3?((const char *)buf_ptr)[3]:'.',
  40.845 +			size>4?((const char *)buf_ptr)[4]:'.',
  40.846 +			size>5?((const char *)buf_ptr)[5]:'.');
  40.847 +		break;
  40.848 +	}
  40.849 +
  40.850 +	ctx->phase = 4;	/* "Phase out" on hard failure */
  40.851 +	RETURN(RC_FAIL);
  40.852 +}
  40.853 +
  40.854 +asn_enc_rval_t
  40.855 +SEQUENCE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
  40.856 +	int ilevel, enum xer_encoder_flags_e flags,
  40.857 +		asn_app_consume_bytes_f *cb, void *app_key) {
  40.858 +	asn_enc_rval_t er;
  40.859 +	int xcan = (flags & XER_F_CANONICAL);
  40.860 +	int edx;
  40.861 +
  40.862 +	if(!sptr)
  40.863 +		_ASN_ENCODE_FAILED;
  40.864 +
  40.865 +	er.encoded = 0;
  40.866 +
  40.867 +	for(edx = 0; edx < td->elements_count; edx++) {
  40.868 +		asn_enc_rval_t tmper;
  40.869 +		asn_TYPE_member_t *elm = &td->elements[edx];
  40.870 +		void *memb_ptr;
  40.871 +		const char *mname = elm->name;
  40.872 +		unsigned int mlen = strlen(mname);
  40.873 +
  40.874 +		if(elm->flags & ATF_POINTER) {
  40.875 +			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
  40.876 +			if(!memb_ptr) {
  40.877 +				if(elm->optional)
  40.878 +					continue;
  40.879 +				/* Mandatory element is missing */
  40.880 +				_ASN_ENCODE_FAILED;
  40.881 +			}
  40.882 +		} else {
  40.883 +			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
  40.884 +		}
  40.885 +
  40.886 +		if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel);
  40.887 +		_ASN_CALLBACK3("<", 1, mname, mlen, ">", 1);
  40.888 +
  40.889 +		/* Print the member itself */
  40.890 +		tmper = elm->type->xer_encoder(elm->type, memb_ptr,
  40.891 +			ilevel + 1, flags, cb, app_key);
  40.892 +		if(tmper.encoded == -1) return tmper;
  40.893 +
  40.894 +		_ASN_CALLBACK3("</", 2, mname, mlen, ">", 1);
  40.895 +		er.encoded += 5 + (2 * mlen) + tmper.encoded;
  40.896 +	}
  40.897 +
  40.898 +	if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1);
  40.899 +
  40.900 +	_ASN_ENCODED_OK(er);
  40.901 +cb_failed:
  40.902 +	_ASN_ENCODE_FAILED;
  40.903 +}
  40.904 +
  40.905 +int
  40.906 +SEQUENCE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
  40.907 +		asn_app_consume_bytes_f *cb, void *app_key) {
  40.908 +	int edx;
  40.909 +	int ret;
  40.910 +
  40.911 +	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
  40.912 +
  40.913 +	/* Dump preamble */
  40.914 +	if(cb(td->name, strlen(td->name), app_key) < 0
  40.915 +	|| cb(" ::= {", 6, app_key) < 0)
  40.916 +		return -1;
  40.917 +
  40.918 +	for(edx = 0; edx < td->elements_count; edx++) {
  40.919 +		asn_TYPE_member_t *elm = &td->elements[edx];
  40.920 +		const void *memb_ptr;
  40.921 +
  40.922 +		if(elm->flags & ATF_POINTER) {
  40.923 +			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
  40.924 +			if(!memb_ptr) {
  40.925 +				if(elm->optional) continue;
  40.926 +				/* Print <absent> line */
  40.927 +				/* Fall through */
  40.928 +			}
  40.929 +		} else {
  40.930 +			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
  40.931 +		}
  40.932 +
  40.933 +		/* Indentation */
  40.934 +		_i_INDENT(1);
  40.935 +
  40.936 +		/* Print the member's name and stuff */
  40.937 +		if(cb(elm->name, strlen(elm->name), app_key) < 0
  40.938 +		|| cb(": ", 2, app_key) < 0)
  40.939 +			return -1;
  40.940 +
  40.941 +		/* Print the member itself */
  40.942 +		ret = elm->type->print_struct(elm->type, memb_ptr, ilevel + 1,
  40.943 +			cb, app_key);
  40.944 +		if(ret) return ret;
  40.945 +	}
  40.946 +
  40.947 +	ilevel--;
  40.948 +	_i_INDENT(1);
  40.949 +
  40.950 +	return (cb("}", 1, app_key) < 0) ? -1 : 0;
  40.951 +}
  40.952 +
  40.953 +void
  40.954 +SEQUENCE_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
  40.955 +	int edx;
  40.956 +
  40.957 +	if(!td || !sptr)
  40.958 +		return;
  40.959 +
  40.960 +	ASN_DEBUG("Freeing %s as SEQUENCE", td->name);
  40.961 +
  40.962 +	for(edx = 0; edx < td->elements_count; edx++) {
  40.963 +		asn_TYPE_member_t *elm = &td->elements[edx];
  40.964 +		void *memb_ptr;
  40.965 +		if(elm->flags & ATF_POINTER) {
  40.966 +			memb_ptr = *(void **)((char *)sptr + elm->memb_offset);
  40.967 +			if(memb_ptr)
  40.968 +				ASN_STRUCT_FREE(*elm->type, memb_ptr);
  40.969 +		} else {
  40.970 +			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
  40.971 +			ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr);
  40.972 +		}
  40.973 +	}
  40.974 +
  40.975 +	if(!contents_only) {
  40.976 +		FREEMEM(sptr);
  40.977 +	}
  40.978 +}
  40.979 +
  40.980 +int
  40.981 +SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
  40.982 +		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
  40.983 +	int edx;
  40.984 +
  40.985 +	if(!sptr) {
  40.986 +		_ASN_CTFAIL(app_key, td, sptr,
  40.987 +			"%s: value not given (%s:%d)",
  40.988 +			td->name, __FILE__, __LINE__);
  40.989 +		return -1;
  40.990 +	}
  40.991 +
  40.992 +	/*
  40.993 +	 * Iterate over structure members and check their validity.
  40.994 +	 */
  40.995 +	for(edx = 0; edx < td->elements_count; edx++) {
  40.996 +		asn_TYPE_member_t *elm = &td->elements[edx];
  40.997 +		const void *memb_ptr;
  40.998 +
  40.999 +		if(elm->flags & ATF_POINTER) {
 40.1000 +			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
 40.1001 +			if(!memb_ptr) {
 40.1002 +				if(elm->optional)
 40.1003 +					continue;
 40.1004 +				_ASN_CTFAIL(app_key, td, sptr,
 40.1005 +				"%s: mandatory element %s absent (%s:%d)",
 40.1006 +				td->name, elm->name, __FILE__, __LINE__);
 40.1007 +				return -1;
 40.1008 +			}
 40.1009 +		} else {
 40.1010 +			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 40.1011 +		}
 40.1012 +
 40.1013 +		if(elm->memb_constraints) {
 40.1014 +			int ret = elm->memb_constraints(elm->type, memb_ptr,
 40.1015 +				ctfailcb, app_key);
 40.1016 +			if(ret) return ret;
 40.1017 +		} else {
 40.1018 +			int ret = elm->type->check_constraints(elm->type,
 40.1019 +				memb_ptr, ctfailcb, app_key);
 40.1020 +			if(ret) return ret;
 40.1021 +			/*
 40.1022 +			 * Cannot inherit it earlier:
 40.1023 +			 * need to make sure we get the updated version.
 40.1024 +			 */
 40.1025 +			elm->memb_constraints = elm->type->check_constraints;
 40.1026 +		}
 40.1027 +	}
 40.1028 +
 40.1029 +	return 0;
 40.1030 +}
 40.1031 +
 40.1032 +asn_dec_rval_t
 40.1033 +SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
 40.1034 +	asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
 40.1035 +	asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
 40.1036 +	void *st = *sptr;	/* Target structure. */
 40.1037 +	int extpresent;		/* Extension additions are present */
 40.1038 +	uint8_t *opres;		/* Presence of optional root members */
 40.1039 +	asn_per_data_t opmd;
 40.1040 +	asn_dec_rval_t rv;
 40.1041 +	int edx;
 40.1042 +
 40.1043 +	(void)constraints;
 40.1044 +
 40.1045 +	if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
 40.1046 +		_ASN_DECODE_FAILED;
 40.1047 +
 40.1048 +	if(!st) {
 40.1049 +		st = *sptr = CALLOC(1, specs->struct_size);
 40.1050 +		if(!st) _ASN_DECODE_FAILED;
 40.1051 +	}
 40.1052 +
 40.1053 +	ASN_DEBUG("Decoding %s as SEQUENCE (UPER)", td->name);
 40.1054 +
 40.1055 +	/* Handle extensions */
 40.1056 +	if(specs->ext_before >= 0) {
 40.1057 +		extpresent = per_get_few_bits(pd, 1);
 40.1058 +		if(extpresent < 0) _ASN_DECODE_STARVED;
 40.1059 +	} else {
 40.1060 +		extpresent = 0;
 40.1061 +	}
 40.1062 +
 40.1063 +	/* Prepare a place and read-in the presence bitmap */
 40.1064 +	memset(&opmd, 0, sizeof(opmd));
 40.1065 +	if(specs->roms_count) {
 40.1066 +		opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1);
 40.1067 +		if(!opres) _ASN_DECODE_FAILED;
 40.1068 +		/* Get the presence map */
 40.1069 +		if(per_get_many_bits(pd, opres, 0, specs->roms_count)) {
 40.1070 +			FREEMEM(opres);
 40.1071 +			_ASN_DECODE_STARVED;
 40.1072 +		}
 40.1073 +		opmd.buffer = opres;
 40.1074 +		opmd.nbits = specs->roms_count;
 40.1075 +		ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)",
 40.1076 +			td->name, specs->roms_count, *opres);
 40.1077 +	} else {
 40.1078 +		opres = 0;
 40.1079 +	}
 40.1080 +
 40.1081 +	/*
 40.1082 +	 * Get the sequence ROOT elements.
 40.1083 +	 */
 40.1084 +	for(edx = 0; edx < td->elements_count; edx++) {
 40.1085 +		asn_TYPE_member_t *elm = &td->elements[edx];
 40.1086 +		void *memb_ptr;		/* Pointer to the member */
 40.1087 +		void **memb_ptr2;	/* Pointer to that pointer */
 40.1088 +
 40.1089 +		if(IN_EXTENSION_GROUP(specs, edx))
 40.1090 +			continue;
 40.1091 +
 40.1092 +		/* Fetch the pointer to this member */
 40.1093 +		if(elm->flags & ATF_POINTER) {
 40.1094 +			memb_ptr2 = (void **)((char *)st + elm->memb_offset);
 40.1095 +		} else {
 40.1096 +			memb_ptr = (char *)st + elm->memb_offset;
 40.1097 +			memb_ptr2 = &memb_ptr;
 40.1098 +		}
 40.1099 +
 40.1100 +		/* Deal with optionality */
 40.1101 +		if(elm->optional) {
 40.1102 +			int present = per_get_few_bits(&opmd, 1);
 40.1103 +			ASN_DEBUG("Member %s->%s is optional, p=%d (%d->%d)",
 40.1104 +				td->name, elm->name, present,
 40.1105 +				(int)opmd.nboff, (int)opmd.nbits);
 40.1106 +			if(present == 0) {
 40.1107 +				/* This element is not present */
 40.1108 +				if(elm->default_value) {
 40.1109 +					/* Fill-in DEFAULT */
 40.1110 +					if(elm->default_value(1, memb_ptr2)) {
 40.1111 +						FREEMEM(opres);
 40.1112 +						_ASN_DECODE_FAILED;
 40.1113 +					}
 40.1114 +					ASN_DEBUG("Filled-in default");
 40.1115 +				}
 40.1116 +				/* The member is just not present */
 40.1117 +				continue;
 40.1118 +			}
 40.1119 +			/* Fall through */
 40.1120 +		}
 40.1121 +
 40.1122 +		/* Fetch the member from the stream */
 40.1123 +		ASN_DEBUG("Decoding member %s in %s", elm->name, td->name);
 40.1124 +		rv = elm->type->uper_decoder(opt_codec_ctx, elm->type,
 40.1125 +			elm->per_constraints, memb_ptr2, pd);
 40.1126 +		if(rv.code != RC_OK) {
 40.1127 +			ASN_DEBUG("Failed decode %s in %s",
 40.1128 +				elm->name, td->name);
 40.1129 +			FREEMEM(opres);
 40.1130 +			return rv;
 40.1131 +		}
 40.1132 +	}
 40.1133 +
 40.1134 +	/* Optionality map is not needed anymore */
 40.1135 +	FREEMEM(opres);
 40.1136 +
 40.1137 +	/*
 40.1138 +	 * Deal with extensions.
 40.1139 +	 */
 40.1140 +	if(extpresent) {
 40.1141 +		ssize_t bmlength;
 40.1142 +		uint8_t *epres;		/* Presence of extension members */
 40.1143 +		asn_per_data_t epmd;
 40.1144 +
 40.1145 +		bmlength = uper_get_nslength(pd);
 40.1146 +		if(bmlength < 0) _ASN_DECODE_STARVED;
 40.1147 +
 40.1148 +		ASN_DEBUG("Extensions %ld present in %s", (long)bmlength, td->name);
 40.1149 +
 40.1150 +		epres = (uint8_t *)MALLOC((bmlength + 15) >> 3);
 40.1151 +		if(!epres) _ASN_DECODE_STARVED;
 40.1152 +
 40.1153 +		/* Get the extensions map */
 40.1154 +		if(per_get_many_bits(pd, epres, 0, bmlength))
 40.1155 +			_ASN_DECODE_STARVED;
 40.1156 +
 40.1157 +		memset(&epmd, 0, sizeof(epmd));
 40.1158 +		epmd.buffer = epres;
 40.1159 +		epmd.nbits = bmlength;
 40.1160 +		ASN_DEBUG("Read in extensions bitmap for %s of %ld bits (%x..)",
 40.1161 +			td->name, (long)bmlength, *epres);
 40.1162 +
 40.1163 +	    /* Go over extensions and read them in */
 40.1164 +	    for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
 40.1165 +		asn_TYPE_member_t *elm = &td->elements[edx];
 40.1166 +		void *memb_ptr;		/* Pointer to the member */
 40.1167 +		void **memb_ptr2;	/* Pointer to that pointer */
 40.1168 +		int present;
 40.1169 +
 40.1170 +		if(!IN_EXTENSION_GROUP(specs, edx)) {
 40.1171 +			ASN_DEBUG("%d is not extension", edx);
 40.1172 +			continue;
 40.1173 +		}
 40.1174 +
 40.1175 +		/* Fetch the pointer to this member */
 40.1176 +		if(elm->flags & ATF_POINTER) {
 40.1177 +			memb_ptr2 = (void **)((char *)st + elm->memb_offset);
 40.1178 +		} else {
 40.1179 +			memb_ptr = (void *)((char *)st + elm->memb_offset);
 40.1180 +			memb_ptr2 = &memb_ptr;
 40.1181 +		}
 40.1182 +
 40.1183 +		present = per_get_few_bits(&epmd, 1);
 40.1184 +		if(present <= 0) {
 40.1185 +			if(present < 0) break;	/* No more extensions */
 40.1186 +			continue;
 40.1187 +		}
 40.1188 +
 40.1189 +		ASN_DEBUG("Decoding member %s in %s %p", elm->name, td->name, *memb_ptr2);
 40.1190 +		rv = uper_open_type_get(opt_codec_ctx, elm->type,
 40.1191 +			elm->per_constraints, memb_ptr2, pd);
 40.1192 +		if(rv.code != RC_OK) {
 40.1193 +			FREEMEM(epres);
 40.1194 +			return rv;
 40.1195 +		}
 40.1196 +	    }
 40.1197 +
 40.1198 +		/* Skip over overflow extensions which aren't present
 40.1199 +		 * in this system's version of the protocol */
 40.1200 +		for(;;) {
 40.1201 +			ASN_DEBUG("Getting overflow extensions");
 40.1202 +			switch(per_get_few_bits(&epmd, 1)) {
 40.1203 +			case -1: break;
 40.1204 +			case 0: continue;
 40.1205 +			default:
 40.1206 +				if(uper_open_type_skip(opt_codec_ctx, pd)) {
 40.1207 +					FREEMEM(epres);
 40.1208 +					_ASN_DECODE_STARVED;
 40.1209 +				}
 40.1210 +			}
 40.1211 +			break;
 40.1212 +		}
 40.1213 +
 40.1214 +		FREEMEM(epres);
 40.1215 +	}
 40.1216 +
 40.1217 +	/* Fill DEFAULT members in extensions */
 40.1218 +	for(edx = specs->roms_count; edx < specs->roms_count
 40.1219 +			+ specs->aoms_count; edx++) {
 40.1220 +		asn_TYPE_member_t *elm = &td->elements[edx];
 40.1221 +		void **memb_ptr2;	/* Pointer to member pointer */
 40.1222 +
 40.1223 +		if(!elm->default_value) continue;
 40.1224 +
 40.1225 +		/* Fetch the pointer to this member */
 40.1226 +		if(elm->flags & ATF_POINTER) {
 40.1227 +			memb_ptr2 = (void **)((char *)st
 40.1228 +					+ elm->memb_offset);
 40.1229 +			if(*memb_ptr2) continue;
 40.1230 +		} else {
 40.1231 +			continue;	/* Extensions are all optionals */
 40.1232 +		}
 40.1233 +
 40.1234 +		/* Set default value */
 40.1235 +		if(elm->default_value(1, memb_ptr2)) {
 40.1236 +			_ASN_DECODE_FAILED;
 40.1237 +		}
 40.1238 +	}
 40.1239 +
 40.1240 +	rv.consumed = 0;
 40.1241 +	rv.code = RC_OK;
 40.1242 +	return rv;
 40.1243 +}
 40.1244 +
 40.1245 +static int
 40.1246 +SEQUENCE_handle_extensions(asn_TYPE_descriptor_t *td, void *sptr,
 40.1247 +		asn_per_outp_t *po1, asn_per_outp_t *po2) {
 40.1248 +	asn_SEQUENCE_specifics_t *specs
 40.1249 +		= (asn_SEQUENCE_specifics_t *)td->specifics;
 40.1250 +	int exts_present = 0;
 40.1251 +	int exts_count = 0;
 40.1252 +	int edx;
 40.1253 +
 40.1254 +	if(specs->ext_before < 0)
 40.1255 +		return 0;
 40.1256 +
 40.1257 +	/* Find out which extensions are present */
 40.1258 +	for(edx = specs->ext_after + 1; edx < td->elements_count; edx++) {
 40.1259 +		asn_TYPE_member_t *elm = &td->elements[edx];
 40.1260 +		void *memb_ptr;		/* Pointer to the member */
 40.1261 +		void **memb_ptr2;	/* Pointer to that pointer */
 40.1262 +		int present;
 40.1263 +
 40.1264 +		if(!IN_EXTENSION_GROUP(specs, edx)) {
 40.1265 +			ASN_DEBUG("%s (@%d) is not extension", elm->type->name, edx);
 40.1266 +			continue;
 40.1267 +		}
 40.1268 +
 40.1269 +		/* Fetch the pointer to this member */
 40.1270 +		if(elm->flags & ATF_POINTER) {
 40.1271 +			memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
 40.1272 +			present = (*memb_ptr2 != 0);
 40.1273 +		} else {
 40.1274 +			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
 40.1275 +			memb_ptr2 = &memb_ptr;
 40.1276 +			present = 1;
 40.1277 +		}
 40.1278 +
 40.1279 +		ASN_DEBUG("checking %s (@%d) present => %d",
 40.1280 +			elm->type->name, edx, present);
 40.1281 +		exts_count++;
 40.1282 +		exts_present += present;
 40.1283 +
 40.1284 +		/* Encode as presence marker */
 40.1285 +		if(po1 && per_put_few_bits(po1, present, 1))
 40.1286 +			return -1;
 40.1287 +		/* Encode as open type field */
 40.1288 +		if(po2 && present && uper_open_type_put(elm->type,
 40.1289 +				elm->per_constraints, *memb_ptr2, po2))
 40.1290 +			return -1;
 40.1291 +
 40.1292 +	}
 40.1293 +
 40.1294 +	return exts_present ? exts_count : 0;
 40.1295 +}
 40.1296 +
 40.1297 +asn_enc_rval_t
 40.1298 +SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td,
 40.1299 +	asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
 40.1300 +	asn_SEQUENCE_specifics_t *specs
 40.1301 +		= (asn_SEQUENCE_specifics_t *)td->specifics;
 40.1302 +	asn_enc_rval_t er;
 40.1303 +	int n_extensions;
 40.1304 +	int edx;
 40.1305 +	int i;
 40.1306 +
 40.1307 +	(void)constraints;
 40.1308 +
 40.1309 +	if(!sptr)
 40.1310 +		_ASN_ENCODE_FAILED;
 40.1311 +
 40.1312 +	er.encoded = 0;
 40.1313 +
 40.1314 +	ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name);
 40.1315 +
 40.1316 +
 40.1317 +	/*
 40.1318 +	 * X.691#18.1 Whether structure is extensible
 40.1319 +	 * and whether to encode extensions
 40.1320 +	 */
 40.1321 +	if(specs->ext_before >= 0) {
 40.1322 +		n_extensions = SEQUENCE_handle_extensions(td, sptr, 0, 0);
 40.1323 +		per_put_few_bits(po, n_extensions ? 1 : 0, 1);
 40.1324 +	} else {
 40.1325 +		n_extensions = 0;	/* There are no extensions to encode */
 40.1326 +	}
 40.1327 +
 40.1328 +	/* Encode a presence bitmap */
 40.1329 +	for(i = 0; i < specs->roms_count; i++) {
 40.1330 +		asn_TYPE_member_t *elm;
 40.1331 +		void *memb_ptr;		/* Pointer to the member */
 40.1332 +		void **memb_ptr2;	/* Pointer to that pointer */
 40.1333 +		int present;
 40.1334 +
 40.1335 +		edx = specs->oms[i];
 40.1336 +		elm = &td->elements[edx];
 40.1337 +
 40.1338 +		/* Fetch the pointer to this member */
 40.1339 +		if(elm->flags & ATF_POINTER) {
 40.1340 +			memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
 40.1341 +			present = (*memb_ptr2 != 0);
 40.1342 +		} else {
 40.1343 +			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
 40.1344 +			memb_ptr2 = &memb_ptr;
 40.1345 +			present = 1;
 40.1346 +		}
 40.1347 +
 40.1348 +		/* Eliminate default values */
 40.1349 +		if(present && elm->default_value
 40.1350 +		&& elm->default_value(0, memb_ptr2) == 1)
 40.1351 +			present = 0;
 40.1352 +
 40.1353 +		ASN_DEBUG("Element %s %s %s->%s is %s",
 40.1354 +			elm->flags & ATF_POINTER ? "ptr" : "inline",
 40.1355 +			elm->default_value ? "def" : "wtv",
 40.1356 +			td->name, elm->name, present ? "present" : "absent");
 40.1357 +		if(per_put_few_bits(po, present, 1))
 40.1358 +			_ASN_ENCODE_FAILED;
 40.1359 +	}
 40.1360 +
 40.1361 +	/*
 40.1362 +	 * Encode the sequence ROOT elements.
 40.1363 +	 */
 40.1364 +	ASN_DEBUG("ext_after = %d, ec = %d, eb = %d", specs->ext_after, td->elements_count, specs->ext_before);
 40.1365 +	for(edx = 0; edx < ((specs->ext_after < 0)
 40.1366 +		? td->elements_count : specs->ext_before - 1); edx++) {
 40.1367 +
 40.1368 +		asn_TYPE_member_t *elm = &td->elements[edx];
 40.1369 +		void *memb_ptr;		/* Pointer to the member */
 40.1370 +		void **memb_ptr2;	/* Pointer to that pointer */
 40.1371 +
 40.1372 +		if(IN_EXTENSION_GROUP(specs, edx))
 40.1373 +			continue;
 40.1374 +
 40.1375 +		ASN_DEBUG("About to encode %s", elm->type->name);
 40.1376 +
 40.1377 +		/* Fetch the pointer to this member */
 40.1378 +		if(elm->flags & ATF_POINTER) {
 40.1379 +			memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
 40.1380 +			if(!*memb_ptr2) {
 40.1381 +				ASN_DEBUG("Element %s %d not present",
 40.1382 +					elm->name, edx);
 40.1383 +				if(elm->optional)
 40.1384 +					continue;
 40.1385 +				/* Mandatory element is missing */
 40.1386 +				_ASN_ENCODE_FAILED;
 40.1387 +			}
 40.1388 +		} else {
 40.1389 +			memb_ptr = (void *)((char *)sptr + elm->memb_offset);
 40.1390 +			memb_ptr2 = &memb_ptr;
 40.1391 +		}
 40.1392 +
 40.1393 +		/* Eliminate default values */
 40.1394 +		if(elm->default_value && elm->default_value(0, memb_ptr2) == 1)
 40.1395 +			continue;
 40.1396 +
 40.1397 +		ASN_DEBUG("Encoding %s->%s", td->name, elm->name);
 40.1398 +		er = elm->type->uper_encoder(elm->type, elm->per_constraints,
 40.1399 +			*memb_ptr2, po);
 40.1400 +		if(er.encoded == -1)
 40.1401 +			return er;
 40.1402 +	}
 40.1403 +
 40.1404 +	/* No extensions to encode */
 40.1405 +	if(!n_extensions) _ASN_ENCODED_OK(er);
 40.1406 +
 40.1407 +	ASN_DEBUG("Length of %d bit-map", n_extensions);
 40.1408 +	/* #18.8. Write down the presence bit-map length. */
 40.1409 +	if(uper_put_nslength(po, n_extensions))
 40.1410 +		_ASN_ENCODE_FAILED;
 40.1411 +
 40.1412 +	ASN_DEBUG("Bit-map of %d elements", n_extensions);
 40.1413 +	/* #18.7. Encoding the extensions presence bit-map. */
 40.1414 +	/* TODO: act upon NOTE in #18.7 for canonical PER */
 40.1415 +	if(SEQUENCE_handle_extensions(td, sptr, po, 0) != n_extensions)
 40.1416 +		_ASN_ENCODE_FAILED;
 40.1417 +
 40.1418 +	ASN_DEBUG("Writing %d extensions", n_extensions);
 40.1419 +	/* #18.9. Encode extensions as open type fields. */
 40.1420 +	if(SEQUENCE_handle_extensions(td, sptr, 0, po) != n_extensions)
 40.1421 +		_ASN_ENCODE_FAILED;
 40.1422 +
 40.1423 +	_ASN_ENCODED_OK(er);
 40.1424 +}
 40.1425 +
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/asn.1/constr_SEQUENCE.h	Wed May 11 20:06:23 2016 +0200
    41.3 @@ -0,0 +1,60 @@
    41.4 +/*-
    41.5 + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
    41.6 + * Redistribution and modifications are permitted subject to BSD license.
    41.7 + */
    41.8 +#ifndef	_CONSTR_SEQUENCE_H_
    41.9 +#define	_CONSTR_SEQUENCE_H_
   41.10 +
   41.11 +#include <asn_application.h>
   41.12 +
   41.13 +#ifdef __cplusplus
   41.14 +extern "C" {
   41.15 +#endif
   41.16 +
   41.17 +typedef struct asn_SEQUENCE_specifics_s {
   41.18 +	/*
   41.19 +	 * Target structure description.
   41.20 +	 */
   41.21 +	int struct_size;	/* Size of the target structure. */
   41.22 +	int ctx_offset;		/* Offset of the asn_struct_ctx_t member */
   41.23 +
   41.24 +	/*
   41.25 +	 * Tags to members mapping table (sorted).
   41.26 +	 */
   41.27 +	asn_TYPE_tag2member_t *tag2el;
   41.28 +	int tag2el_count;
   41.29 +
   41.30 +	/*
   41.31 +	 * Optional members of the extensions root (roms) or additions (aoms).
   41.32 +	 * Meaningful for PER.
   41.33 +	 */
   41.34 +	int *oms;		/* Optional MemberS */
   41.35 +	int  roms_count;	/* Root optional members count */
   41.36 +	int  aoms_count;	/* Additions optional members count */
   41.37 +
   41.38 +	/*
   41.39 +	 * Description of an extensions group.
   41.40 +	 */
   41.41 +	int ext_after;		/* Extensions start after this member */
   41.42 +	int ext_before;		/* Extensions stop before this member */
   41.43 +} asn_SEQUENCE_specifics_t;
   41.44 +
   41.45 +
   41.46 +/*
   41.47 + * A set specialized functions dealing with the SEQUENCE type.
   41.48 + */
   41.49 +asn_struct_free_f SEQUENCE_free;
   41.50 +asn_struct_print_f SEQUENCE_print;
   41.51 +asn_constr_check_f SEQUENCE_constraint;
   41.52 +ber_type_decoder_f SEQUENCE_decode_ber;
   41.53 +der_type_encoder_f SEQUENCE_encode_der;
   41.54 +xer_type_decoder_f SEQUENCE_decode_xer;
   41.55 +xer_type_encoder_f SEQUENCE_encode_xer;
   41.56 +per_type_decoder_f SEQUENCE_decode_uper;
   41.57 +per_type_encoder_f SEQUENCE_encode_uper;
   41.58 +
   41.59 +#ifdef __cplusplus
   41.60 +}
   41.61 +#endif
   41.62 +
   41.63 +#endif	/* _CONSTR_SEQUENCE_H_ */
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/asn.1/constr_SEQUENCE_OF.c	Wed May 11 20:06:23 2016 +0200
    42.3 @@ -0,0 +1,208 @@
    42.4 +/*-
    42.5 + * Copyright (c) 2003, 2004, 2006 Lev Walkin <vlm@lionet.info>.
    42.6 + * All rights reserved.
    42.7 + * Redistribution and modifications are permitted subject to BSD license.
    42.8 + */
    42.9 +#include <asn_internal.h>
   42.10 +#include <constr_SEQUENCE_OF.h>
   42.11 +#include <asn_SEQUENCE_OF.h>
   42.12 +
   42.13 +/*
   42.14 + * The DER encoder of the SEQUENCE OF type.
   42.15 + */
   42.16 +asn_enc_rval_t
   42.17 +SEQUENCE_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr,
   42.18 +	int tag_mode, ber_tlv_tag_t tag,
   42.19 +	asn_app_consume_bytes_f *cb, void *app_key) {
   42.20 +	asn_TYPE_member_t *elm = td->elements;
   42.21 +	asn_anonymous_sequence_ *list = _A_SEQUENCE_FROM_VOID(ptr);
   42.22 +	size_t computed_size = 0;
   42.23 +	ssize_t encoding_size = 0;
   42.24 +	asn_enc_rval_t erval;
   42.25 +	int edx;
   42.26 +
   42.27 +	ASN_DEBUG("Estimating size of SEQUENCE OF %s", td->name);
   42.28 +
   42.29 +	/*
   42.30 +	 * Gather the length of the underlying members sequence.
   42.31 +	 */
   42.32 +	for(edx = 0; edx < list->count; edx++) {
   42.33 +		void *memb_ptr = list->array[edx];
   42.34 +		if(!memb_ptr) continue;
   42.35 +		erval = elm->type->der_encoder(elm->type, memb_ptr,
   42.36 +			0, elm->tag,
   42.37 +			0, 0);
   42.38 +		if(erval.encoded == -1)
   42.39 +			return erval;
   42.40 +		computed_size += erval.encoded;
   42.41 +	}
   42.42 +
   42.43 +	/*
   42.44 +	 * Encode the TLV for the sequence itself.
   42.45 +	 */
   42.46 +	encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag,
   42.47 +		cb, app_key);
   42.48 +	if(encoding_size == -1) {
   42.49 +		erval.encoded = -1;
   42.50 +		erval.failed_type = td;
   42.51 +		erval.structure_ptr = ptr;
   42.52 +		return erval;
   42.53 +	}
   42.54 +
   42.55 +	computed_size += encoding_size;
   42.56 +	if(!cb) {
   42.57 +		erval.encoded = computed_size;
   42.58 +		_ASN_ENCODED_OK(erval);
   42.59 +	}
   42.60 +
   42.61 +	ASN_DEBUG("Encoding members of SEQUENCE OF %s", td->name);
   42.62 +
   42.63 +	/*
   42.64 +	 * Encode all members.
   42.65 +	 */
   42.66 +	for(edx = 0; edx < list->count; edx++) {
   42.67 +		void *memb_ptr = list->array[edx];
   42.68 +		if(!memb_ptr) continue;
   42.69 +		erval = elm->type->der_encoder(elm->type, memb_ptr,
   42.70 +			0, elm->tag,
   42.71 +			cb, app_key);
   42.72 +		if(erval.encoded == -1)
   42.73 +			return erval;
   42.74 +		encoding_size += erval.encoded;
   42.75 +	}
   42.76 +
   42.77 +	if(computed_size != (size_t)encoding_size) {
   42.78 +		/*
   42.79 +		 * Encoded size is not equal to the computed size.
   42.80 +		 */
   42.81 +		erval.encoded = -1;
   42.82 +		erval.failed_type = td;
   42.83 +		erval.structure_ptr = ptr;
   42.84 +	} else {
   42.85 +		erval.encoded = computed_size;
   42.86 +		erval.structure_ptr = 0;
   42.87 +		erval.failed_type = 0;
   42.88 +	}
   42.89 +
   42.90 +	return erval;
   42.91 +}
   42.92 +
   42.93 +asn_enc_rval_t
   42.94 +SEQUENCE_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
   42.95 +	int ilevel, enum xer_encoder_flags_e flags,
   42.96 +		asn_app_consume_bytes_f *cb, void *app_key) {
   42.97 +	asn_enc_rval_t er;
   42.98 +        asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics;
   42.99 +	asn_TYPE_member_t *elm = td->elements;
  42.100 +	asn_anonymous_sequence_ *list = _A_SEQUENCE_FROM_VOID(sptr);
  42.101 +	const char *mname = specs->as_XMLValueList
  42.102 +		? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag);
  42.103 +	unsigned int mlen = mname ? strlen(mname) : 0;
  42.104 +	int xcan = (flags & XER_F_CANONICAL);
  42.105 +	int i;
  42.106 +
  42.107 +	if(!sptr) _ASN_ENCODE_FAILED;
  42.108 +
  42.109 +	er.encoded = 0;
  42.110 +
  42.111 +	for(i = 0; i < list->count; i++) {
  42.112 +		asn_enc_rval_t tmper;
  42.113 +		void *memb_ptr = list->array[i];
  42.114 +		if(!memb_ptr) continue;
  42.115 +
  42.116 +		if(mname) {
  42.117 +			if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel);
  42.118 +			_ASN_CALLBACK3("<", 1, mname, mlen, ">", 1);
  42.119 +		}
  42.120 +
  42.121 +		tmper = elm->type->xer_encoder(elm->type, memb_ptr,
  42.122 +				ilevel + 1, flags, cb, app_key);
  42.123 +		if(tmper.encoded == -1) return tmper;
  42.124 +                if(tmper.encoded == 0 && specs->as_XMLValueList) {
  42.125 +                        const char *name = elm->type->xml_tag;
  42.126 +			size_t len = strlen(name);
  42.127 +			if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel + 1);
  42.128 +			_ASN_CALLBACK3("<", 1, name, len, "/>", 2);
  42.129 +                }
  42.130 +
  42.131 +		if(mname) {
  42.132 +			_ASN_CALLBACK3("</", 2, mname, mlen, ">", 1);
  42.133 +			er.encoded += 5;
  42.134 +		}
  42.135 +
  42.136 +		er.encoded += (2 * mlen) + tmper.encoded;
  42.137 +	}
  42.138 +