return NULL;
}
+ asn1->orig_stack = stack;
asn1->stack1 = stack1;
asn1->stack2 = silc_stack_alloc(0, stack);
if (!asn1->stack2) {
SilcBool silc_asn1_init(SilcAsn1 asn1, SilcStack stack)
{
+ asn1->orig_stack = stack;
+
asn1->stack1 = silc_stack_alloc(0, stack);
if (!asn1->stack1)
return FALSE;
}
fprintf(stdout, "Type %s [%d]\n",
- silc_asn1_tag_name(rtag), rtag);
+ silc_asn1_tag_name(rtag), (int)rtag);
if (renc == SILC_BER_ENC_PRIMITIVE)
len = len + rdata_len;
* SILC_ASN1_EXPLICIT, 100, boolval),
* SILC_ASN1_END);
*
+ *
+ * // Decode optional value, with SILC_ASN1_OPTIONAL the type must be
+ * // a pointer so that NULL can be returned if the type is not present.
+ * SilcBool *val;
+ *
+ * silc_asn1_decode(asn1, src,
+ * SILC_ASN1_OPTS(SILC_ASN1_OPTIONAL),
+ * SILC_ASN1_BOOLEAN(&val),
+ * SILC_ASN1_END);
+ *
+ * // If val == NULL, the optional value was not present
+ * if (val == NULL)
+ * error;
+ *
* SOURCE
*/
typedef enum {
/* ASN.1 encoder/decoder options (bitmask). These can be given
only with SILC_ASN1_OPTS macro at the start of encoding/decoding. */
- SILC_ASN1_ALLOC = 0x0400, /* Dynamically allocate results */
+ SILC_ASN1_ALLOC = 0x0400, /* Dynamically allocate results,
+ or if stack was given to
+ silc_asn1_alloc, they are allocated
+ and consumed from the stack. */
SILC_ASN1_ACCUMUL = 0x0800, /* Accumulate memory for results,
next call to silc_asn1_decode
will not cancel old results. */
*
* When this context is freed with silc_asn1_free all memory will be
* freed, and all encoded ASN.1 buffers becomes invalid. Also all
- * data that is returned by silc_asn1_decode function becomes invalid.
+ * data that is returned by silc_asn1_encode and silc_asn1_decode function
+ * becomes invalid, unless SILC_ASN1_ALLOC flag is used, in which case the
+ * memory is allocated from `stack' and the `stack' is consumed.
*
***/
SilcAsn1 silc_asn1_alloc(SilcStack stack);
*
* If the SILC_ASN1_OPTS macro with SILC_ASN1_ALLOC option is given then
* the `dest' is dynamically allocated and caller must free it by itself.
- * Alternatively if SILC_ASN1_ACCUMUL is given then memory is accumulated
- * from `asn1' for `dest' and it is freed only when silc_asn1_free or
- * silc_asn1_uninit is called. Next call to silc_asn1_encode will not
- * cancel the previous result, but will accumulate more memory for new
- * result.
+ * If the `stack' was given to silc_asn1_alloc, the SILC_ASN1_ALLOC will
+ * allocate from that stack and consume the stack. Alternatively if
+ * SILC_ASN1_ACCUMUL is given then memory is accumulated from `asn1' fo
+ * `dest' and it is freed only when silc_asn1_free or silc_asn1_uninit
+ * is called. Next call to silc_asn1_encode will not cancel the previous
+ * result, but will accumulate more memory for new result.
*
* The variable argument list is constructed by using various
* macros, for example SILC_ASN1_SEQUENCE, etc. The variable argument
*
* If the SILC_ASN1_OPTS macro with SILC_ASN1_ALLOC option is given then
* all results are dynamically allocated and caller must free them by
- * itself. Alternatively if SILC_ASN1_ACCUMUL is given then memory is
- * accumulated from `asn1' for results and they are freed only when the
- * silc_asn1_free or silc_asn1_uninit is called. Next calls to the
- * silc_asn1_decode will NOT invalidate the old results, but will
- * accumulate more memory for new results. If the SILC_ASN1_OPTS is not
- * given at all then the default allocation method (decribed above)
- * applies.
+ * itself. If the `stack' was given to silc_asn1_alloc, the SILC_ASN1_ALLOC
+ * will allocate from that stack and consume the stack. Alternatively if
+ * SILC_ASN1_ACCUMUL is given then memory is accumulated from `asn1' for
+ * results and they are freed only when the silc_asn1_free or
+ * silc_asn1_uninit is called. Next calls to the silc_asn1_decode will
+ * NOT invalidate the old results, but will accumulate more memory for new
+ * results. If the SILC_ASN1_OPTS is not given at all then the default
+ * allocation method (decribed above) applies.
*
* If caller needs to store the results even after `asn1' becomes invalid
* then call must either use SILC_ASN1_ALLOC option or duplicate the
* SYNOPSIS
*
* Decoding:
- * SILC_ASN1_CHOICE
+ * SILC_ASN1_CHOICE(&chosen)
*
* DESCRIPTION
*
* Macro used to specify choices in decoding. The choice list must
* be terminated with SILC_ASN1_END. There is no limit how many choices
- * can be specified in the list.
+ * can be specified in the list. The `chosen' is SilcUInt32 and its
+ * value tells which of the choice was found. First choice in the list
+ * has value 1, second value 2, and so on.
*
* EXAMPLE
*
* // Decode timeval that is either UTC or generalized time
* silc_asn1_decode(asn1, tree,
* SILC_ASN1_SEQUENCE,
- * SILC_ASN1_CHOICE,
+ * SILC_ASN1_CHOICE(&chosen),
* SILC_ASN1_UTC_TIME(&timeval),
* SILC_ASN1_GEN_TIME(&timeval),
* SILC_ASN1_END,
* SILC_ASN1_END, SILC_ASN1_END);
*
***/
-#define SILC_ASN1_CHOICE SILC_ASN1_U0(CHOICE)
+#define SILC_ASN1_CHOICE(x) SILC_ASN1_U1(CHOICE, x)
/****f* silcasn1/SilcASN1API/SILC_ASN1_BOOLEAN
*
*
* Encoding:
* SILC_ASN1_NULL
- * SILC_ASN1_NULL_T(opts, tag)
+ * SILC_ASN1_NULL_T(opts, tag, set)
*
* Decoding:
* SILC_ASN1_NULL
- * SILC_ASN1_NULL_T(opts, tag)
+ * SILC_ASN1_NULL_T(opts, tag, &set)
*
* DESCRIPTION
*
* Macro used to encode or decode null value.
*
- * The `opts' is SilcAsn1Options. The `tag' is a tag number.
+ * The `opts' is SilcAsn1Options. The `tag' is a tag number. In encoding
+ * `set' is SilcBool and if it is TRUE the NULL value will be encoded. If
+ * it is FALSE the SILC_ASN1_NULL will be ignored. In decoding the `set'
+ * is SilcBool and if it is TRUE the NULL value was present. This can be
+ * used to verify whether NULL was present if it is SILC_ASN1_OPTIONAL.
*
***/
-#define SILC_ASN1_NULL SILC_ASN1_U0(NULL)
-#define SILC_ASN1_NULL_T(o, t) SILC_ASN1_T0(NULL, 0, t)
+#define SILC_ASN1_NULL(x) SILC_ASN1_U1(NULL, x)
+#define SILC_ASN1_NULL_T(o, t, x) SILC_ASN1_T1(NULL, o, t, x)
/****f* silcasn1/SilcASN1API/SILC_ASN1_OID
*
#include "silcasn1.h"
#include "silcber.h"
+#define SILC_ASN1_STACK(stack, asn1) stack ? stack : asn1->orig_stack
+
/************************** ASN.1 Decoder routines **************************/
/* Internal SEQUENCE OF and SET OF decoder. This is used only when decoding
SilcBuffer *retb;
SilcUInt32 *retc, rtag;
const unsigned char *rdata;
- SilcUInt32 rdata_len, len = 0;
- SilcBool found = FALSE, rindef;
+ SilcUInt32 rdata_len, len = 0, *choice_index = NULL;
+ SilcBool found = FALSE, rindef, chosen = FALSE;
struct SilcAsn1SofStruct {
SilcAsn1Tag type;
if (type == SILC_ASN1_TAG_CHOICE) {
/* The sequence may consist of the following types. */
+ choice_index = va_arg(asn1->ap, SilcUInt32 *);
+ *choice_index = 0;
+
type = va_arg(asn1->ap, SilcUInt32);
assert(type != SILC_ASN1_END);
while (type != SILC_ASN1_END) {
- t = silc_smalloc(asn1->stack1, sizeof(*t));
+ t = silc_smalloc(SILC_ASN1_STACK(asn1->stack1, asn1), sizeof(*t));
if (!t)
goto out;
t->type = type;
}
} else {
/* The sequence consists of this type. */
- t = silc_smalloc(asn1->stack1, sizeof(*t));
+ t = silc_smalloc(SILC_ASN1_STACK(asn1->stack1, asn1), sizeof(*t));
if (!t)
goto out;
t->type = type;
found = FALSE;
silc_list_start(types);
while ((t = silc_list_get(types)) != SILC_LIST_END) {
+ if (choice_index && !chosen)
+ (*choice_index)++;
+
if (t->type != rtag)
continue;
- *retb = silc_srealloc(asn1->stack1, sizeof(**retb) * (*retc), *retb,
+ *retb = silc_srealloc(SILC_ASN1_STACK(asn1->stack1, asn1),
+ sizeof(**retb) * (*retc), *retb,
sizeof(**retb) * (*retc + 1));
if (*retb == NULL)
goto out;
SILC_LOG_DEBUG(("Decode %s [%d] from sequence of types",
silc_asn1_tag_name(rtag), rtag));
- /* Data is duplicated only if SILC_ASN1_ALLOC flag is set */
+ /* Data is duplicated only if SILC_ASN1_ALLOC flag is set, ie.
+ asn1->stack1 == NULL */
if (!asn1->stack1)
- rdata = silc_memdup(rdata - len, rdata_len + len);
+ rdata = silc_smemdup(asn1->orig_stack, rdata - len, rdata_len + len);
else
rdata = rdata - len;
rdata_len += len;
silc_buffer_set(&(*retb)[*retc], (unsigned char *)rdata, rdata_len);
(*retc)++;
found = TRUE;
+ chosen = TRUE;
break;
}
if (!asn1->stack1) {
silc_list_start(types);
while ((t = silc_list_get(types)) != SILC_LIST_END)
- silc_free(t);
+ silc_sfree(asn1->orig_stack, t);
}
return ret;
} \
if (name == NULL) \
break; \
- *name = silc_scalloc(asn1->stack1, 1, sizeof(**name)); \
+ *name = silc_scalloc(SILC_ASN1_STACK(stack1, asn1), \
+ 1, sizeof(**name)); \
if (*name == NULL) \
break; \
} else { \
#define SILC_ASN1_VA_FREE(opts, name) \
if ((opts) & SILC_ASN1_OPTIONAL) \
- silc_free(*name);
+ silc_sfree(SILC_ASN1_STACK(stack1, asn1), *name);
/* Decodes string to UTF-8 string which is our internal representation
of any string. */
ret = FALSE; \
goto fail; \
} \
- *s = silc_smalloc(stack1, *s_len + 1); \
+ *s = silc_smalloc(SILC_ASN1_STACK(stack1, asn1), *s_len + 1); \
if (*s) { \
silc_utf8_encode(rdata, rdata_len, (enc), *s, *s_len); \
(*s)[*s_len] = '\0'; \
SilcBerEncoding renc;
SilcUInt32 len = 0, rtag;
SilcBool ret, indef, rindef, found = FALSE, choice = FALSE;
+ SilcBool choice_found = FALSE;
const unsigned char *rdata;
- SilcUInt32 rdata_len;
+ SilcUInt32 rdata_len, *choice_index = NULL;
int i;
#ifdef SILC_DEBUG
having OPTIONAL flag set, except that at the end one must have
been found. */
if (type == SILC_ASN1_TAG_CHOICE) {
+ choice_index = va_arg(asn1->ap, SilcUInt32 *);
+ *choice_index = 0;
choice = TRUE;
SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
opts |= SILC_ASN1_OPTIONAL;
the node */
SILC_ASN1_VAD(asn1, opts, SilcBufferStruct, node);
- *node = silc_buffer_srealloc_size(stack1, *node, len + rdata_len);
+ *node = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1),
+ *node, len + rdata_len);
silc_buffer_put(*node, rdata - len, rdata_len + len);
break;
}
/* ANY_PRIMITIVE returns the raw data blob of any primitive type. */
SILC_ASN1_VAD(asn1, opts, SilcBufferStruct, prim);
- *prim = silc_buffer_srealloc_size(stack1, *prim, rdata_len);
+ *prim = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1),
+ *prim, rdata_len);
silc_buffer_put(*prim, rdata, rdata_len);
break;
}
SILC_ASN1_ARGS(asn1, rtype, rtag, rclass, ropts);
/* Decode the sequence recursively */
- ret = silc_asn1_decoder(asn1, stack1, rtype, rtag, rclass,
- ropts, src, depth + 1, FALSE);
+ ret = silc_asn1_decoder(asn1, SILC_ASN1_STACK(stack1, asn1),
+ rtype, rtag, rclass, ropts, src,
+ depth + 1, FALSE);
if (!ret)
goto fail;
break;
goto fail;
}
- silc_mp_sinit(asn1->stack1, *intval);
+ silc_mp_sinit(SILC_ASN1_STACK(stack1, asn1), *intval);
/* Check whether the integer is positive or negative */
if (rdata[0] & 0x80) {
goto fail;
}
- silc_stack_push(asn1->stack1, NULL);
- silc_mp_sinit(asn1->stack1, &z);
+ silc_stack_push(SILC_ASN1_STACK(stack1, asn1), NULL);
+ silc_mp_sinit(SILC_ASN1_STACK(stack1, asn1), &z);
silc_mp_bin2mp((unsigned char *)rdata, rdata_len, &z);
*(*intval) = silc_mp_get_ui(&z);
silc_mp_uninit(&z);
- silc_stack_pop(asn1->stack1);
+ silc_stack_pop(SILC_ASN1_STACK(stack1, asn1));
break;
}
silc_snprintf(tmpstr, sizeof(tmpstr) - 1, "%lu.%lu",
(unsigned long)(rdata[0] & 0xff) / 40,
(unsigned long)(rdata[0] & 0xff) % 40);
- silc_buffer_sstrformat(asn1->stack1, &tmpb, tmpstr, SILC_STR_END);
+ silc_buffer_sstrformat(SILC_ASN1_STACK(stack1, asn1),
+ &tmpb, tmpstr, SILC_STR_END);
/* Set rest of the OID values, each octet having 7 bits of the
OID value with bit 8 set. An octet not having bit 8 set
oid |= rdata[i];
memset(tmpstr, 0, sizeof(tmpstr));
- silc_snprintf(tmpstr, sizeof(tmpstr) - 1, ".%lu", (unsigned long)oid);
- silc_buffer_sstrformat(asn1->stack1, &tmpb, tmpstr, SILC_STR_END);
+ silc_snprintf(tmpstr, sizeof(tmpstr) - 1, ".%lu",
+ (unsigned long)oid);
+ silc_buffer_sstrformat(SILC_ASN1_STACK(stack1, asn1),
+ &tmpb, tmpstr, SILC_STR_END);
}
*oidstr = tmpb.head;
goto fail;
}
- *d = silc_smemdup(stack1, rdata + 1, rdata_len - 1);
+ *d = silc_smemdup(SILC_ASN1_STACK(stack1, asn1),
+ rdata + 1, rdata_len - 1);
*d_len = (rdata_len - 1) * 8;
break;
}
case SILC_ASN1_TAG_NULL:
{
+ SILC_ASN1_VAD(asn1, opts, SilcBool, val);
+
/* Decode empty BER block */
if (rdata_len != 0) {
SILC_LOG_DEBUG(("Malformed null value"));
goto fail;
}
+
+ *(*val) = TRUE;
break;
}
goto fail;
}
- *s = silc_smemdup(stack1, rdata, rdata_len);
+ *s = silc_smemdup(SILC_ASN1_STACK(stack1, asn1), rdata, rdata_len);
*s_len = rdata_len;
break;
}
{
/* Octet string. Take data as is. */
SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
- *s = silc_smemdup(stack1, rdata, rdata_len);
+ *s = silc_smemdup(SILC_ASN1_STACK(stack1, asn1), rdata, rdata_len);
*s_len = rdata_len;
break;
}
if (!found) {
/* No choices were found, error */
SILC_LOG_DEBUG(("Invalid ASN.1 choice: no choices present"));
+ *choice_index = 0;
ret = FALSE;
goto fail;
}
+ if (!choice_found) {
+ (*choice_index)++;
+ SILC_LOG_DEBUG(("Found choice %s type, index %d",
+ silc_asn1_tag_name(rtype), *choice_index));
+ }
+
/* Take next type and new BER object, choices are over */
choice = FALSE;
SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
}
if (choice) {
+ if (!choice_found)
+ (*choice_index)++;
+
/* Even if the choice was found we must go through rest of
the choices. */
if (found && len) {
- SILC_LOG_DEBUG(("Found choice %s type", silc_asn1_tag_name(rtype)));
+ choice_found = TRUE;
+ SILC_LOG_DEBUG(("Found choice %s type, index %d",
+ silc_asn1_tag_name(rtype), *choice_index));
rdata_len = len = 0;
}
opts |= SILC_ASN1_OPTIONAL;
SilcAsn1Options opts;
SilcBerClass ber_class;
SilcStackFrame frame1, frame2;
- SilcStack stack1 = NULL, stack2 = NULL;
+ SilcStack stack1 = NULL, stack2 = NULL, orig;
SilcBool ret;
if (!asn1)
va_start(asn1->ap, src);
+ orig = asn1->orig_stack;
+
/* Get the first arguments and call the decoder. */
SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
if (!type) {
stack2 = asn1->stack2;
asn1->stack1 = NULL;
asn1->stack2 = NULL;
+ asn1->orig_stack = orig;
}
if (o & SILC_ASN1_ACCUMUL) {
asn1->stack2 = stack2;
}
+ asn1->orig_stack = orig;
+
va_end(asn1->ap);
return ret;
#include "silcber.h"
#define SILC_ASN1_BUFFER_FREE(b, stack) if (!stack) silc_buffer_purge(b);
+#define SILC_ASN1_STACK(stack, asn1) stack ? stack : asn1->orig_stack
/************************** ASN.1 Encoder routines **************************/
s[s_len] = '\0'; \
} \
len = silc_ber_encoded_len(tag, s_len, indef); \
- dest = silc_buffer_srealloc_size(stack1, dest, \
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest, \
silc_buffer_truelen(dest) + len); \
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_PRIMITIVE, \
tag, s, s_len, indef); \
/* Encode the explicit tag */
len = silc_ber_encoded_len(tag, silc_buffer_len(&buf), FALSE);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_CONSTRUCTED,
tag, buf.data, silc_buffer_len(&buf), FALSE);
/* Now encode with implicit tagging */
len = silc_ber_encoded_len(tag, d_len, FALSE);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_CONSTRUCTED,
tag, d, d_len, FALSE);
} else {
/* Copy the data directly into the tree. */
len = silc_buffer_len(node);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
if (!dest)
goto fail;
/* Encode the primitive data */
len = silc_ber_encoded_len(tag, silc_buffer_len(prim), FALSE);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_PRIMITIVE,
tag, prim->data, silc_buffer_len(prim), FALSE);
/* Encode the sequence */
len = silc_ber_encoded_len(tag, silc_buffer_len(&buf), indef);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_CONSTRUCTED,
tag, buf.data, silc_buffer_len(&buf), indef);
/* Encode the integer */
len = silc_ber_encoded_len(tag, len, indef);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_PRIMITIVE,
tag, buf.data, silc_buffer_len(&buf), FALSE);
/* Encode the integer */
len = silc_ber_encoded_len(tag, len, indef);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_PRIMITIVE,
tag, buf.data, silc_buffer_len(&buf), FALSE);
}
len = silc_ber_encoded_len(tag, silc_buffer_len(&buf), indef);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_PRIMITIVE,
tag, buf.data, silc_buffer_len(&buf), FALSE);
assert(indef == FALSE);
len = silc_ber_encoded_len(tag, 1, FALSE);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_PRIMITIVE,
tag, val, 1, FALSE);
silc_buffer_push(&buf, 1);
len = silc_ber_encoded_len(tag, silc_buffer_len(&buf), indef);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_PRIMITIVE,
tag, buf.data, silc_buffer_len(&buf), indef);
case SILC_ASN1_TAG_NULL:
{
/* Encode empty BER block */
+ SilcBool val = va_arg(asn1->ap, SilcUInt32);
+
assert(indef == FALSE);
+
+ if (!val)
+ break;
+
len = silc_ber_encoded_len(tag, 0, FALSE);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_PRIMITIVE,
tag, NULL, 0, FALSE);
if (!ret)
goto fail;
+
break;
}
}
len = silc_ber_encoded_len(tag, strlen(timestr), indef);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_PRIMITIVE,
tag, timestr, strlen(timestr), indef);
}
len = silc_ber_encoded_len(tag, strlen(timestr), indef);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_PRIMITIVE,
tag, timestr, strlen(timestr), indef);
}
len = silc_ber_encoded_len(tag, d_len, indef);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_PRIMITIVE,
tag, d, d_len, indef);
SilcUInt32 d_len = va_arg(asn1->ap, SilcUInt32);
len = silc_ber_encoded_len(tag, d_len, indef);
- dest = silc_buffer_srealloc_size(stack1, dest,
+ dest = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1), dest,
silc_buffer_truelen(dest) + len);
ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_PRIMITIVE,
tag, d, d_len, indef);
SilcAsn1Options opts;
SilcBerClass ber_class;
SilcStackFrame frame1, frame2;
- SilcStack stack1 = NULL;
+ SilcStack stack1 = NULL, orig;
SilcBool ret;
if (!asn1)
va_start(asn1->ap, dest);
+ orig = asn1->orig_stack;
+ asn1->orig_stack = NULL;
+
/* Get the first arguments and call the encoder. */
SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
if (!type) {
that stack aware calls revert to normal allocation routines. */
stack1 = asn1->stack1;
asn1->stack1 = NULL;
+ asn1->orig_stack = orig;
}
if (o & SILC_ASN1_ACCUMUL) {
if (stack1 && !asn1->stack1)
asn1->stack1 = stack1;
+ asn1->orig_stack = orig;
+
va_end(asn1->ap);
return ret;
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2003 - 2006 Pekka Riikonen
+ Copyright (C) 2003 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* ASN.1 context */
struct SilcAsn1Object {
- va_list ap; /* List of ASN.1 types given as argument */
+ SilcStack orig_stack; /* Stack given to silc_asn1_alloc */
SilcStack stack1; /* Stack for encoder */
SilcStack stack2; /* Internal stack for encoding/decoding */
+ va_list ap; /* List of ASN.1 types given as argument */
unsigned int accumul : 1; /* Accumulate memory from stack for result */
};
SilcBufferStruct node, node2;
SilcAsn1 asn1;
SilcBool success = FALSE;
- SilcBool val = TRUE;
+ SilcBool val = TRUE, nval;
int i;
- unsigned char *str;
- SilcUInt32 str_len, tmpint;
+ unsigned char *str, buf[512];
+ SilcUInt32 str_len, tmpint, choice;
char tmp[32];
SilcRng rng;
SilcMPInt mpint, mpint2;
SILC_ASN1_SEQUENCE_T(SILC_ASN1_EXPLICIT, 9),
SILC_ASN1_SEQUENCE_T(SILC_ASN1_INDEFINITE, 0),
SILC_ASN1_BOOLEAN_T(0, 4, &val),
- SILC_ASN1_BOOLEAN(&val),
+ SILC_ASN1_CHOICE(&choice),
+ SILC_ASN1_SHORT_INT(&tmpint),
+ SILC_ASN1_BOOLEAN(&val),
+ SILC_ASN1_END,
SILC_ASN1_END,
SILC_ASN1_END,
SILC_ASN1_END, SILC_ASN1_END);
}
SILC_LOG_DEBUG(("Decoding success"));
SILC_LOG_DEBUG(("Boolean val %d", val));
+ SILC_LOG_DEBUG(("Choice index %d", choice));
+ if (choice != 2)
+ goto out;
printf("\n");
SILC_ASN1_BOOLEAN_T(0, 100, val),
SILC_ASN1_END,
SILC_ASN1_SEQUENCE,
- SILC_ASN1_NULL,
+ SILC_ASN1_NULL(TRUE),
SILC_ASN1_BOOLEAN_T(SILC_ASN1_EXPLICIT, 0, val),
SILC_ASN1_OCTET_STRING("foobar", 6),
SILC_ASN1_BOOLEAN_T(SILC_ASN1_PRIVATE, 43, val),
SILC_ASN1_BOOLEAN_T(0, 100, &val),
SILC_ASN1_END,
SILC_ASN1_SEQUENCE,
- SILC_ASN1_NULL,
+ SILC_ASN1_NULL(&nval),
SILC_ASN1_BOOLEAN_T(SILC_ASN1_EXPLICIT, 0, &val),
SILC_ASN1_OCTET_STRING(&str, &str_len),
SILC_ASN1_BOOLEAN_T(SILC_ASN1_PRIVATE, 43, &val),
}
SILC_LOG_DEBUG(("Decoding success"));
SILC_LOG_DEBUG(("Boolean val %d", val));
+ SILC_LOG_DEBUG(("NULL is present %s", nval ? "yes" : "no"));
SILC_LOG_DEBUG(("Ooctet-string %s, len %d", str, str_len));
printf("\n");
memset(&node, 0, sizeof(node));
SILC_LOG_DEBUG(("Encoding ASN.1 tree 10 (INTEGER)"));
- str = silc_rng_get_rn_data(rng, 256);
+ silc_rng_get_rn_data(rng, 256, buf, sizeof(buf));
silc_mp_init(&mpint);
silc_mp_init(&mpint2);
- silc_mp_bin2mp(str, 256, &mpint);
+ silc_mp_bin2mp(buf, 256, &mpint);
success =
silc_asn1_encode(asn1, &node,
SILC_ASN1_INT(&mpint),