primitive data type.
return "choice";
case SILC_ASN1_TAG_ANY:
return "any";
+ case SILC_ASN1_TAG_ANY_PRIMITIVE:
+ return "any primitive";
case SILC_ASN1_TAG_SEQUENCE_OF:
return "sequence of";
-
case SILC_ASN1_TAG_SEQUENCE:
return "sequence";
case SILC_ASN1_TAG_SET:
#define SILC_ASN1_ANY(x) SILC_ASN1_U1(ANY, x)
#define SILC_ASN1_ANY_T(o, t, x) SILC_ASN1_T1(ANY, o, t, x)
+/****f* silcasn1/SilcASN1API/SILC_ASN1_ANY_PRIMITIVE
+ *
+ * SYNOPSIS
+ *
+ * Encoding:
+ * SILC_ASN1_ANY_PRIMITIVE(tag, buffer)
+ * SILC_ASN1_ANY_PRIMITIVE_T(opts, tag, buffer)
+ *
+ * Decoding:
+ * SILC_ASN1_ANY_PRIMITIVE(tag, &buffer)
+ * SILC_ASN1_ANY_PRIMITIVE_T(opts, tag, &buffer)
+ *
+ * DESCRIPTION
+ *
+ * Special macro used to encode pre-encoded primitive data blob. The data
+ * can be any primitive type that is already encoded in correct format.
+ * The caller is responsible of making sure the data is formatted
+ * correctly. When decoding this returns the raw data blob and the caller
+ * must know of what type and format it is. The buffer type is SilcBuffer.
+ *
+ * This macro can be used in cases when the data to be encoded is already
+ * in encoded format, and it only needs to be added to ASN.1 tree. The
+ * SILC_ASN1_ANY cannot be used with primitives when tagging implicitly,
+ * in these cases this macro can be used.
+ *
+ * The `opts' is SilcAsn1Options. The `tag' is a tag number.
+ *
+ * EXAMPLE
+ *
+ * // Get MP integer in encoded format
+ * mpbuf = mp_get_octet_string(mp);
+ *
+ * // Encode the MP integer data to the tree
+ * silc_asn1_encode(asn1, tree,
+ * SILC_ASN1_ANY_PRIMITIVE(SILC_ASN1_TAG_INTEGER, mpbuf),
+ * SILC_ASN1_END);
+ *
+ * // Decode the MP integer data from the tree
+ * silc_asn1_decode(asn1, tree,
+ * SILC_ASN1_ANY_PRIMITIVE(SILC_ASN1_TAG_INTEGER, &buffer),
+ * SILC_ASN1_END);
+ *
+ ***/
+#define SILC_ASN1_ANY_PRIMITIVE(t, x) SILC_ASN1_T1(ANY_PRIMITIVE, 0, t, x)
+#define SILC_ASN1_ANY_PRIMITIVE_T(o, t, x) SILC_ASN1_T1(ANY_PRIMITIVE, o, t, x)
+
/****f* silcasn1/SilcASN1API/SILC_ASN1_SEQUENCE
*
* SYNOPSIS
indef = (opts & SILC_ASN1_INDEFINITE ? TRUE : FALSE);
/* By default UNIVERSAL is implied unless the following conditions
- are met when CONTEXT will apply. */
+ are met when CONTEXT will apply. For SILC_ASN1_TAG_ANY_PRIMITIVE
+ the class is changed only if flags dictate it. */
if (ber_class == SILC_BER_CLASS_UNIVERSAL) {
- if (tag != type ||
- opts & SILC_ASN1_IMPLICIT ||
- opts & SILC_ASN1_EXPLICIT)
- ber_class = SILC_BER_CLASS_CONTEXT;
+ if (type == SILC_ASN1_TAG_ANY_PRIMITIVE) {
+ if (opts & SILC_ASN1_IMPLICIT ||
+ opts & SILC_ASN1_EXPLICIT)
+ ber_class = SILC_BER_CLASS_CONTEXT;
+ } else {
+ if (tag != type ||
+ opts & SILC_ASN1_IMPLICIT ||
+ opts & SILC_ASN1_EXPLICIT)
+ ber_class = SILC_BER_CLASS_CONTEXT;
+ }
}
/* Now decode a BER encoded block from the source buffer. It must be
break;
}
+ case SILC_ASN1_TAG_ANY_PRIMITIVE:
+ {
+ /* 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);
+ silc_buffer_put(*prim, rdata, rdata_len);
+ break;
+ }
+
case SILC_ASN1_TAG_SEQUENCE:
case SILC_ASN1_TAG_SET:
{
indef = (opts & SILC_ASN1_INDEFINITE ? TRUE : FALSE);
/* By default UNIVERSAL is implied unless the following conditions
- are met when CONTEXT will apply. */
+ are met when CONTEXT will apply. For SILC_ASN1_TAG_ANY_PRIMITIVE
+ the class is changed only if flags dictate it. */
if (ber_class == SILC_BER_CLASS_UNIVERSAL) {
- if (tag != type ||
- opts & SILC_ASN1_IMPLICIT ||
- opts & SILC_ASN1_EXPLICIT)
- ber_class = SILC_BER_CLASS_CONTEXT;
+ if (type == SILC_ASN1_TAG_ANY_PRIMITIVE) {
+ if (opts & SILC_ASN1_IMPLICIT ||
+ opts & SILC_ASN1_EXPLICIT)
+ ber_class = SILC_BER_CLASS_CONTEXT;
+ } else {
+ if (tag != type ||
+ opts & SILC_ASN1_IMPLICIT ||
+ opts & SILC_ASN1_EXPLICIT)
+ ber_class = SILC_BER_CLASS_CONTEXT;
+ }
}
#ifdef SILC_DEBUG
break;
}
+ case SILC_ASN1_TAG_ANY_PRIMITIVE:
+ {
+ /* ANY_PRIMITIVE is any primitive in encoded format. */
+ SilcBuffer prim = va_arg(asn1->ap, SilcBuffer);
+ if (!prim)
+ break;
+
+ /* Encode the primitive data */
+ len = silc_ber_encoded_len(tag, silc_buffer_len(prim), FALSE);
+ dest = silc_buffer_srealloc_size(stack1, 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);
+ if (!ret)
+ goto fail;
+ break;
+ }
+
case SILC_ASN1_TAG_SEQUENCE:
case SILC_ASN1_TAG_SET:
{
#define SILC_ASN1_RECURSION_DEPTH 512
/* Implementation specific special tags. Range is 0x7000 - 0x7fff. */
-#define SILC_ASN1_TAG_ANY 0x7000 /* SILC_ASN1_ANY given */
-#define SILC_ASN1_TAG_FUNC 0x7001 /* Callback encoder/decoder */
-#define SILC_ASN1_TAG_OPTS 0x7002 /* SILC_ASN1_OPTS given */
-#define SILC_ASN1_TAG_CHOICE 0x7003 /* SILC_ASN1_CHOICE given */
-#define SILC_ASN1_TAG_SEQUENCE_OF 0x7004 /* SILC_ASN1_SEQUENCE_OF given */
+#define SILC_ASN1_TAG_ANY 0x7000 /* SILC_ASN1_ANY given */
+#define SILC_ASN1_TAG_FUNC 0x7001 /* Callback encoder/decoder */
+#define SILC_ASN1_TAG_OPTS 0x7002 /* SILC_ASN1_OPTS given */
+#define SILC_ASN1_TAG_CHOICE 0x7003 /* SILC_ASN1_CHOICE given */
+#define SILC_ASN1_TAG_SEQUENCE_OF 0x7004 /* SILC_ASN1_SEQUENCE_OF given */
+#define SILC_ASN1_TAG_ANY_PRIMITIVE 0x7005 /* Pre-encoded primitive data */
/* Helper macros for adding the arguments to encoder and decoder. */
include the length of the data in the BER block. */
SilcBool silc_ber_encode(SilcBuffer ber, SilcBerClass ber_class,
- SilcBerEncoding encoding, SilcUInt32 tag,
- const unsigned char *data, SilcUInt32 data_len,
- SilcBool indefinite)
+ SilcBerEncoding encoding, SilcUInt32 tag,
+ const unsigned char *data, SilcUInt32 data_len,
+ SilcBool indefinite)
{
int i = 0, c;
SilcUInt32 tmp;
of the entire BER object is `identifier_len' + `data_len'. */
SilcBool silc_ber_decode(SilcBuffer ber, SilcBerClass *ber_class,
- SilcBerEncoding *encoding, SilcUInt32 *tag,
- const unsigned char **data, SilcUInt32 *data_len,
- SilcBool *indefinite, SilcUInt32 *identifier_len)
+ SilcBerEncoding *encoding, SilcUInt32 *tag,
+ const unsigned char **data, SilcUInt32 *data_len,
+ SilcBool *indefinite, SilcUInt32 *identifier_len)
{
int i = 0, c;
SilcUInt32 t;
int i;
unsigned char *str;
SilcUInt32 str_len;
+ char tmp[32];
memset(&node, 0, sizeof(node));
memset(&node2, 0, sizeof(node2));
printf("\n");
+ memset(&node, 0, sizeof(node));
+ SILC_LOG_DEBUG(("Encoding ASN.1 tree (ANY_PRIMITIVE)"));
+ memset(tmp, 0, sizeof(tmp));
+ tmp[0] = 0xff;
+ silc_buffer_set(&node2, tmp, 1);
+ SILC_LOG_DEBUG(("Encoding success"));
+ success =
+ silc_asn1_encode(asn1, &node,
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_ANY_PRIMITIVE(SILC_ASN1_TAG_BOOLEAN,
+ &node2),
+ SILC_ASN1_END, SILC_ASN1_END);
+ if (!success) {
+ SILC_LOG_DEBUG(("Encoding failed"));
+ goto out;
+ }
+ SILC_LOG_DEBUG(("Encoding success"));
+ SILC_LOG_HEXDUMP(("ASN.1 tree"), node.data, silc_buffer_len(&node));
+ memset(&node2, 0, sizeof(node2));
+ SILC_LOG_DEBUG(("Decoding ASN.1 tree (ANY_PRIMITIVE)"));
+ success =
+ silc_asn1_decode(asn1, &node,
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_ANY_PRIMITIVE(SILC_ASN1_TAG_BOOLEAN,
+ &node2),
+ SILC_ASN1_END, SILC_ASN1_END);
+ if (!success) {
+ SILC_LOG_DEBUG(("Decoding failed"));
+ goto out;
+ }
+ SILC_LOG_DEBUG(("Boolean val %d", node2.data[0]));
+ if (node2.data[0] != 0xff) {
+ SILC_LOG_DEBUG(("Decoding failed"));
+ goto out;
+ }
+ SILC_LOG_DEBUG(("Decoding success"));
+ memset(&node, 0, sizeof(node));
+ SILC_LOG_DEBUG(("Encoding ASN.1 tree (ANY_PRIMITIVE)"));
+ memset(tmp, 0, sizeof(tmp));
+ tmp[0] = 0xff;
+ silc_buffer_set(&node2, tmp, 1);
+ SILC_LOG_DEBUG(("Encoding success"));
+ success =
+ silc_asn1_encode(asn1, &node,
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_ANY_PRIMITIVE(SILC_ASN1_TAG_BOOLEAN,
+ &node2),
+ SILC_ASN1_END, SILC_ASN1_END);
+ if (!success) {
+ SILC_LOG_DEBUG(("Encoding failed"));
+ goto out;
+ }
+ SILC_LOG_DEBUG(("Encoding success"));
+ SILC_LOG_HEXDUMP(("ASN.1 tree"), node.data, silc_buffer_len(&node));
+ memset(&node2, 0, sizeof(node2));
+ SILC_LOG_DEBUG(("Decoding ASN.1 tree (ANY_PRIMITIVE)"));
+ success =
+ silc_asn1_decode(asn1, &node,
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_BOOLEAN(&val),
+ SILC_ASN1_END, SILC_ASN1_END);
+ if (!success) {
+ SILC_LOG_DEBUG(("Decoding failed"));
+ goto out;
+ }
+ SILC_LOG_DEBUG(("Decoding success"));
+ SILC_LOG_DEBUG(("Boolean val %d", val));
+ memset(&node, 0, sizeof(node));
+ SILC_LOG_DEBUG(("Encoding ASN.1 tree (ANY_PRIMITIVE)"));
+ memset(tmp, 0, sizeof(tmp));
+ tmp[0] = 0xff;
+ silc_buffer_set(&node2, tmp, 1);
+ SILC_LOG_DEBUG(("Encoding success"));
+ success =
+ silc_asn1_encode(asn1, &node,
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_BOOLEAN(val),
+ SILC_ASN1_END, SILC_ASN1_END);
+ if (!success) {
+ SILC_LOG_DEBUG(("Encoding failed"));
+ goto out;
+ }
+ SILC_LOG_DEBUG(("Encoding success"));
+ SILC_LOG_HEXDUMP(("ASN.1 tree"), node.data, silc_buffer_len(&node));
+ memset(&node2, 0, sizeof(node2));
+ SILC_LOG_DEBUG(("Decoding ASN.1 tree (ANY_PRIMITIVE)"));
+ success =
+ silc_asn1_decode(asn1, &node,
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_ANY_PRIMITIVE(SILC_ASN1_TAG_BOOLEAN,
+ &node2),
+ SILC_ASN1_END, SILC_ASN1_END);
+ if (!success) {
+ SILC_LOG_DEBUG(("Decoding failed"));
+ goto out;
+ }
+ SILC_LOG_DEBUG(("Boolean val %d", node2.data[0]));
+ if (node2.data[0] != 0xff) {
+ SILC_LOG_DEBUG(("Decoding failed"));
+ goto out;
+ }
+ SILC_LOG_DEBUG(("Decoding success"));
+ memset(&node2, 0, sizeof(node2));
+ printf("\n");
+
+
memset(&node, 0, sizeof(node));
SILC_LOG_DEBUG(("Encoding ASN.1 tree 6"));
success =